diff --git a/includes/admin.inc b/includes/admin.inc index 29c4757ce015cfea782757b798b00190f54e93e9..7ae715fee93e23b31ca3a1eb54575338aba6466c 100644 --- a/includes/admin.inc +++ b/includes/admin.inc @@ -1062,7 +1062,7 @@ function views_ui_edit_form($form, &$form_state, ViewUI $view, $display_id = NUL $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)) { + if (!empty($view->display[$display_id]['deleted'])) { $form['displays']['settings']['settings_content']['tab_content']['#attributes']['class'][] = 'views-display-deleted'; } // Mark disabled displays as such. @@ -1262,10 +1262,9 @@ function views_ui_edit_form_submit_duplicate_display($form, &$form_state) { $display_id = $form_state['display_id']; // Create the new display. - $display = $view->display[$display_id]; + $display = $view->storage->display[$display_id]; $new_display_id = $view->storage->addDisplay($display['display_plugin']); - $view->storage->display[$new_display_id] = clone $display; - $view->storage->display[$new_display_id]['id'] = $new_display_id; + $view->storage->display[$new_display_id] = $display; // By setting the current display the changed marker will appear on the new // display. @@ -1284,7 +1283,7 @@ function views_ui_edit_form_submit_delete_display($form, &$form_state) { $display_id = $form_state['display_id']; // Mark the display for deletion. - $view->storage->display[$display_id]->deleted = TRUE; + $view->storage->display[$display_id]['deleted'] = TRUE; views_ui_cache_set($view); // Redirect to the top-level edit page. The first remaining display will @@ -1298,7 +1297,7 @@ function views_ui_edit_form_submit_delete_display($form, &$form_state) { 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; + $form_state['view']->storage->display[$id]['deleted'] = FALSE; // Store in cache views_ui_cache_set($form_state['view']); @@ -1393,6 +1392,7 @@ 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', @@ -1402,7 +1402,7 @@ function views_ui_edit_page_display_tabs(ViewUI $view, $display_id = NULL) { 'localized_options' => array(), ), ); - if (!empty($display->deleted)) { + 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']) { @@ -1485,7 +1485,7 @@ function views_ui_get_display_tab_details(ViewUI $view, $display) { // 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); + $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. @@ -2035,9 +2035,10 @@ function views_ui_edit_view_form_validate($form, &$form_state) { */ function views_ui_edit_view_form_submit($form, &$form_state) { // Go through and remove displayed scheduled for removal. - foreach ($form_state['view']->displayHandlers as $id => $display) { - if (!empty($display->deleted)) { + foreach ($form_state['view']->storage->display as $id => $display) { + if (!empty($display['deleted'])) { unset($form_state['view']->displayHandlers[$id]); + unset($form_state['view']->storage->display[$id]); } } // Rename display ids if needed. @@ -2864,7 +2865,7 @@ function views_ui_ajax_form($js, $key, ViewUI $view, $display_id = '') { function views_ui_remove_display_form_restore($form, &$form_state) { // Create the new display $id = $form_state['display_id']; - $form_state['view']->display[$id]->deleted = FALSE; + $form_state['view']->storage->display[$id]['deleted'] = FALSE; // Store in cache views_ui_cache_set($form_state['view']); @@ -2912,15 +2913,16 @@ function views_ui_reorder_displays_form($form, &$form_state) { $form['#tree'] = TRUE; - $last_display = end($view->display); + uasort($form_state['view']->storage->display, '_views_position_sort'); + $count = count($view->storage->display); - foreach ($view->display as $display) { + foreach ($view->storage->display as $display) { $form[$display['id']] = array( 'title' => array('#markup' => $display['display_title']), 'weight' => array( '#type' => 'weight', '#value' => $display['position'], - '#delta' => $last_display['position'], + '#delta' => $count, '#title' => t('Weight for @display', array('@display' => $display['display_title'])), '#title_display' => 'invisible', ), @@ -2930,11 +2932,11 @@ function views_ui_reorder_displays_form($form, &$form_state) { '#type' => 'checkbox', '#id' => 'display-removed-' . $display['id'], '#attributes' => array('class' => array('views-remove-checkbox')), - '#default_value' => isset($display->deleted), + '#default_value' => isset($display['deleted']), ), ); - if (isset($display->deleted) && $display->deleted) { + if (isset($display->deleted) && $display['deleted']) { $form[$display['id']]['deleted'] = array('#type' => 'value', '#value' => TRUE); } if ($display['id'] === 'default') { @@ -2986,34 +2988,36 @@ function views_ui_reorder_displays_form_submit($form, &$form_state) { $order[$display] = $info['weight']; } } + debug($form_state['input']); // Sort the order array asort($order); // Fixing up positions - $position = 2; + $position = 1; foreach (array_keys($order) as $display) { $order[$display] = $position++; } // Setting up position and removing deleted displays - $displays = $form_state['view']->display; + $displays = $form_state['view']->storage->display; foreach ($displays as $display_id => $display) { // Don't touch the default !!! if ($display_id === 'default') { + $form_state['view']->storage->display[$display_id]['position'] = 0; continue; } if (isset($order[$display_id])) { - $form_state['view']->display[$display_id]['position'] = $order[$display_id]; + $form_state['view']->storage->display[$display_id]['position'] = $order[$display_id]; } else { - $form_state['view']->display[$display_id]->deleted = TRUE; + $form_state['view']->storage->display[$display_id]['deleted'] = TRUE; } } // Sorting back the display array as the position is not enough - uasort($form_state['view']->display, '_views_position_sort'); + uasort($form_state['view']->storage->display, '_views_position_sort'); // Store in cache views_ui_cache_set($form_state['view']); diff --git a/lib/Drupal/views/Plugin/views/display/Feed.php b/lib/Drupal/views/Plugin/views/display/Feed.php index 5b9de864066422f60880ba294eeeeb87886baf31..9a4165aaf889648a3fac0d6f11bfaf443bf92187 100644 --- a/lib/Drupal/views/Plugin/views/display/Feed.php +++ b/lib/Drupal/views/Plugin/views/display/Feed.php @@ -194,7 +194,7 @@ public function buildOptionsForm(&$form, &$form_state) { case 'displays': $form['#title'] .= t('Attach to'); $displays = array(); - foreach ($this->view->display as $display_id => $display) { + foreach ($this->view->storage->display as $display_id => $display) { // @todo The display plugin should have display_title and id as well. if (!empty($this->view->displayHandlers[$display_id]) && $this->view->displayHandlers[$display_id]->acceptAttachments()) { $displays[$display_id] = $display['display_title']; diff --git a/lib/Drupal/views/Tests/Plugin/DisplayFeedTest.php b/lib/Drupal/views/Tests/Plugin/DisplayFeedTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6bc229720ea3cb83f4e7859a3948ff2b8ba3669b --- /dev/null +++ b/lib/Drupal/views/Tests/Plugin/DisplayFeedTest.php @@ -0,0 +1,64 @@ +<?php + +/** + * @file + * Definition of Drupal\views\Tests\Plugin\DisplayFeedTest. + */ + +namespace Drupal\views\Tests\Plugin; + +/** + * Tests the feed display plugin. + * + * @see Drupal\views\Plugin\views\display\Feed + */ +class DisplayFeedTest extends PluginTestBase { + + /** + * Modules to enable. + * + * @var array + */ + public static $modules = array('views_ui'); + + public static function getInfo() { + return array( + 'name' => 'Display: Feed plugin', + 'description' => 'Tests the feed display plugin.', + 'group' => 'Views Plugins', + ); + } + + protected function setUp() { + parent::setUp(); + + $this->enableViewsTestModule(); + + $admin_user = $this->drupalCreateUser(array('administer views', 'administer site configuration')); + $this->drupalLogin($admin_user); + } + + /** + * Tests feed display admin ui. + */ + public function testFeedUI() { + $this->drupalGet('admin/structure/views'); + + // Check the attach TO interface. + $this->drupalGet('admin/structure/views/nojs/display/test_feed_display/feed/displays'); + + // Load all the options of the checkbox. + $result = $this->xpath('//div[@id="edit-displays"]/div'); + $options = array(); + foreach ($result as $value) { + foreach ($value->input->attributes() as $attribute => $value) { + if ($attribute == 'value') { + $options[] = (string) $value; + } + } + } + + $this->assertEqual($options, array('default', 'feed', 'page'), 'Make sure all displays appears as expected.'); + } + +} diff --git a/lib/Drupal/views/Tests/UI/DisplayTest.php b/lib/Drupal/views/Tests/UI/DisplayTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5a38e696aec77073acb6d2917697da5e9e96cb7d --- /dev/null +++ b/lib/Drupal/views/Tests/UI/DisplayTest.php @@ -0,0 +1,141 @@ +<?php + +/** + * @file + * Definition of Drupal\views\Tests\UI\DisplayTest. + */ + +namespace Drupal\views\Tests\UI; + +/** + * Tests the handling of displays in the UI, adding removing etc. + */ +class DisplayTest extends UITestBase { + + public static function getInfo() { + return array( + 'name' => 'Display tests', + 'description' => 'Tests the handling of displays in the UI, adding removing etc.', + 'group' => 'Views UI', + ); + } + + /** + * A helper method which creates a random view. + */ + public function randomView(array $view = array()) { + // Create a new view in the UI. + $default = array(); + $default['human_name'] = $this->randomName(16); + $default['name'] = strtolower($this->randomName(16)); + $default['description'] = $this->randomName(16); + $default['page[create]'] = TRUE; + $default['page[path]'] = $default['name']; + + $view += $default; + + $this->drupalPost('admin/structure/views/add', $view, t('Continue & edit')); + + return $default; + } + + /** + * Tests removing a display. + */ + public function testRemoveDisplay() { + $view = $this->randomView(); + $path_prefix = 'admin/structure/views/view/' . $view['name'] .'/edit'; + + $this->drupalGet($path_prefix . '/default'); + $this->assertNoFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-delete', 'delete Page', 'Make sure there is no delete button on the default display.'); + + $this->drupalGet($path_prefix . '/page'); + $this->assertFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-delete', 'delete Page', 'Make sure there is a delete button on the page display.'); + + // Delete the page, so we can test the undo process. + $this->drupalPost($path_prefix . '/page', array(), 'delete Page'); + $this->assertFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-undo-delete', 'undo delete of Page', 'Make sure there a undo button on the page display after deleting.'); + $this->assertTrue($this->xpath('//div[contains(@class, views-display-deleted-link)]'). 'Make sure the display link is marked as to be deleted.'); + + // Undo the deleting of the display. + $this->drupalPost($path_prefix . '/page', array(), 'undo delete of Page'); + $this->assertNoFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-undo-delete', 'undo delete of Page', 'Make sure there is no undo button on the page display after reverting.'); + $this->assertFieldById('edit-displays-settings-settings-content-tab-content-details-top-actions-delete', 'delete Page', 'Make sure there is a delete button on the page display after the reverting.'); + + // Now delete again and save the view. + $this->drupalPost($path_prefix . '/page', array(), 'delete Page'); + $this->drupalPost(NULL, array(), t('Save')); + + $this->assertNoLinkByHref($path_prefix . '/page', 'Make sure there is no display tab for the deleted display.'); + } + + /** + * Tests adding a display. + */ + public function testAddDisplay() { + $settings['page[create]'] = FALSE; + $view = $this->randomView($settings); + + $path_prefix = 'admin/structure/views/view/' . $view['name'] .'/edit'; + $this->drupalGet($path_prefix); + + // Add a new display. + $this->drupalPost(NULL, array(), 'Add Page'); + // @todo Revising this after http://drupal.org/node/1793700 got in. + $this->assertLinkByHref($path_prefix . '/page_1', 0, 'Make sure after adding a display the new display appears in the UI'); + } + + /** + * Tests reordering of displays. + */ + public function testReorderDisplay() { + $view = array( + 'block[create]' => TRUE + ); + $view = $this->randomView($view); + $path_prefix = 'admin/structure/views/view/' . $view['name'] .'/edit'; + + $edit = array(); + $this->drupalPost($path_prefix, $edit, t('Save')); + $this->clickLink(t('reorder displays')); + $this->assertTrue($this->xpath('//tr[@id="display-row-default"]'), 'Make sure the default display appears on the reorder listing'); + $this->assertTrue($this->xpath('//tr[@id="display-row-page"]'), 'Make sure the page display appears on the reorder listing'); + $this->assertTrue($this->xpath('//tr[@id="display-row-block"]'), 'Make sure the block display appears on the reorder listing'); + + // Put the block display in front of the page display. + $edit = array( + 'page[weight]' => 2, + 'block[weight]' => 1 + ); + $this->drupalPost(NULL, $edit, t('Apply')); + $this->drupalPost(NULL, array(), t('Save')); + + $view = views_get_view($view['name']); + $this->assertEqual($view->storage->display['default']['position'], 0, 'Make sure the master display comes first.'); + $this->assertEqual($view->storage->display['block']['position'], 1, 'Make sure the block display comes before the page display.'); + $this->assertEqual($view->storage->display['page']['position'], 2, 'Make sure the page display comes after the block display.'); + } + + /** + * Tests that the correct display is loaded by default. + */ + public function testDefaultDisplay() { + $this->drupalGet('admin/structure/views/view/test_display'); + $elements = $this->xpath('//*[@id="views-page-display-title"]'); + $this->assertEqual(count($elements), 1, 'The page display is loaded as the default display.'); + } + + /** + * Tests the cloning of a display. + */ + public function testCloneDisplay() { + $view = $this->randomView(); + $path_prefix = 'admin/structure/views/view/' . $view['name'] .'/edit'; + + $this->drupalGet($path_prefix); + $this->drupalPost(NULL, array(), 'clone Page'); + // @todo Revising this after http://drupal.org/node/1793700 got in. + $this->assertLinkByHref($path_prefix . '/page_1', 0, 'Make sure after cloning the new display appears in the UI'); + } + +} diff --git a/tests/views_test_config/config/views.view.test_display.yml b/tests/views_test_config/config/views.view.test_display.yml new file mode 100644 index 0000000000000000000000000000000000000000..5c44bb22d83ab19e6eb73c9f0d158757cc2193b5 --- /dev/null +++ b/tests/views_test_config/config/views.view.test_display.yml @@ -0,0 +1,87 @@ +api_version: '3.0' +base_table: node +core: '8' +description: '' +disabled: '1' +display: + block: + display_options: + defaults: + pager: '0' + pager_options: '0' + row_options: '0' + row_plugin: '0' + style_options: '0' + style_plugin: '0' + field: + title: + link_to_node: '1' + pager: + options: + items_per_page: '5' + type: some + pager_options: { } + row_options: + build_mode: teaser + comments: '0' + links: '1' + row_plugin: fields + style_options: { } + style_plugin: default + display_plugin: block + display_title: Block + id: block + position: '2' + default: + display_options: + access: + type: perm + cache: + type: none + exposed_form: + type: basic + fields: + title: + field: title + id: title + table: node + filters: + status: + field: status + group: '1' + id: status + table: node + value: '1' + pager: + options: + items_per_page: '10' + type: full + query: + type: views_query + row_options: + build_mode: teaser + comments: '0' + links: '1' + row_plugin: node + sorts: + created: + field: created + id: created + order: DESC + table: node + style_plugin: default + title: 'Test Display' + display_plugin: default + display_title: Master + id: default + position: '0' + page: + display_options: + path: test-display + display_plugin: page + display_title: Page + id: page + position: '1' +human_name: '' +name: test_display +tag: '' diff --git a/tests/views_test_config/config/views.view.test_feed_display.yml b/tests/views_test_config/config/views.view.test_feed_display.yml new file mode 100644 index 0000000000000000000000000000000000000000..3fd15c9dcc768468117fe7f4d48dbbbce1006f46 --- /dev/null +++ b/tests/views_test_config/config/views.view.test_feed_display.yml @@ -0,0 +1,93 @@ +api_version: '3.0' +base_table: node +core: 8.0-dev +description: '' +disabled: '0' +display: + default: + display_options: + access: + type: perm + cache: + type: none + exposed_form: + type: basic + fields: + title: + alter: + absolute: '0' + alter_text: '0' + ellipsis: '0' + html: '0' + make_link: '0' + strip_tags: '0' + trim: '0' + word_boundary: '0' + empty_zero: '0' + field: title + hide_empty: '0' + id: title + label: '' + link_to_node: '1' + table: node + filters: + status: + expose: + operator: '0' + field: status + group: '1' + id: status + table: node + value: '1' + pager: + options: + items_per_page: '10' + type: full + query: + type: views_query + row: + options: + build_mode: teaser + comments: '0' + links: '1' + type: node + sorts: + created: + field: created + id: created + order: DESC + table: node + style: + type: default + title: test_feed_display + display_plugin: default + display_title: Master + id: default + position: '0' + feed: + display_options: + displays: + default: default + page: page + pager: + type: some + path: test-feed-display.xml + row: + type: node_rss + style: + type: rss + display_plugin: feed + display_title: Feed + id: feed + position: '0' + page: + display_options: + path: test-feed-display + display_plugin: page + display_title: Page + id: page + position: '0' +human_name: test_feed_display +module: views +name: test_feed_display +tag: default