diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 906a7c1..d7cdccf 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -2773,7 +2773,8 @@ function language_list($flags = LANGUAGE_CONFIGURABLE) { $default = language_default(); if (language_multilingual() || module_exists('language')) { // Use language module configuration if available. - $languages = db_query('SELECT * FROM {language} ORDER BY weight ASC, name ASC')->fetchAllAssoc('langcode', PDO::FETCH_ASSOC); + $languages = entity_load_multiple('language'); + uasort($languages, 'Drupal\Core\Entity\ConfigEntityBase::language'); // Initialize default property so callers have an easy reference and can // save the same object without data loss. diff --git a/core/includes/common.inc b/core/includes/common.inc index c9913a2..37896ec 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -2099,9 +2099,9 @@ function _format_date_callback(array $matches = NULL, $new_langcode = NULL) { * Defaults to empty string when clean URLs are in effect, and to * 'index.php/' when they are not. * - 'entity_type': The entity type of the object that called url(). Only - * set if url() is invoked by Drupal\entity\Entity::uri(). + * set if url() is invoked by Drupal\Core\Entity\Entity::uri(). * - 'entity': The entity object (such as a node) for which the URL is being - * generated. Only set if url() is invoked by Drupal\entity\Entity::uri(). + * generated. Only set if url() is invoked by Drupal\Core\Entity\Entity::uri(). * * @return * A string containing a URL to the given path. diff --git a/core/lib/Drupal/Core/Entity/ConfigEntityBase.php b/core/lib/Drupal/Core/Entity/ConfigEntityBase.php new file mode 100644 index 0000000..62f0103 --- /dev/null +++ b/core/lib/Drupal/Core/Entity/ConfigEntityBase.php @@ -0,0 +1,102 @@ +id()) { + $this->originalID = $original_id; + } + } + + /** + * Implements ConfigEntityInterface::getOriginalID(). + */ + public function getOriginalID() { + return $this->originalID; + } + + /** + * Overrides Entity::isNew(). + * + * EntityInterface::enforceIsNew() is not supported by configuration entities, + * since each configuration entity is unique. + */ + final public function isNew() { + return !$this->id(); + } + + /** + * Overrides Entity::bundle(). + * + * EntityInterface::bundle() is not supported by configuration entities, since + * a configuration entity is a bundle. + */ + final public function bundle() { + return $this->entityType; + } + + /** + * Overrides Entity::get(). + * + * EntityInterface::get() implements support for fieldable entities, but + * configuration entities are not fieldable. + */ + public function get($property_name, $langcode = NULL) { + // @todo: Add support for translatable properties being not fields. + return isset($this->{$property_name}) ? $this->{$property_name} : NULL; + } + + /** + * Overrides Entity::set(). + * + * EntityInterface::set() implements support for fieldable entities, but + * configuration entities are not fieldable. + */ + public function set($property_name, $value, $langcode = NULL) { + // @todo: Add support for translatable properties being not fields. + $this->{$property_name} = $value; + } + + /** + * Helper callback for uasort() to sort configuration entities by weight and label. + */ + public static function sort($a, $b) { + $a_weight = isset($a->weight) ? $a->weight : 0; + $b_weight = isset($b->weight) ? $b->weight : 0; + if ($a_weight == $b_weight) { + $a_label = $a->label(); + $b_label = $b->label(); + return strnatcasecmp($a_label, $b_label); + } + return ($a_weight < $b_weight) ? -1 : 1; + } +} diff --git a/core/lib/Drupal/Core/Entity/ConfigEntityInterface.php b/core/lib/Drupal/Core/Entity/ConfigEntityInterface.php new file mode 100644 index 0000000..0a9a833 --- /dev/null +++ b/core/lib/Drupal/Core/Entity/ConfigEntityInterface.php @@ -0,0 +1,25 @@ +entityType = $entityType; + $this->entityInfo = entity_get_info($entityType); + $this->hookLoadArguments = array(); + $this->idKey = $this->entityInfo['entity keys']['id']; + } + + /** + * Implements Drupal\Core\Entity\EntityStorageControllerInterface::resetCache(). + */ + public function resetCache(array $ids = NULL) { + // The configuration system is fast enough and/or implements its own + // (advanced) caching mechanism already. + } + + /** + * Implements Drupal\Core\Entity\EntityStorageControllerInterface::load(). + */ + public function load(array $ids = NULL) { + $entities = array(); + + // Create a new variable which is either a prepared version of the $ids + // array for later comparison with the entity cache, or FALSE if no $ids + // were passed. + $passed_ids = !empty($ids) ? array_flip($ids) : FALSE; + + // Load any remaining entities. This is the case if $ids is set to NULL (so + // we load all entities). + if ($ids === NULL || $ids) { + $queried_entities = $this->buildQuery($ids); + } + + // Pass all entities loaded from the database through $this->attachLoad(), + // which calls the + // entity type specific load callback, for example hook_node_type_load(). + if (!empty($queried_entities)) { + $this->attachLoad($queried_entities); + $entities += $queried_entities; + } + + // Ensure that the returned array is ordered the same as the original + // $ids array if this was passed in and remove any invalid ids. + if ($passed_ids) { + // Remove any invalid ids from the array. + $passed_ids = array_intersect_key($passed_ids, $entities); + foreach ($entities as $entity) { + $passed_ids[$entity->{$this->idKey}] = $entity; + } + $entities = $passed_ids; + } + + return $entities; + } + + /** + * Implements Drupal\Core\Entity\EntityStorageControllerInterface::loadRevision(). + */ + public function loadRevision($revision_id) { + return FALSE; + } + + /** + * Implements Drupal\Core\Entity\EntityStorageControllerInterface::loadByProperties(). + */ + public function loadByProperties(array $values = array()) { + return array(); + } + + /** + * Builds the query to load the entity. + * + * This has full revision support. For entities requiring special queries, + * the class can be extended, and the default query can be constructed by + * calling parent::buildQuery(). This is usually necessary when the object + * being loaded needs to be augmented with additional data from another + * table, such as loading node type into comments or vocabulary machine name + * into terms, however it can also support $conditions on different tables. + * See Drupal\comment\CommentStorageController::buildQuery() or + * Drupal\taxonomy\TermStorageController::buildQuery() for examples. + * + * @param $ids + * An array of entity IDs, or NULL to load all entities. + * @param $revision_id + * The ID of the revision to load, or FALSE if this query is asking for the + * most current revision(s). + * + * @return SelectQuery + * A SelectQuery object for loading the entity. + */ + protected function buildQuery($ids, $revision_id = FALSE) { + $config_class = $this->entityInfo['entity class']; + $prefix = $this->entityInfo['config prefix'] . '.'; + + // Load all of the configuration entities. + if ($ids === NULL) { + $names = drupal_container()->get('config.storage')->listAll($prefix); + $result = array(); + foreach ($names as $name) { + $config = config($name); + $result[$config->get($this->idKey)] = new $config_class($config->get(), $this->entityType); + } + return $result; + } + else { + $result = array(); + foreach ($ids as $id) { + // Add the prefix to the ID to serve as the configuration object name. + $config = config($prefix . $id); + if (!$config->isNew()) { + $result[$id] = new $config_class($config->get(), $this->entityType); + } + } + return $result; + } + } + + /** + * Attaches data to entities upon loading. + * + * This will attach fields, if the entity is fieldable. It calls + * hook_entity_load() for modules which need to add data to all entities. + * It also calls hook_TYPE_load() on the loaded entities. For example + * hook_node_load() or hook_user_load(). If your hook_TYPE_load() + * expects special parameters apart from the queried entities, you can set + * $this->hookLoadArguments prior to calling the method. + * See Drupal\node\NodeStorageController::attachLoad() for an example. + * + * @param $queried_entities + * Associative array of query results, keyed on the entity ID. + * @param $revision_id + * ID of the revision that was loaded, or FALSE if the most current revision + * was loaded. + */ + protected function attachLoad(&$queried_entities, $revision_id = FALSE) { + // Call hook_entity_load(). + foreach (module_implements('entity_load') as $module) { + $function = $module . '_entity_load'; + $function($queried_entities, $this->entityType); + } + // Call hook_TYPE_load(). The first argument for hook_TYPE_load() are + // always the queried entities, followed by additional arguments set in + // $this->hookLoadArguments. + $args = array_merge(array($queried_entities), $this->hookLoadArguments); + foreach (module_implements($this->entityType . '_load') as $module) { + call_user_func_array($module . '_' . $this->entityType . '_load', $args); + } + } + + /** + * Implements Drupal\Core\Entity\EntityStorageControllerInterface::create(). + */ + public function create(array $values) { + $class = isset($this->entityInfo['entity class']) ? $this->entityInfo['entity class'] : 'Drupal\Core\Entity\Entity'; + + $entity = new $class($values, $this->entityType); + + // Assign a new UUID if there is none yet. + if (!isset($entity->{$this->uuidKey})) { + $uuid = new Uuid(); + $entity->{$this->uuidKey} = $uuid->generate(); + } + + return $entity; + } + + /** + * Implements Drupal\Core\Entity\EntityStorageControllerInterface::delete(). + */ + public function delete($ids) { + $entities = $ids ? $this->load($ids) : FALSE; + if (!$entities) { + // If no IDs or invalid IDs were passed, do nothing. + return; + } + + $this->preDelete($entities); + foreach ($entities as $id => $entity) { + $this->invokeHook('predelete', $entity); + } + + foreach ($entities as $id => $entity) { + $config = config($this->entityInfo['config prefix'] . '.' . $entity->id()); + $config->delete(); + } + + $this->postDelete($entities); + foreach ($entities as $id => $entity) { + $this->invokeHook('delete', $entity); + } + } + + /** + * Implements Drupal\Core\Entity\EntityStorageControllerInterface::save(). + */ + public function save(EntityInterface $entity) { + $prefix = $this->entityInfo['config prefix'] . '.'; + + // Load the stored entity, if any. + if ($entity->getOriginalID()) { + $id = $entity->getOriginalID(); + } + else { + $id = $entity->id(); + } + $config = config($prefix . $id); + $config->setName($prefix . $entity->id()); + + if (!$config->isNew() && !isset($entity->original)) { + $entity->original = entity_load_unchanged($this->entityType, $id); + } + + $this->preSave($entity); + $this->invokeHook('presave', $entity); + + // Configuration objects do not have a schema. Extract all key names from + // class properties. + $class_info = new \ReflectionClass($entity); + $properties = $class_info->getProperties(\ReflectionProperty::IS_PUBLIC); + foreach ($properties as $property) { + $name = $property->getName(); + $config->set($name, $entity->$name); + } + + if (!$config->isNew()) { + $return = SAVED_NEW; + $config->save(); + $this->postSave($entity, TRUE); + $this->invokeHook('update', $entity); + } + else { + $return = SAVED_UPDATED; + $config->save(); + $entity->enforceIsNew(FALSE); + $this->postSave($entity, FALSE); + $this->invokeHook('insert', $entity); + } + + unset($entity->original); + + return $return; + } + + /** + * Acts on an entity before the presave hook is invoked. + * + * Used before the entity is saved and before invoking the presave hook. + */ + protected function preSave(EntityInterface $entity) { + } + + /** + * Acts on a saved entity before the insert or update hook is invoked. + * + * Used after the entity is saved, but before invoking the insert or update + * hook. + * + * @param $update + * (bool) TRUE if the entity has been updated, or FALSE if it has been + * inserted. + */ + protected function postSave(EntityInterface $entity, $update) { + // Delete the original configuration entity, in case the entity ID was + // renamed. + if ($update && !empty($entity->original) && $entity->{$this->idKey} !== $entity->original->{$this->idKey}) { + // @todo This should just delete the original config object without going + // through the API, no? + $entity->original->delete(); + } + } + + /** + * Acts on entities before they are deleted. + * + * Used before the entities are deleted and before invoking the delete hook. + */ + protected function preDelete($entities) { + } + + /** + * Acts on deleted entities before the delete hook is invoked. + * + * Used after the entities are deleted but before invoking the delete hook. + */ + protected function postDelete($entities) { + } + + /** + * Invokes a hook on behalf of the entity. + * + * @param $hook + * One of 'presave', 'insert', 'update', 'predelete', or 'delete'. + * @param $entity + * The entity object. + */ + protected function invokeHook($hook, EntityInterface $entity) { + // Invoke the hook. + module_invoke_all($this->entityType . '_' . $hook, $entity); + // Invoke the respective entity-level hook. + module_invoke_all('entity_' . $hook, $entity, $this->entityType); + } +} diff --git a/core/lib/Drupal/Core/Entity/ContentEntityInterface.php b/core/lib/Drupal/Core/Entity/ContentEntityInterface.php new file mode 100644 index 0000000..33ecdae --- /dev/null +++ b/core/lib/Drupal/Core/Entity/ContentEntityInterface.php @@ -0,0 +1,15 @@ +entityType = $entityType; + $this->entityInfo = entity_get_info($entityType); + $this->entityCache = array(); + $this->hookLoadArguments = array(); + $this->idKey = $this->entityInfo['entity keys']['id']; + + // Check if the entity type supports UUIDs. + if (!empty($this->entityInfo['entity keys']['uuid'])) { + $this->uuidKey = $this->entityInfo['entity keys']['uuid']; + } + else { + $this->uuidKey = FALSE; + } + + // Check if the entity type supports revisions. + if (!empty($this->entityInfo['entity keys']['revision'])) { + $this->revisionKey = $this->entityInfo['entity keys']['revision']; + $this->revisionTable = $this->entityInfo['revision table']; + } + else { + $this->revisionKey = FALSE; + } + + // Check if the entity type supports static caching of loaded entities. + $this->cache = !empty($this->entityInfo['static cache']); + } + + /** + * Implements Drupal\Core\Entity\EntityStorageControllerInterface::resetCache(). + */ + public function resetCache(array $ids = NULL) { + if (isset($ids)) { + foreach ($ids as $id) { + unset($this->entityCache[$id]); + } + } + else { + $this->entityCache = array(); + } + } + + /** + * Implements Drupal\Core\Entity\EntityStorageControllerInterface::load(). + */ + public function load(array $ids = NULL) { + $entities = array(); + + // Create a new variable which is either a prepared version of the $ids + // array for later comparison with the entity cache, or FALSE if no $ids + // were passed. The $ids array is reduced as items are loaded from cache, + // and we need to know if it's empty for this reason to avoid querying the + // database when all requested entities are loaded from cache. + $passed_ids = !empty($ids) ? array_flip($ids) : FALSE; + // Try to load entities from the static cache, if the entity type supports + // static caching. + if ($this->cache && $ids) { + $entities += $this->cacheGet($ids); + // If any entities were loaded, remove them from the ids still to load. + if ($passed_ids) { + $ids = array_keys(array_diff_key($passed_ids, $entities)); + } + } + + // Load any remaining entities from the database. This is the case if $ids + // is set to NULL (so we load all entities) or if there are any ids left to + // load. + if ($ids === NULL || $ids) { + // Build and execute the query. + $query_result = $this->buildQuery($ids)->execute(); + + if (!empty($this->entityInfo['entity class'])) { + // We provide the necessary arguments for PDO to create objects of the + // specified entity class. + // @see Drupal\Core\Entity\EntityInterface::__construct() + $query_result->setFetchMode(PDO::FETCH_CLASS, $this->entityInfo['entity class'], array(array(), $this->entityType)); + } + $queried_entities = $query_result->fetchAllAssoc($this->idKey); + } + + // Pass all entities loaded from the database through $this->attachLoad(), + // 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); + $entities += $queried_entities; + } + + if ($this->cache) { + // Add entities to the cache. + if (!empty($queried_entities)) { + $this->cacheSet($queried_entities); + } + } + + // Ensure that the returned array is ordered the same as the original + // $ids array if this was passed in and remove any invalid ids. + if ($passed_ids) { + // Remove any invalid ids from the array. + $passed_ids = array_intersect_key($passed_ids, $entities); + foreach ($entities as $entity) { + $passed_ids[$entity->{$this->idKey}] = $entity; + } + $entities = $passed_ids; + } + + return $entities; + } + + /** + * Implements Drupal\Core\Entity\EntityStorageControllerInterface::loadRevision(). + */ + public function loadRevision($revision_id) { + // Build and execute the query. + $query_result = $this->buildQuery(array(), $revision_id)->execute(); + + if (!empty($this->entityInfo['entity class'])) { + // We provide the necessary arguments for PDO to create objects of the + // specified entity class. + // @see Drupal\Core\Entity\EntityInterface::__construct() + $query_result->setFetchMode(PDO::FETCH_CLASS, $this->entityInfo['entity class'], array(array(), $this->entityType)); + } + $queried_entities = $query_result->fetchAllAssoc($this->idKey); + + // Pass the loaded entities from the database through $this->attachLoad(), + // 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); + } + return reset($queried_entities); + } + + /** + * Implements Drupal\Core\Entity\EntityStorageControllerInterface::loadByProperties(). + */ + public function loadByProperties(array $values = array()) { + // Build a query to fetch the entity IDs. + $entity_query = new EntityFieldQuery(); + $entity_query->entityCondition('entity_type', $this->entityType); + $this->buildPropertyQuery($entity_query, $values); + $result = $entity_query->execute(); + + if (empty($result[$this->entityType])) { + return array(); + } + // Load and return the found entities. + return $this->load(array_keys($result[$this->entityType])); + } + + /** + * Builds an entity query. + * + * @param Drupal\Core\Entity\EntityFieldQuery $entity_query + * EntityFieldQuery instance. + * @param array $values + * An associative array of properties of the entity, where the keys are the + * property names and the values are the values those properties must have. + */ + protected function buildPropertyQuery(EntityFieldQuery $entity_query, array $values) { + foreach ($values as $name => $value) { + $entity_query->propertyCondition($name, $value); + } + } + + /** + * Builds the query to load the entity. + * + * This has full revision support. For entities requiring special queries, + * the class can be extended, and the default query can be constructed by + * calling parent::buildQuery(). This is usually necessary when the object + * being loaded needs to be augmented with additional data from another + * table, such as loading node type into comments or vocabulary machine name + * into terms, however it can also support $conditions on different tables. + * See Drupal\comment\CommentStorageController::buildQuery() or + * Drupal\taxonomy\TermStorageController::buildQuery() for examples. + * + * @param array|null $ids + * An array of entity IDs, or NULL to load all entities. + * @param $revision_id + * The ID of the revision to load, or FALSE if this query is asking for the + * most current revision(s). + * + * @return SelectQuery + * A SelectQuery object for loading the entity. + */ + protected function buildQuery($ids, $revision_id = FALSE) { + $query = db_select($this->entityInfo['base table'], 'base'); + + $query->addTag($this->entityType . '_load_multiple'); + + 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) { + // 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; + } + + /** + * Attaches data to entities upon loading. + * + * This will attach fields, if the entity is fieldable. It calls + * hook_entity_load() for modules which need to add data to all entities. + * It also calls hook_TYPE_load() on the loaded entities. For example + * hook_node_load() or hook_user_load(). If your hook_TYPE_load() + * expects special parameters apart from the queried entities, you can set + * $this->hookLoadArguments prior to calling the method. + * See Drupal\node\NodeStorageController::attachLoad() for an example. + * + * @param $queried_entities + * Associative array of query results, keyed on the entity ID. + * @param $load_revision + * (optional) TRUE if the revision should be loaded, defaults to FALSE. + */ + protected function attachLoad(&$queried_entities, $load_revision = FALSE) { + // Attach fields. + if ($this->entityInfo['fieldable']) { + if ($load_revision) { + field_attach_load_revision($this->entityType, $queried_entities); + } + else { + field_attach_load($this->entityType, $queried_entities); + } + } + + // Call hook_entity_load(). + foreach (module_implements('entity_load') as $module) { + $function = $module . '_entity_load'; + $function($queried_entities, $this->entityType); + } + // Call hook_TYPE_load(). The first argument for hook_TYPE_load() are + // always the queried entities, followed by additional arguments set in + // $this->hookLoadArguments. + $args = array_merge(array($queried_entities), $this->hookLoadArguments); + foreach (module_implements($this->entityType . '_load') as $module) { + call_user_func_array($module . '_' . $this->entityType . '_load', $args); + } + } + + /** + * Gets entities from the static cache. + * + * @param $ids + * If not empty, return entities that match these IDs. + * + * @return + * Array of entities from the entity cache. + */ + protected function cacheGet($ids) { + $entities = array(); + // Load any available entities from the internal cache. + if (!empty($this->entityCache)) { + $entities += array_intersect_key($this->entityCache, array_flip($ids)); + } + return $entities; + } + + /** + * Stores entities in the static entity cache. + * + * @param $entities + * Entities to store in the cache. + */ + protected function cacheSet($entities) { + $this->entityCache += $entities; + } + + /** + * Implements Drupal\Core\Entity\EntityStorageControllerInterface::create(). + */ + public function create(array $values) { + $class = isset($this->entityInfo['entity class']) ? $this->entityInfo['entity class'] : 'Drupal\Core\Entity\Entity'; + + $entity = new $class($values, $this->entityType); + + // Assign a new UUID if there is none yet. + if ($this->uuidKey && !isset($entity->{$this->uuidKey})) { + $uuid = new Uuid(); + $entity->{$this->uuidKey} = $uuid->generate(); + } + + return $entity; + } + + /** + * Implements Drupal\Core\Entity\EntityStorageControllerInterface::delete(). + */ + public function delete($ids) { + $entities = $ids ? $this->load($ids) : FALSE; + if (!$entities) { + // If no IDs or invalid IDs were passed, do nothing. + return; + } + $transaction = db_transaction(); + + try { + $this->preDelete($entities); + foreach ($entities as $id => $entity) { + $this->invokeHook('predelete', $entity); + } + $ids = array_keys($entities); + + db_delete($this->entityInfo['base table']) + ->condition($this->idKey, $ids, 'IN') + ->execute(); + // Reset the cache as soon as the changes have been applied. + $this->resetCache($ids); + + $this->postDelete($entities); + foreach ($entities as $id => $entity) { + $this->invokeHook('delete', $entity); + } + // Ignore slave server temporarily. + db_ignore_slave(); + } + catch (Exception $e) { + $transaction->rollback(); + watchdog_exception($this->entityType, $e); + throw new EntityStorageException($e->getMessage, $e->getCode, $e); + } + } + + /** + * Implements Drupal\Core\Entity\EntityStorageControllerInterface::save(). + */ + public function save(EntityInterface $entity) { + $transaction = db_transaction(); + try { + // Load the stored entity, if any. + if (!$entity->isNew() && !isset($entity->original)) { + $entity->original = entity_load_unchanged($this->entityType, $entity->id()); + } + + $this->preSave($entity); + $this->invokeHook('presave', $entity); + + if (!$entity->isNew()) { + $return = drupal_write_record($this->entityInfo['base table'], $entity, $this->idKey); + $this->resetCache(array($entity->{$this->idKey})); + $this->postSave($entity, TRUE); + $this->invokeHook('update', $entity); + } + else { + $return = drupal_write_record($this->entityInfo['base table'], $entity); + // Reset general caches, but keep caches specific to certain entities. + $this->resetCache(array()); + + $entity->enforceIsNew(FALSE); + $this->postSave($entity, FALSE); + $this->invokeHook('insert', $entity); + } + + // Ignore slave server temporarily. + db_ignore_slave(); + unset($entity->original); + + return $return; + } + catch (Exception $e) { + $transaction->rollback(); + watchdog_exception($this->entityType, $e); + throw new EntityStorageException($e->getMessage(), $e->getCode(), $e); + } + } + + /** + * Acts on an entity before the presave hook is invoked. + * + * Used before the entity is saved and before invoking the presave hook. + */ + protected function preSave(EntityInterface $entity) { } + + /** + * Acts on a saved entity before the insert or update hook is invoked. + * + * Used after the entity is saved, but before invoking the insert or update + * hook. + * + * @param $update + * (bool) TRUE if the entity has been updated, or FALSE if it has been + * inserted. + */ + protected function postSave(EntityInterface $entity, $update) { } + + /** + * Acts on entities before they are deleted. + * + * Used before the entities are deleted and before invoking the delete hook. + */ + protected function preDelete($entities) { } + + /** + * Acts on deleted entities before the delete hook is invoked. + * + * Used after the entities are deleted but before invoking the delete hook. + */ + protected function postDelete($entities) { } + + /** + * Invokes a hook on behalf of the entity. + * + * @param $hook + * One of 'presave', 'insert', 'update', 'predelete', or 'delete'. + * @param $entity + * The entity object. + */ + protected function invokeHook($hook, EntityInterface $entity) { + if (!empty($this->entityInfo['fieldable']) && function_exists($function = 'field_attach_' . $hook)) { + $function($this->entityType, $entity); + } + // Invoke the hook. + module_invoke_all($this->entityType . '_' . $hook, $entity); + // Invoke the respective entity-level hook. + module_invoke_all('entity_' . $hook, $entity, $this->entityType); + } +} diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php new file mode 100644 index 0000000..1d22278 --- /dev/null +++ b/core/lib/Drupal/Core/Entity/Entity.php @@ -0,0 +1,290 @@ +entityType = $entity_type; + // Set initial values. + foreach ($values as $key => $value) { + $this->$key = $value; + } + } + + /** + * Implements EntityInterface::id(). + */ + public function id() { + return isset($this->id) ? $this->id : NULL; + } + + /** + * Implements EntityInterface::uuid(). + */ + public function uuid() { + return isset($this->uuid) ? $this->uuid : NULL; + } + + /** + * Implements EntityInterface::isNew(). + */ + public function isNew() { + return !empty($this->enforceIsNew) || !$this->id(); + } + + /** + * Implements EntityInterface::enforceIsNew(). + */ + public function enforceIsNew($value = TRUE) { + $this->enforceIsNew = $value; + } + + /** + * Implements EntityInterface::entityType(). + */ + public function entityType() { + return $this->entityType; + } + + /** + * Implements EntityInterface::bundle(). + */ + public function bundle() { + return $this->entityType; + } + + /** + * Implements EntityInterface::label(). + */ + public function label($langcode = NULL) { + $label = NULL; + $entity_info = $this->entityInfo(); + if (isset($entity_info['label callback']) && function_exists($entity_info['label callback'])) { + $label = $entity_info['label callback']($this->entityType, $this, $langcode); + } + elseif (!empty($entity_info['entity keys']['label']) && isset($this->{$entity_info['entity keys']['label']})) { + $label = $this->{$entity_info['entity keys']['label']}; + } + return $label; + } + + /** + * Implements EntityInterface::uri(). + */ + public function uri() { + $bundle = $this->bundle(); + // A bundle-specific callback takes precedence over the generic one for the + // entity type. + $entity_info = $this->entityInfo(); + if (isset($entity_info['bundles'][$bundle]['uri callback'])) { + $uri_callback = $entity_info['bundles'][$bundle]['uri callback']; + } + elseif (isset($entity_info['uri callback'])) { + $uri_callback = $entity_info['uri callback']; + } + else { + return NULL; + } + + // Invoke the callback to get the URI. If there is no callback, return NULL. + if (isset($uri_callback) && function_exists($uri_callback)) { + $uri = $uri_callback($this); + // Pass the entity data to url() so that alter functions do not need to + // look up this entity again. + $uri['options']['entity_type'] = $this->entityType; + $uri['options']['entity'] = $this; + return $uri; + } + } + + /** + * Implements EntityInterface::language(). + */ + public function language() { + return !empty($this->langcode) ? language_load($this->langcode) : new Language(array('langcode' => LANGUAGE_NOT_SPECIFIED)); + } + + /** + * Implements EntityInterface::translations(). + */ + public function translations() { + $languages = array(); + $entity_info = $this->entityInfo(); + if ($entity_info['fieldable'] && ($default_language = $this->language())) { + // Go through translatable properties and determine all languages for + // which translated values are available. + foreach (field_info_instances($this->entityType, $this->bundle()) as $field_name => $instance) { + $field = field_info_field($field_name); + if (field_is_translatable($this->entityType, $field) && isset($this->$field_name)) { + foreach ($this->$field_name as $langcode => $value) { + $languages[$langcode] = TRUE; + } + } + } + // Remove the default language from the translations. + unset($languages[$default_language->langcode]); + $languages = array_intersect_key(language_list(), $languages); + } + return $languages; + } + + /** + * Implements EntityInterface::get(). + */ + public function get($property_name, $langcode = NULL) { + // Handle fields. + $entity_info = $this->entityInfo(); + if ($entity_info['fieldable'] && field_info_instance($this->entityType, $property_name, $this->bundle())) { + $field = field_info_field($property_name); + $langcode = $this->getFieldLangcode($field, $langcode); + return isset($this->{$property_name}[$langcode]) ? $this->{$property_name}[$langcode] : NULL; + } + else { + // Handle properties being not fields. + // @todo: Add support for translatable properties being not fields. + return isset($this->{$property_name}) ? $this->{$property_name} : NULL; + } + } + + /** + * Implements EntityInterface::set(). + */ + public function set($property_name, $value, $langcode = NULL) { + // Handle fields. + $entity_info = $this->entityInfo(); + if ($entity_info['fieldable'] && field_info_instance($this->entityType, $property_name, $this->bundle())) { + $field = field_info_field($property_name); + $langcode = $this->getFieldLangcode($field, $langcode); + $this->{$property_name}[$langcode] = $value; + } + else { + // Handle properties being not fields. + // @todo: Add support for translatable properties being not fields. + $this->{$property_name} = $value; + } + } + + /** + * Determines the language code to use for accessing a field value in a certain language. + */ + protected function getFieldLangcode($field, $langcode = NULL) { + // Only apply the given langcode if the entity is language-specific. + // Otherwise translatable fields are handled as non-translatable fields. + if (field_is_translatable($this->entityType, $field) && ($default_language = $this->language()) && !language_is_locked($this->langcode)) { + // For translatable fields the values in default language are stored using + // the language code of the default language. + return isset($langcode) ? $langcode : $default_language->langcode; + } + else { + // If there is a langcode defined for this field, just return it. Otherwise + // return LANGUAGE_NOT_SPECIFIED. + return (isset($this->langcode) ? $this->langcode : LANGUAGE_NOT_SPECIFIED); + } + } + + /** + * Implements EntityInterface::save(). + */ + public function save() { + return entity_get_controller($this->entityType)->save($this); + } + + /** + * Implements EntityInterface::delete(). + */ + public function delete() { + if (!$this->isNew()) { + entity_get_controller($this->entityType)->delete(array($this->id())); + } + } + + /** + * Implements EntityInterface::createDuplicate(). + */ + public function createDuplicate() { + $duplicate = clone $this; + $entity_info = $this->entityInfo(); + $this->{$entity_info['entity keys']['id']} = NULL; + + // Check if the entity type supports UUIDs and generate a new one if so. + if (!empty($entity_info['entity keys']['uuid'])) { + $uuid = new Uuid(); + $duplicate->{$entity_info['entity keys']['uuid']} = $uuid->generate(); + } + return $duplicate; + } + + /** + * Implements EntityInterface::entityInfo(). + */ + public function entityInfo() { + return entity_get_info($this->entityType); + } + + /** + * Implements Drupal\Core\Entity\EntityInterface::getRevisionId(). + */ + public function getRevisionId() { + return NULL; + } + + /** + * Implements Drupal\Core\Entity\EntityInterface::isDefaultRevision(). + */ + public function isDefaultRevision($new_value = NULL) { + $return = $this->isDefaultRevision; + if (isset($new_value)) { + $this->isDefaultRevision = (bool) $new_value; + } + return $return; + } + +} diff --git a/core/lib/Drupal/Core/Entity/EntityFieldQuery.php b/core/lib/Drupal/Core/Entity/EntityFieldQuery.php new file mode 100644 index 0000000..979cb2f --- /dev/null +++ b/core/lib/Drupal/Core/Entity/EntityFieldQuery.php @@ -0,0 +1,964 @@ +changed), field values, and generic entity meta data (bundle, + * entity type, entity id, and revision ID). It is not possible to query across + * multiple entity types. For example, there is no facility to find published + * nodes written by users created in the last hour, as this would require + * querying both node->status and user->created. + * + * Normally we would not want to have public properties on the object, as that + * allows the object's state to become inconsistent too easily. However, this + * class's standard use case involves primarily code that does need to have + * direct access to the collected properties in order to handle alternate + * execution routines. We therefore use public properties for simplicity. Note + * that code that is simply creating and running a field query should still use + * the appropriate methods to add conditions on the query. + * + * Storage engines are not required to support every type of query. By default, + * an EntityFieldQueryException will be raised if an unsupported condition is + * specified or if the query has field conditions or sorts that are stored in + * different field storage engines. However, this logic can be overridden in + * hook_entity_query_alter(). + * + * Also note that this query does not automatically respect entity access + * restrictions. Node access control is performed by the SQL storage engine but + * other storage engines might not do this. + */ +class EntityFieldQuery { + + /** + * Indicates that both deleted and non-deleted fields should be returned. + * + * @see Drupal\Core\Entity\EntityFieldQuery::deleted() + */ + const RETURN_ALL = NULL; + + /** + * TRUE if the query has already been altered, FALSE if it hasn't. + * + * Used in alter hooks to check for cloned queries that have already been + * altered prior to the clone (for example, the pager count query). + * + * @var boolean + */ + public $altered = FALSE; + + /** + * Associative array of entity-generic metadata conditions. + * + * @var array + * + * @see Drupal\Core\Entity\EntityFieldQuery::entityCondition() + */ + public $entityConditions = array(); + + /** + * List of field conditions. + * + * @var array + * + * @see Drupal\Core\Entity\EntityFieldQuery::fieldCondition() + */ + public $fieldConditions = array(); + + /** + * List of field meta conditions (language and delta). + * + * Field conditions operate on columns specified by hook_field_schema(), + * the meta conditions operate on columns added by the system: delta + * and language. These can not be mixed with the field conditions because + * field columns can have any name including delta and language. + * + * @var array + * + * @see Drupal\Core\Entity\EntityFieldQuery::fieldLanguageCondition() + * @see Drupal\Core\Entity\EntityFieldQuery::fieldDeltaCondition() + */ + public $fieldMetaConditions = array(); + + /** + * List of property conditions. + * + * @var array + * + * @see Drupal\Core\Entity\EntityFieldQuery::propertyCondition() + */ + public $propertyConditions = array(); + + /** + * List of order clauses. + * + * @var array + */ + public $order = array(); + + /** + * The query range. + * + * @var array + * + * @see Drupal\Core\Entity\EntityFieldQuery::range() + */ + public $range = array(); + + /** + * The query pager data. + * + * @var array + * + * @see Drupal\Core\Entity\EntityFieldQuery::pager() + */ + public $pager = array(); + + /** + * Query behavior for deleted data. + * + * TRUE to return only deleted data, FALSE to return only non-deleted data, + * EntityFieldQuery::RETURN_ALL to return everything. + * + * @see Drupal\Core\Entity\EntityFieldQuery::deleted() + */ + public $deleted = FALSE; + + /** + * A list of field arrays used. + * + * Field names passed to EntityFieldQuery::fieldCondition() and + * EntityFieldQuery::fieldOrderBy() are run through field_info_field() before + * stored in this array. This way, the elements of this array are field + * arrays. + * + * @var array + */ + public $fields = array(); + + /** + * TRUE if this is a count query, FALSE if it isn't. + * + * @var boolean + */ + public $count = FALSE; + + /** + * Flag indicating whether this is querying current or all revisions. + * + * @var int + * + * @see Drupal\Core\Entity\EntityFieldQuery::age() + */ + public $age = FIELD_LOAD_CURRENT; + + /** + * A list of the tags added to this query. + * + * @var array + * + * @see Drupal\Core\Entity\EntityFieldQuery::addTag() + */ + public $tags = array(); + + /** + * A list of metadata added to this query. + * + * @var array + * + * @see Drupal\Core\Entity\EntityFieldQuery::addMetaData() + */ + public $metaData = array(); + + /** + * The ordered results. + * + * @var array + * + * @see Drupal\Core\Entity\EntityFieldQuery::execute(). + */ + public $orderedResults = array(); + + /** + * The method executing the query, if it is overriding the default. + * + * @var string + * + * @see Drupal\Core\Entity\EntityFieldQuery::execute() + */ + public $executeCallback = ''; + + /** + * Adds a condition on entity-generic metadata. + * + * If the overall query contains only entity conditions or ordering, or if + * there are property conditions, then specifying the entity type is + * mandatory. If there are field conditions or ordering but no property + * conditions or ordering, then specifying an entity type is optional. While + * the field storage engine might support field conditions on more than one + * entity type, there is no way to query across multiple entity base tables by + * default. To specify the entity type, pass in 'entity_type' for $name, + * the type as a string for $value, and no $operator (it's disregarded). + * + * 'bundle', 'revision_id' and 'entity_id' have no such restrictions. + * + * Note: The "comment" entity type does not support bundle conditions. + * + * @param $name + * 'entity_type', 'bundle', 'revision_id' or 'entity_id'. + * @param $value + * The value for $name. In most cases, this is a scalar. For more complex + * options, it is an array. The meaning of each element in the array is + * dependent on $operator. + * @param $operator + * Possible values: + * - '=', '<>', '>', '>=', '<', '<=', 'STARTS_WITH', 'CONTAINS': These + * operators expect $value to be a literal of the same type as the + * column. + * - 'IN', 'NOT IN': These operators expect $value to be an array of + * literals of the same type as the column. + * - 'BETWEEN': This operator expects $value to be an array of two literals + * of the same type as the column. + * The operator can be omitted, and will default to 'IN' if the value is an + * array, or to '=' otherwise. + * + * @return Drupal\Core\Entity\EntityFieldQuery + * The called object. + */ + public function entityCondition($name, $value, $operator = NULL) { + $this->entityConditions[$name] = array( + 'value' => $value, + 'operator' => $operator, + ); + return $this; + } + + /** + * Adds a condition on field values. + * + * Note that entities with empty field values will be excluded from the + * EntityFieldQuery results when using this method. + * + * @param $field + * Either a field name or a field array. + * @param $column + * The column that should hold the value to be matched. + * @param $value + * The value to test the column value against. + * @param $operator + * The operator to be used to test the given value. + * @param $delta_group + * An arbitrary identifier: conditions in the same group must have the same + * $delta_group. + * @param $langcode_group + * An arbitrary identifier: conditions in the same group must have the same + * $langcode_group. + * + * @return Drupal\Core\Entity\EntityFieldQuery + * The called object. + * + * @see Drupal\Core\Entity\EntityFieldQuery::addFieldCondition() + * @see Drupal\Core\Entity\EntityFieldQuery::deleted() + */ + public function fieldCondition($field, $column = NULL, $value = NULL, $operator = NULL, $delta_group = NULL, $langcode_group = NULL) { + return $this->addFieldCondition($this->fieldConditions, $field, $column, $value, $operator, $delta_group, $langcode_group); + } + + /** + * Adds a condition on the field language column. + * + * @param $field + * Either a field name or a field array. + * @param $value + * The value to test the column value against. + * @param $operator + * The operator to be used to test the given value. + * @param $delta_group + * An arbitrary identifier: conditions in the same group must have the same + * $delta_group. + * @param $langcode_group + * An arbitrary identifier: conditions in the same group must have the same + * $langcode_group. + * + * @return Drupal\Core\Entity\EntityFieldQuery + * The called object. + * + * @see Drupal\Core\Entity\EntityFieldQuery::addFieldCondition() + * @see Drupal\Core\Entity\EntityFieldQuery::deleted() + */ + public function fieldLanguageCondition($field, $value = NULL, $operator = NULL, $delta_group = NULL, $langcode_group = NULL) { + return $this->addFieldCondition($this->fieldMetaConditions, $field, 'langcode', $value, $operator, $delta_group, $langcode_group); + } + + /** + * Adds a condition on the field delta column. + * + * @param $field + * Either a field name or a field array. + * @param $value + * The value to test the column value against. + * @param $operator + * The operator to be used to test the given value. + * @param $delta_group + * An arbitrary identifier: conditions in the same group must have the same + * $delta_group. + * @param $langcode_group + * An arbitrary identifier: conditions in the same group must have the same + * $langcode_group. + * + * @return Drupal\Core\Entity\EntityFieldQuery + * The called object. + * + * @see Drupal\Core\Entity\EntityFieldQuery::addFieldCondition() + * @see Drupal\Core\Entity\EntityFieldQuery::deleted() + */ + public function fieldDeltaCondition($field, $value = NULL, $operator = NULL, $delta_group = NULL, $langcode_group = NULL) { + return $this->addFieldCondition($this->fieldMetaConditions, $field, 'delta', $value, $operator, $delta_group, $langcode_group); + } + + /** + * Adds the given condition to the proper condition array. + * + * @param $conditions + * A reference to an array of conditions. + * @param $field + * Either a field name or a field array. + * @param $column + * A column defined in the hook_field_schema() of this field. If this is + * omitted then the query will find only entities that have data in this + * field, using the entity and property conditions if there are any. + * @param $value + * The value to test the column value against. In most cases, this is a + * scalar. For more complex options, it is an array. The meaning of each + * element in the array is dependent on $operator. + * @param $operator + * Possible values: + * - '=', '<>', '>', '>=', '<', '<=', 'STARTS_WITH', 'CONTAINS': These + * operators expect $value to be a literal of the same type as the + * column. + * - 'IN', 'NOT IN': These operators expect $value to be an array of + * literals of the same type as the column. + * - 'BETWEEN': This operator expects $value to be an array of two literals + * of the same type as the column. + * The operator can be omitted, and will default to 'IN' if the value is an + * array, or to '=' otherwise. + * @param $delta_group + * An arbitrary identifier: conditions in the same group must have the same + * $delta_group. For example, let's presume a multivalue field which has + * two columns, 'color' and 'shape', and for entity id 1, there are two + * values: red/square and blue/circle. Entity ID 1 does not have values + * corresponding to 'red circle', however if you pass 'red' and 'circle' as + * conditions, it will appear in the results - by default queries will run + * against any combination of deltas. By passing the conditions with the + * same $delta_group it will ensure that only values attached to the same + * delta are matched, and entity 1 would then be excluded from the results. + * @param $langcode_group + * An arbitrary identifier: conditions in the same group must have the same + * $langcode_group. + * + * @return Drupal\Core\Entity\EntityFieldQuery + * The called object. + */ + protected function addFieldCondition(&$conditions, $field, $column = NULL, $value = NULL, $operator = NULL, $delta_group = NULL, $langcode_group = NULL) { + if (is_scalar($field)) { + $field_definition = field_info_field($field); + if (empty($field_definition)) { + throw new EntityFieldQueryException(t('Unknown field: @field_name', array('@field_name' => $field))); + } + $field = $field_definition; + } + // Ensure the same index is used for field conditions as for fields. + $index = count($this->fields); + $this->fields[$index] = $field; + if (isset($column)) { + $conditions[$index] = array( + 'field' => $field, + 'column' => $column, + 'value' => $value, + 'operator' => $operator, + 'delta_group' => $delta_group, + 'langcode_group' => $langcode_group, + ); + } + return $this; + } + + /** + * Adds a condition on an entity-specific property. + * + * An $entity_type must be specified by calling + * EntityFieldCondition::entityCondition('entity_type', $entity_type) before + * executing the query. Also, by default only entities stored in SQL are + * supported; however, EntityFieldQuery::executeCallback can be set to handle + * different entity storage. + * + * @param $column + * A column defined in the hook_schema() of the base table of the entity. + * @param $value + * The value to test the field against. In most cases, this is a scalar. For + * more complex options, it is an array. The meaning of each element in the + * array is dependent on $operator. + * @param $operator + * Possible values: + * - '=', '<>', '>', '>=', '<', '<=', 'STARTS_WITH', 'CONTAINS': These + * operators expect $value to be a literal of the same type as the + * column. + * - 'IN', 'NOT IN': These operators expect $value to be an array of + * literals of the same type as the column. + * - 'BETWEEN': This operator expects $value to be an array of two literals + * of the same type as the column. + * The operator can be omitted, and will default to 'IN' if the value is an + * array, or to '=' otherwise. + * + * @return Drupal\Core\Entity\EntityFieldQuery + * The called object. + */ + public function propertyCondition($column, $value, $operator = NULL) { + $this->propertyConditions[] = array( + 'column' => $column, + 'value' => $value, + 'operator' => $operator, + ); + return $this; + } + + /** + * Orders the result set by entity-generic metadata. + * + * If called multiple times, the query will order by each specified column in + * the order this method is called. + * + * Note: The "comment" and "taxonomy_term" entity types don't support ordering + * by bundle. For "taxonomy_term", propertyOrderBy('vid') can be used instead. + * + * @param $name + * 'entity_type', 'bundle', 'revision_id' or 'entity_id'. + * @param $direction + * The direction to sort. Legal values are "ASC" and "DESC". + * + * @return Drupal\Core\Entity\EntityFieldQuery + * The called object. + */ + public function entityOrderBy($name, $direction = 'ASC') { + $this->order[] = array( + 'type' => 'entity', + 'specifier' => $name, + 'direction' => $direction, + ); + return $this; + } + + /** + * Orders the result set by a given field column. + * + * If called multiple times, the query will order by each specified column in + * the order this method is called. Note that entities with empty field + * values will be excluded from the EntityFieldQuery results when using this + * method. + * + * @param $field + * Either a field name or a field array. + * @param $column + * A column defined in the hook_field_schema() of this field. entity_id and + * bundle can also be used. + * @param $direction + * The direction to sort. Legal values are "ASC" and "DESC". + * + * @return Drupal\Core\Entity\EntityFieldQuery + * The called object. + */ + public function fieldOrderBy($field, $column, $direction = 'ASC') { + if (is_scalar($field)) { + $field_definition = field_info_field($field); + if (empty($field_definition)) { + throw new EntityFieldQueryException(t('Unknown field: @field_name', array('@field_name' => $field))); + } + $field = $field_definition; + } + // Save the index used for the new field, for later use in field storage. + $index = count($this->fields); + $this->fields[$index] = $field; + $this->order[] = array( + 'type' => 'field', + 'specifier' => array( + 'field' => $field, + 'index' => $index, + 'column' => $column, + ), + 'direction' => $direction, + ); + return $this; + } + + /** + * Orders the result set by an entity-specific property. + * + * An $entity_type must be specified by calling + * EntityFieldCondition::entityCondition('entity_type', $entity_type) before + * executing the query. + * + * If called multiple times, the query will order by each specified column in + * the order this method is called. + * + * @param $column + * The column on which to order. + * @param $direction + * The direction to sort. Legal values are "ASC" and "DESC". + * + * @return Drupal\Core\Entity\EntityFieldQuery + * The called object. + */ + public function propertyOrderBy($column, $direction = 'ASC') { + $this->order[] = array( + 'type' => 'property', + 'specifier' => $column, + 'direction' => $direction, + ); + return $this; + } + + /** + * Sets the query to be a count query only. + * + * @return Drupal\Core\Entity\EntityFieldQuery + * The called object. + */ + public function count() { + $this->count = TRUE; + return $this; + } + + /** + * Restricts a query to a given range in the result set. + * + * @param $start + * The first entity from the result set to return. If NULL, removes any + * range directives that are set. + * @param $length + * The number of entities to return from the result set. + * + * @return Drupal\Core\Entity\EntityFieldQuery + * The called object. + */ + public function range($start = NULL, $length = NULL) { + $this->range = array( + 'start' => $start, + 'length' => $length, + ); + return $this; + } + + /** + * Enables a pager for the query. + * + * @param $limit + * An integer specifying the number of elements per page. If passed a false + * value (FALSE, 0, NULL), the pager is disabled. + * @param $element + * An optional integer to distinguish between multiple pagers on one page. + * If not provided, one is automatically calculated. + * + * @return Drupal\Core\Entity\EntityFieldQuery + * The called object. + */ + public function pager($limit = 10, $element = NULL) { + if (!isset($element)) { + $element = PagerSelectExtender::$maxElement++; + } + elseif ($element >= PagerSelectExtender::$maxElement) { + PagerSelectExtender::$maxElement = $element + 1; + } + + $this->pager = array( + 'limit' => $limit, + 'element' => $element, + ); + return $this; + } + + /** + * Enables sortable tables for this query. + * + * @param $headers + * An EFQ Header array based on which the order clause is added to the + * query. + * + * @return Drupal\Core\Entity\EntityFieldQuery + * The called object. + */ + public function tableSort(&$headers) { + // If 'field' is not initialized, the header columns aren't clickable + foreach ($headers as $key =>$header) { + if (is_array($header) && isset($header['specifier'])) { + $headers[$key]['field'] = ''; + } + } + + $order = tablesort_get_order($headers); + $direction = tablesort_get_sort($headers); + foreach ($headers as $header) { + if (is_array($header) && ($header['data'] == $order['name'])) { + if ($header['type'] == 'field') { + $this->fieldOrderBy($header['specifier']['field'], $header['specifier']['column'], $direction); + } + else { + $header['direction'] = $direction; + $this->order[] = $header; + } + } + } + + return $this; + } + + /** + * Filters on the data being deleted. + * + * @param $deleted + * TRUE to only return deleted data, FALSE to return non-deleted data, + * EntityFieldQuery::RETURN_ALL to return everything. Defaults to FALSE. + * + * @return Drupal\Core\Entity\EntityFieldQuery + * The called object. + */ + public function deleted($deleted = TRUE) { + $this->deleted = $deleted; + return $this; + } + + /** + * Queries the current or every revision. + * + * Note that this only affects field conditions. Property conditions always + * apply to the current revision. + * @TODO: Once revision tables have been cleaned up, revisit this. + * + * @param $age + * - FIELD_LOAD_CURRENT (default): Query the most recent revisions for all + * entities. The results will be keyed by entity type and entity ID. + * - FIELD_LOAD_REVISION: Query all revisions. The results will be keyed by + * entity type and entity revision ID. + * + * @return Drupal\Core\Entity\EntityFieldQuery + * The called object. + */ + public function age($age) { + $this->age = $age; + return $this; + } + + /** + * Adds a tag to the query. + * + * Tags are strings that mark a query so that hook_query_alter() and + * hook_query_TAG_alter() implementations may decide if they wish to alter + * the query. A query may have any number of tags, and they must be valid PHP + * identifiers (composed of letters, numbers, and underscores). For example, + * queries involving nodes that will be displayed for a user need to add the + * tag 'node_access', so that the node module can add access restrictions to + * the query. + * + * If an entity field query has tags, it must also have an entity type + * specified, because the alter hook will need the entity base table. + * + * @param string $tag + * The tag to add. + * + * @return Drupal\Core\Entity\EntityFieldQuery + * The called object. + */ + public function addTag($tag) { + $this->tags[$tag] = $tag; + return $this; + } + + /** + * Adds additional metadata to the query. + * + * Sometimes a query may need to provide additional contextual data for the + * alter hook. The alter hook implementations may then use that information + * to decide if and how to take action. + * + * @param $key + * The unique identifier for this piece of metadata. Must be a string that + * follows the same rules as any other PHP identifier. + * @param $object + * The additional data to add to the query. May be any valid PHP variable. + * + * @return Drupal\Core\Entity\EntityFieldQuery + * The called object. + */ + public function addMetaData($key, $object) { + $this->metaData[$key] = $object; + return $this; + } + + /** + * Executes the query. + * + * After executing the query, $this->orderedResults will contain a list of + * the same entity ids in the order returned by the query. This is only + * relevant if there are multiple entity types in the returned value and + * a field ordering was requested. In every other case, the returned value + * contains everything necessary for processing. + * + * @return + * Either a number if count() was called or an array of associative arrays + * of the entity ids. The outer array keys are entity types, and the inner + * array keys are the relevant ID. (In most cases this will be the entity + * ID. The only exception is when age=FIELD_LOAD_REVISION is used and field + * conditions or sorts are present -- in this case, the key will be the + * revision ID.) The entity type will only exist in the outer array if + * results were found. The inner array values consist of an object with the + * entity_id, revision_id and bundle properties. To traverse the returned + * array: + * @code + * foreach ($query->execute() as $entity_type => $entities) { + * foreach ($entities as $entity_id => $entity) { + * @endcode + * Note if the entity type is known, then the following snippet will load + * the entities found: + * @code + * $result = $query->execute(); + * if (!empty($result[$my_type])) { + * $entities = entity_load_multiple($my_type, array_keys($result[$my_type])); + * } + * @endcode + */ + public function execute() { + // Give a chance to other modules to alter the query. + drupal_alter('entity_query', $this); + $this->altered = TRUE; + + // Initialize the pager. + $this->initializePager(); + + // Execute the query using the correct callback. + $result = call_user_func($this->queryCallback(), $this); + + return $result; + } + + /** + * Determines the query callback to use for this entity query. + * + * @return + * A callback that can be used with call_user_func(). + */ + public function queryCallback() { + // Use the override from $this->executeCallback. It can be set either + // while building the query, or using hook_entity_query_alter(). + if (function_exists($this->executeCallback)) { + return $this->executeCallback; + } + // If there are no field conditions and sorts, and no execute callback + // then we default to querying entity tables in SQL. + if (empty($this->fields)) { + return array($this, 'propertyQuery'); + } + // If no override, find the storage engine to be used. + foreach ($this->fields as $field) { + if (!isset($storage)) { + $storage = $field['storage']['module']; + } + elseif ($storage != $field['storage']['module']) { + throw new EntityFieldQueryException(t("Can't handle more than one field storage engine")); + } + } + if ($storage) { + // Use hook_field_storage_query() from the field storage. + return $storage . '_field_storage_query'; + } + else { + throw new EntityFieldQueryException(t("Field storage engine not found.")); + } + } + + /** + * Queries entity tables in SQL for property conditions and sorts. + * + * This method is only used if there are no field conditions and sorts. + * + * @return + * See EntityFieldQuery::execute(). + */ + protected function propertyQuery() { + if (empty($this->entityConditions['entity_type'])) { + throw new EntityFieldQueryException(t('For this query an entity type must be specified.')); + } + $entity_type = $this->entityConditions['entity_type']['value']; + $entity_info = entity_get_info($entity_type); + if (empty($entity_info['base table'])) { + throw new EntityFieldQueryException(t('Entity %entity has no base table.', array('%entity' => $entity_type))); + } + $base_table = $entity_info['base table']; + $base_table_schema = drupal_get_schema($base_table); + $select_query = db_select($base_table); + $select_query->addExpression(':entity_type', 'entity_type', array(':entity_type' => $entity_type)); + // Process the property conditions. + foreach ($this->propertyConditions as $property_condition) { + $this->addCondition($select_query, $base_table . '.' . $property_condition['column'], $property_condition); + } + // Process the four possible entity condition. + // The id field is always present in entity keys. + $sql_field = $entity_info['entity keys']['id']; + $id_map['entity_id'] = $sql_field; + $select_query->addField($base_table, $sql_field, 'entity_id'); + if (isset($this->entityConditions['entity_id'])) { + $this->addCondition($select_query, $base_table . '.' . $sql_field, $this->entityConditions['entity_id']); + } + + // If there is a revision key defined, use it. + if (!empty($entity_info['entity keys']['revision'])) { + $sql_field = $entity_info['entity keys']['revision']; + $select_query->addField($base_table, $sql_field, 'revision_id'); + if (isset($this->entityConditions['revision_id'])) { + $this->addCondition($select_query, $base_table . '.' . $sql_field, $this->entityConditions['revision_id']); + } + } + else { + $sql_field = 'revision_id'; + $select_query->addExpression('NULL', 'revision_id'); + } + $id_map['revision_id'] = $sql_field; + + // Handle bundles. + if (!empty($entity_info['entity keys']['bundle'])) { + $sql_field = $entity_info['entity keys']['bundle']; + $having = FALSE; + + if (!empty($base_table_schema['fields'][$sql_field])) { + $select_query->addField($base_table, $sql_field, 'bundle'); + } + } + else { + $sql_field = 'bundle'; + $select_query->addExpression(':bundle', 'bundle', array(':bundle' => $entity_type)); + $having = TRUE; + } + $id_map['bundle'] = $sql_field; + if (isset($this->entityConditions['bundle'])) { + if (!empty($entity_info['entity keys']['bundle'])) { + $this->addCondition($select_query, $base_table . '.' . $sql_field, $this->entityConditions['bundle'], $having); + } + else { + // This entity has no bundle, so invalidate the query. + $select_query->where('1 = 0'); + } + } + + // Order the query. + foreach ($this->order as $order) { + if ($order['type'] == 'entity') { + $key = $order['specifier']; + if (!isset($id_map[$key])) { + throw new EntityFieldQueryException(t('Do not know how to order on @key for @entity_type', array('@key' => $key, '@entity_type' => $entity_type))); + } + $select_query->orderBy($id_map[$key], $order['direction']); + } + elseif ($order['type'] == 'property') { + $select_query->orderBy($base_table . '.' . $order['specifier'], $order['direction']); + } + } + + return $this->finishQuery($select_query); + } + + /** + * Gets the total number of results and initialize a pager for the query. + * + * The pager can be disabled by either setting the pager limit to 0, or by + * setting this query to be a count query. + */ + function initializePager() { + if ($this->pager && !empty($this->pager['limit']) && !$this->count) { + $page = pager_find_page($this->pager['element']); + $count_query = clone $this; + $this->pager['total'] = $count_query->count()->execute(); + $this->pager['start'] = $page * $this->pager['limit']; + pager_default_initialize($this->pager['total'], $this->pager['limit'], $this->pager['element']); + $this->range($this->pager['start'], $this->pager['limit']); + } + } + + /** + * Finishes the query. + * + * Adds tags, metaData, range and returns the requested list or count. + * + * @param SelectQuery $select_query + * A SelectQuery which has entity_type, entity_id, revision_id and bundle + * fields added. + * @param $id_key + * Which field's values to use as the returned array keys. + * + * @return + * See EntityFieldQuery::execute(). + */ + function finishQuery($select_query, $id_key = 'entity_id') { + foreach ($this->tags as $tag) { + $select_query->addTag($tag); + } + foreach ($this->metaData as $key => $object) { + $select_query->addMetaData($key, $object); + } + $select_query->addMetaData('entity_field_query', $this); + if ($this->range) { + $select_query->range($this->range['start'], $this->range['length']); + } + if ($this->count) { + return $select_query->countQuery()->execute()->fetchField(); + } + $return = array(); + foreach ($select_query->execute() as $ids) { + if (!isset($ids->bundle)) { + $ids->bundle = NULL; + } + $return[$ids->entity_type][$ids->$id_key] = $ids; + $this->ordered_results[] = $ids; + } + return $return; + } + + /** + * Adds a condition to an already built SelectQuery (internal function). + * + * This is a helper for hook_entity_query() and hook_field_storage_query(). + * + * @param SelectQuery $select_query + * A SelectQuery object. + * @param $sql_field + * The name of the field. + * @param $condition + * A condition as described in EntityFieldQuery::fieldCondition() and + * EntityFieldQuery::entityCondition(). + * @param $having + * HAVING or WHERE. This is necessary because SQL can't handle WHERE + * conditions on aliased columns. + */ + public function addCondition(Select $select_query, $sql_field, $condition, $having = FALSE) { + $method = $having ? 'havingCondition' : 'condition'; + $like_prefix = ''; + switch ($condition['operator']) { + case 'CONTAINS': + $like_prefix = '%'; + case 'STARTS_WITH': + $select_query->$method($sql_field, $like_prefix . db_like($condition['value']) . '%', 'LIKE'); + break; + default: + $select_query->$method($sql_field, $condition['value'], $condition['operator']); + } + } + +} diff --git a/core/lib/Drupal/Core/Entity/EntityFieldQueryException.php b/core/lib/Drupal/Core/Entity/EntityFieldQueryException.php new file mode 100644 index 0000000..bf792a5 --- /dev/null +++ b/core/lib/Drupal/Core/Entity/EntityFieldQueryException.php @@ -0,0 +1,19 @@ +operation = $operation; + } + + /** + * Implements Drupal\Core\Entity\EntityFormControllerInterface::build(). + */ + public function build(array $form, array &$form_state, EntityInterface $entity) { + + // During the initial form build, add the entity to the form state for use + // during form building and processing. During a rebuild, use what is in the + // form state. + if (!$this->getEntity($form_state)) { + $this->init($form_state, $entity); + } + + // Retrieve the form array using the possibly updated entity in form state. + $entity = $this->getEntity($form_state); + $form = $this->form($form, $form_state, $entity); + + // Retrieve and add the form actions array. + $actions = $this->actionsElement($form, $form_state); + if (!empty($actions)) { + $form['actions'] = $actions; + } + + return $form; + } + + /** + * Initialize the form state and the entity before the first form build. + */ + protected function init(array &$form_state, EntityInterface $entity) { + // Add the controller to the form state so it can be easily accessed by + // module-provided form handlers there. + $form_state['controller'] = $this; + $this->setEntity($entity, $form_state); + $this->prepareEntity($entity); + } + + /** + * Returns the actual form array to be built. + * + * @see Drupal\Core\Entity\EntityFormController::build() + */ + public function form(array $form, array &$form_state, EntityInterface $entity) { + // @todo Exploit the Property API to generate the default widgets for the + // entity properties. + $info = $entity->entityInfo(); + if (!empty($info['fieldable'])) { + field_attach_form($entity->entityType(), $entity, $form, $form_state, $this->getFormLangcode($form_state)); + } + return $form; + } + + /** + * Returns the action form element for the current entity form. + */ + protected function actionsElement(array $form, array &$form_state) { + $element = $this->actions($form, $form_state); + + // We cannot delete an entity that has not been created yet. + if ($this->getEntity($form_state)->isNew()) { + unset($element['delete']); + } + elseif (isset($element['delete'])) { + // Move the delete action as last one, unless weights are explicitly + // provided. + $delete = $element['delete']; + unset($element['delete']); + $element['delete'] = $delete; + } + + $count = 0; + foreach (element_children($element) as $action) { + $element[$action] += array( + '#type' => 'submit', + '#weight' => ++$count * 5, + ); + } + + if (!empty($element)) { + $element['#type'] = 'actions'; + } + + return $element; + } + + /** + * Returns an array of supported actions for the current entity form. + */ + protected function actions(array $form, array &$form_state) { + return array( + // @todo Rename the action key from submit to save. + 'submit' => array( + '#value' => t('Save'), + '#validate' => array( + array($this, 'validate'), + ), + '#submit' => array( + array($this, 'submit'), + array($this, 'save'), + ), + ), + 'delete' => array( + '#value' => t('Delete'), + // No need to validate the form when deleting the entity. + '#submit' => array( + array($this, 'delete'), + ), + ), + // @todo Consider introducing a 'preview' action here, since it is used by + // many entity types. + ); + } + + /** + * Implements Drupal\Core\Entity\EntityFormControllerInterface::validate(). + */ + public function validate(array $form, array &$form_state) { + // @todo Exploit the Property API to validate the values submitted for the + // entity properties. + $entity = $this->buildEntity($form, $form_state); + $info = $entity->entityInfo(); + + if (!empty($info['fieldable'])) { + field_attach_form_validate($entity->entityType(), $entity, $form, $form_state); + } + + // @todo Remove this. + // Execute legacy global validation handlers. + unset($form_state['validate_handlers']); + form_execute_handlers('validate', $form, $form_state); + } + + /** + * Implements Drupal\Core\Entity\EntityFormControllerInterface::submit(). + * + * This is the default entity object builder function. It is called before any + * other submit handler to build the new entity object to be passed to the + * following submit handlers. At this point of the form workflow the entity is + * validated and the form state can be updated, this way the subsequently + * invoked handlers can retrieve a regular entity object to act on. + * + * @param array $form + * An associative array containing the structure of the form. + * @param array $form_state + * A reference to a keyed array containing the current state of the form. + */ + public function submit(array $form, array &$form_state) { + $entity = $this->buildEntity($form, $form_state); + $this->setEntity($entity, $form_state); + return $entity; + } + + /** + * Form submission handler for the 'save' action. + * + * @param array $form + * An associative array containing the structure of the form. + * @param array $form_state + * A reference to a keyed array containing the current state of the form. + */ + public function save(array $form, array &$form_state) { + // @todo Perform common save operations. + } + + /** + * Form submission handler for the 'delete' action. + * + * @param array $form + * An associative array containing the structure of the form. + * @param array $form_state + * A reference to a keyed array containing the current state of the form. + */ + public function delete(array $form, array &$form_state) { + // @todo Perform common delete operations. + } + + /** + * Implements Drupal\Core\Entity\EntityFormControllerInterface::getFormLangcode(). + */ + public function getFormLangcode(array $form_state) { + $entity = $this->getEntity($form_state); + $translations = $entity->translations(); + + if (!empty($form_state['langcode'])) { + $langcode = $form_state['langcode']; + } + else { + // If no form langcode was provided we default to the current content + // language and inspect existing translations to find a valid fallback, + // if any. + $langcode = language(LANGUAGE_TYPE_CONTENT)->langcode; + $fallback = language_multilingual() ? language_fallback_get_candidates() : array(); + while (!empty($langcode) && !isset($translations[$langcode])) { + $langcode = array_shift($fallback); + } + } + + // If the site is not multilingual or no translation for the given form + // language is available, fall back to the entity language. + return !empty($langcode) ? $langcode : $entity->language()->langcode; + } + + /** + * Implements Drupal\Core\Entity\EntityFormControllerInterface::buildEntity(). + */ + public function buildEntity(array $form, array &$form_state) { + $entity = clone $this->getEntity($form_state); + // @todo Move entity_form_submit_build_entity() here. + // @todo Exploit the Property API to process the submitted entity property. + entity_form_submit_build_entity($entity->entityType(), $entity, $form, $form_state); + return $entity; + } + + /** + * Implements Drupal\Core\Entity\EntityFormControllerInterface::getEntity(). + */ + public function getEntity(array $form_state) { + return isset($form_state['entity']) ? $form_state['entity'] : NULL; + } + + /** + * Implements Drupal\Core\Entity\EntityFormControllerInterface::setEntity(). + */ + public function setEntity(EntityInterface $entity, array &$form_state) { + $form_state['entity'] = $entity; + } + + /** + * Prepares the entity object before the form is built first. + */ + protected function prepareEntity(EntityInterface $entity) { + // @todo Perform common prepare operations and add a hook. + } + + /** + * Implements Drupal\Core\Entity\EntityFormControllerInterface::getOperation(). + */ + public function getOperation() { + return $this->operation; + } +} diff --git a/core/lib/Drupal/Core/Entity/EntityFormControllerInterface.php b/core/lib/Drupal/Core/Entity/EntityFormControllerInterface.php new file mode 100644 index 0000000..72c97f1 --- /dev/null +++ b/core/lib/Drupal/Core/Entity/EntityFormControllerInterface.php @@ -0,0 +1,134 @@ + $value) { $this->$name = $value; @@ -63,4 +114,22 @@ class Language { $this->$var = $value; } } + + /** + * Return TRUE if the current language is the dafult of the site. + * + * @return boolean + */ + public function isDefault() { + return $this->default; + } + + /** + * Set the status for the default value. + * + * @param bool $value + */ + public function setDefault($value) { + $this->default = $value; + } } diff --git a/core/modules/comment/comment.api.php b/core/modules/comment/comment.api.php index fded934..95c3e1d 100644 --- a/core/modules/comment/comment.api.php +++ b/core/modules/comment/comment.api.php @@ -1,6 +1,6 @@ cid; } /** - * Implements Drupal\entity\EntityInterface::bundle(). + * Implements Drupal\Core\Entity\EntityInterface::bundle(). */ public function bundle() { return $this->node_type; diff --git a/core/modules/comment/lib/Drupal/comment/CommentFormController.php b/core/modules/comment/lib/Drupal/comment/CommentFormController.php index f0f16c2..7dae92d 100644 --- a/core/modules/comment/lib/Drupal/comment/CommentFormController.php +++ b/core/modules/comment/lib/Drupal/comment/CommentFormController.php @@ -7,8 +7,8 @@ namespace Drupal\comment; -use Drupal\entity\EntityInterface; -use Drupal\entity\EntityFormController; +use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityFormController; /** * Base for controller for comment forms. @@ -16,7 +16,7 @@ use Drupal\entity\EntityFormController; class CommentFormController extends EntityFormController { /** - * Overrides Drupal\entity\EntityFormController::form(). + * Overrides Drupal\Core\Entity\EntityFormController::form(). */ public function form(array $form, array &$form_state, EntityInterface $comment) { global $user; @@ -193,7 +193,7 @@ class CommentFormController extends EntityFormController { } /** - * Overrides Drupal\entity\EntityFormController::actions(). + * Overrides Drupal\Core\Entity\EntityFormController::actions(). */ protected function actions(array $form, array &$form_state) { $element = parent::actions($form, $form_state); @@ -227,7 +227,7 @@ class CommentFormController extends EntityFormController { } /** - * Overrides Drupal\entity\EntityFormController::validate(). + * Overrides Drupal\Core\Entity\EntityFormController::validate(). */ public function validate(array $form, array &$form_state) { parent::validate($form, $form_state); @@ -264,7 +264,7 @@ class CommentFormController extends EntityFormController { } /** - * Overrides Drupal\entity\EntityFormController::submit(). + * Overrides Drupal\Core\Entity\EntityFormController::submit(). */ public function submit(array $form, array &$form_state) { $comment = parent::submit($form, $form_state); @@ -328,7 +328,7 @@ class CommentFormController extends EntityFormController { } /** - * Overrides Drupal\entity\EntityFormController::save(). + * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { $node = node_load($form_state['values']['nid']); diff --git a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php index 5dcda40..26cc6e0 100644 --- a/core/modules/comment/lib/Drupal/comment/CommentStorageController.php +++ b/core/modules/comment/lib/Drupal/comment/CommentStorageController.php @@ -7,14 +7,14 @@ namespace Drupal\comment; -use Drupal\entity\EntityInterface; -use Drupal\entity\DatabaseStorageController; +use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\DatabaseStorageController; use LogicException; /** * Defines the controller class for comments. * - * This extends the Drupal\entity\DatabaseStorageController class, adding + * This extends the Drupal\Core\Entity\DatabaseStorageController class, adding * required special handling for comment entities. */ class CommentStorageController extends DatabaseStorageController { @@ -25,7 +25,7 @@ class CommentStorageController extends DatabaseStorageController { /** - * Overrides Drupal\entity\DatabaseStorageController::buildQuery(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::buildQuery(). */ protected function buildQuery($ids, $revision_id = FALSE) { $query = parent::buildQuery($ids, $revision_id); @@ -39,7 +39,7 @@ class CommentStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::attachLoad(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::attachLoad(). */ protected function attachLoad(&$comments, $load_revision = FALSE) { // Set up standard comment properties. @@ -53,7 +53,7 @@ class CommentStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::preSave(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::preSave(). * * @see comment_int_to_alphadecimal() * @see comment_alphadecimal_to_int() @@ -149,7 +149,7 @@ class CommentStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::postSave(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::postSave(). */ protected function postSave(EntityInterface $comment, $update) { $this->releaseThreadLock(); @@ -161,7 +161,7 @@ class CommentStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::postDelete(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::postDelete(). */ protected function postDelete($comments) { // Delete the comments' replies. diff --git a/core/modules/config/lib/Drupal/config/ConfigEntityBase.php b/core/modules/config/lib/Drupal/config/ConfigEntityBase.php deleted file mode 100644 index 921ab36..0000000 --- a/core/modules/config/lib/Drupal/config/ConfigEntityBase.php +++ /dev/null @@ -1,102 +0,0 @@ -id()) { - $this->originalID = $original_id; - } - } - - /** - * Implements ConfigEntityInterface::getOriginalID(). - */ - public function getOriginalID() { - return $this->originalID; - } - - /** - * Overrides Entity::isNew(). - * - * EntityInterface::enforceIsNew() is not supported by configuration entities, - * since each configuration entity is unique. - */ - final public function isNew() { - return !$this->id(); - } - - /** - * Overrides Entity::bundle(). - * - * EntityInterface::bundle() is not supported by configuration entities, since - * a configuration entity is a bundle. - */ - final public function bundle() { - return $this->entityType; - } - - /** - * Overrides Entity::get(). - * - * EntityInterface::get() implements support for fieldable entities, but - * configuration entities are not fieldable. - */ - public function get($property_name, $langcode = NULL) { - // @todo: Add support for translatable properties being not fields. - return isset($this->{$property_name}) ? $this->{$property_name} : NULL; - } - - /** - * Overrides Entity::set(). - * - * EntityInterface::set() implements support for fieldable entities, but - * configuration entities are not fieldable. - */ - public function set($property_name, $value, $langcode = NULL) { - // @todo: Add support for translatable properties being not fields. - $this->{$property_name} = $value; - } - - /** - * Helper callback for uasort() to sort configuration entities by weight and label. - */ - public static function sort($a, $b) { - $a_weight = isset($a->weight) ? $a->weight : 0; - $b_weight = isset($b->weight) ? $b->weight : 0; - if ($a_weight == $b_weight) { - $a_label = $a->label(); - $b_label = $b->label(); - return strnatcasecmp($a_label, $b_label); - } - return ($a_weight < $b_weight) ? -1 : 1; - } -} diff --git a/core/modules/config/lib/Drupal/config/ConfigEntityInterface.php b/core/modules/config/lib/Drupal/config/ConfigEntityInterface.php deleted file mode 100644 index ee4bb93..0000000 --- a/core/modules/config/lib/Drupal/config/ConfigEntityInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -entityType = $entityType; - $this->entityInfo = entity_get_info($entityType); - $this->hookLoadArguments = array(); - $this->idKey = $this->entityInfo['entity keys']['id']; - } - - /** - * Implements Drupal\entity\EntityStorageControllerInterface::resetCache(). - */ - public function resetCache(array $ids = NULL) { - // The configuration system is fast enough and/or implements its own - // (advanced) caching mechanism already. - } - - /** - * Implements Drupal\entity\EntityStorageControllerInterface::load(). - */ - public function load(array $ids = NULL) { - $entities = array(); - - // Create a new variable which is either a prepared version of the $ids - // array for later comparison with the entity cache, or FALSE if no $ids - // were passed. - $passed_ids = !empty($ids) ? array_flip($ids) : FALSE; - - // Load any remaining entities. This is the case if $ids is set to NULL (so - // we load all entities). - if ($ids === NULL || $ids) { - $queried_entities = $this->buildQuery($ids); - } - - // Pass all entities loaded from the database through $this->attachLoad(), - // which calls the - // entity type specific load callback, for example hook_node_type_load(). - if (!empty($queried_entities)) { - $this->attachLoad($queried_entities); - $entities += $queried_entities; - } - - // Ensure that the returned array is ordered the same as the original - // $ids array if this was passed in and remove any invalid ids. - if ($passed_ids) { - // Remove any invalid ids from the array. - $passed_ids = array_intersect_key($passed_ids, $entities); - foreach ($entities as $entity) { - $passed_ids[$entity->{$this->idKey}] = $entity; - } - $entities = $passed_ids; - } - - return $entities; - } - - /** - * Implements Drupal\entity\EntityStorageControllerInterface::loadRevision(). - */ - public function loadRevision($revision_id) { - return FALSE; - } - - /** - * Implements Drupal\entity\EntityStorageControllerInterface::loadByProperties(). - */ - public function loadByProperties(array $values = array()) { - return array(); - } - - /** - * Builds the query to load the entity. - * - * This has full revision support. For entities requiring special queries, - * the class can be extended, and the default query can be constructed by - * calling parent::buildQuery(). This is usually necessary when the object - * being loaded needs to be augmented with additional data from another - * table, such as loading node type into comments or vocabulary machine name - * into terms, however it can also support $conditions on different tables. - * See Drupal\comment\CommentStorageController::buildQuery() or - * Drupal\taxonomy\TermStorageController::buildQuery() for examples. - * - * @param $ids - * An array of entity IDs, or NULL to load all entities. - * @param $revision_id - * The ID of the revision to load, or FALSE if this query is asking for the - * most current revision(s). - * - * @return SelectQuery - * A SelectQuery object for loading the entity. - */ - protected function buildQuery($ids, $revision_id = FALSE) { - $config_class = $this->entityInfo['entity class']; - $prefix = $this->entityInfo['config prefix'] . '.'; - - // Load all of the configuration entities. - if ($ids === NULL) { - $names = drupal_container()->get('config.storage')->listAll($prefix); - $result = array(); - foreach ($names as $name) { - $config = config($name); - $result[$config->get($this->idKey)] = new $config_class($config->get(), $this->entityType); - } - return $result; - } - else { - $result = array(); - foreach ($ids as $id) { - // Add the prefix to the ID to serve as the configuration object name. - $config = config($prefix . $id); - if (!$config->isNew()) { - $result[$id] = new $config_class($config->get(), $this->entityType); - } - } - return $result; - } - } - - /** - * Attaches data to entities upon loading. - * - * This will attach fields, if the entity is fieldable. It calls - * hook_entity_load() for modules which need to add data to all entities. - * It also calls hook_TYPE_load() on the loaded entities. For example - * hook_node_load() or hook_user_load(). If your hook_TYPE_load() - * expects special parameters apart from the queried entities, you can set - * $this->hookLoadArguments prior to calling the method. - * See Drupal\node\NodeStorageController::attachLoad() for an example. - * - * @param $queried_entities - * Associative array of query results, keyed on the entity ID. - * @param $revision_id - * ID of the revision that was loaded, or FALSE if the most current revision - * was loaded. - */ - protected function attachLoad(&$queried_entities, $revision_id = FALSE) { - // Call hook_entity_load(). - foreach (module_implements('entity_load') as $module) { - $function = $module . '_entity_load'; - $function($queried_entities, $this->entityType); - } - // Call hook_TYPE_load(). The first argument for hook_TYPE_load() are - // always the queried entities, followed by additional arguments set in - // $this->hookLoadArguments. - $args = array_merge(array($queried_entities), $this->hookLoadArguments); - foreach (module_implements($this->entityType . '_load') as $module) { - call_user_func_array($module . '_' . $this->entityType . '_load', $args); - } - } - - /** - * Implements Drupal\entity\EntityStorageControllerInterface::create(). - */ - public function create(array $values) { - $class = isset($this->entityInfo['entity class']) ? $this->entityInfo['entity class'] : 'Drupal\entity\Entity'; - - $entity = new $class($values, $this->entityType); - - // Assign a new UUID if there is none yet. - if (!isset($entity->{$this->uuidKey})) { - $uuid = new Uuid(); - $entity->{$this->uuidKey} = $uuid->generate(); - } - - return $entity; - } - - /** - * Implements Drupal\entity\EntityStorageControllerInterface::delete(). - */ - public function delete($ids) { - $entities = $ids ? $this->load($ids) : FALSE; - if (!$entities) { - // If no IDs or invalid IDs were passed, do nothing. - return; - } - - $this->preDelete($entities); - foreach ($entities as $id => $entity) { - $this->invokeHook('predelete', $entity); - } - - foreach ($entities as $id => $entity) { - $config = config($this->entityInfo['config prefix'] . '.' . $entity->id()); - $config->delete(); - } - - $this->postDelete($entities); - foreach ($entities as $id => $entity) { - $this->invokeHook('delete', $entity); - } - } - - /** - * Implements Drupal\entity\EntityStorageControllerInterface::save(). - */ - public function save(EntityInterface $entity) { - $prefix = $this->entityInfo['config prefix'] . '.'; - - // Load the stored entity, if any. - if ($entity->getOriginalID()) { - $id = $entity->getOriginalID(); - } - else { - $id = $entity->id(); - } - $config = config($prefix . $id); - $config->setName($prefix . $entity->id()); - - if (!$config->isNew() && !isset($entity->original)) { - $entity->original = entity_load_unchanged($this->entityType, $id); - } - - $this->preSave($entity); - $this->invokeHook('presave', $entity); - - // Configuration objects do not have a schema. Extract all key names from - // class properties. - $class_info = new \ReflectionClass($entity); - $properties = $class_info->getProperties(\ReflectionProperty::IS_PUBLIC); - foreach ($properties as $property) { - $name = $property->getName(); - $config->set($name, $entity->$name); - } - - if (!$config->isNew()) { - $return = SAVED_NEW; - $config->save(); - $this->postSave($entity, TRUE); - $this->invokeHook('update', $entity); - } - else { - $return = SAVED_UPDATED; - $config->save(); - $entity->enforceIsNew(FALSE); - $this->postSave($entity, FALSE); - $this->invokeHook('insert', $entity); - } - - unset($entity->original); - - return $return; - } - - /** - * Acts on an entity before the presave hook is invoked. - * - * Used before the entity is saved and before invoking the presave hook. - */ - protected function preSave(EntityInterface $entity) { - } - - /** - * Acts on a saved entity before the insert or update hook is invoked. - * - * Used after the entity is saved, but before invoking the insert or update - * hook. - * - * @param $update - * (bool) TRUE if the entity has been updated, or FALSE if it has been - * inserted. - */ - protected function postSave(EntityInterface $entity, $update) { - // Delete the original configuration entity, in case the entity ID was - // renamed. - if ($update && !empty($entity->original) && $entity->{$this->idKey} !== $entity->original->{$this->idKey}) { - // @todo This should just delete the original config object without going - // through the API, no? - $entity->original->delete(); - } - } - - /** - * Acts on entities before they are deleted. - * - * Used before the entities are deleted and before invoking the delete hook. - */ - protected function preDelete($entities) { - } - - /** - * Acts on deleted entities before the delete hook is invoked. - * - * Used after the entities are deleted but before invoking the delete hook. - */ - protected function postDelete($entities) { - } - - /** - * Invokes a hook on behalf of the entity. - * - * @param $hook - * One of 'presave', 'insert', 'update', 'predelete', or 'delete'. - * @param $entity - * The entity object. - */ - protected function invokeHook($hook, EntityInterface $entity) { - // Invoke the hook. - module_invoke_all($this->entityType . '_' . $hook, $entity); - // Invoke the respective entity-level hook. - module_invoke_all('entity_' . $hook, $entity, $this->entityType); - } -} diff --git a/core/modules/config/tests/config_test/config_test.module b/core/modules/config/tests/config_test/config_test.module index 44d4087..180f111 100644 --- a/core/modules/config/tests/config_test/config_test.module +++ b/core/modules/config/tests/config_test/config_test.module @@ -177,7 +177,7 @@ function config_test_delete($id) { */ function config_test_list_page() { $entities = entity_load_multiple('config_test'); - uasort($entities, 'Drupal\config\ConfigEntityBase::sort'); + uasort($entities, 'Drupal\Core\Entity\ConfigEntityBase::sort'); $rows = array(); foreach ($entities as $config_test) { diff --git a/core/modules/config/tests/config_test/lib/Drupal/config_test/ConfigTest.php b/core/modules/config/tests/config_test/lib/Drupal/config_test/ConfigTest.php index 3f6b86a..40134e4 100644 --- a/core/modules/config/tests/config_test/lib/Drupal/config_test/ConfigTest.php +++ b/core/modules/config/tests/config_test/lib/Drupal/config_test/ConfigTest.php @@ -7,7 +7,7 @@ namespace Drupal\config_test; -use Drupal\config\ConfigEntityBase; +use Drupal\Core\Entity\ConfigEntityBase; /** * Defines the ConfigTest configuration entity. diff --git a/core/modules/entity/entity.api.php b/core/modules/entity/entity.api.php index 11e99d1..5afd67c 100644 --- a/core/modules/entity/entity.api.php +++ b/core/modules/entity/entity.api.php @@ -22,11 +22,11 @@ * properties of those types that the system needs to know about: * - label: The human-readable name of the type. * - entity class: The name of the entity class, defaults to - * Drupal\entity\Entity. The entity class must implement EntityInterface. + * Drupal\Core\Entity\Entity. The entity class must implement EntityInterface. * - controller class: The name of the class that is used to load the objects. * The class has to implement the - * Drupal\entity\EntityStorageControllerInterface interface. Leave blank - * to use the Drupal\entity\DatabaseStorageController implementation. + * Drupal\Core\Entity\EntityStorageControllerInterface interface. Leave blank + * to use the Drupal\Core\Entity\DatabaseStorageController implementation. * - form controller class: An associative array where the keys are the names * of the different form operations (such as creation, editing or deletion) * and the values are the names of the controller classes. To facilitate @@ -34,9 +34,9 @@ * different operations, the name of the operation is passed also to the * constructor of the form controller class. This way, one class can be used * for multiple entity forms. - * - base table: (used by Drupal\entity\DatabaseStorageController) The + * - base table: (used by Drupal\Core\Entity\DatabaseStorageController) The * name of the entity type's base table. - * - static cache: (used by Drupal\entity\DatabaseStorageController) + * - static cache: (used by Drupal\Core\Entity\DatabaseStorageController) * FALSE to disable static caching of entities during a page request. * Defaults to TRUE. * - field cache: (used by Field API loading and saving of field data) FALSE @@ -57,7 +57,7 @@ * (see below). If more complex logic is needed to determine the label of * an entity, you can instead specify a callback function here, which will * be called to determine the entity label. See also the - * Drupal\entity\Entity::label() method, which implements this logic. + * Drupal\Core\Entity\Entity::label() method, which implements this logic. * - fieldable: Set to TRUE if you want your entity type to be fieldable. * - translation: An associative array of modules registered as field * translation handlers. Array keys are the module names, array values @@ -229,7 +229,7 @@ function hook_entity_info() { */ function hook_entity_info_alter(&$entity_info) { // Set the controller class for nodes to an alternate implementation of the - // Drupal\entity\EntityStorageControllerInterface interface. + // Drupal\Core\Entity\EntityStorageControllerInterface interface. $entity_info['node']['controller class'] = 'Drupal\mymodule\MyCustomNodeStorageController'; } @@ -253,20 +253,20 @@ function hook_entity_load($entities, $entity_type) { /** * Act on an entity before it is about to be created or updated. * - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The entity object. */ -function hook_entity_presave(Drupal\entity\EntityInterface $entity) { +function hook_entity_presave(Drupal\Core\Entity\EntityInterface $entity) { $entity->changed = REQUEST_TIME; } /** * Act on entities when inserted. * - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The entity object. */ -function hook_entity_insert(Drupal\entity\EntityInterface $entity) { +function hook_entity_insert(Drupal\Core\Entity\EntityInterface $entity) { // Insert the new entity into a fictional table of all entities. db_insert('example_entity') ->fields(array( @@ -281,10 +281,10 @@ function hook_entity_insert(Drupal\entity\EntityInterface $entity) { /** * Act on entities when updated. * - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The entity object. */ -function hook_entity_update(Drupal\entity\EntityInterface $entity) { +function hook_entity_update(Drupal\Core\Entity\EntityInterface $entity) { // Update the entity's entry in a fictional table of all entities. db_update('example_entity') ->fields(array( @@ -300,10 +300,10 @@ function hook_entity_update(Drupal\entity\EntityInterface $entity) { * * This hook runs after the entity type-specific predelete hook. * - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The entity object for the entity that is about to be deleted. */ -function hook_entity_predelete(Drupal\entity\EntityInterface $entity) { +function hook_entity_predelete(Drupal\Core\Entity\EntityInterface $entity) { // Count references to this entity in a custom table before they are removed // upon entity deletion. $id = $entity->id(); @@ -329,10 +329,10 @@ function hook_entity_predelete(Drupal\entity\EntityInterface $entity) { * * This hook runs after the entity type-specific delete hook. * - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The entity object for the entity that has been deleted. */ -function hook_entity_delete(Drupal\entity\EntityInterface $entity) { +function hook_entity_delete(Drupal\Core\Entity\EntityInterface $entity) { // Delete the entity's entry from a fictional table of all entities. db_delete('example_entity') ->condition('type', $entity->entityType()) @@ -341,9 +341,9 @@ function hook_entity_delete(Drupal\entity\EntityInterface $entity) { } /** - * Alter or execute an Drupal\entity\EntityFieldQuery. + * Alter or execute an Drupal\Core\Entity\EntityFieldQuery. * - * @param Drupal\entity\EntityFieldQuery $query + * @param Drupal\Core\Entity\EntityFieldQuery $query * An EntityFieldQuery. One of the most important properties to be changed is * EntityFieldQuery::executeCallback. If this is set to an existing function, * this function will get the query as its single argument and its result @@ -362,14 +362,14 @@ function hook_entity_delete(Drupal\entity\EntityInterface $entity) { * ($query->pager && $query->count), allowing the driver to return 0 from * the count query and disable the pager. */ -function hook_entity_query_alter(Drupal\entity\EntityFieldQuery $query) { +function hook_entity_query_alter(Drupal\Core\Entity\EntityFieldQuery $query) { $query->executeCallback = 'my_module_query_callback'; } /** * Act on entities being assembled before rendering. * - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The entity object. * @param $view_mode * The view mode the entity is rendered in. @@ -385,7 +385,7 @@ function hook_entity_query_alter(Drupal\entity\EntityFieldQuery $query) { * @see hook_node_view() * @see hook_user_view() */ -function hook_entity_view(Drupal\entity\EntityInterface $entity, $view_mode, $langcode) { +function hook_entity_view(Drupal\Core\Entity\EntityInterface $entity, $view_mode, $langcode) { $entity->content['my_additional_field'] = array( '#markup' => $additional_field, '#weight' => 10, @@ -408,7 +408,7 @@ function hook_entity_view(Drupal\entity\EntityInterface $entity, $view_mode, $la * * @param $build * A renderable array representing the entity content. - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The entity object being rendered. * * @see hook_entity_view() @@ -417,7 +417,7 @@ function hook_entity_view(Drupal\entity\EntityInterface $entity, $view_mode, $la * @see hook_taxonomy_term_view_alter() * @see hook_user_view_alter() */ -function hook_entity_view_alter(&$build, Drupal\entity\EntityInterface $entity) { +function hook_entity_view_alter(&$build, Drupal\Core\Entity\EntityInterface $entity) { if ($build['#view_mode'] == 'full' && isset($build['an_additional_field'])) { // Change its weight. $build['an_additional_field']['#weight'] = -10; @@ -454,13 +454,13 @@ function hook_entity_prepare_view($entities, $entity_type) { * * @param string $view_mode * The view_mode that is to be used to display the entity. - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The entity that is being viewed. * @param array $context * Array with additional context information, currently only contains the * langcode the entity is viewed in. */ -function hook_entity_view_mode_alter(&$view_mode, Drupal\entity\EntityInterface $entity, $context) { +function hook_entity_view_mode_alter(&$view_mode, Drupal\Core\Entity\EntityInterface $entity, $context) { // For nodes, change the view mode when it is teaser. if ($entity->entityType() == 'node' && $view_mode == 'teaser') { $view_mode = 'my_custom_view_mode'; diff --git a/core/modules/entity/entity.module b/core/modules/entity/entity.module index 8bd2fc1..a43d234 100644 --- a/core/modules/entity/entity.module +++ b/core/modules/entity/entity.module @@ -6,10 +6,10 @@ */ use \InvalidArgumentException; -use Drupal\entity\EntityFieldQuery; -use Drupal\entity\EntityMalformedException; -use Drupal\entity\EntityStorageException; -use Drupal\entity\EntityInterface; +use Drupal\Core\Entity\EntityFieldQuery; +use Drupal\Core\Entity\EntityMalformedException; +use Drupal\Core\Entity\EntityStorageException; +use Drupal\Core\Entity\EntityInterface; /** * Implements hook_help(). @@ -72,10 +72,10 @@ function entity_get_info($entity_type = NULL) { foreach ($entity_info as $name => $data) { $entity_info[$name] += array( 'fieldable' => FALSE, - 'entity class' => 'Drupal\entity\Entity', - 'controller class' => 'Drupal\entity\DatabaseStorageController', + 'entity class' => 'Drupal\Core\Entity\Entity', + 'controller class' => 'Drupal\Core\Entity\DatabaseStorageController', 'form controller class' => array( - 'default' => 'Drupal\entity\EntityFormController', + 'default' => 'Drupal\Core\Entity\EntityFormController', ), 'static cache' => TRUE, 'field cache' => TRUE, @@ -99,7 +99,7 @@ function entity_get_info($entity_type = NULL) { $entity_info[$name]['bundles'] = array($name => array('label' => $entity_info[$name]['label'])); } // Prepare entity schema fields SQL info for - // Drupal\entity\DatabaseStorageControllerInterface::buildQuery(). + // Drupal\Core\Entity\DatabaseStorageControllerInterface::buildQuery(). if (isset($entity_info[$name]['base table'])) { $entity_info[$name]['schema_fields_sql']['base table'] = drupal_schema_fields_sql($entity_info[$name]['base table']); if (isset($entity_info[$name]['revision table'])) { @@ -140,14 +140,14 @@ function entity_info_cache_clear() { * @param bool $reset * Whether to reset the internal cache for the requested entity type. * - * @return Drupal\entity\EntityInterface + * @return Drupal\Core\Entity\EntityInterface * The entity object, or FALSE if there is no entity with the given id. * * @see hook_entity_info() * @see entity_load_multiple() - * @see Drupal\entity\EntityStorageControllerInterface - * @see Drupal\entity\DatabaseStorageController - * @see Drupal\entity\EntityFieldQuery + * @see Drupal\Core\Entity\EntityStorageControllerInterface + * @see Drupal\Core\Entity\DatabaseStorageController + * @see Drupal\Core\Entity\EntityFieldQuery */ function entity_load($entity_type, $id, $reset = FALSE) { $entities = entity_load_multiple($entity_type, array($id), $reset); @@ -162,13 +162,13 @@ function entity_load($entity_type, $id, $reset = FALSE) { * @param int $revision_id * The id of the entity to load. * - * @return Drupal\entity\EntityInterface + * @return Drupal\Core\Entity\EntityInterface * The entity object, or FALSE if there is no entity with the given revision * id. * * @see hook_entity_info() - * @see Drupal\entity\EntityStorageControllerInterface - * @see Drupal\entity\DatabaseStorageController + * @see Drupal\Core\Entity\EntityStorageControllerInterface + * @see Drupal\Core\Entity\DatabaseStorageController */ function entity_revision_load($entity_type, $revision_id) { return entity_get_controller($entity_type)->loadRevision($revision_id); @@ -189,7 +189,7 @@ function entity_revision_load($entity_type, $revision_id) { * @return EntityInterface|FALSE * The entity object, or FALSE if there is no entity with the given UUID. * - * @throws Drupal\entity\EntityStorageException + * @throws Drupal\Core\Entity\EntityStorageException * Thrown in case the requested entity type does not support UUIDs. * * @see hook_entity_info() @@ -217,12 +217,12 @@ function entity_load_by_uuid($entity_type, $uuid, $reset = FALSE) { * database access if loaded again during the same page request. * * The actual loading is done through a class that has to implement the - * Drupal\entity\EntityStorageControllerInterface interface. By default, - * Drupal\entity\DatabaseStorageController is used. Entity types can + * Drupal\Core\Entity\EntityStorageControllerInterface interface. By default, + * Drupal\Core\Entity\DatabaseStorageController is used. Entity types can * specify that a different class should be used by setting the * 'controller class' key in hook_entity_info(). These classes can either - * implement the Drupal\entity\EntityStorageControllerInterface interface, or, - * most commonly, extend the Drupal\entity\DatabaseStorageController + * implement the Drupal\Core\Entity\EntityStorageControllerInterface interface, or, + * most commonly, extend the Drupal\Core\Entity\DatabaseStorageController * class. See node_entity_info() and the NodeStorageController in node.module as * an example. * @@ -237,9 +237,9 @@ function entity_load_by_uuid($entity_type, $uuid, $reset = FALSE) { * An array of entity objects indexed by their ids. * * @see hook_entity_info() - * @see Drupal\entity\EntityStorageControllerInterface - * @see Drupal\entity\DatabaseStorageController - * @see Drupal\entity\EntityFieldQuery + * @see Drupal\Core\Entity\EntityStorageControllerInterface + * @see Drupal\Core\Entity\DatabaseStorageController + * @see Drupal\Core\Entity\EntityFieldQuery */ function entity_load_multiple($entity_type, array $ids = NULL, $reset = FALSE) { if ($reset) { @@ -307,7 +307,7 @@ function entity_delete_multiple($entity_type, $ids) { * An array of values to set, keyed by property name. If the entity type has * bundles the bundle key has to be specified. * - * @return Drupal\entity\EntityInterface + * @return Drupal\Core\Entity\EntityInterface * A new entity object. */ function entity_create($entity_type, array $values) { @@ -317,7 +317,7 @@ function entity_create($entity_type, array $values) { /** * Gets the entity controller class for an entity type. * - * @return Drupal\entity\EntityStorageControllerInterface + * @return Drupal\Core\Entity\EntityStorageControllerInterface */ function entity_get_controller($entity_type) { $controllers = &drupal_static(__FUNCTION__, array()); @@ -373,10 +373,10 @@ function entity_prepare_view($entity_type, $entities) { /** * Returns the label of an entity. * - * This is a wrapper for Drupal\entity\EntityInterface::label(). This function + * This is a wrapper for Drupal\Core\Entity\EntityInterface::label(). This function * should only be used as a callback, e.g. for menu title callbacks. * - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The entity for which to generate the label. * @param $langcode * (optional) The language code of the language that should be used for @@ -386,7 +386,7 @@ function entity_prepare_view($entity_type, $entities) { * @return * The label of the entity, or NULL if there is no label defined. * - * @see Drupal\entity\EntityInterface::label() + * @see Drupal\Core\Entity\EntityInterface::label() */ function entity_page_label(EntityInterface $entity, $langcode = NULL) { return $entity->label($langcode); @@ -410,7 +410,7 @@ function entity_page_label(EntityInterface $entity, $langcode = NULL) { * identifying the controlled form. Defaults to 'default' which is the usual * create/edit form. * - * @return Drupal\entity\EntityFormControllerInterface + * @return Drupal\Core\Entity\EntityFormControllerInterface * An entity form controller instance. */ function entity_form_controller($entity_type, $operation = 'default') { @@ -422,7 +422,7 @@ function entity_form_controller($entity_type, $operation = 'default') { } // If no controller is specified default to the base implementation. elseif (empty($info['form controller class']) && $operation == 'default') { - $class = 'Drupal\entity\EntityFormController'; + $class = 'Drupal\Core\Entity\EntityFormController'; } // If a non-existing operation has been specified stop. else { diff --git a/core/modules/entity/lib/Drupal/entity/ContentEntityInterface.php b/core/modules/entity/lib/Drupal/entity/ContentEntityInterface.php deleted file mode 100644 index dfafdca..0000000 --- a/core/modules/entity/lib/Drupal/entity/ContentEntityInterface.php +++ /dev/null @@ -1,15 +0,0 @@ -entityType = $entityType; - $this->entityInfo = entity_get_info($entityType); - $this->entityCache = array(); - $this->hookLoadArguments = array(); - $this->idKey = $this->entityInfo['entity keys']['id']; - - // Check if the entity type supports UUIDs. - if (!empty($this->entityInfo['entity keys']['uuid'])) { - $this->uuidKey = $this->entityInfo['entity keys']['uuid']; - } - else { - $this->uuidKey = FALSE; - } - - // Check if the entity type supports revisions. - if (!empty($this->entityInfo['entity keys']['revision'])) { - $this->revisionKey = $this->entityInfo['entity keys']['revision']; - $this->revisionTable = $this->entityInfo['revision table']; - } - else { - $this->revisionKey = FALSE; - } - - // Check if the entity type supports static caching of loaded entities. - $this->cache = !empty($this->entityInfo['static cache']); - } - - /** - * Implements Drupal\entity\EntityStorageControllerInterface::resetCache(). - */ - public function resetCache(array $ids = NULL) { - if (isset($ids)) { - foreach ($ids as $id) { - unset($this->entityCache[$id]); - } - } - else { - $this->entityCache = array(); - } - } - - /** - * Implements Drupal\entity\EntityStorageControllerInterface::load(). - */ - public function load(array $ids = NULL) { - $entities = array(); - - // Create a new variable which is either a prepared version of the $ids - // array for later comparison with the entity cache, or FALSE if no $ids - // were passed. The $ids array is reduced as items are loaded from cache, - // and we need to know if it's empty for this reason to avoid querying the - // database when all requested entities are loaded from cache. - $passed_ids = !empty($ids) ? array_flip($ids) : FALSE; - // Try to load entities from the static cache, if the entity type supports - // static caching. - if ($this->cache && $ids) { - $entities += $this->cacheGet($ids); - // If any entities were loaded, remove them from the ids still to load. - if ($passed_ids) { - $ids = array_keys(array_diff_key($passed_ids, $entities)); - } - } - - // Load any remaining entities from the database. This is the case if $ids - // is set to NULL (so we load all entities) or if there are any ids left to - // load. - if ($ids === NULL || $ids) { - // Build and execute the query. - $query_result = $this->buildQuery($ids)->execute(); - - if (!empty($this->entityInfo['entity class'])) { - // We provide the necessary arguments for PDO to create objects of the - // specified entity class. - // @see Drupal\entity\EntityInterface::__construct() - $query_result->setFetchMode(PDO::FETCH_CLASS, $this->entityInfo['entity class'], array(array(), $this->entityType)); - } - $queried_entities = $query_result->fetchAllAssoc($this->idKey); - } - - // Pass all entities loaded from the database through $this->attachLoad(), - // 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); - $entities += $queried_entities; - } - - if ($this->cache) { - // Add entities to the cache. - if (!empty($queried_entities)) { - $this->cacheSet($queried_entities); - } - } - - // Ensure that the returned array is ordered the same as the original - // $ids array if this was passed in and remove any invalid ids. - if ($passed_ids) { - // Remove any invalid ids from the array. - $passed_ids = array_intersect_key($passed_ids, $entities); - foreach ($entities as $entity) { - $passed_ids[$entity->{$this->idKey}] = $entity; - } - $entities = $passed_ids; - } - - return $entities; - } - - /** - * Implements Drupal\entity\EntityStorageControllerInterface::loadRevision(). - */ - public function loadRevision($revision_id) { - // Build and execute the query. - $query_result = $this->buildQuery(array(), $revision_id)->execute(); - - if (!empty($this->entityInfo['entity class'])) { - // We provide the necessary arguments for PDO to create objects of the - // specified entity class. - // @see Drupal\entity\EntityInterface::__construct() - $query_result->setFetchMode(PDO::FETCH_CLASS, $this->entityInfo['entity class'], array(array(), $this->entityType)); - } - $queried_entities = $query_result->fetchAllAssoc($this->idKey); - - // Pass the loaded entities from the database through $this->attachLoad(), - // 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); - } - return reset($queried_entities); - } - - /** - * Implements Drupal\entity\EntityStorageControllerInterface::loadByProperties(). - */ - public function loadByProperties(array $values = array()) { - // Build a query to fetch the entity IDs. - $entity_query = new EntityFieldQuery(); - $entity_query->entityCondition('entity_type', $this->entityType); - $this->buildPropertyQuery($entity_query, $values); - $result = $entity_query->execute(); - - if (empty($result[$this->entityType])) { - return array(); - } - // Load and return the found entities. - return $this->load(array_keys($result[$this->entityType])); - } - - /** - * Builds an entity query. - * - * @param Drupal\entity\EntityFieldQuery $entity_query - * EntityFieldQuery instance. - * @param array $values - * An associative array of properties of the entity, where the keys are the - * property names and the values are the values those properties must have. - */ - protected function buildPropertyQuery(EntityFieldQuery $entity_query, array $values) { - foreach ($values as $name => $value) { - $entity_query->propertyCondition($name, $value); - } - } - - /** - * Builds the query to load the entity. - * - * This has full revision support. For entities requiring special queries, - * the class can be extended, and the default query can be constructed by - * calling parent::buildQuery(). This is usually necessary when the object - * being loaded needs to be augmented with additional data from another - * table, such as loading node type into comments or vocabulary machine name - * into terms, however it can also support $conditions on different tables. - * See Drupal\comment\CommentStorageController::buildQuery() or - * Drupal\taxonomy\TermStorageController::buildQuery() for examples. - * - * @param array|null $ids - * An array of entity IDs, or NULL to load all entities. - * @param $revision_id - * The ID of the revision to load, or FALSE if this query is asking for the - * most current revision(s). - * - * @return SelectQuery - * A SelectQuery object for loading the entity. - */ - protected function buildQuery($ids, $revision_id = FALSE) { - $query = db_select($this->entityInfo['base table'], 'base'); - - $query->addTag($this->entityType . '_load_multiple'); - - 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) { - // 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; - } - - /** - * Attaches data to entities upon loading. - * - * This will attach fields, if the entity is fieldable. It calls - * hook_entity_load() for modules which need to add data to all entities. - * It also calls hook_TYPE_load() on the loaded entities. For example - * hook_node_load() or hook_user_load(). If your hook_TYPE_load() - * expects special parameters apart from the queried entities, you can set - * $this->hookLoadArguments prior to calling the method. - * See Drupal\node\NodeStorageController::attachLoad() for an example. - * - * @param $queried_entities - * Associative array of query results, keyed on the entity ID. - * @param $load_revision - * (optional) TRUE if the revision should be loaded, defaults to FALSE. - */ - protected function attachLoad(&$queried_entities, $load_revision = FALSE) { - // Attach fields. - if ($this->entityInfo['fieldable']) { - if ($load_revision) { - field_attach_load_revision($this->entityType, $queried_entities); - } - else { - field_attach_load($this->entityType, $queried_entities); - } - } - - // Call hook_entity_load(). - foreach (module_implements('entity_load') as $module) { - $function = $module . '_entity_load'; - $function($queried_entities, $this->entityType); - } - // Call hook_TYPE_load(). The first argument for hook_TYPE_load() are - // always the queried entities, followed by additional arguments set in - // $this->hookLoadArguments. - $args = array_merge(array($queried_entities), $this->hookLoadArguments); - foreach (module_implements($this->entityType . '_load') as $module) { - call_user_func_array($module . '_' . $this->entityType . '_load', $args); - } - } - - /** - * Gets entities from the static cache. - * - * @param $ids - * If not empty, return entities that match these IDs. - * - * @return - * Array of entities from the entity cache. - */ - protected function cacheGet($ids) { - $entities = array(); - // Load any available entities from the internal cache. - if (!empty($this->entityCache)) { - $entities += array_intersect_key($this->entityCache, array_flip($ids)); - } - return $entities; - } - - /** - * Stores entities in the static entity cache. - * - * @param $entities - * Entities to store in the cache. - */ - protected function cacheSet($entities) { - $this->entityCache += $entities; - } - - /** - * Implements Drupal\entity\EntityStorageControllerInterface::create(). - */ - public function create(array $values) { - $class = isset($this->entityInfo['entity class']) ? $this->entityInfo['entity class'] : 'Drupal\entity\Entity'; - - $entity = new $class($values, $this->entityType); - - // Assign a new UUID if there is none yet. - if ($this->uuidKey && !isset($entity->{$this->uuidKey})) { - $uuid = new Uuid(); - $entity->{$this->uuidKey} = $uuid->generate(); - } - - return $entity; - } - - /** - * Implements Drupal\entity\EntityStorageControllerInterface::delete(). - */ - public function delete($ids) { - $entities = $ids ? $this->load($ids) : FALSE; - if (!$entities) { - // If no IDs or invalid IDs were passed, do nothing. - return; - } - $transaction = db_transaction(); - - try { - $this->preDelete($entities); - foreach ($entities as $id => $entity) { - $this->invokeHook('predelete', $entity); - } - $ids = array_keys($entities); - - db_delete($this->entityInfo['base table']) - ->condition($this->idKey, $ids, 'IN') - ->execute(); - // Reset the cache as soon as the changes have been applied. - $this->resetCache($ids); - - $this->postDelete($entities); - foreach ($entities as $id => $entity) { - $this->invokeHook('delete', $entity); - } - // Ignore slave server temporarily. - db_ignore_slave(); - } - catch (Exception $e) { - $transaction->rollback(); - watchdog_exception($this->entityType, $e); - throw new EntityStorageException($e->getMessage, $e->getCode, $e); - } - } - - /** - * Implements Drupal\entity\EntityStorageControllerInterface::save(). - */ - public function save(EntityInterface $entity) { - $transaction = db_transaction(); - try { - // Load the stored entity, if any. - if (!$entity->isNew() && !isset($entity->original)) { - $entity->original = entity_load_unchanged($this->entityType, $entity->id()); - } - - $this->preSave($entity); - $this->invokeHook('presave', $entity); - - if (!$entity->isNew()) { - $return = drupal_write_record($this->entityInfo['base table'], $entity, $this->idKey); - $this->resetCache(array($entity->{$this->idKey})); - $this->postSave($entity, TRUE); - $this->invokeHook('update', $entity); - } - else { - $return = drupal_write_record($this->entityInfo['base table'], $entity); - // Reset general caches, but keep caches specific to certain entities. - $this->resetCache(array()); - - $entity->enforceIsNew(FALSE); - $this->postSave($entity, FALSE); - $this->invokeHook('insert', $entity); - } - - // Ignore slave server temporarily. - db_ignore_slave(); - unset($entity->original); - - return $return; - } - catch (Exception $e) { - $transaction->rollback(); - watchdog_exception($this->entityType, $e); - throw new EntityStorageException($e->getMessage(), $e->getCode(), $e); - } - } - - /** - * Acts on an entity before the presave hook is invoked. - * - * Used before the entity is saved and before invoking the presave hook. - */ - protected function preSave(EntityInterface $entity) { } - - /** - * Acts on a saved entity before the insert or update hook is invoked. - * - * Used after the entity is saved, but before invoking the insert or update - * hook. - * - * @param $update - * (bool) TRUE if the entity has been updated, or FALSE if it has been - * inserted. - */ - protected function postSave(EntityInterface $entity, $update) { } - - /** - * Acts on entities before they are deleted. - * - * Used before the entities are deleted and before invoking the delete hook. - */ - protected function preDelete($entities) { } - - /** - * Acts on deleted entities before the delete hook is invoked. - * - * Used after the entities are deleted but before invoking the delete hook. - */ - protected function postDelete($entities) { } - - /** - * Invokes a hook on behalf of the entity. - * - * @param $hook - * One of 'presave', 'insert', 'update', 'predelete', or 'delete'. - * @param $entity - * The entity object. - */ - protected function invokeHook($hook, EntityInterface $entity) { - if (!empty($this->entityInfo['fieldable']) && function_exists($function = 'field_attach_' . $hook)) { - $function($this->entityType, $entity); - } - // Invoke the hook. - module_invoke_all($this->entityType . '_' . $hook, $entity); - // Invoke the respective entity-level hook. - module_invoke_all('entity_' . $hook, $entity, $this->entityType); - } -} diff --git a/core/modules/entity/lib/Drupal/entity/Entity.php b/core/modules/entity/lib/Drupal/entity/Entity.php deleted file mode 100644 index 7e5d175..0000000 --- a/core/modules/entity/lib/Drupal/entity/Entity.php +++ /dev/null @@ -1,290 +0,0 @@ -entityType = $entity_type; - // Set initial values. - foreach ($values as $key => $value) { - $this->$key = $value; - } - } - - /** - * Implements EntityInterface::id(). - */ - public function id() { - return isset($this->id) ? $this->id : NULL; - } - - /** - * Implements EntityInterface::uuid(). - */ - public function uuid() { - return isset($this->uuid) ? $this->uuid : NULL; - } - - /** - * Implements EntityInterface::isNew(). - */ - public function isNew() { - return !empty($this->enforceIsNew) || !$this->id(); - } - - /** - * Implements EntityInterface::enforceIsNew(). - */ - public function enforceIsNew($value = TRUE) { - $this->enforceIsNew = $value; - } - - /** - * Implements EntityInterface::entityType(). - */ - public function entityType() { - return $this->entityType; - } - - /** - * Implements EntityInterface::bundle(). - */ - public function bundle() { - return $this->entityType; - } - - /** - * Implements EntityInterface::label(). - */ - public function label($langcode = NULL) { - $label = NULL; - $entity_info = $this->entityInfo(); - if (isset($entity_info['label callback']) && function_exists($entity_info['label callback'])) { - $label = $entity_info['label callback']($this->entityType, $this, $langcode); - } - elseif (!empty($entity_info['entity keys']['label']) && isset($this->{$entity_info['entity keys']['label']})) { - $label = $this->{$entity_info['entity keys']['label']}; - } - return $label; - } - - /** - * Implements EntityInterface::uri(). - */ - public function uri() { - $bundle = $this->bundle(); - // A bundle-specific callback takes precedence over the generic one for the - // entity type. - $entity_info = $this->entityInfo(); - if (isset($entity_info['bundles'][$bundle]['uri callback'])) { - $uri_callback = $entity_info['bundles'][$bundle]['uri callback']; - } - elseif (isset($entity_info['uri callback'])) { - $uri_callback = $entity_info['uri callback']; - } - else { - return NULL; - } - - // Invoke the callback to get the URI. If there is no callback, return NULL. - if (isset($uri_callback) && function_exists($uri_callback)) { - $uri = $uri_callback($this); - // Pass the entity data to url() so that alter functions do not need to - // look up this entity again. - $uri['options']['entity_type'] = $this->entityType; - $uri['options']['entity'] = $this; - return $uri; - } - } - - /** - * Implements EntityInterface::language(). - */ - public function language() { - return !empty($this->langcode) ? language_load($this->langcode) : new Language(array('langcode' => LANGUAGE_NOT_SPECIFIED)); - } - - /** - * Implements EntityInterface::translations(). - */ - public function translations() { - $languages = array(); - $entity_info = $this->entityInfo(); - if ($entity_info['fieldable'] && ($default_language = $this->language())) { - // Go through translatable properties and determine all languages for - // which translated values are available. - foreach (field_info_instances($this->entityType, $this->bundle()) as $field_name => $instance) { - $field = field_info_field($field_name); - if (field_is_translatable($this->entityType, $field) && isset($this->$field_name)) { - foreach ($this->$field_name as $langcode => $value) { - $languages[$langcode] = TRUE; - } - } - } - // Remove the default language from the translations. - unset($languages[$default_language->langcode]); - $languages = array_intersect_key(language_list(), $languages); - } - return $languages; - } - - /** - * Implements EntityInterface::get(). - */ - public function get($property_name, $langcode = NULL) { - // Handle fields. - $entity_info = $this->entityInfo(); - if ($entity_info['fieldable'] && field_info_instance($this->entityType, $property_name, $this->bundle())) { - $field = field_info_field($property_name); - $langcode = $this->getFieldLangcode($field, $langcode); - return isset($this->{$property_name}[$langcode]) ? $this->{$property_name}[$langcode] : NULL; - } - else { - // Handle properties being not fields. - // @todo: Add support for translatable properties being not fields. - return isset($this->{$property_name}) ? $this->{$property_name} : NULL; - } - } - - /** - * Implements EntityInterface::set(). - */ - public function set($property_name, $value, $langcode = NULL) { - // Handle fields. - $entity_info = $this->entityInfo(); - if ($entity_info['fieldable'] && field_info_instance($this->entityType, $property_name, $this->bundle())) { - $field = field_info_field($property_name); - $langcode = $this->getFieldLangcode($field, $langcode); - $this->{$property_name}[$langcode] = $value; - } - else { - // Handle properties being not fields. - // @todo: Add support for translatable properties being not fields. - $this->{$property_name} = $value; - } - } - - /** - * Determines the language code to use for accessing a field value in a certain language. - */ - protected function getFieldLangcode($field, $langcode = NULL) { - // Only apply the given langcode if the entity is language-specific. - // Otherwise translatable fields are handled as non-translatable fields. - if (field_is_translatable($this->entityType, $field) && ($default_language = $this->language()) && !language_is_locked($this->langcode)) { - // For translatable fields the values in default language are stored using - // the language code of the default language. - return isset($langcode) ? $langcode : $default_language->langcode; - } - else { - // If there is a langcode defined for this field, just return it. Otherwise - // return LANGUAGE_NOT_SPECIFIED. - return (isset($this->langcode) ? $this->langcode : LANGUAGE_NOT_SPECIFIED); - } - } - - /** - * Implements EntityInterface::save(). - */ - public function save() { - return entity_get_controller($this->entityType)->save($this); - } - - /** - * Implements EntityInterface::delete(). - */ - public function delete() { - if (!$this->isNew()) { - entity_get_controller($this->entityType)->delete(array($this->id())); - } - } - - /** - * Implements EntityInterface::createDuplicate(). - */ - public function createDuplicate() { - $duplicate = clone $this; - $entity_info = $this->entityInfo(); - $this->{$entity_info['entity keys']['id']} = NULL; - - // Check if the entity type supports UUIDs and generate a new one if so. - if (!empty($entity_info['entity keys']['uuid'])) { - $uuid = new Uuid(); - $duplicate->{$entity_info['entity keys']['uuid']} = $uuid->generate(); - } - return $duplicate; - } - - /** - * Implements EntityInterface::entityInfo(). - */ - public function entityInfo() { - return entity_get_info($this->entityType); - } - - /** - * Implements Drupal\entity\EntityInterface::getRevisionId(). - */ - public function getRevisionId() { - return NULL; - } - - /** - * Implements Drupal\entity\EntityInterface::isDefaultRevision(). - */ - public function isDefaultRevision($new_value = NULL) { - $return = $this->isDefaultRevision; - if (isset($new_value)) { - $this->isDefaultRevision = (bool) $new_value; - } - return $return; - } - -} diff --git a/core/modules/entity/lib/Drupal/entity/EntityFieldQuery.php b/core/modules/entity/lib/Drupal/entity/EntityFieldQuery.php deleted file mode 100644 index fc283fc..0000000 --- a/core/modules/entity/lib/Drupal/entity/EntityFieldQuery.php +++ /dev/null @@ -1,964 +0,0 @@ -changed), field values, and generic entity meta data (bundle, - * entity type, entity id, and revision ID). It is not possible to query across - * multiple entity types. For example, there is no facility to find published - * nodes written by users created in the last hour, as this would require - * querying both node->status and user->created. - * - * Normally we would not want to have public properties on the object, as that - * allows the object's state to become inconsistent too easily. However, this - * class's standard use case involves primarily code that does need to have - * direct access to the collected properties in order to handle alternate - * execution routines. We therefore use public properties for simplicity. Note - * that code that is simply creating and running a field query should still use - * the appropriate methods to add conditions on the query. - * - * Storage engines are not required to support every type of query. By default, - * an EntityFieldQueryException will be raised if an unsupported condition is - * specified or if the query has field conditions or sorts that are stored in - * different field storage engines. However, this logic can be overridden in - * hook_entity_query_alter(). - * - * Also note that this query does not automatically respect entity access - * restrictions. Node access control is performed by the SQL storage engine but - * other storage engines might not do this. - */ -class EntityFieldQuery { - - /** - * Indicates that both deleted and non-deleted fields should be returned. - * - * @see Drupal\entity\EntityFieldQuery::deleted() - */ - const RETURN_ALL = NULL; - - /** - * TRUE if the query has already been altered, FALSE if it hasn't. - * - * Used in alter hooks to check for cloned queries that have already been - * altered prior to the clone (for example, the pager count query). - * - * @var boolean - */ - public $altered = FALSE; - - /** - * Associative array of entity-generic metadata conditions. - * - * @var array - * - * @see Drupal\entity\EntityFieldQuery::entityCondition() - */ - public $entityConditions = array(); - - /** - * List of field conditions. - * - * @var array - * - * @see Drupal\entity\EntityFieldQuery::fieldCondition() - */ - public $fieldConditions = array(); - - /** - * List of field meta conditions (language and delta). - * - * Field conditions operate on columns specified by hook_field_schema(), - * the meta conditions operate on columns added by the system: delta - * and language. These can not be mixed with the field conditions because - * field columns can have any name including delta and language. - * - * @var array - * - * @see Drupal\entity\EntityFieldQuery::fieldLanguageCondition() - * @see Drupal\entity\EntityFieldQuery::fieldDeltaCondition() - */ - public $fieldMetaConditions = array(); - - /** - * List of property conditions. - * - * @var array - * - * @see Drupal\entity\EntityFieldQuery::propertyCondition() - */ - public $propertyConditions = array(); - - /** - * List of order clauses. - * - * @var array - */ - public $order = array(); - - /** - * The query range. - * - * @var array - * - * @see Drupal\entity\EntityFieldQuery::range() - */ - public $range = array(); - - /** - * The query pager data. - * - * @var array - * - * @see Drupal\entity\EntityFieldQuery::pager() - */ - public $pager = array(); - - /** - * Query behavior for deleted data. - * - * TRUE to return only deleted data, FALSE to return only non-deleted data, - * EntityFieldQuery::RETURN_ALL to return everything. - * - * @see Drupal\entity\EntityFieldQuery::deleted() - */ - public $deleted = FALSE; - - /** - * A list of field arrays used. - * - * Field names passed to EntityFieldQuery::fieldCondition() and - * EntityFieldQuery::fieldOrderBy() are run through field_info_field() before - * stored in this array. This way, the elements of this array are field - * arrays. - * - * @var array - */ - public $fields = array(); - - /** - * TRUE if this is a count query, FALSE if it isn't. - * - * @var boolean - */ - public $count = FALSE; - - /** - * Flag indicating whether this is querying current or all revisions. - * - * @var int - * - * @see Drupal\entity\EntityFieldQuery::age() - */ - public $age = FIELD_LOAD_CURRENT; - - /** - * A list of the tags added to this query. - * - * @var array - * - * @see Drupal\entity\EntityFieldQuery::addTag() - */ - public $tags = array(); - - /** - * A list of metadata added to this query. - * - * @var array - * - * @see Drupal\entity\EntityFieldQuery::addMetaData() - */ - public $metaData = array(); - - /** - * The ordered results. - * - * @var array - * - * @see Drupal\entity\EntityFieldQuery::execute(). - */ - public $orderedResults = array(); - - /** - * The method executing the query, if it is overriding the default. - * - * @var string - * - * @see Drupal\entity\EntityFieldQuery::execute() - */ - public $executeCallback = ''; - - /** - * Adds a condition on entity-generic metadata. - * - * If the overall query contains only entity conditions or ordering, or if - * there are property conditions, then specifying the entity type is - * mandatory. If there are field conditions or ordering but no property - * conditions or ordering, then specifying an entity type is optional. While - * the field storage engine might support field conditions on more than one - * entity type, there is no way to query across multiple entity base tables by - * default. To specify the entity type, pass in 'entity_type' for $name, - * the type as a string for $value, and no $operator (it's disregarded). - * - * 'bundle', 'revision_id' and 'entity_id' have no such restrictions. - * - * Note: The "comment" entity type does not support bundle conditions. - * - * @param $name - * 'entity_type', 'bundle', 'revision_id' or 'entity_id'. - * @param $value - * The value for $name. In most cases, this is a scalar. For more complex - * options, it is an array. The meaning of each element in the array is - * dependent on $operator. - * @param $operator - * Possible values: - * - '=', '<>', '>', '>=', '<', '<=', 'STARTS_WITH', 'CONTAINS': These - * operators expect $value to be a literal of the same type as the - * column. - * - 'IN', 'NOT IN': These operators expect $value to be an array of - * literals of the same type as the column. - * - 'BETWEEN': This operator expects $value to be an array of two literals - * of the same type as the column. - * The operator can be omitted, and will default to 'IN' if the value is an - * array, or to '=' otherwise. - * - * @return Drupal\entity\EntityFieldQuery - * The called object. - */ - public function entityCondition($name, $value, $operator = NULL) { - $this->entityConditions[$name] = array( - 'value' => $value, - 'operator' => $operator, - ); - return $this; - } - - /** - * Adds a condition on field values. - * - * Note that entities with empty field values will be excluded from the - * EntityFieldQuery results when using this method. - * - * @param $field - * Either a field name or a field array. - * @param $column - * The column that should hold the value to be matched. - * @param $value - * The value to test the column value against. - * @param $operator - * The operator to be used to test the given value. - * @param $delta_group - * An arbitrary identifier: conditions in the same group must have the same - * $delta_group. - * @param $langcode_group - * An arbitrary identifier: conditions in the same group must have the same - * $langcode_group. - * - * @return Drupal\entity\EntityFieldQuery - * The called object. - * - * @see Drupal\entity\EntityFieldQuery::addFieldCondition() - * @see Drupal\entity\EntityFieldQuery::deleted() - */ - public function fieldCondition($field, $column = NULL, $value = NULL, $operator = NULL, $delta_group = NULL, $langcode_group = NULL) { - return $this->addFieldCondition($this->fieldConditions, $field, $column, $value, $operator, $delta_group, $langcode_group); - } - - /** - * Adds a condition on the field language column. - * - * @param $field - * Either a field name or a field array. - * @param $value - * The value to test the column value against. - * @param $operator - * The operator to be used to test the given value. - * @param $delta_group - * An arbitrary identifier: conditions in the same group must have the same - * $delta_group. - * @param $langcode_group - * An arbitrary identifier: conditions in the same group must have the same - * $langcode_group. - * - * @return Drupal\entity\EntityFieldQuery - * The called object. - * - * @see Drupal\entity\EntityFieldQuery::addFieldCondition() - * @see Drupal\entity\EntityFieldQuery::deleted() - */ - public function fieldLanguageCondition($field, $value = NULL, $operator = NULL, $delta_group = NULL, $langcode_group = NULL) { - return $this->addFieldCondition($this->fieldMetaConditions, $field, 'langcode', $value, $operator, $delta_group, $langcode_group); - } - - /** - * Adds a condition on the field delta column. - * - * @param $field - * Either a field name or a field array. - * @param $value - * The value to test the column value against. - * @param $operator - * The operator to be used to test the given value. - * @param $delta_group - * An arbitrary identifier: conditions in the same group must have the same - * $delta_group. - * @param $langcode_group - * An arbitrary identifier: conditions in the same group must have the same - * $langcode_group. - * - * @return Drupal\entity\EntityFieldQuery - * The called object. - * - * @see Drupal\entity\EntityFieldQuery::addFieldCondition() - * @see Drupal\entity\EntityFieldQuery::deleted() - */ - public function fieldDeltaCondition($field, $value = NULL, $operator = NULL, $delta_group = NULL, $langcode_group = NULL) { - return $this->addFieldCondition($this->fieldMetaConditions, $field, 'delta', $value, $operator, $delta_group, $langcode_group); - } - - /** - * Adds the given condition to the proper condition array. - * - * @param $conditions - * A reference to an array of conditions. - * @param $field - * Either a field name or a field array. - * @param $column - * A column defined in the hook_field_schema() of this field. If this is - * omitted then the query will find only entities that have data in this - * field, using the entity and property conditions if there are any. - * @param $value - * The value to test the column value against. In most cases, this is a - * scalar. For more complex options, it is an array. The meaning of each - * element in the array is dependent on $operator. - * @param $operator - * Possible values: - * - '=', '<>', '>', '>=', '<', '<=', 'STARTS_WITH', 'CONTAINS': These - * operators expect $value to be a literal of the same type as the - * column. - * - 'IN', 'NOT IN': These operators expect $value to be an array of - * literals of the same type as the column. - * - 'BETWEEN': This operator expects $value to be an array of two literals - * of the same type as the column. - * The operator can be omitted, and will default to 'IN' if the value is an - * array, or to '=' otherwise. - * @param $delta_group - * An arbitrary identifier: conditions in the same group must have the same - * $delta_group. For example, let's presume a multivalue field which has - * two columns, 'color' and 'shape', and for entity id 1, there are two - * values: red/square and blue/circle. Entity ID 1 does not have values - * corresponding to 'red circle', however if you pass 'red' and 'circle' as - * conditions, it will appear in the results - by default queries will run - * against any combination of deltas. By passing the conditions with the - * same $delta_group it will ensure that only values attached to the same - * delta are matched, and entity 1 would then be excluded from the results. - * @param $langcode_group - * An arbitrary identifier: conditions in the same group must have the same - * $langcode_group. - * - * @return Drupal\entity\EntityFieldQuery - * The called object. - */ - protected function addFieldCondition(&$conditions, $field, $column = NULL, $value = NULL, $operator = NULL, $delta_group = NULL, $langcode_group = NULL) { - if (is_scalar($field)) { - $field_definition = field_info_field($field); - if (empty($field_definition)) { - throw new EntityFieldQueryException(t('Unknown field: @field_name', array('@field_name' => $field))); - } - $field = $field_definition; - } - // Ensure the same index is used for field conditions as for fields. - $index = count($this->fields); - $this->fields[$index] = $field; - if (isset($column)) { - $conditions[$index] = array( - 'field' => $field, - 'column' => $column, - 'value' => $value, - 'operator' => $operator, - 'delta_group' => $delta_group, - 'langcode_group' => $langcode_group, - ); - } - return $this; - } - - /** - * Adds a condition on an entity-specific property. - * - * An $entity_type must be specified by calling - * EntityFieldCondition::entityCondition('entity_type', $entity_type) before - * executing the query. Also, by default only entities stored in SQL are - * supported; however, EntityFieldQuery::executeCallback can be set to handle - * different entity storage. - * - * @param $column - * A column defined in the hook_schema() of the base table of the entity. - * @param $value - * The value to test the field against. In most cases, this is a scalar. For - * more complex options, it is an array. The meaning of each element in the - * array is dependent on $operator. - * @param $operator - * Possible values: - * - '=', '<>', '>', '>=', '<', '<=', 'STARTS_WITH', 'CONTAINS': These - * operators expect $value to be a literal of the same type as the - * column. - * - 'IN', 'NOT IN': These operators expect $value to be an array of - * literals of the same type as the column. - * - 'BETWEEN': This operator expects $value to be an array of two literals - * of the same type as the column. - * The operator can be omitted, and will default to 'IN' if the value is an - * array, or to '=' otherwise. - * - * @return Drupal\entity\EntityFieldQuery - * The called object. - */ - public function propertyCondition($column, $value, $operator = NULL) { - $this->propertyConditions[] = array( - 'column' => $column, - 'value' => $value, - 'operator' => $operator, - ); - return $this; - } - - /** - * Orders the result set by entity-generic metadata. - * - * If called multiple times, the query will order by each specified column in - * the order this method is called. - * - * Note: The "comment" and "taxonomy_term" entity types don't support ordering - * by bundle. For "taxonomy_term", propertyOrderBy('vid') can be used instead. - * - * @param $name - * 'entity_type', 'bundle', 'revision_id' or 'entity_id'. - * @param $direction - * The direction to sort. Legal values are "ASC" and "DESC". - * - * @return Drupal\entity\EntityFieldQuery - * The called object. - */ - public function entityOrderBy($name, $direction = 'ASC') { - $this->order[] = array( - 'type' => 'entity', - 'specifier' => $name, - 'direction' => $direction, - ); - return $this; - } - - /** - * Orders the result set by a given field column. - * - * If called multiple times, the query will order by each specified column in - * the order this method is called. Note that entities with empty field - * values will be excluded from the EntityFieldQuery results when using this - * method. - * - * @param $field - * Either a field name or a field array. - * @param $column - * A column defined in the hook_field_schema() of this field. entity_id and - * bundle can also be used. - * @param $direction - * The direction to sort. Legal values are "ASC" and "DESC". - * - * @return Drupal\entity\EntityFieldQuery - * The called object. - */ - public function fieldOrderBy($field, $column, $direction = 'ASC') { - if (is_scalar($field)) { - $field_definition = field_info_field($field); - if (empty($field_definition)) { - throw new EntityFieldQueryException(t('Unknown field: @field_name', array('@field_name' => $field))); - } - $field = $field_definition; - } - // Save the index used for the new field, for later use in field storage. - $index = count($this->fields); - $this->fields[$index] = $field; - $this->order[] = array( - 'type' => 'field', - 'specifier' => array( - 'field' => $field, - 'index' => $index, - 'column' => $column, - ), - 'direction' => $direction, - ); - return $this; - } - - /** - * Orders the result set by an entity-specific property. - * - * An $entity_type must be specified by calling - * EntityFieldCondition::entityCondition('entity_type', $entity_type) before - * executing the query. - * - * If called multiple times, the query will order by each specified column in - * the order this method is called. - * - * @param $column - * The column on which to order. - * @param $direction - * The direction to sort. Legal values are "ASC" and "DESC". - * - * @return Drupal\entity\EntityFieldQuery - * The called object. - */ - public function propertyOrderBy($column, $direction = 'ASC') { - $this->order[] = array( - 'type' => 'property', - 'specifier' => $column, - 'direction' => $direction, - ); - return $this; - } - - /** - * Sets the query to be a count query only. - * - * @return Drupal\entity\EntityFieldQuery - * The called object. - */ - public function count() { - $this->count = TRUE; - return $this; - } - - /** - * Restricts a query to a given range in the result set. - * - * @param $start - * The first entity from the result set to return. If NULL, removes any - * range directives that are set. - * @param $length - * The number of entities to return from the result set. - * - * @return Drupal\entity\EntityFieldQuery - * The called object. - */ - public function range($start = NULL, $length = NULL) { - $this->range = array( - 'start' => $start, - 'length' => $length, - ); - return $this; - } - - /** - * Enables a pager for the query. - * - * @param $limit - * An integer specifying the number of elements per page. If passed a false - * value (FALSE, 0, NULL), the pager is disabled. - * @param $element - * An optional integer to distinguish between multiple pagers on one page. - * If not provided, one is automatically calculated. - * - * @return Drupal\entity\EntityFieldQuery - * The called object. - */ - public function pager($limit = 10, $element = NULL) { - if (!isset($element)) { - $element = PagerSelectExtender::$maxElement++; - } - elseif ($element >= PagerSelectExtender::$maxElement) { - PagerSelectExtender::$maxElement = $element + 1; - } - - $this->pager = array( - 'limit' => $limit, - 'element' => $element, - ); - return $this; - } - - /** - * Enables sortable tables for this query. - * - * @param $headers - * An EFQ Header array based on which the order clause is added to the - * query. - * - * @return Drupal\entity\EntityFieldQuery - * The called object. - */ - public function tableSort(&$headers) { - // If 'field' is not initialized, the header columns aren't clickable - foreach ($headers as $key =>$header) { - if (is_array($header) && isset($header['specifier'])) { - $headers[$key]['field'] = ''; - } - } - - $order = tablesort_get_order($headers); - $direction = tablesort_get_sort($headers); - foreach ($headers as $header) { - if (is_array($header) && ($header['data'] == $order['name'])) { - if ($header['type'] == 'field') { - $this->fieldOrderBy($header['specifier']['field'], $header['specifier']['column'], $direction); - } - else { - $header['direction'] = $direction; - $this->order[] = $header; - } - } - } - - return $this; - } - - /** - * Filters on the data being deleted. - * - * @param $deleted - * TRUE to only return deleted data, FALSE to return non-deleted data, - * EntityFieldQuery::RETURN_ALL to return everything. Defaults to FALSE. - * - * @return Drupal\entity\EntityFieldQuery - * The called object. - */ - public function deleted($deleted = TRUE) { - $this->deleted = $deleted; - return $this; - } - - /** - * Queries the current or every revision. - * - * Note that this only affects field conditions. Property conditions always - * apply to the current revision. - * @TODO: Once revision tables have been cleaned up, revisit this. - * - * @param $age - * - FIELD_LOAD_CURRENT (default): Query the most recent revisions for all - * entities. The results will be keyed by entity type and entity ID. - * - FIELD_LOAD_REVISION: Query all revisions. The results will be keyed by - * entity type and entity revision ID. - * - * @return Drupal\entity\EntityFieldQuery - * The called object. - */ - public function age($age) { - $this->age = $age; - return $this; - } - - /** - * Adds a tag to the query. - * - * Tags are strings that mark a query so that hook_query_alter() and - * hook_query_TAG_alter() implementations may decide if they wish to alter - * the query. A query may have any number of tags, and they must be valid PHP - * identifiers (composed of letters, numbers, and underscores). For example, - * queries involving nodes that will be displayed for a user need to add the - * tag 'node_access', so that the node module can add access restrictions to - * the query. - * - * If an entity field query has tags, it must also have an entity type - * specified, because the alter hook will need the entity base table. - * - * @param string $tag - * The tag to add. - * - * @return Drupal\entity\EntityFieldQuery - * The called object. - */ - public function addTag($tag) { - $this->tags[$tag] = $tag; - return $this; - } - - /** - * Adds additional metadata to the query. - * - * Sometimes a query may need to provide additional contextual data for the - * alter hook. The alter hook implementations may then use that information - * to decide if and how to take action. - * - * @param $key - * The unique identifier for this piece of metadata. Must be a string that - * follows the same rules as any other PHP identifier. - * @param $object - * The additional data to add to the query. May be any valid PHP variable. - * - * @return Drupal\entity\EntityFieldQuery - * The called object. - */ - public function addMetaData($key, $object) { - $this->metaData[$key] = $object; - return $this; - } - - /** - * Executes the query. - * - * After executing the query, $this->orderedResults will contain a list of - * the same entity ids in the order returned by the query. This is only - * relevant if there are multiple entity types in the returned value and - * a field ordering was requested. In every other case, the returned value - * contains everything necessary for processing. - * - * @return - * Either a number if count() was called or an array of associative arrays - * of the entity ids. The outer array keys are entity types, and the inner - * array keys are the relevant ID. (In most cases this will be the entity - * ID. The only exception is when age=FIELD_LOAD_REVISION is used and field - * conditions or sorts are present -- in this case, the key will be the - * revision ID.) The entity type will only exist in the outer array if - * results were found. The inner array values consist of an object with the - * entity_id, revision_id and bundle properties. To traverse the returned - * array: - * @code - * foreach ($query->execute() as $entity_type => $entities) { - * foreach ($entities as $entity_id => $entity) { - * @endcode - * Note if the entity type is known, then the following snippet will load - * the entities found: - * @code - * $result = $query->execute(); - * if (!empty($result[$my_type])) { - * $entities = entity_load_multiple($my_type, array_keys($result[$my_type])); - * } - * @endcode - */ - public function execute() { - // Give a chance to other modules to alter the query. - drupal_alter('entity_query', $this); - $this->altered = TRUE; - - // Initialize the pager. - $this->initializePager(); - - // Execute the query using the correct callback. - $result = call_user_func($this->queryCallback(), $this); - - return $result; - } - - /** - * Determines the query callback to use for this entity query. - * - * @return - * A callback that can be used with call_user_func(). - */ - public function queryCallback() { - // Use the override from $this->executeCallback. It can be set either - // while building the query, or using hook_entity_query_alter(). - if (function_exists($this->executeCallback)) { - return $this->executeCallback; - } - // If there are no field conditions and sorts, and no execute callback - // then we default to querying entity tables in SQL. - if (empty($this->fields)) { - return array($this, 'propertyQuery'); - } - // If no override, find the storage engine to be used. - foreach ($this->fields as $field) { - if (!isset($storage)) { - $storage = $field['storage']['module']; - } - elseif ($storage != $field['storage']['module']) { - throw new EntityFieldQueryException(t("Can't handle more than one field storage engine")); - } - } - if ($storage) { - // Use hook_field_storage_query() from the field storage. - return $storage . '_field_storage_query'; - } - else { - throw new EntityFieldQueryException(t("Field storage engine not found.")); - } - } - - /** - * Queries entity tables in SQL for property conditions and sorts. - * - * This method is only used if there are no field conditions and sorts. - * - * @return - * See EntityFieldQuery::execute(). - */ - protected function propertyQuery() { - if (empty($this->entityConditions['entity_type'])) { - throw new EntityFieldQueryException(t('For this query an entity type must be specified.')); - } - $entity_type = $this->entityConditions['entity_type']['value']; - $entity_info = entity_get_info($entity_type); - if (empty($entity_info['base table'])) { - throw new EntityFieldQueryException(t('Entity %entity has no base table.', array('%entity' => $entity_type))); - } - $base_table = $entity_info['base table']; - $base_table_schema = drupal_get_schema($base_table); - $select_query = db_select($base_table); - $select_query->addExpression(':entity_type', 'entity_type', array(':entity_type' => $entity_type)); - // Process the property conditions. - foreach ($this->propertyConditions as $property_condition) { - $this->addCondition($select_query, $base_table . '.' . $property_condition['column'], $property_condition); - } - // Process the four possible entity condition. - // The id field is always present in entity keys. - $sql_field = $entity_info['entity keys']['id']; - $id_map['entity_id'] = $sql_field; - $select_query->addField($base_table, $sql_field, 'entity_id'); - if (isset($this->entityConditions['entity_id'])) { - $this->addCondition($select_query, $base_table . '.' . $sql_field, $this->entityConditions['entity_id']); - } - - // If there is a revision key defined, use it. - if (!empty($entity_info['entity keys']['revision'])) { - $sql_field = $entity_info['entity keys']['revision']; - $select_query->addField($base_table, $sql_field, 'revision_id'); - if (isset($this->entityConditions['revision_id'])) { - $this->addCondition($select_query, $base_table . '.' . $sql_field, $this->entityConditions['revision_id']); - } - } - else { - $sql_field = 'revision_id'; - $select_query->addExpression('NULL', 'revision_id'); - } - $id_map['revision_id'] = $sql_field; - - // Handle bundles. - if (!empty($entity_info['entity keys']['bundle'])) { - $sql_field = $entity_info['entity keys']['bundle']; - $having = FALSE; - - if (!empty($base_table_schema['fields'][$sql_field])) { - $select_query->addField($base_table, $sql_field, 'bundle'); - } - } - else { - $sql_field = 'bundle'; - $select_query->addExpression(':bundle', 'bundle', array(':bundle' => $entity_type)); - $having = TRUE; - } - $id_map['bundle'] = $sql_field; - if (isset($this->entityConditions['bundle'])) { - if (!empty($entity_info['entity keys']['bundle'])) { - $this->addCondition($select_query, $base_table . '.' . $sql_field, $this->entityConditions['bundle'], $having); - } - else { - // This entity has no bundle, so invalidate the query. - $select_query->where('1 = 0'); - } - } - - // Order the query. - foreach ($this->order as $order) { - if ($order['type'] == 'entity') { - $key = $order['specifier']; - if (!isset($id_map[$key])) { - throw new EntityFieldQueryException(t('Do not know how to order on @key for @entity_type', array('@key' => $key, '@entity_type' => $entity_type))); - } - $select_query->orderBy($id_map[$key], $order['direction']); - } - elseif ($order['type'] == 'property') { - $select_query->orderBy($base_table . '.' . $order['specifier'], $order['direction']); - } - } - - return $this->finishQuery($select_query); - } - - /** - * Gets the total number of results and initialize a pager for the query. - * - * The pager can be disabled by either setting the pager limit to 0, or by - * setting this query to be a count query. - */ - function initializePager() { - if ($this->pager && !empty($this->pager['limit']) && !$this->count) { - $page = pager_find_page($this->pager['element']); - $count_query = clone $this; - $this->pager['total'] = $count_query->count()->execute(); - $this->pager['start'] = $page * $this->pager['limit']; - pager_default_initialize($this->pager['total'], $this->pager['limit'], $this->pager['element']); - $this->range($this->pager['start'], $this->pager['limit']); - } - } - - /** - * Finishes the query. - * - * Adds tags, metaData, range and returns the requested list or count. - * - * @param SelectQuery $select_query - * A SelectQuery which has entity_type, entity_id, revision_id and bundle - * fields added. - * @param $id_key - * Which field's values to use as the returned array keys. - * - * @return - * See EntityFieldQuery::execute(). - */ - function finishQuery($select_query, $id_key = 'entity_id') { - foreach ($this->tags as $tag) { - $select_query->addTag($tag); - } - foreach ($this->metaData as $key => $object) { - $select_query->addMetaData($key, $object); - } - $select_query->addMetaData('entity_field_query', $this); - if ($this->range) { - $select_query->range($this->range['start'], $this->range['length']); - } - if ($this->count) { - return $select_query->countQuery()->execute()->fetchField(); - } - $return = array(); - foreach ($select_query->execute() as $ids) { - if (!isset($ids->bundle)) { - $ids->bundle = NULL; - } - $return[$ids->entity_type][$ids->$id_key] = $ids; - $this->ordered_results[] = $ids; - } - return $return; - } - - /** - * Adds a condition to an already built SelectQuery (internal function). - * - * This is a helper for hook_entity_query() and hook_field_storage_query(). - * - * @param SelectQuery $select_query - * A SelectQuery object. - * @param $sql_field - * The name of the field. - * @param $condition - * A condition as described in EntityFieldQuery::fieldCondition() and - * EntityFieldQuery::entityCondition(). - * @param $having - * HAVING or WHERE. This is necessary because SQL can't handle WHERE - * conditions on aliased columns. - */ - public function addCondition(Select $select_query, $sql_field, $condition, $having = FALSE) { - $method = $having ? 'havingCondition' : 'condition'; - $like_prefix = ''; - switch ($condition['operator']) { - case 'CONTAINS': - $like_prefix = '%'; - case 'STARTS_WITH': - $select_query->$method($sql_field, $like_prefix . db_like($condition['value']) . '%', 'LIKE'); - break; - default: - $select_query->$method($sql_field, $condition['value'], $condition['operator']); - } - } - -} diff --git a/core/modules/entity/lib/Drupal/entity/EntityFieldQueryException.php b/core/modules/entity/lib/Drupal/entity/EntityFieldQueryException.php deleted file mode 100644 index 12f2a1c..0000000 --- a/core/modules/entity/lib/Drupal/entity/EntityFieldQueryException.php +++ /dev/null @@ -1,19 +0,0 @@ -operation = $operation; - } - - /** - * Implements Drupal\entity\EntityFormControllerInterface::build(). - */ - public function build(array $form, array &$form_state, EntityInterface $entity) { - - // During the initial form build, add the entity to the form state for use - // during form building and processing. During a rebuild, use what is in the - // form state. - if (!$this->getEntity($form_state)) { - $this->init($form_state, $entity); - } - - // Retrieve the form array using the possibly updated entity in form state. - $entity = $this->getEntity($form_state); - $form = $this->form($form, $form_state, $entity); - - // Retrieve and add the form actions array. - $actions = $this->actionsElement($form, $form_state); - if (!empty($actions)) { - $form['actions'] = $actions; - } - - return $form; - } - - /** - * Initialize the form state and the entity before the first form build. - */ - protected function init(array &$form_state, EntityInterface $entity) { - // Add the controller to the form state so it can be easily accessed by - // module-provided form handlers there. - $form_state['controller'] = $this; - $this->setEntity($entity, $form_state); - $this->prepareEntity($entity); - } - - /** - * Returns the actual form array to be built. - * - * @see Drupal\entity\EntityFormController::build() - */ - public function form(array $form, array &$form_state, EntityInterface $entity) { - // @todo Exploit the Property API to generate the default widgets for the - // entity properties. - $info = $entity->entityInfo(); - if (!empty($info['fieldable'])) { - field_attach_form($entity->entityType(), $entity, $form, $form_state, $this->getFormLangcode($form_state)); - } - return $form; - } - - /** - * Returns the action form element for the current entity form. - */ - protected function actionsElement(array $form, array &$form_state) { - $element = $this->actions($form, $form_state); - - // We cannot delete an entity that has not been created yet. - if ($this->getEntity($form_state)->isNew()) { - unset($element['delete']); - } - elseif (isset($element['delete'])) { - // Move the delete action as last one, unless weights are explicitly - // provided. - $delete = $element['delete']; - unset($element['delete']); - $element['delete'] = $delete; - } - - $count = 0; - foreach (element_children($element) as $action) { - $element[$action] += array( - '#type' => 'submit', - '#weight' => ++$count * 5, - ); - } - - if (!empty($element)) { - $element['#type'] = 'actions'; - } - - return $element; - } - - /** - * Returns an array of supported actions for the current entity form. - */ - protected function actions(array $form, array &$form_state) { - return array( - // @todo Rename the action key from submit to save. - 'submit' => array( - '#value' => t('Save'), - '#validate' => array( - array($this, 'validate'), - ), - '#submit' => array( - array($this, 'submit'), - array($this, 'save'), - ), - ), - 'delete' => array( - '#value' => t('Delete'), - // No need to validate the form when deleting the entity. - '#submit' => array( - array($this, 'delete'), - ), - ), - // @todo Consider introducing a 'preview' action here, since it is used by - // many entity types. - ); - } - - /** - * Implements Drupal\entity\EntityFormControllerInterface::validate(). - */ - public function validate(array $form, array &$form_state) { - // @todo Exploit the Property API to validate the values submitted for the - // entity properties. - $entity = $this->buildEntity($form, $form_state); - $info = $entity->entityInfo(); - - if (!empty($info['fieldable'])) { - field_attach_form_validate($entity->entityType(), $entity, $form, $form_state); - } - - // @todo Remove this. - // Execute legacy global validation handlers. - unset($form_state['validate_handlers']); - form_execute_handlers('validate', $form, $form_state); - } - - /** - * Implements Drupal\entity\EntityFormControllerInterface::submit(). - * - * This is the default entity object builder function. It is called before any - * other submit handler to build the new entity object to be passed to the - * following submit handlers. At this point of the form workflow the entity is - * validated and the form state can be updated, this way the subsequently - * invoked handlers can retrieve a regular entity object to act on. - * - * @param array $form - * An associative array containing the structure of the form. - * @param array $form_state - * A reference to a keyed array containing the current state of the form. - */ - public function submit(array $form, array &$form_state) { - $entity = $this->buildEntity($form, $form_state); - $this->setEntity($entity, $form_state); - return $entity; - } - - /** - * Form submission handler for the 'save' action. - * - * @param array $form - * An associative array containing the structure of the form. - * @param array $form_state - * A reference to a keyed array containing the current state of the form. - */ - public function save(array $form, array &$form_state) { - // @todo Perform common save operations. - } - - /** - * Form submission handler for the 'delete' action. - * - * @param array $form - * An associative array containing the structure of the form. - * @param array $form_state - * A reference to a keyed array containing the current state of the form. - */ - public function delete(array $form, array &$form_state) { - // @todo Perform common delete operations. - } - - /** - * Implements Drupal\entity\EntityFormControllerInterface::getFormLangcode(). - */ - public function getFormLangcode(array $form_state) { - $entity = $this->getEntity($form_state); - $translations = $entity->translations(); - - if (!empty($form_state['langcode'])) { - $langcode = $form_state['langcode']; - } - else { - // If no form langcode was provided we default to the current content - // language and inspect existing translations to find a valid fallback, - // if any. - $langcode = language(LANGUAGE_TYPE_CONTENT)->langcode; - $fallback = language_multilingual() ? language_fallback_get_candidates() : array(); - while (!empty($langcode) && !isset($translations[$langcode])) { - $langcode = array_shift($fallback); - } - } - - // If the site is not multilingual or no translation for the given form - // language is available, fall back to the entity language. - return !empty($langcode) ? $langcode : $entity->language()->langcode; - } - - /** - * Implements Drupal\entity\EntityFormControllerInterface::buildEntity(). - */ - public function buildEntity(array $form, array &$form_state) { - $entity = clone $this->getEntity($form_state); - // @todo Move entity_form_submit_build_entity() here. - // @todo Exploit the Property API to process the submitted entity property. - entity_form_submit_build_entity($entity->entityType(), $entity, $form, $form_state); - return $entity; - } - - /** - * Implements Drupal\entity\EntityFormControllerInterface::getEntity(). - */ - public function getEntity(array $form_state) { - return isset($form_state['entity']) ? $form_state['entity'] : NULL; - } - - /** - * Implements Drupal\entity\EntityFormControllerInterface::setEntity(). - */ - public function setEntity(EntityInterface $entity, array &$form_state) { - $form_state['entity'] = $entity; - } - - /** - * Prepares the entity object before the form is built first. - */ - protected function prepareEntity(EntityInterface $entity) { - // @todo Perform common prepare operations and add a hook. - } - - /** - * Implements Drupal\entity\EntityFormControllerInterface::getOperation(). - */ - public function getOperation() { - return $this->operation; - } -} diff --git a/core/modules/entity/lib/Drupal/entity/EntityFormControllerInterface.php b/core/modules/entity/lib/Drupal/entity/EntityFormControllerInterface.php deleted file mode 100644 index 95fb2fc..0000000 --- a/core/modules/entity/lib/Drupal/entity/EntityFormControllerInterface.php +++ /dev/null @@ -1,134 +0,0 @@ -assertEqual($info['label'], 'Entity Cache Test', 'Entity info label is correct.'); - $this->assertEqual($info['controller class'], 'Drupal\entity\DatabaseStorageController', 'Entity controller class info is correct.'); + $this->assertEqual($info['controller class'], 'Drupal\Core\Entity\DatabaseStorageController', 'Entity controller class info is correct.'); } } diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityApiTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityApiTest.php index e8d979f..4b6a94f 100644 --- a/core/modules/entity/lib/Drupal/entity/Tests/EntityApiTest.php +++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityApiTest.php @@ -2,10 +2,10 @@ /** * @file - * Definition of Drupal\entity\Tests\EntityApiTest. + * Definition of Drupal\Core\Entity\Tests\EntityApiTest. */ -namespace Drupal\entity\Tests; +namespace Drupal\Core\Entity\Tests; use Drupal\simpletest\WebTestBase; diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityCrudHookTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityCrudHookTest.php index 251dd3c..0417179 100644 --- a/core/modules/entity/lib/Drupal/entity/Tests/EntityCrudHookTest.php +++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityCrudHookTest.php @@ -2,10 +2,10 @@ /** * @file - * Definition of Drupal\entity\Tests\EntityCrudHookTest. + * Definition of Drupal\Core\Entity\Tests\EntityCrudHookTest. */ -namespace Drupal\entity\Tests; +namespace Drupal\Core\Entity\Tests; use Drupal\simpletest\WebTestBase; diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityFieldQueryTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityFieldQueryTest.php index 8015c67..a05527e 100644 --- a/core/modules/entity/lib/Drupal/entity/Tests/EntityFieldQueryTest.php +++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityFieldQueryTest.php @@ -2,19 +2,19 @@ /** * @file - * Definition of Drupal\entity\Tests\EntityFieldQueryTest. + * Definition of Drupal\Core\Entity\Tests\EntityFieldQueryTest. */ -namespace Drupal\entity\Tests; +namespace Drupal\Core\Entity\Tests; use Drupal\simpletest\WebTestBase; -use Drupal\entity\EntityFieldQuery; -use Drupal\entity\EntityFieldQueryException; +use Drupal\Core\Entity\EntityFieldQuery; +use Drupal\Core\Entity\EntityFieldQueryException; use stdClass; use Exception; /** - * Tests Drupal\entity\EntityFieldQuery. + * Tests Drupal\Core\Entity\EntityFieldQuery. */ class EntityFieldQueryTest extends WebTestBase { diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityTranslationFormTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityTranslationFormTest.php index 3908184..0d4447f 100644 --- a/core/modules/entity/lib/Drupal/entity/Tests/EntityTranslationFormTest.php +++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityTranslationFormTest.php @@ -2,10 +2,10 @@ /** * @file - * Definition of Drupal\entity\Tests\EntityTranslationFormTest. + * Definition of Drupal\Core\Entity\Tests\EntityTranslationFormTest. */ -namespace Drupal\entity\Tests; +namespace Drupal\Core\Entity\Tests; use Exception; use InvalidArgumentException; diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityTranslationTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityTranslationTest.php index 252e048..5fd938f 100644 --- a/core/modules/entity/lib/Drupal/entity/Tests/EntityTranslationTest.php +++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityTranslationTest.php @@ -2,10 +2,10 @@ /** * @file - * Definition of Drupal\entity\Tests\EntityTranslationTest. + * Definition of Drupal\Core\Entity\Tests\EntityTranslationTest. */ -namespace Drupal\entity\Tests; +namespace Drupal\Core\Entity\Tests; use Exception; use InvalidArgumentException; diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityUUIDTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityUUIDTest.php index e7607dc..e264247 100644 --- a/core/modules/entity/lib/Drupal/entity/Tests/EntityUUIDTest.php +++ b/core/modules/entity/lib/Drupal/entity/Tests/EntityUUIDTest.php @@ -2,10 +2,10 @@ /** * @file - * Definition of Drupal\entity\Tests\EntityUUIDTest. + * Definition of Drupal\Core\Entity\Tests\EntityUUIDTest. */ -namespace Drupal\entity\Tests; +namespace Drupal\Core\Entity\Tests; use Drupal\Component\Uuid\Uuid; use Drupal\simpletest\WebTestBase; diff --git a/core/modules/entity/tests/modules/entity_crud_hook_test/entity_crud_hook_test.module b/core/modules/entity/tests/modules/entity_crud_hook_test/entity_crud_hook_test.module index 48a2876..8a1e43c 100644 --- a/core/modules/entity/tests/modules/entity_crud_hook_test/entity_crud_hook_test.module +++ b/core/modules/entity/tests/modules/entity_crud_hook_test/entity_crud_hook_test.module @@ -5,7 +5,7 @@ * Test module for the Entity CRUD API. */ -use Drupal\entity\EntityInterface; +use Drupal\Core\Entity\EntityInterface; /** * Implements hook_entity_presave(). diff --git a/core/modules/entity/tests/modules/entity_query_access_test/entity_query_access_test.module b/core/modules/entity/tests/modules/entity_query_access_test/entity_query_access_test.module index 262f3b7..2a4fd75 100644 --- a/core/modules/entity/tests/modules/entity_query_access_test/entity_query_access_test.module +++ b/core/modules/entity/tests/modules/entity_query_access_test/entity_query_access_test.module @@ -5,8 +5,8 @@ * Helper module for testing EntityFieldQuery access on any type of entity. */ -use Drupal\entity\EntityFieldQuery; -use Drupal\entity\EntityFieldQueryException; +use Drupal\Core\Entity\EntityFieldQuery; +use Drupal\Core\Entity\EntityFieldQueryException; /** * Implements hook_menu(). diff --git a/core/modules/entity/tests/modules/entity_test/entity_test.module b/core/modules/entity/tests/modules/entity_test/entity_test.module index 9b1b224..59acb21 100644 --- a/core/modules/entity/tests/modules/entity_test/entity_test.module +++ b/core/modules/entity/tests/modules/entity_test/entity_test.module @@ -11,8 +11,8 @@ function entity_test_entity_info() { $items['entity_test'] = array( 'label' => t('Test entity'), - 'entity class' => 'Drupal\entity_test\EntityTest', - 'controller class' => 'Drupal\entity_test\EntityTestStorageController', + 'entity class' => 'Drupal\Core\Entity_test\EntityTest', + 'controller class' => 'Drupal\Core\Entity_test\EntityTestStorageController', 'base table' => 'entity_test', 'fieldable' => TRUE, 'entity keys' => array( @@ -35,7 +35,7 @@ function entity_test_entity_info() { * @param bool $reset * A boolean indicating that the internal cache should be reset. * - * @return Drupal\entity_test\EntityTest + * @return Drupal\Core\Entity_test\EntityTest * The loaded entity object, or FALSE if the entity cannot be loaded. */ function entity_test_load($id, $reset = FALSE) { diff --git a/core/modules/entity/tests/modules/entity_test/lib/Drupal/entity_test/EntityTest.php b/core/modules/entity/tests/modules/entity_test/lib/Drupal/entity_test/EntityTest.php index 6c95f75..e112dcd 100644 --- a/core/modules/entity/tests/modules/entity_test/lib/Drupal/entity_test/EntityTest.php +++ b/core/modules/entity/tests/modules/entity_test/lib/Drupal/entity_test/EntityTest.php @@ -2,14 +2,14 @@ /** * @file - * Definition of Drupal\entity_test\EntityTest. + * Definition of Drupal\Core\Entity_test\EntityTest. */ -namespace Drupal\entity_test; +namespace Drupal\Core\Entity_test; use InvalidArgumentException; -use Drupal\entity\Entity; +use Drupal\Core\Entity\Entity; /** * Defines the test entity class. diff --git a/core/modules/entity/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestStorageController.php b/core/modules/entity/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestStorageController.php index b31e5ce..6966788 100644 --- a/core/modules/entity/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestStorageController.php +++ b/core/modules/entity/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestStorageController.php @@ -2,26 +2,26 @@ /** * @file - * Definition of Drupal\entity_test\EntityTestStorageController. + * Definition of Drupal\Core\Entity_test\EntityTestStorageController. */ -namespace Drupal\entity_test; +namespace Drupal\Core\Entity_test; use PDO; -use Drupal\entity\EntityInterface; -use Drupal\entity\DatabaseStorageController; +use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\DatabaseStorageController; /** * Defines the controller class for the test entity. * - * This extends the Drupal\entity\DatabaseStorageController class, adding + * This extends the Drupal\Core\Entity\DatabaseStorageController class, adding * required special handling for test entities. */ class EntityTestStorageController extends DatabaseStorageController { /** - * Overrides Drupal\entity\DatabaseStorageController::loadByProperties(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::loadByProperties(). */ public function loadByProperties(array $values) { $query = db_select($this->entityInfo['base table'], 'base'); @@ -58,7 +58,7 @@ class EntityTestStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::attachLoad(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::attachLoad(). */ protected function attachLoad(&$queried_entities, $load_revision = FALSE) { $data = db_select('entity_test_property_data', 'data', array('fetch' => PDO::FETCH_ASSOC)) @@ -82,7 +82,7 @@ class EntityTestStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::postSave(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::postSave(). */ protected function postSave(EntityInterface $entity, $update) { $default_langcode = ($language = $entity->language()) ? $language->langcode : LANGUAGE_NOT_SPECIFIED; @@ -107,7 +107,7 @@ class EntityTestStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::postDelete(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::postDelete(). */ protected function postDelete($entities) { db_delete('entity_test_property_data') diff --git a/core/modules/field/field.api.php b/core/modules/field/field.api.php index 1f76def..a407c74 100644 --- a/core/modules/field/field.api.php +++ b/core/modules/field/field.api.php @@ -1942,18 +1942,18 @@ function hook_field_storage_delete_revision($entity_type, $entity, $fields) { } /** - * Execute a Drupal\entity\EntityFieldQuery. + * Execute a Drupal\Core\Entity\EntityFieldQuery. * * This hook is called to find the entities having certain entity and field * conditions and sort them in the given field order. If the field storage * engine also handles property sorts and orders, it should unset those * properties in the called object to signal that those have been handled. * - * @param Drupal\entity\EntityFieldQuery $query + * @param Drupal\Core\Entity\EntityFieldQuery $query * An EntityFieldQuery. * * @return - * See Drupal\entity\EntityFieldQuery::execute() for the return values. + * See Drupal\Core\Entity\EntityFieldQuery::execute() for the return values. */ function hook_field_storage_query($query) { $groups = array(); diff --git a/core/modules/field/field.attach.inc b/core/modules/field/field.attach.inc index 611b577..7c2acdb 100644 --- a/core/modules/field/field.attach.inc +++ b/core/modules/field/field.attach.inc @@ -6,7 +6,7 @@ */ use Drupal\field\FieldValidationException; -use Drupal\entity\EntityInterface; +use Drupal\Core\Entity\EntityInterface; /** * @defgroup field_storage Field Storage API @@ -123,7 +123,7 @@ const FIELD_STORAGE_INSERT = 'insert'; * - prepare translation * @param $entity_type * The type of $entity; e.g. 'node' or 'user'. - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The fully formed $entity_type entity. * @param $a * - The $form in the 'form' operation. @@ -519,7 +519,7 @@ function _field_invoke_get_instances($entity_type, $bundle, $options) { * * @param $entity_type * The type of $entity; e.g. 'node' or 'user'. - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The entity for which to load form elements, used to initialize * default form values. * @param $form @@ -739,7 +739,7 @@ function field_attach_load_revision($entity_type, $entities, $options = array()) * * @param $entity_type * The type of $entity; e.g. 'node' or 'user'. - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The entity with fields to validate. * @throws Drupal\field\FieldValidationException * If validation errors are found, a FieldValidationException is thrown. The @@ -784,7 +784,7 @@ function field_attach_validate($entity_type, $entity) { * * @param $entity_type * The type of $entity; e.g. 'node' or 'user'. - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The entity being submitted. The 'bundle', 'id' and (if applicable) * 'revision' keys should be present. The actual field values will be read * from $form_state['values']. @@ -824,7 +824,7 @@ function field_attach_form_validate($entity_type, EntityInterface $entity, $form * * @param $entity_type * The type of $entity; e.g. 'node' or 'user'. - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The entity being submitted. The 'bundle', 'id' and (if applicable) * 'revision' keys should be present. The actual field values will be read * from $form_state['values']. @@ -876,7 +876,7 @@ function field_attach_presave($entity_type, $entity) { * * @param $entity_type * The type of $entity; e.g. 'node' or 'user'. - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The entity with fields to save. * @return * Default values (if any) will be added to the $entity parameter for fields @@ -925,7 +925,7 @@ function field_attach_insert($entity_type, EntityInterface $entity) { * * @param $entity_type * The type of $entity; e.g. 'node' or 'user'. - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The entity with fields to save. */ function field_attach_update($entity_type, EntityInterface $entity) { @@ -978,7 +978,7 @@ function field_attach_update($entity_type, EntityInterface $entity) { * * @param $entity_type * The type of $entity; e.g. 'node' or 'user'. - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The entity whose field data to delete. */ function field_attach_delete($entity_type, $entity) { @@ -1013,7 +1013,7 @@ function field_attach_delete($entity_type, $entity) { * * @param $entity_type * The type of $entity; e.g. 'node' or 'user'. - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The entity with fields to save. */ function field_attach_delete_revision($entity_type, $entity) { @@ -1128,7 +1128,7 @@ function field_attach_prepare_view($entity_type, $entities, $view_mode, $langcod * * @param $entity_type * The type of $entity; e.g. 'node' or 'user'. - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The entity with fields to render. * @param $view_mode * View mode, e.g. 'full', 'teaser'... @@ -1181,7 +1181,7 @@ function field_attach_view($entity_type, EntityInterface $entity, $view_mode, $l * * @param $entity_type * The type of $entity; e.g. 'node' or 'user'. - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The entity with fields to render. * @param $element * The structured array containing the values ready for rendering. @@ -1221,7 +1221,7 @@ function field_attach_preprocess($entity_type, EntityInterface $entity, $element * * @param $entity_type * The type of $entity; e.g. 'node' or 'user'. - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The entity to be prepared for translation. * @param $langcode * The language the entity has to be translated in. diff --git a/core/modules/field/field.crud.inc b/core/modules/field/field.crud.inc index b748c51..f1e5481 100644 --- a/core/modules/field/field.crud.inc +++ b/core/modules/field/field.crud.inc @@ -6,7 +6,7 @@ */ use Drupal\field\FieldException; -use Drupal\entity\EntityFieldQuery; +use Drupal\Core\Entity\EntityFieldQuery; /** * @defgroup field_crud Field CRUD API diff --git a/core/modules/field/field.module b/core/modules/field/field.module index e75111e..72b6d91 100644 --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -4,7 +4,7 @@ * Attach custom data fields to Drupal entities. */ -use Drupal\entity\EntityFieldQuery; +use Drupal\Core\Entity\EntityFieldQuery; use Drupal\Core\Template\Attribute; /* diff --git a/core/modules/field/lib/Drupal/field/Tests/BulkDeleteTest.php b/core/modules/field/lib/Drupal/field/Tests/BulkDeleteTest.php index 8021673..84b6f06 100644 --- a/core/modules/field/lib/Drupal/field/Tests/BulkDeleteTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/BulkDeleteTest.php @@ -7,7 +7,7 @@ namespace Drupal\field\Tests; -use Drupal\entity\EntityFieldQuery; +use Drupal\Core\Entity\EntityFieldQuery; /** * Unit test class for field bulk delete and batch purge functionality. diff --git a/core/modules/field/modules/field_sql_storage/field_sql_storage.module b/core/modules/field/modules/field_sql_storage/field_sql_storage.module index 91956ad..ba1e710 100644 --- a/core/modules/field/modules/field_sql_storage/field_sql_storage.module +++ b/core/modules/field/modules/field_sql_storage/field_sql_storage.module @@ -7,8 +7,8 @@ use Drupal\Core\Database\Database; use Drupal\Core\Database\Query\Select; -use Drupal\entity\EntityFieldQuery; -use Drupal\entity\EntityFieldQueryException; +use Drupal\Core\Entity\EntityFieldQuery; +use Drupal\Core\Entity\EntityFieldQueryException; use Drupal\field\FieldUpdateForbiddenException; /** @@ -620,7 +620,7 @@ function _field_sql_storage_query_join_entity(Select $select_query, $entity_type /** * Adds field (meta) conditions to the given query objects respecting groupings. * - * @param Drupal\entity\EntityFieldQuery $query + * @param Drupal\Core\Entity\EntityFieldQuery $query * The field query object to be processed. * @param SelectQuery $select_query * The SelectQuery that should get grouping conditions. diff --git a/core/modules/field/modules/options/options.module b/core/modules/field/modules/options/options.module index 3cda56b..4d70277 100644 --- a/core/modules/field/modules/options/options.module +++ b/core/modules/field/modules/options/options.module @@ -6,7 +6,7 @@ */ use Drupal\field\FieldUpdateForbiddenException; -use Drupal\entity\EntityFieldQuery; +use Drupal\Core\Entity\EntityFieldQuery; /** * Implements hook_help(). diff --git a/core/modules/field/tests/modules/field_test/field_test.entity.inc b/core/modules/field/tests/modules/field_test/field_test.entity.inc index 1601f09..4819b3f 100644 --- a/core/modules/field/tests/modules/field_test/field_test.entity.inc +++ b/core/modules/field/tests/modules/field_test/field_test.entity.inc @@ -5,7 +5,7 @@ * Defines an entity type. */ -use Drupal\entity\EntityInterface; +use Drupal\Core\Entity\EntityInterface; use Drupal\field_test\TestEntity; /** diff --git a/core/modules/field/tests/modules/field_test/field_test.module b/core/modules/field/tests/modules/field_test/field_test.module index ea38362..92173a5 100644 --- a/core/modules/field/tests/modules/field_test/field_test.module +++ b/core/modules/field/tests/modules/field_test/field_test.module @@ -13,7 +13,7 @@ * test helper functions */ -use Drupal\entity\EntityFieldQuery; +use Drupal\Core\Entity\EntityFieldQuery; require_once DRUPAL_ROOT . '/core/modules/field/tests/modules/field_test/field_test.entity.inc'; require_once DRUPAL_ROOT . '/core/modules/field/tests/modules/field_test/field_test.field.inc'; @@ -278,7 +278,7 @@ function field_test_field_widget_form_alter(&$element, &$form_state, $context) { /** * Implements hook_query_TAG_alter() for tag 'efq_table_prefixing_test'. * - * @see Drupal\entity\Tests\EntityFieldQueryTest::testTablePrefixing() + * @see Drupal\Core\Entity\Tests\EntityFieldQueryTest::testTablePrefixing() */ function field_test_query_efq_table_prefixing_test_alter(&$query) { // Add an additional join onto the entity base table. This will cause an diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/TestEntity.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/TestEntity.php index fb1335b..18cfff5 100644 --- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/TestEntity.php +++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/TestEntity.php @@ -7,7 +7,7 @@ namespace Drupal\field_test; -use Drupal\entity\Entity; +use Drupal\Core\Entity\Entity; /** * Test entity class. @@ -36,21 +36,21 @@ class TestEntity extends Entity { public $fttype; /** - * Overrides Drupal\entity\Entity::id(). + * Overrides Drupal\Core\Entity\Entity::id(). */ public function id() { return $this->ftid; } /** - * Overrides Drupal\entity\Entity::getRevisionId(). + * Overrides Drupal\Core\Entity\Entity::getRevisionId(). */ public function getRevisionId() { return $this->ftvid; } /** - * Overrides Drupal\entity\Entity::bundle(). + * Overrides Drupal\Core\Entity\Entity::bundle(). */ public function bundle() { return !empty($this->fttype) ? $this->fttype : $this->entityType(); diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/TestEntityController.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/TestEntityController.php index 3bdab77..16f66df 100644 --- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/TestEntityController.php +++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/TestEntityController.php @@ -7,8 +7,8 @@ namespace Drupal\field_test; -use Drupal\entity\DatabaseStorageController; -use Drupal\entity\EntityInterface; +use Drupal\Core\Entity\DatabaseStorageController; +use Drupal\Core\Entity\EntityInterface; /** * Controller class for the test entity entity types. @@ -16,7 +16,7 @@ use Drupal\entity\EntityInterface; class TestEntityController extends DatabaseStorageController { /** - * Overrides Drupal\entity\DatabaseStorageController::preSave(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::preSave(). */ public function preSave(EntityInterface $entity) { // Prepare for a new revision. @@ -27,7 +27,7 @@ class TestEntityController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::postSave(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::postSave(). */ public function postSave(EntityInterface $entity, $update) { // Only the test_entity entity type has revisions. diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/TestEntityFormController.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/TestEntityFormController.php index d860d5f..93ef2aa 100644 --- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/TestEntityFormController.php +++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/TestEntityFormController.php @@ -7,8 +7,8 @@ namespace Drupal\field_test; -use Drupal\entity\EntityInterface; -use Drupal\entity\EntityFormController; +use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityFormController; /** * Form controller for the test entity edit forms. @@ -16,7 +16,7 @@ use Drupal\entity\EntityFormController; class TestEntityFormController extends EntityFormController { /** - * Overrides Drupal\entity\EntityFormController::form(). + * Overrides Drupal\Core\Entity\EntityFormController::form(). */ public function form(array $form, array &$form_state, EntityInterface $entity) { $form = parent::form($form, $form_state, $entity); @@ -33,7 +33,7 @@ class TestEntityFormController extends EntityFormController { } /** - * Overrides Drupal\entity\EntityFormController::save(). + * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { $entity = $this->getEntity($form_state); diff --git a/core/modules/file/file.api.php b/core/modules/file/file.api.php index 2583d83..c0b0d52 100644 --- a/core/modules/file/file.api.php +++ b/core/modules/file/file.api.php @@ -172,7 +172,7 @@ function hook_file_delete(Drupal\file\File $file) { * * @param $field * The field to which the file belongs. - * @param Drupal\entity\EntityInterface $entity + * @param Drupal\Core\Entity\EntityInterface $entity * The entity which references the file. * @param Drupal\file\File $file * The file entity that is being requested. @@ -184,7 +184,7 @@ function hook_file_delete(Drupal\file\File $file) { * * @see hook_field_access(). */ -function hook_file_download_access($field, Drupal\entity\EntityInterface $entity, Drupal\file\File $file) { +function hook_file_download_access($field, Drupal\Core\Entity\EntityInterface $entity, Drupal\file\File $file) { if ($entity->entityType() == 'node') { return node_access('view', $entity); } diff --git a/core/modules/file/file.module b/core/modules/file/file.module index 3b81b1a..53dc798 100644 --- a/core/modules/file/file.module +++ b/core/modules/file/file.module @@ -5,7 +5,7 @@ * Defines a "managed_file" Form API field and a "file" field for Field module. */ -use Drupal\entity\EntityFieldQuery; +use Drupal\Core\Entity\EntityFieldQuery; use Drupal\file\File; use Drupal\Core\Template\Attribute; use Symfony\Component\HttpFoundation\JsonResponse; @@ -116,7 +116,7 @@ function file_entity_info() { * @see hook_file_load() * @see file_load() * @see entity_load() - * @see Drupal\entity\EntityFieldQuery + * @see Drupal\Core\Entity\EntityFieldQuery */ function file_load_multiple(array $fids = NULL) { return entity_load_multiple('file', $fids); diff --git a/core/modules/file/lib/Drupal/file/File.php b/core/modules/file/lib/Drupal/file/File.php index e70e3d0..9b965e3 100644 --- a/core/modules/file/lib/Drupal/file/File.php +++ b/core/modules/file/lib/Drupal/file/File.php @@ -7,7 +7,7 @@ namespace Drupal\file; -use Drupal\entity\Entity; +use Drupal\Core\Entity\Entity; /** * Defines the file entity class. @@ -92,7 +92,7 @@ class File extends Entity { public $timestamp; /** - * Overrides Drupal\entity\Entity::id(). + * Overrides Drupal\Core\Entity\Entity::id(). */ public function id() { return $this->fid; diff --git a/core/modules/file/lib/Drupal/file/FileStorageController.php b/core/modules/file/lib/Drupal/file/FileStorageController.php index 356e5c4..195ab95 100644 --- a/core/modules/file/lib/Drupal/file/FileStorageController.php +++ b/core/modules/file/lib/Drupal/file/FileStorageController.php @@ -7,8 +7,8 @@ namespace Drupal\file; -use Drupal\entity\DatabaseStorageController; -use Drupal\entity\EntityInterface; +use Drupal\Core\Entity\DatabaseStorageController; +use Drupal\Core\Entity\EntityInterface; /** * File storage controller for files. @@ -16,7 +16,7 @@ use Drupal\entity\EntityInterface; class FileStorageController extends DatabaseStorageController { /** - * Overrides Drupal\entity\DatabaseStorageController::create(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::create(). */ public function create(array $values) { // Automatically detect filename if not set. @@ -32,7 +32,7 @@ class FileStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::presave(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::presave(). */ protected function preSave(EntityInterface $entity) { $entity->timestamp = REQUEST_TIME; @@ -47,7 +47,7 @@ class FileStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::preDelete(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::preDelete(). */ public function preDelete($entities) { foreach ($entities as $entity) { diff --git a/core/modules/file/tests/file_module_test.module b/core/modules/file/tests/file_module_test.module index c9dd819..eae577e 100644 --- a/core/modules/file/tests/file_module_test.module +++ b/core/modules/file/tests/file_module_test.module @@ -5,7 +5,7 @@ * Provides File module pages for testing purposes. */ -use Drupal\entity\EntityInterface; +use Drupal\Core\Entity\EntityInterface; use Drupal\file\File; /** diff --git a/core/modules/language/language.admin.inc b/core/modules/language/language.admin.inc index af2b3b1..53af56c 100644 --- a/core/modules/language/language.admin.inc +++ b/core/modules/language/language.admin.inc @@ -169,7 +169,7 @@ function language_admin_overview_form_submit($form, &$form_state) { $old_default = language_default(); foreach ($languages as $langcode => $language) { - $language->default = ($form_state['values']['site_default'] == $langcode); + $language->setDefault($form_state['values']['site_default'] == $langcode); $language->weight = $form_state['values']['languages'][$langcode]['weight']; language_save($language); } @@ -696,7 +696,7 @@ function language_negotiation_configure_url_form($form, &$form_state) { $t_args = array('%language' => $language->name, '%langcode' => $language->langcode); $form['prefix'][$langcode] = array( '#type' => 'textfield', - '#title' => $language->default ? t('%language (%langcode) path prefix (Default language)', $t_args) : t('%language (%langcode) path prefix', $t_args), + '#title' => $language->isDefault() ? t('%language (%langcode) path prefix (Default language)', $t_args) : t('%language (%langcode) path prefix', $t_args), '#maxlength' => 64, '#default_value' => isset($prefixes[$langcode]) ? $prefixes[$langcode] : '', '#field_prefix' => $base_url . '/', @@ -734,7 +734,7 @@ function language_negotiation_configure_url_form_validate($form, &$form_state) { $value = $form_state['values']['prefix'][$langcode]; if ($value === '') { - if (!$language->default && $form_state['values']['language_negotiation_url_part'] == LANGUAGE_NEGOTIATION_URL_PREFIX) { + if (!$language->isDefault() && $form_state['values']['language_negotiation_url_part'] == LANGUAGE_NEGOTIATION_URL_PREFIX) { // Throw a form error if the prefix is blank for a non-default language, // although it is required for selected negotiation type. form_error($form['prefix'][$langcode], t('The prefix may only be left blank for the default language.')); @@ -758,7 +758,7 @@ function language_negotiation_configure_url_form_validate($form, &$form_state) { $value = $form_state['values']['domain'][$langcode]; if ($value === '') { - if (!$language->default && $form_state['values']['language_negotiation_url_part'] == LANGUAGE_NEGOTIATION_URL_DOMAIN) { + if (!$language->isDefault() && $form_state['values']['language_negotiation_url_part'] == LANGUAGE_NEGOTIATION_URL_DOMAIN) { // Throw a form error if the domain is blank for a non-default language, // although it is required for selected negotiation type. form_error($form['domain'][$langcode], t('The domain may only be left blank for the default language.')); diff --git a/core/modules/language/language.api.php b/core/modules/language/language.api.php index 6f19835..9d413ad 100644 --- a/core/modules/language/language.api.php +++ b/core/modules/language/language.api.php @@ -17,7 +17,7 @@ * A language object. */ function hook_language_presave($language) { - if ($language->default) { + if ($language->isDefault()) { // React to a new default language. example_new_default_language($language); } diff --git a/core/modules/language/language.install b/core/modules/language/language.install index 2884d4b..0b1db76 100644 --- a/core/modules/language/language.install +++ b/core/modules/language/language.install @@ -55,55 +55,6 @@ function language_uninstall() { } /** - * Implements hook_schema(). - */ -function language_schema() { - $schema['language'] = array( - 'description' => 'List of all available languages in the system.', - 'fields' => array( - 'langcode' => array( - 'type' => 'varchar', - 'length' => 12, - 'not null' => TRUE, - 'default' => '', - 'description' => "Language code, e.g. 'de' or 'en-US'.", - ), - 'name' => array( - 'type' => 'varchar', - 'length' => 64, - 'not null' => TRUE, - 'default' => '', - 'description' => 'Language name.', - ), - 'direction' => array( - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - 'description' => 'Direction of language (Left-to-Right = 0, Right-to-Left = 1).', - ), - 'weight' => array( - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - 'description' => 'Weight, used in lists of languages.', - ), - 'locked' => array( - 'type' => 'int', - 'size' => 'tiny', - 'not null' => TRUE, - 'default' => 0, - 'description' => 'A boolean indicating whether the administrator can edit or delete the language.', - ), - ), - 'primary key' => array('langcode'), - 'indexes' => array( - 'list' => array('weight', 'name'), - ), - ); - return $schema; -} - -/** * Implements hook_enable(). */ function language_enable() { @@ -121,3 +72,33 @@ function language_disable() { // will be FALSE, because the language module is disabled. variable_set('language_count', 1); } + +/** + * Migrate languages into configuration. + * + * @ingroup config_upgrade + */ +function language_update_8001() { + $result = db_query('SELECT * FROM {language}'); + foreach ($result as $language) { + // Save the config object. + config('language.site_language.' . $language->langcode) + ->set('langcode', $language->langcode) + ->set('direction', $language->direction) + ->set('locked', $language->locked) + ->set('weight', $language->weight) + ->save(); + } +} + +/** + * Drop the {language} table. + */ +function language_update_8002() { + db_drop_table('language'); +} + +/** + * @} End of "defgroup updates-7.x-to-8.x". + * The next series of updates should start at 9000. + */ diff --git a/core/modules/language/language.module b/core/modules/language/language.module index 5b62382..8cb4073 100644 --- a/core/modules/language/language.module +++ b/core/modules/language/language.module @@ -247,7 +247,7 @@ function language_save($language) { watchdog('language', 'The %language (%langcode) language has been updated.', $t_args); } - if (!empty($language->default)) { + if ($language->isDefault()) { // Set the new version of this language as default in a variable. $default_language = language_default(); variable_set('language_default', (array) $language); @@ -336,6 +336,73 @@ function language_css_alter(&$css) { } /** + * Implements MODULE_config_import_create(). + */ +function language_config_import_create($name, $new_config, $old_config) { + if (strpos($name, 'language.site_language.') !== 0) { + return FALSE; + } + + $language = entity_create('language', $new_config->get()); + $language->save(); + return TRUE; +} + +/** + * Implements MODULE_config_import_change(). + */ +function language_config_import_change($name, $new_config, $old_config) { + if (strpos($name, 'language.site_language.') !== 0) { + return FALSE; + } + + list(, , $id) = explode('.', $name); + $language = entity_load('language', $id); + + $language->original = clone $language; + foreach ($old_config->get() as $property => $value) { + $language->original->$property = $value; + } + + foreach ($new_config->get() as $property => $value) { + $language->$property = $value; + } + + $language->save(); + return TRUE; +} + +/** + * Implements MODULE_config_import_delete(). + */ +function language_config_import_delete($name, $new_config, $old_config) { + if (strpos($name, 'language.site_language.') !== 0) { + return FALSE; + } + + list(, , $id) = explode('.', $name); + entity_delete_multiple('language', array($id)); + return TRUE; +} + +/** + * Implements hook_entity_info(). + */ +function language_entity_info() { + $types['language'] = array( + 'label' => 'Language', + 'controller class' => 'Drupal\config\ConfigEntityStorageController', + 'entity class' => 'Drupal\language\Language', + 'config prefix' => 'language.site_language', + 'entity keys' => array( + 'langcode' => 'langcode', + 'uuid' => 'uuid', + ), + ); + return $types; +} + +/** * Implements hook_language_types_info(). * * Defines the three core language types: diff --git a/core/modules/language/language.negotiation.inc b/core/modules/language/language.negotiation.inc index fa6a517..542ce1f 100644 --- a/core/modules/language/language.negotiation.inc +++ b/core/modules/language/language.negotiation.inc @@ -518,7 +518,7 @@ function language_negotiation_url_prefixes_update() { if (empty($prefixes[$language->langcode])) { // For the default language, set the prefix to the empty string, // otherwise use the langcode. - $prefixes[$language->langcode] = !empty($language->default) ? '' : $language->langcode; + $prefixes[$language->langcode] = $language->isDefault() ? '' : $language->langcode; } // Otherwise we keep the configured prefix. } diff --git a/core/modules/node/lib/Drupal/node/Node.php b/core/modules/node/lib/Drupal/node/Node.php index 51077c7..45d93f0 100644 --- a/core/modules/node/lib/Drupal/node/Node.php +++ b/core/modules/node/lib/Drupal/node/Node.php @@ -7,8 +7,8 @@ namespace Drupal\node; -use Drupal\entity\ContentEntityInterface; -use Drupal\entity\Entity; +use Drupal\Core\Entity\ContentEntityInterface; +use Drupal\Core\Entity\Entity; /** * Defines the node entity class. @@ -163,21 +163,21 @@ class Node extends Entity implements ContentEntityInterface { public $revision_uid; /** - * Implements Drupal\entity\EntityInterface::id(). + * Implements Drupal\Core\Entity\EntityInterface::id(). */ public function id() { return $this->nid; } /** - * Implements Drupal\entity\EntityInterface::bundle(). + * Implements Drupal\Core\Entity\EntityInterface::bundle(). */ public function bundle() { return $this->type; } /** - * Overrides Drupal\entity\Entity::createDuplicate(). + * Overrides Drupal\Core\Entity\Entity::createDuplicate(). */ public function createDuplicate() { $duplicate = parent::createDuplicate(); @@ -186,7 +186,7 @@ class Node extends Entity implements ContentEntityInterface { } /** - * Overrides Drupal\entity\Entity::getRevisionId(). + * Overrides Drupal\Core\Entity\Entity::getRevisionId(). */ public function getRevisionId() { return $this->vid; diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php index b27e1a6..7924acc 100644 --- a/core/modules/node/lib/Drupal/node/NodeFormController.php +++ b/core/modules/node/lib/Drupal/node/NodeFormController.php @@ -7,8 +7,8 @@ namespace Drupal\node; -use Drupal\entity\EntityInterface; -use Drupal\entity\EntityFormController; +use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityFormController; /** * Form controller for the node edit forms. @@ -21,7 +21,7 @@ class NodeFormController extends EntityFormController { * Fills in a few default values, and then invokes hook_prepare() on the node * type module, and hook_node_prepare() on all modules. * - * Overrides Drupal\entity\EntityFormController::prepareEntity(). + * Overrides Drupal\Core\Entity\EntityFormController::prepareEntity(). */ protected function prepareEntity(EntityInterface $node) { // Set up default values, if required. @@ -51,7 +51,7 @@ class NodeFormController extends EntityFormController { } /** - * Overrides Drupal\entity\EntityFormController::form(). + * Overrides Drupal\Core\Entity\EntityFormController::form(). */ public function form(array $form, array &$form_state, EntityInterface $node) { $user_config = config('user.settings'); @@ -243,7 +243,7 @@ class NodeFormController extends EntityFormController { } /** - * Overrides Drupal\entity\EntityFormController::actions(). + * Overrides Drupal\Core\Entity\EntityFormController::actions(). */ protected function actions(array $form, array &$form_state) { $element = parent::actions($form, $form_state); @@ -269,7 +269,7 @@ class NodeFormController extends EntityFormController { } /** - * Overrides Drupal\entity\EntityFormController::validate(). + * Overrides Drupal\Core\Entity\EntityFormController::validate(). */ public function validate(array $form, array &$form_state) { $node = $this->buildEntity($form, $form_state); @@ -314,7 +314,7 @@ class NodeFormController extends EntityFormController { * form state's entity with the current step's values before proceeding to the * next step. * - * Overrides Drupal\entity\EntityFormController::submit(). + * Overrides Drupal\Core\Entity\EntityFormController::submit(). */ public function submit(array $form, array &$form_state) { $this->submitNodeLanguage($form, $form_state); @@ -376,7 +376,7 @@ class NodeFormController extends EntityFormController { } /** - * Overrides Drupal\entity\EntityFormController::save(). + * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { $node = $this->getEntity($form_state); @@ -412,7 +412,7 @@ class NodeFormController extends EntityFormController { } /** - * Overrides Drupal\entity\EntityFormController::delete(). + * Overrides Drupal\Core\Entity\EntityFormController::delete(). */ public function delete(array $form, array &$form_state) { $destination = array(); diff --git a/core/modules/node/lib/Drupal/node/NodeStorageController.php b/core/modules/node/lib/Drupal/node/NodeStorageController.php index 1b1eedd..55b52c3 100644 --- a/core/modules/node/lib/Drupal/node/NodeStorageController.php +++ b/core/modules/node/lib/Drupal/node/NodeStorageController.php @@ -7,21 +7,21 @@ namespace Drupal\node; -use Drupal\entity\DatabaseStorageController; -use Drupal\entity\EntityInterface; -use Drupal\entity\EntityStorageException; +use Drupal\Core\Entity\DatabaseStorageController; +use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityStorageException; use Exception; /** * Controller class for nodes. * - * This extends the Drupal\entity\DatabaseStorageController class, adding + * This extends the Drupal\Core\Entity\DatabaseStorageController class, adding * required special handling for node entities. */ class NodeStorageController extends DatabaseStorageController { /** - * Overrides Drupal\entity\DatabaseStorageController::create(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::create(). */ public function create(array $values) { $node = parent::create($values); @@ -35,7 +35,7 @@ class NodeStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::delete(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::delete(). */ public function delete($ids) { $entities = $ids ? $this->load($ids) : FALSE; @@ -80,7 +80,7 @@ class NodeStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::save(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::save(). */ public function save(EntityInterface $entity) { $transaction = db_transaction(); @@ -138,7 +138,7 @@ class NodeStorageController extends DatabaseStorageController { /** * Saves a node revision. * - * @param Drupal\entity\EntityInterface $node + * @param Drupal\Core\Entity\EntityInterface $node * The node entity. */ protected function saveRevision(EntityInterface $entity) { @@ -164,7 +164,7 @@ class NodeStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::attachLoad(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::attachLoad(). */ protected function attachLoad(&$nodes, $load_revision = FALSE) { // Create an array of nodes for each content type and pass this to the @@ -189,7 +189,7 @@ class NodeStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::buildQuery(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::buildQuery(). */ protected function buildQuery($ids, $revision_id = FALSE) { // Ensure that uid is taken from the {node} table, @@ -204,7 +204,7 @@ class NodeStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::invokeHook(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::invokeHook(). */ protected function invokeHook($hook, EntityInterface $node) { if ($hook == 'insert' || $hook == 'update') { @@ -253,7 +253,7 @@ class NodeStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::preSave(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::preSave(). */ protected function preSave(EntityInterface $node) { // Before saving the node, set changed and revision times. @@ -269,7 +269,7 @@ class NodeStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::postSave(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::postSave(). */ function postSave(EntityInterface $node, $update) { // Update the node access table for this node, but only if it is the @@ -280,7 +280,7 @@ class NodeStorageController extends DatabaseStorageController { } } /** - * Overrides Drupal\entity\DatabaseStorageController::preDelete(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::preDelete(). */ function preDelete($entities) { if (module_exists('search')) { @@ -291,7 +291,7 @@ class NodeStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::postDelete(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::postDelete(). */ protected function postDelete($nodes) { // Delete values from other tables also referencing this node. diff --git a/core/modules/node/node.api.php b/core/modules/node/node.api.php index a73b851..8032d51 100644 --- a/core/modules/node/node.api.php +++ b/core/modules/node/node.api.php @@ -1,6 +1,6 @@ assertTrue(language_default()->langcode == 'ca', t('Catalan is the default language')); $languages = language_list(LANGUAGE_ALL); foreach ($languages as $language) { - $this->assertTrue($language->default == ($language->langcode == 'ca'), t('@language default property properly set', array('@language' => $language->name))); + $this->assertTrue($language->isDefault() == ($language->langcode == 'ca'), t('@language default property properly set', array('@language' => $language->name))); } // Check that both comments display on the node. diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Term.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Term.php index 87d823a..42ad4c5 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Term.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Term.php @@ -7,8 +7,8 @@ namespace Drupal\taxonomy; -use Drupal\entity\ContentEntityInterface; -use Drupal\entity\Entity; +use Drupal\Core\Entity\ContentEntityInterface; +use Drupal\Core\Entity\Entity; /** * Defines the taxonomy term entity. @@ -92,14 +92,14 @@ class Term extends Entity implements ContentEntityInterface { public $vocabulary_machine_name; /** - * Implements Drupal\entity\EntityInterface::id(). + * Implements Drupal\Core\Entity\EntityInterface::id(). */ public function id() { return $this->tid; } /** - * Implements Drupal\entity\EntityInterface::bundle(). + * Implements Drupal\Core\Entity\EntityInterface::bundle(). */ public function bundle() { return $this->vocabulary_machine_name; diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php index dfa1c3f..c7ee415 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermFormController.php @@ -7,8 +7,8 @@ namespace Drupal\taxonomy; -use Drupal\entity\EntityInterface; -use Drupal\entity\EntityFormController; +use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityFormController; /** * Base for controller for taxonomy term edit forms. @@ -16,7 +16,7 @@ use Drupal\entity\EntityFormController; class TermFormController extends EntityFormController { /** - * Overrides Drupal\entity\EntityFormController::form(). + * Overrides Drupal\Core\Entity\EntityFormController::form(). */ public function form(array $form, array &$form_state, EntityInterface $term) { $vocabulary = taxonomy_vocabulary_load($term->vid); @@ -123,7 +123,7 @@ class TermFormController extends EntityFormController { } /** - * Overrides Drupal\entity\EntityFormController::validate(). + * Overrides Drupal\Core\Entity\EntityFormController::validate(). */ public function validate(array $form, array &$form_state) { parent::validate($form, $form_state); @@ -135,7 +135,7 @@ class TermFormController extends EntityFormController { } /** - * Overrides Drupal\entity\EntityFormController::submit(). + * Overrides Drupal\Core\Entity\EntityFormController::submit(). */ public function submit(array $form, array &$form_state) { $term = parent::submit($form, $form_state); @@ -152,7 +152,7 @@ class TermFormController extends EntityFormController { } /** - * Overrides Drupal\entity\EntityFormController::save(). + * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { $term = $this->getEntity($form_state); @@ -196,7 +196,7 @@ class TermFormController extends EntityFormController { } /** - * Overrides Drupal\entity\EntityFormController::delete(). + * Overrides Drupal\Core\Entity\EntityFormController::delete(). */ public function delete(array $form, array &$form_state) { $destination = array(); diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermStorageController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermStorageController.php index 961ebf0..c77cad5 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermStorageController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermStorageController.php @@ -7,8 +7,8 @@ namespace Drupal\taxonomy; -use Drupal\entity\EntityInterface; -use Drupal\entity\DatabaseStorageController; +use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\DatabaseStorageController; /** * Defines a Controller class for taxonomy terms. @@ -16,7 +16,7 @@ use Drupal\entity\DatabaseStorageController; class TermStorageController extends DatabaseStorageController { /** - * Overrides Drupal\entity\DatabaseStorageController::create(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::create(). * * @param array $values * An array of values to set, keyed by property name. A value for the @@ -41,7 +41,7 @@ class TermStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::buildQuery(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::buildQuery(). */ protected function buildQuery($ids, $revision_id = FALSE) { $query = parent::buildQuery($ids, $revision_id); @@ -55,9 +55,9 @@ class TermStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::buildPropertyQuery(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::buildPropertyQuery(). */ - protected function buildPropertyQuery(\Drupal\entity\EntityFieldQuery $entity_query, array $values) { + protected function buildPropertyQuery(\Drupal\Core\Entity\EntityFieldQuery $entity_query, array $values) { if (isset($values['name'])) { $entity_query->propertyCondition('name', $values['name'], 'LIKE'); unset($values['name']); @@ -66,7 +66,7 @@ class TermStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::postDelete(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::postDelete(). */ protected function postDelete($entities) { // See if any of the term's children are about to be become orphans. @@ -97,7 +97,7 @@ class TermStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::postSave(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::postSave(). */ protected function postSave(EntityInterface $entity, $update) { if (isset($entity->parent)) { @@ -119,7 +119,7 @@ class TermStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::resetCache(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::resetCache(). */ public function resetCache(array $ids = NULL) { drupal_static_reset('taxonomy_term_count_nodes'); diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/EfqTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/EfqTest.php index 8fb20d0..7726dbf 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/EfqTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/EfqTest.php @@ -7,7 +7,7 @@ namespace Drupal\taxonomy\Tests; -use Drupal\entity\EntityFieldQuery; +use Drupal\Core\Entity\EntityFieldQuery; /** * Tests the functionality of EntityFieldQuery for taxonomy entities. diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Vocabulary.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Vocabulary.php index 13f6bbf..e32f285 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Vocabulary.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Vocabulary.php @@ -7,7 +7,7 @@ namespace Drupal\taxonomy; -use Drupal\entity\Entity; +use Drupal\Core\Entity\Entity; /** * Defines the taxonomy vocabulary entity. @@ -62,7 +62,7 @@ class Vocabulary extends Entity { public $weight = 0; /** - * Implements Drupal\entity\EntityInterface::id(). + * Implements Drupal\Core\Entity\EntityInterface::id(). */ public function id() { return $this->vid; diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php index 667041e..bdeea4c 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyFormController.php @@ -7,8 +7,8 @@ namespace Drupal\taxonomy; -use Drupal\entity\EntityInterface; -use Drupal\entity\EntityFormController; +use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityFormController; /** * Base form controller for vocabulary edit forms. @@ -16,7 +16,7 @@ use Drupal\entity\EntityFormController; class VocabularyFormController extends EntityFormController { /** - * Overrides Drupal\entity\EntityFormController::form(). + * Overrides Drupal\Core\Entity\EntityFormController::form(). */ public function form(array $form, array &$form_state, EntityInterface $vocabulary) { @@ -80,7 +80,7 @@ class VocabularyFormController extends EntityFormController { } /** - * Overrides Drupal\entity\EntityFormController::validate(). + * Overrides Drupal\Core\Entity\EntityFormController::validate(). */ public function validate(array $form, array &$form_state) { parent::validate($form, $form_state); @@ -100,7 +100,7 @@ class VocabularyFormController extends EntityFormController { } /** - * Overrides Drupal\entity\EntityFormController::submit(). + * Overrides Drupal\Core\Entity\EntityFormController::submit(). */ public function submit(array $form, array &$form_state) { // @todo We should not be calling taxonomy_vocabulary_confirm_delete() from @@ -117,7 +117,7 @@ class VocabularyFormController extends EntityFormController { } /** - * Overrides Drupal\entity\EntityFormController::save(). + * Overrides Drupal\Core\Entity\EntityFormController::save(). */ public function save(array $form, array &$form_state) { $vocabulary = $this->getEntity($form_state); diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyStorageController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyStorageController.php index 8f4ef5b..dd5b478 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyStorageController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyStorageController.php @@ -7,8 +7,8 @@ namespace Drupal\taxonomy; -use Drupal\entity\EntityInterface; -use Drupal\entity\DatabaseStorageController; +use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\DatabaseStorageController; /** * Defines a controller class for taxonomy vocabularies. @@ -16,7 +16,7 @@ use Drupal\entity\DatabaseStorageController; class VocabularyStorageController extends DatabaseStorageController { /** - * Overrides Drupal\entity\DatabaseStorageController::buildQuery(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::buildQuery(). */ protected function buildQuery($ids, $revision_id = FALSE) { $query = parent::buildQuery($ids, $revision_id); @@ -27,7 +27,7 @@ class VocabularyStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::postSave(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::postSave(). */ protected function postSave(EntityInterface $entity, $update) { if (!$update) { @@ -39,7 +39,7 @@ class VocabularyStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::preDelete(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::preDelete(). */ protected function preDelete($entities) { // Only load terms without a parent, child terms will get deleted too. @@ -48,7 +48,7 @@ class VocabularyStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::postDelete(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::postDelete(). */ protected function postDelete($entities) { // Load all Taxonomy module fields and delete those which use only this @@ -79,7 +79,7 @@ class VocabularyStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DrupalDatabaseStorageController::resetCache(). + * Overrides Drupal\Core\Entity\DrupalDatabaseStorageController::resetCache(). */ public function resetCache(array $ids = NULL) { drupal_static_reset('taxonomy_vocabulary_get_names'); diff --git a/core/modules/taxonomy/taxonomy.api.php b/core/modules/taxonomy/taxonomy.api.php index 2ef691f..78f03e6 100644 --- a/core/modules/taxonomy/taxonomy.api.php +++ b/core/modules/taxonomy/taxonomy.api.php @@ -1,6 +1,6 @@ getEntity($form_state); diff --git a/core/modules/user/lib/Drupal/user/RegisterFormController.php b/core/modules/user/lib/Drupal/user/RegisterFormController.php index 77aa58b..6e4a260 100644 --- a/core/modules/user/lib/Drupal/user/RegisterFormController.php +++ b/core/modules/user/lib/Drupal/user/RegisterFormController.php @@ -7,7 +7,7 @@ namespace Drupal\user; -use Drupal\entity\EntityInterface; +use Drupal\Core\Entity\EntityInterface; /** * Form controller for the user register forms. @@ -15,7 +15,7 @@ use Drupal\entity\EntityInterface; class RegisterFormController extends AccountFormController { /** - * Overrides Drupal\entity\EntityFormController::form(). + * Overrides Drupal\Core\Entity\EntityFormController::form(). */ public function form(array $form, array &$form_state, EntityInterface $account) { global $user; @@ -60,7 +60,7 @@ class RegisterFormController extends AccountFormController { } /** - * Overrides Drupal\entity\EntityFormController::actions(). + * Overrides Drupal\Core\Entity\EntityFormController::actions(). */ protected function actions(array $form, array &$form_state) { $element = parent::actions($form, $form_state); @@ -69,7 +69,7 @@ class RegisterFormController extends AccountFormController { } /** - * Overrides Drupal\entity\EntityFormController::submit(). + * Overrides Drupal\Core\Entity\EntityFormController::submit(). */ public function submit(array $form, array &$form_state) { $admin = $form_state['values']['administer_users']; @@ -91,7 +91,7 @@ class RegisterFormController extends AccountFormController { } /** - * Overrides Drupal\entity\EntityFormController::submit(). + * Overrides Drupal\Core\Entity\EntityFormController::submit(). */ public function save(array $form, array &$form_state) { $account = $this->getEntity($form_state); diff --git a/core/modules/user/lib/Drupal/user/User.php b/core/modules/user/lib/Drupal/user/User.php index 74e2bf3..2217588 100644 --- a/core/modules/user/lib/Drupal/user/User.php +++ b/core/modules/user/lib/Drupal/user/User.php @@ -7,7 +7,7 @@ namespace Drupal\user; -use Drupal\entity\Entity; +use Drupal\Core\Entity\Entity; /** * Defines the user entity class. @@ -150,7 +150,7 @@ class User extends Entity { public $roles = array(); /** - * Implements Drupal\entity\EntityInterface::id(). + * Implements Drupal\Core\Entity\EntityInterface::id(). */ public function id() { return $this->uid; diff --git a/core/modules/user/lib/Drupal/user/UserStorageController.php b/core/modules/user/lib/Drupal/user/UserStorageController.php index 0cafbc6..2660300 100644 --- a/core/modules/user/lib/Drupal/user/UserStorageController.php +++ b/core/modules/user/lib/Drupal/user/UserStorageController.php @@ -7,20 +7,20 @@ namespace Drupal\user; -use Drupal\entity\EntityInterface; -use Drupal\entity\EntityMalformedException; -use Drupal\entity\DatabaseStorageController; +use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityMalformedException; +use Drupal\Core\Entity\DatabaseStorageController; /** * Controller class for users. * - * This extends the Drupal\entity\DatabaseStorageController class, adding + * This extends the Drupal\Core\Entity\DatabaseStorageController class, adding * required special handling for user objects. */ class UserStorageController extends DatabaseStorageController { /** - * Overrides Drupal\entity\DatabaseStorageController::attachLoad(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::attachLoad(). */ function attachLoad(&$queried_users, $load_revision = FALSE) { // Build an array of user picture IDs so that these can be fetched later. @@ -60,7 +60,7 @@ class UserStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::create(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::create(). */ public function create(array $values) { if (!isset($values['created'])) { @@ -73,7 +73,7 @@ class UserStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::save(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::save(). */ public function save(EntityInterface $entity) { if (empty($entity->uid)) { @@ -84,7 +84,7 @@ class UserStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::preSave(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::preSave(). */ protected function preSave(EntityInterface $entity) { // Update the user password if it has changed. @@ -158,7 +158,7 @@ class UserStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::postSave(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::postSave(). */ protected function postSave(EntityInterface $entity, $update) { @@ -223,7 +223,7 @@ class UserStorageController extends DatabaseStorageController { } /** - * Overrides Drupal\entity\DatabaseStorageController::postDelete(). + * Overrides Drupal\Core\Entity\DatabaseStorageController::postDelete(). */ protected function postDelete($entities) { db_delete('users_roles') diff --git a/core/modules/user/user.api.php b/core/modules/user/user.api.php index 98b9887..660c06b 100644 --- a/core/modules/user/user.api.php +++ b/core/modules/user/user.api.php @@ -1,6 +1,6 @@