diff --git a/includes/admin.inc b/includes/admin.inc
index 7ae715fee93e..a69cb080ee1e 100644
--- a/includes/admin.inc
+++ b/includes/admin.inc
@@ -6,72 +6,10 @@
*/
use Drupal\Core\Database\Database;
-use Drupal\views\TempStore\UserTempStore;
-use Drupal\views\ViewExecutable;
use Drupal\views\ViewUI;
use Drupal\views\Analyzer;
use Drupal\views\Plugin\views\wizard\WizardException;
-/**
- * Create an array of Views admin CSS for adding or attaching.
- *
- * This returns an array of arrays. Each array represents a single
- * file. The array format is:
- * - file: The fully qualified name of the file to send to drupal_add_css
- * - options: An array of options to pass to drupal_add_css.
- */
-function views_ui_get_admin_css() {
- $module_path = drupal_get_path('module', 'views_ui');
- $list = array();
- $list[$module_path . '/css/views-admin.css'] = array();
- $list[$module_path . '/css/views-admin.theme.css'] = array();
-
- // Add in any theme specific CSS files we have
- $themes = list_themes();
- $theme_key = $GLOBALS['theme'];
- while ($theme_key) {
- // Try to find the admin css file for non-core themes.
- if (!in_array($theme_key, array('seven', 'bartik'))) {
- $theme_path = drupal_get_path('theme', $theme_key);
- // First search in the css directory, then in the root folder of the theme.
- if (file_exists($theme_path . "/css/views-admin.$theme_key.css")) {
- $list[$theme_path . "/css/views-admin.$theme_key.css"] = array(
- 'group' => CSS_THEME,
- );
- }
- elseif (file_exists($theme_path . "/views-admin.$theme_key.css")) {
- $list[$theme_path . "/views-admin.$theme_key.css"] = array(
- 'group' => CSS_THEME,
- );
- }
- }
- else {
- $list[$module_path . "/css/views-admin.$theme_key.css"] = array(
- 'group' => CSS_THEME,
- );
- }
- $theme_key = isset($themes[$theme_key]->base_theme) ? $themes[$theme_key]->base_theme : '';
- }
- // Views contains style overrides for the following modules
- $module_list = array('contextual', 'ctools');
- foreach ($module_list as $module) {
- if (module_exists($module)) {
- $list[$module_path . '/css/views-admin.' . $module . '.css'] = array();
- }
- }
-
- return $list;
-}
-
-/**
- * Adds standard Views administration CSS to the current page.
- */
-function views_ui_add_admin_css() {
- foreach (views_ui_get_admin_css() as $file => $options) {
- drupal_add_css($file, $options);
- }
-}
-
/**
* Returns the results of the live preview.
*/
@@ -81,298 +19,17 @@ function views_ui_preview(ViewUI $view, $display_id, $args = array()) {
if (!is_array($args)) {
$args = array_slice(func_get_args(), 2);
}
-
- // Save the current path so it can be restored before returning from this function.
- $old_q = current_path();
-
- // Determine where the query and performance statistics should be output.
- $config = config('views.settings');
- $show_query = $config->get('ui.show.sql_query.enabled');
- $show_info = $config->get('ui.show.preview_information');
- $show_location = $config->get('ui.show.sql_query.where');
-
- $show_stats = $config->get('ui.show.performance_statistics');
- if ($show_stats) {
- $show_stats = $config->get('ui.show.sql_query.where');
- }
-
- $combined = $show_query && $show_stats;
-
- $rows = array('query' => array(), 'statistics' => array());
- $output = '';
-
- $errors = $view->validate();
- if ($errors === TRUE) {
- $view->ajax = TRUE;
- $view->live_preview = TRUE;
- $view->views_ui_context = TRUE;
-
- // AJAX happens via $_POST but everything expects exposed data to
- // be in GET. Copy stuff but remove ajax-framework specific keys.
- // If we're clicking on links in a preview, though, we could actually
- // still have some in $_GET, so we use $_REQUEST to ensure we get it all.
- $exposed_input = drupal_container()->get('request')->request->all();
- foreach (array('view_name', 'view_display_id', 'view_args', 'view_path', 'view_dom_id', 'pager_element', 'view_base_path', 'ajax_html_ids', 'ajax_page_state', 'form_id', 'form_build_id', 'form_token') as $key) {
- if (isset($exposed_input[$key])) {
- unset($exposed_input[$key]);
- }
- }
-
- $view->setExposedInput($exposed_input);
-
- if (!$view->setDisplay($display_id)) {
- return t('Invalid display id @display', array('@display' => $display_id));
- }
-
- $view->setArguments($args);
-
- // Store the current view URL for later use:
- if ($view->display_handler->getOption('path')) {
- $path = $view->getUrl();
- }
-
- // Make view links come back to preview.
- $view->override_path = 'admin/structure/views/nojs/preview/' . $view->storage->name . '/' . $display_id;
-
- // Also override the current path so we get the pager.
- $original_path = current_path();
- $q = _current_path($view->override_path);
- if ($args) {
- $q .= '/' . implode('/', $args);
- _current_path($q);
- }
-
- // Suppress contextual links of entities within the result set during a
- // Preview.
- // @todo We'll want to add contextual links specific to editing the View, so
- // the suppression may need to be moved deeper into the Preview pipeline.
- views_ui_contextual_links_suppress_push();
- $preview = $view->preview($display_id, $args);
- views_ui_contextual_links_suppress_pop();
-
- // Reset variables.
- unset($view->override_path);
- _current_path($original_path);
-
- // Prepare the query information and statistics to show either above or
- // below the view preview.
- if ($show_info || $show_query || $show_stats) {
- // Get information from the preview for display.
- if (!empty($view->build_info['query'])) {
- if ($show_query) {
- $query = $view->build_info['query'];
- // Only the sql default class has a method getArguments.
- $quoted = array();
-
- if (get_class($view->query) == 'views_plugin_query_default') {
- $quoted = $query->getArguments();
- $connection = Database::getConnection();
- foreach ($quoted as $key => $val) {
- if (is_array($val)) {
- $quoted[$key] = implode(', ', array_map(array($connection, 'quote'), $val));
- }
- else {
- $quoted[$key] = $connection->quote($val);
- }
- }
- }
- $rows['query'][] = array('' . t('Query') . '', '
';
-
- // Add a text that the display is disabled.
- if (!empty($view->displayHandlers[$display_id])) {
- $enabled = $view->displayHandlers[$display_id]->getOption('enabled');
- if (empty($enabled)) {
- $form['displays']['settings']['disabled']['#markup'] = t('This display is disabled.');
- }
- }
-
- $form['displays']['settings']['settings_content']= array(
- '#theme_wrappers' => array('container'),
- );
- // Add the edit display content
- $form['displays']['settings']['settings_content']['tab_content'] = views_ui_get_display_tab($view, $display_id);
- $form['displays']['settings']['settings_content']['tab_content']['#theme_wrappers'] = array('container');
- $form['displays']['settings']['settings_content']['tab_content']['#attributes'] = array('class' => array('views-display-tab'));
- $form['displays']['settings']['settings_content']['tab_content']['#id'] = 'views-tab-' . $display_id;
- // Mark deleted displays as such.
- if (!empty($view->display[$display_id]['deleted'])) {
- $form['displays']['settings']['settings_content']['tab_content']['#attributes']['class'][] = 'views-display-deleted';
- }
- // Mark disabled displays as such.
- if (empty($enabled)) {
- $form['displays']['settings']['settings_content']['tab_content']['#attributes']['class'][] = 'views-display-disabled';
- }
-
- // The content of the popup dialog.
- $form['ajax-area'] = array(
- '#theme_wrappers' => array('container'),
- '#id' => 'views-ajax-popup',
- );
- $form['ajax-area']['ajax-title'] = array(
- '#markup' => '',
- );
- $form['ajax-area']['ajax-body'] = array(
- '#theme_wrappers' => array('container'),
- '#id' => 'views-ajax-body',
- '#markup' => views_ui_get_default_ajax_message(),
- );
- }
-
- // If relationships had to be fixed, we want to get that into the cache
- // so that edits work properly, and to try to get the user to save it
- // so that it's not using weird fixed up relationships.
- if (!empty($view->relationships_changed) && drupal_container()->get('request')->request->count()) {
- drupal_set_message(t('This view has been automatically updated to fix missing relationships. While this View should continue to work, you should verify that the automatic updates are correct and save this view.'));
- views_ui_cache_set($view);
- }
- return $form;
-}
-
-/**
- * Provide the preview formulas and the preview output, too.
- */
-function views_ui_preview_form($form, &$form_state, ViewUI $view, $display_id = 'default') {
- $form_state['no_cache'] = TRUE;
- $form_state['view'] = $view;
-
- $form['#attributes'] = array('class' => array('clearfix'));
-
- // Add a checkbox controlling whether or not this display auto-previews.
- $form['live_preview'] = array(
- '#type' => 'checkbox',
- '#id' => 'edit-displays-live-preview',
- '#title' => t('Auto preview'),
- '#default_value' => config('views.settings')->get('ui.always_live_preview'),
- );
-
- // Add the arguments textfield
- $form['view_args'] = array(
- '#type' => 'textfield',
- '#title' => t('Preview with contextual filters:'),
- '#description' => t('Separate contextual filter values with a "/". For example, %example.', array('%example' => '40/12/10')),
- '#id' => 'preview-args',
- );
-
- // Add the preview button
- $form['button'] = array(
- '#type' => 'submit',
- '#value' => t('Update preview'),
- '#attributes' => array('class' => array('arguments-preview', 'ctools-auto-submit-click')),
- '#prefix' => '
',
- '#suffix' => '
',
- '#id' => 'preview-submit',
- '#submit' => array('views_ui_edit_form_submit_preview'),
- '#ajax' => array(
- 'path' => 'admin/structure/views/view/' . $view->storage->name . '/preview/' . $display_id . '/ajax',
- 'wrapper' => 'views-preview-wrapper',
- 'event' => 'click',
- 'progress' => array('type' => 'throbber'),
- 'method' => 'replace',
- ),
- // Make ENTER in arguments textfield (and other controls) submit the form
- // as this button, not the Save button.
- // @todo This only works for JS users. To make this work for nojs users,
- // we may need to split Preview into a separate form.
- '#process' => array_merge(array('views_ui_default_button'), element_info_property('submit', '#process', array())),
- );
- $form['#action'] = url('admin/structure/views/view/' . $view->storage->name .'/preview/' . $display_id);
-
- return $form;
-}
-
-/**
- * Render the top of the display so it can be updated during ajax operations.
- */
-function views_ui_render_display_top(ViewUI $view, $display_id) {
- $element['#theme_wrappers'] = array('views_container');
- $element['#attributes']['class'] = array('views-display-top', 'clearfix');
- $element['#attributes']['id'] = array('views-display-top');
-
- // Extra actions for the display
- $element['extra_actions'] = array(
- '#theme' => 'links__ctools_dropbutton',
- '#attributes' => array(
- 'id' => 'views-display-extra-actions',
- 'class' => array(
- 'horizontal', 'right', 'links', 'actions',
- ),
- ),
- '#links' => array(
- 'edit-details' => array(
- 'title' => t('edit view name/description'),
- 'href' => "admin/structure/views/nojs/edit-details/{$view->storage->name}",
- 'attributes' => array('class' => array('views-ajax-link')),
- ),
- 'analyze' => array(
- 'title' => t('analyze view'),
- 'href' => "admin/structure/views/nojs/analyze/{$view->storage->name}/$display_id",
- 'attributes' => array('class' => array('views-ajax-link')),
- ),
- 'clone' => array(
- 'title' => t('clone view'),
- 'href' => "admin/structure/views/view/{$view->storage->name}/clone",
- ),
- 'reorder' => array(
- 'title' => t('reorder displays'),
- 'href' => "admin/structure/views/nojs/reorder-displays/{$view->storage->name}/$display_id",
- 'attributes' => array('class' => array('views-ajax-link')),
- ),
- ),
- );
-
- // Let other modules add additional links here.
- drupal_alter('views_ui_display_top_links', $element['extra_actions']['#links'], $view, $display_id);
-
- if (isset($view->type) && $view->type != t('Default')) {
- if ($view->type == t('Overridden')) {
- $element['extra_actions']['#links']['revert'] = array(
- 'title' => t('revert view'),
- 'href' => "admin/structure/views/view/{$view->storage->name}/revert",
- 'query' => array('destination' => "admin/structure/views/view/{$view->storage->name}"),
- );
- }
- else {
- $element['extra_actions']['#links']['delete'] = array(
- 'title' => t('delete view'),
- 'href' => "admin/structure/views/view/{$view->storage->name}/delete",
- );
- }
- }
-
- // Determine the displays available for editing.
- if ($tabs = views_ui_edit_page_display_tabs($view, $display_id)) {
- if ($display_id) {
- $tabs[$display_id]['#active'] = TRUE;
- }
- $tabs['#prefix'] = '
' . t('Secondary tabs') . '
';
- $tabs['#suffix'] = '
';
- $element['tabs'] = $tabs;
- }
-
- // Buttons for adding a new display.
- foreach (views_fetch_plugin_names('display', NULL, array($view->storage->base_table)) as $type => $label) {
- $element['add_display'][$type] = array(
- '#type' => 'submit',
- '#value' => t('Add !display', array('!display' => $label)),
- '#limit_validation_errors' => array(),
- '#submit' => array('views_ui_edit_form_submit_add_display', 'views_ui_edit_form_submit_delay_destination'),
- '#attributes' => array('class' => array('add-display')),
- // Allow JavaScript to remove the 'Add ' prefix from the button label when
- // placing the button in a "Add" dropdown menu.
- '#process' => array_merge(array('views_ui_form_button_was_clicked'), element_info_property('submit', '#process', array())),
- '#values' => array(t('Add !display', array('!display' => $label)), $label),
- );
- }
-
- return $element;
-}
-
-function views_ui_get_default_ajax_message() {
- return '
' . t("Click on an item to edit that item's details.") . '
';
-}
-
-/**
- * Submit handler to add a display to a view.
- */
-function views_ui_edit_form_submit_add_display($form, &$form_state) {
- $view = $form_state['view'];
-
- // Create the new display.
- $parents = $form_state['triggering_element']['#parents'];
- $display_type = array_pop($parents);
- $display_id = $view->storage->addDisplay($display_type);
- views_ui_cache_set($view);
-
- // Redirect to the new display's edit page.
- $form_state['redirect'] = 'admin/structure/views/view/' . $view->storage->name . '/edit/' . $display_id;
-}
-
-/**
- * Submit handler to duplicate a display for a view.
- */
-function views_ui_edit_form_submit_duplicate_display($form, &$form_state) {
- $view = $form_state['view'];
- $display_id = $form_state['display_id'];
-
- // Create the new display.
- $display = $view->storage->display[$display_id];
- $new_display_id = $view->storage->addDisplay($display['display_plugin']);
- $view->storage->display[$new_display_id] = $display;
-
- // By setting the current display the changed marker will appear on the new
- // display.
- $view->current_display = $new_display_id;
- views_ui_cache_set($view);
-
- // Redirect to the new display's edit page.
- $form_state['redirect'] = 'admin/structure/views/view/' . $view->storage->name . '/edit/' . $new_display_id;
-}
-
-/**
- * Submit handler to delete a display from a view.
- */
-function views_ui_edit_form_submit_delete_display($form, &$form_state) {
- $view = $form_state['view'];
- $display_id = $form_state['display_id'];
-
- // Mark the display for deletion.
- $view->storage->display[$display_id]['deleted'] = TRUE;
- views_ui_cache_set($view);
-
- // Redirect to the top-level edit page. The first remaining display will
- // become the active display.
- $form_state['redirect'] = 'admin/structure/views/view/' . $view->storage->name;
-}
-
-/**
- * Submit handler to add a restore a removed display to a view.
- */
-function views_ui_edit_form_submit_undo_delete_display($form, &$form_state) {
- // Create the new display
- $id = $form_state['display_id'];
- $form_state['view']->storage->display[$id]['deleted'] = FALSE;
-
- // Store in cache
- views_ui_cache_set($form_state['view']);
-
- // Redirect to the top-level edit page.
- $form_state['redirect'] = 'admin/structure/views/view/' . $form_state['view']->storage->name . '/edit/' . $id;
-}
-
-/**
- * Submit handler to enable a disabled display.
- */
-function views_ui_edit_form_submit_enable_display($form, &$form_state) {
- $id = $form_state['display_id'];
- // setOption doesn't work because this would might affect upper displays
- $form_state['view']->displayHandlers[$id]->setOption('enabled', TRUE);
-
- // Store in cache
- views_ui_cache_set($form_state['view']);
-
- // Redirect to the top-level edit page.
- $form_state['redirect'] = 'admin/structure/views/view/' . $form_state['view']->storage->name . '/edit/' . $id;
-}
-
-/**
- * Submit handler to disable display.
- */
-function views_ui_edit_form_submit_disable_display($form, &$form_state) {
- $id = $form_state['display_id'];
- $form_state['view']->displayHandlers[$id]->setOption('enabled', FALSE);
-
- // Store in cache
- views_ui_cache_set($form_state['view']);
-
- // Redirect to the top-level edit page.
- $form_state['redirect'] = 'admin/structure/views/view/' . $form_state['view']->storage->name . '/edit/' . $id;
-}
-
-/**
- * Submit handler when Preview button is clicked.
- */
-function views_ui_edit_form_submit_preview($form, &$form_state) {
- // Rebuild the form with a pristine $view object.
- $form_state['build_info']['args'][0] = views_ui_cache_load($form_state['view']->storage->name);
- $form_state['show_preview'] = TRUE;
- $form_state['rebuild'] = TRUE;
-}
-
-/**
- * Submit handler for form buttons that do not complete a form workflow.
- *
- * The Edit View form is a multistep form workflow, but with state managed by
- * the CTools object cache rather than $form_state['rebuild']. Without this
- * submit handler, buttons that add or remove displays would redirect to the
- * destination parameter (e.g., when the Edit View form is linked to from a
- * contextual link). This handler can be added to buttons whose form submission
- * should not yet redirect to the destination.
- */
-function views_ui_edit_form_submit_delay_destination($form, &$form_state) {
- $query = drupal_container()->get('request')->query;
- // @todo: Revisit this when http://drupal.org/node/1668866 is in.
- $destination = $query->get('destination');
- if (isset($destination) && $form_state['redirect'] !== FALSE) {
- if (!isset($form_state['redirect'])) {
- $form_state['redirect'] = current_path();
- }
- if (is_string($form_state['redirect'])) {
- $form_state['redirect'] = array($form_state['redirect']);
- }
- $options = isset($form_state['redirect'][1]) ? $form_state['redirect'][1] : array();
- if (!isset($options['query']['destination'])) {
- $options['query']['destination'] = $destination;
- }
- $form_state['redirect'][1] = $options;
- $query->remove('destination');
- }
-}
-
-/**
- * Adds tabs for navigating across Displays when editing a View.
- *
- * This function can be called from hook_menu_local_tasks_alter() to implement
- * these tabs as secondary local tasks, or it can be called from elsewhere if
- * having them as secondary local tasks isn't desired. The caller is responsible
- * for setting the active tab's #active property to TRUE.
- *
- * @param view $view
- * The view which will be edited.
- * @param $display_id
- * The display_id which is edited on the current request.
- */
-function views_ui_edit_page_display_tabs(ViewUI $view, $display_id = NULL) {
- $tabs = array();
-
- // Create a tab for each display.
- uasort($view->storage->display, '_views_position_sort');
- foreach ($view->storage->display as $id => $display) {
- $tabs[$id] = array(
- '#theme' => 'menu_local_task',
- '#link' => array(
- 'title' => views_ui_get_display_label($view, $id),
- 'href' => 'admin/structure/views/view/' . $view->storage->name . '/edit/' . $id,
- 'localized_options' => array(),
- ),
- );
- if (!empty($display['deleted'])) {
- $tabs[$id]['#link']['localized_options']['attributes']['class'][] = 'views-display-deleted-link';
- }
- if (isset($display['display_options']['enabled']) && !$display['display_options']['enabled']) {
- $tabs[$id]['#link']['localized_options']['attributes']['class'][] = 'views-display-disabled-link';
- }
- }
-
- // If the default display isn't supposed to be shown, don't display its tab, unless it's the only display.
- if ((!views_ui_show_default_display($view) && $display_id != 'default') && count($tabs) > 1) {
- $tabs['default']['#access'] = FALSE;
- }
-
- // Mark the display tab as red to show validation errors.
- $view->validate();
- foreach ($view->storage->display as $id => $display) {
- if (!empty($view->display_errors[$id])) {
- // Always show the tab.
- $tabs[$id]['#access'] = TRUE;
- // Add a class to mark the error and a title to make a hover tip.
- $tabs[$id]['#link']['localized_options']['attributes']['class'][] = 'error';
- $tabs[$id]['#link']['localized_options']['attributes']['title'] = t('This display has one or more validation errors; please review it.');
- }
- }
-
- return $tabs;
-}
-
-/**
- * Controls whether or not the default display should have its own tab on edit.
- */
-function views_ui_show_default_display(ViewUI $view) {
- // Always show the default display for advanced users who prefer that mode.
- $advanced_mode = config('views.settings')->get('ui.show.master_display');
- // For other users, show the default display only if there are no others, and
- // hide it if there's at least one "real" display.
- $additional_displays = (count($view->displayHandlers) == 1);
-
- return $advanced_mode || $additional_displays;
-}
-
-/**
- * Returns a renderable array representing the edit page for one display.
- */
-function views_ui_get_display_tab(ViewUI $view, $display_id) {
- $build = array();
- $display = $view->displayHandlers[$display_id];
- // If the plugin doesn't exist, display an error message instead of an edit
- // page.
- if (empty($display)) {
- $title = isset($display['display_title']) ? $display['display_title'] : t('Invalid');
- // @TODO: Improved UX for the case where a plugin is missing.
- $build['#markup'] = t("Error: Display @display refers to a plugin named '@plugin', but that plugin is not available.", array('@display' => $display['id'], '@plugin' => $display['display_plugin']));
- }
- // Build the content of the edit page.
- else {
- $build['details'] = views_ui_get_display_tab_details($view, $display->display);
- }
- // In AJAX context, views_ui_regenerate_tab() returns this outside of form
- // context, so hook_form_views_ui_edit_form_alter() is insufficient.
- drupal_alter('views_ui_display_tab', $build, $view, $display_id);
- return $build;
-}
-
-/**
- * Helper function to get the display details section of the edit UI.
- *
- * @param $view
- * @param $display
- *
- * @return array
- * A renderable page build array.
- */
-function views_ui_get_display_tab_details(ViewUI $view, $display) {
- $display_title = views_ui_get_display_label($view, $display['id'], FALSE);
- $build = array(
- '#theme_wrappers' => array('container'),
- '#attributes' => array('id' => 'edit-display-settings-details'),
- );
-
- // The following is for display purposes only. We need to determine if there is more than one button and wrap
- // the buttons in a .ctools-dropbutton class if more than one is present. Otherwise, we'll just wrap the
- // actions in the .ctools-button class.
- $is_display_deleted = !empty($display['deleted']);
- // The master display cannot be cloned.
- $is_default = $display['id'] == 'default';
- // @todo: Figure out why getOption doesn't work here.
- $is_enabled = $view->displayHandlers[$display['id']]->getOption('enabled');
-
- if (!$is_display_deleted && !$is_default) {
- $prefix = '
';
- $item_element = 'li';
- }
-
- if ($display['id'] != 'default') {
- $build['top']['#theme_wrappers'] = array('container');
- $build['top']['#attributes']['id'] = 'edit-display-settings-top';
- $build['top']['#attributes']['class'] = array('views-ui-display-tab-actions', 'views-ui-display-tab-bucket', 'clearfix');
-
- // The Delete, Duplicate and Undo Delete buttons.
- $build['top']['actions'] = array(
- '#prefix' => $prefix,
- '#suffix' => $suffix,
- );
-
- if (!$is_display_deleted) {
- if (!$is_enabled) {
- $build['top']['actions']['enable'] = array(
- '#type' => 'submit',
- '#value' => t('enable @display_title', array('@display_title' => $display_title)),
- '#limit_validation_errors' => array(),
- '#submit' => array('views_ui_edit_form_submit_enable_display', 'views_ui_edit_form_submit_delay_destination'),
- '#prefix' => '<' . $item_element . ' class="enable">',
- "#suffix" => '' . $item_element . '>',
- );
- }
- // Add a link to view the page.
- elseif ($view->displayHandlers[$display['id']]->hasPath()) {
- $path = $view->displayHandlers[$display['id']]->getPath();
- if (strpos($path, '%') === FALSE) {
- $build['top']['actions']['path'] = array(
- '#type' => 'link',
- '#title' => t('view @display', array('@display' => $display['display_title'])),
- '#options' => array('alt' => array(t("Go to the real page for this display"))),
- '#href' => $path,
- '#prefix' => '<' . $item_element . ' class="view">',
- "#suffix" => '' . $item_element . '>',
- );
- }
- }
- if (!$is_default) {
- $build['top']['actions']['duplicate'] = array(
- '#type' => 'submit',
- '#value' => t('clone @display_title', array('@display_title' => $display_title)),
- '#limit_validation_errors' => array(),
- '#submit' => array('views_ui_edit_form_submit_duplicate_display', 'views_ui_edit_form_submit_delay_destination'),
- '#prefix' => '<' . $item_element . ' class="duplicate">',
- "#suffix" => '' . $item_element . '>',
- );
- }
- // Always allow a display to be deleted.
- $build['top']['actions']['delete'] = array(
- '#type' => 'submit',
- '#value' => t('delete @display_title', array('@display_title' => $display_title)),
- '#limit_validation_errors' => array(),
- '#submit' => array('views_ui_edit_form_submit_delete_display', 'views_ui_edit_form_submit_delay_destination'),
- '#prefix' => '<' . $item_element . ' class="delete">',
- "#suffix" => '' . $item_element . '>',
- );
- if ($is_enabled) {
- $build['top']['actions']['disable'] = array(
- '#type' => 'submit',
- '#value' => t('disable @display_title', array('@display_title' => $display_title)),
- '#limit_validation_errors' => array(),
- '#submit' => array('views_ui_edit_form_submit_disable_display', 'views_ui_edit_form_submit_delay_destination'),
- '#prefix' => '<' . $item_element . ' class="disable">',
- "#suffix" => '' . $item_element . '>',
- );
- }
- }
- else {
- $build['top']['actions']['undo_delete'] = array(
- '#type' => 'submit',
- '#value' => t('undo delete of @display_title', array('@display_title' => $display_title)),
- '#limit_validation_errors' => array(),
- '#submit' => array('views_ui_edit_form_submit_undo_delete_display', 'views_ui_edit_form_submit_delay_destination'),
- '#prefix' => '<' . $item_element . ' class="undo-delete">',
- "#suffix" => '' . $item_element . '>',
- );
- }
-
- // The area above the three columns.
- $build['top']['display_title'] = array(
- '#theme' => 'views_ui_display_tab_setting',
- '#description' => t('Display name'),
- '#link' => $view->displayHandlers[$display['id']]->optionLink(check_plain($display_title), 'display_title'),
- );
- }
-
- $build['columns'] = array();
- $build['columns']['#theme_wrappers'] = array('container');
- $build['columns']['#attributes'] = array('id' => 'edit-display-settings-main', 'class' => array('clearfix', 'views-display-columns'));
-
- $build['columns']['first']['#theme_wrappers'] = array('container');
- $build['columns']['first']['#attributes'] = array('class' => array('views-display-column', 'first'));
-
- $build['columns']['second']['#theme_wrappers'] = array('container');
- $build['columns']['second']['#attributes'] = array('class' => array('views-display-column', 'second'));
-
- $build['columns']['second']['settings'] = array();
- $build['columns']['second']['header'] = array();
- $build['columns']['second']['footer'] = array();
- $build['columns']['second']['pager'] = array();
-
- // The third column buckets are wrapped in a fieldset.
- $build['columns']['third'] = array(
- '#type' => 'fieldset',
- '#title' => t('Advanced'),
- '#collapsible' => TRUE,
- '#collapsed' => TRUE,
- '#theme_wrappers' => array('fieldset', 'container'),
- '#attributes' => array(
- 'class' => array(
- 'views-display-column',
- 'third',
- ),
- ),
- );
-
- // Collapse the fieldset by default.
- if (config('views.settings')->get('ui.show.advanced_column')) {
- $build['columns']['third']['#collapsed'] = FALSE;
- }
-
- // Each option (e.g. title, access, display as grid/table/list) fits into one
- // of several "buckets," or boxes (Format, Fields, Sort, and so on).
- $buckets = array();
-
- // Fetch options from the display plugin, with a list of buckets they go into.
- $options = array();
- $view->displayHandlers[$display['id']]->optionsSummary($buckets, $options);
-
- // Place each option into its bucket.
- foreach ($options as $id => $option) {
- // Each option self-identifies as belonging in a particular bucket.
- $buckets[$option['category']]['build'][$id] = views_ui_edit_form_get_build_from_option($id, $option, $view, $display);
- }
-
- // Place each bucket into the proper column.
- foreach ($buckets as $id => $bucket) {
- // Let buckets identify themselves as belonging in a column.
- if (isset($bucket['column']) && isset($build['columns'][$bucket['column']])) {
- $column = $bucket['column'];
- }
- // If a bucket doesn't pick one of our predefined columns to belong to, put
- // it in the last one.
- else {
- $column = 'third';
- }
- if (isset($bucket['build']) && is_array($bucket['build'])) {
- $build['columns'][$column][$id] = $bucket['build'];
- $build['columns'][$column][$id]['#theme_wrappers'][] = 'views_ui_display_tab_bucket';
- $build['columns'][$column][$id]['#title'] = !empty($bucket['title']) ? $bucket['title'] : '';
- $build['columns'][$column][$id]['#name'] = !empty($bucket['title']) ? $bucket['title'] : $id;
- }
- }
-
- $build['columns']['first']['fields'] = views_ui_edit_form_get_bucket('field', $view, $display);
- $build['columns']['first']['filters'] = views_ui_edit_form_get_bucket('filter', $view, $display);
- $build['columns']['first']['sorts'] = views_ui_edit_form_get_bucket('sort', $view, $display);
- $build['columns']['second']['header'] = views_ui_edit_form_get_bucket('header', $view, $display);
- $build['columns']['second']['footer'] = views_ui_edit_form_get_bucket('footer', $view, $display);
- $build['columns']['third']['arguments'] = views_ui_edit_form_get_bucket('argument', $view, $display);
- $build['columns']['third']['relationships'] = views_ui_edit_form_get_bucket('relationship', $view, $display);
- $build['columns']['third']['empty'] = views_ui_edit_form_get_bucket('empty', $view, $display);
-
- return $build;
-}
-
-/**
- * Build a renderable array representing one option on the edit form.
- *
- * This function might be more logical as a method on an object, if a suitable
- * object emerges out of refactoring.
- */
-function views_ui_edit_form_get_build_from_option($id, $option, ViewUI $view, $display) {
- $option_build = array();
- $option_build['#theme'] = 'views_ui_display_tab_setting';
-
- $option_build['#description'] = $option['title'];
-
- $option_build['#link'] = $view->displayHandlers[$display['id']]->optionLink($option['value'], $id, '', empty($option['desc']) ? '' : $option['desc']);
-
- $option_build['#links'] = array();
- if (!empty($option['links']) && is_array($option['links'])) {
- foreach ($option['links'] as $link_id => $link_value) {
- $option_build['#settings_links'][] = $view->displayHandlers[$display['id']]->optionLink($option['setting'], $link_id, 'views-button-configure', $link_value);
- }
- }
-
- if (!empty($view->displayHandlers[$display['id']]->options['defaults'][$id])) {
- $display_id = 'default';
- $option_build['#defaulted'] = TRUE;
- }
- else {
- $display_id = $display['id'];
- if (!$view->displayHandlers[$display['id']]->isDefaultDisplay()) {
- if ($view->displayHandlers[$display['id']]->defaultableSections($id)) {
- $option_build['#overridden'] = TRUE;
- }
- }
- }
- $option_build['#attributes']['class'][] = drupal_clean_css_identifier($display_id . '-' . $id);
- return $option_build;
-}
-
function template_preprocess_views_ui_display_tab_setting(&$variables) {
static $zebra = 0;
$variables['zebra'] = ($zebra % 2 === 0 ? 'odd' : 'even');
@@ -1824,195 +640,6 @@ function views_ui_pre_render_move_argument_options($form) {
return $form;
}
-/**
- * Custom form radios process function.
- *
- * Roll out a single radios element to a list of radios,
- * using the options array as index.
- * While doing that, create a container element underneath each option, which
- * contains the settings related to that option.
- *
- * @see form_process_radios()
- */
-function views_ui_process_container_radios($element) {
- if (count($element['#options']) > 0) {
- foreach ($element['#options'] as $key => $choice) {
- $element += array($key => array());
- // Generate the parents as the autogenerator does, so we will have a
- // unique id for each radio button.
- $parents_for_id = array_merge($element['#parents'], array($key));
-
- $element[$key] += array(
- '#type' => 'radio',
- '#title' => $choice,
- // The key is sanitized in drupal_attributes() during output from the
- // theme function.
- '#return_value' => $key,
- '#default_value' => isset($element['#default_value']) ? $element['#default_value'] : NULL,
- '#attributes' => $element['#attributes'],
- '#parents' => $element['#parents'],
- '#id' => drupal_html_id('edit-' . implode('-', $parents_for_id)),
- '#ajax' => isset($element['#ajax']) ? $element['#ajax'] : NULL,
- );
- $element[$key . '_options'] = array(
- '#type' => 'container',
- '#attributes' => array('class' => array('views-admin-dependent')),
- );
- }
- }
- return $element;
-}
-
-/**
- * Import a view from cut & paste.
- */
-function views_ui_import_page($form, &$form_state) {
- $form['name'] = array(
- '#type' => 'textfield',
- '#title' => t('View name'),
- '#description' => t('Enter the name to use for this view if it is different from the source view. Leave blank to use the name of the view.'),
- );
-
- $form['name_override'] = array(
- '#type' => 'checkbox',
- '#title' => t('Replace an existing view if one exists with the same name'),
- );
-
- $form['bypass_validation'] = array(
- '#type' => 'checkbox',
- '#title' => t('Bypass view validation'),
- '#description' => t('Bypass the validation of plugins and handlers when importing this view.'),
- );
-
- $form['view'] = array(
- '#type' => 'textarea',
- '#title' => t('Paste view code here'),
- '#required' => TRUE,
- );
-
- $form['submit'] = array(
- '#type' => 'submit',
- '#value' => t('Import'),
- '#submit' => array('views_ui_import_submit'),
- '#validate' => array('views_ui_import_validate'),
- );
- return $form;
-}
-
-/**
- * Validate handler to import a view.
- */
-function views_ui_import_validate($form, &$form_state) {
- $view = '';
- // Be forgiving if someone pastes views code that starts with 'api_version) || $view->api_version < 2) {
- form_error($form['view'], t('That view is not compatible with this version of Views.
- If you have a view from views1 you have to go to a drupal6 installation and import it there.'));
- }
- elseif (version_compare($view->api_version, views_api_version(), '>')) {
- form_error($form['view'], t('That view is created for the version @import_version of views, but you only have @api_version', array(
- '@import_version' => $view->api_version,
- '@api_version' => views_api_version())));
- }
-
- // View name must be alphanumeric or underscores, no other punctuation.
- if (!empty($form_state['values']['name']) && preg_match('/[^a-zA-Z0-9_]/', $form_state['values']['name'])) {
- form_error($form['name'], t('View name must be alphanumeric or underscores only.'));
- }
-
- if ($form_state['values']['name']) {
- $view->storage->name = $form_state['values']['name'];
- }
-
- $test = views_get_view($view->storage->name);
- if (!$form_state['values']['name_override']) {
- if ($test && $test->type != t('Default')) {
- form_set_error('', t('A view by that name already exists; please choose a different name'));
- }
- }
- else {
- if ($test->vid) {
- $view->vid = $test->vid;
- }
- }
-
- // Make sure base table gets set properly if it got moved.
- $view->update();
-
- $view->initDisplay();
-
- $broken = FALSE;
-
- // Bypass the validation of view pluigns/handlers if option is checked.
- if (!$form_state['values']['bypass_validation']) {
- // Make sure that all plugins and handlers needed by this view actually exist.
- foreach ($view->displayHandlers as $id => $display) {
- if (empty($display) || !empty($display->broken)) {
- drupal_set_message(t('Display plugin @plugin is not available.', array('@plugin' => $display->getPluginId())), 'error');
- $broken = TRUE;
- continue;
- }
-
- $style = $display->getOption('style');
- $plugin = views_get_plugin('style', $style['type']);
- if (!$plugin) {
- drupal_set_message(t('Style plugin @plugin is not available.', array('@plugin' => $style['type'])), 'error');
- $broken = TRUE;
- }
- elseif ($plugin->usesRowPlugin()) {
- $row = $display->getOption('row');
- $plugin = views_get_plugin('row', $row['type']);
- if (!$plugin) {
- drupal_set_message(t('Row plugin @plugin is not available.', array('@plugin' => $row['type'])), 'error');
- $broken = TRUE;
- }
- }
-
- foreach (ViewExecutable::viewsHandlerTypes() as $type => $info) {
- $handlers = $display->getHandlers($type);
- if ($handlers) {
- foreach ($handlers as $id => $handler) {
- if ($handler->broken()) {
- drupal_set_message(t('@type handler @table.@field is not available.', array(
- '@type' => $info['stitle'],
- '@table' => $handler->table,
- '@field' => $handler->field,
- )), 'error');
- $broken = TRUE;
- }
- }
- }
- }
- }
- }
-
- if ($broken) {
- form_set_error('', t('Unable to import view.'));
- }
-
- $form_state['view'] = &$view;
-}
-
-/**
- * Submit handler for view import.
- */
-function views_ui_import_submit($form, &$form_state) {
- // Store in cache and then go to edit.
- views_ui_cache_set($form_state['view']);
- $form_state['redirect'] = 'admin/structure/views/view/' . $form_state['view']->storage->name . '/edit';
-}
-
/**
* Validate that a view is complete and whole.
*/
@@ -2044,9 +671,14 @@ function views_ui_edit_view_form_submit($form, &$form_state) {
// Rename display ids if needed.
foreach ($form_state['view']->displayHandlers as $id => $display) {
if (!empty($display->display['new_id'])) {
- $form_state['view']->displayHandlers[$id]['id'] = $display['new_id'];
+ $new_id = $display->display['new_id'];
+ $form_state['view']->displayHandlers[$new_id] = $form_state['view']->displayHandlers[$id];
+ $form_state['view']->displayHandlers[$new_id]->display['id'] = $new_id;
+
+ $form_state['view']->storage->display[$new_id] = $form_state['view']->storage->display[$id];
+ unset($form_state['view']->storage->display[$id]);
// Redirect the user to the renamed display to be sure that the page itself exists and doesn't throw errors.
- $form_state['redirect'] = 'admin/structure/views/view/' . $form_state['view']->storage->name . '/edit/' . $display['new_id'];
+ $form_state['redirect'] = 'admin/structure/views/view/' . $form_state['view']->storage->name . '/edit/' . $new_id;
}
}
@@ -2091,428 +723,6 @@ function views_ui_edit_view_form_cancel($form, &$form_state) {
}
}
-function views_ui_edit_view_form_delete($form, &$form_state) {
- $request = drupal_container()->get('request')->request;
- // @todo: Revisit this when http://drupal.org/node/1668866 is in.
- if ($request->get('destination') !== NULL) {
- $request->remove('destination');
- }
- // Redirect to the delete confirm page
- $form_state['redirect'] = array('admin/structure/views/view/' . $form_state['view']->storage->name . '/delete', array('query' => drupal_get_destination() + array('cancel' => 'admin/structure/views/view/' . $form_state['view']->storage->name . '/edit')));
-}
-
-/**
- * Add information about a section to a display.
- */
-function views_ui_edit_form_get_bucket($type, ViewUI $view, $display) {
- $build = array(
- '#theme_wrappers' => array('views_ui_display_tab_bucket'),
- );
- $types = ViewExecutable::viewsHandlerTypes();
-
- $build['#overridden'] = FALSE;
- $build['#defaulted'] = FALSE;
-
- $build['#name'] = $build['#title'] = $types[$type]['title'];
-
- // Different types now have different rearrange forms, so we use this switch
- // to get the right one.
- switch ($type) {
- case 'filter':
- $rearrange_url = "admin/structure/views/nojs/rearrange-$type/{$view->storage->name}/{$display['id']}/$type";
- $rearrange_text = t('And/Or, Rearrange');
- // TODO: Add another class to have another symbol for filter rearrange.
- $class = 'icon compact rearrange';
- break;
- case 'field':
- // Fetch the style plugin info so we know whether to list fields or not.
- $style = $view->displayHandlers[$display['id']]->getOption('style');
- $style_plugin = $view->displayHandlers[$display['id']]->getPlugin('style', $style['type']);
- $uses_fields = $style_plugin && $style_plugin->usesFields();
- if (!$uses_fields) {
- $build['fields'][] = array(
- '#markup' => t('The selected style or row format does not utilize fields.'),
- '#theme_wrappers' => array('views_container'),
- '#attributes' => array('class' => array('views-display-setting')),
- );
- return $build;
- }
-
- default:
- $rearrange_url = "admin/structure/views/nojs/rearrange/{$view->storage->name}/{$display['id']}/$type";
- $rearrange_text = t('Rearrange');
- $class = 'icon compact rearrange';
- }
-
- // Create an array of actions to pass to theme_links
- $actions = array();
- $count_handlers = count($view->displayHandlers[$display['id']]->getHandlers($type));
- $actions['add'] = array(
- 'title' => t('Add'),
- 'href' => "admin/structure/views/nojs/add-item/{$view->storage->name}/{$display['id']}/$type",
- 'attributes' => array('class' => array('icon compact add', 'views-ajax-link'), 'title' => t('Add'), 'id' => 'views-add-' . $type),
- 'html' => TRUE,
- );
- if ($count_handlers > 0) {
- $actions['rearrange'] = array(
- 'title' => $rearrange_text,
- 'href' => $rearrange_url,
- 'attributes' => array('class' => array($class, 'views-ajax-link'), 'title' => t('Rearrange'), 'id' => 'views-rearrange-' . $type),
- 'html' => TRUE,
- );
- }
-
- // Render the array of links
- $build['#actions'] = theme('links__ctools_dropbutton',
- array(
- 'links' => $actions,
- 'attributes' => array(
- 'class' => array('inline', 'links', 'actions', 'horizontal', 'right')
- ),
- 'class' => array('views-ui-settings-bucket-operations'),
- )
- );
-
- if (!$view->displayHandlers[$display['id']]->isDefaultDisplay()) {
- if (!$view->displayHandlers[$display['id']]->isDefaulted($types[$type]['plural'])) {
- $build['#overridden'] = TRUE;
- }
- else {
- $build['#defaulted'] = TRUE;
- }
- }
-
- // If there's an options form for the bucket, link to it.
- if (!empty($types[$type]['options'])) {
- $build['#title'] = l($build['#title'], "admin/structure/views/nojs/config-type/{$view->storage->name}/{$display['id']}/$type", array('attributes' => array('class' => array('views-ajax-link'), 'id' => 'views-title-' . $type)));
- }
-
- static $relationships = NULL;
- if (!isset($relationships)) {
- // Get relationship labels
- $relationships = array();
- foreach ($view->displayHandlers[$display['id']]->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 = $view->display_handler->getOption('filter_groups');
- // If there is only one group but it is using the "OR" filter, we still
- // treat it as a group for display purposes, since we want to display the
- // "OR" label next to items within the group.
- if (!empty($group_info['groups']) && (count($group_info['groups']) > 1 || current($group_info['groups']) == 'OR')) {
- $grouping = TRUE;
- $groups = array(0 => array());
- }
- }
-
- $build['fields'] = array();
-
- foreach ($view->displayHandlers[$display['id']]->getOption($types[$type]['plural']) as $id => $field) {
- // Build the option link for this handler ("Node: ID = article").
- $build['fields'][$id] = array();
- $build['fields'][$id]['#theme'] = 'views_ui_display_tab_setting';
-
- $handler = $view->displayHandlers[$display['id']]->getHandler($type, $id);
- if (empty($handler)) {
- $build['fields'][$id]['#class'][] = 'broken';
- $field_name = t('Broken/missing handler: @table > @field', array('@table' => $field['table'], '@field' => $field['field']));
- $build['fields'][$id]['#link'] = l($field_name, "admin/structure/views/nojs/config-item/{$view->storage->name}/{$display['id']}/$type/$id", array('attributes' => array('class' => array('views-ajax-link')), 'html' => TRUE));
- continue;
- }
-
- $field_name = check_plain($handler->adminLabel(TRUE));
- if (!empty($field['relationship']) && !empty($relationships[$field['relationship']])) {
- $field_name = '(' . $relationships[$field['relationship']] . ') ' . $field_name;
- }
-
- $description = filter_xss_admin($handler->adminSummary());
- $link_text = $field_name . (empty($description) ? '' : " ($description)");
- $link_attributes = array('class' => array('views-ajax-link'));
- if (!empty($field['exclude'])) {
- $link_attributes['class'][] = 'views-field-excluded';
- }
- $build['fields'][$id]['#link'] = l($link_text, "admin/structure/views/nojs/config-item/{$view->storage->name}/{$display['id']}/$type/$id", array('attributes' => $link_attributes, 'html' => TRUE));
- $build['fields'][$id]['#class'][] = drupal_clean_css_identifier($display['id']. '-' . $type . '-' . $id);
-
- if ($view->displayHandlers[$display['id']]->useGroupBy() && $handler->usesGroupBy()) {
- $build['fields'][$id]['#settings_links'][] = l('' . t('Aggregation settings') . '', "admin/structure/views/nojs/config-item-group/{$view->storage->name}/{$display['id']}/$type/$id", array('attributes' => array('class' => 'views-button-configure views-ajax-link', 'title' => t('Aggregation settings')), 'html' => TRUE));
- }
-
- if ($handler->hasExtraOptions()) {
- $build['fields'][$id]['#settings_links'][] = l('' . t('Settings') . '', "admin/structure/views/nojs/config-item-extra/{$view->storage->name}/{$display['id']}/$type/$id", array('attributes' => array('class' => array('views-button-configure', 'views-ajax-link'), 'title' => t('Settings')), 'html' => TRUE));
- }
-
- if ($grouping) {
- $gid = $handler->options['group'];
-
- // Show in default group if the group does not exist.
- if (empty($group_info['groups'][$gid])) {
- $gid = 0;
- }
- $groups[$gid][] = $id;
- }
- }
-
- // If using grouping, re-order fields so that they show up properly in the list.
- if ($type == 'filter' && $grouping) {
- $store = $build['fields'];
- $build['fields'] = array();
- foreach ($groups as $gid => $contents) {
- // Display an operator between each group.
- if (!empty($build['fields'])) {
- $build['fields'][] = array(
- '#theme' => 'views_ui_display_tab_setting',
- '#class' => array('views-group-text'),
- '#link' => ($group_info['operator'] == 'OR' ? t('OR') : t('AND')),
- );
- }
- // Display an operator between each pair of filters within the group.
- $keys = array_keys($contents);
- $last = end($keys);
- foreach ($contents as $key => $pid) {
- if ($key != $last) {
- $store[$pid]['#link'] .= ' ' . ($group_info['groups'][$gid] == 'OR' ? t('OR') : t('AND'));
- }
- $build['fields'][$pid] = $store[$pid];
- }
- }
- }
-
- return $build;
-}
-
-/**
- * Regenerate the current tab for AJAX updates.
- */
-function views_ui_regenerate_tab(ViewUI $view, &$output, $display_id) {
- if (!$view->setDisplay('default')) {
- return;
- }
-
- // Regenerate the main display area.
- $build = views_ui_get_display_tab($view, $display_id);
- views_ui_add_microweights($build);
- $output[] = ajax_command_html('#views-tab-' . $display_id, drupal_render($build));
-
- // Regenerate the top area so changes to display names and order will appear.
- $build = views_ui_render_display_top($view, $display_id);
- views_ui_add_microweights($build);
- $output[] = ajax_command_replace('#views-display-top', drupal_render($build));
-}
-
-/**
- * Recursively adds microweights to a render array, similar to what form_builder() does for forms.
- *
- * @todo Submit a core patch to fix drupal_render() to do this, so that all
- * render arrays automatically preserve array insertion order, as forms do.
- */
-function views_ui_add_microweights(&$build) {
- $count = 0;
- foreach (element_children($build) as $key) {
- if (!isset($build[$key]['#weight'])) {
- $build[$key]['#weight'] = $count/1000;
- }
- views_ui_add_microweights($build[$key]);
- $count++;
- }
-}
-
-/**
- * Provide a standard set of Apply/Cancel/OK buttons for the forms. Also provide
- * a hidden op operator because the forms plugin doesn't seem to properly
- * provide which button was clicked.
- *
- * TODO: Is the hidden op operator still here somewhere, or is that part of the
- * docblock outdated?
- */
-function views_ui_standard_form_buttons(&$form, &$form_state, $form_id, $name = NULL, $third = NULL, $submit = NULL) {
- $form['buttons'] = array(
- '#prefix' => '
',
- '#suffix' => '
',
- );
-
- if (empty($name)) {
- $name = t('Apply');
- $view = $form_state['view'];
- if (!empty($view->stack) && count($view->stack) > 1) {
- $name = t('Apply and continue');
- }
- $names = array(t('Apply'), t('Apply and continue'));
- }
-
- // Forms that are purely informational set an ok_button flag, so we know not
- // to create an "Apply" button for them.
- if (empty($form_state['ok_button'])) {
- $form['buttons']['submit'] = array(
- '#type' => 'submit',
- '#value' => $name,
- // The regular submit handler ($form_id . '_submit') does not apply if
- // we're updating the default display. It does apply if we're updating
- // the current display. Since we have no way of knowing at this point
- // which display the user wants to update, views_ui_standard_submit will
- // take care of running the regular submit handler as appropriate.
- '#submit' => array('views_ui_standard_submit'),
- );
- // 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.
- 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 (function_exists($form_id . '_validate')) {
- $form['buttons']['submit']['#validate'][] = $form_id . '_validate';
- }
- }
-
- // Create a "Cancel" button. For purely informational forms, label it "OK".
- $cancel_submit = function_exists($form_id . '_cancel') ? $form_id . '_cancel' : 'views_ui_standard_cancel';
- $form['buttons']['cancel'] = array(
- '#type' => 'submit',
- '#value' => empty($form_state['ok_button']) ? t('Cancel') : t('Ok'),
- '#submit' => array($cancel_submit),
- '#validate' => array(),
- );
-
- // Some forms specify a third button, with a name and submit handler.
- if ($third) {
- if (empty($submit)) {
- $submit = 'third';
- }
- $third_submit = function_exists($form_id . '_' . $submit) ? $form_id . '_' . $submit : 'views_ui_standard_cancel';
-
- $form['buttons'][$submit] = array(
- '#type' => 'submit',
- '#value' => $third,
- '#validate' => array(),
- '#submit' => array($third_submit),
- );
- }
-
- // Compatibility, to be removed later: // TODO: When is "later"?
- // We used to set these items on the form, but now we want them on the $form_state:
- if (isset($form['#title'])) {
- $form_state['title'] = $form['#title'];
- }
- if (isset($form['#url'])) {
- $form_state['url'] = $form['#url'];
- }
- if (isset($form['#section'])) {
- $form_state['#section'] = $form['#section'];
- }
- // Finally, we never want these cached -- our object cache does that for us.
- $form['#no_cache'] = TRUE;
-
- // If this isn't an ajaxy form, then we want to set the title.
- if (!empty($form['#title'])) {
- drupal_set_title($form['#title']);
- }
-}
-
-/**
- * Basic submit handler applicable to all 'standard' forms.
- *
- * This submit handler determines whether the user wants the submitted changes
- * to apply to the default display or to the current display, and dispatches
- * control appropriately.
- */
-function views_ui_standard_submit($form, &$form_state) {
- // Determine whether the values the user entered are intended to apply to
- // the current display or the default display.
-
- list($was_defaulted, $is_defaulted, $revert) = views_ui_standard_override_values($form, $form_state);
-
- // Based on the user's choice in the display dropdown, determine which display
- // these changes apply to.
- if ($revert) {
- // If it's revert just change the override and return.
- $display = &$form_state['view']->displayHandlers[$form_state['display_id']];
- $display->optionsOverride($form, $form_state);
-
- // Don't execute the normal submit handling but still store the changed view into cache.
- views_ui_cache_set($form_state['view']);
- return;
- }
- elseif ($was_defaulted === $is_defaulted) {
- // We're not changing which display these form values apply to.
- // Run the regular submit handler for this form.
- }
- elseif ($was_defaulted && !$is_defaulted) {
- // We were using the default display's values, but we're now overriding
- // the default display and saving values specific to this display.
- $display = &$form_state['view']->displayHandlers[$form_state['display_id']];
- // optionsOverride toggles the override of this section.
- $display->optionsOverride($form, $form_state);
- $display->submitOptionsForm($form, $form_state);
- }
- elseif (!$was_defaulted && $is_defaulted) {
- // We used to have an override for this display, but the user now wants
- // to go back to the default display.
- // Overwrite the default display with the current form values, and make
- // the current display use the new default values.
- $display = &$form_state['view']->displayHandlers[$form_state['display_id']];
- // optionsOverride toggles the override of this section.
- $display->optionsOverride($form, $form_state);
- $display->submitOptionsForm($form, $form_state);
- }
-
- $submit_handler = $form['#form_id'] . '_submit';
- if (function_exists($submit_handler)) {
- $submit_handler($form, $form_state);
- }
-}
-
-/**
- * Return the was_defaulted, is_defaulted and revert state of a form.
- */
-function views_ui_standard_override_values($form, $form_state) {
- // Make sure the dropdown exists in the first place.
- if (isset($form_state['values']['override']['dropdown'])) {
- // #default_value is used to determine whether it was the default value or not.
- // So the available options are: $display, 'default' and 'default_revert', not 'defaults'.
- $was_defaulted = ($form['override']['dropdown']['#default_value'] === 'defaults');
- $is_defaulted = ($form_state['values']['override']['dropdown'] === 'default');
- $revert = ($form_state['values']['override']['dropdown'] === 'default_revert');
-
- if ($was_defaulted !== $is_defaulted && isset($form['#section'])) {
- // We're changing which display these values apply to.
- // Update the #section so it knows what to mark changed.
- $form['#section'] = str_replace('default-', $form_state['display_id'] . '-', $form['#section']);
- }
- }
- else {
- // The user didn't get the dropdown for overriding the default display.
- $was_defaulted = FALSE;
- $is_defaulted = FALSE;
- $revert = FALSE;
- }
-
- return array($was_defaulted, $is_defaulted, $revert);
-}
-
-/**
- * Submit handler for cancel button
- */
-function views_ui_standard_cancel($form, &$form_state) {
- if (!empty($form_state['view']->changed) && isset($form_state['view']->form_cache)) {
- unset($form_state['view']->form_cache);
- views_ui_cache_set($form_state['view']);
- }
-
- $form_state['redirect'] = 'admin/structure/views/view/' . $form_state['view']->storage->name . '/edit';
-}
-
/**
* Add a