diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php index 6d0a3f4..c4c2874 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php @@ -137,6 +137,16 @@ public function loadByProperties(array $values = array()) { } /** + * Returns the config prefix used by the configuration entity type. + * + * @return string + * The full configuration prefix, for example `views.view.`. + */ + public function getConfigPrefix() { + return $this->entityInfo['config_prefix'] . '.'; + } + + /** * Builds the query to load the entity. * * This has full revision support. For entities requiring special queries, @@ -159,7 +169,7 @@ public function loadByProperties(array $values = array()) { */ protected function buildQuery($ids, $revision_id = FALSE) { $config_class = $this->entityInfo['class']; - $prefix = $this->entityInfo['config_prefix'] . '.'; + $prefix = $this->getConfigPrefix(); // Load all of the configuration entities. if ($ids === NULL) { @@ -251,7 +261,7 @@ public function delete(array $entities) { } foreach ($entities as $id => $entity) { - $config = config($this->entityInfo['config_prefix'] . '.' . $entity->id()); + $config = config($this->getConfigPrefix() . $entity->id()); $config->delete(); // Remove the entity from the manifest file. @@ -273,7 +283,7 @@ public function delete(array $entities) { * When attempting to save a configuration entity that has no ID. */ public function save(EntityInterface $entity) { - $prefix = $this->entityInfo['config_prefix'] . '.'; + $prefix = $this->getConfigPrefix(); // Configuration entity IDs are strings, and '0' is a valid ID. $id = $entity->id(); diff --git a/core/modules/views/lib/Drupal/views/Plugin/Core/Entity/View.php b/core/modules/views/lib/Drupal/views/Plugin/Core/Entity/View.php index 3f39af8..0d666c6 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/Core/Entity/View.php +++ b/core/modules/views/lib/Drupal/views/Plugin/Core/Entity/View.php @@ -26,7 +26,8 @@ * form_controller_class = { * "edit" = "Drupal\views_ui\ViewEditFormController", * "add" = "Drupal\views_ui\ViewAddFormController", - * "preview" = "Drupal\views_ui\ViewPreviewFormController" + * "preview" = "Drupal\views_ui\ViewPreviewFormController", + * "manage_snapshot" = "Drupal\views_ui\ViewSnapshotManageFormController" * }, * config_prefix = "views.view", * fieldable = FALSE, diff --git a/core/modules/views/lib/Drupal/views/Plugin/Core/Entity/ViewSnapshot.php b/core/modules/views/lib/Drupal/views/Plugin/Core/Entity/ViewSnapshot.php new file mode 100644 index 0000000..1aceef1 --- /dev/null +++ b/core/modules/views/lib/Drupal/views/Plugin/Core/Entity/ViewSnapshot.php @@ -0,0 +1,66 @@ +get('snapshotID'); + } + +} diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/field/FieldPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/field/FieldPluginBase.php index 8d6fe06..9de6365 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/field/FieldPluginBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/field/FieldPluginBase.php @@ -402,7 +402,12 @@ function use_string_group_by() { protected function defineOptions() { $options = parent::defineOptions(); - $options['label'] = array('default' => $this->definition['title'], 'translatable' => TRUE); + $options['label'] = array('default' => '', 'translatable' => TRUE); + // Some styles (for example table) should have field labels enabled by + // default. + if (isset($this->view->style_plugin) && $this->view->style_plugin->defaultFieldLabels()) { + $options['label']['default'] = $this->definition['title']; + } $options['exclude'] = array('default' => FALSE, 'bool' => TRUE); $options['alter'] = array( 'contains' => array( diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/style/StylePluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/style/StylePluginBase.php index ee8081d..15e8919 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/style/StylePluginBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/style/StylePluginBase.php @@ -80,6 +80,13 @@ protected $usesFields = FALSE; /** + * Should field labels be enabled by default. + * + * @var bool + */ + protected $defaultFieldLabels = FALSE; + + /** * Initialize a style plugin. * * @param $view @@ -172,6 +179,15 @@ function uses_tokens() { } /** + * Return TRUE if this style enables field labels by default. + * + * @return bool + */ + public function defaultFieldLabels() { + return $this->defaultFieldLabels; + } + + /** * Return the token replaced row class for the specified row. */ function get_row_class($row_index) { diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/style/Table.php b/core/modules/views/lib/Drupal/views/Plugin/views/style/Table.php index 5a3e907..014219a 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/style/Table.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/style/Table.php @@ -59,6 +59,11 @@ class Table extends StylePluginBase { */ public $order; + /** + * Override \Drupal\views\Plugin\views\style\StylePluginBase::defaultFieldLabels + */ + protected $defaultFieldLabels = TRUE; + protected function defineOptions() { $options = parent::defineOptions(); diff --git a/core/modules/views/lib/Drupal/views/Tests/UI/SnapshotTest.php b/core/modules/views/lib/Drupal/views/Tests/UI/SnapshotTest.php new file mode 100644 index 0000000..5e63f3b --- /dev/null +++ b/core/modules/views/lib/Drupal/views/Tests/UI/SnapshotTest.php @@ -0,0 +1,64 @@ + 'Snapshots', + 'description' => 'Tests the general UI for creating snapshot of views.', + 'group' => 'Views UI', + ); + } + + /** + * Tests CRUD UI functionality of views snapshots. + */ + public function testCRUDUI() { + $view = entity_load('view', 'test_view'); + + // Make sure the snapshots link appear on the actual edit UI. + $uri = $view->uri(); + $this->drupalGet($uri['path'] . '/edit'); + $this->assertLink(t('snapshots'), 0, 'The snapshot link appears'); + + $this->clickLink(t('snapshots'), 0); + $snapshots_list_url = 'admin/structure/views/nojs/snapshots/test_view'; + $this->assertUrl($snapshots_list_url); + + $this->assertTitle(format_string("View snapshots: @view_name | @site_name", array('@view_name' => $view->getHumanName(), '@site_name' => config('system.site')->get('name'))), 'The view name is used in title.'); + + // Create a snapshot and make sure it got saved correctly. + $random_comment = $this->randomName(50); + $this->drupalPost(NULL, array('comment' => $random_comment), t('Create snapshot')); + $this->drupalGet($snapshots_list_url); + $this->assertText('test_view:1', 'A snapshot got created.'); + $this->assertText($random_comment, 'The comment of the snapshot got saved correctly.'); + + // Create a second snapshot, edit it, and make sure the change just got + // added to the changed snapshot. + $this->drupalGet($snapshots_list_url); + $this->drupalPost($snapshots_list_url, array(), t('Create snapshot')); + + $snapshot_1 = entity_load('view_snapshot', 'test_view:1'); + $snapshot_2 = entity_load('view_snapshot', 'test_view:1'); + + // Add a random title, check it on that snapshot and another snapshot. + $random_title = $this->randomName(); + $this->drupalPost("admin/structure/views/nojs/display/{$snapshot_1->id()}/default/title", array('title' => $random_title), t('Apply')); + $this->assertText($random_title); + + $this->drupalGet("admin/structure/views/view/$snapshot_1->id()/edit"); + $this->assertNoText($random_title); + } + +} diff --git a/core/modules/views/lib/Drupal/views/ViewSnapshotStorageController.php b/core/modules/views/lib/Drupal/views/ViewSnapshotStorageController.php new file mode 100644 index 0000000..9d45c35 --- /dev/null +++ b/core/modules/views/lib/Drupal/views/ViewSnapshotStorageController.php @@ -0,0 +1,133 @@ +configPrefix = $this->entityInfo['config_prefix'] . '.'; + } + + /** + * Overrides \Drupal\Core\Config\Entity::getConfigPrefix(). + */ + public function getConfigPrefix() { + return $this->configPrefix; + } + + /** + * Overrides \Drupal\Core\Config\Entity::loadByProperties(). + */ + public function loadByProperties(array $values = array()) { + // The config storage controller does not allow to filter by properties, + // but let's support at least loading all views snapshots by the name of the + // view. + if (isset($values['name'])) { + $old_prefix = $this->getConfigPrefix(); + $this->configPrefix = $old_prefix . $values['name'] . static::$split; + $list = $this->load(); + $this->configPrefix = $old_prefix; + + return $list; + } + else { + return parent::loadByProperties($values); + } + } + + public function createSnapshot(View $view, array $snapshot_values = array()) { + $view_config = entity_get_controller('view')->getProperties($view); + $view_config += $snapshot_values + array( + 'created' => REQUEST_TIME, + ); + + // Generate the next snapshot id by finding the last snapshot and add +1. + $name = $view->get('name'); + $snapshot_keys = array_keys($this->loadByProperties(array('name' => $name))); + $last_snapshot_id = end($snapshot_keys); + $revision_id = (int) str_replace($name . static::$split, '', $last_snapshot_id); + $next_revision_id = ++$revision_id; + + $view_config['snapshotID'] = $name . static::$split . $next_revision_id; + + $snapshot = $this->create($view_config); + return $snapshot; + } + + /** + * Revert a view to a certain snapshot. + * + * @param \Drupal\views\Plugin\Core\Entity\View $view + * The view to revert to a certain snapshot. + * @param \Drupal\views\Plugin\Core\Entity\ViewSnapshot $snapshot + * The snapshot to revert to. + */ + public function revertSnapshot(View $view, ViewSnapshot $snapshot) { + // Get all values of the snapshot to set it to the main view. + $snapshot_properties = $this->getProperties($snapshot); + unset($snapshot_properties['created'], $snapshot_properties['comment'], $snapshot_properties['snapshotID'], $snapshot_properties['uuid']); + + // Set all properties of the snapshot to the view and save it. + foreach ($snapshot_properties as $property_name => $property_value) { + $view->set($property_name, $property_value); + } + $view->save(); + + return $view; + } + + /** + * Overrides \Drupal\views\ViewStorageController::getProperties(). + */ + protected function getProperties(EntityInterface $entity) { + $properties = parent::getProperties($entity); + + $names = array( + 'created', + 'comment', + 'snapshotID' + ); + + foreach ($names as $name) { + $properties[$name] = $entity->get($name); + } + + return $properties; + } + +} diff --git a/core/modules/views/lib/Drupal/views/ViewStorageController.php b/core/modules/views/lib/Drupal/views/ViewStorageController.php index 05268d2..7fa7f4e 100644 --- a/core/modules/views/lib/Drupal/views/ViewStorageController.php +++ b/core/modules/views/lib/Drupal/views/ViewStorageController.php @@ -80,10 +80,11 @@ public function create(array $values) { * @param Drupal\Core\Entity\EntityInterface $entity */ protected function attachDisplays(EntityInterface $entity) { - if (isset($entity->display) && is_array($entity->display)) { + $view_displays = $entity->get('display'); + if (isset($view_displays) && is_array($view_displays)) { $displays = array(); - foreach ($entity->get('display') as $key => $options) { + foreach ($view_displays as $key => $options) { $options += array( 'display_options' => array(), 'display_plugin' => NULL, diff --git a/core/modules/views/tests/views_test_config/config/views.view.test_view.yml b/core/modules/views/tests/views_test_config/config/views.view.test_view.yml index 57dd103..2d849a1 100644 --- a/core/modules/views/tests/views_test_config/config/views.view.test_view.yml +++ b/core/modules/views/tests/views_test_config/config/views.view.test_view.yml @@ -43,6 +43,6 @@ display: display_title: Master id: default position: '0' -human_name: '' +human_name: Test view name: test_view tag: '' diff --git a/core/modules/views/views_ui/admin.inc b/core/modules/views/views_ui/admin.inc index 5b0ae41..c5f1a72 100644 --- a/core/modules/views/views_ui/admin.inc +++ b/core/modules/views/views_ui/admin.inc @@ -513,6 +513,18 @@ function views_ui_ajax_forms($key = NULL) { 'form_id' => 'views_ui_analyze_view_form', 'args' => array(), ), + 'snapshots' => array( + 'form_id' => 'views_ui_snapshot_form', + 'args' => array(), + ), + 'revert-snapshot' => array( + 'form_id' => 'views_ui_revert_snapshot_form', + 'args' => array(), + ), + 'delete-snapshot' => array( + 'form_id' => 'views_ui_delete_snapshot_form', + 'args' => array(), + ), ); if ($key) { @@ -663,6 +675,28 @@ function views_ui_analyze_view_form_submit($form, &$form_state) { } /** + * Form submit handler to create a new snapshot. + */ +function views_ui_snapshot_add_submit($form, &$form_state) { + $view = $form_state['view']; + $snapshot_values = array( + 'created' => REQUEST_TIME, + 'comment' => $form_state['values'], + ); + + entity_get_controller('view_snapshot', 'storage')->createSnapshot($view, $snapshot_values); + + $uri = $view->uri(); +// $form_state['redirect'] = $uri['path'] . '/edit'; +} + +/** + * Form submit handler to delete an existing snapshot. + */ +function views_ui_snapshot_delete_submit($form, &$form_state) { +} + +/** * Form builder to edit details of a view. */ function views_ui_edit_details_form($form, &$form_state) { @@ -2389,3 +2423,51 @@ function views_ui_plugin_list() { '#empty' => t('There are no enabled views.'), ); } + +/** + * Form callback to list snapshots. + * + * @todo It would make sense to convert this to a snapshot form controller on + * the view. + */ +function views_ui_snapshot_form($form, &$form_state) { + $view = &$form_state['view']; + $form = entity_get_form($view, 'manage_snapshot'); + return $form; +} + +/** + * Form submit handler to create a new snapshot. + */ +function views_ui_snapshot_form_create(&$form, &$form_state) { + $snapshot_controller = entity_get_controller('view_snapshot'); + + $storage = $form_state['view']->get('storage'); + $snapshot = $snapshot_controller->createSnapshot($storage, array('comment' => $form_state['values']['comment'])); + $snapshot->save(); + + // Show a message and redirect to the edit view. + drupal_set_message(t('Snapshot number @id created.', array('@id' => $snapshot->id()))); + $uri = $storage->uri(); + $form_state['redirect'] = $uri['path'] . '/edit'; +} + +/** + * Form controller to revert a view to a snapshot. + * + * @see \Drupal\views_ui\ViewSnapshotRevertFormController + */ +function views_ui_revert_snapshot_form($form, &$form_state) { + $snapshot = &$form_state['view']; + return entity_get_form($snapshot, 'revert'); +} + +/** + * Form controller to delete a snapshot. + * + * @see \Drupal\views_ui\ViewSnapshotDeleteFormController + */ +function views_ui_delete_snapshot_form($form, &$form_state) { + $snapshot = &$form_state['view']; + return entity_get_form($snapshot, 'delete'); +} diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewEditFormController.php b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewEditFormController.php index 853d5c9..5daef7f 100644 --- a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewEditFormController.php +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewEditFormController.php @@ -16,20 +16,6 @@ class ViewEditFormController extends ViewFormControllerBase { /** - * Overrides Drupal\Core\Entity\EntityFormController::getEntity(). - */ - public function getEntity(array $form_state) { - return isset($form_state['view']) ? $form_state['view'] : NULL; - } - - /** - * Overrides Drupal\Core\Entity\EntityFormController::setEntity(). - */ - public function setEntity(EntityInterface $entity, array &$form_state) { - $form_state['view'] = $entity; - } - - /** * Overrides Drupal\Core\Entity\EntityFormController::form(). */ public function form(array $form, array &$form_state, EntityInterface $view) { @@ -643,6 +629,11 @@ public function renderDisplayTop(ViewUI $view) { 'href' => "admin/structure/views/nojs/reorder-displays/{$view->get('name')}/$display_id", 'attributes' => array('class' => array('views-ajax-link')), ), + 'snapshots' => array( + 'title' => t('snapshots'), + 'href' => "admin/structure/views/nojs/snapshots/{$view->get('name')}", + 'attributes' => array('class' => array('views-ajax-link')), + ), ), ); diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewFormControllerBase.php b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewFormControllerBase.php index 3683875..656c637 100644 --- a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewFormControllerBase.php +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewFormControllerBase.php @@ -18,6 +18,20 @@ abstract class ViewFormControllerBase extends EntityFormController { /** + * Overrides Drupal\Core\Entity\EntityFormController::getEntity(). + */ + public function getEntity(array $form_state) { + return isset($form_state['view']) ? $form_state['view'] : NULL; + } + + /** + * Overrides Drupal\Core\Entity\EntityFormController::setEntity(). + */ + public function setEntity(EntityInterface $entity, array &$form_state) { + $form_state['view'] = $entity; + } + + /** * Overrides Drupal\Core\Entity\EntityFormController::prepareForm(). */ protected function prepareEntity(EntityInterface $view) { diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewSnapshotDeleteFormController.php b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewSnapshotDeleteFormController.php new file mode 100644 index 0000000..18c0b2e --- /dev/null +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewSnapshotDeleteFormController.php @@ -0,0 +1,55 @@ +id() . '-snapshot-delete'; + $this->setEntity($entity, $form_state); + + // @todo A proper label on the snapshot probably help. + $title = t('Are you sure you want to delete the snapshot @snapshot from @name', array( + '@name' => $entity->get('name'), + '@snapshot' => $entity->id() + )); + $form['#title'] = $title; + + return confirm_form($form, $title, "admin/structure/views/view/{$entity->get('name')}/edit", t('This cannot be undone.'), t('Delete'), t('Cancel')); + } + + /** + * Overrides Drupal\Core\Entity\EntityFormController::submit(). + */ + public function submit(array $form, array &$form_state) { + $view_ui = parent::submit($form, $form_state); + $snapshot = $view_ui->get('storage'); + $snapshot->delete(); + + drupal_set_message(t('Snapshot number @id deleted.', array('@id' => $snapshot->id()))); + + // @todo Redirect the user to the snapshot overview page. + // $form_state['redirect'] = "admin/structure/views/nojs/snapshots/{$snapshot->get('name')}"; + // $view_ui->addFormToStack('snapshots', $view_ui->displayID, array()); + // Store in cache. + // views_ui_cache_set($form_state['view']); + } + +} diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewSnapshotListController.php b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewSnapshotListController.php new file mode 100644 index 0000000..73d3a92 --- /dev/null +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewSnapshotListController.php @@ -0,0 +1,122 @@ +original = $original; + } + + /** + * Overrides Drupal\Core\Entity\EntityListController::load(); + */ + public function load() { + $entities = $this->storage->loadByProperties(array('name' => $this->original->get('name'))); + $this->sort($entities); + return $entities; + } + + /* + * Helper method to sort loaded snapshots by timestamp descending. + */ + protected function sort(array &$entities) { + uasort($entities, function ($a, $b) { + $a_created = $a->get('created'); + $b_created = $b->get('created'); + return $a_created < $b_created; + }); + } + + /** + * Overrides Drupal\Core\Entity\EntityListController::buildRow(); + */ + public function buildRow(EntityInterface $view) { + return array( + 'data' => array( + 'view_snapshot_name' => $view->id(), + 'created' => format_date($view->get('created')), + 'comment' => check_plain($view->get('comment')), + 'operations' => array( + 'data' => $this->buildOperations($view), + ), + ), + ); + } + + /** + * Overrides Drupal\Core\Entity\EntityListController::buildHeader(); + */ + public function buildHeader() { + return array( + 'view_snapshot_name' => array( + 'data' => t('Snapshot'), + 'class' => array('views-ui-snapshot-name'), + ), + 'created' => array( + 'data' => t('Created'), + 'class' => array('views-ui-snapshot-created'), + ), + 'comment' => array( + 'data' => t('Comment'), + 'class' => array('views-ui-snapshot-comment'), + ), + 'operations' => array( + 'data' => t('Operations'), + 'class' => array('views-ui-snapshot-operations'), + ), + ); + } + + /** + * Implements Drupal\Core\Entity\EntityListController::getOperations(); + */ + public function getOperations(EntityInterface $snapshot) { + $uri = $snapshot->uri(); + $path = $uri['path']; + + $definition['edit'] = array( + 'href' => $uri['path'] . '/edit', + 'title' => t('Edit'), + 'weight' => -10, + ); + $definition['revert'] = array( + 'href' => "admin/structure/views/nojs/revert-snapshot/{$snapshot->id()}", + 'title' => t('Revert'), + 'attributes' => array('class' => 'views-ajax-link'), + 'weight' => -5, + ); + $definition['delete'] = array( + 'href' => "admin/structure/views/nojs/delete-snapshot/{$snapshot->id()}", + 'title' => t('Delete'), + 'attributes' => array('class' => 'views-ajax-link'), + 'weight' => 0, + ); + + return $definition; + } + +} diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewSnapshotManageFormController.php b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewSnapshotManageFormController.php new file mode 100644 index 0000000..7728905 --- /dev/null +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewSnapshotManageFormController.php @@ -0,0 +1,75 @@ +setOriginalView($entity->get('storage')); + + $form['options']['#title'] = t('View snapshots: @view', array('@view' => $entity->label())); + $form['#section'] = $entity->id() . '-snapshot-list'; + + $form['options'] = array( + '#theme_wrappers' => array('container'), + '#attributes' => array('class' => array('scroll')), + ); + + $form['options']['list'] = $list_controller->render(); + + $form['options']['create'] = array( + '#type' => 'fieldset', + '#title' => t('New snapshot'), + ); + + $form['options']['create']['comment'] = array( + '#type' => 'textarea', + '#title' => t('Comment/description for the snapshot.'), + '#description' => t('Enter an optional comment to attach to the new snapshot when it is created.'), + ); + + $form_state['ok_button'] = TRUE; + $entity->getStandardButtons($form, $form_state, 'views_ui_snapshot_form', 'create_snapshot', t('Create snapshot'), 'create'); + + // Override the submit handler. + // @todo There is probably a better way but may need to modify getStandard + // buttons method. + //$form['buttons']['create']['#submit'] = array($this, 'submit'); + + return $form; + } + + /** + * Overrides Drupal\Core\Entity\EntityFormController::submit(). + */ + public function submit(array $form, array &$form_state) { + $snapshot_controller = entity_get_controller('view_snapshot'); + + $storage = $form_state['view']->get('storage'); + $snapshot = $snapshot_controller->createSnapshot($storage, array('comment' => $form_state['values']['comment'])); + $snapshot->save(); + + // Show a message and redirect to the edit view. + drupal_set_message(t('Snapshot number @id created.', array('@id' => $snapshot->id()))); + $uri = $storage->uri(); + $form_state['redirect'] = $uri['path'] . '/edit'; + } + +} diff --git a/core/modules/views/views_ui/lib/Drupal/views_ui/ViewSnapshotRevertFormController.php b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewSnapshotRevertFormController.php new file mode 100644 index 0000000..ec01138 --- /dev/null +++ b/core/modules/views/views_ui/lib/Drupal/views_ui/ViewSnapshotRevertFormController.php @@ -0,0 +1,57 @@ + $entity->get('name'), '@snapshot' => $entity->id())), + "admin/structure/views/view/{$entity->get('name')}/edit", + t('This cannot be undone.'), + t('Revert'), + t('Cancel') + ); + } + + /** + * Overrides \Drupal\Core\Entity\EntityFormController::form(). + */ + public function submit(array $form, array &$form_state) { + $view_ui = parent::submit($form, $form_state); + $snapshot = $view_ui->get('storage'); + $view = entity_load('view', $snapshot->get('name')); + + $view = entity_get_controller('view_snapshot')->revertSnapshot($view, $snapshot); + + // Get the ID of the snapshot. + list(, $id) = explode(':', $snapshot->id(), 2); + drupal_set_message(t('View @name reverted to snapshot @id', array('@name' => $view->get('name'), '@id' => $id))); + + // @todo The view just gets updated when you reload the browser after + // reverting. + $view_ui = new ViewUI($view); + views_ui_cache_set($view_ui); + + $uri = $view->uri(); + $form_state['redirect'] = $uri['path'] . '/edit'; + } + +} diff --git a/core/modules/views/views_ui/views_ui.module b/core/modules/views/views_ui/views_ui.module index feb6553..d592142 100644 --- a/core/modules/views/views_ui/views_ui.module +++ b/core/modules/views/views_ui/views_ui.module @@ -91,7 +91,8 @@ function views_ui_menu() { 'page arguments' => array(4), ) + $base; $items['admin/structure/views/view/%views_ui_cache/edit'] = array( - 'title' => 'Edit view', + 'title' => ' + Edit view', 'type' => MENU_DEFAULT_LOCAL_TASK, 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE, 'weight' => -10, @@ -119,7 +120,6 @@ function views_ui_menu() { ) + $base; // Additional pages for acting on a View. - $items['admin/structure/views/view/%views_ui_cache/break-lock'] = array( 'title' => 'Break lock', 'page callback' => 'drupal_get_form', @@ -181,6 +181,8 @@ function views_ui_menu() { 'page callback' => 'views_ui_plugin_list', ) + $base; +// $items['admin/structure/views'] + return $items; } @@ -309,7 +311,7 @@ function views_ui_edit_page_title(ViewUI $view) { * Specialized menu callback to load a view and check its locked status. * * @param $name - * The machine name of the view. + * The machine name of the view or the view snapshot. * * @return * The view object, with a "locked" property indicating whether or not @@ -318,7 +320,14 @@ function views_ui_edit_page_title(ViewUI $view) { function views_ui_cache_load($name) { $views_temp_store = drupal_container()->get('user.tempstore')->get('views'); $view = $views_temp_store->get($name); - $storage = entity_load('view', $name); + + if (strpos($name, ':') === FALSE) { + $storage = entity_load('view', $name); + } + else { + $storage = entity_load('view_snapshot', $name); + } + $original_view = $storage ? new ViewUI($storage) : NULL; if (empty($view)) {