From 6fbbde25a26908cf068731469e016467c62274a7 Mon Sep 17 00:00:00 2001 From: catch Date: Tue, 24 Apr 2012 11:03:13 +0900 Subject: [PATCH] Issue #751168 by elliotttf, caktux, andyceo, setvik, xjm, sun: Fixed Regression: Missing 'Default image' per field instance. --- core/modules/image/image.field.inc | 25 +++- core/modules/image/image.module | 67 +++++++++ core/modules/image/image.test | 232 ++++++++++++++++++++++++++++- 3 files changed, 321 insertions(+), 3 deletions(-) diff --git a/core/modules/image/image.field.inc b/core/modules/image/image.field.inc index 6138b530390..d3f9b2dc200 100644 --- a/core/modules/image/image.field.inc +++ b/core/modules/image/image.field.inc @@ -25,6 +25,7 @@ function image_field_info() { 'title_field' => 0, 'max_resolution' => '', 'min_resolution' => '', + 'default_image' => 0, ), 'default_widget' => 'image_image', 'default_formatter' => 'image', @@ -156,6 +157,15 @@ function image_field_instance_settings_form($field, $instance) { '#weight' => 11, ); + // Add the default image to the instance. + $form['default_image'] = array( + '#title' => t('Default image'), + '#type' => 'managed_file', + '#description' => t("If no image is uploaded, this image will be shown on display and will override the field's default image."), + '#default_value' => $settings['default_image'], + '#upload_location' => $field['settings']['uri_scheme'] . '://default_images/', + ); + return $form; } @@ -190,8 +200,19 @@ function image_field_load($entity_type, $entities, $field, $instances, $langcode function image_field_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items) { // If there are no files specified at all, use the default. foreach ($entities as $id => $entity) { - if (empty($items[$id]) && $field['settings']['default_image']) { - if ($file = file_load($field['settings']['default_image'])) { + if (empty($items[$id])) { + $fid = 0; + // Use the default for the instance if one is available. + if ($instances[$id]['settings']['default_image']) { + $fid = $instances[$id]['settings']['default_image']; + } + // Otherwise, use the default for the field. + elseif ($field['settings']['default_image']) { + $fid = $field['settings']['default_image']; + } + + // Add the default image if one is found. + if ($fid && ($file = file_load($fid))) { $items[$id][0] = (array) $file + array( 'is_default' => TRUE, 'alt' => '', diff --git a/core/modules/image/image.module b/core/modules/image/image.module index 84a6fe00b60..9e13c85735c 100644 --- a/core/modules/image/image.module +++ b/core/modules/image/image.module @@ -411,6 +411,73 @@ function image_field_update_field($field, $prior_field, $has_data) { } } +/** + * Implements hook_field_delete_instance(). + */ +function image_field_delete_instance($instance) { + // Only act on image fields. + $field = field_read_field($instance['field_name']); + if ($field['type'] != 'image') { + return; + } + + // The value of a managed_file element can be an array if the #extended + // property is set to TRUE. + $fid = $instance['settings']['default_image']; + if (is_array($fid)) { + $fid = $fid['fid']; + } + + // Remove the default image when the instance is deleted. + if ($fid && ($file = file_load($fid))) { + file_usage_delete($file, 'image', 'default_image', $instance['id']); + } +} + +/** + * Implements hook_field_update_instance(). + */ +function image_field_update_instance($instance, $prior_instance) { + // Only act on image fields. + $field = field_read_field($instance['field_name']); + if ($field['type'] != 'image') { + return; + } + + // The value of a managed_file element can be an array if the #extended + // property is set to TRUE. + $fid_new = $instance['settings']['default_image']; + if (is_array($fid_new)) { + $fid_new = $fid_new['fid']; + } + $fid_old = $prior_instance['settings']['default_image']; + if (is_array($fid_old)) { + $fid_old = $fid_old['fid']; + } + + // If the old and new files do not match, update the default accordingly. + $file_new = $fid_new ? file_load($fid_new) : FALSE; + if ($fid_new != $fid_old) { + // Save the new file, if present. + if ($file_new) { + $file_new->status = FILE_STATUS_PERMANENT; + file_save($file_new); + file_usage_add($file_new, 'image', 'default_image', $instance['id']); + } + // Delete the old file, if present. + if ($fid_old && ($file_old = file_load($fid_old))) { + file_usage_delete($file_old, 'image', 'default_image', $instance['id']); + } + } + + // If the upload destination changed, then move the file. + if ($file_new && (file_uri_scheme($file_new->uri) != $field['settings']['uri_scheme'])) { + $directory = $field['settings']['uri_scheme'] . '://default_images/'; + file_prepare_directory($directory, FILE_CREATE_DIRECTORY); + file_move($file_new, $directory . $file_new->filename); + } +} + /** * Clear cached versions of a specific file in all styles. * diff --git a/core/modules/image/image.test b/core/modules/image/image.test index 8675b38a4c8..d3b3374d1a9 100644 --- a/core/modules/image/image.test +++ b/core/modules/image/image.test @@ -545,7 +545,8 @@ class ImageAdminStylesUnitTest extends ImageFieldTestCase { // Create an image field that uses the new style. $field_name = strtolower($this->randomName(10)); - $instance = $this->createImageField($field_name, 'article'); + $this->createImageField($field_name, 'article'); + $instance = field_info_instance('node', $field_name, 'article'); $instance['display']['default']['type'] = 'image'; $instance['display']['default']['settings']['image_style'] = $style_name; field_update_instance($instance); @@ -1256,3 +1257,232 @@ class ImageDimensionsScaleTestCase extends DrupalUnitTestCase { } } } + +/** + * Tests default image settings. + */ +class ImageFieldDefaultImagesTestCase extends ImageFieldTestCase { + + public static function getInfo() { + return array( + 'name' => 'Image field default images tests', + 'description' => 'Tests setting up default images both to the field and field instance.', + 'group' => 'Image', + ); + } + + function setUp() { + parent::setUp(array('field_ui')); + } + + /** + * Tests CRUD for fields and fields instances with default images. + */ + function testDefaultImages() { + // Create files to use as the default images. + $files = $this->drupalGetTestFiles('image'); + $default_images = array(); + foreach (array('field', 'instance', 'instance2', 'field_new', 'instance_new') as $image_target) { + $file = array_pop($files); + $file = file_save($file); + $default_images[$image_target] = $file; + } + + // Create an image field and add an instance to the article content type. + $field_name = strtolower($this->randomName()); + $field_settings = array( + 'default_image' => $default_images['field']->fid, + ); + $instance_settings = array( + 'default_image' => $default_images['instance']->fid, + ); + $widget_settings = array( + 'preview_image_style' => 'medium', + ); + $this->createImageField($field_name, 'article', $field_settings, $instance_settings, $widget_settings); + $field = field_info_field($field_name); + $instance = field_info_instance('node', $field_name, 'article'); + + // Add another instance with another default image to the page content type. + $instance2 = array_merge($instance, array( + 'bundle' => 'page', + 'settings' => array( + 'default_image' => $default_images['instance2']->fid, + ), + )); + field_create_instance($instance2); + $instance2 = field_info_instance('node', $field_name, 'page'); + + + // Confirm the defaults are present on the article field admin form. + $this->drupalGet("admin/structure/types/manage/article/fields/$field_name"); + $this->assertFieldByXpath( + '//input[@name="field[settings][default_image][fid]"]', + $default_images['field']->fid, + format_string( + 'Article image field default equals expected file ID of @fid.', + array('@fid' => $default_images['field']->fid) + ) + ); + $this->assertFieldByXpath( + '//input[@name="instance[settings][default_image][fid]"]', + $default_images['instance']->fid, + format_string( + 'Article image field instance default equals expected file ID of @fid.', + array('@fid' => $default_images['instance']->fid) + ) + ); + + // Confirm the defaults are present on the page field admin form. + $this->drupalGet("admin/structure/types/manage/page/fields/$field_name"); + $this->assertFieldByXpath( + '//input[@name="field[settings][default_image][fid]"]', + $default_images['field']->fid, + format_string( + 'Page image field default equals expected file ID of @fid.', + array('@fid' => $default_images['field']->fid) + ) + ); + $this->assertFieldByXpath( + '//input[@name="instance[settings][default_image][fid]"]', + $default_images['instance2']->fid, + format_string( + 'Page image field instance default equals expected file ID of @fid.', + array('@fid' => $default_images['instance2']->fid) + ) + ); + + // Confirm that the image default is shown for a new article node. + $article = $this->drupalCreateNode(array('type' => 'article')); + $article_built = node_view($article); + $this->assertEqual( + $article_built[$field_name]['#items'][0]['fid'], + $default_images['instance']->fid, + format_string( + 'A new article node without an image has the expected default image file ID of @fid.', + array('@fid' => $default_images['instance']->fid) + ) + ); + + // Confirm that the image default is shown for a new page node. + $page = $this->drupalCreateNode(array('type' => 'page')); + $page_built = node_view($page); + $this->assertEqual( + $page_built[$field_name]['#items'][0]['fid'], + $default_images['instance2']->fid, + format_string( + 'A new page node without an image has the expected default image file ID of @fid.', + array('@fid' => $default_images['instance2']->fid) + ) + ); + + // Upload a new default for the field. + $field['settings']['default_image'] = $default_images['field_new']->fid; + field_update_field($field); + + // Confirm that the new field default is used on the article admin form. + $this->drupalGet("admin/structure/types/manage/article/fields/$field_name"); + $this->assertFieldByXpath( + '//input[@name="field[settings][default_image][fid]"]', + $default_images['field_new']->fid, + format_string( + 'Updated image field default equals expected file ID of @fid.', + array('@fid' => $default_images['field_new']->fid) + ) + ); + + // Reload the nodes and confirm the field instance defaults are used. + $article_built = node_view($article = node_load($article->nid, NULL, $reset = TRUE)); + $page_built = node_view($page = node_load($page->nid, NULL, $reset = TRUE)); + $this->assertEqual( + $article_built[$field_name]['#items'][0]['fid'], + $default_images['instance']->fid, + format_string( + 'An existing article node without an image has the expected default image file ID of @fid.', + array('@fid' => $default_images['instance']->fid) + ) + ); + $this->assertEqual( + $page_built[$field_name]['#items'][0]['fid'], + $default_images['instance2']->fid, + format_string( + 'An existing page node without an image has the expected default image file ID of @fid.', + array('@fid' => $default_images['instance2']->fid) + ) + ); + + // Upload a new default for the article's field instance. + $instance['settings']['default_image'] = $default_images['instance_new']->fid; + field_update_instance($instance); + + // Confirm the new field instance default is used on the article field + // admin form. + $this->drupalGet("admin/structure/types/manage/article/fields/$field_name"); + $this->assertFieldByXpath( + '//input[@name="instance[settings][default_image][fid]"]', + $default_images['instance_new']->fid, + format_string( + 'Updated article image field instance default equals expected file ID of @fid.', + array('@fid' => $default_images['instance_new']->fid) + ) + ); + + // Reload the nodes. + $article_built = node_view($article = node_load($article->nid, NULL, $reset = TRUE)); + $page_built = node_view($page = node_load($page->nid, NULL, $reset = TRUE)); + + // Confirm the article uses the new default. + $this->assertEqual( + $article_built[$field_name]['#items'][0]['fid'], + $default_images['instance_new']->fid, + format_string( + 'An existing article node without an image has the expected default image file ID of @fid.', + array('@fid' => $default_images['instance_new']->fid) + ) + ); + // Confirm the page remains unchanged. + $this->assertEqual( + $page_built[$field_name]['#items'][0]['fid'], + $default_images['instance2']->fid, + format_string( + 'An existing page node without an image has the expected default image file ID of @fid.', + array('@fid' => $default_images['instance2']->fid) + ) + ); + + // Remove the instance default from articles. + $instance['settings']['default_image'] = NULL; + field_update_instance($instance); + + // Confirm the article field instance default has been removed. + $this->drupalGet("admin/structure/types/manage/article/fields/$field_name"); + $this->assertFieldByXpath( + '//input[@name="instance[settings][default_image][fid]"]', + '', + 'Updated article image field instance default has been successfully removed.' + ); + + // Reload the nodes. + $article_built = node_view($article = node_load($article->nid, NULL, $reset = TRUE)); + $page_built = node_view($page = node_load($page->nid, NULL, $reset = TRUE)); + // Confirm the article uses the new field (not instance) default. + $this->assertEqual( + $article_built[$field_name]['#items'][0]['fid'], + $default_images['field_new']->fid, + format_string( + 'An existing article node without an image has the expected default image file ID of @fid.', + array('@fid' => $default_images['field_new']->fid) + ) + ); + // Confirm the page remains unchanged. + $this->assertEqual( + $page_built[$field_name]['#items'][0]['fid'], + $default_images['instance2']->fid, + format_string( + 'An existing page node without an image has the expected default image file ID of @fid.', + array('@fid' => $default_images['instance2']->fid) + ) + ); + } + +}