Issue #2357801 by dawehner, amitgoyal: File field default values are not deployable -- use UUIDs for the default file

8.0.x
Nathaniel Catchpole 2015-01-06 13:50:10 +00:00
parent 503e46bb6b
commit 0485e555a4
12 changed files with 95 additions and 63 deletions

View File

@ -13,8 +13,8 @@ image_size:
field_default_image:
type: mapping
mapping:
fid:
type: integer
uuid:
type: string
label: 'Image'
alt:
type: label

View File

@ -340,18 +340,18 @@ function image_entity_presave(EntityInterface $entity) {
return;
}
$fid = $entity->settings['default_image']['fid'];
if ($fid) {
$original_fid = isset($entity->original) ? $entity->original->settings['default_image']['fid'] : NULL;
if ($fid != $original_fid) {
$file = file_load($fid);
$uuid = $entity->settings['default_image']['uuid'];
if ($uuid) {
$original_uuid = isset($entity->original) ? $entity->original->settings['default_image']['uuid'] : NULL;
if ($uuid != $original_uuid) {
$file = \Drupal::entityManager()->loadEntityByUuid('file', $uuid);
if ($file) {
$image = \Drupal::service('image.factory')->get($file->getFileUri());
$entity->settings['default_image']['width'] = $image->getWidth();
$entity->settings['default_image']['height'] = $image->getHeight();
}
else {
$entity->settings['default_image']['fid'] = NULL;
$entity->settings['default_image']['uuid'] = NULL;
}
}
}
@ -371,12 +371,12 @@ function image_field_storage_config_update(FieldStorageConfigInterface $field_st
$prior_field_storage = $field_storage->original;
// The value of a managed_file element can be an array if #extended == TRUE.
$fid_new = $field_storage->settings['default_image']['fid'];
$fid_old = $prior_field_storage->settings['default_image']['fid'];
$uuid_new = $field_storage->settings['default_image']['uuid'];
$uuid_old = $prior_field_storage->settings['default_image']['uuid'];
$file_new = $fid_new ? file_load($fid_new) : FALSE;
$file_new = $uuid_new ? \Drupal::entityManager()->loadEntityByUuid('file', $uuid_new) : FALSE;
if ($fid_new != $fid_old) {
if ($uuid_new != $uuid_old) {
// Is there a new file?
if ($file_new) {
@ -386,7 +386,7 @@ function image_field_storage_config_update(FieldStorageConfigInterface $field_st
}
// Is there an old file?
if ($fid_old && ($file_old = file_load($fid_old))) {
if ($uuid_old && ($file_old = \Drupal::entityManager()->loadEntityByUuid('file', $uuid_old))) {
\Drupal::service('file.usage')->delete($file_old, 'image', 'default_image', $field_storage->uuid());
}
}
@ -411,12 +411,12 @@ function image_field_config_update(FieldConfigInterface $field) {
$prior_instance = $field->original;
$fid_new = $field->settings['default_image']['fid'];
$fid_old = $prior_instance->settings['default_image']['fid'];
$uuid_new = $field->settings['default_image']['uuid'];
$uuid_old = $prior_instance->settings['default_image']['uuid'];
// 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) {
$file_new = $uuid_new ? \Drupal::entityManager()->loadEntityByUuid('file', $uuid_new) : FALSE;
if ($uuid_new != $uuid_old) {
// Save the new file, if present.
if ($file_new) {
$file_new->status = FILE_STATUS_PERMANENT;
@ -424,7 +424,7 @@ function image_field_config_update(FieldConfigInterface $field) {
\Drupal::service('file.usage')->add($file_new, 'image', 'default_image', $field->uuid());
}
// Delete the old file, if present.
if ($fid_old && ($file_old = file_load($fid_old))) {
if ($uuid_old && ($file_old = \Drupal::entityManager()->loadEntityByUuid('file', $uuid_old))) {
\Drupal::service('file.usage')->delete($file_old, 'image', 'default_image', $field->uuid());
}
}
@ -447,8 +447,8 @@ function image_field_storage_config_delete(FieldStorageConfigInterface $field) {
}
// The value of a managed_file element can be an array if #extended == TRUE.
$fid = $field->settings['default_image']['fid'];
if ($fid && ($file = file_load($fid))) {
$uuid = $field->settings['default_image']['uuid'];
if ($uuid && ($file = \Drupal::entityManager()->loadEntityByUuid('file', $uuid))) {
\Drupal::service('file.usage')->delete($file, 'image', 'default_image', $field->uuid());
}
}
@ -464,10 +464,10 @@ function image_field_config_delete(FieldConfigInterface $field) {
}
// The value of a managed_file element can be an array if #extended == TRUE.
$fid = $field->settings['default_image']['fid'];
$uuid = $field->settings['default_image']['uuid'];
// Remove the default image when the instance is deleted.
if ($fid && ($file = file_load($fid))) {
if ($uuid && ($file = \Drupal::entityManager()->loadEntityByUuid('file', $uuid))) {
\Drupal::service('file.usage')->delete($file, 'image', 'default_image', $field->uuid());
}
}

View File

@ -28,11 +28,11 @@ abstract class ImageFormatterBase extends FileFormatterBase {
$default_image = $this->getFieldSetting('default_image');
// If we are dealing with a configurable field, look in both
// instance-level and field-level settings.
if (empty($default_image['fid']) && $this->fieldDefinition instanceof FieldConfigInterface) {
if (empty($default_image['uuid']) && $this->fieldDefinition instanceof FieldConfigInterface) {
$default_image = $this->fieldDefinition->getFieldStorageDefinition()->getSetting('default_image');
}
if (!empty($default_image['fid']) && ($file = file_load($default_image['fid']))) {
if (!empty($default_image['uuid']) && ($file = \Drupal::entityManager()->loadEntityByUuid('file', $default_image['uuid']))) {
$items->setValue(array(array(
'is_default' => TRUE,
'alt' => $default_image['alt'],

View File

@ -47,13 +47,20 @@ use Drupal\file\Plugin\Field\FieldType\FileItem;
*/
class ImageItem extends FileItem {
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityManagerInterface
*/
protected $entityManager;
/**
* {@inheritdoc}
*/
public static function defaultStorageSettings() {
return array(
'default_image' => array(
'fid' => NULL,
'uuid' => NULL,
'alt' => '',
'title' => '',
'width' => NULL,
@ -75,7 +82,7 @@ class ImageItem extends FileItem {
'max_resolution' => '',
'min_resolution' => '',
'default_image' => array(
'fid' => NULL,
'uuid' => NULL,
'alt' => '',
'title' => '',
'width' => NULL,
@ -397,11 +404,16 @@ class ImageItem extends FileItem {
'#title' => t('Default image'),
'#open' => TRUE,
);
$element['default_image']['fid'] = array(
// Convert the stored UUID to a FID.
$fids = [];
if ($file = $this->getEntityManager()->loadEntityByUuid('file', $settings['default_image']['uuid'])) {
$fids[0] = $file->id();
}
$element['default_image']['uuid'] = array(
'#type' => 'managed_file',
'#title' => t('Image'),
'#description' => t('Image to be shown if no image is uploaded.'),
'#default_value' => empty($settings['default_image']['fid']) ? array() : array($settings['default_image']['fid']),
'#default_value' => $fids,
'#upload_location' => $settings['uri_scheme'] . '://default_images/',
'#element_validate' => array(
'\Drupal\file\Element\ManagedFile::validateManagedFile',
@ -450,9 +462,13 @@ class ImageItem extends FileItem {
// for default image is not TRUE and this is a single value.
if (isset($element['fids']['#value'][0])) {
$value = $element['fids']['#value'][0];
// Convert the file ID to a uuid.
if ($file = \Drupal::entityManager()->getStorage('file')->load($value)) {
$value = $file->uuid();
}
}
else {
$value = 0;
$value = '';
}
$form_state->setValueForElement($element, $value);
}
@ -465,4 +481,16 @@ class ImageItem extends FileItem {
return TRUE;
}
/**
* Gets the entity manager.
*
* @return \Drupal\Core\Entity\EntityManagerInterface.
*/
protected function getEntityManager() {
if (!isset($this->entityManager)) {
$this->entityManager = \Drupal::entityManager();
}
return $this->entityManager;
}
}

View File

@ -138,9 +138,13 @@ class ImageWidget extends FileWidget {
// Default image.
$default_image = $field_settings['default_image'];
if (empty($default_image['fid'])) {
if (empty($default_image['uuid'])) {
$default_image = $this->fieldDefinition->getFieldStorageDefinition()->getSetting('default_image');
}
// Convert the stored UUID into a file ID.
if (!empty($default_image['uuid']) && $entity = \Drupal::entityManager()->loadEntityByUuid('file', $default_image['uuid'])) {
$default_image['fid'] = $entity->id();
}
$element['#default_image'] = !empty($default_image['fid']) ? $default_image : array();
return $element;

View File

@ -48,14 +48,14 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
// Create an image field and add an field to the article content type.
$field_name = strtolower($this->randomMachineName());
$storage_settings['default_image'] = array(
'fid' => $default_images['field']->id(),
'uuid' => $default_images['field']->uuid(),
'alt' => '',
'title' => '',
'width' => 0,
'height' => 0,
);
$field_settings['default_image'] = array(
'fid' => $default_images['field']->id(),
'uuid' => $default_images['field']->uuid(),
'alt' => '',
'title' => '',
'width' => 0,
@ -67,18 +67,18 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
$field = $this->createImageField($field_name, 'article', $storage_settings, $field_settings, $widget_settings);
// The field default image id should be 2.
$this->assertEqual($field->getSetting('default_image')['fid'], $default_images['field']->id());
$this->assertEqual($field->getSetting('default_image')['uuid'], $default_images['field']->uuid());
// Also test \Drupal\field\Entity\FieldConfig::getSetting().
$this->assertEqual($field->getSettings()['default_image']['fid'], $default_images['field']->id());
$this->assertEqual($field->getSettings()['default_image']['uuid'], $default_images['field']->uuid());
$field_storage = $field->getFieldStorageDefinition();
// The field default image id should be 1.
$this->assertEqual($field_storage->getSetting('default_image')['fid'], $default_images['field']->id());
$this->assertEqual($field_storage->getSetting('default_image')['uuid'], $default_images['field']->uuid());
// Also test \Drupal\field\Entity\FieldStorageConfig::getSettings().
$this->assertEqual($field_storage->getSettings()['default_image']['fid'], $default_images['field']->id());
$this->assertEqual($field_storage->getSettings()['default_image']['uuid'], $default_images['field']->uuid());
// Add another field with another default image to the page content type.
$field2 = entity_create('field_config', array(
@ -88,7 +88,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
'required' => $field->required,
'settings' => array(
'default_image' => array(
'fid' => $default_images['field2']->id(),
'uuid' => $default_images['field2']->uuid(),
'alt' => '',
'title' => '',
'width' => 0,
@ -110,7 +110,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
$field_id = $field->id();
$this->drupalGet("admin/structure/types/manage/article/fields/$field_id/storage");
$this->assertFieldByXpath(
'//input[@name="field_storage[settings][default_image][fid][fids]"]',
'//input[@name="field_storage[settings][default_image][uuid][fids]"]',
$default_images['field']->id(),
format_string(
'Article image field default equals expected file ID of @fid.',
@ -120,7 +120,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
// Confirm the defaults are present on the article field edit form.
$this->drupalGet("admin/structure/types/manage/article/fields/$field_id");
$this->assertFieldByXpath(
'//input[@name="field[settings][default_image][fid][fids]"]',
'//input[@name="field[settings][default_image][uuid][fids]"]',
$default_images['field']->id(),
format_string(
'Article image field field default equals expected file ID of @fid.',
@ -131,7 +131,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
// Confirm the defaults are present on the page field settings form.
$this->drupalGet("admin/structure/types/manage/page/fields/$field_id/storage");
$this->assertFieldByXpath(
'//input[@name="field_storage[settings][default_image][fid][fids]"]',
'//input[@name="field_storage[settings][default_image][uuid][fids]"]',
$default_images['field']->id(),
format_string(
'Page image field default equals expected file ID of @fid.',
@ -142,7 +142,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
$field2_id = $field2->id();
$this->drupalGet("admin/structure/types/manage/page/fields/$field2_id");
$this->assertFieldByXpath(
'//input[@name="field[settings][default_image][fid][fids]"]',
'//input[@name="field[settings][default_image][uuid][fids]"]',
$default_images['field2']->id(),
format_string(
'Page image field field default equals expected file ID of @fid.',
@ -175,13 +175,13 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
);
// Upload a new default for the field storage.
$field_storage->settings['default_image']['fid'] = $default_images['field_new']->id();
$field_storage->settings['default_image']['uuid'] = $default_images['field_new']->uuid();
$field_storage->save();
// Confirm that the new default is used on the article field settings form.
$this->drupalGet("admin/structure/types/manage/article/fields/$field_id/storage");
$this->assertFieldByXpath(
'//input[@name="field_storage[settings][default_image][fid][fids]"]',
'//input[@name="field_storage[settings][default_image][uuid][fids]"]',
$default_images['field_new']->id(),
format_string(
'Updated image field default equals expected file ID of @fid.',
@ -211,14 +211,14 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
);
// Upload a new default for the article's field field.
$field->settings['default_image']['fid'] = $default_images['field_new']->id();
$field->settings['default_image']['uuid'] = $default_images['field_new']->uuid();
$field->save();
// Confirm the new field field default is used on the article field
// admin form.
$this->drupalGet("admin/structure/types/manage/article/fields/$field_id");
$this->assertFieldByXpath(
'//input[@name="field[settings][default_image][fid][fids]"]',
'//input[@name="field[settings][default_image][uuid][fids]"]',
$default_images['field_new']->id(),
format_string(
'Updated article image field field default equals expected file ID of @fid.',
@ -256,13 +256,13 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
$this->assertRaw($file->getFilename());
// Remove the instance default from articles.
$field->settings['default_image']['fid'] = 0;
$field->settings['default_image']['uuid'] = 0;
$field->save();
// Confirm the article field field default has been removed.
$this->drupalGet("admin/structure/types/manage/article/fields/$field_id");
$this->assertFieldByXpath(
'//input[@name="field[settings][default_image][fid][fids]"]',
'//input[@name="field[settings][default_image][uuid][fids]"]',
'',
'Updated article image field field default has been successfully removed.'
);
@ -291,7 +291,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
);
$non_image = $this->drupalGetTestFiles('text');
$this->drupalPostForm(NULL, array('files[field_settings_default_image_fid]' => drupal_realpath($non_image[0]->uri)), t("Upload"));
$this->drupalPostForm(NULL, array('files[field_settings_default_image_uuid]' => drupal_realpath($non_image[0]->uri)), t("Upload"));
$this->assertText(t('The specified file text-0.txt could not be uploaded. Only files with the following extensions are allowed: png gif jpg jpeg.'), 'Non-image file cannot be used as default image.');
// Confirm the default image is shown on the node form.
@ -310,14 +310,14 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
'type' => 'image',
'settings' => array(
'default_image' => array(
'fid' => 100000,
'uuid' => 100000,
)
),
));
$field_storage->save();
$settings = $field_storage->getSettings();
// The non-existent default image should not be saved.
$this->assertNull($settings['default_image']['fid']);
$this->assertNull($settings['default_image']['uuid']);
$field = entity_create('field_config', array(
'field_storage' => $field_storage,
@ -325,14 +325,14 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
'label' => $this->randomMachineName(),
'settings' => array(
'default_image' => array(
'fid' => 100000,
'uuid' => 100000,
)
),
));
$field->save();
$settings = $field->getSettings();
// The non-existent default image should not be saved.
$this->assertNull($settings['default_image']['fid']);
$this->assertNull($settings['default_image']['uuid']);
}
}

View File

@ -318,7 +318,7 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
$alt = $this->randomString(512);
$title = $this->randomString(1024);
$edit = array(
'files[field_storage_settings_default_image_fid]' => drupal_realpath($images[0]->uri),
'files[field_storage_settings_default_image_uuid]' => drupal_realpath($images[0]->uri),
'field_storage[settings][default_image][alt]' => $alt,
'field_storage[settings][default_image][title]' => $title,
);
@ -327,7 +327,7 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
\Drupal::entityManager()->clearCachedFieldDefinitions();
$field_storage = FieldStorageConfig::loadByName('node', $field_name);
$default_image = $field_storage->getSetting('default_image');
$file = file_load($default_image['fid']);
$file = \Drupal::entityManager()->loadEntityByUuid('file', $default_image['uuid']);
$this->assertTrue($file->isPermanent(), 'The default image status is permanent.');
$image = array(
'#theme' => 'image',
@ -363,21 +363,21 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
// Remove default image from the field and make sure it is no longer used.
$edit = array(
'field_storage[settings][default_image][fid][fids]' => 0,
'field_storage[settings][default_image][uuid][fids]' => 0,
);
$this->drupalPostForm("admin/structure/types/manage/article/fields/node.article.$field_name/storage", $edit, t('Save field settings'));
// Clear field definition cache so the new default image is detected.
\Drupal::entityManager()->clearCachedFieldDefinitions();
$field_storage = FieldStorageConfig::loadByName('node', $field_name);
$default_image = $field_storage->getSetting('default_image');
$this->assertFalse($default_image['fid'], 'Default image removed from field.');
$this->assertFalse($default_image['uuid'], 'Default image removed from field.');
// Create an image field that uses the private:// scheme and test that the
// default image works as expected.
$private_field_name = strtolower($this->randomMachineName());
$this->createImageField($private_field_name, 'article', array('uri_scheme' => 'private'));
// Add a default image to the new field.
$edit = array(
'files[field_storage_settings_default_image_fid]' => drupal_realpath($images[1]->uri),
'files[field_storage_settings_default_image_uuid]' => drupal_realpath($images[1]->uri),
'field_storage[settings][default_image][alt]' => $alt,
'field_storage[settings][default_image][title]' => $title,
);
@ -387,7 +387,7 @@ class ImageFieldDisplayTest extends ImageFieldTestBase {
$private_field_storage = FieldStorageConfig::loadByName('node', $private_field_name);
$default_image = $private_field_storage->getSetting('default_image');
$file = file_load($default_image['fid']);
$file = \Drupal::entityManager()->loadEntityByUuid('file', $default_image['uuid']);
$this->assertEqual('private', file_uri_scheme($file->getFileUri()), 'Default image uses private:// scheme.');
$this->assertTrue($file->isPermanent(), 'The default image status is permanent.');
// Create a new node with no image attached and ensure that default private

View File

@ -72,7 +72,7 @@ class MigrateFieldTest extends MigrateDrupalTestBase {
$settings = $field_storage->getSettings();
$this->assertEqual($settings['target_type'], 'file');
$this->assertEqual($settings['uri_scheme'], 'public');
$this->assertEqual($settings['default_image']['fid'], '');
$this->assertEqual($settings['default_image']['uuid'], '');
$this->assertEqual(array_filter($settings['default_image']), array());
// Phone field.

View File

@ -18,7 +18,7 @@ settings:
alt_field_required: false
title_field_required: false
default_image:
fid: null
uuid: null
alt: ''
title: ''
width: null

View File

@ -18,7 +18,7 @@ settings:
max_resolution: 85x85
min_resolution: ''
default_image:
fid: null
uuid: null
alt: ''
title: ''
width: null

View File

@ -6,7 +6,7 @@ module: image
settings:
uri_scheme: public
default_image:
fid: null
uuid: null
alt: ''
title: ''
width: null

View File

@ -7,7 +7,7 @@ type: image
settings:
uri_scheme: public
default_image:
fid: null
uuid: null
alt: ''
title: ''
width: null