diff --git a/core/modules/field/modules/field_sql_storage/field_sql_storage.module b/core/modules/field/modules/field_sql_storage/field_sql_storage.module index fd2f52c25674b192165059258ffe8568770636ec..71de141722b91f7fa27edb840a0d5b96a10f94f7 100644 --- a/core/modules/field/modules/field_sql_storage/field_sql_storage.module +++ b/core/modules/field/modules/field_sql_storage/field_sql_storage.module @@ -398,11 +398,13 @@ function field_sql_storage_field_storage_write($entity_type, $entity, $op, $fiel // Delete all language codes if $entity->$field_name is empty. $langcodes = !empty($entity->$field_name) ? $field_langcodes : $all_langcodes; if ($langcodes) { - db_delete($table_name) - ->condition('entity_type', $entity_type) - ->condition('entity_id', $id) - ->condition('langcode', $langcodes, 'IN') - ->execute(); + if (!property_exists($entity, 'isDefault') || !empty($entity->isDefault)) { + db_delete($table_name) + ->condition('entity_type', $entity_type) + ->condition('entity_id', $id) + ->condition('langcode', $langcodes, 'IN') + ->execute(); + } db_delete($revision_name) ->condition('entity_type', $entity_type) ->condition('entity_id', $id) @@ -451,7 +453,11 @@ function field_sql_storage_field_storage_write($entity_type, $entity, $op, $fiel // Execute the query if we have values to insert. if ($do_insert) { - $query->execute(); + // Only overwrite the field's base table if saving the default revision + // of an entity. + if (!property_exists($entity, 'isDefault') || !empty($entity->isDefault)) { + $query->execute(); + } $revision_query->execute(); } } diff --git a/core/modules/node/lib/Drupal/node/Node.php b/core/modules/node/lib/Drupal/node/Node.php index cee6967b0c1b74ad111e085095fb882625e3a254..d173dd018d0192a70e1e43b865deacdfbda3904f 100644 --- a/core/modules/node/lib/Drupal/node/Node.php +++ b/core/modules/node/lib/Drupal/node/Node.php @@ -22,6 +22,15 @@ class Node extends Entity { public $nid; /** + * The default node revision indicator. + * + * Only default revisions are saved to the node table. + * + * @var boolean + */ + public $isDefault = TRUE; + + /** * The node revision ID. * * @var integer diff --git a/core/modules/node/lib/Drupal/node/NodeStorageController.php b/core/modules/node/lib/Drupal/node/NodeStorageController.php index 0fa7b3387dcf31e082328c1cc13652b0e2435d53..c9af8a5fb1eeebe452d18a1cacb84715c7389f19 100644 --- a/core/modules/node/lib/Drupal/node/NodeStorageController.php +++ b/core/modules/node/lib/Drupal/node/NodeStorageController.php @@ -100,7 +100,19 @@ class NodeStorageController extends DatabaseStorageController { } else { $op = 'update'; - $return = drupal_write_record($this->entityInfo['base table'], $entity, $this->idKey); + + // Update the base node table, but only if this revision is marked as + // the default revision. + if ($entity->isDefault) { + $return = drupal_write_record($this->entityInfo['base table'], $entity, $this->idKey); + } + else { + // @todo, should a different value be returned when saving an entity + // with $isDefault = FALSE? + $return = FALSE; + } + + } if ($this->revisionKey) { @@ -139,10 +151,12 @@ class NodeStorageController extends DatabaseStorageController { if (empty($entity->{$this->revisionKey}) || !empty($entity->revision)) { drupal_write_record($this->revisionTable, $record); - db_update($this->entityInfo['base table']) - ->fields(array($this->revisionKey => $record->{$this->revisionKey})) - ->condition($this->idKey, $entity->{$this->idKey}) - ->execute(); + if ($entity->isDefault) { + db_update($this->entityInfo['base table']) + ->fields(array($this->revisionKey => $record->{$this->revisionKey})) + ->condition($this->idKey, $entity->{$this->idKey}) + ->execute(); + } } else { drupal_write_record($this->revisionTable, $record, $this->revisionKey); @@ -263,7 +277,13 @@ class NodeStorageController extends DatabaseStorageController { * Overrides Drupal\entity\DatabaseStorageController::postSave(). */ function postSave(EntityInterface $node, $update) { - node_access_acquire_grants($node, $update); + + // Update the node access table for this node, but only if it is the + // default revision. There's no need to delete existing records if the node + // is new. + if ($node->isDefault) { + node_access_acquire_grants($node, $update); + } } /** diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeRevisionsTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeRevisionsTest.php index 3cba15d075d282586a9fd6274616267d77b46ab5..d81e92138fdd26c9dcc44554529947ceffd403ab 100644 --- a/core/modules/node/lib/Drupal/node/Tests/NodeRevisionsTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/NodeRevisionsTest.php @@ -24,7 +24,7 @@ class NodeRevisionsTest extends NodeTestBase { // Create and login user. $web_user = $this->drupalCreateUser(array('view revisions', 'revert revisions', 'edit any page content', - 'delete revisions', 'delete any page content')); + 'delete revisions', 'delete any page content', 'administer nodes')); $this->drupalLogin($web_user); // Create initial node. @@ -112,6 +112,44 @@ class NodeRevisionsTest extends NodeTestBase { '%title' => $nodes[2]->title, '%revision-date' => format_date($old_revision_date), ))); + + // Make a new revision and set it to not be default. + // This will create a "forward revision." + $edit = array(); + $langcode = LANGUAGE_NOT_SPECIFIED; + $new_body = $this->randomName(); + $edit["body[$langcode][0][value]"] = $new_body; + // Save this as a forward revision. + $edit["revision"] = TRUE; + $edit["isDefault"] = FALSE; + $this->drupalPost("node/$node->nid/edit", $edit, t('Save')); + $this->drupalGet("node/$node->nid"); + $this->assertNoText($new_body, t('Forward revision body text is not present on live version of node.')); + + // Get the highest vid for this node. + $versions = db_select('node_revision', 'nr') + ->fields('nr', array('vid')) + ->condition('nid', $node->nid) + ->orderBy('nr.vid', 'DESC') + ->range(0,1) + ->execute() + ->fetchCol(); + + $forward_revision_vid = $versions[0]; + + // Verify that the new body text is present on the forward revision. + $this->drupalGet("node/$node->nid/revisions/" . $forward_revision_vid . "/view"); + $this->assertText($new_body, t('Forward revision body text is present on forward version of node.')); + + // Verify that the forward revision vid is greater than the default + // revision vid. + $default_revision = db_select('node', 'n') + ->fields('n', array('vid')) + ->condition('nid', $node->nid) + ->execute() + ->fetchCol(); + $default_revision_vid = $default_revision[0]; + $this->assertTrue($forward_revision_vid > $default_revision_vid, 'Forward revision vid is greater than default revision vid.'); } /** diff --git a/core/modules/node/node.pages.inc b/core/modules/node/node.pages.inc index 5d60f7c7af591b7473e654ba1bb43cface39fed9..55e1cb618c8bcb7ee9891dace79dbd5738853a68 100644 --- a/core/modules/node/node.pages.inc +++ b/core/modules/node/node.pages.inc @@ -239,6 +239,18 @@ function node_form($form, &$form_state, Node $node) { '#default_value' => $node->revision, '#access' => user_access('administer nodes'), ); + $form['revision_information']['isDefault'] = array( + '#type' => 'checkbox', + '#title' => t('Set as default revision'), + '#default_value' => 1, + '#access' => user_access('administer nodes'), + '#states' => array( + 'visible' => array( + ':input[name="revision"]' => array('checked' => TRUE), + ), + ), + ); + // Check the revision log checkbox when the log textarea is filled in. // This must not happen if "Create new revision" is enabled by default, since // the state would auto-disable the checkbox otherwise. diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module index ddc84fe576c16d2aeb638823e932f537df1f2413..0925b1c2865c2a0102e9151bee2ee039b7a01f21 100644 --- a/core/modules/taxonomy/taxonomy.module +++ b/core/modules/taxonomy/taxonomy.module @@ -1585,7 +1585,7 @@ function taxonomy_build_node_index($node) { } } // We only maintain the taxonomy index for published nodes. - if ($status) { + if ($status && !empty($node->isDefault)) { // Collect a unique list of all the term IDs from all node fields. $tid_all = array(); foreach (field_info_instances('node', $node->type) as $instance) {