Chris@0: loadInclude('views_ui', 'inc', 'admin'); Chris@0: $form_state->set('view', $this->entity); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function buildForm(array $form, FormStateInterface $form_state, $display_id = NULL) { Chris@0: if (isset($display_id) && $form_state->has('display_id') && ($display_id !== $form_state->get('display_id'))) { Chris@0: throw new \InvalidArgumentException('Mismatch between $form_state->get(\'display_id\') and $display_id.'); Chris@0: } Chris@0: $this->displayID = $form_state->has('display_id') ? $form_state->get('display_id') : $display_id; Chris@0: return parent::buildForm($form, $form_state); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: protected function prepareEntity() { Chris@0: // Determine the displays available for editing. Chris@0: if ($tabs = $this->getDisplayTabs($this->entity)) { Chris@0: if (empty($this->displayID)) { Chris@0: // If a display isn't specified, use the first one after sorting by Chris@0: // #weight. Chris@0: uasort($tabs, 'Drupal\Component\Utility\SortArray::sortByWeightProperty'); Chris@0: foreach ($tabs as $id => $tab) { Chris@0: if (!isset($tab['#access']) || $tab['#access']) { Chris@0: $this->displayID = $id; Chris@0: break; Chris@0: } Chris@0: } Chris@0: } Chris@0: // If a display is specified, but we don't have access to it, return Chris@0: // an access denied page. Chris@0: if ($this->displayID && !isset($tabs[$this->displayID])) { Chris@0: throw new NotFoundHttpException(); Chris@0: } Chris@0: elseif ($this->displayID && (isset($tabs[$this->displayID]['#access']) && !$tabs[$this->displayID]['#access'])) { Chris@0: throw new AccessDeniedHttpException(); Chris@0: } Chris@0: Chris@0: } Chris@0: elseif ($this->displayID) { Chris@0: throw new NotFoundHttpException(); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Adds tabs for navigating across Displays when editing a View. Chris@0: * Chris@0: * This function can be called from hook_menu_local_tasks_alter() to implement Chris@0: * these tabs as secondary local tasks, or it can be called from elsewhere if Chris@0: * having them as secondary local tasks isn't desired. The caller is responsible Chris@0: * for setting the active tab's #active property to TRUE. Chris@0: * Chris@0: * @param $display_id Chris@0: * The display_id which is edited on the current request. Chris@0: */ Chris@0: public function getDisplayTabs(ViewUI $view) { Chris@0: $executable = $view->getExecutable(); Chris@0: $executable->initDisplay(); Chris@0: $display_id = $this->displayID; Chris@0: $tabs = []; Chris@0: Chris@0: // Create a tab for each display. Chris@0: foreach ($view->get('display') as $id => $display) { Chris@0: // Get an instance of the display plugin, to make sure it will work in the Chris@0: // UI. Chris@0: $display_plugin = $executable->displayHandlers->get($id); Chris@0: if (empty($display_plugin)) { Chris@0: continue; Chris@0: } Chris@0: Chris@0: $tabs[$id] = [ Chris@0: '#theme' => 'menu_local_task', Chris@0: '#weight' => $display['position'], Chris@0: '#link' => [ Chris@0: 'title' => $this->getDisplayLabel($view, $id), Chris@0: 'localized_options' => [], Chris@18: 'url' => $view->toUrl('edit-display-form')->setRouteParameter('display_id', $id), Chris@0: ], Chris@0: ]; Chris@0: if (!empty($display['deleted'])) { Chris@0: $tabs[$id]['#link']['localized_options']['attributes']['class'][] = 'views-display-deleted-link'; Chris@0: } Chris@0: if (isset($display['display_options']['enabled']) && !$display['display_options']['enabled']) { Chris@0: $tabs[$id]['#link']['localized_options']['attributes']['class'][] = 'views-display-disabled-link'; Chris@0: } Chris@0: } Chris@0: Chris@0: // If the default display isn't supposed to be shown, don't display its tab, unless it's the only display. Chris@0: if ((!$this->isDefaultDisplayShown($view) && $display_id != 'default') && count($tabs) > 1) { Chris@0: $tabs['default']['#access'] = FALSE; Chris@0: } Chris@0: Chris@0: // Mark the display tab as red to show validation errors. Chris@0: $errors = $executable->validate(); Chris@0: foreach ($view->get('display') as $id => $display) { Chris@0: if (!empty($errors[$id])) { Chris@0: // Always show the tab. Chris@0: $tabs[$id]['#access'] = TRUE; Chris@0: // Add a class to mark the error and a title to make a hover tip. Chris@0: $tabs[$id]['#link']['localized_options']['attributes']['class'][] = 'error'; Chris@0: $tabs[$id]['#link']['localized_options']['attributes']['title'] = $this->t('This display has one or more validation errors.'); Chris@0: } Chris@0: } Chris@0: Chris@0: return $tabs; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Controls whether or not the default display should have its own tab on edit. Chris@0: */ Chris@0: public function isDefaultDisplayShown(ViewUI $view) { Chris@0: // Always show the default display for advanced users who prefer that mode. Chris@0: $advanced_mode = \Drupal::config('views.settings')->get('ui.show.master_display'); Chris@0: // For other users, show the default display only if there are no others, and Chris@0: // hide it if there's at least one "real" display. Chris@0: $additional_displays = (count($view->getExecutable()->displayHandlers) == 1); Chris@0: Chris@0: return $advanced_mode || $additional_displays; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Placeholder function for overriding $display['display_title']. Chris@0: * Chris@0: * @todo Remove this function once editing the display title is possible. Chris@0: */ Chris@0: public function getDisplayLabel(ViewUI $view, $display_id, $check_changed = TRUE) { Chris@0: $display = $view->get('display'); Chris@0: $title = $display_id == 'default' ? $this->t('Master') : $display[$display_id]['display_title']; Chris@0: $title = views_ui_truncate($title, 25); Chris@0: Chris@0: if ($check_changed && !empty($view->changed_display[$display_id])) { Chris@0: $changed = '*'; Chris@0: $title = $title . $changed; Chris@0: } Chris@0: Chris@0: return $title; Chris@0: } Chris@0: Chris@0: }