diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php b/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php index e18edbd..7cc7a08 100644 --- a/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php +++ b/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php @@ -483,7 +483,9 @@ protected function mapToDataStorageRecord(EntityInterface $entity, $langcode) { $record = new \stdClass(); foreach ($this->entityInfo['schema_fields_sql']['data_table'] as $name) { - $record->$name = $translation->$name->value; + if (isset($translation->$name->value)) { + $record->$name = $translation->$name->value; + } } $record->langcode = $langcode; $record->default_langcode = intval($default_langcode == $langcode); diff --git a/core/modules/node/lib/Drupal/node/NodeStorageController.php b/core/modules/node/lib/Drupal/node/NodeStorageController.php index c9e832e..aefc0d2 100644 --- a/core/modules/node/lib/Drupal/node/NodeStorageController.php +++ b/core/modules/node/lib/Drupal/node/NodeStorageController.php @@ -80,21 +80,6 @@ protected function attachLoad(&$queried_entities, $load_revision = FALSE) { } /** - * Overrides Drupal\Core\Entity\DatabaseStorageController::buildQuery(). - */ - protected function buildQuery($ids, $revision_id = FALSE) { - // Ensure that uid is taken from the {node} table, - // alias timestamp to revision_timestamp and add revision_uid. - $query = parent::buildQuery($ids, $revision_id); - $fields =& $query->getFields(); - unset($fields['timestamp']); - $query->addField('revision', 'timestamp', 'revision_timestamp'); - $fields['uid']['table'] = 'base'; - $query->addField('revision', 'uid', 'revision_uid'); - return $query; - } - - /** * Overrides Drupal\Core\Entity\DatabaseStorageController::invokeHook(). */ protected function invokeHook($hook, EntityInterface $node) { @@ -129,6 +114,16 @@ protected function invokeHook($hook, EntityInterface $node) { } /** + * Overrides \Drupal\Core\Entity\DatabaseStorageControllerNG::mapToDataStorageRecord(). + */ + protected function mapToDataStorageRecord(EntityInterface $entity, $langcode) { + // @todo Remove this once comment is a regular entity field. + $record = parent::mapToDataStorageRecord($entity, $langcode); + $record->comment = intval($record->comment); + return $record; + } + + /** * Overrides Drupal\Core\Entity\DatabaseStorageController::preSave(). */ protected function preSave(EntityInterface $node) { 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 e367425..c1bf677 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 @@ -27,7 +27,8 @@ * }, * translation_controller_class = "Drupal\node\NodeTranslationController", * base_table = "node", - * revision_table = "node_revision", + * data_table = "node_property_data", + * revision_table = "node_property_revision", * uri_callback = "node_uri", * fieldable = TRUE, * translatable = TRUE, diff --git a/core/modules/node/node.install b/core/modules/node/node.install index ebbce13..573bdba0 100644 --- a/core/modules/node/node.install +++ b/core/modules/node/node.install @@ -27,7 +27,7 @@ function node_schema() { // Defaults to NULL in order to avoid a brief period of potential // deadlocks on the index. 'vid' => array( - 'description' => 'The current {node_revision}.vid version identifier.', + 'description' => 'The current {node_property_revision}.vid version identifier.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => FALSE, @@ -47,56 +47,8 @@ function node_schema() { 'not null' => TRUE, 'default' => '', ), - 'title' => array( - 'description' => 'The title of this node, always treated as non-markup plain text.', - 'type' => 'varchar', - 'length' => 255, - 'not null' => TRUE, - 'default' => '', - ), - 'uid' => array( - 'description' => 'The {users}.uid that owns this node; initially, this is the user that created it.', - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'default' => 0, - ), - 'status' => array( - 'description' => 'Boolean indicating whether the node is published (visible to non-administrators).', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 1, - ), - 'created' => array( - 'description' => 'The Unix timestamp when the node was created.', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - ), - 'changed' => array( - 'description' => 'The Unix timestamp when the node was most recently saved.', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - ), - 'comment' => array( - 'description' => 'Whether comments are allowed on this node: 0 = no, 1 = closed (read only), 2 = open (read/write).', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - ), - 'promote' => array( - 'description' => 'Boolean indicating whether the node should be displayed on the front page.', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - ), - 'sticky' => array( - 'description' => 'Boolean indicating whether the node should be displayed at the top of lists in which it appears.', - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - ), + // @todo Remove the following columns when removing the legacy Content + // Translation module. 'tnid' => array( 'description' => 'The translation set id for this node, which equals the node id of the source post in each set.', 'type' => 'int', @@ -112,15 +64,9 @@ function node_schema() { ), ), 'indexes' => array( - 'node_changed' => array('changed'), - 'node_created' => array('created'), - 'node_frontpage' => array('promote', 'status', 'sticky', 'created'), - 'node_status_type' => array('status', 'type', 'nid'), - 'node_title_type' => array('title', array('type', 4)), - 'node_type' => array(array('type', 4)), - 'uid' => array('uid'), - 'tnid' => array('tnid'), - 'translate' => array('translate'), + 'node_type' => array(array('type', 4)), + 'tnid' => array('tnid'), + 'translate' => array('translate'), ), 'unique keys' => array( 'vid' => array('vid'), @@ -128,76 +74,118 @@ function node_schema() { ), 'foreign keys' => array( 'node_revision' => array( - 'table' => 'node_revision', + 'table' => 'node_property_revision', 'columns' => array('vid' => 'vid'), ), - 'node_author' => array( - 'table' => 'users', - 'columns' => array('uid' => 'uid'), - ), ), 'primary key' => array('nid'), ); - $schema['node_access'] = array( - 'description' => 'Identifies which realm/grant pairs a user must possess in order to view, update, or delete specific nodes.', + // Node property storage. + $schema['node_property_data'] = array( + 'description' => 'Base table for node properties.', 'fields' => array( 'nid' => array( - 'description' => 'The {node}.nid this record affects.', - 'type' => 'int', + 'description' => 'The primary identifier for a node.', + 'type' => 'serial', 'unsigned' => TRUE, 'not null' => TRUE, - 'default' => 0, ), - 'gid' => array( - 'description' => "The grant ID a user must possess in the specified realm to gain this row's privileges on the node.", + 'vid' => array( + 'description' => 'The current {node_property_revision}.vid version identifier.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, - 'default' => 0, ), - 'realm' => array( - 'description' => 'The realm in which the user must possess the grant ID. Each node access node can define one or more realms.', + 'langcode' => array( + 'description' => 'The {language}.langcode of these node property values.', + 'type' => 'varchar', + 'length' => 12, + 'not null' => TRUE, + 'default' => '', + ), + 'default_langcode' => array( + 'description' => 'Boolean indicating whether the property values are in the {language}.langcode of this node.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 1, + ), + 'title' => array( + 'description' => 'The title of this node, always treated as non-markup plain text.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), - 'grant_view' => array( - 'description' => 'Boolean indicating whether a user with the realm/grant pair can view this node.', + 'uid' => array( + 'description' => 'The {users}.uid that owns this node; initially, this is the user that created it.', 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, - 'size' => 'tiny', ), - 'grant_update' => array( - 'description' => 'Boolean indicating whether a user with the realm/grant pair can edit this node.', + 'status' => array( + 'description' => 'Boolean indicating whether the node translation is published (visible to non-administrators).', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 1, + ), + 'created' => array( + 'description' => 'The Unix timestamp when the node translation was created.', 'type' => 'int', - 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, - 'size' => 'tiny', ), - 'grant_delete' => array( - 'description' => 'Boolean indicating whether a user with the realm/grant pair can delete this node.', + 'changed' => array( + 'description' => 'The Unix timestamp when the node translation was most recently saved.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), + 'comment' => array( + 'description' => 'Whether comments are allowed on this node translation: 0 = no, 1 = closed (read only), 2 = open (read/write).', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), + 'promote' => array( + 'description' => 'Boolean indicating whether the node translation should be displayed on the front page.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), + 'sticky' => array( + 'description' => 'Boolean indicating whether the node translation should be displayed at the top of lists in which it appears.', 'type' => 'int', - 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, - 'size' => 'tiny', ), ), - 'primary key' => array('nid', 'gid', 'realm'), + 'indexes' => array( + 'node_changed' => array('changed'), + 'node_created' => array('created'), + 'node_frontpage' => array('promote', 'status', 'sticky', 'created'), + // @todo Figure out how to replace the 'node_status_type' and the + // 'node_title_type' indexes. + 'nid' => array('nid'), + 'vid' => array('vid'), + 'uid' => array('uid'), + ), 'foreign keys' => array( - 'affected_node' => array( + 'node_base' => array( 'table' => 'node', 'columns' => array('nid' => 'nid'), ), - ), + 'node_author' => array( + 'table' => 'users', + 'columns' => array('uid' => 'uid'), + ), + ), + 'primary key' => array('nid', 'vid', 'langcode'), ); - $schema['node_revision'] = array( + // Node property revision storage. + $schema['node_property_revision'] = array( 'description' => 'Stores information about each saved version of a {node}.', 'fields' => array( 'nid' => array( @@ -205,7 +193,6 @@ function node_schema() { 'type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE, - 'default' => 0, ), 'vid' => array( 'description' => 'The primary identifier for this version.', @@ -213,29 +200,30 @@ function node_schema() { 'unsigned' => TRUE, 'not null' => TRUE, ), - 'uid' => array( - 'description' => 'The {users}.uid that created this version.', + 'langcode' => array( + 'description' => 'The {language}.langcode of this version.', + 'type' => 'varchar', + 'length' => 12, + 'not null' => TRUE, + 'default' => '', + ), + 'default_langcode' => array( + 'description' => 'Boolean indicating whether the property values of this version are in the {language}.langcode of this node.', 'type' => 'int', - 'unsigned' => TRUE, 'not null' => TRUE, - 'default' => 0, + 'default' => 1, ), 'title' => array( - 'description' => 'The title of this version.', + 'description' => 'The title of this version, always treated as non-markup plain text.', 'type' => 'varchar', 'length' => 255, 'not null' => TRUE, 'default' => '', ), - 'log' => array( - 'description' => 'The log entry explaining the changes in this version.', - 'type' => 'text', - 'not null' => TRUE, - 'size' => 'big', - ), - 'timestamp' => array( - 'description' => 'A Unix timestamp indicating when this version was created.', + 'uid' => array( + 'description' => 'The {users}.uid that created this version.', 'type' => 'int', + 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 0, ), @@ -245,6 +233,18 @@ function node_schema() { 'not null' => TRUE, 'default' => 1, ), + 'created' => array( + 'description' => 'The Unix timestamp when the version was created.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), + 'changed' => array( + 'description' => 'The Unix timestamp when the version was most recently saved.', + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + ), 'comment' => array( 'description' => 'Whether comments are allowed on this node (at the time of this revision): 0 = no, 1 = closed (read only), 2 = open (read/write).', 'type' => 'int', @@ -263,12 +263,18 @@ function node_schema() { 'not null' => TRUE, 'default' => 0, ), + 'log' => array( + 'description' => 'The log entry explaining the changes in this version.', + 'type' => 'text', + 'not null' => FALSE, + 'size' => 'big', + ), ), 'indexes' => array( 'nid' => array('nid'), 'uid' => array('uid'), + 'vid' => array('vid'), ), - 'primary key' => array('vid'), 'foreign keys' => array( 'versioned_node' => array( 'table' => 'node', @@ -279,6 +285,65 @@ function node_schema() { 'columns' => array('uid' => 'uid'), ), ), + 'primary key' => array('nid', 'vid', 'langcode'), + ); + + $schema['node_access'] = array( + 'description' => 'Identifies which realm/grant pairs a user must possess in order to view, update, or delete specific nodes.', + 'fields' => array( + 'nid' => array( + 'description' => 'The {node}.nid this record affects.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'gid' => array( + 'description' => "The grant ID a user must possess in the specified realm to gain this row's privileges on the node.", + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + ), + 'realm' => array( + 'description' => 'The realm in which the user must possess the grant ID. Each node access node can define one or more realms.', + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + ), + 'grant_view' => array( + 'description' => 'Boolean indicating whether a user with the realm/grant pair can view this node.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'size' => 'tiny', + ), + 'grant_update' => array( + 'description' => 'Boolean indicating whether a user with the realm/grant pair can edit this node.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'size' => 'tiny', + ), + 'grant_delete' => array( + 'description' => 'Boolean indicating whether a user with the realm/grant pair can delete this node.', + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'default' => 0, + 'size' => 'tiny', + ), + ), + 'primary key' => array('nid', 'gid', 'realm'), + 'foreign keys' => array( + 'affected_node' => array( + 'table' => 'node', + 'columns' => array('nid' => 'nid'), + ), + ), ); $schema['node_type'] = array( @@ -361,7 +426,7 @@ function node_schema() { 'type' => 'int', 'not null' => TRUE, 'default' => 0, - 'size' => 'tiny' + 'size' => 'tiny', ), 'orig_type' => array( 'description' => 'The original machine-readable name of this node type. This may be different from the current type name if the locked field is 0.', diff --git a/core/modules/node/node.module b/core/modules/node/node.module index 0b7262c..e14ab3d 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -1606,7 +1606,7 @@ function _node_revision_access(EntityInterface $node, $op = 'view', $account = N // different revisions so there is no need for a separate database check. // Also, if you try to revert to or delete the default revision, that's // not good. - if ($node->isDefaultRevision() && (db_query('SELECT COUNT(vid) FROM {node_revision} WHERE nid = :nid', array(':nid' => $node->nid))->fetchField() == 1 || $op == 'update' || $op == 'delete')) { + if ($node->isDefaultRevision() && (db_query('SELECT COUNT(vid) FROM {node_property_revision} WHERE nid = :nid', array(':nid' => $node->nid))->fetchField() == 1 || $op == 'update' || $op == 'delete')) { $access[$cid] = FALSE; } elseif (user_access('administer nodes', $account)) { @@ -1857,7 +1857,7 @@ function node_page_title(EntityInterface $node) { * A unix timestamp indicating the last time the node was changed. */ function node_last_changed($nid) { - return db_query('SELECT changed FROM {node} WHERE nid = :nid', array(':nid' => $nid))->fetch()->changed; + return db_query('SELECT changed FROM {node_property_data} WHERE nid = :nid', array(':nid' => $nid))->fetch()->changed; } /**