diff --git a/core/modules/edit/edit.module b/core/modules/edit/edit.module index a704221..60f845d 100644 --- a/core/modules/edit/edit.module +++ b/core/modules/edit/edit.module @@ -164,7 +164,9 @@ function edit_library_info() { function edit_preprocess_field(&$variables) { $element = $variables['element']; $entity = $element['#object']; - $variables['attributes']['data-edit-id'] = $entity->entityType() . '/' . $entity->id() . '/' . $element['#field_name'] . '/' . $element['#language'] . '/' . $element['#view_mode']; + if (empty($entity->in_preview)) { + $variables['attributes']['data-edit-id'] = $entity->entityType() . '/' . $entity->id() . '/' . $element['#field_name'] . '/' . $element['#language'] . '/' . $element['#view_mode']; + } } /** diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterFormatAccessTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterFormatAccessTest.php index 48faf24..de7d5e0 100644 --- a/core/modules/filter/lib/Drupal/filter/Tests/FilterFormatAccessTest.php +++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterFormatAccessTest.php @@ -225,7 +225,7 @@ function testFormatWidgetPermissions() { $this->assertText($edit[$body_value_key], 'Old body found in preview.'); // Save and verify that only the title was changed. - $this->drupalPost(NULL, $new_edit, t('Save')); + $this->drupalPost('node/' . $node->nid . '/edit', $new_edit, t('Save')); $this->assertNoText($edit['title'], 'Old title not found.'); $this->assertText($new_edit['title'], 'New title found.'); $this->assertText($edit[$body_value_key], 'Old body found.'); diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php index 47e1f30..6dedb2d 100644 --- a/core/modules/node/lib/Drupal/node/NodeFormController.php +++ b/core/modules/node/lib/Drupal/node/NodeFormController.php @@ -26,6 +26,16 @@ class NodeFormController extends EntityFormController { * Overrides Drupal\Core\Entity\EntityFormController::prepareEntity(). */ protected function prepareEntity(EntityInterface $node) { + + // Check if we can retrieve a node from the tempstore. + $tempstore_id = drupal_container()->get('request')->query->get('tempstore_id'); + if ($tempstore_id) { + $node->tempstore_id = $tempstore_id; + } + else { + $node->tempstore_id = $node->uuid; + } + // Set up default values, if required. $node_options = variable_get('node_options_' . $node->type, array('status', 'promote')); // If this is a new node, fill in the default values. @@ -71,13 +81,19 @@ public function form(array $form, array &$form_state, EntityInterface $node) { } $user_config = config('user.settings'); - // Some special stuff when previewing a node. - if (isset($form_state['node_preview'])) { - $form['#prefix'] = $form_state['node_preview']; - $node->in_preview = TRUE; - } - else { - unset($node->in_preview); + + // Check if we can retrieve a node from the tempstore. + $tempstore_id = drupal_container()->get('request')->query->get('tempstore_id'); + if (!empty($tempstore_id) && ($data = node_tempstore_load($tempstore_id))) { + $node = $data; + + // Restore the destination if we previewed the node + if (isset($node->destination)) { + $form['node_destination'] = array( + '#type' => 'hidden', + '#value' => $node->destination, + ); + } } // Override the default CSS class name, since the user-defined node type @@ -381,9 +397,21 @@ public function submit(array $form, array &$form_state) { * A reference to a keyed array containing the current state of the form. */ public function preview(array $form, array &$form_state) { - drupal_set_title(t('Preview'), PASS_THROUGH); - $form_state['node_preview'] = node_preview($this->getEntity($form_state)); - $form_state['rebuild'] = TRUE; + $entity = $this->getEntity($form_state); + $entity->in_preview = TRUE; + + // In case the destination parameter is set + if (isset($_GET['destination'])) { + $entity->destination = $_GET['destination']; + unset($_GET['destination']); + } + // In case we already previewed the node, but we want to preview it again. + elseif (isset($form_state['values']['node_destination'])) { + $entity->destination = $form_state['values']['node_destination']; + } + + drupal_container()->get('user.tempstore')->get('node')->set($entity->tempstore_id, $entity); + $form_state['redirect'] = 'node/preview/' . $entity->tempstore_id; } /** @@ -418,6 +446,14 @@ public function save(array $form, array &$form_state) { $form_state['rebuild'] = TRUE; } + // In case we visited the node preview, override the redirect. + if (isset($form_state['values']['node_destination'])) { + $form_state['redirect'] = $form_state['values']['node_destination']; + } + + // Remove from tempstore. + drupal_container()->get('user.tempstore')->get('node')->delete($node->tempstore_id); + // Clear the page and block caches. cache_invalidate_tags(array('content' => TRUE)); } diff --git a/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php b/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php index 6cf9fac..660c9fe 100644 --- a/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php +++ b/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php @@ -206,6 +206,13 @@ class Node extends Entity implements ContentEntityInterface { public $revision_uid; /** + * The node tempstore id. + * + * @var integer + */ + public $tempstore_id; + + /** * Implements Drupal\Core\Entity\EntityInterface::id(). */ public function id() { diff --git a/core/modules/node/lib/Drupal/node/Tests/PagePreviewTest.php b/core/modules/node/lib/Drupal/node/Tests/PagePreviewTest.php index b429e07..54dcd1d 100644 --- a/core/modules/node/lib/Drupal/node/Tests/PagePreviewTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/PagePreviewTest.php @@ -41,11 +41,29 @@ function testPagePreview() { $this->drupalPost('node/add/page', $edit, t('Preview')); // Check that the preview is displaying the title and body. - $this->assertTitle(t('Preview | Drupal'), 'Basic page title is preview.'); + $this->assertTitle(t('@title | Drupal', array('@title' => $edit[$title_key])), 'Basic page title is preview.'); $this->assertText($edit[$title_key], 'Title displayed.'); $this->assertText($edit[$body_key], 'Body displayed.'); + $this->assertLink(t('Back to content editing')); - // Check that the title and body fields are displayed with the correct values. + // Get the tempstore id. + $url = parse_url($this->getUrl()); + $paths = explode('/', $url['path']); + $tempstore_id = array_pop($paths); + + // Switch view mode. We'll remove the body from the body from the teaser + // view mode. + entity_get_display('node', 'page', 'teaser') + ->removeComponent('body') + ->save(); + $view_mode_edit = array('view_mode' => 'teaser'); + $this->drupalPost('node/preview/' . $tempstore_id, $view_mode_edit, t('Switch')); + $this->assertRaw('view-mode-teaser', 'View mode teaser class found.'); + $this->assertNoText($edit[$body_key], 'Body not displayed.'); + + // Check that the title and body fields are displayed with the correct + // values after going back to the content edit page. + $this->clickLink(t('Back to content editing')); $this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.'); $this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.'); } @@ -68,11 +86,13 @@ function testPagePreviewWithRevisions() { $this->drupalPost('node/add/page', $edit, t('Preview')); // Check that the preview is displaying the title and body. - $this->assertTitle(t('Preview | Drupal'), 'Basic page title is preview.'); + $this->assertTitle(t('@title | Drupal', array('@title' => $edit[$title_key])), 'Basic page title is preview.'); $this->assertText($edit[$title_key], 'Title displayed.'); $this->assertText($edit[$body_key], 'Body displayed.'); - // Check that the title and body fields are displayed with the correct values. + // Check that the title and body fields are displayed with the correct + // values after going back to the content edit page. + $this->clickLink(t('Back to content editing')); $this->assertFieldByName($title_key, $edit[$title_key], 'Title field displayed.'); $this->assertFieldByName($body_key, $edit[$body_key], 'Body field displayed.'); diff --git a/core/modules/node/node.module b/core/modules/node/node.module index eb56876..5edbbf9 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -158,10 +158,6 @@ function node_theme() { 'variables' => array('content' => NULL), 'file' => 'node.pages.inc', ), - 'node_preview' => array( - 'variables' => array('node' => NULL), - 'file' => 'node.pages.inc', - ), 'node_admin_overview' => array( 'variables' => array('name' => NULL, 'type' => NULL), ), @@ -943,6 +939,23 @@ function node_load($nid = NULL, $reset = FALSE) { } /** + * Load the node from the tempstore. + * + * @param int $tempstore_id + * The id of a tempstore object. + * + * @return Drupal\node\Node|false + * A fully-populated node entity, or FALSE if the node is not found. + */ +function node_tempstore_load($tempstore_id) { + $node = drupal_container()->get('user.tempstore')->get('node')->get($tempstore_id); + if ($node) { + return $node; + } + return FALSE; +} + +/** * Loads a node revision from the database. * * @param int $nid @@ -1134,7 +1147,7 @@ function template_preprocess_node(&$variables) { $uri = $node->uri(); $variables['node_url'] = url($uri['path'], $uri['options']); $variables['label'] = check_plain($node->label()); - $variables['page'] = $variables['view_mode'] == 'full' && node_is_page($node); + $variables['page'] = ($variables['view_mode'] == 'full' && node_is_page($node)) || (!empty($node->node_page_title)); // Make useful flags and node data available. // @todo: The comment properties only exist if comment.module is enabled, but @@ -1740,6 +1753,13 @@ function node_menu() { 'type' => MENU_DEFAULT_LOCAL_TASK, 'weight' => -10, ); + $items['node/preview/%node_tempstore'] = array( + 'page callback' => 'node_preview', + 'page arguments' => array(2), + 'access callback' => 'node_access_preview', + 'access arguments' => array(2), + 'file' => 'node.pages.inc', + ); $items['node/%node/edit'] = array( 'title' => 'Edit', 'page callback' => 'node_page_edit', @@ -2256,6 +2276,98 @@ function node_page_view(Node $node) { } /** + * Implements hook_page_build(). + */ +function node_page_build(&$page) { + + // Add 'Back to content edit editing' link on preview page. + $node = menu_get_object('node_tempstore', 2); + if ($node) { + + $page['page_top']['node-preview'] = array( + '#type' => 'container', + '#attributes' => array( + 'class' => array('node-preview-container', 'container-inline') + ), + ); + + $form = drupal_get_form('node_preview_form_select', $node); + $page['page_top']['node-preview']['view-mode'] = $form; + } +} + +/** + * Get the preview form selection box. + * + * @param Drupal\node\Node $node + * A node entity. + * + * @return $form + * The view mode preview selection form. + */ +function node_preview_form_select($form, $form_state, Node $node) { + + // Always add default. + $view_mode_options = array('default' => t('Full')); + + // Get view mode options. + $entity_info = entity_get_info('node'); + foreach ($entity_info['view_modes'] as $key => $info) { + if (!empty($info['custom_settings'])) { + $view_mode_options[$key] = $info['label']; + } + } + + $link = 'node/add/' . $node->bundle(); + if (!empty($node->nid)) { + $link = 'node/' . $node->nid . '/edit'; + } + + $view_mode = drupal_container()->get('request')->query->get('view_mode'); + if (empty($view_mode)) { + $view_mode = 'full'; + } + + $form['backlink'] = array( + '#type' => 'link', + '#title' => t('Back to content editing'), + '#href' => $link, + // Add the "overlay-restore" class to indicate this link should restore + // the context in which the preview demonstration page was opened. + '#options' => array('query' => array('tempstore_id' => $node->tempstore_id) ,'attributes' => array('class' => array('node-preview-backlink button-action', 'overlay-restore'))), + //'#prefix' => '