diff --git a/core/modules/media/src/Plugin/Field/FieldFormatter/MediaFileFormatterBase.php b/core/modules/media/src/Plugin/Field/FieldFormatter/MediaFileFormatterBase.php new file mode 100644 index 0000000..15ccac2 --- /dev/null +++ b/core/modules/media/src/Plugin/Field/FieldFormatter/MediaFileFormatterBase.php @@ -0,0 +1,48 @@ +getSetting('target_type') === 'media') { + /** @var \Drupal\media\Entity\MediaType[] $allowed_types */ + $allowed_types = MediaType::loadMultiple($field_definition->getSetting('handler_settings')['target_bundles']); + + $media_sources = []; + $definitions = \Drupal::service('plugin.manager.field.formatter')->getDefinitions(); + foreach ($definitions as $definition) { + if ($definition['class'] === static::class) { + $media_sources = $definition['media_sources']; + } + } + + /** @var \Drupal\media\Entity\MediaType $type */ + foreach ($allowed_types as $type) { + if (in_array($type->getSource()->getPluginId(), $media_sources)) { + return TRUE; + } + } + } + return FALSE; + } + + /** + * {@inheritdoc} + */ + protected function needsEntityLoad(EntityReferenceItem $item) { + return TRUE; + } + +} diff --git a/core/modules/media/src/Plugin/Field/FieldFormatter/MediaGenericFileFormatter.php b/core/modules/media/src/Plugin/Field/FieldFormatter/MediaGenericFileFormatter.php new file mode 100644 index 0000000..b2f10b5 --- /dev/null +++ b/core/modules/media/src/Plugin/Field/FieldFormatter/MediaGenericFileFormatter.php @@ -0,0 +1,109 @@ +renderer = $renderer; + } + + /** + * {@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('renderer') + ); + } + + /** + * {@inheritdoc} + */ + public function viewElements(FieldItemListInterface $items, $langcode) { + $elements = []; + + /** @var \Drupal\Core\Field\EntityReferenceFieldItemListInterface $items */ + /** @var \Drupal\media\MediaInterface $entity */ + foreach ($this->getEntitiesToView($items, $langcode) as $delta => $entity) { + $source_field_name = $entity->getSource()->getConfiguration()['source_field']; + /** @var \Drupal\file\FileInterface $file */ + $file = $entity->get($source_field_name)->entity; + $item = $file->_referringItem; + + $elements[$delta] = [ + '#theme' => 'file_link', + '#file' => $file, + '#description' => $file->description, + ]; + $this->renderer->addCacheableDependency($elements[$delta], $file); + + // Pass field item attributes to the theme function. + if (isset($item->_attributes)) { + $elements[$delta] += ['#attributes' => []]; + $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); + } + } + + return $elements; + } + +} diff --git a/core/modules/media/src/Plugin/Field/FieldFormatter/MediaImageFormatter.php b/core/modules/media/src/Plugin/Field/FieldFormatter/MediaImageFormatter.php new file mode 100644 index 0000000..910ec77 --- /dev/null +++ b/core/modules/media/src/Plugin/Field/FieldFormatter/MediaImageFormatter.php @@ -0,0 +1,283 @@ +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} + */ + public function viewElements(FieldItemListInterface $items, $langcode) { + $elements = []; + + /** @var \Drupal\Core\Field\EntityReferenceFieldItemListInterface $items */ + $entities = $this->getEntitiesToView($items, $langcode); + + // Early opt-out if the field is empty. + if (empty($entities)) { + return $elements; + } + + $url = NULL; + $image_link_setting = $this->getSetting('image_link'); + // Check if the formatter involves a link. + if ($image_link_setting == 'content') { + $entity = $items->getEntity(); + if (!$entity->isNew()) { + $url = $entity->urlInfo(); + } + } + elseif ($image_link_setting == 'file') { + $link_file = TRUE; + } + + $image_style_setting = $this->getSetting('image_style'); + + // Collect cache tags to be added for each item in the field. + $base_cache_tags = []; + if (!empty($image_style_setting)) { + $image_style = $this->imageStyleStorage->load($image_style_setting); + $base_cache_tags = $image_style->getCacheTags(); + } + + /** @var \Drupal\media\MediaInterface $entity */ + foreach ($entities as $delta => $entity) { + $source_field_name = $entity->getSource()->getConfiguration()['source_field']; + /** @var \Drupal\file\FileInterface $file */ + $source_field = $entity->get($source_field_name); + $file = $source_field->entity; + $cache_contexts = []; + if (isset($link_file)) { + $image_uri = $file->getFileUri(); + // @todo Wrap in file_url_transform_relative(). This is currently + // impossible. As a work-around, we currently add the 'url.site' cache + // context to ensure different file URLs are generated for different + // sites in a multisite setup, including HTTP and HTTPS versions of the + // same site. Fix in https://www.drupal.org/node/2646744. + $url = Url::fromUri(file_create_url($image_uri)); + $cache_contexts[] = 'url.site'; + } + $cache_tags = Cache::mergeTags($base_cache_tags, $file->getCacheTags()); + + // 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] = [ + '#theme' => 'image_formatter', + '#item' => $source_field, + '#item_attributes' => $item_attributes, + '#image_style' => $image_style_setting, + '#url' => $url, + '#cache' => [ + 'tags' => $cache_tags, + 'contexts' => $cache_contexts, + ], + ]; + } + + return $elements; + } + + /** + * {@inheritdoc} + */ + public function calculateDependencies() { + $dependencies = parent::calculateDependencies(); + $style_id = $this->getSetting('image_style'); + /** @var \Drupal\image\ImageStyleInterface $style */ + if ($style_id && $style = ImageStyle::load($style_id)) { + // If this formatter uses a valid image style to display the image, add + // the image style configuration entity as dependency of this formatter. + $dependencies[$style->getConfigDependencyKey()][] = $style->getConfigDependencyName(); + } + return $dependencies; + } + + /** + * {@inheritdoc} + */ + public function onDependencyRemoval(array $dependencies) { + $changed = parent::onDependencyRemoval($dependencies); + $style_id = $this->getSetting('image_style'); + /** @var \Drupal\image\ImageStyleInterface $style */ + if ($style_id && $style = ImageStyle::load($style_id)) { + if (!empty($dependencies[$style->getConfigDependencyKey()][$style->getConfigDependencyName()])) { + $replacement_id = $this->imageStyleStorage->getReplacementId($style_id); + // If a valid replacement has been provided in the storage, replace the + // image style with the replacement and signal that the formatter plugin + // settings were updated. + if ($replacement_id && ImageStyle::load($replacement_id)) { + $this->setSetting('image_style', $replacement_id); + $changed = TRUE; + } + } + } + return $changed; + } + +} diff --git a/core/modules/media/src/Plugin/Field/FieldFormatter/MediaImageUrlFormatter.php b/core/modules/media/src/Plugin/Field/FieldFormatter/MediaImageUrlFormatter.php new file mode 100644 index 0000000..5f66483 --- /dev/null +++ b/core/modules/media/src/Plugin/Field/FieldFormatter/MediaImageUrlFormatter.php @@ -0,0 +1,90 @@ + '', + ]; + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state) { + $element = parent::settingsForm($form, $form_state); + + unset($element['image_link']);; + + return $element; + } + + /** + * {@inheritdoc} + */ + public function settingsSummary() { + $summary = parent::settingsSummary(); + return [$summary[0]]; + } + + /** + * {@inheritdoc} + */ + public function viewElements(FieldItemListInterface $items, $langcode) { + $elements = []; + + /** @var \Drupal\Core\Field\EntityReferenceFieldItemListInterface $items */ + $entities = $this->getEntitiesToView($items, $langcode); + + // Early opt-out if the field is empty. + if (empty($entities)) { + return $elements; + } + + /** @var \Drupal\image\ImageStyleInterface $image_style */ + $image_style = $this->imageStyleStorage->load($this->getSetting('image_style')); + /** @var \Drupal\media\MediaInterface $entity */ + foreach ($entities as $delta => $entity) { + $source_field_name = $entity->getSource()->getConfiguration()['source_field']; + /** @var \Drupal\file\FileInterface $file */ + $file = $entity->get($source_field_name)->entity; + $image_uri = $file->getFileUri(); + $url = $image_style ? $image_style->buildUrl($image_uri) : file_create_url($image_uri); + $url = file_url_transform_relative($url); + + // Add cacheability metadata from the image and image style. + $cacheability = CacheableMetadata::createFromObject($file); + if ($image_style) { + $cacheability->addCacheableDependency(CacheableMetadata::createFromObject($image_style)); + } + + $elements[$delta] = ['#markup' => $url]; + $cacheability->applyTo($elements[$delta]); + } + return $elements; + } + +} diff --git a/core/modules/media/src/Plugin/Field/FieldFormatter/MediaTableFormatter.php b/core/modules/media/src/Plugin/Field/FieldFormatter/MediaTableFormatter.php new file mode 100644 index 0000000..cf15d96 --- /dev/null +++ b/core/modules/media/src/Plugin/Field/FieldFormatter/MediaTableFormatter.php @@ -0,0 +1,65 @@ +getEntitiesToView($items, $langcode)) { + $header = [t('Attachment'), t('Size')]; + $rows = []; + /** @var \Drupal\media\MediaInterface $entity */ + foreach ($entities as $delta => $entity) { + $source_field_name = $entity->getSource()->getConfiguration()['source_field']; + /** @var \Drupal\file\FileInterface $file */ + $file = $entity->get($source_field_name)->entity; + $rows[] = [ + [ + 'data' => [ + '#theme' => 'file_link', + '#file' => $file, + '#cache' => [ + 'tags' => $file->getCacheTags(), + ], + ], + ], + ['data' => format_size($file->getSize())], + ]; + } + + $elements[0] = []; + if (!empty($rows)) { + $elements[0] = [ + '#theme' => 'table__file_formatter_table', + '#header' => $header, + '#rows' => $rows, + ]; + } + } + + return $elements; + } + +} diff --git a/core/modules/media/src/Plugin/Field/FieldFormatter/MediaUrlPlainFormatter.php b/core/modules/media/src/Plugin/Field/FieldFormatter/MediaUrlPlainFormatter.php new file mode 100644 index 0000000..5d1ef2a --- /dev/null +++ b/core/modules/media/src/Plugin/Field/FieldFormatter/MediaUrlPlainFormatter.php @@ -0,0 +1,46 @@ +getEntitiesToView($items, $langcode) as $delta => $entity) { + $source_field_name = $entity->getSource()->getConfiguration()['source_field']; + /** @var \Drupal\file\FileInterface $file */ + $file = $entity->get($source_field_name)->entity; + $elements[] = [ + '#markup' => file_url_transform_relative(file_create_url($file->getFileUri())), + '#cache' => [ + 'tags' => $file->getCacheTags(), + ], + ]; + } + + return $elements; + } + +}