media.module

Same filename in other branches
  1. 9 core/modules/media/media.module
  2. 8.9.x core/modules/media/media.module
  3. 10 core/modules/media/media.module

File

core/modules/media/media.module

View source
<?php


/**
 * @file
 */
use Drupal\Component\Plugin\DerivativeInspectionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Render\Element\RenderElementBase;
use Drupal\Core\Template\Attribute;
use Drupal\Core\Url;
use Drupal\media\Plugin\media\Source\OEmbedInterface;

/**
 * Implements hook_theme_suggestions_HOOK().
 */
function media_theme_suggestions_media(array $variables) {
    $suggestions = [];
    
    /** @var \Drupal\media\MediaInterface $media */
    $media = $variables['elements']['#media'];
    $sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_');
    $suggestions[] = 'media__' . $sanitized_view_mode;
    $suggestions[] = 'media__' . $media->bundle();
    $suggestions[] = 'media__' . $media->bundle() . '__' . $sanitized_view_mode;
    // Add suggestions based on the source plugin ID.
    $source = $media->getSource();
    if ($source instanceof DerivativeInspectionInterface) {
        $source_id = $source->getBaseId();
        $derivative_id = $source->getDerivativeId();
        if ($derivative_id) {
            $source_id .= '__derivative_' . $derivative_id;
        }
    }
    else {
        $source_id = $source->getPluginId();
    }
    $suggestions[] = "media__source_{$source_id}";
    // If the source plugin uses oEmbed, add a suggestion based on the provider
    // name, if available.
    if ($source instanceof OEmbedInterface) {
        $provider_id = $source->getMetadata($media, 'provider_name');
        if ($provider_id) {
            $provider_id = \Drupal::transliteration()->transliterate($provider_id);
            $provider_id = preg_replace('/[^a-z0-9_]+/', '_', mb_strtolower($provider_id));
            $suggestions[] = end($suggestions) . "__provider_{$provider_id}";
        }
    }
    return $suggestions;
}

/**
 * Prepares variables for media templates.
 *
 * Default template: media.html.twig.
 *
 * @param array $variables
 *   An associative array containing:
 *   - elements: An array of elements to display in view mode.
 *   - media: The media item.
 *   - name: The label for the media item.
 *   - view_mode: View mode; e.g., 'full', 'teaser', etc.
 */
function template_preprocess_media(array &$variables) {
    $variables['media'] = $variables['elements']['#media'];
    $variables['view_mode'] = $variables['elements']['#view_mode'];
    $variables['name'] = $variables['media']->label();
    // Helpful $content variable for templates.
    foreach (Element::children($variables['elements']) as $key) {
        $variables['content'][$key] = $variables['elements'][$key];
    }
}

/**
 * Implements hook_preprocess_HOOK() for media reference widgets.
 */
function media_preprocess_media_reference_help(&$variables) {
    // Most of these attribute checks are copied from
    // template_preprocess_fieldset(). Our template extends
    // field-multiple-value-form.html.twig to provide our help text, but also
    // groups the information within a semantic fieldset with a legend. So, we
    // incorporate parity for both.
    $element = $variables['element'];
    Element::setAttributes($element, [
        'id',
    ]);
    RenderElementBase::setAttributes($element);
    $variables['attributes'] = $element['#attributes'] ?? [];
    $variables['legend_attributes'] = new Attribute();
    $variables['header_attributes'] = new Attribute();
    $variables['description']['attributes'] = new Attribute();
    $variables['legend_span_attributes'] = new Attribute();
    if (!empty($element['#media_help'])) {
        foreach ($element['#media_help'] as $key => $text) {
            $variables[substr($key, 1)] = $text;
        }
    }
}

/**
 * Returns the appropriate URL to add media for the current user.
 *
 * @todo Remove in https://www.drupal.org/project/drupal/issues/2938116
 *
 * @param string[] $allowed_bundles
 *   An array of bundles that should be checked for create access.
 *
 * @return bool|\Drupal\Core\Url
 *   The URL to add media, or FALSE if the user cannot create any media.
 *
 * @internal
 *   This function is internal and may be removed in a minor release.
 */
function _media_get_add_url($allowed_bundles) {
    $access_handler = \Drupal::entityTypeManager()->getAccessControlHandler('media');
    $create_bundles = array_filter($allowed_bundles, [
        $access_handler,
        'createAccess',
    ]);
    // Add a section about how to create media if the user has access to do so.
    if (count($create_bundles) === 1) {
        return Url::fromRoute('entity.media.add_form', [
            'media_type' => reset($create_bundles),
        ])->toString();
    }
    elseif (count($create_bundles) > 1) {
        return Url::fromRoute('entity.media.add_page')->toString();
    }
    return FALSE;
}

/**
 * Validate callback to ensure filter order and allowed_html are compatible.
 */
function media_filter_format_edit_form_validate($form, FormStateInterface $form_state) {
    if ($form_state->getTriggeringElement()['#name'] !== 'op') {
        return;
    }
    $allowed_html_path = [
        'filters',
        'filter_html',
        'settings',
        'allowed_html',
    ];
    $filter_html_settings_path = [
        'filters',
        'filter_html',
        'settings',
    ];
    $filter_html_enabled = $form_state->getValue([
        'filters',
        'filter_html',
        'status',
    ]);
    $media_embed_enabled = $form_state->getValue([
        'filters',
        'media_embed',
        'status',
    ]);
    if (!$media_embed_enabled) {
        return;
    }
    $get_filter_label = function ($filter_plugin_id) use ($form) {
        return (string) $form['filters']['order'][$filter_plugin_id]['filter']['#markup'];
    };
    if ($filter_html_enabled && $form_state->getValue($allowed_html_path)) {
        
        /** @var \Drupal\filter\Entity\FilterFormat $filter_format */
        $filter_format = $form_state->getFormObject()
            ->getEntity();
        $filter_html = clone $filter_format->filters()
            ->get('filter_html');
        $filter_html->setConfiguration([
            'settings' => $form_state->getValue($filter_html_settings_path),
        ]);
        $restrictions = $filter_html->getHTMLRestrictions();
        $allowed = $restrictions['allowed'];
        // Require `<drupal-media>` HTML tag if filter_html is enabled.
        if (!isset($allowed['drupal-media'])) {
            $form_state->setError($form['filters']['settings']['filter_html']['allowed_html'], t('The %media-embed-filter-label filter requires <code>&lt;drupal-media&gt;</code> among the allowed HTML tags.', [
                '%media-embed-filter-label' => $get_filter_label('media_embed'),
            ]));
        }
        else {
            $required_attributes = [
                'data-entity-type',
                'data-entity-uuid',
            ];
            // If there are no attributes, the allowed item is set to FALSE,
            // otherwise, it is set to an array.
            if ($allowed['drupal-media'] === FALSE) {
                $missing_attributes = $required_attributes;
            }
            else {
                $missing_attributes = array_diff($required_attributes, array_keys($allowed['drupal-media']));
            }
            if ($missing_attributes) {
                $form_state->setError($form['filters']['settings']['filter_html']['allowed_html'], t('The <code>&lt;drupal-media&gt;</code> tag in the allowed HTML tags is missing the following attributes: <code>%list</code>.', [
                    '%list' => implode(', ', $missing_attributes),
                ]));
            }
        }
    }
    $filters = $form_state->getValue('filters');
    // The "media_embed" filter must run after "filter_align", "filter_caption",
    // and "filter_html_image_secure".
    $precedents = [
        'filter_align',
        'filter_caption',
        'filter_html_image_secure',
    ];
    $error_filters = [];
    foreach ($precedents as $filter_name) {
        // A filter that should run before media embed filter.
        $precedent = $filters[$filter_name];
        if (empty($precedent['status']) || !isset($precedent['weight'])) {
            continue;
        }
        if ($precedent['weight'] >= $filters['media_embed']['weight']) {
            $error_filters[$filter_name] = $get_filter_label($filter_name);
        }
    }
    if (!empty($error_filters)) {
        $error_message = \Drupal::translation()->formatPlural(count($error_filters), 'The %media-embed-filter-label filter needs to be placed after the %filter filter.', 'The %media-embed-filter-label filter needs to be placed after the following filters: %filters.', [
            '%media-embed-filter-label' => $get_filter_label('media_embed'),
            '%filter' => reset($error_filters),
            '%filters' => implode(', ', $error_filters),
        ]);
        $form_state->setErrorByName('filters', $error_message);
    }
}

Functions

Title Deprecated Summary
media_filter_format_edit_form_validate Validate callback to ensure filter order and allowed_html are compatible.
media_preprocess_media_reference_help Implements hook_preprocess_HOOK() for media reference widgets.
media_theme_suggestions_media Implements hook_theme_suggestions_HOOK().
template_preprocess_media Prepares variables for media templates.
_media_get_add_url Returns the appropriate URL to add media for the current user.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.