diff --git a/core/lib/Drupal/Core/Entity/FieldableEntityStorageControllerBase.php b/core/lib/Drupal/Core/Entity/FieldableEntityStorageControllerBase.php index 87b86c0..a977241 100644 --- a/core/lib/Drupal/Core/Entity/FieldableEntityStorageControllerBase.php +++ b/core/lib/Drupal/Core/Entity/FieldableEntityStorageControllerBase.php @@ -89,8 +89,24 @@ protected function loadFieldItems(array $entities, $age) { $instances = field_info_instances($this->entityType, $entity->bundle()); foreach ($entity->getTranslationLanguages() as $langcode => $language) { $translation = $entity->getTranslation($langcode); - foreach ($instances as $instance) { - $data[$langcode][$instance['field_name']] = $translation->{$instance['field_name']}->getValue(); + foreach ($instances as $field_name => $instance) { + $items = $translation->$field_name; + + // First collect all non-computed properties. + $field_data = $items->getValue(); + + // Then individually collect cacheable computed properties. All + // items have the same properties, so we optimize by iterating on + // the properties of the first item. + foreach ($items->offsetGet(0)->getPropertyDefinitions() as $property => $definition) { + if (!empty($definition['computed']) && !empty($definition['cache'])) { + foreach ($items as $delta => $item) { + $field_data[$delta][$property] = $item->$property; + } + } + } + + $data[$langcode][$field_name] = $field_data; } } $cid = "field:{$this->entityType}:$id"; diff --git a/core/lib/Drupal/Core/TypedData/TypedDataManager.php b/core/lib/Drupal/Core/TypedData/TypedDataManager.php index bbc0d7f..7dda25d 100644 --- a/core/lib/Drupal/Core/TypedData/TypedDataManager.php +++ b/core/lib/Drupal/Core/TypedData/TypedDataManager.php @@ -103,7 +103,11 @@ public function createInstance($plugin_id, array $configuration, $name = NULL, $ * - list: Whether the data is multi-valued, i.e. a list of data items. * Defaults to FALSE. * - computed: A boolean specifying whether the data value is computed by - * the object, e.g. depending on some other values. + * the object, e.g. depending on some other values. Defaults to FALSE. + * - cache: (only supported for FieldItem objects) A boolean specifying + * whether the value should be cached as part of the field values cache. + * This only applies to computed properties since the field cache always + * includes non-computed properties. Defaults to FALSE. * - read-only: A boolean specifying whether the data is read-only. Defaults * to TRUE for computed properties, to FALSE otherwise. * - class: If set and 'list' is FALSE, the class to use for creating the diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItemBase.php b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItemBase.php index 54630fd..06e7153 100644 --- a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItemBase.php +++ b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextItemBase.php @@ -40,6 +40,7 @@ public function getPropertyDefinitions() { 'label' => t('Processed text'), 'description' => t('The text value with the text format applied.'), 'computed' => TRUE, + 'cache' => TRUE, 'class' => '\Drupal\text\TextProcessed', 'settings' => array( 'text source' => 'value', diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextWithSummaryItem.php b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextWithSummaryItem.php index 8d5c9fb..f06dea0 100644 --- a/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextWithSummaryItem.php +++ b/core/modules/text/lib/Drupal/text/Plugin/field/field_type/TextWithSummaryItem.php @@ -51,6 +51,7 @@ public function getPropertyDefinitions() { 'label' => t('Processed summary text'), 'description' => t('The summary text value with the text format applied.'), 'computed' => TRUE, + 'cache' => TRUE, 'class' => '\Drupal\text\TextProcessed', 'settings' => array( 'text source' => 'summary', diff --git a/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php b/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php index ef9a7df..1899524 100644 --- a/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php +++ b/core/modules/text/lib/Drupal/text/Tests/TextWithSummaryItemTest.php @@ -119,26 +119,26 @@ function testProcessedCache() { $entity->name->value = $this->randomName(); $entity->save(); - // Inject values into the cache to make sure that these are used as-is and - // not re-calculated. - $data = array( + // Check that the processed values are correctly computed. + $this->assertEqual($entity->summary_field->processed, $value); + $this->assertEqual($entity->summary_field->summary_processed, $summary); + + // Load the entity and check that the expected cached data was set. + $entity = entity_load($entity_type, $entity->id()); + $cache = cache('field')->get("field:$entity_type:" . $entity->id()); + $this->assertEqual($cache->data, array( Language::LANGCODE_DEFAULT => array( 'summary_field' => array( 0 => array( 'value' => $value, 'summary' => $summary, 'format' => 'plain_text', - 'processed' => 'Cached processed value', - 'summary_processed' => 'Cached summary processed value', + 'processed' => $value, + 'summary_processed' => $summary, ), ), ), - ); - cache('field')->set("field:$entity_type:" . $entity->id(), $data); - - $entity = entity_load($entity_type, $entity->id()); - $this->assertEqual($entity->summary_field->processed, 'Cached processed value'); - $this->assertEqual($entity->summary_field->summary_processed, 'Cached summary processed value'); + )); // Change the format, this should update the processed properties. $entity->summary_field->format = 'no_filters';