diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php index 1c7d9fd..2ca1ff3 100644 --- a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php +++ b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php @@ -263,7 +263,7 @@ public function loadRevision($revision_id) { // which attaches fields (if supported by the entity type) and calls the // entity type specific load callback, for example hook_node_load(). if (!empty($queried_entities)) { - $this->attachLoad($queried_entities, TRUE); + $this->attachLoad($queried_entities, $revision_id); } return reset($queried_entities); } diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php b/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php index e18edbd..67c3ce2 100644 --- a/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php +++ b/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php @@ -148,6 +148,56 @@ protected function buildPropertyQuery(QueryInterface $entity_query, array $value } /** + * Overrides \Drupal\Core\Entity\DatabaseStorageController::buildQuery(). + */ + protected function buildQuery($ids, $revision_id = FALSE) { + $query = db_select($this->entityInfo['base_table'], 'base'); + + $query->addTag($this->entityType . '_load_multiple'); + + if (!$this->dataTable) { + if ($revision_id) { + $query->join($this->revisionTable, 'revision', "revision.{$this->idKey} = base.{$this->idKey} AND revision.{$this->revisionKey} = :revisionId", array(':revisionId' => $revision_id)); + } + elseif ($this->revisionKey) { + $query->join($this->revisionTable, 'revision', "revision.{$this->revisionKey} = base.{$this->revisionKey}"); + } + } + + // Add fields from the {entity} table. + $entity_fields = $this->entityInfo['schema_fields_sql']['base_table']; + + if ($this->revisionKey && !$this->dataTable) { + // Add all fields from the {entity_revision} table. + $entity_revision_fields = drupal_map_assoc($this->entityInfo['schema_fields_sql']['revision_table']); + // The id field is provided by entity, so remove it. + unset($entity_revision_fields[$this->idKey]); + + // Remove all fields from the base table that are also fields by the same + // name in the revision table. + $entity_field_keys = array_flip($entity_fields); + foreach ($entity_revision_fields as $key => $name) { + if (isset($entity_field_keys[$name])) { + unset($entity_fields[$entity_field_keys[$name]]); + } + } + $query->fields('revision', $entity_revision_fields); + + // Compare revision id of the base and revision table, if equal then this + // is the default revision. + $query->addExpression('base.' . $this->revisionKey . ' = revision.' . $this->revisionKey, 'isDefaultRevision'); + } + + $query->fields('base', $entity_fields); + + if ($ids) { + $query->condition("base.{$this->idKey}", $ids, 'IN'); + } + + return $query; + } + + /** * Overrides DatabaseStorageController::attachLoad(). * * Added mapping from storage records to entities. @@ -220,39 +270,54 @@ protected function mapFromStorageRecords(array $records, $load_revision = FALSE) * * @param array &$entities * Associative array of entities, keyed on the entity ID. - * @param boolean $load_revision - * (optional) TRUE if the revision should be loaded, defaults to FALSE. + * @param int $revision_id + * (optional) The revision to be loaded. Defaults to FALSE. */ - protected function attachPropertyData(array &$entities, $load_revision = FALSE) { + protected function attachPropertyData(array &$entities, $revision_id = FALSE) { if ($this->dataTable) { - $query = db_select($this->dataTable, 'data', array('fetch' => PDO::FETCH_ASSOC)) + // If a revision table is available, we need all the properties of the + // latest revision. Otherwise we fall back to the data table. + $table = $this->revisionTable ?: $this->dataTable; + $query = db_select($table, 'data', array('fetch' => PDO::FETCH_ASSOC)) ->fields('data') ->condition($this->idKey, array_keys($entities)) ->orderBy('data.' . $this->idKey); - if ($load_revision) { - // Get revision ID's. - $revision_ids = array(); - foreach ($entities as $id => $entity) { - $revision_ids[] = $entity->get($this->revisionKey)->value; + + if ($this->revisionTable) { + if ($revision_id) { + $query->condition($this->revisionKey, $revision_id); + } + else { + // Get revision ID's. + $revision_ids = array(); + foreach ($entities as $id => $entity) { + $revision_ids[] = $entity->get($this->revisionKey)->value; + } + $query->condition($this->revisionKey, $revision_ids); } - $query->condition($this->revisionKey, $revision_ids); } + $data = $query->execute(); - // Fetch the field definitions to check which field is translatable. $field_definition = $this->getFieldDefinitions(array()); $data_fields = array_flip($this->entityInfo['schema_fields_sql']['data_table']); foreach ($data as $values) { $id = $values[$this->idKey]; + + if ($this->revisionTable) { + // Unless a revision id was specified we are dealing with the default + // revision. + $entities[$id]->getBCEntity()->isDefaultRevision = intval(empty($revision_id)); + } + // Field values in default language are stored with LANGUAGE_DEFAULT as // key. $langcode = empty($values['default_langcode']) ? $values['langcode'] : LANGUAGE_DEFAULT; $translation = $entities[$id]->getTranslation($langcode); foreach ($field_definition as $name => $definition) { - // Set translatable properties only. - if (isset($data_fields[$name]) && !empty($definition['translatable'])) { + if (isset($data_fields[$name])) { // @todo Figure out how to determine which property has to be set. // Currently it's guessing, and guessing is evil! $property_definition = $translation->{$name}->getPropertyDefinitions(); @@ -483,7 +548,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..40389ae 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 = isset($record->comment) ? intval($record->comment) : 0; + 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 92ed8e8..a3e22cb 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 @@ -28,7 +28,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/lib/Drupal/node/Tests/NodeAdminTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeAdminTest.php index bcfbfcd..8ba9e99 100644 --- a/core/modules/node/lib/Drupal/node/Tests/NodeAdminTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/NodeAdminTest.php @@ -44,7 +44,7 @@ function testContentAdminSort() { } // Test that the default sort by node.changed DESC actually fires properly. - $nodes_query = db_select('node', 'n') + $nodes_query = db_select('node_property_data', 'n') ->fields('n', array('nid')) ->orderBy('changed', 'DESC') ->execute() @@ -59,7 +59,7 @@ function testContentAdminSort() { // Compare the rendered HTML node list to a query for the nodes ordered by // title to account for possible database-dependent sort order. - $nodes_query = db_select('node', 'n') + $nodes_query = db_select('node_property_data', 'n') ->fields('n', array('nid')) ->orderBy('title') ->execute() diff --git a/core/modules/node/node.admin.inc b/core/modules/node/node.admin.inc index 139b2d2..d4995d3 100644 --- a/core/modules/node/node.admin.inc +++ b/core/modules/node/node.admin.inc @@ -5,7 +5,7 @@ * Content administration and module settings user interface. */ -use Drupal\Core\Database\Query\SelectInterface; +use Drupal\Core\Entity\Query\QueryInterface; /** * Page callback: Form constructor for the permission rebuild confirmation form. @@ -131,18 +131,21 @@ function node_filters() { * @param Drupal\Core\Database\Query\SelectInterface $query * A SelectQuery to which the filters should be applied. */ -function node_build_filter_query(SelectInterface $query) { +function node_build_filter_query(QueryInterface $query) { // Build query $filter_data = isset($_SESSION['node_overview_filter']) ? $_SESSION['node_overview_filter'] : array(); foreach ($filter_data as $index => $filter) { list($key, $value) = $filter; switch ($key) { case 'status': - // Note: no exploitable hole as $key/$value have already been checked when submitted + // Note: no exploitable hole as $key/$value have already been checked + // when submitted. list($key, $value) = explode('-', $value, 2); + $query->condition($key, $value); + break; case 'type': case 'langcode': - $query->condition('n.' . $key, $value); + $query->condition($key, $value); break; } } @@ -460,11 +463,11 @@ function node_admin_nodes() { $header = array( 'title' => array( 'data' => t('Title'), - 'field' => 'n.title', + 'specifier' => 'title', ), 'type' => array( 'data' => t('Content type'), - 'field' => 'n.type', + 'specifier' => 'type', 'class' => array(RESPONSIVE_PRIORITY_MEDIUM), ), 'author' => array( @@ -473,47 +476,45 @@ function node_admin_nodes() { ), 'status' => array( 'data' => t('Status'), - 'field' => 'n.status', + 'specifier' => 'status', ), 'changed' => array( 'data' => t('Updated'), - 'field' => 'n.changed', + 'specifier' => 'changed', 'sort' => 'desc', 'class' => array(RESPONSIVE_PRIORITY_LOW) ,) ); if ($multilingual) { - $header['language_name'] = array('data' => t('Language'), 'field' => 'n.langcode', 'class' => array(RESPONSIVE_PRIORITY_LOW)); + $header['language_name'] = array('data' => t('Language'), 'specifier' => 'langcode', 'class' => array(RESPONSIVE_PRIORITY_LOW)); } $header['operations'] = array('data' => t('Operations')); - $query = db_select('node', 'n') - ->extend('Drupal\Core\Database\Query\PagerSelectExtender') - ->extend('Drupal\Core\Database\Query\TableSortExtender'); + $query = entity_query('node') + ->pager(50) + ->tableSort($header) + // Provide a default sort. + ->sort('nid', 'desc'); node_build_filter_query($query); if (!user_access('bypass node access')) { // If the user is able to view their own unpublished nodes, allow them // to see these in addition to published nodes. Check that they actually // have some unpublished nodes to view before adding the condition. - if (user_access('view own unpublished content') && $own_unpublished = db_query('SELECT nid FROM {node} WHERE uid = :uid AND status = :status', array(':uid' => $GLOBALS['user']->uid, ':status' => 0))->fetchCol()) { - $query->condition(db_or() - ->condition('n.status', 1) - ->condition('n.nid', $own_unpublished, 'IN') + if (user_access('view own unpublished content') && $own_unpublished = entity_query('node')->condition('uid', $GLOBALS['user']->uid)->condition('status', 0)->execute()) { + $query->condition( + $query->orConditionGroup() + ->condition('status', 1) + ->condition('nid', $own_unpublished, 'IN') ); } else { // If not, restrict the query to published nodes. - $query->condition('n.status', 1); + $query->condition('status', 1); } } - $nids = $query - ->fields('n',array('nid')) - ->limit(50) - ->orderByHeader($header) - ->addTag('node_access') - ->execute() - ->fetchCol(); + + $nids = $query->execute(); $nodes = node_load_multiple($nids); // Prepare the list of nodes. @@ -568,7 +569,7 @@ function node_admin_nodes() { 'query' => $destination, ); } - if (module_invoke('translation_entity', 'enabled', 'node', $node->bundle())) { + if ($node->isTranslatable()) { $operations['translate'] = array( 'title' => t('Translate'), 'href' => 'node/' . $node->nid . '/translations', 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 4c7392b..3dfbfe8 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -1607,7 +1607,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)) { @@ -1858,7 +1858,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; } /** diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php index 5cca38a..aba4967 100644 --- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php +++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php @@ -274,10 +274,10 @@ protected function drupalCreateNode(array $settings = array()) { $node->save(); // Small hack to link revisions to our test user. - db_update('node_revision') - ->fields(array('uid' => $node->uid)) - ->condition('vid', $node->vid) - ->execute(); +// db_update('node_revision') +// ->fields(array('uid' => $node->uid)) +// ->condition('vid', $node->vid) +// ->execute(); return $node; }