Chris@18: entityTypeManager = $entity_type_manager; Chris@18: $this->request = $request_stack->getCurrentRequest(); Chris@18: $this->viewsExecutableFactory = $views_executable_factory; Chris@18: $this->formBuilder = $form_builder; Chris@18: } Chris@18: Chris@18: /** Chris@18: * Get media library dialog options. Chris@18: * Chris@18: * @return array Chris@18: * The media library dialog options. Chris@18: */ Chris@18: public static function dialogOptions() { Chris@18: return [ Chris@18: 'dialogClass' => 'media-library-widget-modal', Chris@18: 'title' => t('Add or select media'), Chris@18: 'height' => '75%', Chris@18: 'width' => '75%', Chris@18: ]; Chris@18: } Chris@18: Chris@18: /** Chris@18: * Build the media library UI. Chris@18: * Chris@18: * @param \Drupal\media_library\MediaLibraryState $state Chris@18: * (optional) The current state of the media library, derived from the Chris@18: * current request. Chris@18: * Chris@18: * @return array Chris@18: * The render array for the media library. Chris@18: */ Chris@18: public function buildUi(MediaLibraryState $state = NULL) { Chris@18: if (!$state) { Chris@18: $state = MediaLibraryState::fromRequest($this->request); Chris@18: } Chris@18: // When navigating to a media type through the vertical tabs, we only want Chris@18: // to load the changed library content. This is not only more efficient, but Chris@18: // also provides a more accessible user experience for screen readers. Chris@18: if ($state->get('media_library_content') === '1') { Chris@18: return $this->buildLibraryContent($state); Chris@18: } Chris@18: else { Chris@18: return [ Chris@18: '#type' => 'html_tag', Chris@18: '#tag' => 'div', Chris@18: '#attributes' => [ Chris@18: 'id' => 'media-library-wrapper', Chris@18: 'class' => ['media-library-wrapper'], Chris@18: ], Chris@18: 'menu' => $this->buildMediaTypeMenu($state), Chris@18: 'content' => $this->buildLibraryContent($state), Chris@18: // Attach the JavaScript for the media library UI. The number of Chris@18: // available slots needs to be added to make sure users can't select Chris@18: // more items than allowed. Chris@18: '#attached' => [ Chris@18: 'library' => ['media_library/ui'], Chris@18: 'drupalSettings' => [ Chris@18: 'media_library' => [ Chris@18: 'selection_remaining' => $state->getAvailableSlots(), Chris@18: ], Chris@18: ], Chris@18: ], Chris@18: ]; Chris@18: } Chris@18: } Chris@18: Chris@18: /** Chris@18: * Build the media library content area. Chris@18: * Chris@18: * @param \Drupal\media_library\MediaLibraryState $state Chris@18: * The current state of the media library, derived from the current request. Chris@18: * Chris@18: * @return array Chris@18: * The render array for the media library. Chris@18: */ Chris@18: protected function buildLibraryContent(MediaLibraryState $state) { Chris@18: return [ Chris@18: '#type' => 'html_tag', Chris@18: '#tag' => 'div', Chris@18: '#attributes' => [ Chris@18: 'id' => 'media-library-content', Chris@18: 'class' => ['media-library-content'], Chris@18: 'tabindex' => -1, Chris@18: ], Chris@18: 'form' => $this->buildMediaTypeAddForm($state), Chris@18: 'view' => $this->buildMediaLibraryView($state), Chris@18: ]; Chris@18: } Chris@18: Chris@18: /** Chris@18: * Check access to the media library. Chris@18: * Chris@18: * @param \Drupal\Core\Session\AccountInterface $account Chris@18: * (optional) Run access checks for this account. Chris@18: * @param \Drupal\media_library\MediaLibraryState $state Chris@18: * (optional) The current state of the media library, derived from the Chris@18: * current request. Chris@18: * Chris@18: * @return \Drupal\Core\Access\AccessResult Chris@18: * The access result. Chris@18: */ Chris@18: public function checkAccess(AccountInterface $account = NULL, MediaLibraryState $state = NULL) { Chris@18: if (!$state) { Chris@18: try { Chris@18: MediaLibraryState::fromRequest($this->request); Chris@18: } Chris@18: catch (BadRequestHttpException $e) { Chris@18: return AccessResult::forbidden($e->getMessage()); Chris@18: } Chris@18: catch (\InvalidArgumentException $e) { Chris@18: return AccessResult::forbidden($e->getMessage()); Chris@18: } Chris@18: } Chris@18: // Deny access if the view or display are removed. Chris@18: $view = $this->entityTypeManager->getStorage('view')->load('media_library'); Chris@18: if (!$view) { Chris@18: return AccessResult::forbidden('The media library view does not exist.') Chris@18: ->setCacheMaxAge(0); Chris@18: } Chris@18: if (!$view->getDisplay('widget')) { Chris@18: return AccessResult::forbidden('The media library widget display does not exist.') Chris@18: ->addCacheableDependency($view); Chris@18: } Chris@18: return AccessResult::allowedIfHasPermission($account, 'view media') Chris@18: ->addCacheableDependency($view); Chris@18: } Chris@18: Chris@18: /** Chris@18: * Get the media type menu for the media library. Chris@18: * Chris@18: * @param \Drupal\media_library\MediaLibraryState $state Chris@18: * The current state of the media library, derived from the current request. Chris@18: * Chris@18: * @return array Chris@18: * The render array for the media type menu. Chris@18: */ Chris@18: protected function buildMediaTypeMenu(MediaLibraryState $state) { Chris@18: // Add the menu for each type if we have more than 1 media type enabled for Chris@18: // the field. Chris@18: $allowed_type_ids = $state->getAllowedTypeIds(); Chris@18: if (count($allowed_type_ids) <= 1) { Chris@18: return []; Chris@18: } Chris@18: Chris@18: // @todo: Add a class to the li element. Chris@18: // https://www.drupal.org/project/drupal/issues/3029227 Chris@18: $menu = [ Chris@18: '#theme' => 'links', Chris@18: '#links' => [], Chris@18: '#attributes' => [ Chris@18: 'class' => ['media-library-menu', 'js-media-library-menu'], Chris@18: ], Chris@18: ]; Chris@18: Chris@18: $allowed_types = $this->entityTypeManager->getStorage('media_type')->loadMultiple($allowed_type_ids); Chris@18: Chris@18: $selected_type_id = $state->getSelectedTypeId(); Chris@18: foreach ($allowed_types as $allowed_type_id => $allowed_type) { Chris@18: $link_state = MediaLibraryState::create($state->getOpenerId(), $state->getAllowedTypeIds(), $allowed_type_id, $state->getAvailableSlots()); Chris@18: // Add the 'media_library_content' parameter so the response will contain Chris@18: // only the updated content for the tab. Chris@18: // @see self::buildUi() Chris@18: $link_state->set('media_library_content', 1); Chris@18: Chris@18: $title = $allowed_type->label(); Chris@18: if ($allowed_type_id === $selected_type_id) { Chris@18: $title = [ Chris@18: '#markup' => $this->t('@title (active tab)', ['@title' => $title]), Chris@18: ]; Chris@18: } Chris@18: Chris@18: $menu['#links']['media-library-menu-' . $allowed_type_id] = [ Chris@18: 'title' => $title, Chris@18: 'url' => Url::fromRoute('media_library.ui', [], [ Chris@18: 'query' => $link_state->all(), Chris@18: ]), Chris@18: 'attributes' => [ Chris@18: 'class' => ['media-library-menu__link'], Chris@18: ], Chris@18: ]; Chris@18: } Chris@18: Chris@18: // Set the active menu item. Chris@18: $menu['#links']['media-library-menu-' . $selected_type_id]['attributes']['class'][] = 'active'; Chris@18: Chris@18: return $menu; Chris@18: } Chris@18: Chris@18: /** Chris@18: * Get the add form for the selected media type. Chris@18: * Chris@18: * @param \Drupal\media_library\MediaLibraryState $state Chris@18: * The current state of the media library, derived from the current request. Chris@18: * Chris@18: * @return array Chris@18: * The render array for the media type add form. Chris@18: */ Chris@18: protected function buildMediaTypeAddForm(MediaLibraryState $state) { Chris@18: $selected_type_id = $state->getSelectedTypeId(); Chris@18: Chris@18: if (!$this->entityTypeManager->getAccessControlHandler('media')->createAccess($selected_type_id)) { Chris@18: return []; Chris@18: } Chris@18: Chris@18: $selected_type = $this->entityTypeManager->getStorage('media_type')->load($selected_type_id); Chris@18: $plugin_definition = $selected_type->getSource()->getPluginDefinition(); Chris@18: Chris@18: if (empty($plugin_definition['forms']['media_library_add'])) { Chris@18: return []; Chris@18: } Chris@18: Chris@18: // After the form to add new media is submitted, we need to rebuild the Chris@18: // media library with a new instance of the media add form. The form API Chris@18: // allows us to do that by forcing empty user input. Chris@18: // @see \Drupal\Core\Form\FormBuilder::doBuildForm() Chris@18: $form_state = new FormState(); Chris@18: if ($state->get('_media_library_form_rebuild')) { Chris@18: $form_state->setUserInput([]); Chris@18: $state->remove('_media_library_form_rebuild'); Chris@18: } Chris@18: $form_state->set('media_library_state', $state); Chris@18: return $this->formBuilder->buildForm($plugin_definition['forms']['media_library_add'], $form_state); Chris@18: } Chris@18: Chris@18: /** Chris@18: * Get the media library view. Chris@18: * Chris@18: * @param \Drupal\media_library\MediaLibraryState $state Chris@18: * The current state of the media library, derived from the current request. Chris@18: * Chris@18: * @return array Chris@18: * The render array for the media library view. Chris@18: */ Chris@18: protected function buildMediaLibraryView(MediaLibraryState $state) { Chris@18: // @todo Make the view configurable in Chris@18: // https://www.drupal.org/project/drupal/issues/2971209 Chris@18: $view = $this->entityTypeManager->getStorage('view')->load('media_library'); Chris@18: $view_executable = $this->viewsExecutableFactory->get($view); Chris@18: $display_id = 'widget'; Chris@18: Chris@18: // Make sure the state parameters are set in the request so the view can Chris@18: // pass the parameters along in the pager, filters etc. Chris@18: $view_request = $view_executable->getRequest(); Chris@18: $view_request->query->add($state->all()); Chris@18: $view_executable->setRequest($view_request); Chris@18: Chris@18: $args = [$state->getSelectedTypeId()]; Chris@18: Chris@18: // Make sure the state parameters are set in the request so the view can Chris@18: // pass the parameters along in the pager, filters etc. Chris@18: $request = $view_executable->getRequest(); Chris@18: $request->query->add($state->all()); Chris@18: $view_executable->setRequest($request); Chris@18: Chris@18: $view_executable->setDisplay($display_id); Chris@18: $view_executable->preExecute($args); Chris@18: $view_executable->execute($display_id); Chris@18: Chris@18: return $view_executable->buildRenderable($display_id, $args, FALSE); Chris@18: } Chris@18: Chris@18: }