Issue #2405469 by yched, googletorp, amateescu, larowlan, Berdir: FileFormatterBase should extend EntityReferenceFormatterBase
parent
9c0bfb2d3b
commit
ef0cb6e091
|
@ -7,7 +7,8 @@
|
|||
|
||||
namespace Drupal\Core\Field\Plugin\Field\FieldFormatter;
|
||||
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Drupal\Core\Field\EntityReferenceFieldItemListInterface;
|
||||
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
|
||||
use Drupal\Core\Field\FormatterBase;
|
||||
use Drupal\Core\TypedData\TranslatableInterface;
|
||||
|
||||
|
@ -17,15 +18,26 @@ use Drupal\Core\TypedData\TranslatableInterface;
|
|||
abstract class EntityReferenceFormatterBase extends FormatterBase {
|
||||
|
||||
/**
|
||||
* Returns the accessible and translated entities for view.
|
||||
* Returns the referenced entities for display.
|
||||
*
|
||||
* @param \Drupal\Core\Field\FieldItemListInterface $items
|
||||
* The method takes care of:
|
||||
* - checking entity access,
|
||||
* - placing the entities in the language expected for display.
|
||||
* It is thus strongly recommended that formatters use it in their
|
||||
* implementation of viewElements($items) rather than dealing with $items
|
||||
* directly.
|
||||
*
|
||||
* For each entity, the EntityReferenceItem by which the entity is referenced
|
||||
* is available in $entity->_referringItem. This is useful for field types
|
||||
* that store additional values next to the reference itself.
|
||||
*
|
||||
* @param \Drupal\Core\Field\EntityReferenceFieldItemListInterface $items
|
||||
* The item list.
|
||||
*
|
||||
* @return \Drupal\Core\Entity\EntityInterface[]
|
||||
* The entities to view.
|
||||
* The array of referenced entities to display, keyed by delta.
|
||||
*/
|
||||
protected function getEntitiesToView(FieldItemListInterface $items) {
|
||||
protected function getEntitiesToView(EntityReferenceFieldItemListInterface $items) {
|
||||
$entities = array();
|
||||
|
||||
$parent_entity_langcode = $items->getEntity()->language()->getId();
|
||||
|
@ -39,8 +51,10 @@ abstract class EntityReferenceFormatterBase extends FormatterBase {
|
|||
$entity = $entity->getTranslation($parent_entity_langcode);
|
||||
}
|
||||
|
||||
// Check entity access.
|
||||
if ($entity->access('view')) {
|
||||
// Check entity access if needed.
|
||||
if (!$this->needsAccessCheck($item) || $entity->access('view')) {
|
||||
// Add the referring item, in case the formatter needs it.
|
||||
$entity->_referringItem = $items[$delta];
|
||||
$entities[$delta] = $entity;
|
||||
}
|
||||
}
|
||||
|
@ -56,10 +70,9 @@ abstract class EntityReferenceFormatterBase extends FormatterBase {
|
|||
* viewed.
|
||||
*/
|
||||
public function prepareView(array $entities_items) {
|
||||
// Load the existing (non-autocreate) entities. For performance, we want to
|
||||
// use a single "multiple entity load" to load all the entities for the
|
||||
// multiple "entity reference item lists" that are being displayed. We thus
|
||||
// cannot use
|
||||
// Collect entity IDs to load. For performance, we want to use a single
|
||||
// "multiple entity load" to load all the entities for the multiple
|
||||
// "entity reference item lists" being displayed. We thus cannot use
|
||||
// \Drupal\Core\Field\EntityReferenceFieldItemList::referencedEntities().
|
||||
$ids = array();
|
||||
foreach ($entities_items as $items) {
|
||||
|
@ -69,7 +82,7 @@ abstract class EntityReferenceFormatterBase extends FormatterBase {
|
|||
// contains a valid entity ready for display. All items are initialized
|
||||
// at FALSE.
|
||||
$item->_loaded = FALSE;
|
||||
if ($item->target_id !== NULL) {
|
||||
if ($this->needsEntityLoad($item)) {
|
||||
$ids[] = $item->target_id;
|
||||
}
|
||||
}
|
||||
|
@ -94,4 +107,30 @@ abstract class EntityReferenceFormatterBase extends FormatterBase {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the entity referenced by an item needs to be loaded.
|
||||
*
|
||||
* @param \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem $item
|
||||
* The item to check.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the entity needs to be loaded.
|
||||
*/
|
||||
protected function needsEntityLoad(EntityReferenceItem $item) {
|
||||
return !$item->hasNewEntity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether entity access should be checked.
|
||||
*
|
||||
* @param \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem $item
|
||||
* The item to check.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if entity access should be checked.
|
||||
*/
|
||||
protected function needsAccessCheck(EntityReferenceItem $item) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\FileAccessFormatterControlHandlerInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\file;
|
||||
|
||||
use Drupal\Core\Entity\EntityAccessControlHandlerInterface;
|
||||
|
||||
/**
|
||||
* Defines an interface for file access handlers that need to run on file formatters.
|
||||
*
|
||||
* \Drupal\Core\Field\Plugin\Field\FieldFormatter\EntityReferenceFormatterBase,
|
||||
* which file and image formatters extend, checks 'view' access on the
|
||||
* referenced files before displaying them. That check would be useless and
|
||||
* costly with Core's default access control implementation for files
|
||||
* (\Drupal\file\FileAccessControlHandler grants access based on whether
|
||||
* there are existing entities with granted access that reference the file). But
|
||||
* it might be needed if a different access control handler with different logic
|
||||
* is swapped in.
|
||||
*
|
||||
* \Drupal\file\Plugin\Field\FieldFormatter\FileFormatterBase thus adjusts that
|
||||
* behavior, and only checks access if the access control handler in use for
|
||||
* files opts in by implementing this interface.
|
||||
*
|
||||
* @see \Drupal\file\Plugin\Field\FieldFormatter\FileFormatterBase::needsAccessCheck()
|
||||
*/
|
||||
interface FileAccessFormatterControlHandlerInterface extends EntityAccessControlHandlerInterface { }
|
|
@ -7,40 +7,29 @@
|
|||
|
||||
namespace Drupal\file\Plugin\Field\FieldFormatter;
|
||||
|
||||
use Drupal\Core\Field\FormatterBase;
|
||||
use Drupal\Core\Field\Plugin\Field\FieldFormatter\EntityReferenceFormatterBase;
|
||||
use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
|
||||
|
||||
/**
|
||||
* Base class for file formatters.
|
||||
*/
|
||||
abstract class FileFormatterBase extends FormatterBase {
|
||||
abstract class FileFormatterBase extends EntityReferenceFormatterBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prepareView(array $entities_items) {
|
||||
// Remove files specified to not be displayed.
|
||||
$fids = array();
|
||||
foreach ($entities_items as $items) {
|
||||
foreach ($items as $item) {
|
||||
if ($item->isDisplayed() && !empty($item->target_id)) {
|
||||
// Load the files from the files table.
|
||||
$fids[] = $item->target_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($fids) {
|
||||
$files = file_load_multiple($fids);
|
||||
|
||||
foreach ($entities_items as $items) {
|
||||
/** @var \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem $item */
|
||||
foreach ($items as $item) {
|
||||
// If the file does not exist, mark the entire item as empty.
|
||||
if (!empty($item->target_id) && !$item->hasNewEntity()) {
|
||||
$item->entity = isset($files[$item->target_id]) ? $files[$item->target_id] : NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
protected function needsEntityLoad(EntityReferenceItem $item) {
|
||||
return parent::needsEntityLoad($item) && $item->isDisplayed();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function needsAccessCheck(EntityReferenceItem $item) {
|
||||
// Only check access if the current file access control handler explicitly
|
||||
// opts in by implementing FileAccessFormatterControlHandlerInterface.
|
||||
$access_handler_class = $item->entity->getEntityType()->getHandlerClass('access');
|
||||
return is_subclass_of($access_handler_class, '\Drupal\file\FileAccessFormatterControlHandlerInterface');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,21 +28,20 @@ class GenericFileFormatter extends FileFormatterBase {
|
|||
public function viewElements(FieldItemListInterface $items) {
|
||||
$elements = array();
|
||||
|
||||
foreach ($items as $delta => $item) {
|
||||
if ($item->isDisplayed() && $item->entity) {
|
||||
$elements[$delta] = array(
|
||||
'#theme' => 'file_link',
|
||||
'#file' => $item->entity,
|
||||
'#description' => $item->description,
|
||||
);
|
||||
// Pass field item attributes to the theme function.
|
||||
if (isset($item->_attributes)) {
|
||||
$elements[$delta] += array('#attributes' => array());
|
||||
$elements[$delta]['#attributes'] += $item->_attributes;
|
||||
// Unset field item attributes since they have been included in the
|
||||
// formatter output and should not be rendered in the field template.
|
||||
unset($item->_attributes);
|
||||
}
|
||||
foreach ($this->getEntitiesToView($items) as $delta => $file) {
|
||||
$item = $file->_referringItem;
|
||||
$elements[$delta] = array(
|
||||
'#theme' => 'file_link',
|
||||
'#file' => $file,
|
||||
'#description' => $item->description,
|
||||
);
|
||||
// Pass field item attributes to the theme function.
|
||||
if (isset($item->_attributes)) {
|
||||
$elements[$delta] += array('#attributes' => array());
|
||||
$elements[$delta]['#attributes'] += $item->_attributes;
|
||||
// Unset field item attributes since they have been included in the
|
||||
// formatter output and should not be rendered in the field template.
|
||||
unset($item->_attributes);
|
||||
}
|
||||
}
|
||||
if (!empty($elements)) {
|
||||
|
|
|
@ -29,21 +29,16 @@ class RSSEnclosureFormatter extends FileFormatterBase {
|
|||
$entity = $items->getEntity();
|
||||
// Add the first file as an enclosure to the RSS item. RSS allows only one
|
||||
// enclosure per item. See: http://en.wikipedia.org/wiki/RSS_enclosure
|
||||
foreach ($items as $item) {
|
||||
if ($item->isDisplayed() && $item->entity) {
|
||||
$file = $item->entity;
|
||||
$entity->rss_elements[] = array(
|
||||
'key' => 'enclosure',
|
||||
'attributes' => array(
|
||||
'url' => file_create_url($file->getFileUri()),
|
||||
'length' => $file->getSize(),
|
||||
'type' => $file->getMimeType(),
|
||||
),
|
||||
);
|
||||
break;
|
||||
}
|
||||
foreach ($this->getEntitiesToView($items) as $delta => $file) {
|
||||
$entity->rss_elements[] = array(
|
||||
'key' => 'enclosure',
|
||||
'attributes' => array(
|
||||
'url' => file_create_url($file->getFileUri()),
|
||||
'length' => $file->getSize(),
|
||||
'type' => $file->getMimeType(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,22 +28,19 @@ class TableFormatter extends FileFormatterBase {
|
|||
public function viewElements(FieldItemListInterface $items) {
|
||||
$elements = array();
|
||||
|
||||
if (!$items->isEmpty()) {
|
||||
|
||||
if ($files = $this->getEntitiesToView($items)) {
|
||||
$header = array(t('Attachment'), t('Size'));
|
||||
$rows = array();
|
||||
foreach ($items as $delta => $item) {
|
||||
if ($item->isDisplayed() && $item->entity) {
|
||||
$rows[] = array(
|
||||
array(
|
||||
'data' => array(
|
||||
'#theme' => 'file_link',
|
||||
'#file' => $item->entity,
|
||||
),
|
||||
foreach ($files as $delta => $file) {
|
||||
$rows[] = array(
|
||||
array(
|
||||
'data' => array(
|
||||
'#theme' => 'file_link',
|
||||
'#file' => $file,
|
||||
),
|
||||
array('data' => format_size($item->entity->getSize())),
|
||||
);
|
||||
}
|
||||
),
|
||||
array('data' => format_size($file->getSize())),
|
||||
);
|
||||
}
|
||||
|
||||
$elements[0] = array();
|
||||
|
|
|
@ -28,10 +28,8 @@ class UrlPlainFormatter extends FileFormatterBase {
|
|||
public function viewElements(FieldItemListInterface $items) {
|
||||
$elements = array();
|
||||
|
||||
foreach ($items as $delta => $item) {
|
||||
if ($item->isDisplayed() && $item->entity) {
|
||||
$elements[$delta] = array('#markup' => empty($item->entity) ? '' : file_create_url($item->entity->getFileUri()));
|
||||
}
|
||||
foreach ($this->getEntitiesToView($items) as $delta => $file) {
|
||||
$elements[$delta] = array('#markup' => file_create_url($file->getFileUri()));
|
||||
}
|
||||
|
||||
return $elements;
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file\Tests\FileFieldFormatterAccessTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\file\Tests;
|
||||
|
||||
|
||||
/**
|
||||
* Tests file formatter access.
|
||||
* @group file
|
||||
*/
|
||||
class FileFieldFormatterAccessTest extends FileFieldTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node', 'file', 'field_ui', 'file_test'];
|
||||
|
||||
/**
|
||||
* Tests the custom access handler is invoked.
|
||||
*/
|
||||
public function testFileAccessHandler() {
|
||||
$type_name = 'article';
|
||||
$field_name = strtolower($this->randomMachineName());
|
||||
$this->createFileField($field_name, 'node', $type_name);
|
||||
\Drupal::state()->set('file_test_alternate_access_handler', TRUE);
|
||||
\Drupal::entityManager()->clearCachedDefinitions();
|
||||
$test_file = $this->getTestFile('text');
|
||||
$nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
|
||||
$this->drupalGet('node/' . $nid);
|
||||
$this->assertTrue(\Drupal::state()->get('file_access_formatter_check', FALSE));
|
||||
}
|
||||
|
||||
}
|
|
@ -333,3 +333,14 @@ function file_test_file_scan_callback($filepath = NULL) {
|
|||
function file_test_file_scan_callback_reset() {
|
||||
drupal_static_reset('file_test_file_scan_callback');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_entity_info_alter().
|
||||
*/
|
||||
function file_test_entity_type_alter(&$entity_types) {
|
||||
if (\Drupal::state()->get('file_test_alternate_access_handler', FALSE)) {
|
||||
/** @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
|
||||
$entity_types['file']
|
||||
->setAccessClass('Drupal\file_test\FileTestAccessControlHandler');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\file_test\FileTestAccessControlHandler.
|
||||
*/
|
||||
|
||||
namespace Drupal\file_test;
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\file\FileAccessFormatterControlHandlerInterface;
|
||||
use Drupal\file\FileAccessControlHandler;
|
||||
|
||||
/**
|
||||
* Defines a class for an alternate file access control handler.
|
||||
*/
|
||||
class FileTestAccessControlHandler extends FileAccessControlHandler implements FileAccessFormatterControlHandlerInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function checkAccess(EntityInterface $entity, $operation, $langcode, AccountInterface $account) {
|
||||
\Drupal::state()->set('file_access_formatter_check', TRUE);
|
||||
return parent::checkAccess($entity, $operation, $langcode, $account);
|
||||
}
|
||||
|
||||
}
|
|
@ -167,8 +167,14 @@ class ImageFormatter extends ImageFormatterBase implements ContainerFactoryPlugi
|
|||
*/
|
||||
public function viewElements(FieldItemListInterface $items) {
|
||||
$elements = array();
|
||||
$url = NULL;
|
||||
$files = $this->getEntitiesToView($items);
|
||||
|
||||
// Early opt-out if the field is empty.
|
||||
if (empty($files)) {
|
||||
return $elements;
|
||||
}
|
||||
|
||||
$url = NULL;
|
||||
$image_link_setting = $this->getSetting('image_link');
|
||||
// Check if the formatter involves a link.
|
||||
if ($image_link_setting == 'content') {
|
||||
|
@ -190,29 +196,28 @@ class ImageFormatter extends ImageFormatterBase implements ContainerFactoryPlugi
|
|||
$cache_tags = $image_style->getCacheTags();
|
||||
}
|
||||
|
||||
foreach ($items as $delta => $item) {
|
||||
if ($item->entity) {
|
||||
if (isset($link_file)) {
|
||||
$image_uri = $item->entity->getFileUri();
|
||||
$url = Url::fromUri(file_create_url($image_uri));
|
||||
}
|
||||
|
||||
// Extract field item attributes for the theme function, and unset them
|
||||
// from the $item so that the field template does not re-render them.
|
||||
$item_attributes = $item->_attributes;
|
||||
unset($item->_attributes);
|
||||
|
||||
$elements[$delta] = array(
|
||||
'#theme' => 'image_formatter',
|
||||
'#item' => $item,
|
||||
'#item_attributes' => $item_attributes,
|
||||
'#image_style' => $image_style_setting,
|
||||
'#url' => $url,
|
||||
'#cache' => array(
|
||||
'tags' => $cache_tags,
|
||||
),
|
||||
);
|
||||
foreach ($files as $delta => $file) {
|
||||
if (isset($link_file)) {
|
||||
$image_uri = $file->getFileUri();
|
||||
$url = Url::fromUri(file_create_url($image_uri));
|
||||
}
|
||||
|
||||
// Extract field item attributes for the theme function, and unset them
|
||||
// from the $item so that the field template does not re-render them.
|
||||
$item = $file->_referringItem;
|
||||
$item_attributes = $item->_attributes;
|
||||
unset($item->_attributes);
|
||||
|
||||
$elements[$delta] = array(
|
||||
'#theme' => 'image_formatter',
|
||||
'#item' => $item,
|
||||
'#item_attributes' => $item_attributes,
|
||||
'#image_style' => $image_style_setting,
|
||||
'#url' => $url,
|
||||
'#cache' => array(
|
||||
'tags' => $cache_tags,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return $elements;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
namespace Drupal\image\Plugin\Field\FieldFormatter;
|
||||
|
||||
use Drupal\Core\Field\EntityReferenceFieldItemListInterface;
|
||||
use Drupal\field\FieldConfigInterface;
|
||||
use Drupal\file\Plugin\Field\FieldFormatter\FileFormatterBase;
|
||||
|
||||
|
@ -18,33 +19,36 @@ abstract class ImageFormatterBase extends FileFormatterBase {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function prepareView(array $entities_items) {
|
||||
parent::prepareView($entities_items);
|
||||
protected function getEntitiesToView(EntityReferenceFieldItemListInterface $items) {
|
||||
// Add the default image if needed.
|
||||
if ($items->isEmpty()) {
|
||||
$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['uuid']) && $this->fieldDefinition instanceof FieldConfigInterface) {
|
||||
$default_image = $this->fieldDefinition->getFieldStorageDefinition()->getSetting('default_image');
|
||||
}
|
||||
|
||||
// If there are no files specified at all, use the default.
|
||||
foreach ($entities_items as $items) {
|
||||
if ($items->isEmpty()) {
|
||||
// Add the default image if one is found.
|
||||
$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['uuid']) && $this->fieldDefinition instanceof FieldConfigInterface) {
|
||||
$default_image = $this->fieldDefinition->getFieldStorageDefinition()->getSetting('default_image');
|
||||
}
|
||||
|
||||
if (!empty($default_image['uuid']) && ($file = \Drupal::entityManager()->loadEntityByUuid('file', $default_image['uuid']))) {
|
||||
$items->setValue(array(array(
|
||||
'is_default' => TRUE,
|
||||
'alt' => $default_image['alt'],
|
||||
'title' => $default_image['title'],
|
||||
'width' => $default_image['width'],
|
||||
'height' => $default_image['height'],
|
||||
'entity' => $file,
|
||||
'target_id' => $file->id(),
|
||||
)));
|
||||
}
|
||||
if (!empty($default_image['uuid']) && $file = \Drupal::entityManager()->loadEntityByUuid('file', $default_image['uuid'])) {
|
||||
// Clone the FieldItemList into a runtime-only object for the formatter,
|
||||
// so that the fallback image can be rendered without affecting the
|
||||
// field values in the entity being rendered.
|
||||
$items = clone $items;
|
||||
$items->setValue(array(
|
||||
'target_id' => $file->id(),
|
||||
'alt' => $default_image['alt'],
|
||||
'title' => $default_image['title'],
|
||||
'width' => $default_image['width'],
|
||||
'height' => $default_image['height'],
|
||||
'entity' => $file,
|
||||
'_loaded' => TRUE,
|
||||
'_is_default' => TRUE,
|
||||
));
|
||||
$file->_referringItem = $items[0];
|
||||
}
|
||||
}
|
||||
|
||||
return parent::getEntitiesToView($items);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -154,7 +154,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
|
|||
$article = $this->drupalCreateNode(array('type' => 'article'));
|
||||
$article_built = $this->drupalBuildEntityView($article);
|
||||
$this->assertEqual(
|
||||
$article_built[$field_name]['#items'][0]->target_id,
|
||||
$article_built[$field_name][0]['#item']->target_id,
|
||||
$default_images['field']->id(),
|
||||
format_string(
|
||||
'A new article node without an image has the expected default image file ID of @fid.',
|
||||
|
@ -166,7 +166,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
|
|||
$page = $this->drupalCreateNode(array('type' => 'page'));
|
||||
$page_built = $this->drupalBuildEntityView($page);
|
||||
$this->assertEqual(
|
||||
$page_built[$field_name]['#items'][0]->target_id,
|
||||
$page_built[$field_name][0]['#item']->target_id,
|
||||
$default_images['field2']->id(),
|
||||
format_string(
|
||||
'A new page node without an image has the expected default image file ID of @fid.',
|
||||
|
@ -196,7 +196,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
|
|||
$article_built = $this->drupalBuildEntityView($article = $node_storage->load($article->id()));
|
||||
$page_built = $this->drupalBuildEntityView($page = $node_storage->load($page->id()));
|
||||
$this->assertEqual(
|
||||
$article_built[$field_name]['#items'][0]->target_id,
|
||||
$article_built[$field_name][0]['#item']->target_id,
|
||||
$default_images['field']->id(),
|
||||
format_string(
|
||||
'An existing article node without an image has the expected default image file ID of @fid.',
|
||||
|
@ -204,7 +204,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
|
|||
)
|
||||
);
|
||||
$this->assertEqual(
|
||||
$page_built[$field_name]['#items'][0]->target_id,
|
||||
$page_built[$field_name][0]['#item']->target_id,
|
||||
$default_images['field2']->id(),
|
||||
format_string(
|
||||
'An existing page node without an image has the expected default image file ID of @fid.',
|
||||
|
@ -235,7 +235,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
|
|||
|
||||
// Confirm the article uses the new default.
|
||||
$this->assertEqual(
|
||||
$article_built[$field_name]['#items'][0]->target_id,
|
||||
$article_built[$field_name][0]['#item']->target_id,
|
||||
$default_images['field_new']->id(),
|
||||
format_string(
|
||||
'An existing article node without an image has the expected default image file ID of @fid.',
|
||||
|
@ -244,7 +244,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
|
|||
);
|
||||
// Confirm the page remains unchanged.
|
||||
$this->assertEqual(
|
||||
$page_built[$field_name]['#items'][0]->target_id,
|
||||
$page_built[$field_name][0]['#item']->target_id,
|
||||
$default_images['field2']->id(),
|
||||
format_string(
|
||||
'An existing page node without an image has the expected default image file ID of @fid.',
|
||||
|
@ -275,7 +275,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
|
|||
$page_built = $this->drupalBuildEntityView($page = $node_storage->load($page->id()));
|
||||
// Confirm the article uses the new field (not field) default.
|
||||
$this->assertEqual(
|
||||
$article_built[$field_name]['#items'][0]->target_id,
|
||||
$article_built[$field_name][0]['#item']->target_id,
|
||||
$default_images['field_new']->id(),
|
||||
format_string(
|
||||
'An existing article node without an image has the expected default image file ID of @fid.',
|
||||
|
@ -284,7 +284,7 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
|
|||
);
|
||||
// Confirm the page remains unchanged.
|
||||
$this->assertEqual(
|
||||
$page_built[$field_name]['#items'][0]->target_id,
|
||||
$page_built[$field_name][0]['#item']->target_id,
|
||||
$default_images['field2']->id(),
|
||||
format_string(
|
||||
'An existing page node without an image has the expected default image file ID of @fid.',
|
||||
|
|
|
@ -175,6 +175,13 @@ class ResponsiveImageFormatter extends ImageFormatterBase implements ContainerFa
|
|||
*/
|
||||
public function viewElements(FieldItemListInterface $items) {
|
||||
$elements = array();
|
||||
$files = $this->getEntitiesToView($items);
|
||||
|
||||
// Early opt-out if the field is empty.
|
||||
if (empty($files)) {
|
||||
return $elements;
|
||||
}
|
||||
|
||||
$url = NULL;
|
||||
// Check if the formatter involves a link.
|
||||
if ($this->getSetting('image_link') == 'content') {
|
||||
|
@ -220,10 +227,10 @@ class ResponsiveImageFormatter extends ImageFormatterBase implements ContainerFa
|
|||
$cache_tags = Cache::mergeTags($cache_tags, $image_style->getCacheTags());
|
||||
}
|
||||
|
||||
foreach ($items as $delta => $item) {
|
||||
foreach ($files as $delta => $file) {
|
||||
// Link the <picture> element to the original file.
|
||||
if (isset($link_file)) {
|
||||
$url = Url::fromUri(file_create_url($item->entity->getFileUri()));
|
||||
$url = Url::fromUri(file_create_url($file->getFileUri()));
|
||||
}
|
||||
$elements[$delta] = array(
|
||||
'#theme' => 'responsive_image_formatter',
|
||||
|
@ -232,7 +239,7 @@ class ResponsiveImageFormatter extends ImageFormatterBase implements ContainerFa
|
|||
'core/picturefill',
|
||||
),
|
||||
),
|
||||
'#item' => $item,
|
||||
'#item' => $file->_referringItem,
|
||||
'#image_style' => $fallback_image_style,
|
||||
'#responsive_image_style_id' => $responsive_image_style ? $responsive_image_style->id() : '',
|
||||
'#url' => $url,
|
||||
|
|
Loading…
Reference in New Issue