' . t('About') . ''; $output .= '

' . t('The Media library module overrides the /admin/content/media view to provide a rich visual interface for performing administrative operations on media. For more information, see the online documentation for the Media library module.', [':media' => 'https://www.drupal.org/docs/8/core/modules/media']) . '

'; return $output; } } /** * Implements hook_theme(). */ function media_library_theme() { return [ 'media__media_library' => [ 'base hook' => 'media', ], ]; } /** * Implements hook_preprocess_view(). * * Adds a link to add media above the view. */ function media_library_preprocess_views_view(&$variables) { $view = $variables['view']; if ($view->id() === 'media_library' && $view->current_display === 'widget') { $url = Url::fromRoute('media_library.upload'); if ($url->access()) { $url->setOption('query', \Drupal::request()->query->all()); $variables['header']['add_media'] = [ '#type' => 'link', '#title' => t('Add media'), '#url' => $url, '#attributes' => [ 'class' => ['button', 'button-action', 'button--primary', 'use-ajax'], 'data-dialog-type' => 'modal', 'data-dialog-options' => Json::encode([ 'dialogClass' => 'media-library-widget-modal', 'height' => '75%', 'width' => '75%', 'title' => t('Add media'), ]), ], ]; } } } /** * Implements hook_views_post_render(). */ function media_library_views_post_render(ViewExecutable $view, &$output, CachePluginBase $cache) { if ($view->id() === 'media_library') { $output['#attached']['library'][] = 'media_library/view'; if ($view->current_display === 'widget') { $query = array_intersect_key(\Drupal::request()->query->all(), array_flip([ 'media_library_widget_id', 'media_library_allowed_types', 'media_library_remaining', ])); // If the current query contains any parameters we use to contextually // filter the view, ensure they persist across AJAX rebuilds. // The ajax_path is shared for all AJAX views on the page, but our query // parameters are prefixed and should not interfere with any other views. // @todo Rework or remove this in https://www.drupal.org/node/2983451 if (!empty($query)) { $ajax_path = &$output['#attached']['drupalSettings']['views']['ajax_path']; $parsed_url = UrlHelper::parse($ajax_path); $query = array_merge($query, $parsed_url['query']); $ajax_path = $parsed_url['path'] . '?' . UrlHelper::buildQuery($query); if (isset($query['media_library_remaining'])) { $output['#attached']['drupalSettings']['media_library']['selection_remaining'] = (int) $query['media_library_remaining']; } } } } } /** * Implements hook_preprocess_media(). */ function media_library_preprocess_media(&$variables) { if ($variables['view_mode'] === 'media_library') { /** @var \Drupal\media\MediaInterface $media */ $media = $variables['media']; $variables['#cache']['contexts'][] = 'user.permissions'; $rel = $media->access('edit') ? 'edit-form' : 'canonical'; $variables['url'] = $media->toUrl($rel, [ 'language' => $media->language(), ]); $variables['preview_attributes'] = new Attribute(); $variables['preview_attributes']->addClass('media-library-item__preview', 'js-media-library-item-preview', 'js-click-to-select-trigger'); $variables['metadata_attributes'] = new Attribute(); $variables['metadata_attributes']->addClass('media-library-item__attributes'); $variables['status'] = $media->isPublished(); } } /** * Alter the bulk form to add a more accessible label. * * @param array $form * An associative array containing the structure of the form. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. * * @todo Remove in https://www.drupal.org/node/2983454 */ function media_library_form_views_form_media_library_page_alter(array &$form, FormStateInterface $form_state) { if (isset($form['media_bulk_form']) && isset($form['output'])) { /** @var \Drupal\views\ViewExecutable $view */ $view = $form['output'][0]['#view']; foreach (Element::getVisibleChildren($form['media_bulk_form']) as $key) { if (isset($view->result[$key])) { $media = $view->field['media_bulk_form']->getEntity($view->result[$key]); $form['media_bulk_form'][$key]['#title'] = t('Select @label', [ '@label' => $media->label(), ]); } } } } /** * Implements hook_form_alter(). */ function media_library_form_alter(array &$form, FormStateInterface $form_state, $form_id) { $form_object = $form_state->getFormObject(); if ($form_object instanceof ViewsForm && strpos($form_object->getBaseFormId(), 'views_form_media_library') === 0) { $form['#attributes']['class'][] = 'media-library-views-form'; if (isset($form['header'])) { $form['header']['#attributes']['class'][] = 'media-library-views-form__header'; $form['header']['media_bulk_form']['#attributes']['class'][] = 'media-library-views-form__bulk_form'; } } // Add after build to fix media library views exposed filter's submit button. if ($form_id === 'views_exposed_form' && $form['#id'] === 'views-exposed-form-media-library-widget') { $form['#after_build'][] = '_media_library_views_form_media_library_after_build'; } } /** * After build callback for views form media library. */ function _media_library_views_form_media_library_after_build(array $form, FormStateInterface $form_state) { // Remove .form-actions from media library views exposed filter actions // and replace with .media-library-view--form-actions. // // This prevents the views exposed filter's 'Apply filter' submit button from // being moved into the dialog's buttons. // @see \Drupal\Core\Render\Element\Actions::processActions // @see Drupal.behaviors.dialog.prepareDialogButtons if (($key = array_search('form-actions', $form['actions']['#attributes']['class'])) !== FALSE) { unset($form['actions']['#attributes']['class'][$key]); } $form['actions']['#attributes']['class'][] = 'media-library-view--form-actions'; return $form; } /** * Implements hook_views_query_alter(). * * Alters the widget view's query to only show media that can be selected, * based on what types are allowed in the field settings. * * @todo Remove in https://www.drupal.org/node/2983454 */ function media_library_views_query_alter(ViewExecutable $view, QueryPluginBase $query) { if ($query instanceof Sql && $view->id() === 'media_library' && $view->current_display === 'widget') { $types = _media_library_get_allowed_types(); if ($types) { $entity_type = \Drupal::entityTypeManager()->getDefinition('media'); $group = $query->setWhereGroup(); $query->addWhere($group, $entity_type->getDataTable() . '.' . $entity_type->getKey('bundle'), $types, 'in'); } } } /** * Implements hook_form_FORM_ID_alter(). * * Limits the types available in the exposed filter to avoid users trying to * filter by a type that is un-selectable. * * @see media_library_views_query_alter() * * @todo Remove in https://www.drupal.org/node/2983454 */ function media_library_form_views_exposed_form_alter(array &$form, FormStateInterface $form_state) { if (isset($form['#id']) && $form['#id'] === 'views-exposed-form-media-library-widget') { $types = _media_library_get_allowed_types(); if ($types && isset($form['type']['#options'])) { $keys = array_flip($types); // Ensure that the default value (by default "All") persists. if (isset($form['type']['#default_value'])) { $keys[$form['type']['#default_value']] = TRUE; } $form['type']['#options'] = array_intersect_key($form['type']['#options'], $keys); } } } /** * Implements hook_field_ui_preconfigured_options_alter(). */ function media_library_field_ui_preconfigured_options_alter(array &$options, $field_type) { // If the field is not an "entity_reference"-based field, bail out. $class = \Drupal::service('plugin.manager.field.field_type')->getPluginClass($field_type); if (!is_a($class, EntityReferenceItem::class, TRUE)) { return; } // Set the default field widget for media to be the Media library. if (!empty($options['media'])) { $options['media']['entity_form_display']['type'] = 'media_library_widget'; } } /** * Implements hook_local_tasks_alter(). * * Removes tasks for the Media library if the view display no longer exists. */ function media_library_local_tasks_alter(&$local_tasks) { /** @var \Symfony\Component\Routing\RouteCollection $route_collection */ $route_collection = \Drupal::service('router')->getRouteCollection(); foreach (['media_library.grid', 'media_library.table'] as $key) { if (isset($local_tasks[$key]) && !$route_collection->get($local_tasks[$key]['route_name'])) { unset($local_tasks[$key]); } } } /** * Determines what types are allowed based on the current request. * * @return array * An array of allowed types. */ function _media_library_get_allowed_types() { $types = \Drupal::request()->query->get('media_library_allowed_types'); if ($types && is_array($types)) { return array_filter($types, 'is_string'); } return []; }