diff --git a/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php b/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php index 43eb437..bba9b11 100644 --- a/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php +++ b/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php @@ -10,6 +10,7 @@ use Drupal\Core\Database\Connection; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\Query\QueryInterface; +use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Language\Language; use Drupal\Component\Utility\NestedArray; use Drupal\Component\Uuid\Uuid; @@ -1502,8 +1503,6 @@ static public function _fieldColumnName(FieldConfigInterface $field, $column) { * @return array|null * Returns the schema definitions for the entity type's tables. If the * entity type does not have a schema, returns NULL. - * - * @throws \LogicException */ public function getSchema($table_key = NULL) { $passed_table_key = $table_key; @@ -1529,92 +1528,24 @@ public function getSchema($table_key = NULL) { 'bundle' => $this->bundleKey, 'uuid' => $this->uuidKey, )); - - // Prepare a mapping of which fields should be stored on which table. This - // information depends on which table types are provided. - if (!isset($tables['data_table']) && !isset($tables['revision_table'])) { - // In the simplest case all fields are stored in the base table. - $field_table_mapping = array('base_table' => array_values($entity_keys)); - $other_fields_tables = array('base_table'); - } - elseif (!isset($tables['data_table']) && isset($tables['revision_table'])) { - // For non-translatable, revisionable entities the entity key fields - // except for ID and revision ID are only stored in the base table. The ID - // is stored in both the base table and the revision table and the - // revision ID is only stored in the revision table. Additionally, the - // default revision ID of an entity is tracked as the revision ID field in - // the base table. - // Other fields are stored in the in the revision table and other fields - // of the default revision are stored in the the base table. - $field_table_mapping = array( - 'base_table' => array_values($entity_keys), - 'revision_table' => array($entity_keys['id'], $entity_keys['revision']), - ); - $other_fields_tables = array('base_table', 'revision_table'); - } - elseif (isset($tables['data_table']) && !isset($tables['revision_table'])) { - // @todo Remove this when https://drupal.org/node/2143729 has landed - $entity_keys['langcode'] = 'langcode'; - - // For translatable, non-revisionable entities the entity key fields - // except for ID and language code are only stored in the base table. All - // other fields are only stored in the data table. The ID is stored in - // both the base table and the data table and the language code is only - // stored in the data table. Additionally, whether or not a language - // variant belongs to the default language code of an entity is tracked in - // the data table as the default language code field and the respective - // default language code is stored as the language code field in the base - // table. - $field_table_mapping = array( - 'base_table' => array_values($entity_keys), - 'data_table' => array($entity_keys['id'], 'langcode', 'default_langcode'), - ); - $other_fields_tables = array('data_table'); - } - else { - // @todo Remove this when https://drupal.org/node/2143729 has landed - $entity_keys['langcode'] = 'langcode'; - - // For translatable, revisionable entities the entity key fields except - // for ID, language code and revision ID are only stored on the base - // table. The ID is stored on the base table, the data table, the revision - // table, and the revision data table. The language code is stored both on - // the data table and the revision data table. Additionally, whether or - // not a language variant belongs to the default language code of an - // entity is tracked in the data table as the default language code field - // and the respective default language code is stored as the language code - // field in the base table. Similarly, whether or not a language variant - // belongs to the default language code of an entity revision is tracked - // in the revision data table as the default language code field and the - // respective default language code is stored as the language code field - // in the revision table. Furthermore, the revision ID is stored both in - // the revision table and the revision data table. Additionally, the - // default revision ID of an entity is tracked as the revision ID field in - // both the base table and the data table. Other fields are stored in the - // revision data table and other fields of the default revision are stored - // in the data table. - $field_table_mapping = array( - 'base_table' => array_values($entity_keys), - 'revision_table' => array($entity_keys['id'], $entity_keys['revision'], 'langcode'), - 'data_table' => array($entity_keys['id'], $entity_keys['revision'], 'langcode', 'default_langcode'), - 'revision_data_table' => array($entity_keys['id'], $entity_keys['revision'], 'langcode', 'default_langcode'), - ); - $other_fields_tables = array('data_table', 'revision_data_table'); + if ($this->dataTable) { + $entity_keys['language'] = 'langcode'; + $entity_keys['default_language'] = 'default_langcode'; } // Add primary keys and common foreign keys to the tables. $this->schema[$tables['base_table']]['primary key'] = array($entity_keys['id']); $this->schema[$tables['base_table']]['foreign keys'] = array(); - if (isset($tables['data_table'])) { - $this->schema[$tables['data_table']]['primary key'] = array($entity_keys['id'], 'langcode'); - $this->schema[$tables['data_table']]['foreign keys'][$entity_keys['id']] = array( + if (isset($tables['revision_table'])) { + $this->schema[$tables['revision_table']]['primary key'] = array($entity_keys['revision']); + $this->schema[$tables['revision_table']]['foreign keys'][$entity_keys['id']] = array( 'table' => $tables['base_table'], 'columns' => array($entity_keys['id'] => $entity_keys['id']), ); } - if (isset($tables['revision_table'])) { - $this->schema[$tables['revision_table']]['primary key'] = array($entity_keys['revision']); - $this->schema[$tables['revision_table']]['foreign keys'][$entity_keys['id']] = array( + if (isset($tables['data_table'])) { + $this->schema[$tables['data_table']]['primary key'] = array($entity_keys['id'], 'langcode'); + $this->schema[$tables['data_table']]['foreign keys'][$entity_keys['id']] = array( 'table' => $tables['base_table'], 'columns' => array($entity_keys['id'] => $entity_keys['id']), ); @@ -1636,60 +1567,35 @@ public function getSchema($table_key = NULL) { // info or alter hooks. foreach($class::baseFieldDefinitions($entity_type_id) as $field_name => $field_definition) { /** @var \Drupal\Core\Field\FieldDefinitionInterface $field_definition */ + if ($field_definition->isComputed()) { + continue; + } - $field_schema = $field_definition->getSchema(); - $field_schema['description'] = $field_definition->getDescription(); - - $single_column_field = count($field_schema['columns']) == 1; - $main_property_name = $field_definition->getMainPropertyName(); - - if (in_array($field_name, $entity_keys)) { - foreach ($field_table_mapping as $table_key => $field_names) { - if (in_array($field_name, $field_names)) { - if (!$single_column_field) { - throw new \LogicException("The $field_name field of the $entity_type_id entity type has multiple columns."); - } - $this->schema[$tables[$table_key]]['fields'][$field_name] = $field_schema['columns'][$main_property_name]; - $this->schema[$tables[$table_key]]['fields'][$field_name]['description'] = $field_definition->getDescription(); - - if (!empty($field_schema['unique keys'])) { - $this->schema[$tables[$table_key]]['unique keys'][$field_name] = array($field_name); - } - if (!empty($field_schema['indexes'])) { - // @todo Support indexes specified as an array of column name and - // length. - $this->schema[$tables[$table_key]]['indexes'][$field_name] = array($field_name); - } - if (!empty($field_schema['foreign keys'])) { - $this->schema[$tables[$table_key]]['foreign keys'] += $field_schema['foreign keys']; - } - } + if (FALSE !== $key = array_search($field_name, $entity_keys)) { + if ($key !== 'default_language') { + $this->addFieldSchema($this->schema[$this->baseTable], $field_name, $field_definition); + } + if ($this->revisionTable && in_array($key, array('id', 'revision', 'language'))) { + $this->addFieldSchema($this->schema[$this->revisionTable], $field_name, $field_definition); + } + if ($this->dataTable && in_array($key, array('id', 'revision', 'language', 'default_language'))) { + $this->addFieldSchema($this->schema[$this->dataTable], $field_name, $field_definition); + } + if ($this->revisionDataTable && in_array($key, array('id', 'revision', 'language', 'default_language'))) { + $this->addFieldSchema($this->schema[$this->revisionDataTable], $field_name, $field_definition); } } else { - foreach ($other_fields_tables as $table_key) { - if ($single_column_field) { - $this->schema[$tables[$table_key]]['fields'][$field_name] = $field_schema['columns'][$main_property_name]; - $this->schema[$tables[$table_key]]['fields'][$field_name]['description'] = $field_definition->getDescription(); - - if (!empty($field_schema['unique keys'])) { - $this->schema[$tables[$table_key]]['unique keys'][$field_name] = array($field_name); - } - if (!empty($field_schema['indexes'])) { - // @todo Support indexes specified as an array of column name and - // length. - $this->schema[$tables[$table_key]]['indexes'][$field_name] = array($field_name); - } - if (!empty($field_schema['foreign keys'])) { - $this->schema[$tables[$table_key]]['foreign keys'] += $field_schema['foreign keys']; - } + if (!$this->dataTable || !$field_definition->isTranslatable()) { + $this->addFieldSchema($this->schema[$this->baseTable], $field_name, $field_definition); + if ($this->revisionTable) { + $this->addFieldSchema($this->schema[$this->revisionTable], $field_name, $field_definition); } - else { - foreach ($field_schema['columns'] as $column_name => $column_schema) { - $this->schema[$tables[$table_key]]['fields'][$field_name . '__' . $column_name] = $column_schema; - } - - // @todo Unique keys, indexes and foreign keys. + } + else { + $this->addFieldSchema($this->schema[$this->dataTable], $field_name, $field_definition); + if ($this->revisionDataTable) { + $this->addFieldSchema($this->schema[$this->revisionDataTable], $field_name, $field_definition); } } } @@ -1724,6 +1630,43 @@ public function getSchema($table_key = NULL) { } /** + * Adds the schema for a single to the table schema. + * + * @param array $schema + * The schema array for a table, passed by reference. + * @param string $field_name + * The name of the field. + * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition + * The field definition of the field. + */ + protected function addFieldSchema(&$schema, $field_name, FieldDefinitionInterface $field_definition) { + $field_schema = $field_definition->getSchema(); + if (count($field_schema['columns']) == 1) { + $schema['fields'][$field_name] = $field_schema['columns'][$field_definition->getMainPropertyName()]; + $schema['fields'][$field_name]['description'] = $field_definition->getDescription(); + + if (!empty($field_schema['unique keys'])) { + $schema['unique keys'][$field_name] = array($field_name); + } + if (!empty($field_schema['indexes'])) { + // @todo Support indexes specified as an array of column name and + // length. + $schema['indexes'][$field_name] = array($field_name); + } + if (!empty($field_schema['foreign keys'])) { + $schema['foreign keys'] += $field_schema['foreign keys']; + } + } + else { + foreach ($field_schema['columns'] as $column_name => $column_schema) { + $schema['fields'][$field_name . '__' . $column_name] = $column_schema; + } + + // @todo Descriptions, unique keys, indexes and foreign keys. + } + } + + /** * Checks whether the entity tables exist in the database. * * @return bool diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php index e366b85..3c4198f 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php @@ -240,7 +240,10 @@ public static function baseFieldDefinitions($entity_type) { ->setDescription(t('The parents of this term.')) // Save new terms with no parents by default. ->setSetting('default_value', 0) - ->setConstraints(array('TermParent' => array())); + ->setConstraints(array('TermParent' => array())) + // The parent of a taxonomy term is not computed from other fields but is + // stored separately in the {taxonomy_term_hierarchy] table. + ->setComputed(TRUE); $fields['changed'] = FieldDefinition::create('integer') ->setLabel(t('Changed')) diff --git a/core/modules/user/lib/Drupal/user/Entity/User.php b/core/modules/user/lib/Drupal/user/Entity/User.php index 44bce77..02a0bce 100644 --- a/core/modules/user/lib/Drupal/user/Entity/User.php +++ b/core/modules/user/lib/Drupal/user/Entity/User.php @@ -513,7 +513,10 @@ public static function baseFieldDefinitions($entity_type) { // https://drupal.org/node/2044859. $fields['roles'] = FieldDefinition::create('string') ->setLabel(t('Roles')) - ->setDescription(t('The roles the user has.')); + ->setDescription(t('The roles the user has.')) + // The roles of a user are not computed from other fields but are stored + // separately in the {users_roles} table. + ->setComputed(TRUE); return $fields; }