diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php b/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php index 6b6d5ff..98fdd69 100644 --- a/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php +++ b/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php @@ -77,13 +77,10 @@ public function __construct($entityType) { * A new entity object. */ public function create(array $values) { - $entity = new $this->entityClass(array(), $this->entityType); + // We have to determine the bundle first. + $bundle = $this->bundleKey ? $values[$this->bundleKey] : FALSE; + $entity = new $this->entityClass(array(), $this->entityType, $bundle); - // Make sure to set the bundle first. - if ($this->bundleKey && !empty($values[$this->bundleKey])) { - $entity->{$this->bundleKey} = $values[$this->bundleKey]; - unset($values[$this->bundleKey]); - } // Set all other given values. foreach ($values as $name => $value) { $entity->$name = $value; @@ -146,11 +143,14 @@ protected function attachLoad(&$queried_entities, $load_revision = FALSE) { protected function mapFromStorageRecords(array $records) { foreach ($records as $id => $record) { + $values = array(); foreach ($record as $name => $value) { - $values[$name][LANGUAGE_DEFAULT][0]['value'] = $value; + // Avoid unnecessary array hierarchies to save memory. + $values[$name][LANGUAGE_DEFAULT] = $value; } - $entity = new $this->entityClass($values, $this->entityType); - $records[$id] = $entity; + $bundle = $this->bundleKey ? $record->{$this->bundleKey} : FALSE; + // Turn the record into an entity class. + $records[$id] = new $this->entityClass($values, $this->entityType, $bundle); } return $records; } diff --git a/core/lib/Drupal/Core/Entity/EntityNG.php b/core/lib/Drupal/Core/Entity/EntityNG.php index 5f0b044..4b9f10f 100644 --- a/core/lib/Drupal/Core/Entity/EntityNG.php +++ b/core/lib/Drupal/Core/Entity/EntityNG.php @@ -26,6 +26,13 @@ class EntityNG extends Entity { /** + * Local cache holding the value of the bundle field. + * + * @var string + */ + protected $bundle = FALSE; + + /** * The plain data values of the contained fields. * * This always holds the original, unchanged values of the entity. The values @@ -57,18 +64,23 @@ class EntityNG extends Entity { protected $bcEntity; /** - * Static cache for property definitions. + * Static cache for field definitions, keyed by entity type and bundle. + * + * @see self::getPropertyDefinitions() * * @var array */ - protected $fieldDefinitions; + static $fieldDefinitions; /** * Overrides Entity::__construct(). */ - public function __construct(array $values, $entity_type) { - parent::__construct(array(), $entity_type); - $this->values = $values + $this->values; + public function __construct(array $values, $entity_type, $bundle = FALSE) { + $this->entityType = $entity_type; + $this->bundle = $bundle ? $bundle : $this->entityType; + foreach ($values as $key => $value) { + $this->values[$key] = $value; + } $this->init(); } @@ -76,6 +88,13 @@ public function __construct(array $values, $entity_type) { * Initialize the object. Invoked upon construction and wake up. */ protected function init() { + if (!isset(static::$fieldDefinitions[$this->entityType][$this->bundle])) { + $definitions = entity_get_controller($this->entityType)->getFieldDefinitions(array( + 'entity type' => $this->entityType, + 'bundle' => $this->bundle, + )); + static::$fieldDefinitions[$this->entityType][$this->bundle] = $definitions; + } // We unset all defined properties, so magic getters apply. unset($this->langcode); } @@ -88,10 +107,17 @@ public function __wakeup() { } /** - * Overrides Entity::id(). + * Implements Drupal\Core\Entity\EntityInterface::id(). */ public function id() { - return $this->get('id')->value; + return $this->id->value; + } + + /** + * Implements Drupal\Core\Entity\EntityInterface::bundle(). + */ + public function bundle() { + return $this->bundle; } /** @@ -170,37 +196,15 @@ public function getIterator() { * Implements ComplexDataInterface::getPropertyDefinition(). */ public function getPropertyDefinition($name) { - // Try to read from static cache. - if (isset($this->fieldDefinitions)) { - return isset($this->fieldDefinitions[$name]) ? $this->fieldDefinitions[$name] : FALSE; - } - - // First try getting property definitions which apply to all entities of - // this type. Then if this fails add in definitions of optional properties - // as well. That way we can use property definitions of base properties - // when determining the optional properties of an entity. - $definitions = entity_get_controller($this->entityType)->getFieldDefinitions(array()); - - if (isset($definitions[$name])) { - return $definitions[$name]; - } - // Add in optional properties if any. - if ($definitions = $this->getPropertyDefinitions()) { - return isset($definitions[$name]) ? $definitions[$name] : FALSE; - } + $definitions = &static::$fieldDefinitions[$this->entityType][$this->bundle]; + return isset($definitions[$name]) ? $definitions[$name] : FALSE; } /** * Implements ComplexDataInterface::getPropertyDefinitions(). */ public function getPropertyDefinitions() { - if (!isset($this->fieldDefinitions)) { - $this->fieldDefinitions = entity_get_controller($this->entityType)->getFieldDefinitions(array( - 'entity type' => $this->entityType, - 'bundle' => $this->bundle(), - )); - } - return $this->fieldDefinitions; + return static::$fieldDefinitions[$this->entityType][$this->bundle]; } /** @@ -366,7 +370,7 @@ public function &__get($name) { return $this->fields[$name][LANGUAGE_DEFAULT]; } if ($this->getPropertyDefinition($name)) { - $return = $this->get($name); + $return = $this->getTranslatedField($name, LANGUAGE_DEFAULT); return $return; } // Allow the EntityBCDecorator to directly access the values and fields. @@ -375,7 +379,7 @@ public function &__get($name) { return $this->$name; } // Else directly read/write plain values. That way, fields not yet converted - // to the entity field API can always be accessed as in compatibility mode. + // to the entity field API can always be directly accessed. if (!isset($this->values[$name])) { $this->values[$name] = NULL; } @@ -395,10 +399,10 @@ public function __set($name, $value) { $this->fields[$name][LANGUAGE_DEFAULT]->setValue($value); } elseif ($this->getPropertyDefinition($name)) { - $this->get($name)->setValue($value); + $this->getTranslatedField($name, LANGUAGE_DEFAULT)->setValue($value); } // Else directly read/write plain values. That way, fields not yet converted - // to the entity field API can always be accessed as in compatibility mode. + // to the entity field API can always be directly accessed. else { $this->values[$name] = $value; } diff --git a/core/lib/Drupal/Core/Entity/Field/Type/BooleanItem.php b/core/lib/Drupal/Core/Entity/Field/Type/BooleanItem.php index af0652a..b6f9df6 100644 --- a/core/lib/Drupal/Core/Entity/Field/Type/BooleanItem.php +++ b/core/lib/Drupal/Core/Entity/Field/Type/BooleanItem.php @@ -21,7 +21,7 @@ class BooleanItem extends FieldItemBase { /** - * Field definitions of the contained properties. + * Definitions of the contained properties. * * @see self::getPropertyDefinitions() * diff --git a/core/lib/Drupal/Core/Entity/Field/Type/DateItem.php b/core/lib/Drupal/Core/Entity/Field/Type/DateItem.php index 5201051..20d7437 100644 --- a/core/lib/Drupal/Core/Entity/Field/Type/DateItem.php +++ b/core/lib/Drupal/Core/Entity/Field/Type/DateItem.php @@ -21,7 +21,7 @@ class DateItem extends FieldItemBase { /** - * Field definitions of the contained properties. + * Definitions of the contained properties. * * @see self::getPropertyDefinitions() * diff --git a/core/lib/Drupal/Core/Entity/Field/Type/EntityReferenceItem.php b/core/lib/Drupal/Core/Entity/Field/Type/EntityReferenceItem.php index 411aad1..b67a6d8 100644 --- a/core/lib/Drupal/Core/Entity/Field/Type/EntityReferenceItem.php +++ b/core/lib/Drupal/Core/Entity/Field/Type/EntityReferenceItem.php @@ -23,7 +23,7 @@ class EntityReferenceItem extends FieldItemBase { /** - * Field definitions of the contained properties. + * Definitions of the contained properties. * * @see self::getPropertyDefinitions() * diff --git a/core/lib/Drupal/Core/Entity/Field/Type/EntityWrapper.php b/core/lib/Drupal/Core/Entity/Field/Type/EntityWrapper.php index 97449e7..6d743d0 100644 --- a/core/lib/Drupal/Core/Entity/Field/Type/EntityWrapper.php +++ b/core/lib/Drupal/Core/Entity/Field/Type/EntityWrapper.php @@ -70,7 +70,7 @@ class EntityWrapper extends TypedData implements IteratorAggregate, ComplexDataI * Implements TypedDataInterface::__construct(). */ public function __construct(array $definition) { - $this->definition = $definition + array('constraints' => array()); + $this->definition = $definition; $this->entityType = isset($this->definition['constraints']['entity type']) ? $this->definition['constraints']['entity type'] : NULL; } diff --git a/core/lib/Drupal/Core/Entity/Field/Type/IntegerItem.php b/core/lib/Drupal/Core/Entity/Field/Type/IntegerItem.php index fc542f1..2ddc4d5 100644 --- a/core/lib/Drupal/Core/Entity/Field/Type/IntegerItem.php +++ b/core/lib/Drupal/Core/Entity/Field/Type/IntegerItem.php @@ -21,7 +21,7 @@ class IntegerItem extends FieldItemBase { /** - * Field definitions of the contained properties. + * Definitions of the contained properties. * * @see self::getPropertyDefinitions() * diff --git a/core/lib/Drupal/Core/Entity/Field/Type/LanguageItem.php b/core/lib/Drupal/Core/Entity/Field/Type/LanguageItem.php index 646718b..1392119 100644 --- a/core/lib/Drupal/Core/Entity/Field/Type/LanguageItem.php +++ b/core/lib/Drupal/Core/Entity/Field/Type/LanguageItem.php @@ -22,9 +22,9 @@ class LanguageItem extends FieldItemBase { /** - * Array of property definitions of contained properties. + * Definitions of the contained properties. * - * @see PropertyEntityReferenceItem::getPropertyDefinitions() + * @see self::getPropertyDefinitions() * * @var array */ diff --git a/core/lib/Drupal/Core/Entity/Field/Type/StringItem.php b/core/lib/Drupal/Core/Entity/Field/Type/StringItem.php index 85fd6d6..bd22984 100644 --- a/core/lib/Drupal/Core/Entity/Field/Type/StringItem.php +++ b/core/lib/Drupal/Core/Entity/Field/Type/StringItem.php @@ -21,7 +21,7 @@ class StringItem extends FieldItemBase { /** - * Field definitions of the contained properties. + * Definitions of the contained properties. * * @see self::getPropertyDefinitions() * diff --git a/core/lib/Drupal/Core/TypedData/TypedDataFactory.php b/core/lib/Drupal/Core/TypedData/TypedDataFactory.php index 3c87148..94b9dac 100644 --- a/core/lib/Drupal/Core/TypedData/TypedDataFactory.php +++ b/core/lib/Drupal/Core/TypedData/TypedDataFactory.php @@ -7,6 +7,7 @@ namespace Drupal\Core\TypedData; +use InvalidArgumentException; use Drupal\Component\Plugin\Factory\DefaultFactory; use Drupal\Component\Plugin\Exception\PluginException; @@ -19,6 +20,13 @@ class TypedDataFactory extends DefaultFactory { /** + * Static cache for definitions to speed things up. + * + * @var array + */ + protected $definitions; + + /** * Implements Drupal\Component\Plugin\Factory\FactoryInterface::createInstance(). * * @param string $plugin_id @@ -29,12 +37,18 @@ class TypedDataFactory extends DefaultFactory { * @return Drupal\Core\TypedData\TypedDataInterface */ public function createInstance($plugin_id, array $configuration) { - $type_definition = $this->discovery->getDefinition($plugin_id); - // Allow per-data definition overrides of the used classes and generally - // default to the data type definition. - $key = empty($configuration['list']) ? 'class' : 'list class'; + if (!isset($this->definitions)) { + $this->definitions = $this->discovery->getDefinitions(); + } + if (!isset($this->definitions[$plugin_id])) { + throw new InvalidArgumentException(format_string('Invalid data type %plugin_id has been given.', array('%plugin_id' => $plugin_id))); + } + + $type_definition = $this->definitions[$plugin_id]; + // Allow per-data definition overrides of the used classes. + $key = empty($configuration['list']) ? 'class' : 'list class'; if (isset($configuration[$key])) { $class = $configuration[$key]; } @@ -45,7 +59,6 @@ public function createInstance($plugin_id, array $configuration) { if (!isset($class)) { throw new PluginException(sprintf('The plugin (%s) did not specify an instance class.', $plugin_id)); } - - return new $class($configuration, $plugin_id, $this->discovery); + return new $class($configuration, $plugin_id); } } diff --git a/core/lib/Drupal/Core/TypedData/TypedDataManager.php b/core/lib/Drupal/Core/TypedData/TypedDataManager.php index a1522d8..d7f4ee1 100644 --- a/core/lib/Drupal/Core/TypedData/TypedDataManager.php +++ b/core/lib/Drupal/Core/TypedData/TypedDataManager.php @@ -94,7 +94,7 @@ public function createInstance($plugin_id, array $configuration) { * @see Drupal\Core\Entity\Field\EntityWrapper */ function create(array $definition, $value = NULL, array $context = array()) { - $wrapper = $this->createInstance($definition['type'], $definition); + $wrapper = $this->factory->createInstance($definition['type'], $definition); if (isset($value)) { $wrapper->setValue($value); } diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index 5ba1050..53be66d 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -1666,7 +1666,7 @@ function template_preprocess_comment(&$variables) { $variables['author'] = theme('username', array('account' => $account)); $variables['created'] = format_date($comment->created->value->getTimestamp()); $variables['changed'] = format_date($comment->changed->value->getTimestamp()); - $variables['new'] = !empty($comment->new->value) ? t('new') : ''; + $variables['new'] = $comment->new->value ? t('new') : ''; $variables['user_picture'] = theme_get_setting('toggle_comment_user_picture') ? theme('user_picture', array('account' => $account)) : ''; if (config('user.settings')->get('signatures') && !empty($account->signature)) { diff --git a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php index 488931e..24b32e0 100644 --- a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php +++ b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php @@ -56,14 +56,13 @@ protected function attachLoad(&$records, $load_revision = FALSE) { * Overrides Drupal\Core\Entity\DatabaseStorageControllerNG::create(). */ public function create(array $values) { - $comment = new $this->entityClass(array(), $this->entityType); - - // Make sure the bundle is set first, so bundle specific values can be set. - if (!empty($values['nid'])) { - $comment->nid = $values['nid']; - $comment->node_type->value = 'comment_node_' . $comment->nid->entity->type; - unset($values['nid']); + // We have to determine the bundle first. + if (empty($values['node_type']) && !empty($values['nid'])) { + $node = node_load($values['nid']); + $values['node_type'] = 'comment_node_' . $node->type; } + $comment = new $this->entityClass(array(), $this->entityType, $values['node_type']); + // Set all other given values. foreach ($values as $name => $value) { $comment->$name = $value; diff --git a/core/modules/comment/lib/Drupal/comment/FieldNewValue.php b/core/modules/comment/lib/Drupal/comment/FieldNewValue.php index eb22ba0..5afd132 100644 --- a/core/modules/comment/lib/Drupal/comment/FieldNewValue.php +++ b/core/modules/comment/lib/Drupal/comment/FieldNewValue.php @@ -68,13 +68,15 @@ public function setParent($parent) { * Implements TypedDataInterface::getValue(). */ public function getValue($langcode = NULL) { - - if (!isset($this->parent)) { - throw new InvalidArgumentException('Computed properties require context for computation.'); + if (!isset($this->value)) { + if (!isset($this->parent)) { + throw new InvalidArgumentException('Computed properties require context for computation.'); + } + $field = $this->parent->getParent(); + $entity = $field->getParent(); + $this->value = node_mark($entity->nid->value, $entity->changed->value->getTimestamp()); } - $field = $this->parent->getParent(); - $entity = $field->getParent(); - return node_mark($entity->nid->value, $entity->changed->value->getTimestamp()); + return $this->value; } /** diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/Core/Entity/Comment.php b/core/modules/comment/lib/Drupal/comment/Plugin/Core/Entity/Comment.php index cc13922..7530ed0 100644 --- a/core/modules/comment/lib/Drupal/comment/Plugin/Core/Entity/Comment.php +++ b/core/modules/comment/lib/Drupal/comment/Plugin/Core/Entity/Comment.php @@ -218,11 +218,4 @@ protected function init() { public function id() { return $this->get('cid')->value; } - - /** - * Implements Drupal\Core\Entity\EntityInterface::bundle(). - */ - public function bundle() { - return $this->get('node_type')->value; - } } diff --git a/core/modules/field/modules/text/lib/Drupal/text/Type/TextItem.php b/core/modules/field/modules/text/lib/Drupal/text/Type/TextItem.php index 98b6bb6..e44fc1d 100644 --- a/core/modules/field/modules/text/lib/Drupal/text/Type/TextItem.php +++ b/core/modules/field/modules/text/lib/Drupal/text/Type/TextItem.php @@ -21,7 +21,7 @@ class TextItem extends FieldItemBase { /** - * Field definitions of the contained properties. + * Definitions of the contained properties. * * @see self::getPropertyDefinitions() * diff --git a/core/modules/field/modules/text/lib/Drupal/text/Type/TextSummaryItem.php b/core/modules/field/modules/text/lib/Drupal/text/Type/TextSummaryItem.php index eb563ce..06f3be1 100644 --- a/core/modules/field/modules/text/lib/Drupal/text/Type/TextSummaryItem.php +++ b/core/modules/field/modules/text/lib/Drupal/text/Type/TextSummaryItem.php @@ -19,7 +19,7 @@ class TextSummaryItem extends TextItem { /** - * Field definitions of the contained properties. + * Definitions of the contained properties. * * @see self::getPropertyDefinitions() *