diff --git a/core/modules/image/config/schema/image.schema.yml b/core/modules/image/config/schema/image.schema.yml index 323220b..de28bb2 100644 --- a/core/modules/image/config/schema/image.schema.yml +++ b/core/modules/image/config/schema/image.schema.yml @@ -139,6 +139,17 @@ field.formatter.settings.image: type: string label: 'Image style' +field.formatter.settings.image_url: + type: mapping + label: 'Image URL format settings' + mapping: + image_link: + type: string + label: 'Link image to' + 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/css/image.theme.css b/core/modules/image/css/image.theme.css new file mode 100644 index 0000000..3da51ef --- /dev/null +++ b/core/modules/image/css/image.theme.css @@ -0,0 +1,21 @@ + +/** + * Image upload widget. + */ +.image-preview { + float: left; /* LTR */ + padding: 0 10px 10px 0; /* LTR */ +} +[dir="rtl"] .image-preview { + float: right; + padding: 0 0 10px 10px; +} +.image-widget-data { + float: left; /* LTR */ +} +[dir="rtl"] .image-widget-data { + float: right; +} +.image-widget-data .text-field { + width: auto; +} diff --git a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php index aa24a95..7c86ca2 100644 --- a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php +++ b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php @@ -7,17 +7,10 @@ namespace Drupal\image\Plugin\Field\FieldFormatter; -use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Field\FieldItemListInterface; -use Drupal\Core\Field\FieldDefinitionInterface; +use Drupal\Core\Form\FormStateInterface; 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,64 +24,7 @@ * } * ) */ -class ImageFormatter extends ImageFormatterBase 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') - ); - } +class ImageFormatter extends ImageFormatterBase { /** * {@inheritdoc} @@ -171,7 +107,8 @@ public function settingsSummary() { */ public function viewElements(FieldItemListInterface $items, $langcode) { $elements = array(); - $files = $this->getEntitiesToView($items, $langcode); + /** @var \Drupal\file\Entity\File[] $files */ + $files = $this->getEntitiesToView($items); // Early opt-out if the field is empty. if (empty($files)) { diff --git a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatterBase.php b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatterBase.php index 6f79497..d11ff4d 100644 --- a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatterBase.php +++ b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatterBase.php @@ -7,15 +7,76 @@ namespace Drupal\image\Plugin\Field\FieldFormatter; +use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Field\EntityReferenceFieldItemListInterface; -use Drupal\Core\Language\LanguageInterface; +use Drupal\Core\Field\FieldDefinitionInterface; +use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\Core\Session\AccountInterface; 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} @@ -51,4 +112,19 @@ protected function getEntitiesToView(EntityReferenceFieldItemListInterface $item return parent::getEntitiesToView($items, $langcode); } + /** + * {@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 index 9d4fc11..fdf419d 100644 --- a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageUrlFormatter.php +++ b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageUrlFormatter.php @@ -7,6 +7,7 @@ namespace Drupal\image\Plugin\Field\FieldFormatter; use Drupal\Core\Cache\Cache; +use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Link; use Drupal\Core\Url; @@ -27,7 +28,7 @@ class ImageUrlFormatter extends ImageFormatterBase { /** * {@inheritdoc} */ - public function viewElements(FieldItemListInterface $items) { + public function viewElements(FieldItemListInterface $items, $langcode) { $elements = []; /** @var \Drupal\file\Entity\File[] $images */ $images = $this->getEntitiesToView($items); @@ -61,23 +62,20 @@ public function viewElements(FieldItemListInterface $items) { // 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 cacheable metadata from the image and image style. + $cacheable_metadata = CacheableMetadata::createFromObject($image); + if ($image_style) { + $cacheable_metadata = $cacheable_metadata->merge(CacheableMetadata::createFromObject($image_style)); + } // 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, - ], - ]; + if ($link_url instanceof Url) { + $elements[$delta] = Link::fromTextAndUrl($url, $link_url)->toRenderable(); + } + else { + $elements[$delta] = ['#markup' => $url]; + } + $cacheable_metadata->applyTo($elements[$delta]); } return $elements; diff --git a/core/modules/image/src/Tests/ImageFieldDisplayTest.php b/core/modules/image/src/Tests/ImageFieldDisplayTest.php index c4cf485..b5caad8 100644 --- a/core/modules/image/src/Tests/ImageFieldDisplayTest.php +++ b/core/modules/image/src/Tests/ImageFieldDisplayTest.php @@ -93,6 +93,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 +203,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 d1290cb..08648e7 100644 --- a/core/modules/responsive_image/src/Plugin/Field/FieldFormatter/ResponsiveImageFormatter.php +++ b/core/modules/responsive_image/src/Plugin/Field/FieldFormatter/ResponsiveImageFormatter.php @@ -85,7 +85,7 @@ class ResponsiveImageFormatter extends ImageFormatterBase implements ContainerFa * The current user. */ 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, LinkGeneratorInterface $link_generator, AccountInterface $current_user) { - parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings); + parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings, $current_user, $image_style_storage); $this->responsiveImageStyleStorage = $responsive_image_style_storage; $this->imageStyleStorage = $image_style_storage; @@ -116,10 +116,14 @@ public static function create(ContainerInterface $container, array $configuratio * {@inheritdoc} */ public static function defaultSettings() { - return array( + $default_settings = parent::defaultSettings(); + + // Use responsive_image_style instead of image_style; + unset($default_settings['image_style']); + + return [ 'responsive_image_style' => '', - 'image_link' => '', - ) + parent::defaultSettings(); + ] + $default_settings ; } /**