diff --git a/core/modules/image/config/schema/image.schema.yml b/core/modules/image/config/schema/image.schema.yml
index 323220b..ad95a70 100644
--- a/core/modules/image/config/schema/image.schema.yml
+++ b/core/modules/image/config/schema/image.schema.yml
@@ -139,6 +139,14 @@ field.formatter.settings.image:
type: string
label: 'Image style'
+field.formatter.settings.image_url:
+ type: mapping
+ label: 'Image URL format settings'
+ mapping:
+ image_style:
+ type: string
+ label: 'Image style'
+
field.widget.settings.image_image:
type: mapping
label: 'Image field display format settings'
diff --git a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php
index 3069721..f81a6d8 100644
--- a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php
+++ b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php
@@ -7,17 +7,8 @@
namespace Drupal\image\Plugin\Field\FieldFormatter;
-use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Field\FieldItemListInterface;
-use Drupal\Core\Field\FieldDefinitionInterface;
-use Drupal\Core\Link;
-use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
-use Drupal\Core\Routing\UrlGeneratorInterface;
-use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
-use Drupal\Core\Utility\LinkGeneratorInterface;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Cache\Cache;
/**
@@ -31,146 +22,15 @@
* }
* )
*/
-class ImageFormatter extends ImageFormatterBase implements ContainerFactoryPluginInterface {
+class ImageFormatter extends ImageFormatterBase {
- /**
- * The current user.
- *
- * @var \Drupal\Core\Session\AccountInterface
- */
- protected $currentUser;
-
- /**
- * The image style entity storage.
- *
- * @var \Drupal\Core\Entity\EntityStorageInterface
- */
- protected $imageStyleStorage;
-
- /**
- * Constructs an ImageFormatter object.
- *
- * @param string $plugin_id
- * The plugin_id for the formatter.
- * @param mixed $plugin_definition
- * The plugin implementation definition.
- * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
- * The definition of the field to which the formatter is associated.
- * @param array $settings
- * The formatter settings.
- * @param string $label
- * The formatter label display setting.
- * @param string $view_mode
- * The view mode.
- * @param array $third_party_settings
- * Any third party settings settings.
- * @param \Drupal\Core\Session\AccountInterface $current_user
- * The current user.
- */
- public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, AccountInterface $current_user, EntityStorageInterface $image_style_storage) {
- parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
- $this->currentUser = $current_user;
- $this->imageStyleStorage = $image_style_storage;
- }
-
- /**
- * {@inheritdoc}
- */
- public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
- return new static(
- $plugin_id,
- $plugin_definition,
- $configuration['field_definition'],
- $configuration['settings'],
- $configuration['label'],
- $configuration['view_mode'],
- $configuration['third_party_settings'],
- $container->get('current_user'),
- $container->get('entity.manager')->getStorage('image_style')
- );
- }
-
- /**
- * {@inheritdoc}
- */
- public static function defaultSettings() {
- return array(
- 'image_style' => '',
- 'image_link' => '',
- ) + parent::defaultSettings();
- }
-
- /**
- * {@inheritdoc}
- */
- public function settingsForm(array $form, FormStateInterface $form_state) {
- $image_styles = image_style_options(FALSE);
- $description_link = Link::fromTextAndUrl(
- $this->t('Configure Image Styles'),
- Url::fromRoute('entity.image_style.collection')
- );
- $element['image_style'] = [
- '#title' => t('Image style'),
- '#type' => 'select',
- '#default_value' => $this->getSetting('image_style'),
- '#empty_option' => t('None (original image)'),
- '#options' => $image_styles,
- '#description' => $description_link->toRenderable() + [
- '#access' => $this->currentUser->hasPermission('administer image styles')
- ],
- ];
- $link_types = array(
- 'content' => t('Content'),
- 'file' => t('File'),
- );
- $element['image_link'] = array(
- '#title' => t('Link image to'),
- '#type' => 'select',
- '#default_value' => $this->getSetting('image_link'),
- '#empty_option' => t('Nothing'),
- '#options' => $link_types,
- );
-
- return $element;
- }
-
- /**
- * {@inheritdoc}
- */
- public function settingsSummary() {
- $summary = array();
-
- $image_styles = image_style_options(FALSE);
- // Unset possible 'No defined styles' option.
- unset($image_styles['']);
- // Styles could be lost because of enabled/disabled modules that defines
- // their styles in code.
- $image_style_setting = $this->getSetting('image_style');
- if (isset($image_styles[$image_style_setting])) {
- $summary[] = t('Image style: @style', array('@style' => $image_styles[$image_style_setting]));
- }
- else {
- $summary[] = t('Original image');
- }
-
- $link_types = array(
- 'content' => t('Linked to content'),
- 'file' => t('Linked to file'),
- );
- // Display this setting only if image is linked.
- $image_link_setting = $this->getSetting('image_link');
- if (isset($link_types[$image_link_setting])) {
- $summary[] = $link_types[$image_link_setting];
- }
-
- return $summary;
- }
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items) {
- $elements = array();
+ $elements = [];
+ /** @var \Drupal\file\Entity\File[] $files */
$files = $this->getEntitiesToView($items);
// Early opt-out if the field is empty.
@@ -194,7 +54,7 @@ public function viewElements(FieldItemListInterface $items) {
$image_style_setting = $this->getSetting('image_style');
// Collect cache tags to be added for each item in the field.
- $cache_tags = array();
+ $cache_tags = [];
if (!empty($image_style_setting)) {
$image_style = $this->imageStyleStorage->load($image_style_setting);
$cache_tags = $image_style->getCacheTags();
@@ -213,19 +73,18 @@ public function viewElements(FieldItemListInterface $items) {
$item_attributes = $item->_attributes;
unset($item->_attributes);
- $elements[$delta] = array(
+ $elements[$delta] = [
'#theme' => 'image_formatter',
'#item' => $item,
'#item_attributes' => $item_attributes,
'#image_style' => $image_style_setting,
'#url' => $url,
- '#cache' => array(
+ '#cache' => [
'tags' => $cache_tags,
- ),
- );
+ ],
+ ];
}
return $elements;
}
-
}
diff --git a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatterBase.php b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatterBase.php
index 6a0d3ed..cd4ab7e 100644
--- a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatterBase.php
+++ b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatterBase.php
@@ -7,14 +7,154 @@
namespace Drupal\image\Plugin\Field\FieldFormatter;
+use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Field\EntityReferenceFieldItemListInterface;
+use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Link;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\Url;
use Drupal\field\FieldConfigInterface;
use Drupal\file\Plugin\Field\FieldFormatter\FileFormatterBase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Base class for image file formatters.
*/
-abstract class ImageFormatterBase extends FileFormatterBase {
+abstract class ImageFormatterBase extends FileFormatterBase implements ContainerFactoryPluginInterface {
+
+ /**
+ * The current user.
+ *
+ * @var \Drupal\Core\Session\AccountInterface
+ */
+ protected $currentUser;
+
+ /**
+ * The image style entity storage.
+ *
+ * @var \Drupal\Core\Entity\EntityStorageInterface
+ */
+ protected $imageStyleStorage;
+
+ /**
+ * Constructs an ImageFormatter object.
+ *
+ * @param string $plugin_id
+ * The plugin_id for the formatter.
+ * @param mixed $plugin_definition
+ * The plugin implementation definition.
+ * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
+ * The definition of the field to which the formatter is associated.
+ * @param array $settings
+ * The formatter settings.
+ * @param string $label
+ * The formatter label display setting.
+ * @param string $view_mode
+ * The view mode.
+ * @param array $third_party_settings
+ * Any third party settings settings.
+ * @param \Drupal\Core\Session\AccountInterface $current_user
+ * The current user.
+ */
+ public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, AccountInterface $current_user, EntityStorageInterface $image_style_storage) {
+ parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
+ $this->currentUser = $current_user;
+ $this->imageStyleStorage = $image_style_storage;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+ return new static(
+ $plugin_id,
+ $plugin_definition,
+ $configuration['field_definition'],
+ $configuration['settings'],
+ $configuration['label'],
+ $configuration['view_mode'],
+ $configuration['third_party_settings'],
+ $container->get('current_user'),
+ $container->get('entity.manager')->getStorage('image_style')
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function defaultSettings() {
+ return [
+ 'image_style' => '',
+ 'image_link' => '',
+ ] + parent::defaultSettings();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function settingsForm(array $form, FormStateInterface $form_state) {
+ $image_styles = image_style_options(FALSE);
+ $description_link = Link::fromTextAndUrl(
+ $this->t('Configure Image Styles'),
+ Url::fromRoute('entity.image_style.collection')
+ );
+ $element['image_style'] = [
+ '#title' => t('Image style'),
+ '#type' => 'select',
+ '#default_value' => $this->getSetting('image_style'),
+ '#empty_option' => t('None (original image)'),
+ '#options' => $image_styles,
+ '#description' => $description_link->toRenderable() + [
+ '#access' => $this->currentUser->hasPermission('administer image styles')
+ ],
+ ];
+ $link_types = [
+ 'content' => t('Content'),
+ 'file' => t('File'),
+ ];
+ $element['image_link'] = [
+ '#title' => t('Link image to'),
+ '#type' => 'select',
+ '#default_value' => $this->getSetting('image_link'),
+ '#empty_option' => t('Nothing'),
+ '#options' => $link_types,
+ ];
+ return $element;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function settingsSummary() {
+ $summary = [];
+ $image_styles = image_style_options(FALSE);
+
+ // Unset possible 'No defined styles' option.
+ unset($image_styles['']);
+
+ // Styles could be lost because of enabled/disabled modules that defines
+ // their styles in code.
+ $image_style_setting = $this->getSetting('image_style');
+ if (isset($image_styles[$image_style_setting])) {
+ $summary[] = t('Image style: @style', ['@style' => $image_styles[$image_style_setting]]);
+ }
+ else {
+ $summary[] = t('Original image');
+ }
+ $link_types = [
+ 'content' => t('Linked to content'),
+ 'file' => t('Linked to file'),
+ ];
+
+ // Display this setting only if image is linked.
+ $image_link_setting = $this->getSetting('image_link');
+ if (isset($link_types[$image_link_setting])) {
+ $summary[] = $link_types[$image_link_setting];
+ }
+ return $summary;
+ }
/**
* {@inheritdoc}
@@ -23,18 +163,19 @@ protected function getEntitiesToView(EntityReferenceFieldItemListInterface $item
// 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 (!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(
+ $items->setValue([
'target_id' => $file->id(),
'alt' => $default_image['alt'],
'title' => $default_image['title'],
@@ -43,12 +184,26 @@ protected function getEntitiesToView(EntityReferenceFieldItemListInterface $item
'entity' => $file,
'_loaded' => TRUE,
'_is_default' => TRUE,
- ));
+ ]);
$file->_referringItem = $items[0];
}
}
-
return parent::getEntitiesToView($items);
}
+ /**
+ * {@inheritdoc}
+ */
+ public function calculateDependencies() {
+ // Make sure to include 3rd party dependencies.
+ $dependencies = parent::calculateDependencies();
+
+ // Check for image style.
+ if (!empty($image_style_setting) && $image_style = $this->imageStyleStorage->load($image_style_setting)) {
+ // Add the image style dependencies as well.
+ $dependencies['config'][] = $image_style->getConfigDependencyName();
+ }
+
+ return $dependencies;
+ }
}
diff --git a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageUrlFormatter.php b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageUrlFormatter.php
new file mode 100644
index 0000000..9d4fc11
--- /dev/null
+++ b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageUrlFormatter.php
@@ -0,0 +1,85 @@
+getEntitiesToView($items);
+
+ // Early opt-out if the field is empty.
+ if (empty($images)) {
+ return $elements;
+ }
+
+ $image_link_setting = $this->getSetting('image_link');
+ // Url to be linked to.
+ $link_url = FALSE;
+ // Check if the formatter involves a link.
+ if ($image_link_setting == 'content') {
+ $entity = $items->getEntity();
+ if (!$entity->isNew()) {
+ $link_url = $entity->urlInfo();
+ }
+ }
+
+ /** @var \Drupal\image\Entity\ImageStyle|false $image_style */
+ $image_style = ($image_style_setting = $this->getSetting('image_style')) && !empty($image_style_setting) ? $this->imageStyleStorage->load($image_style_setting) : NULL;
+
+ foreach ($images as $delta => $image) {
+ /** @var \Drupal\file\Entity\File $image */
+ $image_uri = $image->getFileUri();
+ $url = $image_style
+ ? $image_style->buildUrl($image_uri)
+ : file_create_url($image_uri);
+
+ // Set the link url if settings require such.
+ $link_url = ($image_link_setting == 'file') ? Url::fromUri($url) : $link_url;
+
+ // Collect cache tags to be added for each item in the field.
+ $cache_tags = $image_style
+ ? Cache::mergeTags($image_style->getCacheTags(), $image->getCacheTags())
+ : $image->getCacheTags();
+
+ // Add a link if we have a valid link url.
+ $elements[$delta] = ($link_url instanceof Url)
+ ? Link::fromTextAndUrl($url, $link_url)->toRenderable() + [
+ '#cache' => [
+ 'tags' => $cache_tags,
+ ],
+ ] : [
+ '#markup' => $url,
+ '#cache' => [
+ 'tags' => $cache_tags,
+ ],
+ ];
+ }
+
+ return $elements;
+ }
+}
diff --git a/core/modules/image/src/Tests/ImageFieldDisplayTest.php b/core/modules/image/src/Tests/ImageFieldDisplayTest.php
index c4cf485..8cd47ad 100644
--- a/core/modules/image/src/Tests/ImageFieldDisplayTest.php
+++ b/core/modules/image/src/Tests/ImageFieldDisplayTest.php
@@ -8,6 +8,7 @@
namespace Drupal\image\Tests;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\Core\Url;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\user\RoleInterface;
use Drupal\image\Entity\ImageStyle;
@@ -93,6 +94,7 @@ function _testImageFieldFormatters($scheme) {
// Save node.
$nid = $this->uploadNodeImage($test_image, $field_name, 'article', $alt);
$node_storage->resetCache(array($nid));
+ /** @var \Drupal\node\Entity\Node $node */
$node = $node_storage->load($nid);
// Test that the default formatter is being used.
@@ -202,6 +204,51 @@ function _testImageFieldFormatters($scheme) {
$this->drupalGet(ImageStyle::load('thumbnail')->buildUrl($image_uri));
$this->assertResponse('403', 'Access denied to image style thumbnail as anonymous user.');
}
+
+ // Test the image URL formatter without an image style.
+ $display_options = [
+ 'type' => 'image_url',
+ 'settings' => [],
+ ];
+
+ $expected_url = file_create_url($image_uri);
+ $this->assertEqual($expected_url, $node->{$field_name}->view($display_options)[0]['#markup']);
+
+ // Test the image URL formatter with an image style.
+ $display_options = [
+ 'type' => 'image_url',
+ 'settings' => [
+ 'image_style' => 'thumbnail',
+ ],
+ ];
+
+ $expected_url = ImageStyle::load('thumbnail')->buildUrl($image_uri);
+ $this->assertEqual($expected_url, $node->{$field_name}->view($display_options)[0]['#markup']);
+
+ // Test the image URL formatter with an image style that links to content.
+ $display_options = [
+ 'type' => 'image_url',
+ 'settings' => [
+ 'image_style' => 'thumbnail',
+ 'image_link' => 'content',
+ ],
+ ];
+
+ $expected_output = '' . ImageStyle::load('thumbnail')->buildUrl($image_uri) . '';
+ $this->assertEqual($expected_output, (string) $renderer->renderRoot($node->{$field_name}->view($display_options)[0]));
+
+ // Test the image URL formatter with an image style that links to file.
+ $display_options = [
+ 'type' => 'image_url',
+ 'settings' => [
+ 'image_style' => 'thumbnail',
+ 'image_link' => 'file',
+ ],
+ ];
+
+ $expected_url = ImageStyle::load('thumbnail')->buildUrl($image_uri);
+ $expected_output = '' . $expected_url . '';
+ $this->assertEqual($expected_output, (string) $renderer->renderRoot($node->{$field_name}->view($display_options)[0]));
}
/**
diff --git a/core/modules/responsive_image/src/Plugin/Field/FieldFormatter/ResponsiveImageFormatter.php b/core/modules/responsive_image/src/Plugin/Field/FieldFormatter/ResponsiveImageFormatter.php
index 7749452..8a0a9a7 100644
--- a/core/modules/responsive_image/src/Plugin/Field/FieldFormatter/ResponsiveImageFormatter.php
+++ b/core/modules/responsive_image/src/Plugin/Field/FieldFormatter/ResponsiveImageFormatter.php
@@ -116,17 +116,17 @@ public static function create(ContainerInterface $container, array $configuratio
* {@inheritdoc}
*/
public static function defaultSettings() {
- return array(
+ return [
'responsive_image_style' => '',
'image_link' => '',
- ) + parent::defaultSettings();
+ ] + parent::defaultSettings();
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
- $responsive_image_options = array();
+ $responsive_image_options = [];
$responsive_image_styles = $this->responsiveImageStyleStorage->loadMultiple();
if ($responsive_image_styles && !empty($responsive_image_styles)) {
foreach ($responsive_image_styles as $machine_name => $responsive_image_style) {
@@ -136,29 +136,29 @@ public function settingsForm(array $form, FormStateInterface $form_state) {
}
}
- $elements['responsive_image_style'] = array(
+ $elements['responsive_image_style'] = [
'#title' => t('Responsive image style'),
'#type' => 'select',
'#default_value' => $this->getSetting('responsive_image_style'),
'#required' => TRUE,
'#options' => $responsive_image_options,
- '#description' => array(
+ '#description' => [
'#markup' => $this->linkGenerator->generate($this->t('Configure Responsive Image Styles'), new Url('entity.responsive_image_style.collection')),
'#access' => $this->currentUser->hasPermission('administer responsive image styles'),
- ),
+ ],
);
- $link_types = array(
+ $link_types = [
'content' => t('Content'),
'file' => t('File'),
- );
- $elements['image_link'] = array(
+ ];
+ $elements['image_link'] = [
'#title' => t('Link image to'),
'#type' => 'select',
'#default_value' => $this->getSetting('image_link'),
'#empty_option' => t('Nothing'),
'#options' => $link_types,
- );
+ ];
return $elements;
}
@@ -167,16 +167,16 @@ public function settingsForm(array $form, FormStateInterface $form_state) {
* {@inheritdoc}
*/
public function settingsSummary() {
- $summary = array();
+ $summary = [];
$responsive_image_style = $this->responsiveImageStyleStorage->load($this->getSetting('responsive_image_style'));
if ($responsive_image_style) {
- $summary[] = t('Responsive image style: @responsive_image_style', array('@responsive_image_style' => $responsive_image_style->label()));
+ $summary[] = t('Responsive image style: @responsive_image_style', ['@responsive_image_style' => $responsive_image_style->label()]);
- $link_types = array(
+ $link_types = [
'content' => t('Linked to content'),
'file' => t('Linked to file'),
- );
+ ];
// Display this setting only if image is linked.
if (isset($link_types[$this->getSetting('image_link')])) {
$summary[] = $link_types[$this->getSetting('image_link')];
@@ -193,7 +193,7 @@ public function settingsSummary() {
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items) {
- $elements = array();
+ $elements = [];
$files = $this->getEntitiesToView($items);
// Early opt-out if the field is empty.
@@ -215,7 +215,7 @@ public function viewElements(FieldItemListInterface $items) {
// Collect cache tags to be added for each item in the field.
$responsive_image_style = $this->responsiveImageStyleStorage->load($this->getSetting('responsive_image_style'));
- $image_styles_to_load = array();
+ $image_styles_to_load = [];
$cache_tags = [];
if ($responsive_image_style) {
$cache_tags = Cache::mergeTags($cache_tags, $responsive_image_style->getCacheTags());
@@ -238,16 +238,16 @@ public function viewElements(FieldItemListInterface $items) {
$item_attributes = $item->_attributes;
unset($item->_attributes);
- $elements[$delta] = array(
+ $elements[$delta] = [
'#theme' => 'responsive_image_formatter',
'#item' => $item,
'#item_attributes' => $item_attributes,
'#responsive_image_style_id' => $responsive_image_style ? $responsive_image_style->id() : '',
'#url' => $url,
- '#cache' => array(
+ '#cache' => [
'tags' => $cache_tags,
- ),
- );
+ ],
+ ];
}
return $elements;
}