diff --git a/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php b/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php index 5497efb..370dea6 100644 --- a/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php +++ b/core/lib/Drupal/Core/Entity/FieldableDatabaseStorageController.php @@ -281,11 +281,21 @@ protected function mapFromStorageRecords(array $records, $load_revision = FALSE) $entities = array(); foreach ($records as $id => $record) { $entities[$id] = array(); + // Skip the item delta and item value levels but let the field assign + // the value as suiting. This avoids unnecessary array hierarchies and + // saves memory here. foreach ($record as $name => $value) { - // Skip the item delta and item value levels but let the field assign - // the value as suiting. This avoids unnecessary array hierarchies and - // saves memory here. - $entities[$id][$name][Language::LANGCODE_DEFAULT] = $value; + // Handle columns named [field_name]__[column_name] (e.g for field types + // that store several properties). + if ($field = strstr($name, '__', TRUE)) { + $property_name = substr($name, strpos($name, '__') + 2); + $entities[$id][$field][Language::LANGCODE_DEFAULT][$property_name] = $value; + } + else { + // Handle columns named directly after the field (e.g if the field + // type only stores one property). + $entities[$id][$name][Language::LANGCODE_DEFAULT] = $value; + } } // If we have no multilingual values we can instantiate entity objecs // right now, otherwise we need to collect all the field values first. @@ -332,13 +342,13 @@ protected function attachPropertyData(array &$entities, $revision_id = FALSE) { } $data = $query->execute(); - $field_definition = \Drupal::entityManager()->getFieldDefinitions($this->entityType); + $field_definitions = \Drupal::entityManager()->getFieldDefinitions($this->entityType); $translations = array(); if ($this->revisionDataTable) { - $data_fields = array_flip(array_diff(drupal_schema_fields_sql($this->entityInfo['revision_data_table']), drupal_schema_fields_sql($this->entityInfo['base_table']))); + $data_column_names = array_flip(array_diff(drupal_schema_fields_sql($this->entityInfo['revision_data_table']), drupal_schema_fields_sql($this->entityInfo['base_table']))); } else { - $data_fields = array_flip(drupal_schema_fields_sql($this->entityInfo['data_table'])); + $data_column_names = array_flip(drupal_schema_fields_sql($this->entityInfo['data_table'])); } foreach ($data as $values) { @@ -349,9 +359,21 @@ protected function attachPropertyData(array &$entities, $revision_id = FALSE) { $langcode = empty($values['default_langcode']) ? $values['langcode'] : Language::LANGCODE_DEFAULT; $translations[$id][$langcode] = TRUE; - foreach ($field_definition as $name => $definition) { - if (isset($data_fields[$name])) { - $entities[$id][$name][$langcode] = $values[$name]; + foreach (array_keys($field_definitions) as $field_name) { + // Handle columns named directly after the field. + if (isset($data_column_names[$field_name])) { + $entities[$id][$field_name][$langcode] = $values[$field_name]; + } + else { + foreach ($data_column_names as $data_column_name) { + // Handle columns named [field_name]__[column_name], for which we + // need to look through all column names from the table that start + // with the name of the field. + if (($field = strstr($data_column_name, '__', TRUE)) && $field === $field_name) { + $property_name = substr($data_column_name, strpos($data_column_name, '__') + 2); + $entities[$id][$field_name][$langcode][$property_name] = $values[$data_column_name]; + } + } } } } @@ -744,17 +766,41 @@ protected function savePropertyData(EntityInterface $entity, $table_key = 'data_ */ protected function mapToStorageRecord(EntityInterface $entity, $table_key = 'base_table') { $record = new \stdClass(); + $values = array(); $definitions = $entity->getPropertyDefinitions(); $schema = drupal_get_schema($this->entityInfo[$table_key]); $is_new = $entity->isNew(); + $multi_column_fields = array(); foreach (drupal_schema_fields_sql($this->entityInfo[$table_key]) as $name) { - $info = $schema['fields'][$name]; - $value = isset($definitions[$name]) && isset($entity->$name->value) ? $entity->$name->value : NULL; + // Check for fields which store data in multiple columns and process them + // separately. + if ($field = strstr($name, '__', TRUE)) { + $multi_column_fields[$field] = TRUE; + continue; + } + $values[$name] = isset($definitions[$name]) && isset($entity->$name->value) ? $entity->$name->value : NULL; + } + + // Handle fields that store multiple properties and match each property name + // to its schema column name. + foreach (array_keys($multi_column_fields) as $field_name) { + $field_items = $entity->get($field_name); + $field_value = $field_items->getValue(); + // @todo Reconsider the usage of getFieldPropertyNames() after + // https://drupal.org/node/2144327. + foreach ($field_items->getFieldDefinition()->getFieldPropertyNames() as $property_name) { + if (isset($schema['fields'][$field_name . '__' . $property_name])) { + $values[$field_name . '__' . $property_name] = isset($field_value[0][$property_name]) ? $field_value[0][$property_name] : NULL; + } + } + } + + foreach ($values as $field_name => $value) { // If we are creating a new entity, we must not populate the record with // NULL values otherwise defaults would not be applied. if (isset($value) || !$is_new) { - $record->$name = drupal_schema_get_field_value($info, $value); + $record->$field_name = drupal_schema_get_field_value($schema['fields'][$field_name], $value); } } diff --git a/core/lib/Drupal/Core/Field/FieldDefinition.php b/core/lib/Drupal/Core/Field/FieldDefinition.php index 8e57f7c..eecb75b 100644 --- a/core/lib/Drupal/Core/Field/FieldDefinition.php +++ b/core/lib/Drupal/Core/Field/FieldDefinition.php @@ -107,7 +107,7 @@ public function getFieldSetting($setting_name) { * {@inheritdoc} */ public function getFieldPropertyNames() { - return array_keys(\Drupal::typedData()->create($this->definition['type'])->getPropertyDefinitions()); + return array_keys(\Drupal::typedData()->create($this->definition)->getPropertyDefinitions()); } /** diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceItemTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceItemTest.php index a638245..879c02b 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceItemTest.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceItemTest.php @@ -22,7 +22,7 @@ class EntityReferenceItemTest extends FieldUnitTestBase { * * @var array */ - public static $modules = array('entity_reference', 'taxonomy', 'options'); + public static $modules = array('entity_reference', 'taxonomy', 'options', 'text', 'filter'); /** * The taxonomy vocabulary to test with. diff --git a/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php b/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php index 8e7bbb4..caa03e1 100644 --- a/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php +++ b/core/modules/forum/lib/Drupal/forum/Tests/ForumTest.php @@ -387,7 +387,7 @@ function createForum($type, $parent = 0) { ); // Verify forum. - $term = db_query("SELECT * FROM {taxonomy_term_data} t WHERE t.vid = :vid AND t.name = :name AND t.description = :desc", array(':vid' => \Drupal::config('forum.settings')->get('vocabulary'), ':name' => $name, ':desc' => $description))->fetchAssoc(); + $term = db_query("SELECT * FROM {taxonomy_term_data} t WHERE t.vid = :vid AND t.name = :name AND t.description__value = :desc", array(':vid' => \Drupal::config('forum.settings')->get('vocabulary'), ':name' => $name, ':desc' => $description))->fetchAssoc(); $this->assertTrue(!empty($term), 'The ' . $type . ' exists in the database'); // Verify forum hierarchy. diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php index a091d1a..320bec0 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php @@ -230,13 +230,7 @@ public static function baseFieldDefinitions($entity_type) { $properties['description'] = array( 'label' => t('Description'), 'description' => t('A description of the term'), - 'type' => 'string_field', - ); - // @todo Combine with description. - $properties['format'] = array( - 'label' => t('Description format'), - 'description' => t('The filter format ID of the description.'), - 'type' => 'string_field', + 'type' => 'field_item:text_long', ); $properties['weight'] = array( 'label' => t('Weight'), diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php index e7fb41e..bbed7fd 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php @@ -74,7 +74,7 @@ public function form(array $form, array &$form_state) { '#type' => 'text_format', '#title' => $this->t('Description'), '#default_value' => $term->description->value, - '#format' => $term->format->value, + '#format' => $term->description->format, '#weight' => 0, ); $language_configuration = $this->moduleHandler->moduleExists('language') ? language_get_default_configuration('taxonomy_term', $vocabulary->id()) : FALSE; @@ -178,7 +178,7 @@ public function buildEntity(array $form, array &$form_state) { // \Drupal\Core\Entity\Entity::save() method. $description = $form_state['values']['description']; $term->description->value = $description['value']; - $term->format->value = $description['format']; + $term->description->format = $description['format']; // Assign parents with proper delta values starting from 0. $term->parent = array_keys($form_state['values']['parent']); diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermViewBuilder.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermViewBuilder.php index b33dbfd..2497dd6 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermViewBuilder.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermViewBuilder.php @@ -27,7 +27,7 @@ public function buildContent(array $entities, array $displays, $view_mode, $lang $display = $displays[$entity->bundle()]; if (!empty($entity->description->value) && $display->getComponent('description')) { $entity->content['description'] = array( - '#markup' => check_markup($entity->description->value, $entity->format->value, '', TRUE), + '#markup' => check_markup($entity->description->value, $entity->description->format, '', TRUE), '#prefix' => '