210 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
		
		
			
		
	
	
			210 lines
		
	
	
		
			6.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| 
								 | 
							
								<?php
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @file
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								use Drupal\Core\Form\FormStateInterface;
							 | 
						||
| 
								 | 
							
								use Drupal\Core\Hook\Attribute\ProceduralHookScanStop;
							 | 
						||
| 
								 | 
							
								use Drupal\Core\Render\Element;
							 | 
						||
| 
								 | 
							
								use Drupal\Core\Render\Element\RenderElementBase;
							 | 
						||
| 
								 | 
							
								use Drupal\Core\Template\Attribute;
							 | 
						||
| 
								 | 
							
								use Drupal\Core\Url;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * 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): void {
							 | 
						||
| 
								 | 
							
								  $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): void {
							 | 
						||
| 
								 | 
							
								  // 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.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								#[ProceduralHookScanStop]
							 | 
						||
| 
								 | 
							
								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): void {
							 | 
						||
| 
								 | 
							
								  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><drupal-media></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><drupal-media></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);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 |