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 5f15073..fcdcb87 100644 --- a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php +++ b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php @@ -7,15 +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\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; @@ -30,113 +23,34 @@ * } * ) */ -class ImageFormatter extends ImageFormatterBase implements ContainerFactoryPluginInterface { - - /** - * The current user. - * - * @var \Drupal\Core\Session\AccountInterface - */ - protected $currentUser; - - /** - * The link generator. - * - * @var \Drupal\Core\Utility\LinkGeneratorInterface - */ - protected $linkGenerator; - - /** - * 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. - * @param \Drupal\Core\Utility\LinkGeneratorInterface $link_generator - * The link generator service. - */ - public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, AccountInterface $current_user, LinkGeneratorInterface $link_generator, EntityStorageInterface $image_style_storage) { - parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings); - $this->currentUser = $current_user; - $this->linkGenerator = $link_generator; - $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('link_generator'), - $container->get('entity.manager')->getStorage('image_style') - ); - } +class ImageFormatter extends ImageFormatterBase { /** * {@inheritdoc} */ public static function defaultSettings() { - return array( - 'image_style' => '', + return [ 'image_link' => '', - ) + parent::defaultSettings(); + ] + parent::defaultSettings(); } /** * {@inheritdoc} */ public function settingsForm(array $form, FormStateInterface $form_state) { - $image_styles = image_style_options(FALSE); - $element['image_style'] = array( - '#title' => t('Image style'), - '#type' => 'select', - '#default_value' => $this->getSetting('image_style'), - '#empty_option' => t('None (original image)'), - '#options' => $image_styles, - '#description' => array( - '#markup' => $this->linkGenerator->generate($this->t('Configure Image Styles'), new Url('entity.image_style.collection')), - '#access' => $this->currentUser->hasPermission('administer image styles'), - ), - ); - $link_types = array( + $element = parent::settingsForm($form, $form_state); + + $link_types = [ 'content' => t('Content'), 'file' => t('File'), - ); - $element['image_link'] = array( + ]; + $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; } @@ -145,25 +59,12 @@ public function settingsForm(array $form, FormStateInterface $form_state) { * {@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'); - } + $summary = parent::settingsSummary(); - $link_types = array( + $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])) { @@ -177,7 +78,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. @@ -201,7 +102,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(); @@ -220,19 +121,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..7e47597 100644 --- a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatterBase.php +++ b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatterBase.php @@ -7,14 +7,91 @@ 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\Plugin\ContainerFactoryPluginInterface; +use Drupal\Core\Session\AccountInterface; +use Drupal\Core\Url; +use Drupal\Core\Utility\LinkGeneratorInterface; 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 link generator. + * + * @var \Drupal\Core\Utility\LinkGeneratorInterface + */ + protected $linkGenerator; + + /** + * 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. + * @param \Drupal\Core\Utility\LinkGeneratorInterface $link_generator + * The link generator service. + */ + public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, AccountInterface $current_user, LinkGeneratorInterface $link_generator, EntityStorageInterface $image_style_storage) { + parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings); + $this->currentUser = $current_user; + $this->linkGenerator = $link_generator; + $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('link_generator'), + $container->get('entity.manager')->getStorage('image_style') + ); + } /** * {@inheritdoc} @@ -34,7 +111,7 @@ protected function getEntitiesToView(EntityReferenceFieldItemListInterface $item // 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,7 +120,7 @@ protected function getEntitiesToView(EntityReferenceFieldItemListInterface $item 'entity' => $file, '_loaded' => TRUE, '_is_default' => TRUE, - )); + ]); $file->_referringItem = $items[0]; } } @@ -51,4 +128,77 @@ protected function getEntitiesToView(EntityReferenceFieldItemListInterface $item return parent::getEntitiesToView($items); } + /** + * {@inheritdoc} + */ + public static function defaultSettings() { + return [ + 'image_style' => '', + ] + parent::defaultSettings(); + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state) { + $image_styles = image_style_options(FALSE); + $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' => [ + '#markup' => $this->linkGenerator->generate($this->t('Configure Image Styles'), new Url('entity.image_style.collection')), + '#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[] = $this->t('Image style: @style', ['@style' => $image_styles[$image_style_setting]]); + } + else { + $summary[] = $this->t('Original image'); + } + return $summary; + } + + /** + * {@inheritdoc} + */ + public function calculateDependencies() { + $dependencies = []; + + if (!empty($image_style_setting) && $image_style = $this->imageStyleStorage->load($image_style_setting)) { + $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..0e74d32 --- /dev/null +++ b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageUrlFormatter.php @@ -0,0 +1,70 @@ +getEntitiesToView($items); + + // Early opt-out if the field is empty. + if (empty($images)) { + return $elements; + } + + $url = NULL; + + $image_style_setting = $this->getSetting('image_style'); + + /** @var \Drupal\image\Entity\ImageStyle|false $image_style */ + $image_style = FALSE; + if (!empty($image_style_setting)) { + $image_style = $this->imageStyleStorage->load($image_style_setting); + } + + 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); + + // 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(); + + $elements[$delta] = [ + '#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..72d990e 100644 --- a/core/modules/image/src/Tests/ImageFieldDisplayTest.php +++ b/core/modules/image/src/Tests/ImageFieldDisplayTest.php @@ -202,6 +202,26 @@ 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']); } /** 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 3620501..1d5b60e 100644 --- a/core/modules/responsive_image/src/Plugin/Field/FieldFormatter/ResponsiveImageFormatter.php +++ b/core/modules/responsive_image/src/Plugin/Field/FieldFormatter/ResponsiveImageFormatter.php @@ -13,7 +13,9 @@ use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\Core\Session\AccountInterface; use Drupal\Core\Url; +use Drupal\Core\Utility\LinkGeneratorInterface; use Drupal\image\Plugin\Field\FieldFormatter\ImageFormatterBase; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -35,13 +37,6 @@ class ResponsiveImageFormatter extends ImageFormatterBase implements ContainerFa */ protected $responsiveImageStyleStorage; - /* - * The image style entity storage. - * - * @var \Drupal\Core\Entity\EntityStorageInterface - */ - protected $imageStyleStorage; - /** * Constructs a ResponsiveImageFormatter object. * @@ -59,16 +54,19 @@ class ResponsiveImageFormatter extends ImageFormatterBase implements ContainerFa * The view mode. * @param array $third_party_settings * Any third party settings. - * @param \Drupal\Core\Entity\EntityStorageInterface $responsive_image_style_storage - * The responsive image style storage. + * @param \Drupal\Core\Session\AccountInterface $current_user + * The current user. + * @param \Drupal\Core\Utility\LinkGeneratorInterface $link_generator + * The link generator service. * @param \Drupal\Core\Entity\EntityStorageInterface $image_style_storage * The image style storage. + * @param \Drupal\Core\Entity\EntityStorageInterface $responsive_image_style_storage + * The responsive image style storage. */ - public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, EntityStorageInterface $responsive_image_style_storage, EntityStorageInterface $image_style_storage) { - parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings); + public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, AccountInterface $current_user, LinkGeneratorInterface $link_generator, EntityStorageInterface $image_style_storage, EntityStorageInterface $responsive_image_style_storage) { + parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings, $current_user, $link_generator, $image_style_storage); $this->responsiveImageStyleStorage = $responsive_image_style_storage; - $this->imageStyleStorage = $image_style_storage; } /** @@ -83,8 +81,10 @@ public static function create(ContainerInterface $container, array $configuratio $configuration['label'], $configuration['view_mode'], $configuration['third_party_settings'], - $container->get('entity.manager')->getStorage('responsive_image_style'), - $container->get('entity.manager')->getStorage('image_style') + $container->get('current_user'), + $container->get('link_generator'), + $container->get('entity.manager')->getStorage('image_style'), + $container->get('entity.manager')->getStorage('responsive_image_style') ); } @@ -92,17 +92,17 @@ public static function create(ContainerInterface $container, array $configuratio * {@inheritdoc} */ public static function defaultSettings() { - return array( + return [ 'responsive_image_style' => '', 'image_link' => '', - ) + 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) { @@ -112,25 +112,25 @@ 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, - ); + ]; - $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; } @@ -139,16 +139,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')]; @@ -165,7 +165,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. @@ -187,7 +187,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()); @@ -210,16 +210,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; }