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 4da5800..11fc9cd 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 @@ -386,7 +386,8 @@ public function attachTo(ViewExecutable $view, $display_id) { } /** * Static member function to list which sections are defaultable - * and what items each section contains. + * + * Static member function to list which sec and what items each section contains. */ public function defaultableSections($section = NULL) { $sections = array( @@ -1338,7 +1339,7 @@ public function optionsSummary(&$categories, &$options) { public function buildOptionsForm(&$form, &$form_state) { parent::buildOptionsForm($form, $form_state); if ($this->defaultableSections($form_state['section'])) { - views_ui_standard_display_dropdown($form, $form_state, $form_state['section']); + $form_state['view']->getFormProgressIndicator($form, $form_state, $form_state['section']); } $form['#title'] = check_plain($this->display['display_title']) . ': '; diff --git a/core/modules/views/lib/Drupal/views/ViewExecutable.php b/core/modules/views/lib/Drupal/views/ViewExecutable.php index 51f53fb..c0e28ce 100644 --- a/core/modules/views/lib/Drupal/views/ViewExecutable.php +++ b/core/modules/views/lib/Drupal/views/ViewExecutable.php @@ -201,7 +201,7 @@ class ViewExecutable { * An array containing Drupal\views\Plugin\views\display\DisplayPluginBase * objects. * - * @var array + * @var \Drupal\Component\Plugin\PluginBag */ public $displayHandlers; diff --git a/core/modules/views_ui/admin.inc b/core/modules/views_ui/admin.inc index a723854..886dce2 100644 --- a/core/modules/views_ui/admin.inc +++ b/core/modules/views_ui/admin.inc @@ -332,63 +332,7 @@ function views_ui_pre_render_move_argument_options($form) { * change whether this info is stored on the default display or on * the current display. */ -function views_ui_standard_display_dropdown(&$form, &$form_state, $section) { - $view = &$form_state['view']; - $display_id = $form_state['display_id']; - $executable = $view->get('executable'); - $displays = $executable->displayHandlers; - $current_display = $executable->display_handler; - - // @todo Move this to a separate function if it's needed on any forms that - // don't have the display dropdown. - $form['override'] = array( - '#prefix' => '
', - '#suffix' => '
', - '#weight' => -1000, - '#tree' => TRUE, - ); - - // Add the "2 of 3" progress indicator. - if ($form_progress = $view->getFormProgress()) { - $form['progress']['#markup'] = '
' . t('@current of @total', array('@current' => $form_progress['current'], '@total' => $form_progress['total'])) . '
'; - $form['progress']['#weight'] = -1001; - } - - if ($current_display->isDefaultDisplay()) { - return; - } - - // Determine whether any other displays have overrides for this section. - $section_overrides = FALSE; - $section_defaulted = $current_display->isDefaulted($section); - foreach ($displays as $id => $display) { - if ($id === 'default' || $id === $display_id) { - continue; - } - if ($display && !$display->isDefaulted($section)) { - $section_overrides = TRUE; - } - } - - $display_dropdown['default'] = ($section_overrides ? t('All displays (except overridden)') : t('All displays')); - $display_dropdown[$display_id] = t('This @display_type (override)', array('@display_type' => $current_display->getPluginId())); - // Only display the revert option if we are in a overridden section. - if (!$section_defaulted) { - $display_dropdown['default_revert'] = t('Revert to default'); - } - - $form['override']['dropdown'] = array( - '#type' => 'select', - '#title' => t('For'), // @TODO: Translators may need more context than this. - '#options' => $display_dropdown, - ); - if ($current_display->isDefaulted($section)) { - $form['override']['dropdown']['#default_value'] = 'defaults'; - } - else { - $form['override']['dropdown']['#default_value'] = $display_id; - } - +function views_ui_standard_progress_indicator(&$form, &$form_state, $section) { } /** diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/AddItem.php b/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/AddItem.php index 1c8d13e..1161765 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/AddItem.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/AddItem.php @@ -76,8 +76,8 @@ public function buildForm(array $form, array &$form_state) { $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); + // Add the progress indicator. + $form_state['view']->getFormProgressIndicator($form, $form_state, $form_state['section']); // Figure out all the base tables allowed based upon what the relationships provide. $base_tables = $executable->getBaseTables(); @@ -173,7 +173,7 @@ public function buildForm(array $form, array &$form_state) { '#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))); + $view->getStandardButtons($form, $form_state, 'views_ui_add_item_form', $section, 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) { diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/ConfigItem.php b/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/ConfigItem.php index e35cee0..153cf8b 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/ConfigItem.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/ConfigItem.php @@ -82,7 +82,7 @@ public function buildForm(array $form, array &$form_state) { // 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']); + $form_state['view']->getFormProgressIndicator($form, $form_state, $form_state['section']); } // A whole bunch of code to figure out what relationships are valid for @@ -162,12 +162,7 @@ public function buildForm(array $form, array &$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); + $view->getStandardButtons($form, $form_state, 'views_ui_config_item_form', $form_state['section']); // Add a 'remove' button. $form['buttons']['remove'] = array( '#type' => 'submit', diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/Display.php b/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/Display.php index d8c1e9a..7e8c757 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/Display.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/Display.php @@ -92,7 +92,7 @@ public function buildForm(array $form, array &$form_state) { $name = $form_state['update_name']; } - $view->getStandardButtons($form, $form_state, 'views_ui_edit_display_form', $name); + $view->getStandardButtons($form, $form_state, 'views_ui_edit_display_form', $form_state['section'], $name); return $form; } diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/Rearrange.php b/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/Rearrange.php index 75c469f..38e0e2b 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/Rearrange.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/Rearrange.php @@ -63,7 +63,7 @@ public function buildForm(array $form, array &$form_state) { if ($display->defaultableSections($types[$type]['plural'])) { $form_state['section'] = $types[$type]['plural']; - views_ui_standard_display_dropdown($form, $form_state, $form_state['section']); + $form_state['view']->getFormProgressIndicator($form, $form_state, $form_state['section']); } $count = 0; @@ -121,12 +121,7 @@ public function buildForm(array $form, array &$form_state) { ); } - $name = NULL; - if (isset($form_state['update_name'])) { - $name = $form_state['update_name']; - } - - $view->getStandardButtons($form, $form_state, 'views_ui_rearrange_form'); + $view->getStandardButtons($form, $form_state, 'views_ui_rearrange_form', $form_state['section']); return $form; } diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/RearrangeFilter.php b/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/RearrangeFilter.php index ff5db0a..5095a98 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/RearrangeFilter.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/Form/Ajax/RearrangeFilter.php @@ -49,7 +49,7 @@ public function buildForm(array $form, array &$form_state) { if ($display->defaultableSections($types[$type]['plural'])) { $form_state['section'] = $types[$type]['plural']; - views_ui_standard_display_dropdown($form, $form_state, $form_state['section']); + $form_state['view']->getFormProgressIndicator($form, $form_state, $form_state['section']); } if (!empty($view->form_cache)) { @@ -196,7 +196,7 @@ public function buildForm(array $form, array &$form_state) { $name = $form_state['update_name']; } - $view->getStandardButtons($form, $form_state, 'views_ui_rearrange_filter_form'); + $view->getStandardButtons($form, $form_state, 'views_ui_rearrange_filter_form', $form_state['section']); $form['buttons']['add_group'] = array( '#type' => 'submit', '#value' => t('Create new filter group'), diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php index 5877f28..bf91854 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php @@ -187,52 +187,28 @@ public static function getDefaultAJAXMessage() { } /** - * 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. + * Basic submit handler to set the settings to the default display. */ - public function standardSubmit($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) = $this->getOverrideValues($form, $form_state); + public function standardSubmitDefault($form, &$form_state) { + $display = $this->executable->displayHandlers->get($form_state['display_id']); + $display->setOverride($form_state['section'], TRUE); + $display->submitOptionsForm($form, $form_state); + $this->standardSubmit($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 = &$this->executable->displayHandlers->get($form_state['display_id']); - $display->optionsOverride($form, $form_state); + public function standardSubmitDisplay($form, &$form_state) { + $display = $this->executable->displayHandlers->get($form_state['display_id']); + $display->setOverride($form_state['section'], FALSE); + $display->submitOptionsForm($form, $form_state); + $this->standardSubmit($form, $form_state); + } - // Don't execute the normal submit handling but still store the changed view into cache. - $this->cacheSet(); - 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 = &$this->executable->displayHandlers->get($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 = &$this->executable->displayHandlers->get($form_state['display_id']); - // optionsOverride toggles the override of this section. - $display->optionsOverride($form, $form_state); - $display->submitOptionsForm($form, $form_state); - } + // @TODO Add a button to revert to default. + /** + * Basic submit handler applicable to all 'standard' forms. + */ + public function standardSubmit($form, &$form_state) { $submit_handler = $form['#form_id'] . '_submit'; if (isset($form_state['build_info']['callback_object'])) { $submit_handler = array($form_state['build_info']['callback_object'], 'submitForm'); @@ -258,6 +234,64 @@ public function standardCancel($form, &$form_state) { } /** + * Provide the apply button for all forms. + */ + public function getApplyButton(&$form, &$form_state, $section) { + // Forms that are purely informational set an ok_button flag, so we know not + if (!empty($form_state['ok_button'])) { + return; + } + + $view = $form_state['view']; + $executable = $view->get('executable'); + $displays = $executable->displayHandlers; + $current_display = $executable->display_handler; + $display_id = $executable->current_display; + + // Determine whether the form applies to a defaulted display. + $is_defaulted = $this->isFormDefaulted($section); + + $form['buttons']['#type'] = 'actions'; + $form['buttons']['#titlte'] = t('Save buttons'); + + $form['buttons']['submit_default'] = array( + '#type' => 'submit', + '#value' => t('Apply to all'), + '#dropbutton' => 'save', + '#submit' => array(array($this, 'standardSubmitDefault')), + '#button_type' => 'primary', + '#weight' => $is_defaulted ? 0 : 10, + ); + + // Change the label of the apply button if the user changes the default + // display. + if (!$current_display->defaultableSections($section)) { + $form['buttons']['submit_default']['#value'] = t('Apply'); + } + // Add a second button to allow to override the value. + else { + $form['buttons']['submit_display'] = array( + '#type' => 'submit', + '#value' => t('Apply to this display'), + '#dropbutton' => 'save', + '#submit' => array(array($this, 'standardSubmitDisplay')), + '#button_type' => 'primary', + '#weight' => !$is_defaulted ? 0 : 10, + ); + } + + // If a validation handler exists for the form, assign it to this button. + if (isset($form_state['build_info']['callback_object'])) { + $form['buttons']['submit_default']['#validate'][] = array($form_state['build_info']['callback_object'], 'validateForm'); + $form['buttons']['submit_display']['#validate'][] = array($form_state['build_info']['callback_object'], 'validateForm'); + } +// if (FALSE && function_exists($form_id . '_validate')) { +// $form['buttons']['submit_default']['#validate'][] = $form_id . '_validate'; +// $form['buttons']['submit_default']['#validate'][] = $form_id . '_validate'; +// } + } + + /** * 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. @@ -265,55 +299,13 @@ public function standardCancel($form, &$form_state) { * TODO: Is the hidden op operator still here somewhere, or is that part of the * docblock outdated? */ - public function getStandardButtons(&$form, &$form_state, $form_id, $name = NULL) { + public function getStandardButtons(&$form, &$form_state, $form_id, $section = NULL) { $form['buttons'] = array( '#prefix' => '
', '#suffix' => '
', ); - if (empty($name)) { - $name = t('Apply'); - if (!empty($this->stack) && count($this->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(array($this, 'standardSubmit')), - '#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, \Drupal\views_ui\Form\Ajax\ViewsFormBase::getForm() - // 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'], 'validateForm'); - } - if (function_exists($form_id . '_validate')) { - $form['buttons']['submit']['#validate'][] = $form_id . '_validate'; - } - } + $this->getApplyButton($form, $form_state, $section); // Create a "Cancel" button. For purely informational forms, label it "OK". $cancel_submit = function_exists($form_id . '_cancel') ? $form_id . '_cancel' : array($this, 'standardCancel'); @@ -373,6 +365,20 @@ public function getOverrideValues($form, $form_state) { return array($was_defaulted, $is_defaulted, $revert); } + + /** + * Determines whether the section is defaulted or overridden. + * + * @param string $section + * The section which is edited. + * + * @return bool + * Returns TRUE if the section is defaulted else FALSE. + */ + public function isFormDefaulted($section) { + return $this->executable->display_handler->isDefaulted($section); + } + /** * Add another form to the stack; clicking 'apply' will go to this form * rather than closing the ajax popup. @@ -715,13 +721,13 @@ public function renderPreview($display_id, $args = array()) { /** * Get the user's current progress through the form stack. * - * @return + * @return bool * FALSE if the user is not currently in a multiple-form stack. Otherwise, * an associative array with the following keys: * - current: The number of the current form on the stack. * - total: The total number of forms originally on the stack. */ - public function getFormProgress() { + protected function getFormProgress() { $progress = FALSE; if (!empty($this->stack)) { $stack = $this->stack; @@ -742,6 +748,67 @@ public function getFormProgress() { } /** + * Sets a form progress indicator on the form. + */ + public function getFormProgressIndicator(&$form, &$form_state, $section) { + $view = &$form_state['view']; + $display_id = $form_state['display_id']; + $executable = $view->get('executable'); + $displays = $executable->displayHandlers; + $current_display = $executable->display_handler; + + // @todo Move this to a separate function if it's needed on any forms that + // don't have the display dropdown. + $form['override'] = array( + '#prefix' => '
', + '#suffix' => '
', + '#weight' => -1000, + '#tree' => TRUE, + ); + + // Add the "2 of 3" progress indicator. + if ($form_progress = $this->getFormProgress()) { + $form['progress']['#markup'] = '
' . t('@current of @total', array('@current' => $form_progress['current'], '@total' => $form_progress['total'])) . '
'; + $form['progress']['#weight'] = -1001; + } + + if ($current_display->isDefaultDisplay()) { + return; + } + + // Determine whether any other displays have overrides for this section. + $section_overrides = FALSE; + $section_defaulted = $current_display->isDefaulted($section); + foreach ($displays as $id => $display) { + if ($id === 'default' || $id === $display_id) { + continue; + } + if ($display && !$display->isDefaulted($section)) { + $section_overrides = TRUE; + } + } + + $display_dropdown['default'] = ($section_overrides ? t('All displays (except overridden)') : t('All displays')); + $display_dropdown[$display_id] = t('This @display_type (override)', array('@display_type' => $current_display->getPluginId())); + // Only display the revert option if we are in a overridden section. + if (!$section_defaulted) { + $display_dropdown['default_revert'] = t('Revert to default'); + } + + $form['override']['dropdown'] = array( + '#type' => 'select', + '#title' => t('For'), // @TODO: Translators may need more context than this. + '#options' => $display_dropdown, + ); + if ($current_display->isDefaulted($section)) { + $form['override']['dropdown']['#default_value'] = 'defaults'; + } + else { + $form['override']['dropdown']['#default_value'] = $display_id; + } + } + + /** * Sets a cached view object in the user tempstore. */ public function cacheSet() { @@ -1134,4 +1201,5 @@ public function setContext($name = NULL, TypedDataInterface $parent = NULL) { public function onChange($property_name) { $this->storage->onChange($property_name); } + } diff --git a/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewUIObjectTest.php b/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewUITest.php similarity index 68% rename from core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewUIObjectTest.php rename to core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewUITest.php index 6aac5e4..be8f89f 100644 --- a/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewUIObjectTest.php +++ b/core/modules/views_ui/tests/Drupal/views_ui/Tests/ViewUITest.php @@ -2,14 +2,16 @@ /** * @file - * Contains \Drupal\views_ui\Tests\ViewUIObjectTest. + * Contains \Drupal\views_ui\Tests\ViewUITest. */ namespace Drupal\views_ui\Tests; use Drupal\Core\Language\Language; use Drupal\Tests\UnitTestCase; +use Drupal\views\Plugin\Core\Entity\View; use Drupal\views\ViewExecutable; +use Drupal\views\ViewExecutableFactory; use Drupal\views_ui\ViewUI; use Symfony\Component\DependencyInjection\Container; @@ -22,7 +24,7 @@ * * @see \Drupal\views_ui\ViewUI */ -class ViewUIObjectTest extends UnitTestCase { +class ViewUITest extends UnitTestCase { public static function getInfo() { return array( @@ -80,4 +82,31 @@ public function testEntityDecoration() { $view_ui->isNew(); } + + /** + * Tests the isFormDefaulted method. + * + * @see \Drupal\views_ui\ViewUI::isFormDefaulted() + */ + public function testIsFormDefaulted() { + // Create a view UI object. + $values = array(); + $storage = new View($values, 'view'); + $executable = ViewExecutableFactory::get($storage); + $view_ui = new ViewUI($storage, $executable); + + // Add a new display and override a bunch of options/some set to default. + $id = $storage->addDisplay('page'); + + $executable->setDisplay($id); + + $executable->display_handler->overrideOption('fields', array()); + $executable->display_handler->setOverride('filters', FALSE); + $executable->display_handler->setOverride('arguments', TRUE); + + $this->assertFalse($view_ui->isFormDefaulted('fields')); + $this->assertFalse($view_ui->isFormDefaulted('filters')); + $this->assertTrue($view_ui->isFormDefaulted('arguments')); + } + }