diff --git a/core/modules/views/views_ui/admin.inc b/core/modules/views/views_ui/admin.inc index cbc949b..9f57a51 100644 --- a/core/modules/views/views_ui/admin.inc +++ b/core/modules/views/views_ui/admin.inc @@ -8,6 +8,7 @@ use Drupal\Component\Utility\NestedArray; use Drupal\Core\Database\Database; use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Drupal\views_ui\ViewUI; use Drupal\views_ui\ViewFormControllerBase; use Drupal\views\Analyzer; @@ -529,7 +530,7 @@ function views_ui_ajax_form($js, $key, ViewUI $view, $display_id = '') { $form = views_ui_ajax_forms($key); if (empty($form)) { - return MENU_NOT_FOUND; + throw new NotFoundHttpException(); } views_include('ajax'); diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/Routing/ViewsUIController.php b/core/modules/views/views_ui/lib/Drupal/views_ui/Routing/ViewsUIController.php index 86f1a1a..295a4e0 100644 --- a/core/modules/views/views_ui/lib/Drupal/views_ui/Routing/ViewsUIController.php +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/Routing/ViewsUIController.php @@ -9,7 +9,9 @@ use Drupal\views\ViewExecutable; use Drupal\views\ViewStorageInterface; +use Drupal\views_ui\ViewUI; use Drupal\views\ViewsDataCache; +use Drupal\user\TempStoreFactory; use Drupal\Core\Entity\EntityManager; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\JsonResponse; @@ -44,6 +46,13 @@ class ViewsUIController { protected $request; /** + * Stores the user tempstore. + * + * @var \Drupal\user\TempStore + */ + protected $tempStore; + + /** * Constructs a new \Drupal\views_ui\Routing\ViewsUIController object. * * @param \Drupal\Core\Entity\EntityManager $entity_manager @@ -53,10 +62,11 @@ class ViewsUIController { * @param \Symfony\Component\HttpFoundation\Request $request * The request object. */ - public function __construct(EntityManager $entity_manager, ViewsDataCache $views_data, Request $request) { + public function __construct(EntityManager $entity_manager, ViewsDataCache $views_data, Request $request, TempStoreFactory $temp_store) { $this->entityManager = $entity_manager; $this->viewsData = $views_data; $this->request = $request; + $this->tempStore = $temp_store->get('views'); } /** @@ -70,9 +80,6 @@ public function listing() { * Returns the form to add a new view. */ public function add() { - // @todo Remove the need for this. - module_load_include('inc', 'views_ui', 'admin'); - drupal_set_title(t('Add new view')); $entity = $this->entityManager->getStorageController('view')->create(array()); @@ -212,6 +219,9 @@ public function ajaxOperation($view, $op) { * * @param string|\Drupal\views\ViewStorageInterface $view * The view being cloned. + * + * @return array + * The Views clone form. */ public function cloneForm($view) { // @todo Remove this when http://drupal.org/node/1798214 is in. @@ -227,6 +237,9 @@ public function cloneForm($view) { * * @param string|\Drupal\views\ViewStorageInterface $view * The view being deleted. + * + * @return array + * The Views delete form. */ public function deleteForm($view) { // @todo Remove this when http://drupal.org/node/1798214 is in. @@ -265,15 +278,25 @@ public function autocompleteTag() { /** * Returns the form to edit a view. * - * @param string|\Drupal\views\ViewStorageInterface $view + * @param string|\Drupal\views_ui\ViewUI $views_ui * The view being deleted. * @param string|null $display_id * (optional) The display ID being edited. Defaults to NULL, which will * load the first available display. + * + * @return array + * An array containing the Views edit and preview forms. */ public function edit($views_ui, $display_id = NULL) { // @todo Replace with proper upcasting. - $view = views_ui_cache_load($views_ui); + $view = $this->getViewUI($views_ui); + + $name = $view->getHumanName(); + $data = $this->viewsData->get($view->get('base_table')); + if (isset($data['table']['base']['title'])) { + $name .= ' (' . $data['table']['base']['title'] . ')'; + } + drupal_set_title($name); $view->displayID = $display_id; $build['edit'] = entity_get_form($view, 'edit'); @@ -284,15 +307,18 @@ public function edit($views_ui, $display_id = NULL) { /** * Returns the form to preview a view. * - * @param string|\Drupal\views\ViewStorageInterface $view + * @param string|\Drupal\views_ui\ViewUI $views_ui * The view being deleted. * @param string|null $display_id * (optional) The display ID being edited. Defaults to NULL, which will * load the first available display. + * + * @return array + * The Views preview form. */ public function preview($views_ui, $display_id = NULL) { // @todo Replace with proper upcasting. - $view = views_ui_cache_load($views_ui); + $view = $this->getViewUI($views_ui); $view->displayID = $display_id; return entity_get_form($view, 'preview'); @@ -301,31 +327,65 @@ public function preview($views_ui, $display_id = NULL) { /** * Returns the form to break the lock of an edited view. * - * @param string|\Drupal\views\ViewStorageInterface $view + * @param string|\Drupal\views_ui\ViewUI $views_ui * The locked view. + * + * @return array + * The Views 'break lock' form. */ public function breakLock($views_ui) { // @todo Remove the need for this. module_load_include('inc', 'views_ui', 'admin'); // @todo Replace with proper upcasting. - $view = views_ui_cache_load($views_ui); + $view = $this->getViewUI($views_ui); return drupal_get_form('views_ui_break_lock_confirm', $view); } /** * Provides a generic entry point to handle AJAX forms. + * + * @param string $js + * If this is an AJAX form, it will be the string 'ajax'. Otherwise, it will + * be 'nojs'. This determines the response. + * @param \Drupal\views_ui\ViewUI $views_ui + * The view being edited. + * @param string $key + * A string representing a section of the Views UI. Available keys are in + * views_ui_ajax_forms(). + * @param string|null $display_id + * (optional) The display ID being edited. Defaults to NULL, which will + * load the first available display. + * @param string|null $type + * (optional) If $key is 'add-item' or 'config-item', this is the type of + * handled being edited. Otherwise, it is the subsection of the Views UI. + * For example, the 'display' section has 'access' as a subsection, or the + * 'config-item' has 'sytle' as a handler type. Defaults to NULL, if the + * section has no subsections. + * @param string|null $id + * If $key is 'config-item', then this will be the plugin ID of the handler. + * + * @return array + * An form for a specific operation in the Views UI, or an array of AJAX + * commands to render a form. + * + * @todo When http://drupal.org/node/1843224 is in, this will return + * \Drupal\Core\Ajax\AjaxResponse instead of the array of AJAX commands. + * + * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ - public function ajaxForm($js, $views_ui, $operation, $display_id = NULL, $arg1 = NULL, $arg2 = NULL) { + public function ajaxForm($js, $views_ui, $key, $display_id = NULL, $type = NULL, $id = NULL) { + // Determine if this is an AJAX submission. $js = $js == 'ajax'; + // @todo Remove the need for this. module_load_include('inc', 'views_ui', 'admin'); // @todo Replace with proper upcasting. - $view = views_ui_cache_load($views_ui); + $view = $this->getViewUI($views_ui); - return views_ui_ajax_form($js, $operation, $view, $display_id, $arg1, $arg2); + return views_ui_ajax_form($js, $key, $view, $display_id, $type, $id); } /** @@ -344,11 +404,54 @@ protected function upcastView($view) { return $view; } - $entity = entity_load('view', $view); + $results = $this->entityManager->getStorageController('view')->load($name); + $entity = reset($results); if (!($entity instanceof ViewStorageInterface)) { throw new \Exception(format_string("Could not load view '@view'.", array('@view' => $view))); } return $entity; } + /** + * Loads a view, first checking for a view being currently edited. + * + * @param string $name + * The machine name of the view. + * + * @return \Drupal\views_ui\ViewUI|false + * Either the view object, with a "locked" property indicating whether or + * not someone else is already editing the view, or FALSE if the view could + * not be loaded. + */ + public function getViewUI($name) { + $view = $this->tempStore->get($name); + $results = $this->entityManager->getStorageController('view')->load(array($name)); + $storage = reset($results); + $original_view = $storage ? new ViewUI($storage) : NULL; + + if (empty($view)) { + $view = $original_view; + if (!empty($view)) { + // Check to see if someone else is already editing this view. + // Set a flag to indicate that this view is being edited. + // This flag will be used e.g. to determine whether strings + // should be localized. + $view->editing = TRUE; + } + } + else { + // Keep disabled/enabled status real. + if ($original_view) { + $view->set('disabled', $original_view->get('disabled')); + } + } + + if (empty($view)) { + return FALSE; + } + $view->locked = $this->tempStore->getMetadata($view->id()); + + return $view; + } + } diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewFormControllerBase.php b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewFormControllerBase.php index e9ed64f..61eb153 100644 --- a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewFormControllerBase.php +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewFormControllerBase.php @@ -18,6 +18,16 @@ abstract class ViewFormControllerBase extends EntityFormController { /** + * Overrides \Drupal\Core\Entity\EntityFormController::init(). + */ + protected function init(array &$form_state, EntityInterface $entity) { + parent::init($form_state, $entity); + + // @todo Remove the need for this. + form_load_include($form_state, 'inc', 'views_ui', 'admin'); + } + + /** * Overrides Drupal\Core\Entity\EntityFormController::prepareForm(). */ protected function prepareEntity(EntityInterface $view) { diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewPreviewFormController.php b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewPreviewFormController.php index b35e41f..8d8ca11 100644 --- a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewPreviewFormController.php +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewPreviewFormController.php @@ -98,7 +98,7 @@ protected function actions(array $form, array &$form_state) { public function submitPreview($form, &$form_state) { // Rebuild the form with a pristine $view object. $view = $this->getEntity($form_state); - $form_state['build_info']['args'][0] = views_ui_cache_load($view->id()); + $form_state['build_info']['args'][0] = drupal_container()->get('views_ui.controller')->getViewUI($view->id()); $view->renderPreview = TRUE; $form_state['show_preview'] = TRUE; $form_state['rebuild'] = TRUE; diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewsUiBundle.php b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewsUiBundle.php index a53e043..a949b99 100644 --- a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewsUiBundle.php +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewsUiBundle.php @@ -23,7 +23,8 @@ public function build(ContainerBuilder $container) { $container->register('views_ui.controller', 'Drupal\views_ui\Routing\ViewsUIController') ->addArgument(new Reference('plugin.manager.entity')) ->addArgument(new Reference('views.views_data')) - ->addArgument(new Reference('request')); + ->addArgument(new Reference('request')) + ->addArgument(new Reference('user.tempstore')); } } diff --git a/core/modules/views/views_ui/views_ui.module b/core/modules/views/views_ui/views_ui.module index f7a7872..57f3c95 100644 --- a/core/modules/views/views_ui/views_ui.module +++ b/core/modules/views/views_ui/views_ui.module @@ -60,20 +60,18 @@ function views_ui_menu() { // The primary Edit View page. Secondary tabs for each Display are added in // views_ui_menu_local_tasks_alter(). - $items['admin/structure/views/view/%views_ui_cache'] = array( - 'title callback' => 'views_ui_edit_page_title', - 'title arguments' => array(4), + $items['admin/structure/views/view/%'] = array( 'page callback' => 'NOT_USED', 'access arguments' => array('administer views'), ); - $items['admin/structure/views/view/%views_ui_cache/edit'] = array( + $items['admin/structure/views/view/%/edit'] = array( 'title' => 'Edit view', 'type' => MENU_DEFAULT_LOCAL_TASK, 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE, 'weight' => -10, 'access arguments' => array('administer views'), ); - $items['admin/structure/views/view/%views_ui_cache/preview/%'] = array( + $items['admin/structure/views/view/%/preview/%'] = array( 'page callback' => 'NOT_USED', 'page arguments' => array(4, 6), 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE, @@ -83,7 +81,7 @@ function views_ui_menu() { // Additional pages for acting on a View. - $items['admin/structure/views/view/%views_ui_cache/break-lock'] = array( + $items['admin/structure/views/view/%/break-lock'] = array( 'title' => 'Break lock', 'page callback' => 'NOT_USED', 'type' => MENU_VISIBLE_IN_BREADCRUMB, @@ -91,7 +89,7 @@ function views_ui_menu() { ); // NoJS/AJAX callbacks that can use the default Views AJAX form system. - $items['admin/structure/views/nojs/%/%views_ui_cache'] = array( + $items['admin/structure/views/nojs/%/%'] = array( 'page callback' => 'NOT_USED', 'type' => MENU_VISIBLE_IN_BREADCRUMB, 'access arguments' => array('administer views'), @@ -227,61 +225,6 @@ function views_ui_library_info() { } /** - * Page title callback for the Edit View page. - */ -function views_ui_edit_page_title(ViewUI $view) { - module_load_include('inc', 'views_ui', 'admin'); - $bases = views_fetch_base_tables(); - $name = $view->getHumanName(); - if (isset($bases[$view->get('base_table')])) { - $name .= ' (' . $bases[$view->get('base_table')]['title'] . ')'; - } - - return $name; -} - -/** - * Specialized menu callback to load a view and check its locked status. - * - * @param $name - * The machine name of the view. - * - * @return - * The view object, with a "locked" property indicating whether or not - * someone else is already editing the view. - */ -function views_ui_cache_load($name) { - $views_temp_store = drupal_container()->get('user.tempstore')->get('views'); - $view = $views_temp_store->get($name); - $storage = entity_load('view', $name); - $original_view = $storage ? new ViewUI($storage) : NULL; - - if (empty($view)) { - $view = $original_view; - if (!empty($view)) { - // Check to see if someone else is already editing this view. - // Set a flag to indicate that this view is being edited. - // This flag will be used e.g. to determine whether strings - // should be localized. - $view->editing = TRUE; - } - } - else { - // Keep disabled/enabled status real. - if ($original_view) { - $view->set('disabled', $original_view->get('disabled')); - } - } - - if (empty($view)) { - return FALSE; - } - $view->locked = $views_temp_store->getMetadata($view->id()); - - return $view; -} - -/** * Specialized cache function to add a flag to our view, include an appropriate * include, and cache more easily. */ diff --git a/core/modules/views/views_ui/views_ui.routing.yml b/core/modules/views/views_ui/views_ui.routing.yml index eb3a30e..6a2f32c 100644 --- a/core/modules/views/views_ui/views_ui.routing.yml +++ b/core/modules/views/views_ui/views_ui.routing.yml @@ -4,36 +4,42 @@ views_ui.list: _controller: 'views_ui.controller:listing' requirements: _permission: 'administer views' + views_ui.add: pattern: '/admin/structure/views/add' defaults: _controller: 'views_ui.controller:add' requirements: _permission: 'administer views' + views_ui.settings.basic: pattern: '/admin/structure/views/settings' defaults: _controller: 'views_ui.controller:settingsBasic' requirements: _permission: 'administer views' + views_ui.settings.advanced: pattern: '/admin/structure/views/settings/advanced' defaults: _controller: 'views_ui.controller:settingsAdvanced' requirements: _permission: 'administer views' + views_ui.reports.fields: pattern: '/admin/reports/fields/views-fields' defaults: _controller: 'views_ui.controller:reportFields' requirements: _permission: 'administer views' + views_ui.reports.plugins: pattern: '/admin/reports/views-plugins' defaults: _controller: 'views_ui.controller:reportPlugins' requirements: _permission: 'administer views' + views_ui.operation: pattern: '/admin/structure/views/view/{view}/{op}' defaults: @@ -41,30 +47,35 @@ views_ui.operation: requirements: _permission: 'administer views' op: 'enable|disable' + views_ui.clone: pattern: '/admin/structure/views/view/{view}/clone' defaults: _controller: 'views_ui.controller:cloneForm' requirements: _permission: 'administer views' + views_ui.delete: pattern: '/admin/structure/views/view/{view}/delete' defaults: _controller: 'views_ui.controller:deleteForm' requirements: _permission: 'administer views' + views_ui.autocomplete: pattern: '/admin/views/ajax/autocomplete/tag' defaults: _controller: 'views_ui.controller:autocompleteTag' requirements: _permission: 'administer views' + views_ui.edit: pattern: '/admin/structure/views/view/{views_ui}' defaults: _controller: 'views_ui.controller:edit' requirements: _permission: 'administer views' + views_ui.edit.display: pattern: '/admin/structure/views/view/{views_ui}/edit/{display_id}' defaults: @@ -72,6 +83,7 @@ views_ui.edit.display: display_id: NULL requirements: _permission: 'administer views' + views_ui.preview: pattern: '/admin/structure/views/view/{views_ui}/preview/{display_id}' defaults: @@ -79,6 +91,7 @@ views_ui.preview: display_id: NULL requirements: _permission: 'administer views' + views_ui.breakLock: pattern: '/admin/structure/views/view/{views_ui}/break-lock' defaults: @@ -86,12 +99,13 @@ views_ui.breakLock: display_id: NULL requirements: _permission: 'administer views' + views_ui.ajaxForm: - pattern: '/admin/structure/views/{js}/{operation}/{views_ui}/{display_id}/{arg1}/{arg2}' + pattern: '/admin/structure/views/{js}/{key}/{views_ui}/{display_id}/{type}/{id}' defaults: _controller: 'views_ui.controller:ajaxForm' - arg1: NULL - arg2: NULL + type: NULL + id: NULL requirements: _permission: 'administer views' js: 'nojs|ajax'