diff --git a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php index 30836a3..70bb21a 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php +++ b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php @@ -365,7 +365,7 @@ public function buildOptionsForm(&$form, &$form_state) { '#ajax' => array( 'path' => views_ui_build_form_url($form_state), ), - '#submit' => array('views_ui_config_item_form_submit_temporary'), + '#submit' => array(array($this, 'submitTemporaryForm')), '#executes_submit_callback' => TRUE, ); @@ -410,6 +410,65 @@ public function buildOptionsForm(&$form, &$form_state) { } /** + * A submit handler that is used for storing temporary items when using + * multi-step changes, such as ajax requests. + */ + function submitTemporaryForm($form, &$form_state) { + // Run it through the handler's submit function. + $this->submitOptionsForm($form['options'], $form_state); + $item = $this->options; + $types = ViewExecutable::viewsHandlerTypes(); + + // For footer/header $handler_type is area but $type is footer/header. + // For all other handle types it's the same. + $handler_type = $type = $form_state['type']; + if (!empty($types[$type]['type'])) { + $handler_type = $types[$type]['type']; + } + + $override = NULL; + $executable = $form_state['view']->get('executable'); + if ($executable->display_handler->useGroupBy() && !empty($item['group_type'])) { + if (empty($executable->query)) { + $executable->initQuery(); + } + $aggregate = $executable->query->get_aggregation_info(); + if (!empty($aggregate[$item['group_type']]['handler'][$type])) { + $override = $aggregate[$item['group_type']]['handler'][$type]; + } + } + + // Create a new handler and unpack the options from the form onto it. We + // can use that for storage. + $handler = views_get_handler($item['table'], $item['field'], $handler_type, $override); + $handler->init($executable, $executable->display_handler, $item); + + // Add the incoming options to existing options because items using + // the extra form may not have everything in the form here. + $options = $form_state['values']['options'] + $this->options; + + // This unpacks only options that are in the definition, ensuring random + // extra stuff on the form is not sent through. + $handler->unpackOptions($handler->options, $options, NULL, FALSE); + + // Store the item back on the view. + $executable = $form_state['view']->get('executable'); + $executable->temporary_options[$type][$form_state['id']] = $handler->options; + + // @todo Decide if \Drupal\views_ui\Routing\ViewsUIController::ajaxForm() is + // perhaps the better place to fix the issue. + // \Drupal\views_ui\Routing\ViewsUIController::ajaxForm() drops the current + // form from the stack, even if it's an #ajax. So add the item back to the top + // of the stack. + $form_state['view']->addFormToStack($form_state['form_key'], $form_state['display_id'], $type, $item['id'], TRUE); + + $form_state['rerender'] = TRUE; + $form_state['rebuild'] = TRUE; + // Write to cache + views_ui_cache_set($form_state['view']); + } + + /** * Provides a fake field instance. * * @param string $formatter diff --git a/core/modules/views/lib/Drupal/views/Plugin/Core/Entity/View.php b/core/modules/views/lib/Drupal/views/Plugin/Core/Entity/View.php index 7cd98af..f3c02be 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/Core/Entity/View.php +++ b/core/modules/views/lib/Drupal/views/Plugin/Core/Entity/View.php @@ -94,7 +94,7 @@ class View extends ConfigEntityBase implements ViewStorageInterface { * * @var array */ - protected $display; + protected $display = array(); /** * The name of the base field to use. diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/HandlerBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/HandlerBase.php index 943090f..dd4d293 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/HandlerBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/HandlerBase.php @@ -322,8 +322,8 @@ public function buildGroupByForm(&$form, &$form_state) { $form['#section'] = $display_id . '-' . $type . '-' . $id; - $view->initQuery(); - $info = $view->query->get_aggregation_info(); + $this->view->initQuery(); + $info = $this->query->get_aggregation_info(); foreach ($info as $id => $aggregate) { $group_types[$id] = $aggregate['title']; } @@ -938,4 +938,27 @@ public static function breakPhraseString($str, &$handler = NULL) { return $handler; } + /** + * Displays the Expose form. + */ + function buildExposedForm($form, &$form_state) { + $item = &$this->options; + // flip + $item['exposed'] = empty($item['exposed']); + + // If necessary, set new defaults: + if ($item['exposed']) { + $this->defaultExposeOptions(); + } + + $form_state['view']->get('executable')->setItem($form_state['display_id'], $form_state['type'], $form_state['id'], $item); + + $form_state['view']->addFormToStack($form_state['form_key'], $form_state['display_id'], $form_state['type'], $form_state['id'], TRUE, TRUE); + + views_ui_cache_set($form_state['view']); + $form_state['rerender'] = TRUE; + $form_state['rebuild'] = TRUE; + $form_state['force_expose_options'] = TRUE; + } + } diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php index bb3fbdf..0be0173 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php @@ -1837,7 +1837,7 @@ public function buildOptionsForm(&$form, &$form_state) { $form['box']['change'] = array( '#type' => 'submit', '#value' => t('Change theme'), - '#submit' => array('views_ui_edit_display_form_change_theme'), + '#submit' => array(array($this, 'changeThemeForm')), ); $form['analysis'] = array( @@ -1851,7 +1851,7 @@ public function buildOptionsForm(&$form, &$form_state) { $form['rescan_button']['button'] = array( '#type' => 'submit', '#value' => t('Rescan template files'), - '#submit' => array('views_ui_config_item_form_rescan'), + '#submit' => array(array($this, 'rescanThemes')), ); $form['rescan_button']['markup'] = array( '#markup' => '
' . t("Important! When adding, removing, or renaming template files, it is necessary to make Drupal aware of the changes by making it rescan the files on your system. By clicking this button you clear Drupal's theme registry and thereby trigger this rescanning process. The highlighted templates above will then reflect the new state of your system.") . '
', @@ -2021,6 +2021,38 @@ public function buildOptionsForm(&$form, &$form_state) { } /** + * Submit hook to clear Drupal's theme registry (thereby triggering + * a templates rescan). + */ + public function rescanThemes($form, &$form_state) { + drupal_theme_rebuild(); + + // The 'Theme: Information' page is about to be shown again. That page + // analyzes the output of theme_get_registry(). However, this latter + // function uses an internal cache (which was initialized before we + // called drupal_theme_rebuild()) so it won't reflect the + // current state of our theme registry. The only way to clear that cache + // is to re-initialize the theme system: + unset($GLOBALS['theme']); + drupal_theme_initialize(); + + $form_state['rerender'] = TRUE; + $form_state['rebuild'] = TRUE; + } + + /** + * Displays the Change Theme form. + */ + function changeThemeForm($form, &$form_state) { + // This is just a temporary variable. + $form_state['view']->theme = $form_state['values']['theme']; + + views_ui_cache_set($form_state['view']); + $form_state['rerender'] = TRUE; + $form_state['rebuild'] = TRUE; + } + + /** * Format a list of theme templates for output by the theme info helper. */ protected function formatThemes($themes) { @@ -2129,7 +2161,7 @@ public function submitOptionsForm(&$form, &$form_state) { $access = array('type' => $form_state['values']['access']['type']); $this->setOption('access', $access); if ($plugin->usesOptions()) { - $form_state['view']->addFormToStack('display', $this->display['id'], array('access_options')); + $form_state['view']->addFormToStack('display', $this->display['id'], 'access_options'); } } } @@ -2152,7 +2184,7 @@ public function submitOptionsForm(&$form, &$form_state) { $cache = array('type' => $form_state['values']['cache']['type']); $this->setOption('cache', $cache); if ($plugin->usesOptions()) { - $form_state['view']->addFormToStack('display', $this->display['id'], array('cache_options')); + $form_state['view']->addFormToStack('display', $this->display['id'], 'cache_options'); } } } @@ -2213,7 +2245,7 @@ public function submitOptionsForm(&$form, &$form_state) { // send ajax form to options page if we use it. if ($plugin->usesOptions()) { - $form_state['view']->addFormToStack('display', $this->display['id'], array('row_options')); + $form_state['view']->addFormToStack('display', $this->display['id'], 'row_options'); } } } @@ -2229,7 +2261,7 @@ public function submitOptionsForm(&$form, &$form_state) { $this->setOption($section, $row); // send ajax form to options page if we use it. if ($plugin->usesOptions()) { - $form_state['view']->addFormToStack('display', $this->display['id'], array('style_options')); + $form_state['view']->addFormToStack('display', $this->display['id'], 'style_options'); } } } @@ -2263,7 +2295,7 @@ public function submitOptionsForm(&$form, &$form_state) { $exposed_form = array('type' => $form_state['values']['exposed_form']['type'], 'options' => array()); $this->setOption('exposed_form', $exposed_form); if ($plugin->usesOptions()) { - $form_state['view']->addFormToStack('display', $this->display['id'], array('exposed_form_options')); + $form_state['view']->addFormToStack('display', $this->display['id'], 'exposed_form_options'); } } } @@ -2290,7 +2322,7 @@ public function submitOptionsForm(&$form, &$form_state) { $pager = array('type' => $form_state['values']['pager']['type'], 'options' => $plugin->options); $this->setOption('pager', $pager); if ($plugin->usesOptions()) { - $form_state['view']->addFormToStack('display', $this->display['id'], array('pager_options')); + $form_state['view']->addFormToStack('display', $this->display['id'], 'pager_options'); } } } diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/display/Page.php b/core/modules/views/lib/Drupal/views/Plugin/views/display/Page.php index f2846c3..0baba6a 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/display/Page.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/display/Page.php @@ -399,7 +399,7 @@ public function submitOptionsForm(&$form, &$form_state) { $this->setOption('menu', $form_state['values']['menu']); // send ajax form to options page if we use it. if ($form_state['values']['menu']['type'] == 'default tab') { - $form_state['view']->addFormToStack('display', $this->display['id'], array('tab_options')); + $form_state['view']->addFormToStack('display', $this->display['id'], 'tab_options'); } break; case 'tab_options': diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/filter/FilterPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/filter/FilterPluginBase.php index b737cc7..5165577 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/filter/FilterPluginBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/filter/FilterPluginBase.php @@ -398,7 +398,7 @@ function show_build_group_button(&$form, &$form_state) { '#limit_validation_errors' => array(), '#type' => 'submit', '#value' => t('Grouped filters'), - '#submit' => array('views_ui_config_item_form_build_group'), + '#submit' => array(array($this, 'buildGroupForm')), ); $form['group_button']['radios']['radios']['#default_value'] = 0; } @@ -407,11 +407,35 @@ function show_build_group_button(&$form, &$form_state) { '#limit_validation_errors' => array(), '#type' => 'submit', '#value' => t('Single filter'), - '#submit' => array('views_ui_config_item_form_build_group'), + '#submit' => array(array($this, 'buildGroupForm')), ); $form['group_button']['radios']['radios']['#default_value'] = 1; } } + + /** + * Displays the Build Group form. + */ + function buildGroupForm($form, &$form_state) { + $item = &$this->options; + // flip. If the filter was a group, set back to a standard filter. + $item['is_grouped'] = empty($item['is_grouped']); + + // If necessary, set new defaults: + if ($item['is_grouped']) { + $this->build_group_options(); + } + + $form_state['view']->get('executable')->setItem($form_state['display_id'], $form_state['type'], $form_state['id'], $item); + + $form_state['view']->addFormToStack($form_state['form_key'], $form_state['display_id'], $form_state['type'], $form_state['id'], TRUE, TRUE); + + views_ui_cache_set($form_state['view']); + $form_state['rerender'] = TRUE; + $form_state['rebuild'] = TRUE; + $form_state['force_build_group_options'] = TRUE; + } + /** * Shortcut to display the expose/hide button. */ @@ -443,7 +467,7 @@ public function showExposeButton(&$form, &$form_state) { '#limit_validation_errors' => array(), '#type' => 'submit', '#value' => t('Expose filter'), - '#submit' => array('views_ui_config_item_form_expose'), + '#submit' => array(array($this, 'buildExposedForm')), ); $form['expose_button']['checkbox']['checkbox']['#default_value'] = 0; } @@ -455,7 +479,7 @@ public function showExposeButton(&$form, &$form_state) { '#limit_validation_errors' => array(), '#type' => 'submit', '#value' => t('Hide filter'), - '#submit' => array('views_ui_config_item_form_expose'), + '#submit' => array(array($this, 'buildExposedForm')), ); $form['expose_button']['checkbox']['checkbox']['#default_value'] = 1; } @@ -1038,7 +1062,7 @@ function build_group_form(&$form, &$form_state) { '#suffix' => '', '#type' => 'submit', '#value' => t('Add another item'), - '#submit' => array('views_ui_config_item_form_add_group'), + '#submit' => array(array($this, 'addGroupForm')), ); $js = array(); @@ -1058,6 +1082,23 @@ function build_group_form(&$form, &$form_state) { } } + /** + * Add a new group to the exposed filter groups. + */ + function addGroupForm($form, &$form_state) { + $item = &$this->options; + + // Add a new row. + $item['group_info']['group_items'][] = array(); + + $form_state['view']->get('executable')->setItem($form_state['display_id'], $form_state['type'], $form_state['id'], $item); + + views_ui_cache_set($form_state['view']); + $form_state['rerender'] = TRUE; + $form_state['rebuild'] = TRUE; + $form_state['force_build_group_options'] = TRUE; + } + /** * Make some translations to a form item to make it more suitable to diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/sort/SortPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/sort/SortPluginBase.php index 17f1a5f..b987072 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/sort/SortPluginBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/sort/SortPluginBase.php @@ -117,7 +117,7 @@ public function showExposeButton(&$form, &$form_state) { '#limit_validation_errors' => array(), '#type' => 'submit', '#value' => t('Expose sort'), - '#submit' => array('views_ui_config_item_form_expose'), + '#submit' => array(array($this, 'buildExposedForm')), ); $form['expose_button']['checkbox']['checkbox']['#default_value'] = 0; } @@ -129,7 +129,7 @@ public function showExposeButton(&$form, &$form_state) { '#limit_validation_errors' => array(), '#type' => 'submit', '#value' => t('Hide sort'), - '#submit' => array('views_ui_config_item_form_expose'), + '#submit' => array(array($this, 'buildExposedForm')), ); $form['expose_button']['checkbox']['checkbox']['#default_value'] = 1; } diff --git a/core/modules/views/lib/Drupal/views/ViewStorageController.php b/core/modules/views/lib/Drupal/views/ViewStorageController.php index 8a5f87a..1605b0c 100644 --- a/core/modules/views/lib/Drupal/views/ViewStorageController.php +++ b/core/modules/views/lib/Drupal/views/ViewStorageController.php @@ -81,23 +81,26 @@ public function create(array $values) { * The view entity to attach default displays options. */ protected function mergeDefaultDisplaysOptions(EntityInterface $entity) { - if (isset($entity->display) && is_array($entity->display)) { - $displays = array(); - - foreach ($entity->get('display') as $key => $options) { - $options += array( - 'display_options' => array(), - 'display_plugin' => NULL, - 'id' => NULL, - 'display_title' => '', - 'position' => NULL, - ); - // Add the defaults for the display. - $displays[$key] = $options; - } - - $entity->set('display', $displays); + $displays = array(); + foreach ($entity->get('display') as $key => $options) { + $options += array( + 'display_options' => array(), + 'display_plugin' => NULL, + 'id' => NULL, + 'display_title' => '', + 'position' => NULL, + ); + // Add the defaults for the display. + $displays[$key] = $options; } + // Sort the displays. + uasort($displays, function ($display1, $display2) { + if ($display1['position'] != $display2['position']) { + return $display1['position'] < $display2['position'] ? -1 : 1; + } + return 0; + }); + $entity->set('display', $displays); } } diff --git a/core/modules/views/views_ui/admin.inc b/core/modules/views/views_ui/admin.inc index b3bcda1..abf75b0 100644 --- a/core/modules/views/views_ui/admin.inc +++ b/core/modules/views/views_ui/admin.inc @@ -6,19 +6,7 @@ */ use Drupal\Component\Utility\NestedArray; -use Drupal\Core\Database\Database; -use Drupal\views\Ajax\ReplaceTitleCommand; -use Drupal\views\Ajax\TriggerPreviewCommand; -use Drupal\views\Ajax\ShowButtonsCommand; -use Drupal\views\Ajax\DismissFormCommand; -use Drupal\Core\Ajax\AjaxResponse; -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; use Drupal\views\ViewExecutable; -use Drupal\views\Plugin\views\wizard\WizardException; /** * Converts a form element in the add view wizard to be AJAX-enabled. @@ -265,45 +253,6 @@ function views_ui_taxonomy_autocomplete_validate($element, &$form_state) { } /** - * Page to delete a view. - */ -function views_ui_break_lock_confirm($form, &$form_state, ViewUI $view) { - $form_state['view'] = &$view; - $form = array(); - - if (empty($view->locked)) { - $form['message']['#markup'] = t('There is no lock on view %name to break.', array('%name' => $view->id())); - return $form; - } - - $cancel = drupal_container()->get('request')->query->get('cancel'); - if (empty($cancel)) { - $cancel = 'admin/structure/views/view/' . $view->id() . '/edit'; - } - - $account = user_load($view->locked->owner); - $form = confirm_form($form, - t('Do you want to break the lock on view %name?', - array('%name' => $view->id())), - $cancel, - t('By breaking this lock, any unsaved changes made by !user will be lost.', array('!user' => theme('username', array('account' => $account)))), - t('Break lock'), - t('Cancel')); - $form['actions']['submit']['#submit'][] = array($view, 'submitBreakLock'); - return $form; -} - -/** - * Page callback for the Edit View page. - */ -function views_ui_edit_page(ViewUI $view, $display_id = NULL) { - $view->displayID = $display_id; - $build['edit'] = entity_get_form($view, 'edit'); - $build['preview'] = entity_get_form($view, 'preview'); - return $build; -} - -/** * Move form elements into details for presentation purposes. * * Many views forms use #tree = TRUE to keep their values in a hierarchy for @@ -441,1609 +390,21 @@ function views_ui_standard_display_dropdown(&$form, &$form_state, $section) { } - -/** - * Returns information about subforms for editing the pieces of a view. - * - * @param string|null $key - * The form for which to retrieve data. If NULL, the list of all forms is - * returned. - */ -function views_ui_ajax_forms($key = NULL) { - $forms = array( - 'display' => array( - 'form_id' => 'views_ui_edit_display_form', - 'args' => array('section'), - ), - 'remove-display' => array( - 'form_id' => 'views_ui_remove_display_form', - 'args' => array(), - ), - 'rearrange' => array( - 'form_id' => 'views_ui_rearrange_form', - 'args' => array('type'), - ), - 'rearrange-filter' => array( - 'form_id' => 'views_ui_rearrange_filter_form', - 'args' => array('type'), - ), - 'reorder-displays' => array( - 'form_id' => 'views_ui_reorder_displays_form', - 'args' => array(), - 'callback' => 'buildDisplaysReorderForm', - ), - 'add-item' => array( - 'form_id' => 'views_ui_add_item_form', - 'args' => array('type'), - ), - 'config-item' => array( - 'form_id' => 'views_ui_config_item_form', - 'args' => array('type', 'id'), - ), - 'config-item-extra' => array( - 'form_id' => 'views_ui_config_item_extra_form', - 'args' => array('type', 'id'), - ), - 'config-item-group' => array( - 'form_id' => 'views_ui_config_item_group_form', - 'args' => array('type', 'id'), - ), - 'edit-details' => array( - 'form_id' => 'views_ui_edit_details_form', - 'args' => array(), - ), - 'analyze' => array( - 'form_id' => 'views_ui_analyze_view_form', - 'args' => array(), - ), - ); - - if ($key) { - return !empty($forms[$key]) ? $forms[$key] : NULL; - } - - return $forms; -} - /** * Create the URL for one of our standard AJAX forms based upon known * information about the form. */ function views_ui_build_form_url($form_state) { - $form = views_ui_ajax_forms($form_state['form_key']); $ajax = empty($form_state['ajax']) ? 'nojs' : 'ajax'; $name = $form_state['view']->id(); $url = "admin/structure/views/$ajax/$form_state[form_key]/$name/$form_state[display_id]"; - foreach ($form['args'] as $arg) { - $url .= '/' . $form_state[$arg]; - } - return $url; -} - -/** - * Generic entry point to handle forms. - * - * We do this for consistency and to make it easy to chain forms - * together. - */ -function views_ui_ajax_form($js, $key, ViewUI $view, $display_id = '') { - // Reset the cache of IDs. Drupal rather aggressively prevents ID - // duplication but this causes it to remember IDs that are no longer even - // being used. - $seen_ids_init = &drupal_static('drupal_html_id:init'); - $seen_ids_init = array(); - - $form = views_ui_ajax_forms($key); - if (empty($form)) { - throw new NotFoundHttpException(); - } - - module_load_include('inc', 'views', 'includes/ajax'); - $args = func_get_args(); - // Remove the known args - array_splice($args, 0, 4); - - $form_state = $view->buildFormState($js, $key, $display_id, $args); - // check to see if this is the top form of the stack. If it is, pop - // it off; if it isn't, the user clicked somewhere else and the stack is - // now irrelevant. - if (!empty($view->stack)) { - $identifier = $view->buildIdentifier($key, $display_id, $args); - // Retrieve the first form from the stack without changing the integer keys, - // as they're being used for the "2 of 3" progress indicator. - reset($view->stack); - list($key, $top) = each($view->stack); - unset($view->stack[$key]); - - if (array_shift($top) != $identifier) { - $view->stack = array(); - } - } - - // Automatically remove the form cache if it is set and the key does - // not match. This way navigating away from the form without hitting - // update will work. - if (isset($view->form_cache) && $view->form_cache['key'] != $key) { - unset($view->form_cache); - } - - // With the below logic, we may end up rendering a form twice (or two forms - // each sharing the same element ids), potentially resulting in - // drupal_add_js() being called twice to add the same setting. drupal_get_js() - // is ok with that, but until ajax_render() is (http://drupal.org/node/208611), - // reset the drupal_add_js() static before rendering the second time. - $drupal_add_js_original = drupal_add_js(); - $drupal_add_js = &drupal_static('drupal_add_js'); - $response = views_ajax_form_wrapper($form_state['form_id'], $form_state); - if ($form_state['submitted'] && empty($form_state['rerender'])) { - // Sometimes we need to re-generate the form for multi-step type operations. - $object = NULL; - if (!empty($view->stack)) { - $drupal_add_js = $drupal_add_js_original; - $stack = $view->stack; - $top = array_shift($stack); - $top[0] = $js; - $form_state = call_user_func_array(array($view, 'buildFormState'), $top); - $form_state['input'] = array(); - $form_state['url'] = url(views_ui_build_form_url($form_state)); - if (!$js) { - return drupal_goto(views_ui_build_form_url($form_state)); - } - $response = views_ajax_form_wrapper($form_state['form_id'], $form_state); - } - elseif (!$js) { - // if nothing on the stack, non-js forms just go back to the main view editor. - return drupal_goto("admin/structure/views/view/{$view->id()}/edit"); - } - else { - $response = new AjaxResponse(); - $response->addCommand(new DismissFormCommand()); - $response->addCommand(new ShowButtonsCommand()); - $response->addCommand(new TriggerPreviewCommand()); - if (!empty($form_state['#page_title'])) { - $response->addCommand(new ReplaceTitleCommand($form_state['#page_title'])); - } - } - // If this form was for view-wide changes, there's no need to regenerate - // the display section of the form. - if ($display_id !== '') { - drupal_container()->get('plugin.manager.entity') - ->getFormController('view', 'edit') - ->rebuildCurrentTab($view, $response, $display_id); - } - } - - return $response; -} - -/** - * Form constructor callback to display analysis information on a view - */ -function views_ui_analyze_view_form($form, &$form_state) { - $view = &$form_state['view']; - - $form['#title'] = t('View analysis'); - $form['#section'] = 'analyze'; - - $analyzer = new Analyzer($view->get('executable')); - $messages = $analyzer->getMessages(); - - $form['analysis'] = array( - '#prefix' => '
', - '#suffix' => '
', - '#markup' => $analyzer->formatMessages($messages), - ); - - // Inform the standard button function that we want an OK button. - $form_state['ok_button'] = TRUE; - $view->getStandardButtons($form, $form_state, 'views_ui_analyze_view_form'); - return $form; -} - -/** - * Submit handler for views_ui_analyze_view_form - */ -function views_ui_analyze_view_form_submit($form, &$form_state) { - $form_state['redirect'] = 'admin/structure/views/view/' . $form_state['view']->id() . '/edit'; -} - -/** - * Form builder to edit details of a view. - */ -function views_ui_edit_details_form($form, &$form_state) { - $view = &$form_state['view']; - - $form['#title'] = t('View name and description'); - $form['#section'] = 'details'; - - $form['details'] = array( - '#theme_wrappers' => array('container'), - '#attributes' => array('class' => array('scroll')), - ); - $form['details']['human_name'] = array( - '#type' => 'textfield', - '#title' => t('Human-readable name'), - '#description' => t('A descriptive human-readable name for this view. Spaces are allowed'), - '#default_value' => $view->getHumanName(), - ); - $form['details']['tag'] = array( - '#type' => 'textfield', - '#title' => t('View tag'), - '#description' => t('Optionally, enter a comma delimited list of tags for this view to use in filtering and sorting views on the administrative page.'), - '#default_value' => $view->get('tag'), - '#autocomplete_path' => 'admin/views/ajax/autocomplete/tag', - ); - $form['details']['description'] = array( - '#type' => 'textfield', - '#title' => t('View description'), - '#description' => t('This description will appear on the Views administrative UI to tell you what the view is about.'), - '#default_value' => $view->get('description'), - ); - - $view->getStandardButtons($form, $form_state, 'views_ui_edit_details_form'); - return $form; -} - -/** - * Submit handler for views_ui_edit_details_form. - */ -function views_ui_edit_details_form_submit($form, &$form_state) { - $view = $form_state['view']; - foreach ($form_state['values'] as $key => $value) { - // Only save values onto the view if they're actual view properties - // (as opposed to 'op' or 'form_build_id'). - if (isset($form['details'][$key])) { - $view->set($key, $value); - } - } - $bases = drupal_container()->get('views.views_data')->fetchBaseTables(); - $form_state['#page_title'] = $view->getHumanName(); - if (isset($bases[$view->get('base_table')])) { - $form_state['#page_title'] .= ' (' . $bases[$view->get('base_table')]['title'] . ')'; - } - views_ui_cache_set($view); -} - -/** - * Form constructor callback to edit display of a view - */ -function views_ui_edit_display_form($form, &$form_state) { - $view = &$form_state['view']; - $display_id = $form_state['display_id']; - $section = $form_state['section']; - - $executable = $view->get('executable'); - if (!$executable->setDisplay($display_id)) { - views_ajax_error(t('Invalid display id @display', array('@display' => $display_id))); - } - $display = &$executable->display[$display_id]; - - // Get form from the handler. - $form['options'] = array( - '#theme_wrappers' => array('container'), - '#attributes' => array('class' => array('scroll')), - ); - $executable->display_handler->buildOptionsForm($form['options'], $form_state); - - // The handler options form sets $form['#title'], which we need on the entire - // $form instead of just the ['options'] section. - $form['#title'] = $form['options']['#title']; - unset($form['options']['#title']); - - // Move the override dropdown out of the scrollable section of the form. - if (isset($form['options']['override'])) { - $form['override'] = $form['options']['override']; - unset($form['options']['override']); - } - - $name = NULL; - if (isset($form_state['update_name'])) { - $name = $form_state['update_name']; - } - - $view->getStandardButtons($form, $form_state, 'views_ui_edit_display_form', $name); - return $form; -} - -/** - * Validate handler for views_ui_edit_display_form - */ -function views_ui_edit_display_form_validate($form, &$form_state) { - $form_state['view']->get('executable')->displayHandlers->get($form_state['display_id'])->validateOptionsForm($form['options'], $form_state); - - if (form_get_errors()) { - $form_state['rerender'] = TRUE; - } -} - -/** - * Submit handler for views_ui_edit_display_form - */ -function views_ui_edit_display_form_submit($form, &$form_state) { - $form_state['view']->get('executable')->displayHandlers->get($form_state['display_id'])->submitOptionsForm($form['options'], $form_state); - - views_ui_cache_set($form_state['view']); -} - -/** - * Override handler for views_ui_edit_display_form - * - * @TODO: Not currently used. Remove unless we implement an override toggle. - */ -function views_ui_edit_display_form_override($form, &$form_state) { - $form_state['view']->get('executable')->displayHandlers->get($form_state['display_id'])->optionsOverride($form['options'], $form_state); - - views_ui_cache_set($form_state['view']); - $form_state['rerender'] = TRUE; - $form_state['rebuild'] = TRUE; -} - -/** - * Form to rearrange items in the views UI. - */ -function views_ui_rearrange_form($form, &$form_state) { - $view = &$form_state['view']; - $display_id = $form_state['display_id']; - $type = $form_state['type']; - - $types = ViewExecutable::viewsHandlerTypes(); - $executable = $view->get('executable'); - if (!$executable->setDisplay($display_id)) { - views_ajax_error(t('Invalid display id @display', array('@display' => $display_id))); - } - $display = &$executable->displayHandlers->get($display_id); - $form['#title'] = t('Rearrange @type', array('@type' => $types[$type]['ltitle'])); - $form['#section'] = $display_id . 'rearrange-item'; - - if ($display->defaultableSections($types[$type]['plural'])) { - $form_state['section'] = $types[$type]['plural']; - views_ui_standard_display_dropdown($form, $form_state, $form_state['section']); - } - - $count = 0; - - // Get relationship labels - $relationships = array(); - foreach ($display->getHandlers('relationship') as $id => $handler) { - $relationships[$id] = $handler->label(); - } - - // Filters can now be grouped so we do a little bit extra: - $groups = array(); - $grouping = FALSE; - if ($type == 'filter') { - $group_info = $executable->display_handler->getOption('filter_groups'); - if (!empty($group_info['groups']) && count($group_info['groups']) > 1) { - $grouping = TRUE; - $groups = array(0 => array()); - } - } - - foreach ($display->getOption($types[$type]['plural']) as $id => $field) { - $form['fields'][$id] = array('#tree' => TRUE); - $form['fields'][$id]['weight'] = array( - '#type' => 'textfield', - '#default_value' => ++$count, - ); - $handler = $display->getHandler($type, $id); - if ($handler) { - $name = $handler->adminLabel() . ' ' . $handler->adminSummary(); - if (!empty($field['relationship']) && !empty($relationships[$field['relationship']])) { - $name = '(' . $relationships[$field['relationship']] . ') ' . $name; - } - - $form['fields'][$id]['name'] = array( - '#markup' => $name, - ); - } - else { - $form['fields'][$id]['name'] = array('#markup' => t('Broken field @id', array('@id' => $id))); - } - $form['fields'][$id]['removed'] = array( - '#type' => 'checkbox', - '#id' => 'views-removed-' . $id, - '#attributes' => array('class' => array('views-remove-checkbox')), - '#default_value' => 0, - ); - } - - // Add javascript settings that will be added via $.extend for tabledragging - $form['#js']['tableDrag']['arrange']['weight'][0] = array( - 'target' => 'weight', - 'source' => NULL, - 'relationship' => 'sibling', - 'action' => 'order', - 'hidden' => TRUE, - 'limit' => 0, - ); - - $name = NULL; - if (isset($form_state['update_name'])) { - $name = $form_state['update_name']; - } - - $view->getStandardButtons($form, $form_state, 'views_ui_rearrange_form'); - return $form; -} - -/** - * Submit handler for rearranging form. - */ -function views_ui_rearrange_form_submit($form, &$form_state) { - $types = ViewExecutable::viewsHandlerTypes(); - $display = &$form_state['view']->get('executable')->displayHandlers->get($form_state['display_id']); - - $old_fields = $display->getOption($types[$form_state['type']]['plural']); - $new_fields = $order = array(); - - // Make an array with the weights - foreach ($form_state['values'] as $field => $info) { - // add each value that is a field with a weight to our list, but only if - // it has had its 'removed' checkbox checked. - if (is_array($info) && isset($info['weight']) && empty($info['removed'])) { - $order[$field] = $info['weight']; - } - } - - // Sort the array - asort($order); - - // Create a new list of fields in the new order. - foreach (array_keys($order) as $field) { - $new_fields[$field] = $old_fields[$field]; - } - $display->setOption($types[$form_state['type']]['plural'], $new_fields); - - // Store in cache - views_ui_cache_set($form_state['view']); -} - -/** - * Form to rearrange items in the views UI. - */ -function views_ui_rearrange_filter_form($form, &$form_state) { - $view = &$form_state['view']; - $display_id = $form_state['display_id']; - $type = $form_state['type']; - - $types = ViewExecutable::viewsHandlerTypes(); - $executable = $view->get('executable'); - if (!$executable->setDisplay($display_id)) { - views_ajax_render(t('Invalid display id @display', array('@display' => $display_id))); - } - $display = $executable->displayHandlers->get($display_id); - $form['#title'] = check_plain($display->display['display_title']) . ': '; - $form['#title'] .= t('Rearrange @type', array('@type' => $types[$type]['ltitle'])); - $form['#section'] = $display_id . 'rearrange-item'; - - if ($display->defaultableSections($types[$type]['plural'])) { - $form_state['section'] = $types[$type]['plural']; - views_ui_standard_display_dropdown($form, $form_state, $form_state['section']); - } - - if (!empty($view->form_cache)) { - $groups = $view->form_cache['groups']; - $handlers = $view->form_cache['handlers']; - } - else { - $groups = $display->getOption('filter_groups'); - $handlers = $display->getOption($types[$type]['plural']); - } - $count = 0; - - // Get relationship labels - $relationships = array(); - foreach ($display->getHandlers('relationship') as $id => $handler) { - $relationships[$id] = $handler->label(); - } - - $group_options = array(); - - /** - * Filter groups is an array that contains: - * array( - * 'operator' => 'and' || 'or', - * 'groups' => array( - * $group_id => 'and' || 'or', - * ), - * ); - */ - - $grouping = count(array_keys($groups['groups'])) > 1; - - $form['filter_groups']['#tree'] = TRUE; - $form['filter_groups']['operator'] = array( - '#type' => 'select', - '#options' => array( - 'AND' => t('And'), - 'OR' => t('Or'), - ), - '#default_value' => $groups['operator'], - '#attributes' => array( - 'class' => array('warning-on-change'), - ), - '#title' => t('Operator to use on all groups'), - '#description' => t('Either "group 0 AND group 1 AND group 2" or "group 0 OR group 1 OR group 2", etc'), - '#access' => $grouping, - ); - - $form['remove_groups']['#tree'] = TRUE; - - foreach ($groups['groups'] as $id => $group) { - $form['filter_groups']['groups'][$id] = array( - '#title' => t('Operator'), - '#type' => 'select', - '#options' => array( - 'AND' => t('And'), - 'OR' => t('Or'), - ), - '#default_value' => $group, - '#attributes' => array( - 'class' => array('warning-on-change'), - ), - ); - - $form['remove_groups'][$id] = array(); // to prevent a notice - if ($id != 1) { - $form['remove_groups'][$id] = array( - '#type' => 'submit', - '#value' => t('Remove group @group', array('@group' => $id)), - '#id' => "views-remove-group-$id", - '#attributes' => array( - 'class' => array('views-remove-group'), - ), - '#group' => $id, - ); - } - $group_options[$id] = $id == 1 ? t('Default group') : t('Group @group', array('@group' => $id)); - $form['#group_renders'][$id] = array(); + if (isset($form_state['type'])) { + $url .= '/' . $form_state['type']; } - - $form['#group_options'] = $group_options; - $form['#groups'] = $groups; - // We don't use getHandlers() because we want items without handlers to - // appear and show up as 'broken' so that the user can see them. - $form['filters'] = array('#tree' => TRUE); - foreach ($handlers as $id => $field) { - // If the group does not exist, move the filters to the default group. - if (empty($field['group']) || empty($groups['groups'][$field['group']])) { - $field['group'] = 1; - } - - $handler = $display->getHandler($type, $id); - if ($grouping && $handler && !$handler->can_group()) { - $field['group'] = 'ungroupable'; - } - - // If not grouping and the handler is set ungroupable, move it back to - // the default group to prevent weird errors from having it be in its - // own group: - if (!$grouping && $field['group'] == 'ungroupable') { - $field['group'] = 1; - } - - // Place this item into the proper group for rendering. - $form['#group_renders'][$field['group']][] = $id; - - $form['filters'][$id]['weight'] = array( - '#type' => 'textfield', - '#default_value' => ++$count, - '#size' => 8, - ); - $form['filters'][$id]['group'] = array( - '#type' => 'select', - '#options' => $group_options, - '#default_value' => $field['group'], - '#attributes' => array( - 'class' => array('views-region-select', 'views-region-' . $id), - ), - '#access' => $field['group'] !== 'ungroupable', - ); - - if ($handler) { - $name = $handler->adminLabel() . ' ' . $handler->adminSummary(); - if (!empty($field['relationship']) && !empty($relationships[$field['relationship']])) { - $name = '(' . $relationships[$field['relationship']] . ') ' . $name; - } - - $form['filters'][$id]['name'] = array( - '#markup' => $name, - ); - } - else { - $form['filters'][$id]['name'] = array('#markup' => t('Broken field @id', array('@id' => $id))); - } - $form['filters'][$id]['removed'] = array( - '#type' => 'checkbox', - '#id' => 'views-removed-' . $id, - '#attributes' => array('class' => array('views-remove-checkbox')), - '#default_value' => 0, - ); - } - - if (isset($form_state['update_name'])) { - $name = $form_state['update_name']; - } - - $view->getStandardButtons($form, $form_state, 'views_ui_rearrange_filter_form'); - $form['buttons']['add_group'] = array( - '#type' => 'submit', - '#value' => t('Create new filter group'), - '#id' => 'views-add-group', - '#group' => 'add', - ); - - return $form; -} - -/** - * Submit handler for rearranging form - */ -function views_ui_rearrange_filter_form_submit($form, &$form_state) { - $types = ViewExecutable::viewsHandlerTypes(); - $display = &$form_state['view']->get('executable')->displayHandlers->get($form_state['display_id']); - $remember_groups = array(); - - if (!empty($form_state['view']->form_cache)) { - $old_fields = $form_state['view']->form_cache['handlers']; - } - else { - $old_fields = $display->getOption($types[$form_state['type']]['plural']); - } - $count = 0; - - $groups = $form_state['values']['filter_groups']; - // Whatever button was clicked, re-calculate field information. - $new_fields = $order = array(); - - // Make an array with the weights - foreach ($form_state['values']['filters'] as $field => $info) { - // add each value that is a field with a weight to our list, but only if - // it has had its 'removed' checkbox checked. - if (is_array($info) && empty($info['removed'])) { - if (isset($info['weight'])) { - $order[$field] = $info['weight']; - } - - if (isset($info['group'])) { - $old_fields[$field]['group'] = $info['group']; - $remember_groups[$info['group']][] = $field; - } - } - } - - // Sort the array - asort($order); - - // Create a new list of fields in the new order. - foreach (array_keys($order) as $field) { - $new_fields[$field] = $old_fields[$field]; - } - - // If the #group property is set on the clicked button, that means we are - // either adding or removing a group, not actually updating the filters. - if (!empty($form_state['clicked_button']['#group'])) { - if ($form_state['clicked_button']['#group'] == 'add') { - // Add a new group - $groups['groups'][] = 'AND'; - } - else { - // Renumber groups above the removed one down. - foreach (array_keys($groups['groups']) as $group_id) { - if ($group_id >= $form_state['clicked_button']['#group']) { - $old_group = $group_id + 1; - if (isset($groups['groups'][$old_group])) { - $groups['groups'][$group_id] = $groups['groups'][$old_group]; - if (isset($remember_groups[$old_group])) { - foreach ($remember_groups[$old_group] as $id) { - $new_fields[$id]['group'] = $group_id; - } - } - } - else { - // If this is the last one, just unset it. - unset($groups['groups'][$group_id]); - } - } - } - } - // Update our cache with values so that cancel still works the way - // people expect. - $form_state['view']->form_cache = array( - 'key' => 'rearrange-filter', - 'groups' => $groups, - 'handlers' => $new_fields, - ); - - // Return to this form except on actual Update. - $form_state['view']->addFormToStack('rearrange-filter', $form_state['display_id'], array($form_state['type'])); - } - else { - // The actual update button was clicked. Remove the empty groups, and - // renumber them sequentially. - ksort($remember_groups); - $groups['groups'] = views_array_key_plus(array_values(array_intersect_key($groups['groups'], $remember_groups))); - // Change the 'group' key on each field to match. Here, $mapping is an - // array whose keys are the old group numbers and whose values are the new - // (sequentially numbered) ones. - $mapping = array_flip(views_array_key_plus(array_keys($remember_groups))); - foreach ($new_fields as &$new_field) { - $new_field['group'] = $mapping[$new_field['group']]; - } - - // Write the changed handler values. - $display->setOption($types[$form_state['type']]['plural'], $new_fields); - $display->setOption('filter_groups', $groups); - if (isset($form_state['view']->form_cache)) { - unset($form_state['view']->form_cache); - } + if (isset($form_state['id'])) { + $url .= '/' . $form_state['id']; } - - // Store in cache. - views_ui_cache_set($form_state['view']); -} - -/** - * Form to add_item items in the views UI. - */ -function views_ui_add_item_form($form, &$form_state) { - $view = &$form_state['view']; - $display_id = $form_state['display_id']; - $type = $form_state['type']; - - $form = array( - 'options' => array( - '#theme_wrappers' => array('container'), - '#attributes' => array('class' => array('scroll')), - ), - ); - - $executable = $view->get('executable'); - if (!$executable->setDisplay($display_id)) { - views_ajax_error(t('Invalid display id @display', array('@display' => $display_id))); - } - $display = &$executable->displayHandlers->get($display_id); - - $types = ViewExecutable::viewsHandlerTypes(); - $ltitle = $types[$type]['ltitle']; - $section = $types[$type]['plural']; - - if (!empty($types[$type]['type'])) { - $type = $types[$type]['type']; - } - - $form['#title'] = t('Add @type', array('@type' => $ltitle)); - $form['#section'] = $display_id . 'add-item'; - - // Add the display override dropdown. - views_ui_standard_display_dropdown($form, $form_state, $section); - - // Figure out all the base tables allowed based upon what the relationships provide. - $base_tables = $executable->getBaseTables(); - $options = views_fetch_fields(array_keys($base_tables), $type, $display->useGroupBy(), $form_state['type']); - - if (!empty($options)) { - $form['override']['controls'] = array( - '#theme_wrappers' => array('container'), - '#id' => 'views-filterable-options-controls', - '#attributes' => array('class' => array('container-inline')), - ); - $form['override']['controls']['options_search'] = array( - '#type' => 'textfield', - '#title' => t('Search'), - ); - - $groups = array('all' => t('- All -')); - $form['override']['controls']['group'] = array( - '#type' => 'select', - '#title' => t('Type'), - '#options' => array(), - ); - - $form['options']['name'] = array( - '#prefix' => '
', - '#suffix' => '
', - '#tree' => TRUE, - '#default_value' => 'all', - ); - - // Group options first to simplify the usage of #states. - $grouped_options = array(); - foreach ($options as $key => $option) { - $group = preg_replace('/[^a-z0-9]/', '-', strtolower($option['group'])); - $groups[$group] = $option['group']; - $grouped_options[$group][$key] = $option; - if (!empty($option['aliases']) && is_array($option['aliases'])) { - foreach ($option['aliases'] as $id => $alias) { - if (empty($alias['base']) || !empty($base_tables[$alias['base']])) { - $copy = $option; - $copy['group'] = $alias['group']; - $copy['title'] = $alias['title']; - if (isset($alias['help'])) { - $copy['help'] = $alias['help']; - } - - $group = preg_replace('/[^a-z0-9]/', '-', strtolower($copy['group'])); - $groups[$group] = $copy['group']; - $grouped_options[$group][$key . '$' . $id] = $copy; - } - } - } - } - - foreach ($grouped_options as $group => $group_options) { - $zebra = 0; - foreach ($group_options as $key => $option) { - $zebra_class = ($zebra % 2) ? 'odd' : 'even'; - $form['options']['name'][$key] = array( - '#type' => 'checkbox', - '#title' => t('!group: !field', array('!group' => $option['group'], '!field' => $option['title'])), - '#description' => $option['help'], - '#return_value' => $key, - '#prefix' => "
", - '#suffix' => '
', - '#states' => array( - 'visible' => array( - array( - ':input[name="override[controls][group]"]' => array('value' => 'all'), - ), - array( - ':input[name="override[controls][group]"]' => array('value' => $group), - ), - ) - ) - ); - $zebra++; - } - } - - $form['override']['controls']['group']['#options'] = $groups; - } - else { - $form['options']['markup'] = array( - '#markup' => '
' . t('There are no @types available to add.', array('@types' => $ltitle)) . '
', - ); - } - // Add a div to show the selected items - $form['selected'] = array( - '#type' => 'item', - '#markup' => '
', - '#title' => t('Selected') . ':', - '#theme_wrappers' => array('form_element', 'views_ui_container'), - '#attributes' => array('class' => array('container-inline', 'views-add-form-selected')), - ); - $view->getStandardButtons($form, $form_state, 'views_ui_add_item_form', t('Add and configure @types', array('@types' => $ltitle))); - - // Remove the default submit function. - $form['buttons']['submit']['#submit'] = array_filter($form['buttons']['submit']['#submit'], function($var) { - return !(is_array($var) && isset($var[1]) && $var[1] == 'standardSubmit'); - }); - $form['buttons']['submit']['#submit'][] = array($view, 'submitItemAdd'); - - return $form; -} - -/** - * Override handler for views_ui_edit_display_form - */ -function views_ui_config_item_form_build_group($form, &$form_state) { - $item = &$form_state['handler']->options; - // flip. If the filter was a group, set back to a standard filter. - $item['is_grouped'] = empty($item['is_grouped']); - - // If necessary, set new defaults: - if ($item['is_grouped']) { - $form_state['handler']->build_group_options(); - } - - $form_state['view']->get('executable')->setItem($form_state['display_id'], $form_state['type'], $form_state['id'], $item); - - $form_state['view']->addFormToStack($form_state['form_key'], $form_state['display_id'], array($form_state['type'], $form_state['id']), TRUE, TRUE); - - views_ui_cache_set($form_state['view']); - $form_state['rerender'] = TRUE; - $form_state['rebuild'] = TRUE; - $form_state['force_build_group_options'] = TRUE; -} - -/** - * Add a new group to the exposed filter groups. - */ -function views_ui_config_item_form_add_group($form, &$form_state) { - $item =& $form_state['handler']->options; - - // Add a new row. - $item['group_info']['group_items'][] = array(); - - $form_state['view']->get('executable')->setItem($form_state['display_id'], $form_state['type'], $form_state['id'], $item); - - views_ui_cache_set($form_state['view']); - $form_state['rerender'] = TRUE; - $form_state['rebuild'] = TRUE; - $form_state['force_build_group_options'] = TRUE; -} - -/** - * Form to config_item items in the views UI. - */ -function views_ui_config_item_form($form, &$form_state) { - $view = &$form_state['view']; - $display_id = $form_state['display_id']; - $type = $form_state['type']; - $id = $form_state['id']; - - $form = array( - 'options' => array( - '#tree' => TRUE, - '#theme_wrappers' => array('container'), - '#attributes' => array('class' => array('scroll')), - ), - ); - $executable = $view->get('executable'); - $save_ui_cache = FALSE; - if (!$executable->setDisplay($display_id)) { - views_ajax_error(t('Invalid display id @display', array('@display' => $display_id))); - } - $item = $executable->getItem($display_id, $type, $id); - - if ($item) { - $handler = $executable->display_handler->getHandler($type, $id); - if (empty($handler)) { - $form['markup'] = array('#markup' => t("Error: handler for @table > @field doesn't exist!", array('@table' => $item['table'], '@field' => $item['field']))); - } - else { - $types = ViewExecutable::viewsHandlerTypes(); - - // If this item can come from the default display, show a dropdown - // that lets the user choose which display the changes should apply to. - if ($executable->display_handler->defaultableSections($types[$type]['plural'])) { - $form_state['section'] = $types[$type]['plural']; - views_ui_standard_display_dropdown($form, $form_state, $form_state['section']); - } - - // A whole bunch of code to figure out what relationships are valid for - // this item. - $relationships = $executable->display_handler->getOption('relationships'); - $relationship_options = array(); - - foreach ($relationships as $relationship) { - // relationships can't link back to self. But also, due to ordering, - // relationships can only link to prior relationships. - if ($type == 'relationship' && $id == $relationship['id']) { - break; - } - $relationship_handler = views_get_handler($relationship['table'], $relationship['field'], 'relationship'); - // ignore invalid/broken relationships. - if (empty($relationship_handler)) { - continue; - } - - // If this relationship is valid for this type, add it to the list. - $data = drupal_container()->get('views.views_data')->get($relationship['table']); - $base = $data[$relationship['field']]['relationship']['base']; - $base_fields = views_fetch_fields($base, $form_state['type'], $executable->display_handler->useGroupBy()); - if (isset($base_fields[$item['table'] . '.' . $item['field']])) { - $relationship_handler->init($executable, $executable->display_handler, $relationship); - $relationship_options[$relationship['id']] = $relationship_handler->label(); - } - } - - if (!empty($relationship_options)) { - // Make sure the existing relationship is even valid. If not, force - // it to none. - $base_fields = views_fetch_fields($view->get('base_table'), $form_state['type'], $executable->display_handler->useGroupBy()); - if (isset($base_fields[$item['table'] . '.' . $item['field']])) { - $relationship_options = array_merge(array('none' => t('Do not use a relationship')), $relationship_options); - } - $rel = empty($item['relationship']) ? 'none' : $item['relationship']; - if (empty($relationship_options[$rel])) { - // Pick the first relationship. - $rel = key($relationship_options); - // We want this relationship option to get saved even if the user - // skips submitting the form. - $executable->setItemOption($display_id, $type, $id, 'relationship', $rel); - $save_ui_cache = TRUE; - } - - $form['options']['relationship'] = array( - '#type' => 'select', - '#title' => t('Relationship'), - '#options' => $relationship_options, - '#default_value' => $rel, - '#weight' => -500, - ); - } - else { - $form['options']['relationship'] = array( - '#type' => 'value', - '#value' => 'none', - ); - } - - $form['#title'] = t('Configure @type: @item', array('@type' => $types[$type]['lstitle'], '@item' => $handler->adminLabel())); - - if (!empty($handler->definition['help'])) { - $form['options']['form_description'] = array( - '#markup' => $handler->definition['help'], - '#theme_wrappers' => array('container'), - '#attributes' => array('class' => array('form-item description')), - '#weight' => -1000, - ); - } - - $form['#section'] = $display_id . '-' . $type . '-' . $id; - - // Get form from the handler. - $handler->buildOptionsForm($form['options'], $form_state); - $form_state['handler'] = &$handler; - } - - $name = NULL; - if (isset($form_state['update_name'])) { - $name = $form_state['update_name']; - } - - $view->getStandardButtons($form, $form_state, 'views_ui_config_item_form', $name, t('Remove'), 'remove'); - // Only validate the override values, because this values are required for - // the override selection. - $form['buttons']['remove']['#limit_validation_errors'] = array(array('override')); - } - - if ($save_ui_cache) { - views_ui_cache_set($view); - } - - return $form; -} - -/** - * Submit handler for configing new item(s) to a view. - */ -function views_ui_config_item_form_validate($form, &$form_state) { - $form_state['handler']->validateOptionsForm($form['options'], $form_state); - - if (form_get_errors()) { - $form_state['rerender'] = TRUE; - } -} - -/** - * A submit handler that is used for storing temporary items when using - * multi-step changes, such as ajax requests. - */ -function views_ui_config_item_form_submit_temporary($form, &$form_state) { - // Run it through the handler's submit function. - $form_state['handler']->submitOptionsForm($form['options'], $form_state); - $item = $form_state['handler']->options; - $types = ViewExecutable::viewsHandlerTypes(); - - // For footer/header $handler_type is area but $type is footer/header. - // For all other handle types it's the same. - $handler_type = $type = $form_state['type']; - if (!empty($types[$type]['type'])) { - $handler_type = $types[$type]['type']; - } - - $override = NULL; - $executable = $form_state['view']->get('executable'); - if ($executable->display_handler->useGroupBy() && !empty($item['group_type'])) { - if (empty($executable->query)) { - $executable->initQuery(); - } - $aggregate = $executable->query->get_aggregation_info(); - if (!empty($aggregate[$item['group_type']]['handler'][$type])) { - $override = $aggregate[$item['group_type']]['handler'][$type]; - } - } - - // Create a new handler and unpack the options from the form onto it. We - // can use that for storage. - $handler = views_get_handler($item['table'], $item['field'], $handler_type, $override); - $handler->init($executable, $executable->display_handler, $item); - - // Add the incoming options to existing options because items using - // the extra form may not have everything in the form here. - $options = $form_state['values']['options'] + $form_state['handler']->options; - - // This unpacks only options that are in the definition, ensuring random - // extra stuff on the form is not sent through. - $handler->unpackOptions($handler->options, $options, NULL, FALSE); - - // Store the item back on the view. - $executable = $form_state['view']->get('executable'); - $executable->temporary_options[$type][$form_state['id']] = $handler->options; - - // @todo: Figure out whether views_ui_ajax_form is perhaps the better place to fix the issue. - // views_ui_ajax_form() drops the current form from the stack, even if it's an #ajax. - // So add the item back to the top of the stack. - $form_state['view']->addFormToStack($form_state['form_key'], $form_state['display_id'], array($type, $item['id']), TRUE); - - $form_state['rerender'] = TRUE; - $form_state['rebuild'] = TRUE; - // Write to cache - views_ui_cache_set($form_state['view']); -} - -/** - * Submit handler for configing new item(s) to a view. - */ -function views_ui_config_item_form_submit($form, &$form_state) { - // Run it through the handler's submit function. - $form_state['handler']->submitOptionsForm($form['options'], $form_state); - $item = $form_state['handler']->options; - $types = ViewExecutable::viewsHandlerTypes(); - - // For footer/header $handler_type is area but $type is footer/header. - // For all other handle types it's the same. - $handler_type = $type = $form_state['type']; - if (!empty($types[$type]['type'])) { - $handler_type = $types[$type]['type']; - } - - $override = NULL; - $executable = $form_state['view']->get('executable'); - if ($executable->display_handler->useGroupBy() && !empty($item['group_type'])) { - if (empty($executable->query)) { - $executable->initQuery(); - } - $aggregate = $executable->query->get_aggregation_info(); - if (!empty($aggregate[$item['group_type']]['handler'][$type])) { - $override = $aggregate[$item['group_type']]['handler'][$type]; - } - } - - // Create a new handler and unpack the options from the form onto it. We - // can use that for storage. - $handler = views_get_handler($item['table'], $item['field'], $handler_type, $override); - $handler->init($executable, $executable->display_handler, $item); - - // Add the incoming options to existing options because items using - // the extra form may not have everything in the form here. - $options = $form_state['values']['options'] + $form_state['handler']->options; - - // This unpacks only options that are in the definition, ensuring random - // extra stuff on the form is not sent through. - $handler->unpackOptions($handler->options, $options, NULL, FALSE); - - // Store the item back on the view - $executable->setItem($form_state['display_id'], $form_state['type'], $form_state['id'], $handler->options); - - // Ensure any temporary options are removed. - if (isset($form_state['view']->temporary_options[$type][$form_state['id']])) { - unset($form_state['view']->temporary_options[$type][$form_state['id']]); - } - - // Write to cache - views_ui_cache_set($form_state['view']); -} - -/** - * Form to config_item items in the views UI. - */ -function views_ui_config_item_group_form($type, &$form_state) { - $view = &$form_state['view']; - $display_id = $form_state['display_id']; - $type = $form_state['type']; - $id = $form_state['id']; - - $form = array( - 'options' => array( - '#tree' => TRUE, - '#theme_wrappers' => array('container'), - '#attributes' => array('class' => array('scroll')), - ), - ); - $executable = $view->get('executable'); - if (!$executable->setDisplay($display_id)) { - views_ajax_render(t('Invalid display id @display', array('@display' => $display_id))); - } - - $executable->initQuery(); - - $item = $executable->getItem($display_id, $type, $id); - - if ($item) { - $handler = $executable->display_handler->getHandler($type, $id); - if (empty($handler)) { - $form['markup'] = array('#markup' => t("Error: handler for @table > @field doesn't exist!", array('@table' => $item['table'], '@field' => $item['field']))); - } - else { - $handler->init($executable, $executable->display_handler, $item); - $types = ViewExecutable::viewsHandlerTypes(); - - $form['#title'] = t('Configure aggregation settings for @type %item', array('@type' => $types[$type]['lstitle'], '%item' => $handler->adminLabel())); - - $handler->buildGroupByForm($form['options'], $form_state); - $form_state['handler'] = &$handler; - } - - $view->getStandardButtons($form, $form_state, 'views_ui_config_item_group_form'); - } - return $form; -} - -/** - * Submit handler for configing group settings on a view. - */ -function views_ui_config_item_group_form_submit($form, &$form_state) { - $item =& $form_state['handler']->options; - $type = $form_state['type']; - $id = $form_state['id']; - - $handler = views_get_handler($item['table'], $item['field'], $type); - $executable = $form_state['view']->get('executable'); - $handler->init($executable, $executable->display_handler, $item); - - $handler->submitGroupByForm($form, $form_state); - - // Store the item back on the view - $executable->setItem($form_state['display_id'], $form_state['type'], $form_state['id'], $item); - - // Write to cache - views_ui_cache_set($form_state['view']); -} - -/** - * Submit handler for removing an item from a view - */ -function views_ui_config_item_form_remove($form, &$form_state) { - // Store the item back on the view - list($was_defaulted, $is_defaulted) = $form_state['view']->getOverrideValues($form, $form_state); - // If the display selection was changed toggle the override value. - if ($was_defaulted != $is_defaulted) { - $display =& $form_state['view']->get('executable')->displayHandlers->get($form_state['display_id']); - $display->optionsOverride($form, $form_state); - } - $form_state['view']->get('executable')->removeItem($form_state['display_id'], $form_state['type'], $form_state['id']); - - // Write to cache - views_ui_cache_set($form_state['view']); -} - -/** - * Override handler for views_ui_edit_display_form - */ -function views_ui_config_item_form_expose($form, &$form_state) { - $item = &$form_state['handler']->options; - // flip - $item['exposed'] = empty($item['exposed']); - - // If necessary, set new defaults: - if ($item['exposed']) { - $form_state['handler']->defaultExposeOptions(); - } - - $form_state['view']->get('executable')->setItem($form_state['display_id'], $form_state['type'], $form_state['id'], $item); - - $form_state['view']->addFormToStack($form_state['form_key'], $form_state['display_id'], array($form_state['type'], $form_state['id']), TRUE, TRUE); - - views_ui_cache_set($form_state['view']); - $form_state['rerender'] = TRUE; - $form_state['rebuild'] = TRUE; - $form_state['force_expose_options'] = TRUE; -} - -/** - * Form to config_item items in the views UI. - */ -function views_ui_config_item_extra_form($form, &$form_state) { - $view = &$form_state['view']; - $display_id = $form_state['display_id']; - $type = $form_state['type']; - $id = $form_state['id']; - - $form = array( - 'options' => array( - '#tree' => TRUE, - '#theme_wrappers' => array('container'), - '#attributes' => array('class' => array('scroll')), - ), - ); - $executable = $view->get('executable'); - if (!$executable->setDisplay($display_id)) { - views_ajax_error(t('Invalid display id @display', array('@display' => $display_id))); - } - $item = $executable->getItem($display_id, $type, $id); - - if ($item) { - $handler = $executable->display_handler->getHandler($type, $id); - if (empty($handler)) { - $form['markup'] = array('#markup' => t("Error: handler for @table > @field doesn't exist!", array('@table' => $item['table'], '@field' => $item['field']))); - } - else { - $handler->init($executable, $executable->display_handler, $item); - $types = ViewExecutable::viewsHandlerTypes(); - - $form['#title'] = t('Configure extra settings for @type %item', array('@type' => $types[$type]['lstitle'], '%item' => $handler->adminLabel())); - - $form['#section'] = $display_id . '-' . $type . '-' . $id; - - // Get form from the handler. - $handler->buildExtraOptionsForm($form['options'], $form_state); - $form_state['handler'] = &$handler; - } - - $view->getStandardButtons($form, $form_state, 'views_ui_config_item_extra_form'); - } - return $form; -} - -/** - * Validation handler for configing new item(s) to a view. - */ -function views_ui_config_item_extra_form_validate($form, &$form_state) { - $form_state['handler']->validateExtraOptionsForm($form['options'], $form_state); -} - -/** - * Submit handler for configing new item(s) to a view. - */ -function views_ui_config_item_extra_form_submit($form, &$form_state) { - // Run it through the handler's submit function. - $form_state['handler']->submitExtraOptionsForm($form['options'], $form_state); - $item = $form_state['handler']->options; - - // Store the data we're given. - foreach ($form_state['values']['options'] as $key => $value) { - $item[$key] = $value; - } - - // Store the item back on the view - $form_state['view']->get('executable')->setItem($form_state['display_id'], $form_state['type'], $form_state['id'], $item); - - // Write to cache - views_ui_cache_set($form_state['view']); -} - -/** - * Form builder for the admin display defaults page. - */ -function views_ui_admin_settings_basic($form, &$form_state) { - $form = array(); - $form['#attached']['css'] = ViewFormControllerBase::getAdminCSS(); - - $config = config('views.settings'); - - $options = array(); - foreach (list_themes() as $name => $theme) { - if ($theme->status) { - $options[$name] = $theme->info['name']; - } - } - - // This is not currently a fieldset but we may want it to be later, - // so this will make it easier to change if we do. - $form['basic'] = array(); - - $form['basic']['ui_show_master_display'] = array( - '#type' => 'checkbox', - '#title' => t('Always show the master display'), - '#description' => t('Advanced users of views may choose to see the master (i.e. default) display.'), - '#default_value' => $config->get('ui.show.master_display'), - ); - - $form['basic']['ui_show_advanced_column'] = array( - '#type' => 'checkbox', - '#title' => t('Always show advanced display settings'), - '#description' => t('Default to showing advanced display settings, such as relationships and contextual filters.'), - '#default_value' => $config->get('ui.show.advanced_column'), - ); - - $form['basic']['ui_show_display_embed'] = array( - '#type' => 'checkbox', - '#title' => t('Show the embed display in the ui.'), - '#description' => t('Allow advanced user to use the embed view display. The plugin itself works if it\'s not visible in the ui'), - '#default_value' => $config->get('ui.show.display_embed'), - ); - - $form['basic']['ui_exposed_filter_any_label'] = array( - '#type' => 'select', - '#title' => t('Label for "Any" value on non-required single-select exposed filters'), - '#options' => array('old_any' => '', 'new_any' => t('- Any -')), - '#default_value' => $config->get('ui.exposed_filter_any_label'), - ); - - $form['live_preview'] = array( - '#type' => 'details', - '#title' => t('Live preview settings'), - ); - - $form['live_preview']['ui_always_live_preview'] = array( - '#type' => 'checkbox', - '#title' => t('Automatically update preview on changes'), - '#default_value' => $config->get('ui.always_live_preview'), - ); - - $form['live_preview']['ui_show_preview_information'] = array( - '#type' => 'checkbox', - '#title' => t('Show information and statistics about the view during live preview'), - '#default_value' => $config->get('ui.show.preview_information'), - ); - - $form['live_preview']['options'] = array( - '#type' => 'container', - '#states' => array( - 'visible' => array( - ':input[name="ui_show_preview_information"]' => array('checked' => TRUE), - ), - ), - ); - - $form['live_preview']['options']['ui_show_sql_query_where'] = array( - '#type' => 'radios', - '#options' => array( - 'above' => t('Above the preview'), - 'below' => t('Below the preview'), - ), - '#default_value' => $config->get('ui.show.sql_query.where'), - ); - - $form['live_preview']['options']['ui_show_sql_query_enabled'] = array( - '#type' => 'checkbox', - '#title' => t('Show the SQL query'), - '#default_value' => $config->get('ui.show.sql_query.enabled'), - ); - $form['live_preview']['options']['ui_show_performance_statistics'] = array( - '#type' => 'checkbox', - '#title' => t('Show performance statistics'), - '#default_value' => $config->get('ui.show.performance_statistics'), - ); - - $form['live_preview']['options']['ui_show_additional_queries'] = array( - '#type' => 'checkbox', - '#title' => t('Show other queries run during render during live preview'), - '#description' => t("Drupal has the potential to run many queries while a view is being rendered. Checking this box will display every query run during view render as part of the live preview."), - '#default_value' => $config->get('ui.show.additional_queries'), - ); - - return system_config_form($form, $form_state); -} - -/** - * Form builder submit handler; Handle submission the basic views settings. - * @ingroup forms - * @see system_settings_form() - */ -function views_ui_admin_settings_basic_submit(&$form, &$form_state) { - config('views.settings') - ->set('ui.show.master_display', $form_state['values']['ui_show_master_display']) - ->set('ui.show.advanced_column', $form_state['values']['ui_show_advanced_column']) - ->set('ui.show.display_embed', $form_state['values']['ui_show_display_embed']) - ->set('ui.exposed_filter_any_label', $form_state['values']['ui_exposed_filter_any_label']) - ->set('ui.always_live_preview', $form_state['values']['ui_always_live_preview']) - ->set('ui.show.preview_information', $form_state['values']['ui_show_preview_information']) - ->set('ui.show.sql_query.where', $form_state['values']['ui_show_sql_query_where']) - ->set('ui.show.sql_query.enabled', $form_state['values']['ui_show_sql_query_enabled']) - ->set('ui.show.performance_statistics', $form_state['values']['ui_show_performance_statistics']) - ->set('ui.show.additional_queries', $form_state['values']['ui_show_additional_queries']) - ->save(); -} - -/** - * Form builder for the advanced admin settings page. - */ -function views_ui_admin_settings_advanced() { - $form = array(); - $form['#attached']['css'] = ViewFormControllerBase::getAdminCSS(); - - $config = config('views.settings'); - - $form['cache'] = array( - '#type' => 'details', - '#title' => t('Caching'), - ); - - $form['cache']['skip_cache'] = array( - '#type' => 'checkbox', - '#title' => t('Disable views data caching'), - '#description' => t("Views caches data about tables, modules and views available, to increase performance. By checking this box, Views will skip this cache and always rebuild this data when needed. This can have a serious performance impact on your site."), - '#default_value' => $config->get('skip_cache'), - ); - - $form['cache']['clear_cache'] = array( - '#type' => 'submit', - '#value' => t("Clear Views' cache"), - '#submit' => array('views_ui_tools_clear_cache'), - ); - - $form['debug'] = array( - '#type' => 'details', - '#title' => t('Debugging'), - ); - - $form['debug']['sql_signature'] = array( - '#type' => 'checkbox', - '#title' => t('Add Views signature to all SQL queries'), - '#description' => t("All Views-generated queries will include the name of the views and display 'view-name:display-name' as a string at the end of the SELECT clause. This makes identifying Views queries in database server logs simpler, but should only be used when troubleshooting."), - - '#default_value' => $config->get('sql_signature'), - ); - - $form['debug']['no_javascript'] = array( - '#type' => 'checkbox', - '#title' => t('Disable JavaScript with Views'), - '#description' => t("If you are having problems with the JavaScript, you can disable it here. The Views UI should degrade and still be usable without javascript; it's just not as good."), - '#default_value' => $config->get('no_javascript'), - ); - - $options = views_fetch_plugin_names('display_extender'); - if (!empty($options)) { - $form['extenders'] = array( - '#type' => 'details', - ); - ; - $form['extenders']['display_extenders'] = array( - '#title' => t('Display extenders'), - '#default_value' => views_get_enabled_display_extenders(), - '#options' => $options, - '#type' => 'checkboxes', - '#description' => t('Select extensions of the views interface.') - ); - } - - $form['actions']['#type'] = 'actions'; - $form['actions']['submit'] = array( - '#type' => 'submit', - '#value' => t('Save configuration'), - '#button_type' => 'primary', - ); - $form['#submit'][] = 'views_ui_admin_settings_advanced_submit'; - - return $form; -} - -/** - * Form builder submit handler; Handle submission the basic views settings.. - * @ingroup forms - * @see system_settings_form() - */ -function views_ui_admin_settings_advanced_submit(&$form, &$form_state) { - config('views.settings') - ->set('skip_cache', $form_state['values']['skip_cache']) - ->set('sql_signature', $form_state['values']['sql_signature']) - ->set('no_javascript', $form_state['values']['no_javascript']) - ->set('display_extenders', isset($form_state['values']['display_extenders']) ? $form_state['values']['display_extenders'] : array()) - ->save(); -} - -/** - * Submit hook to clear the views cache. - */ -function views_ui_tools_clear_cache() { - views_invalidate_cache(); - drupal_set_message(t('The cache has been cleared.')); -} - -/** - * Submit hook to clear Drupal's theme registry (thereby triggering - * a templates rescan). - */ -function views_ui_config_item_form_rescan($form, &$form_state) { - drupal_theme_rebuild(); - - // The 'Theme: Information' page is about to be shown again. That page - // analyzes the output of theme_get_registry(). However, this latter - // function uses an internal cache (which was initialized before we - // called drupal_theme_rebuild()) so it won't reflect the - // current state of our theme registry. The only way to clear that cache - // is to re-initialize the theme system: - unset($GLOBALS['theme']); - drupal_theme_initialize(); - - $form_state['rerender'] = TRUE; - $form_state['rebuild'] = TRUE; -} - -/** - * Override handler for views_ui_edit_display_form - */ -function views_ui_edit_display_form_change_theme($form, &$form_state) { - // This is just a temporary variable. - $form_state['view']->theme = $form_state['values']['theme']; - - views_ui_cache_set($form_state['view']); - $form_state['rerender'] = TRUE; - $form_state['rebuild'] = TRUE; + return $url; } function _views_sort_types($a, $b) { diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/Form/AddItem.php b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/AddItem.php new file mode 100644 index 0000000..38bf0d0 --- /dev/null +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/AddItem.php @@ -0,0 +1,190 @@ +setType($type); + } + + public function getFormKey() { + return 'add-item'; + } + + public function ajaxForm(ViewStorageInterface $view, $display_id, $js, $type = NULL) { + $this->setType($type); + return parent::ajaxForm($view, $display_id, $js); + } + + /** + * Implements \Drupal\Core\Form\FormInterface::getFormID(). + */ + public function getFormID() { + return 'views_ui_add_item_form'; + } + + /** + * Implements \Drupal\Core\Form\FormInterface::build(). + */ + public function build(array $form, array &$form_state) { + $view = &$form_state['view']; + $display_id = $form_state['display_id']; + $type = $form_state['type']; + + $form = array( + 'options' => array( + '#theme_wrappers' => array('container'), + '#attributes' => array('class' => array('scroll')), + ), + ); + + $executable = $view->get('executable'); + if (!$executable->setDisplay($display_id)) { + views_ajax_error(t('Invalid display id @display', array('@display' => $display_id))); + } + $display = &$executable->displayHandlers->get($display_id); + + $types = ViewExecutable::viewsHandlerTypes(); + $ltitle = $types[$type]['ltitle']; + $section = $types[$type]['plural']; + + if (!empty($types[$type]['type'])) { + $type = $types[$type]['type']; + } + + $form['#title'] = t('Add @type', array('@type' => $ltitle)); + $form['#section'] = $display_id . 'add-item'; + + // Add the display override dropdown. + views_ui_standard_display_dropdown($form, $form_state, $section); + + // Figure out all the base tables allowed based upon what the relationships provide. + $base_tables = $executable->getBaseTables(); + $options = views_fetch_fields(array_keys($base_tables), $type, $display->useGroupBy(), $form_state['type']); + + if (!empty($options)) { + $form['override']['controls'] = array( + '#theme_wrappers' => array('container'), + '#id' => 'views-filterable-options-controls', + '#attributes' => array('class' => array('container-inline')), + ); + $form['override']['controls']['options_search'] = array( + '#type' => 'textfield', + '#title' => t('Search'), + ); + + $groups = array('all' => t('- All -')); + $form['override']['controls']['group'] = array( + '#type' => 'select', + '#title' => t('Type'), + '#options' => array(), + ); + + $form['options']['name'] = array( + '#prefix' => '
', + '#suffix' => '
', + '#tree' => TRUE, + '#default_value' => 'all', + ); + + // Group options first to simplify the usage of #states. + $grouped_options = array(); + foreach ($options as $key => $option) { + $group = preg_replace('/[^a-z0-9]/', '-', strtolower($option['group'])); + $groups[$group] = $option['group']; + $grouped_options[$group][$key] = $option; + if (!empty($option['aliases']) && is_array($option['aliases'])) { + foreach ($option['aliases'] as $id => $alias) { + if (empty($alias['base']) || !empty($base_tables[$alias['base']])) { + $copy = $option; + $copy['group'] = $alias['group']; + $copy['title'] = $alias['title']; + if (isset($alias['help'])) { + $copy['help'] = $alias['help']; + } + + $group = preg_replace('/[^a-z0-9]/', '-', strtolower($copy['group'])); + $groups[$group] = $copy['group']; + $grouped_options[$group][$key . '$' . $id] = $copy; + } + } + } + } + + foreach ($grouped_options as $group => $group_options) { + $zebra = 0; + foreach ($group_options as $key => $option) { + $zebra_class = ($zebra % 2) ? 'odd' : 'even'; + $form['options']['name'][$key] = array( + '#type' => 'checkbox', + '#title' => t('!group: !field', array('!group' => $option['group'], '!field' => $option['title'])), + '#description' => $option['help'], + '#return_value' => $key, + '#prefix' => "
", + '#suffix' => '
', + '#states' => array( + 'visible' => array( + array( + ':input[name="override[controls][group]"]' => array('value' => 'all'), + ), + array( + ':input[name="override[controls][group]"]' => array('value' => $group), + ), + ) + ) + ); + $zebra++; + } + } + + $form['override']['controls']['group']['#options'] = $groups; + } + else { + $form['options']['markup'] = array( + '#markup' => '
' . t('There are no @types available to add.', array('@types' => $ltitle)) . '
', + ); + } + // Add a div to show the selected items + $form['selected'] = array( + '#type' => 'item', + '#markup' => '
', + '#title' => t('Selected') . ':', + '#theme_wrappers' => array('form_element', 'views_ui_container'), + '#attributes' => array('class' => array('container-inline', 'views-add-form-selected')), + ); + $view->getStandardButtons($form, $form_state, 'views_ui_add_item_form', t('Add and configure @types', array('@types' => $ltitle))); + + // Remove the default submit function. + $form['buttons']['submit']['#submit'] = array_filter($form['buttons']['submit']['#submit'], function($var) { + return !(is_array($var) && isset($var[1]) && $var[1] == 'standardSubmit'); + }); + $form['buttons']['submit']['#submit'][] = array($view, 'submitItemAdd'); + + return $form; + } + + /** + * Implements \Drupal\Core\Form\FormInterface::validate(). + */ + public function validate(array &$form, array &$form_state) { + } + + /** + * Implements \Drupal\Core\Form\FormInterface::submit(). + */ + public function submit(array &$form, array &$form_state) { + } + +} diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/Form/Analyze.php b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/Analyze.php new file mode 100644 index 0000000..7a83a37 --- /dev/null +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/Analyze.php @@ -0,0 +1,66 @@ +get('executable')); + $messages = $analyzer->getMessages(); + + $form['analysis'] = array( + '#prefix' => '
', + '#suffix' => '
', + '#markup' => $analyzer->formatMessages($messages), + ); + + // Inform the standard button function that we want an OK button. + $form_state['ok_button'] = TRUE; + $view->getStandardButtons($form, $form_state, 'views_ui_analyze_view_form'); + return $form; + } + + /** + * Implements \Drupal\Core\Form\FormInterface::validate(). + */ + public function validate(array &$form, array &$form_state) { + } + + /** + * Implements \Drupal\Core\Form\FormInterface::submit(). + */ + public function submit(array &$form, array &$form_state) { + $form_state['redirect'] = 'admin/structure/views/view/' . $form_state['view']->id() . '/edit'; + } + +} diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ConfigItem.php b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ConfigItem.php new file mode 100644 index 0000000..34fc7e9 --- /dev/null +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ConfigItem.php @@ -0,0 +1,237 @@ +setType($type); + $this->setID($id); + } + + public function getFormKey() { + return 'config-item'; + } + + public function ajaxForm(ViewStorageInterface $view, $display_id, $js, $type = NULL, $id = NULL) { + $this->setType($type); + $this->setID($id); + return parent::ajaxForm($view, $display_id, $js); + } + + /** + * Implements \Drupal\Core\Form\FormInterface::getFormID(). + */ + public function getFormID() { + return 'views_ui_config_item_form'; + } + + /** + * Implements \Drupal\Core\Form\FormInterface::build(). + */ + public function build(array $form, array &$form_state) { + $view = &$form_state['view']; + $display_id = $form_state['display_id']; + $type = $form_state['type']; + $id = $form_state['id']; + + $form = array( + 'options' => array( + '#tree' => TRUE, + '#theme_wrappers' => array('container'), + '#attributes' => array('class' => array('scroll')), + ), + ); + $executable = $view->get('executable'); + $save_ui_cache = FALSE; + if (!$executable->setDisplay($display_id)) { + views_ajax_error(t('Invalid display id @display', array('@display' => $display_id))); + } + $item = $executable->getItem($display_id, $type, $id); + + if ($item) { + $handler = $executable->display_handler->getHandler($type, $id); + if (empty($handler)) { + $form['markup'] = array('#markup' => t("Error: handler for @table > @field doesn't exist!", array('@table' => $item['table'], '@field' => $item['field']))); + } + else { + $types = ViewExecutable::viewsHandlerTypes(); + + // If this item can come from the default display, show a dropdown + // that lets the user choose which display the changes should apply to. + if ($executable->display_handler->defaultableSections($types[$type]['plural'])) { + $form_state['section'] = $types[$type]['plural']; + views_ui_standard_display_dropdown($form, $form_state, $form_state['section']); + } + + // A whole bunch of code to figure out what relationships are valid for + // this item. + $relationships = $executable->display_handler->getOption('relationships'); + $relationship_options = array(); + + foreach ($relationships as $relationship) { + // relationships can't link back to self. But also, due to ordering, + // relationships can only link to prior relationships. + if ($type == 'relationship' && $id == $relationship['id']) { + break; + } + $relationship_handler = views_get_handler($relationship['table'], $relationship['field'], 'relationship'); + // ignore invalid/broken relationships. + if (empty($relationship_handler)) { + continue; + } + + // If this relationship is valid for this type, add it to the list. + $data = drupal_container()->get('views.views_data')->get($relationship['table']); + $base = $data[$relationship['field']]['relationship']['base']; + $base_fields = views_fetch_fields($base, $form_state['type'], $executable->display_handler->useGroupBy()); + if (isset($base_fields[$item['table'] . '.' . $item['field']])) { + $relationship_handler->init($executable, $executable->display_handler, $relationship); + $relationship_options[$relationship['id']] = $relationship_handler->label(); + } + } + + if (!empty($relationship_options)) { + // Make sure the existing relationship is even valid. If not, force + // it to none. + $base_fields = views_fetch_fields($view->get('base_table'), $form_state['type'], $executable->display_handler->useGroupBy()); + if (isset($base_fields[$item['table'] . '.' . $item['field']])) { + $relationship_options = array_merge(array('none' => t('Do not use a relationship')), $relationship_options); + } + $rel = empty($item['relationship']) ? 'none' : $item['relationship']; + if (empty($relationship_options[$rel])) { + // Pick the first relationship. + $rel = key($relationship_options); + // We want this relationship option to get saved even if the user + // skips submitting the form. + $executable->setItemOption($display_id, $type, $id, 'relationship', $rel); + $save_ui_cache = TRUE; + } + + $form['options']['relationship'] = array( + '#type' => 'select', + '#title' => t('Relationship'), + '#options' => $relationship_options, + '#default_value' => $rel, + '#weight' => -500, + ); + } + else { + $form['options']['relationship'] = array( + '#type' => 'value', + '#value' => 'none', + ); + } + + $form['#title'] = t('Configure @type: @item', array('@type' => $types[$type]['lstitle'], '@item' => $handler->adminLabel())); + + if (!empty($handler->definition['help'])) { + $form['options']['form_description'] = array( + '#markup' => $handler->definition['help'], + '#theme_wrappers' => array('container'), + '#attributes' => array('class' => array('form-item description')), + '#weight' => -1000, + ); + } + + $form['#section'] = $display_id . '-' . $type . '-' . $id; + + // Get form from the handler. + $handler->buildOptionsForm($form['options'], $form_state); + $form_state['handler'] = &$handler; + } + + $name = NULL; + if (isset($form_state['update_name'])) { + $name = $form_state['update_name']; + } + + $view->getStandardButtons($form, $form_state, 'views_ui_config_item_form', $name, t('Remove'), 'remove'); + // Only validate the override values, because this values are required for + // the override selection. + $form['buttons']['remove']['#limit_validation_errors'] = array(array('override')); + } + + if ($save_ui_cache) { + views_ui_cache_set($view); + } + + return $form; + } + + /** + * Implements \Drupal\Core\Form\FormInterface::validate(). + */ + public function validate(array &$form, array &$form_state) { + $form_state['handler']->validateOptionsForm($form['options'], $form_state); + + if (form_get_errors()) { + $form_state['rerender'] = TRUE; + } + } + + /** + * Implements \Drupal\Core\Form\FormInterface::submit(). + */ + public function submit(array &$form, array &$form_state) { + // Run it through the handler's submit function. + $form_state['handler']->submitOptionsForm($form['options'], $form_state); + $item = $form_state['handler']->options; + $types = ViewExecutable::viewsHandlerTypes(); + + // For footer/header $handler_type is area but $type is footer/header. + // For all other handle types it's the same. + $handler_type = $type = $form_state['type']; + if (!empty($types[$type]['type'])) { + $handler_type = $types[$type]['type']; + } + + $override = NULL; + $executable = $form_state['view']->get('executable'); + if ($executable->display_handler->useGroupBy() && !empty($item['group_type'])) { + if (empty($executable->query)) { + $executable->initQuery(); + } + $aggregate = $executable->query->get_aggregation_info(); + if (!empty($aggregate[$item['group_type']]['handler'][$type])) { + $override = $aggregate[$item['group_type']]['handler'][$type]; + } + } + + // Create a new handler and unpack the options from the form onto it. We + // can use that for storage. + $handler = views_get_handler($item['table'], $item['field'], $handler_type, $override); + $handler->init($executable, $executable->display_handler, $item); + + // Add the incoming options to existing options because items using + // the extra form may not have everything in the form here. + $options = $form_state['values']['options'] + $form_state['handler']->options; + + // This unpacks only options that are in the definition, ensuring random + // extra stuff on the form is not sent through. + $handler->unpackOptions($handler->options, $options, NULL, FALSE); + + // Store the item back on the view + $executable->setItem($form_state['display_id'], $form_state['type'], $form_state['id'], $handler->options); + + // Ensure any temporary options are removed. + if (isset($form_state['view']->temporary_options[$type][$form_state['id']])) { + unset($form_state['view']->temporary_options[$type][$form_state['id']]); + } + + // Write to cache + views_ui_cache_set($form_state['view']); + } + +} diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ConfigItemExtra.php b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ConfigItemExtra.php new file mode 100644 index 0000000..5c4515e --- /dev/null +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ConfigItemExtra.php @@ -0,0 +1,112 @@ +setType($type); + $this->setID($id); + } + + public function getFormKey() { + return 'config-item-extra'; + } + + public function ajaxForm(ViewStorageInterface $view, $display_id, $js, $type = NULL, $id = NULL) { + $this->setType($type); + $this->setID($id); + return parent::ajaxForm($view, $display_id, $js); + } + + /** + * Implements \Drupal\Core\Form\FormInterface::getFormID(). + */ + public function getFormID() { + return 'views_ui_config_item_extra_form'; + } + + /** + * Implements \Drupal\Core\Form\FormInterface::build(). + */ + public function build(array $form, array &$form_state) { + $view = &$form_state['view']; + $display_id = $form_state['display_id']; + $type = $form_state['type']; + $id = $form_state['id']; + + $form = array( + 'options' => array( + '#tree' => true, + '#theme_wrappers' => array('container'), + '#attributes' => array('class' => array('scroll')), + ), + ); + $executable = $view->get('executable'); + if (!$executable->setDisplay($display_id)) { + views_ajax_error(t('invalid display id @display', array('@display' => $display_id))); + } + $item = $executable->getItem($display_id, $type, $id); + + if ($item) { + $handler = $executable->display_handler->getHandler($type, $id); + if (empty($handler)) { + $form['markup'] = array('#markup' => t("Error: handler for @table > @field doesn't exist!", array('@table' => $item['table'], '@field' => $item['field']))); + } + else { + $handler->init($executable, $executable->display_handler, $item); + $types = ViewExecutable::viewsHandlerTypes(); + + $form['#title'] = t('Configure extra settings for @type %item', array('@type' => $types[$type]['lstitle'], '%item' => $handler->adminLabel())); + + $form['#section'] = $display_id . '-' . $type . '-' . $id; + + // Get form from the handler. + $handler->buildExtraOptionsForm($form['options'], $form_state); + $form_state['handler'] = &$handler; + } + + $view->getStandardButtons($form, $form_state, 'views_ui_config_item_extra_form'); + } + return $form; + } + + /** + * Implements \Drupal\Core\Form\FormInterface::validate(). + */ + public function validate(array &$form, array &$form_state) { + $form_state['handler']->validateExtraOptionsForm($form['options'], $form_state); + } + + /** + * Implements \Drupal\Core\Form\FormInterface::submit(). + */ + public function submit(array &$form, array &$form_state) { + // Run it through the handler's submit function. + $form_state['handler']->submitExtraOptionsForm($form['options'], $form_state); + $item = $form_state['handler']->options; + + // Store the data we're given. + foreach ($form_state['values']['options'] as $key => $value) { + $item[$key] = $value; + } + + // Store the item back on the view + $form_state['view']->get('executable')->setItem($form_state['display_id'], $form_state['type'], $form_state['id'], $item); + + // Write to cache + views_ui_cache_set($form_state['view']); + } + +} diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ConfigItemGroup.php b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ConfigItemGroup.php new file mode 100644 index 0000000..2fd7337 --- /dev/null +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ConfigItemGroup.php @@ -0,0 +1,112 @@ +setType($type); + $this->setID($id); + } + + public function getFormKey() { + return 'config-item-group'; + } + + public function ajaxForm(ViewStorageInterface $view, $display_id, $js, $type = NULL, $id = NULL) { + $this->setType($type); + $this->setID($id); + return parent::ajaxForm($view, $display_id, $js); + } + + /** + * Implements \Drupal\Core\Form\FormInterface::getFormID(). + */ + public function getFormID() { + return 'views_ui_config_item_group_form'; + } + + /** + * Implements \Drupal\Core\Form\FormInterface::build(). + */ + public function build(array $form, array &$form_state) { + $view = &$form_state['view']; + $display_id = $form_state['display_id']; + $type = $form_state['type']; + $id = $form_state['id']; + + $form = array( + 'options' => array( + '#tree' => TRUE, + '#theme_wrappers' => array('container'), + '#attributes' => array('class' => array('scroll')), + ), + ); + $executable = $view->get('executable'); + if (!$executable->setDisplay($display_id)) { + views_ajax_render(t('Invalid display id @display', array('@display' => $display_id))); + } + + $executable->initQuery(); + + $item = $executable->getItem($display_id, $type, $id); + + if ($item) { + $handler = $executable->display_handler->getHandler($type, $id); + if (empty($handler)) { + $form['markup'] = array('#markup' => t("Error: handler for @table > @field doesn't exist!", array('@table' => $item['table'], '@field' => $item['field']))); + } + else { + $handler->init($executable, $executable->display_handler, $item); + $types = ViewExecutable::viewsHandlerTypes(); + + $form['#title'] = t('Configure aggregation settings for @type %item', array('@type' => $types[$type]['lstitle'], '%item' => $handler->adminLabel())); + + $handler->buildGroupByForm($form['options'], $form_state); + $form_state['handler'] = &$handler; + } + + $view->getStandardButtons($form, $form_state, 'views_ui_config_item_group_form'); + } + return $form; + } + + /** + * Implements \Drupal\Core\Form\FormInterface::validate(). + */ + public function validate(array &$form, array &$form_state) { + } + + /** + * Implements \Drupal\Core\Form\FormInterface::submit(). + */ + public function submit(array &$form, array &$form_state) { + $item = &$form_state['handler']->options; + $type = $form_state['type']; + $id = $form_state['id']; + + $handler = views_get_handler($item['table'], $item['field'], $type); + $executable = $form_state['view']->get('executable'); + $handler->init($executable, $executable->display_handler, $item); + + $handler->submitGroupByForm($form, $form_state); + + // Store the item back on the view + $executable->setItem($form_state['display_id'], $form_state['type'], $form_state['id'], $item); + + // Write to cache + views_ui_cache_set($form_state['view']); + } + +} diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/Form/Display.php b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/Display.php new file mode 100644 index 0000000..c88dd09 --- /dev/null +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/Display.php @@ -0,0 +1,110 @@ +setType($type); + } + + public function getFormKey() { + return 'display'; + } + + /** + * Overrides ViewsFormBase::getFormState(). + * + * @todo Remove this and switch all usage of $form_state['section'] to + * $form_state['type']. + */ + public function getFormState(ViewStorageInterface $view, $display_id, $js) { + return array( + 'section' => $this->type, + ) + parent::getFormState($view, $display_id, $js); + } + + public function ajaxForm(ViewStorageInterface $view, $display_id, $js, $type = NULL) { + $this->setType($type); + return parent::ajaxForm($view, $display_id, $js); + } + + /** + * Implements \Drupal\Core\Form\FormInterface::getFormID(). + */ + public function getFormID() { + return 'views_ui_edit_display_form'; + } + + /** + * Implements \Drupal\Core\Form\FormInterface::build(). + */ + public function build(array $form, array &$form_state) { + $view = &$form_state['view']; + $display_id = $form_state['display_id']; + $section = $form_state['section']; + + $executable = $view->get('executable'); + if (!$executable->setDisplay($display_id)) { + views_ajax_error(t('Invalid display id @display', array('@display' => $display_id))); + } + $display = &$executable->display[$display_id]; + + // Get form from the handler. + $form['options'] = array( + '#theme_wrappers' => array('container'), + '#attributes' => array('class' => array('scroll')), + ); + $executable->display_handler->buildOptionsForm($form['options'], $form_state); + + // The handler options form sets $form['#title'], which we need on the entire + // $form instead of just the ['options'] section. + $form['#title'] = $form['options']['#title']; + unset($form['options']['#title']); + + // Move the override dropdown out of the scrollable section of the form. + if (isset($form['options']['override'])) { + $form['override'] = $form['options']['override']; + unset($form['options']['override']); + } + + $name = NULL; + if (isset($form_state['update_name'])) { + $name = $form_state['update_name']; + } + + $view->getStandardButtons($form, $form_state, 'views_ui_edit_display_form', $name); + return $form; + } + + /** + * Implements \Drupal\Core\Form\FormInterface::validate(). + */ + public function validate(array &$form, array &$form_state) { + $form_state['view']->get('executable')->displayHandlers->get($form_state['display_id'])->validateOptionsForm($form['options'], $form_state); + + if (form_get_errors()) { + $form_state['rerender'] = TRUE; + } + } + + /** + * Implements \Drupal\Core\Form\FormInterface::submit(). + */ + public function submit(array &$form, array &$form_state) { + $form_state['view']->get('executable')->displayHandlers->get($form_state['display_id'])->submitOptionsForm($form['options'], $form_state); + + views_ui_cache_set($form_state['view']); + } + +} diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/Form/EditDetails.php b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/EditDetails.php new file mode 100644 index 0000000..4d0cb7f --- /dev/null +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/EditDetails.php @@ -0,0 +1,91 @@ + array('container'), + '#attributes' => array('class' => array('scroll')), + ); + $form['details']['human_name'] = array( + '#type' => 'textfield', + '#title' => t('Human-readable name'), + '#description' => t('A descriptive human-readable name for this view. Spaces are allowed'), + '#default_value' => $view->getHumanName(), + ); + $form['details']['tag'] = array( + '#type' => 'textfield', + '#title' => t('View tag'), + '#description' => t('Optionally, enter a comma delimited list of tags for this view to use in filtering and sorting views on the administrative page.'), + '#default_value' => $view->get('tag'), + '#autocomplete_path' => 'admin/views/ajax/autocomplete/tag', + ); + $form['details']['description'] = array( + '#type' => 'textfield', + '#title' => t('View description'), + '#description' => t('This description will appear on the Views administrative UI to tell you what the view is about.'), + '#default_value' => $view->get('description'), + ); + + $view->getStandardButtons($form, $form_state, 'views_ui_edit_details_form'); + return $form; + } + + /** + * Implements \Drupal\Core\Form\FormInterface::validate(). + */ + public function validate(array &$form, array &$form_state) { + } + + /** + * Implements \Drupal\Core\Form\FormInterface::submit(). + */ + public function submit(array &$form, array &$form_state) { + $view = $form_state['view']; + foreach ($form_state['values'] as $key => $value) { + // Only save values onto the view if they're actual view properties + // (as opposed to 'op' or 'form_build_id'). + if (isset($form['details'][$key])) { + $view->set($key, $value); + } + } + $bases = drupal_container()->get('views.views_data')->fetchBaseTables(); + $form_state['#page_title'] = $view->getHumanName(); + if (isset($bases[$view->get('base_table')])) { + $form_state['#page_title'] .= ' (' . $bases[$view->get('base_table')]['title'] . ')'; + } + views_ui_cache_set($view); + } + +} diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/Form/Rearrange.php b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/Rearrange.php new file mode 100644 index 0000000..4ad8b5d --- /dev/null +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/Rearrange.php @@ -0,0 +1,164 @@ +setType($type); + } + + public function getFormKey() { + return 'rearrange'; + } + + public function ajaxForm(ViewStorageInterface $view, $display_id, $js, $type = NULL) { + $this->setType($type); + return parent::ajaxForm($view, $display_id, $js); + } + + /** + * Implements \Drupal\Core\Form\FormInterface::getFormID(). + */ + public function getFormID() { + return 'views_ui_rearrange_form'; + } + + /** + * Implements \Drupal\Core\Form\FormInterface::build(). + */ + public function build(array $form, array &$form_state) { + $view = &$form_state['view']; + $display_id = $form_state['display_id']; + $type = $form_state['type']; + + $types = ViewExecutable::viewsHandlerTypes(); + $executable = $view->get('executable'); + if (!$executable->setDisplay($display_id)) { + views_ajax_error(t('Invalid display id @display', array('@display' => $display_id))); + } + $display = &$executable->displayHandlers->get($display_id); + $form['#title'] = t('Rearrange @type', array('@type' => $types[$type]['ltitle'])); + $form['#section'] = $display_id . 'rearrange-item'; + + if ($display->defaultableSections($types[$type]['plural'])) { + $form_state['section'] = $types[$type]['plural']; + views_ui_standard_display_dropdown($form, $form_state, $form_state['section']); + } + + $count = 0; + + // Get relationship labels + $relationships = array(); + foreach ($display->getHandlers('relationship') as $id => $handler) { + $relationships[$id] = $handler->label(); + } + + // Filters can now be grouped so we do a little bit extra: + $groups = array(); + $grouping = FALSE; + if ($type == 'filter') { + $group_info = $executable->display_handler->getOption('filter_groups'); + if (!empty($group_info['groups']) && count($group_info['groups']) > 1) { + $grouping = TRUE; + $groups = array(0 => array()); + } + } + + foreach ($display->getOption($types[$type]['plural']) as $id => $field) { + $form['fields'][$id] = array('#tree' => TRUE); + $form['fields'][$id]['weight'] = array( + '#type' => 'textfield', + '#default_value' => ++$count, + ); + $handler = $display->getHandler($type, $id); + if ($handler) { + $name = $handler->adminLabel() . ' ' . $handler->adminSummary(); + if (!empty($field['relationship']) && !empty($relationships[$field['relationship']])) { + $name = '(' . $relationships[$field['relationship']] . ') ' . $name; + } + + $form['fields'][$id]['name'] = array( + '#markup' => $name, + ); + } + else { + $form['fields'][$id]['name'] = array('#markup' => t('Broken field @id', array('@id' => $id))); + } + $form['fields'][$id]['removed'] = array( + '#type' => 'checkbox', + '#id' => 'views-removed-' . $id, + '#attributes' => array('class' => array('views-remove-checkbox')), + '#default_value' => 0, + ); + } + + // Add javascript settings that will be added via $.extend for tabledragging + $form['#js']['tableDrag']['arrange']['weight'][0] = array( + 'target' => 'weight', + 'source' => NULL, + 'relationship' => 'sibling', + 'action' => 'order', + 'hidden' => TRUE, + 'limit' => 0, + ); + + $name = NULL; + if (isset($form_state['update_name'])) { + $name = $form_state['update_name']; + } + + $view->getStandardButtons($form, $form_state, 'views_ui_rearrange_form'); + return $form; + } + + /** + * Implements \Drupal\Core\Form\FormInterface::validate(). + */ + public function validate(array &$form, array &$form_state) { + } + + /** + * Implements \Drupal\Core\Form\FormInterface::submit(). + */ + public function submit(array &$form, array &$form_state) { + $types = ViewExecutable::viewsHandlerTypes(); + $display = &$form_state['view']->get('executable')->displayHandlers->get($form_state['display_id']); + + $old_fields = $display->getOption($types[$form_state['type']]['plural']); + $new_fields = $order = array(); + + // Make an array with the weights + foreach ($form_state['values'] as $field => $info) { + // add each value that is a field with a weight to our list, but only if + // it has had its 'removed' checkbox checked. + if (is_array($info) && isset($info['weight']) && empty($info['removed'])) { + $order[$field] = $info['weight']; + } + } + + // Sort the array + asort($order); + + // Create a new list of fields in the new order. + foreach (array_keys($order) as $field) { + $new_fields[$field] = $old_fields[$field]; + } + $display->setOption($types[$form_state['type']]['plural'], $new_fields); + + // Store in cache + views_ui_cache_set($form_state['view']); + } + +} diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/Form/RearrangeFilter.php b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/RearrangeFilter.php new file mode 100644 index 0000000..e9b65e0 --- /dev/null +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/RearrangeFilter.php @@ -0,0 +1,321 @@ +get('executable'); + if (!$executable->setDisplay($display_id)) { + views_ajax_render(t('Invalid display id @display', array('@display' => $display_id))); + } + $display = $executable->displayHandlers->get($display_id); + $form['#title'] = check_plain($display->display['display_title']) . ': '; + $form['#title'] .= t('Rearrange @type', array('@type' => $types[$type]['ltitle'])); + $form['#section'] = $display_id . 'rearrange-item'; + + if ($display->defaultableSections($types[$type]['plural'])) { + $form_state['section'] = $types[$type]['plural']; + views_ui_standard_display_dropdown($form, $form_state, $form_state['section']); + } + + if (!empty($view->form_cache)) { + $groups = $view->form_cache['groups']; + $handlers = $view->form_cache['handlers']; + } + else { + $groups = $display->getOption('filter_groups'); + $handlers = $display->getOption($types[$type]['plural']); + } + $count = 0; + + // Get relationship labels + $relationships = array(); + foreach ($display->getHandlers('relationship') as $id => $handler) { + $relationships[$id] = $handler->label(); + } + + $group_options = array(); + + /** + * Filter groups is an array that contains: + * array( + * 'operator' => 'and' || 'or', + * 'groups' => array( + * $group_id => 'and' || 'or', + * ), + * ); + */ + + $grouping = count(array_keys($groups['groups'])) > 1; + + $form['filter_groups']['#tree'] = TRUE; + $form['filter_groups']['operator'] = array( + '#type' => 'select', + '#options' => array( + 'AND' => t('And'), + 'OR' => t('Or'), + ), + '#default_value' => $groups['operator'], + '#attributes' => array( + 'class' => array('warning-on-change'), + ), + '#title' => t('Operator to use on all groups'), + '#description' => t('Either "group 0 AND group 1 AND group 2" or "group 0 OR group 1 OR group 2", etc'), + '#access' => $grouping, + ); + + $form['remove_groups']['#tree'] = TRUE; + + foreach ($groups['groups'] as $id => $group) { + $form['filter_groups']['groups'][$id] = array( + '#title' => t('Operator'), + '#type' => 'select', + '#options' => array( + 'AND' => t('And'), + 'OR' => t('Or'), + ), + '#default_value' => $group, + '#attributes' => array( + 'class' => array('warning-on-change'), + ), + ); + + $form['remove_groups'][$id] = array(); // to prevent a notice + if ($id != 1) { + $form['remove_groups'][$id] = array( + '#type' => 'submit', + '#value' => t('Remove group @group', array('@group' => $id)), + '#id' => "views-remove-group-$id", + '#attributes' => array( + 'class' => array('views-remove-group'), + ), + '#group' => $id, + ); + } + $group_options[$id] = $id == 1 ? t('Default group') : t('Group @group', array('@group' => $id)); + $form['#group_renders'][$id] = array(); + } + + $form['#group_options'] = $group_options; + $form['#groups'] = $groups; + // We don't use getHandlers() because we want items without handlers to + // appear and show up as 'broken' so that the user can see them. + $form['filters'] = array('#tree' => TRUE); + foreach ($handlers as $id => $field) { + // If the group does not exist, move the filters to the default group. + if (empty($field['group']) || empty($groups['groups'][$field['group']])) { + $field['group'] = 1; + } + + $handler = $display->getHandler($type, $id); + if ($grouping && $handler && !$handler->can_group()) { + $field['group'] = 'ungroupable'; + } + + // If not grouping and the handler is set ungroupable, move it back to + // the default group to prevent weird errors from having it be in its + // own group: + if (!$grouping && $field['group'] == 'ungroupable') { + $field['group'] = 1; + } + + // Place this item into the proper group for rendering. + $form['#group_renders'][$field['group']][] = $id; + + $form['filters'][$id]['weight'] = array( + '#type' => 'textfield', + '#default_value' => ++$count, + '#size' => 8, + ); + $form['filters'][$id]['group'] = array( + '#type' => 'select', + '#options' => $group_options, + '#default_value' => $field['group'], + '#attributes' => array( + 'class' => array('views-region-select', 'views-region-' . $id), + ), + '#access' => $field['group'] !== 'ungroupable', + ); + + if ($handler) { + $name = $handler->adminLabel() . ' ' . $handler->adminSummary(); + if (!empty($field['relationship']) && !empty($relationships[$field['relationship']])) { + $name = '(' . $relationships[$field['relationship']] . ') ' . $name; + } + + $form['filters'][$id]['name'] = array( + '#markup' => $name, + ); + } + else { + $form['filters'][$id]['name'] = array('#markup' => t('Broken field @id', array('@id' => $id))); + } + $form['filters'][$id]['removed'] = array( + '#type' => 'checkbox', + '#id' => 'views-removed-' . $id, + '#attributes' => array('class' => array('views-remove-checkbox')), + '#default_value' => 0, + ); + } + + if (isset($form_state['update_name'])) { + $name = $form_state['update_name']; + } + + $view->getStandardButtons($form, $form_state, 'views_ui_rearrange_filter_form'); + $form['buttons']['add_group'] = array( + '#type' => 'submit', + '#value' => t('Create new filter group'), + '#id' => 'views-add-group', + '#group' => 'add', + ); + + return $form; + } + + /** + * Implements \Drupal\Core\Form\FormInterface::validate(). + */ + public function validate(array &$form, array &$form_state) { + } + + /** + * Implements \Drupal\Core\Form\FormInterface::submit(). + */ + public function submit(array &$form, array &$form_state) { + $types = ViewExecutable::viewsHandlerTypes(); + $display = &$form_state['view']->get('executable')->displayHandlers->get($form_state['display_id']); + $remember_groups = array(); + + if (!empty($form_state['view']->form_cache)) { + $old_fields = $form_state['view']->form_cache['handlers']; + } + else { + $old_fields = $display->getOption($types['filter']['plural']); + } + $count = 0; + + $groups = $form_state['values']['filter_groups']; + // Whatever button was clicked, re-calculate field information. + $new_fields = $order = array(); + + // Make an array with the weights + foreach ($form_state['values']['filters'] as $field => $info) { + // add each value that is a field with a weight to our list, but only if + // it has had its 'removed' checkbox checked. + if (is_array($info) && empty($info['removed'])) { + if (isset($info['weight'])) { + $order[$field] = $info['weight']; + } + + if (isset($info['group'])) { + $old_fields[$field]['group'] = $info['group']; + $remember_groups[$info['group']][] = $field; + } + } + } + + // Sort the array + asort($order); + + // Create a new list of fields in the new order. + foreach (array_keys($order) as $field) { + $new_fields[$field] = $old_fields[$field]; + } + + // If the #group property is set on the clicked button, that means we are + // either adding or removing a group, not actually updating the filters. + if (!empty($form_state['clicked_button']['#group'])) { + if ($form_state['clicked_button']['#group'] == 'add') { + // Add a new group + $groups['groups'][] = 'AND'; + } + else { + // Renumber groups above the removed one down. + foreach (array_keys($groups['groups']) as $group_id) { + if ($group_id >= $form_state['clicked_button']['#group']) { + $old_group = $group_id + 1; + if (isset($groups['groups'][$old_group])) { + $groups['groups'][$group_id] = $groups['groups'][$old_group]; + if (isset($remember_groups[$old_group])) { + foreach ($remember_groups[$old_group] as $id) { + $new_fields[$id]['group'] = $group_id; + } + } + } + else { + // If this is the last one, just unset it. + unset($groups['groups'][$group_id]); + } + } + } + } + // Update our cache with values so that cancel still works the way + // people expect. + $form_state['view']->form_cache = array( + 'key' => 'rearrange-filter', + 'groups' => $groups, + 'handlers' => $new_fields, + ); + + // Return to this form except on actual Update. + $form_state['view']->addFormToStack('rearrange-filter', $form_state['display_id'], 'filter'); + } + else { + // The actual update button was clicked. Remove the empty groups, and + // renumber them sequentially. + ksort($remember_groups); + $groups['groups'] = views_array_key_plus(array_values(array_intersect_key($groups['groups'], $remember_groups))); + // Change the 'group' key on each field to match. Here, $mapping is an + // array whose keys are the old group numbers and whose values are the new + // (sequentially numbered) ones. + $mapping = array_flip(views_array_key_plus(array_keys($remember_groups))); + foreach ($new_fields as &$new_field) { + $new_field['group'] = $mapping[$new_field['group']]; + } + + // Write the changed handler values. + $display->setOption($types['filter']['plural'], $new_fields); + $display->setOption('filter_groups', $groups); + if (isset($form_state['view']->form_cache)) { + unset($form_state['view']->form_cache); + } + } + + // Store in cache. + views_ui_cache_set($form_state['view']); + } + +} + diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ReorderDisplays.php b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ReorderDisplays.php new file mode 100644 index 0000000..cf228c7 --- /dev/null +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ReorderDisplays.php @@ -0,0 +1,143 @@ + 'value', '#value' => $view); + + $form['#tree'] = TRUE; + + $count = count($view->get('display')); + + $displays = $view->get('display'); + foreach ($displays as $display) { + $form[$display['id']] = array( + 'title' => array('#markup' => $display['display_title']), + 'weight' => array( + '#type' => 'weight', + '#value' => $display['position'], + '#delta' => $count, + '#title' => t('Weight for @display', array('@display' => $display['display_title'])), + '#title_display' => 'invisible', + ), + '#tree' => TRUE, + '#display' => $display, + 'removed' => array( + '#type' => 'checkbox', + '#id' => 'display-removed-' . $display['id'], + '#attributes' => array('class' => array('views-remove-checkbox')), + '#default_value' => isset($display['deleted']), + ), + ); + + if (isset($display['deleted']) && $display['deleted']) { + $form[$display['id']]['deleted'] = array('#type' => 'value', '#value' => TRUE); + } + if ($display['id'] === 'default') { + unset($form[$display['id']]['weight']); + unset($form[$display['id']]['removed']); + } + + } + + $form['#title'] = t('Displays Reorder'); + $form['#section'] = 'reorder'; + + // Add javascript settings that will be added via $.extend for tabledragging + $form['#js']['tableDrag']['reorder-displays']['weight'][0] = array( + 'target' => 'weight', + 'source' => NULL, + 'relationship' => 'sibling', + 'action' => 'order', + 'hidden' => TRUE, + 'limit' => 0, + ); + + $form['#action'] = url('admin/structure/views/nojs/reorder-displays/' . $view->id() . '/' . $display_id); + + $view->getStandardButtons($form, $form_state, 'views_ui_reorder_displays_form'); + + return $form; + } + + /** + * Implements \Drupal\Core\Form\FormInterface::validate(). + */ + public function validate(array &$form, array &$form_state) { + } + + /** + * Implements \Drupal\Core\Form\FormInterface::submit(). + */ + public function submit(array &$form, array &$form_state) { + $view = $form_state['view']; + foreach ($form_state['input'] as $display => $info) { + // add each value that is a field with a weight to our list, but only if + // it has had its 'removed' checkbox checked. + if (is_array($info) && isset($info['weight']) && empty($info['removed'])) { + $order[$display] = $info['weight']; + } + } + + // Sort the order array + asort($order); + + // Fixing up positions + $position = 1; + + foreach (array_keys($order) as $display) { + $order[$display] = $position++; + } + + // Setting up position and removing deleted displays + $displays = $view->get('display'); + foreach ($displays as $display_id => $display) { + // Don't touch the default !!! + if ($display_id === 'default') { + $displays[$display_id]['position'] = 0; + continue; + } + if (isset($order[$display_id])) { + $displays[$display_id]['position'] = $order[$display_id]; + } + else { + $displays[$display_id]['deleted'] = TRUE; + } + } + $view->set('display', $displays); + + // Store in cache + views_ui_cache_set($view); + $form_state['redirect'] = array('admin/structure/views/view/' . $view->id() . '/edit', array('fragment' => 'views-tab-default')); + } + +} diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ViewsFormBase.php b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ViewsFormBase.php new file mode 100644 index 0000000..ff23906 --- /dev/null +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ViewsFormBase.php @@ -0,0 +1,209 @@ +id = $id; + } + } + + protected function setType($type) { + if ($type) { + $this->type = $type; + } + } + + public function getFormState(ViewStorageInterface $view, $display_id, $js) { + // $js may already have been converted to a Boolean. + $ajax = is_string($js) ? $js === 'ajax' : $js; + return array( + 'form_id' => $this->getFormID(), + 'form_key' => $this->getFormKey(), + 'ajax' => $ajax, + 'display_id' => $display_id, + 'view' => $this->getViewUI($view), + 'type' => $this->type, + 'id' => $this->id, + 'no_redirect' => TRUE, + 'build_info' => array( + 'args' => array(), + 'callback_object' => $this, + ), + ); + } + + /** + * 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 string $key + * A string representing a section of the Views UI. + * @param \Drupal\views\ViewStorageInterface $view + * The view being edited. + * @param string|null $display_id + * The display ID being edited, or NULL to load the first available display. + * @param string|null $type + * If $key is 'add-item' or 'config-item', this is the type of handler 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 + * 'style' as a handler type. 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. + * Otherwise it will be NULL. + * + * @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. + */ + public function ajaxForm(ViewStorageInterface $view, $display_id, $js) { + $form_state = $this->getFormState($view, $display_id, $js); + $view = $form_state['view']; + $key = $form_state['form_key']; + + // @todo Remove the need for this. + module_load_include('inc', 'views_ui', 'admin'); + module_load_include('inc', 'views', 'includes/ajax'); + + // Reset the cache of IDs. Drupal rather aggressively prevents ID + // duplication but this causes it to remember IDs that are no longer even + // being used. + $seen_ids_init = &drupal_static('drupal_html_id:init'); + $seen_ids_init = array(); + + // check to see if this is the top form of the stack. If it is, pop + // it off; if it isn't, the user clicked somewhere else and the stack is + // now irrelevant. + if (!empty($view->stack)) { + $identifier = implode('-', array_filter(array($key, $view->id(), $display_id, $form_state['type'], $form_state['id']))); + // Retrieve the first form from the stack without changing the integer keys, + // as they're being used for the "2 of 3" progress indicator. + reset($view->stack); + list($key, $top) = each($view->stack); + unset($view->stack[$key]); + + if (array_shift($top) != $identifier) { + $view->stack = array(); + } + } + + // Automatically remove the form cache if it is set and the key does + // not match. This way navigating away from the form without hitting + // update will work. + if (isset($view->form_cache) && $view->form_cache['key'] != $key) { + unset($view->form_cache); + } + + // With the below logic, we may end up rendering a form twice (or two forms + // each sharing the same element ids), potentially resulting in + // drupal_add_js() being called twice to add the same setting. drupal_get_js() + // is ok with that, but until ajax_render() is (http://drupal.org/node/208611), + // reset the drupal_add_js() static before rendering the second time. + $drupal_add_js_original = drupal_add_js(); + $drupal_add_js = &drupal_static('drupal_add_js'); + $response = views_ajax_form_wrapper($form_state['form_id'], $form_state); + + // If the form has not been submitted, or was not set for rerendering, stop. + if (!$form_state['submitted'] || !empty($form_state['rerender'])) { + return $response; + } + + // Sometimes we need to re-generate the form for multi-step type operations. + if (!empty($view->stack)) { + $drupal_add_js = $drupal_add_js_original; + $stack = $view->stack; + $top = array_shift($stack); + + // Map a form key to a class name. For example, 'config-item-extra' + // becomes 'ConfigItemExtra'. + // @todo Consider replacing this with an array property mapping them, or + // forms as plugins. + $class = '\\Drupal\\views_ui\\Form\\' . preg_replace_callback('/(^|-)(.)/', function ($match) { return strtoupper($match[2]); }, $top[1]); + + // Build the new form state for the next form in the stack. + $reflection = new \ReflectionClass($class); + $form_state = $reflection->newInstanceArgs(array_slice($top, 3, 2))->getFormState($view, $top[2], $form_state['ajax']); + + $form_state['input'] = array(); + $form_url = views_ui_build_form_url($form_state); + if (!$form_state['ajax']) { + return new RedirectResponse(url($form_url, array('absolute' => TRUE))); + } + $form_state['url'] = url($form_url); + $response = views_ajax_form_wrapper($form_state['form_id'], $form_state); + } + elseif (!$form_state['ajax']) { + // if nothing on the stack, non-js forms just go back to the main view editor. + return new RedirectResponse(url("admin/structure/views/view/{$view->id()}/edit", array('absolute' => TRUE))); + } + else { + $response = new AjaxResponse(); + $response->addCommand(new Ajax\DismissFormCommand()); + $response->addCommand(new Ajax\ShowButtonsCommand()); + $response->addCommand(new Ajax\TriggerPreviewCommand()); + if (!empty($form_state['#page_title'])) { + $response->addCommand(new Ajax\ReplaceTitleCommand($form_state['#page_title'])); + } + } + // If this form was for view-wide changes, there's no need to regenerate + // the display section of the form. + if ($display_id !== '') { + drupal_container()->get('plugin.manager.entity')->getFormController('view', 'edit')->rebuildCurrentTab($view, $response, $display_id); + } + + return $response; + } + + /** + * Loads a view, first checking for a view being currently edited. + * + * @param \Drupal\views\ViewStorageInterface $view + * The view being acted upon. + * + * @return \Drupal\views_ui\ViewUI + * The view object, with a 'locked' property indicating whether or not + * someone else is already editing the view. + */ + public function getViewUI(ViewStorageInterface $view) { + if ($view instanceof ViewUI) { + return $view; + } + $temp_store = drupal_container()->get('user.tempstore')->get('views'); + $view_ui = new ViewUI($view); + if ($new_view = $temp_store->get($view_ui->id())) { + if ($view_ui->status()) { + $new_view->enable(); + } + else { + $new_view->disable(); + } + } + else { + $new_view = $view_ui; + } + $new_view->locked = $temp_store->getMetadata($new_view->id()); + return $new_view; + } + +} diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ViewsFormInterface.php b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ViewsFormInterface.php new file mode 100644 index 0000000..c90b3b8 --- /dev/null +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ViewsFormInterface.php @@ -0,0 +1,19 @@ + 'details', + '#title' => t('Caching'), + ); + + $form['cache']['skip_cache'] = array( + '#type' => 'checkbox', + '#title' => t('Disable views data caching'), + '#description' => t("Views caches data about tables, modules and views available, to increase performance. By checking this box, Views will skip this cache and always rebuild this data when needed. This can have a serious performance impact on your site."), + '#default_value' => $this->config->get('skip_cache'), + ); + + $form['cache']['clear_cache'] = array( + '#type' => 'submit', + '#value' => t("Clear Views' cache"), + '#submit' => array(array($this, 'cacheSubmit')), + ); + + $form['debug'] = array( + '#type' => 'details', + '#title' => t('Debugging'), + ); + + $form['debug']['sql_signature'] = array( + '#type' => 'checkbox', + '#title' => t('Add Views signature to all SQL queries'), + '#description' => t("All Views-generated queries will include the name of the views and display 'view-name:display-name' as a string at the end of the SELECT clause. This makes identifying Views queries in database server logs simpler, but should only be used when troubleshooting."), + + '#default_value' => $this->config->get('sql_signature'), + ); + + $form['debug']['no_javascript'] = array( + '#type' => 'checkbox', + '#title' => t('Disable JavaScript with Views'), + '#description' => t("If you are having problems with the JavaScript, you can disable it here. The Views UI should degrade and still be usable without javascript; it's just not as good."), + '#default_value' => $this->config->get('no_javascript'), + ); + + $options = views_fetch_plugin_names('display_extender'); + if (!empty($options)) { + $form['extenders'] = array( + '#type' => 'details', + ); + $form['extenders']['display_extenders'] = array( + '#title' => t('Display extenders'), + '#default_value' => array_filter($this->config->get('display_extenders')), + '#options' => $options, + '#type' => 'checkboxes', + '#description' => t('Select extensions of the views interface.') + ); + } + + return system_config_form($form, &$form_state); + } + + /** + * Implements \Drupal\Core\Form\FormInterface::submit(). + */ + public function submit(array &$form, array &$form_state) { + $this->config + ->set('skip_cache', $form_state['values']['skip_cache']) + ->set('sql_signature', $form_state['values']['sql_signature']) + ->set('no_javascript', $form_state['values']['no_javascript']) + ->set('display_extenders', isset($form_state['values']['display_extenders']) ? $form_state['values']['display_extenders'] : array()) + ->save(); + } + + /** + * Submission handler to clear the Views cache. + */ + public function cacheSubmit() { + views_invalidate_cache(); + drupal_set_message(t('The cache has been cleared.')); + } + +} diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ViewsUIBasicSettings.php b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ViewsUIBasicSettings.php new file mode 100644 index 0000000..3354ad9 --- /dev/null +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ViewsUIBasicSettings.php @@ -0,0 +1,139 @@ + $theme) { + if ($theme->status) { + $options[$name] = $theme->info['name']; + } + } + + // This is not currently a fieldset but we may want it to be later, + // so this will make it easier to change if we do. + $form['basic'] = array(); + + $form['basic']['ui_show_master_display'] = array( + '#type' => 'checkbox', + '#title' => t('Always show the master display'), + '#description' => t('Advanced users of views may choose to see the master (i.e. default) display.'), + '#default_value' => $this->config->get('ui.show.master_display'), + ); + + $form['basic']['ui_show_advanced_column'] = array( + '#type' => 'checkbox', + '#title' => t('Always show advanced display settings'), + '#description' => t('Default to showing advanced display settings, such as relationships and contextual filters.'), + '#default_value' => $this->config->get('ui.show.advanced_column'), + ); + + $form['basic']['ui_show_display_embed'] = array( + '#type' => 'checkbox', + '#title' => t('Show the embed display in the ui.'), + '#description' => t('Allow advanced user to use the embed view display. The plugin itself works if it\'s not visible in the ui'), + '#default_value' => $this->config->get('ui.show.display_embed'), + ); + + $form['basic']['ui_exposed_filter_any_label'] = array( + '#type' => 'select', + '#title' => t('Label for "Any" value on non-required single-select exposed filters'), + '#options' => array('old_any' => '', 'new_any' => t('- Any -')), + '#default_value' => $this->config->get('ui.exposed_filter_any_label'), + ); + + $form['live_preview'] = array( + '#type' => 'details', + '#title' => t('Live preview settings'), + ); + + $form['live_preview']['ui_always_live_preview'] = array( + '#type' => 'checkbox', + '#title' => t('Automatically update preview on changes'), + '#default_value' => $this->config->get('ui.always_live_preview'), + ); + + $form['live_preview']['ui_show_preview_information'] = array( + '#type' => 'checkbox', + '#title' => t('Show information and statistics about the view during live preview'), + '#default_value' => $this->config->get('ui.show.preview_information'), + ); + + $form['live_preview']['options'] = array( + '#type' => 'container', + '#states' => array( + 'visible' => array( + ':input[name="ui_show_preview_information"]' => array('checked' => TRUE), + ), + ), + ); + + $form['live_preview']['options']['ui_show_sql_query_where'] = array( + '#type' => 'radios', + '#options' => array( + 'above' => t('Above the preview'), + 'below' => t('Below the preview'), + ), + '#default_value' => $this->config->get('ui.show.sql_query.where'), + ); + + $form['live_preview']['options']['ui_show_sql_query_enabled'] = array( + '#type' => 'checkbox', + '#title' => t('Show the SQL query'), + '#default_value' => $this->config->get('ui.show.sql_query.enabled'), + ); + $form['live_preview']['options']['ui_show_performance_statistics'] = array( + '#type' => 'checkbox', + '#title' => t('Show performance statistics'), + '#default_value' => $this->config->get('ui.show.performance_statistics'), + ); + + $form['live_preview']['options']['ui_show_additional_queries'] = array( + '#type' => 'checkbox', + '#title' => t('Show other queries run during render during live preview'), + '#description' => t("Drupal has the potential to run many queries while a view is being rendered. Checking this box will display every query run during view render as part of the live preview."), + '#default_value' => $this->config->get('ui.show.additional_queries'), + ); + + return system_config_form($form, $form_state); + } + + /** + * Implements \Drupal\Core\Form\FormInterface::submit(). + */ + public function submit(array &$form, array &$form_state) { + $this->config + ->set('ui.show.master_display', $form_state['values']['ui_show_master_display']) + ->set('ui.show.advanced_column', $form_state['values']['ui_show_advanced_column']) + ->set('ui.show.display_embed', $form_state['values']['ui_show_display_embed']) + ->set('ui.exposed_filter_any_label', $form_state['values']['ui_exposed_filter_any_label']) + ->set('ui.always_live_preview', $form_state['values']['ui_always_live_preview']) + ->set('ui.show.preview_information', $form_state['values']['ui_show_preview_information']) + ->set('ui.show.sql_query.where', $form_state['values']['ui_show_sql_query_where']) + ->set('ui.show.sql_query.enabled', $form_state['values']['ui_show_sql_query_enabled']) + ->set('ui.show.performance_statistics', $form_state['values']['ui_show_performance_statistics']) + ->set('ui.show.additional_queries', $form_state['values']['ui_show_additional_queries']) + ->save(); + } + +} diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ViewsUIBreakLock.php b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ViewsUIBreakLock.php new file mode 100644 index 0000000..885cbd6 --- /dev/null +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ViewsUIBreakLock.php @@ -0,0 +1,105 @@ +entityManager = $entity_manager; + $this->tempStore = $temp_store_factory->get('views'); + } + + /** + * Creates a new instance of this form. + * + * @param \Drupal\views\ViewStorageInterface $view + * The view being acted upon. + * + * @return array + * The built form array. + */ + public function getForm(ViewStorageInterface $view) { + return drupal_get_form($this, $view); + } + + /** + * Implements \Drupal\Core\Form\FormInterface::getFormID(). + */ + public function getFormID() { + return 'views_ui_break_lock_confirm'; + } + + /** + * Implements \Drupal\Core\Form\FormInterface::build(). + */ + public function build(array $form, array &$form_state, ViewStorageInterface $view = NULL) { + $form_state['view_id'] = $view->id(); + $locked = $this->tempStore->getMetadata($form_state['view_id']); + + if (!$locked) { + $form['message']['#markup'] = t('There is no lock on view %name to break.', array('%name' => $form_state['view_id'])); + return $form; + } + + $account = $this->entityManager->getStorageController('user')->load(array($locked->owner)); + return confirm_form($form, + t('Do you want to break the lock on view %name?', array('%name' => $form_state['view_id'])), + 'admin/structure/views/view/' . $form_state['view_id'], + t('By breaking this lock, any unsaved changes made by !user will be lost.', array('!user' => theme('username', array('account' => reset($account))))), + t('Break lock'), + t('Cancel') + ); + } + + /** + * Implements \Drupal\Core\Form\FormInterface::validate(). + */ + public function validate(array &$form, array &$form_state) { + } + + /** + * Implements \Drupal\Core\Form\FormInterface::submit(). + */ + public function submit(array &$form, array &$form_state) { + $this->tempStore->delete($form_state['view_id']); + $form_state['redirect'] = 'admin/structure/views/view/' . $form_state['view_id']; + drupal_set_message(t('The lock has been broken and you may now edit this view.')); + } + +} diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ViewsUIDelete.php b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ViewsUIDelete.php new file mode 100644 index 0000000..9de9b97 --- /dev/null +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ViewsUIDelete.php @@ -0,0 +1,66 @@ + $view->getHumanName())), + 'admin/structure/views', + t('This action cannot be undone.'), + t('Delete'), + t('Cancel') + ); + } + + /** + * Implements \Drupal\Core\Form\FormInterface::validate(). + */ + public function validate(array &$form, array &$form_state) { + } + + /** + * Implements \Drupal\Core\Form\FormInterface::submit(). + */ + public function submit(array &$form, array &$form_state) { + $form_state['view']->delete(); + $form_state['redirect'] = 'admin/structure/views'; + } + +} diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ViewsUISettingsBase.php b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ViewsUISettingsBase.php new file mode 100644 index 0000000..58e8284 --- /dev/null +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/Form/ViewsUISettingsBase.php @@ -0,0 +1,51 @@ +config = $config_factory->get('views.settings'); + } + + /** + * Creates a new instance of this form. + * + * @return array + * The built form array. + */ + public function getForm() { + return drupal_get_form($this); + } + + /** + * Implements \Drupal\Core\Form\FormInterface::validate(). + */ + public function validate(array &$form, array &$form_state) { + } + +} 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 c0fbf9e..3b5fef4 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 @@ -11,6 +11,7 @@ use Drupal\views\ViewStorageInterface; use Drupal\views_ui\ViewUI; use Drupal\views\ViewsDataCache; +use Drupal\user\TempStore; use Drupal\user\TempStoreFactory; use Drupal\Core\Entity\EntityManager; use Symfony\Component\HttpFoundation\Request; @@ -85,30 +86,6 @@ public function add() { } /** - * Form builder for the admin display defaults page. - * - * @return array - * The Views basic settings form. - */ - public function settingsBasic() { - // @todo Remove the need for this. - module_load_include('inc', 'views_ui', 'admin'); - return drupal_get_form('views_ui_admin_settings_basic'); - } - - /** - * Form builder for the advanced admin settings page. - * - * @return array - * The Views advanced settings form. - */ - public function settingsAdvanced() { - // @todo Remove the need for this. - module_load_include('inc', 'views_ui', 'admin'); - return drupal_get_form('views_ui_admin_settings_advanced'); - } - - /** * Lists all instances of fields on any views. * * @return array @@ -234,19 +211,6 @@ public function cloneForm(ViewStorageInterface $view) { } /** - * Returns the form to delete a view. - * - * @param \Drupal\views\ViewStorageInterface $view - * The view being deleted. - * - * @return array - * The Views delete form. - */ - public function deleteForm(ViewStorageInterface $view) { - return drupal_get_form('views_ui_confirm_delete', $view); - } - - /** * Menu callback for Views tag autocompletion. * * Like other autocomplete functions, this function inspects the 'q' query @@ -321,63 +285,6 @@ public function preview(ViewStorageInterface $view, $display_id = NULL) { } /** - * Returns the form to break the lock of an edited view. - * - * @param \Drupal\views\ViewStorageInterface $view - * The locked view. - * - * @return array - * The Views 'break lock' form. - */ - public function breakLock(ViewStorageInterface $view) { - // @todo Remove the need for this. - module_load_include('inc', 'views_ui', 'admin'); - - return drupal_get_form('views_ui_break_lock_confirm', $this->getViewUI($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 string $key - * A string representing a section of the Views UI. Available keys are in - * views_ui_ajax_forms(). - * @param \Drupal\views\ViewStorageInterface $view - * The view being edited. - * @param string|null $display_id - * The display ID being edited, or NULL to load the first available display. - * @param string|null $type - * If $key is 'add-item' or 'config-item', this is the type of handler 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 - * 'style' as a handler type. 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. - * Otherwise it will be NULL. - * - * @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, $key, ViewStorageInterface $view, $display_id, $type, $id) { - // Determine if this is an AJAX submission. - $js = $js == 'ajax'; - - // @todo Remove the need for this. - module_load_include('inc', 'views_ui', 'admin'); - - return views_ui_ajax_form($js, $key, $this->getViewUI($view), $display_id, $type, $id); - } - - /** * Loads a view, first checking for a view being currently edited. * * @param \Drupal\views\ViewStorageInterface $view diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewEditFormController.php b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewEditFormController.php index c46de11..451aa51 100644 --- a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewEditFormController.php +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewEditFormController.php @@ -884,7 +884,7 @@ public function getFormBucket(ViewUI $view, $type, $display) { case 'filter': // The rearrange form for filters contains the and/or UI, so override // the used path. - $rearrange_url = "admin/structure/views/nojs/rearrange-$type/{$view->id()}/{$display['id']}/$type"; + $rearrange_url = "admin/structure/views/nojs/rearrange-filter/{$view->id()}/{$display['id']}"; $rearrange_text = t('And/Or, Rearrange'); // TODO: Add another class to have another symbol for filter rearrange. $class = 'icon compact rearrange'; 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 61eb153..836edc0 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 @@ -95,8 +95,6 @@ public function getDisplayTabs(ViewUI $view) { // Create a tab for each display. $displays = $view->get('display'); - uasort($displays, array($view, 'sortPosition')); - $view->set('display', $displays); foreach ($displays as $id => $display) { $tabs[$id] = array( '#theme' => 'menu_local_task', diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewUI.php b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewUI.php index ab5a00f..09c6410 100644 --- a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewUI.php +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewUI.php @@ -217,8 +217,11 @@ public function standardSubmit($form, &$form_state) { } $submit_handler = $form['#form_id'] . '_submit'; - if (function_exists($submit_handler)) { - $submit_handler($form, $form_state); + if (isset($form_state['build_info']['callback_object'])) { + $submit_handler = array($form_state['build_info']['callback_object'], 'submit'); + } + if (is_callable($submit_handler)) { + call_user_func($submit_handler, $form, $form_state); } } @@ -271,18 +274,22 @@ public function getStandardButtons(&$form, &$form_state, $form_id, $name = NULL, '#button_type' => 'primary', ); // Form API button click detection requires the button's #value to be the - // same between the form build of the initial page request, and the initial - // form build of the request processing the form submission. Ideally, the - // button's #value shouldn't change until the form rebuild step. However, - // views_ui_ajax_form() implements a different multistep form workflow than - // the Form API does, and adjusts $view->stack prior to form processing, so - // we compensate by extending button click detection code to support any of - // the possible button labels. + // same between the form build of the initial page request, and the + // initial form build of the request processing the form submission. + // Ideally, the button's #value shouldn't change until the form rebuild + // step. However, \Drupal\views_ui\Routing\ViewsUIController::ajaxForm() + // implements a different multistep form workflow than the Form API does, + // and adjusts $view->stack prior to form processing, so we compensate by + // extending button click detection code to support any of the possible + // button labels. if (isset($names)) { $form['buttons']['submit']['#values'] = $names; $form['buttons']['submit']['#process'] = array_merge(array('views_ui_form_button_was_clicked'), element_info_property($form['buttons']['submit']['#type'], '#process', array())); } // If a validation handler exists for the form, assign it to this button. + if (isset($form_state['build_info']['callback_object'])) { + $form['buttons']['submit']['#validate'][] = array($form_state['build_info']['callback_object'], 'validate'); + } if (function_exists($form_id . '_validate')) { $form['buttons']['submit']['#validate'][] = $form_id . '_validate'; } @@ -361,132 +368,10 @@ public function getOverrideValues($form, $form_state) { } /** - * Submit handler to break_lock a view. - */ - public function submitBreakLock(&$form, &$form_state) { - drupal_container()->get('user.tempstore')->get('views')->delete($this->id()); - $form_state['redirect'] = 'admin/structure/views/view/' . $this->id() . '/edit'; - drupal_set_message(t('The lock has been broken and you may now edit this view.')); - } - - /** - * Form constructor callback to reorder displays on a view - */ - public function buildDisplaysReorderForm($form, &$form_state) { - $display_id = $form_state['display_id']; - - $form['view'] = array('#type' => 'value', '#value' => $this); - - $form['#tree'] = TRUE; - - $count = count($this->get('display')); - - $displays = $this->get('display'); - uasort($displays, array('static', 'sortPosition')); - $this->set('display', $displays); - foreach ($displays as $display) { - $form[$display['id']] = array( - 'title' => array('#markup' => $display['display_title']), - 'weight' => array( - '#type' => 'weight', - '#value' => $display['position'], - '#delta' => $count, - '#title' => t('Weight for @display', array('@display' => $display['display_title'])), - '#title_display' => 'invisible', - ), - '#tree' => TRUE, - '#display' => $display, - 'removed' => array( - '#type' => 'checkbox', - '#id' => 'display-removed-' . $display['id'], - '#attributes' => array('class' => array('views-remove-checkbox')), - '#default_value' => isset($display['deleted']), - ), - ); - - if (isset($display['deleted']) && $display['deleted']) { - $form[$display['id']]['deleted'] = array('#type' => 'value', '#value' => TRUE); - } - if ($display['id'] === 'default') { - unset($form[$display['id']]['weight']); - unset($form[$display['id']]['removed']); - } - - } - - $form['#title'] = t('Displays Reorder'); - $form['#section'] = 'reorder'; - - // Add javascript settings that will be added via $.extend for tabledragging - $form['#js']['tableDrag']['reorder-displays']['weight'][0] = array( - 'target' => 'weight', - 'source' => NULL, - 'relationship' => 'sibling', - 'action' => 'order', - 'hidden' => TRUE, - 'limit' => 0, - ); - - $form['#action'] = url('admin/structure/views/nojs/reorder-displays/' . $this->id() . '/' . $display_id); - - $this->getStandardButtons($form, $form_state, 'views_ui_reorder_displays_form'); - $form['buttons']['submit']['#submit'] = array(array($this, 'submitDisplaysReorderForm')); - - return $form; - } - - /** - * Submit handler for rearranging display form - */ - public function submitDisplaysReorderForm($form, &$form_state) { - foreach ($form_state['input'] as $display => $info) { - // add each value that is a field with a weight to our list, but only if - // it has had its 'removed' checkbox checked. - if (is_array($info) && isset($info['weight']) && empty($info['removed'])) { - $order[$display] = $info['weight']; - } - } - - // Sort the order array - asort($order); - - // Fixing up positions - $position = 1; - - foreach (array_keys($order) as $display) { - $order[$display] = $position++; - } - - // Setting up position and removing deleted displays - $displays = $this->get('display'); - foreach ($displays as $display_id => $display) { - // Don't touch the default !!! - if ($display_id === 'default') { - $displays[$display_id]['position'] = 0; - continue; - } - if (isset($order[$display_id])) { - $displays[$display_id]['position'] = $order[$display_id]; - } - else { - $displays[$display_id]['deleted'] = TRUE; - } - } - - // Sorting back the display array as the position is not enough - uasort($displays, array('static', 'sortPosition')); - $this->set('display', $displays); - - // Store in cache - views_ui_cache_set($this); - $form_state['redirect'] = array('admin/structure/views/view/' . $this->id() . '/edit', array('fragment' => 'views-tab-default')); - } - - /** * Add another form to the stack; clicking 'apply' will go to this form * rather than closing the ajax popup. */ - public function addFormToStack($key, $display_id, $args, $top = FALSE, $rebuild_keys = FALSE) { + public function addFormToStack($key, $display_id, $type, $id = NULL, $top = FALSE, $rebuild_keys = FALSE) { // Reset the cache of IDs. Drupal rather aggressively prevents ID // duplication but this causes it to remember IDs that are no longer even // being used. @@ -497,7 +382,7 @@ public function addFormToStack($key, $display_id, $args, $top = FALSE, $rebuild_ $this->stack = array(); } - $stack = array($this->buildIdentifier($key, $display_id, $args), $key, $display_id, $args); + $stack = array(implode('-', array_filter(array($key, $this->id(), $display_id, $type, $id))), $key, $display_id, $type, $id); // If we're being asked to add this form to the bottom of the stack, no // special logic is required. Our work is equally easy if we were asked to add // to the top of the stack, but there's nothing in it yet. @@ -575,15 +460,15 @@ public function submitItemAdd($form, &$form_state) { } $handler = views_get_handler($table, $field, $key); if ($this->executable->displayHandlers->get('default')->useGroupBy() && $handler->usesGroupBy()) { - $this->addFormToStack('config-item-group', $form_state['display_id'], array($type, $id)); + $this->addFormToStack('config-item-group', $form_state['display_id'], $type, $id); } // check to see if this type has settings, if so add the settings form first if ($handler && $handler->hasExtraOptions()) { - $this->addFormToStack('config-item-extra', $form_state['display_id'], array($type, $id)); + $this->addFormToStack('config-item-extra', $form_state['display_id'], $type, $id); } // Then add the form to the stack - $this->addFormToStack('config-item', $form_state['display_id'], array($type, $id)); + $this->addFormToStack('config-item', $form_state['display_id'], $type, $id); } } @@ -844,63 +729,6 @@ public function getFormProgress() { } /** - * Build a form identifier that we can use to see if one form - * is the same as another. Since the arguments differ slightly - * we do a lot of spiffy concatenation here. - */ - public function buildIdentifier($key, $display_id, $args) { - $form = views_ui_ajax_forms($key); - // Automatically remove the single-form cache if it exists and - // does not match the key. - $identifier = implode('-', array($key, $this->id(), $display_id)); - - foreach ($form['args'] as $id) { - $arg = (!empty($args)) ? array_shift($args) : NULL; - $identifier .= '-' . $arg; - } - return $identifier; - } - - /** - * Display position sorting function - */ - public static function sortPosition($display1, $display2) { - if ($display1['position'] != $display2['position']) { - return $display1['position'] < $display2['position'] ? -1 : 1; - } - - return 0; - } - - /** - * Build up a $form_state object suitable for use with drupal_build_form - * based on known information about a form. - */ - public function buildFormState($js, $key, $display_id, $args) { - $form = views_ui_ajax_forms($key); - // Build up form state - $form_state = array( - 'form_key' => $key, - 'form_id' => $form['form_id'], - 'view' => &$this, - 'ajax' => $js, - 'display_id' => $display_id, - 'no_redirect' => TRUE, - ); - // If an method was specified, use that for the callback. - if (isset($form['callback'])) { - $form_state['build_info']['args'] = array(); - $form_state['build_info']['callback'] = array($this, $form['callback']); - } - - foreach ($form['args'] as $id) { - $form_state[$id] = (!empty($args)) ? array_shift($args) : NULL; - } - - return $form_state; - } - - /** * Passes through all unknown calls onto the storage object. */ public function __call($method, $args) { 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 9459721..d264740 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 @@ -24,6 +24,13 @@ public function build(ContainerBuilder $container) { ->addArgument(new Reference('plugin.manager.entity')) ->addArgument(new Reference('views.views_data')) ->addArgument(new Reference('user.tempstore')); + $container->register('views_ui.form.basic_settings', 'Drupal\views_ui\Form\ViewsUIBasicSettings') + ->addArgument(new Reference('config.factory')); + $container->register('views_ui.form.advanced_settings', 'Drupal\views_ui\Form\ViewsUIAdvancedSettings') + ->addArgument(new Reference('config.factory')); + $container->register('views_ui.form.breakLock', 'Drupal\views_ui\Form\ViewsUIBreakLock') + ->addArgument(new Reference('plugin.manager.entity')) + ->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 24d54ef..2dbdcc6 100644 --- a/core/modules/views/views_ui/views_ui.module +++ b/core/modules/views/views_ui/views_ui.module @@ -489,30 +489,3 @@ function views_ui_truncate($string, $length) { function views_ui_load($name) { return views_get_view($name); } - -/** - * Form constructor for the View deletion form. - * - * @param \Drupal\views\ViewExectuable $view - * The View being deleted. - * - * @see views_ui_confirm_delete_submit() - */ -function views_ui_confirm_delete($form, &$form_state, ViewStorageInterface $view) { - $form['view'] = array('#type' => 'value', '#value' => $view); - return confirm_form($form, - t('Are you sure you want to delete the %name view?', array('%name' => $view->getHumanName())), - 'admin/structure/views', - t('This action cannot be undone.'), - t('Delete'), - t('Cancel') - ); -} - -/** - * Form submission handler for views_ui_confirm_delete(). - */ -function views_ui_confirm_delete_submit($form, &$form_state) { - $form_state['values']['view']->delete(); - $form_state['redirect'] = 'admin/structure/views'; -} diff --git a/core/modules/views/views_ui/views_ui.routing.yml b/core/modules/views/views_ui/views_ui.routing.yml index 372020e..a45987c 100644 --- a/core/modules/views/views_ui/views_ui.routing.yml +++ b/core/modules/views/views_ui/views_ui.routing.yml @@ -15,14 +15,14 @@ views_ui.add: views_ui.settings.basic: pattern: '/admin/structure/views/settings' defaults: - _controller: 'views_ui.controller:settingsBasic' + _controller: 'views_ui.form.basic_settings:getForm' requirements: _permission: 'administer views' views_ui.settings.advanced: pattern: '/admin/structure/views/settings/advanced' defaults: - _controller: 'views_ui.controller:settingsAdvanced' + _controller: 'views_ui.form.advanced_settings:getForm' requirements: _permission: 'administer views' @@ -67,7 +67,7 @@ views_ui.delete: converters: view: 'view' defaults: - _controller: 'views_ui.controller:deleteForm' + _controller: 'Drupal\views_ui\Form\ViewsUIDelete::getForm' requirements: _permission: 'administer views' @@ -116,20 +116,118 @@ views_ui.breakLock: converters: view: 'view' defaults: - _controller: 'views_ui.controller:breakLock' + _controller: 'views_ui.form.breakLock:getForm' display_id: NULL requirements: _permission: 'administer views' -views_ui.ajaxForm: - pattern: '/admin/structure/views/{js}/{key}/{view}/{display_id}/{type}/{id}' +views_ui.form.addItem: + pattern: '/admin/structure/views/{js}/add-item/{view}/{display_id}/{type}' options: converters: view: 'view' defaults: - _controller: 'views_ui.controller:ajaxForm' - type: NULL - id: NULL + _controller: '\Drupal\views_ui\Form\AddItem::ajaxForm' + requirements: + _permission: 'administer views' + js: 'nojs|ajax' + +views_ui.form.editDetails: + pattern: '/admin/structure/views/{js}/edit-details/{view}/{display_id}' + options: + converters: + view: 'view' + defaults: + _controller: '\Drupal\views_ui\Form\EditDetails::ajaxForm' + requirements: + _permission: 'administer views' + js: 'nojs|ajax' + +views_ui.form.reorderDisplays: + pattern: '/admin/structure/views/{js}/reorder-displays/{view}/{display_id}' + options: + converters: + view: 'view' + defaults: + _controller: '\Drupal\views_ui\Form\ReorderDisplays::ajaxForm' + requirements: + _permission: 'administer views' + js: 'nojs|ajax' + +views_ui.form.analyze: + pattern: '/admin/structure/views/{js}/analyze/{view}/{display_id}' + options: + converters: + view: 'view' + defaults: + _controller: '\Drupal\views_ui\Form\Analyze::ajaxForm' + requirements: + _permission: 'administer views' + js: 'nojs|ajax' + +views_ui.form.rearrange: + pattern: '/admin/structure/views/{js}/rearrange/{view}/{display_id}/{type}' + options: + converters: + view: 'view' + defaults: + _controller: '\Drupal\views_ui\Form\Rearrange::ajaxForm' + requirements: + _permission: 'administer views' + js: 'nojs|ajax' + +views_ui.form.rearrangeFilter: + pattern: '/admin/structure/views/{js}/rearrange-filter/{view}/{display_id}' + options: + converters: + view: 'view' + defaults: + _controller: '\Drupal\views_ui\Form\RearrangeFilter::ajaxForm' + requirements: + _permission: 'administer views' + js: 'nojs|ajax' + +views_ui.form.display: + pattern: '/admin/structure/views/{js}/display/{view}/{display_id}/{type}' + options: + converters: + view: 'view' + defaults: + _controller: '\Drupal\views_ui\Form\Display::ajaxForm' + requirements: + _permission: 'administer views' + js: 'nojs|ajax' + +views_ui.form.configItem: + pattern: '/admin/structure/views/{js}/config-item/{view}/{display_id}/{type}/{id}' + options: + converters: + view: 'view' + defaults: + _controller: '\Drupal\views_ui\Form\ConfigItem::ajaxForm' + requirements: + _permission: 'administer views' + js: 'nojs|ajax' + +views_ui.form.configItemExtra: + pattern: '/admin/structure/views/{js}/config-item-extra/{view}/{display_id}/{type}/{id}' + options: + converters: + view: 'view' + defaults: + _controller: '\Drupal\views_ui\Form\ConfigItemExtra::ajaxForm' + requirements: + _permission: 'administer views' + js: 'nojs|ajax' + +views_ui.form.configItemGroup: + pattern: '/admin/structure/views/{js}/config-item-group/{view}/{display_id}/{type}/{id}' + options: + converters: + view: 'view' + defaults: + _controller: '\Drupal\views_ui\Form\ConfigItemGroup::ajaxForm' + form_state: NULL requirements: _permission: 'administer views' js: 'nojs|ajax'