diff --git a/core/includes/config.inc b/core/includes/config.inc index 9e2b6dd..a33c4fa 100644 --- a/core/includes/config.inc +++ b/core/includes/config.inc @@ -141,8 +141,8 @@ function config_context_leave() { * @param string $module * The name of the module possibly providing config entities. * - * @return array - * An associative array containing the entity info for any config entities + * @return \Drupal\Core\Entity\Annotation\EntityType[] + * An associative array containing the entity type for any config entities * provided by the requested module, keyed by the entity type. */ function config_get_module_config_entities($module) { @@ -151,7 +151,7 @@ function config_get_module_config_entities($module) { // once per module. $info = entity_get_info(); return array_filter($info, function($entity_info) use ($module) { - return ($entity_info['module'] == $module) && is_subclass_of($entity_info['class'], 'Drupal\Core\Config\Entity\ConfigEntityInterface'); + return ($entity_info->getModule() == $module) && is_subclass_of($entity_info->getClass(), 'Drupal\Core\Config\Entity\ConfigEntityInterface'); }); } @@ -166,7 +166,7 @@ function config_get_module_config_entities($module) { */ function config_get_entity_type_by_name($name) { $entities = array_filter(entity_get_info(), function($entity_info) use ($name) { - return (isset($entity_info['config_prefix']) && strpos($name, $entity_info['config_prefix'] . '.') === 0); + return ($entity_info->getConfigPrefix() && strpos($name, $entity_info->getConfigPrefix() . '.') === 0); }); return key($entities); } diff --git a/core/includes/entity.inc b/core/includes/entity.inc index fe30114..2aaaf7b 100644 --- a/core/includes/entity.inc +++ b/core/includes/entity.inc @@ -17,7 +17,7 @@ * (optional) The entity type (e.g. 'node'). Leave NULL to retrieve * information for all entity types. * - * @return array + * @return \Drupal\Core\Entity\EntityType|\Drupal\Core\Entity\EntityType[] * An array containing the entity type's definition, as retrieved with * \Drupal\Core\Entity\EntityManager. If $entity_type is NULL, an associative * array of all entity type definitions keyed by entity type is returned. @@ -69,7 +69,7 @@ function entity_get_bundles($entity_type = NULL) { // If no bundles are provided, use the entity type name and label. foreach (entity_get_info() as $type => $entity_info) { if (!isset($bundles[$type])) { - $bundles[$type][$type]['label'] = $entity_info['label']; + $bundles[$type][$type]['label'] = $entity_info->getLabel(); } } drupal_alter('entity_bundle_info', $bundles); @@ -265,10 +265,10 @@ function entity_revision_delete($entity_type, $revision_id) { */ function entity_load_by_uuid($entity_type, $uuid, $reset = FALSE) { $entity_info = entity_get_info($entity_type); - if (empty($entity_info['entity_keys']['uuid'])) { + if (!$entity_info->getKey('uuid')) { throw new EntityStorageException("Entity type $entity_type does not support UUIDs."); } - $uuid_key = $entity_info['entity_keys']['uuid']; + $uuid_key = $entity_info->getKey('uuid'); $controller = Drupal::entityManager()->getStorageController($entity_type); if ($reset) { @@ -562,7 +562,7 @@ function entity_form_submit_build_entity($entity_type, $entity, $form, &$form_st // without changing existing entity properties that are not being edited by // this form. Copying field values must be done using // field_attach_extract_form_values(). - $values_excluding_fields = $info['fieldable'] ? array_diff_key($form_state['values'], field_info_instances($entity_type, $entity->bundle())) : $form_state['values']; + $values_excluding_fields = $info->isFieldable() ? array_diff_key($form_state['values'], field_info_instances($entity_type, $entity->bundle())) : $form_state['values']; foreach ($values_excluding_fields as $key => $value) { $entity->set($key, $value); } @@ -575,7 +575,7 @@ function entity_form_submit_build_entity($entity_type, $entity, $form, &$form_st } // Copy field values to the entity. - if ($info['fieldable']) { + if ($info->isFieldable()) { field_attach_extract_form_values($entity, $form, $form_state); } } diff --git a/core/includes/install.inc b/core/includes/install.inc index e0e86cc..4635036 100644 --- a/core/includes/install.inc +++ b/core/includes/install.inc @@ -639,6 +639,7 @@ function drupal_install_system() { // Update the module list to include it. Drupal::moduleHandler()->setModuleList(array('system' => $system_path . '/system.module')); + Drupal::service('kernel')->updateModules(array('system' => $system_path . '/system.module')); config_install_default_config('module', 'system'); diff --git a/core/lib/Drupal/Core/AnnotationReader.php b/core/lib/Drupal/Core/AnnotationReader.php new file mode 100644 index 0000000..b569b2c --- /dev/null +++ b/core/lib/Drupal/Core/AnnotationReader.php @@ -0,0 +1,98 @@ +getClassAnnotations($class_name); + $filtered_annotations = array(); + foreach ($annotations as $annotation) { + if ($annotation instanceOf $annotation_name) { + return $annotation; + } + } + } + + public function getClassAnnotations($class_name) { + return $this->getFromCache($class_name) ?: $this->doGetClassAnnotations($class_name); + } + + protected function doGetClassAnnotations($class_name) { + $this->initialize(); + + $annotations = array(); + if (class_exists($class_name)) { + $reflection_class = new \ReflectionClass($class_name); + $annotations = $this->reader()->getClassAnnotations($reflection_class); + $this->setCache($class_name, $annotations); + } + return $annotations; + } + + protected function doGetClassAnnotationsStatic($class_name) { + $this->initialize(); + $parser = new StaticReflectionParser($class_name, $this->getLoader()); + $reflection_class = $parser->getReflectionClass(); + $annotations = $this->reader()->getClassAnnotations($reflection_class); + $this->setCache($class_name, $annotations); + return $annotations; + } + + protected function reader() { + if (!isset($this->reader)) { + $this->reader = new DoctrineAnnotationReader(); + foreach ($this->globalIgnoreNames() as $name) { + $this->reader->addGlobalIgnoredName($name); + } + } + return $this->reader; + } + + public function setReader($reader) { + $this->reader = $reader; + } + + protected function globalIgnoreNames() { + return array('endlink'); + } + + protected function getFromCache($name) { + return isset($this->cache[$name]) ? $this->cache[$name] : FALSE; + } + + protected function setCache($name, $value) { + $this->cache[$name] = $value; + } + + protected function getLoader() { + return $this->loader ?: $this->defaultLoader(); + } + + public function setLoader($loader) { + $this->loader = $loader; + } + + protected function defaultLoader() { + return drupal_classloader(); + } + + protected function initialize() { + if (!$this->initialized) { + // If the default loader isn't already callable, it's probably an instance + // of the class loader, so make it callable with the right method here. + if (!is_callable($loader = $this->getLoader())) { + $loader = array($loader, 'loadClass'); + } + AnnotationRegistry::registerLoader($loader); + $this->initialized = TRUE; + } + } +} diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityListController.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityListController.php index 41c3ba6..50c3e32 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityListController.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityListController.php @@ -20,7 +20,7 @@ class ConfigEntityListController extends EntityListController { */ public function load() { $entities = parent::load(); - uasort($entities, array($this->entityInfo['class'], 'sort')); + uasort($entities, array($this->entityInfo->getClass(), 'sort')); return $entities; } @@ -38,7 +38,7 @@ public function getOperations(EntityInterface $entity) { $operations['edit']['href'] = $uri['path']; } - if (isset($this->entityInfo['entity_keys']['status'])) { + if ($this->entityInfo->getKey('status')) { if (!$entity->status()) { $operations['enable'] = array( 'title' => t('Enable'), diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php index 7fe3c49..193753d 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php @@ -9,6 +9,8 @@ use Drupal\Component\Uuid\Uuid; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityType; +use Drupal\Core\Entity\EntityControllerInterface; use Drupal\Core\Entity\EntityMalformedException; use Drupal\Core\Entity\EntityStorageControllerBase; use Drupal\Core\Config\Config; @@ -83,18 +85,11 @@ class ConfigStorageController extends EntityStorageControllerBase { * @param \Drupal\Core\Entity\Query\QueryFactory $entity_query_factory * The entity query factory. */ - public function __construct($entity_type, array $entity_info, ConfigFactory $config_factory, StorageInterface $config_storage, QueryFactory $entity_query_factory) { + public function __construct($entity_type, EntityType $entity_info, ConfigFactory $config_factory, StorageInterface $config_storage, QueryFactory $entity_query_factory) { parent::__construct($entity_type, $entity_info); - $this->idKey = $this->entityInfo['entity_keys']['id']; - - if (isset($this->entityInfo['entity_keys']['status'])) { - $this->statusKey = $this->entityInfo['entity_keys']['status']; - } - else { - $this->statusKey = FALSE; - } - + $this->idKey = $this->entityInfo->getKey('id'); + $this->statusKey = $this->entityInfo->getKey('status'); $this->configFactory = $config_factory; $this->configStorage = $config_storage; $this->entityQueryFactory = $entity_query_factory; @@ -103,7 +98,7 @@ public function __construct($entity_type, array $entity_info, ConfigFactory $con /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $entity_type, $entity_info, @@ -210,7 +205,7 @@ public function getQuery($conjunction = 'AND') { * The full configuration prefix, for example 'views.view.'. */ public function getConfigPrefix() { - return $this->entityInfo['config_prefix'] . '.'; + return $this->entityInfo->getConfigPrefix() . '.'; } /** @@ -251,7 +246,7 @@ public static function getIDFromConfigName($config_name, $config_prefix) { * A SelectQuery object for loading the entity. */ protected function buildQuery($ids, $revision_id = FALSE) { - $config_class = $this->entityInfo['class']; + $config_class = $this->entityInfo->getClass(); $prefix = $this->getConfigPrefix(); // Get the names of the configuration entities we are going to load. @@ -310,7 +305,7 @@ protected function attachLoad(&$queried_entities, $revision_id = FALSE) { * Implements Drupal\Core\Entity\EntityStorageControllerInterface::create(). */ public function create(array $values) { - $class = $this->entityInfo['class']; + $class = $this->entityInfo->getClass(); $class::preCreate($this, $values); // Set default language to site default if not provided. @@ -349,7 +344,7 @@ public function delete(array $entities) { return; } - $entity_class = $this->entityInfo['class']; + $entity_class = $this->entityInfo->getClass(); $entity_class::preDelete($this, $entities); foreach ($entities as $id => $entity) { $this->invokeHook('predelete', $entity); @@ -495,7 +490,7 @@ public function importCreate($name, Config $new_config, Config $old_config) { * A configuration object containing the old configuration data. */ public function importUpdate($name, Config $new_config, Config $old_config) { - $id = static::getIDFromConfigName($name, $this->entityInfo['config_prefix']); + $id = static::getIDFromConfigName($name, $this->entityInfo->getConfigPrefix()); $entity = $this->load($id); $entity->original = clone $entity; @@ -525,7 +520,7 @@ public function importUpdate($name, Config $new_config, Config $old_config) { * A configuration object containing the old configuration data. */ public function importDelete($name, Config $new_config, Config $old_config) { - $id = static::getIDFromConfigName($name, $this->entityInfo['config_prefix']); + $id = static::getIDFromConfigName($name, $this->entityInfo->getConfigPrefix()); $entity = $this->load($id); $entity->delete(); return TRUE; diff --git a/core/lib/Drupal/Core/Config/Entity/Query/Query.php b/core/lib/Drupal/Core/Config/Entity/Query/Query.php index c6320f3..eef292e 100644 --- a/core/lib/Drupal/Core/Config/Entity/Query/Query.php +++ b/core/lib/Drupal/Core/Config/Entity/Query/Query.php @@ -83,9 +83,10 @@ public function condition($property, $value = NULL, $operator = NULL, $langcode public function execute() { // Load all config files. $entity_info = $this->entityManager->getDefinition($this->getEntityType()); - $prefix = $entity_info['config_prefix'] . '.'; + $prefix = $entity_info->getConfigPrefix() . '.'; $prefix_length = strlen($prefix); $names = $this->configStorage->listAll($prefix); + $configs = array(); foreach ($names as $name) { $configs[substr($name, $prefix_length)] = config($name)->get(); diff --git a/core/lib/Drupal/Core/Discovery/DiscoverableInterface.php b/core/lib/Drupal/Core/Discovery/DiscoverableInterface.php new file mode 100644 index 0000000..6938c9b --- /dev/null +++ b/core/lib/Drupal/Core/Discovery/DiscoverableInterface.php @@ -0,0 +1,7 @@ +name = $name; + $this->directories = $directories; + } + + public function findAll() { + $parser = $this->parser(); + $all = array_map(function($file) use ($parser) { + return $parser->parse(file_get_contents($file)); + }, $this->findFiles()); + return $all; + } + + protected function parser() { + if (!isset($this->parser)) { + $this->parser = new Parser(); + } + return $this->parser; + } + + protected function findFiles() { + $files = array(); + foreach ($this->directories as $directory) { + $file = $directory . '/' . basename($directory) . '.' . $this->name . '.yml'; + if (file_exists($file)) { + $files[] = $file; + } + } + return $files; + } +} diff --git a/core/lib/Drupal/Core/Entity/Annotation/EntityType.php b/core/lib/Drupal/Core/Entity/Annotation/EntityType.php index b8e4061..ea429b2 100644 --- a/core/lib/Drupal/Core/Entity/Annotation/EntityType.php +++ b/core/lib/Drupal/Core/Entity/Annotation/EntityType.php @@ -7,294 +7,50 @@ namespace Drupal\Core\Entity\Annotation; -use Drupal\Component\Annotation\Plugin; +use Drupal\Component\Annotation\AnnotationInterface; +use Drupal\Component\Utility\NestedArray; /** - * Defines an Entity type annotation object. - * * @Annotation */ -class EntityType extends Plugin { +class EntityType { + + public function __construct($values) { + // Only keep actual default values by ignoring NULL values. + $this->definition = $this->parse(array_filter($values, function ($value) { + return $value !== NULL; + })); + } /** - * The name of the module providing the type. + * Parses an annotation into its definition. * - * @var string + * @param array $values + * The annotation array. + * + * @return array + * The parsed annotation as a definition. */ - public $module; + protected function parse(array $values) { + $definitions = array(); + foreach ($values as $key => $value) { + if ($value instanceof AnnotationInterface) { + $definitions[$key] = $value->get(); + } + elseif (is_array($value)) { + $definitions[$key] = $this->parse($value); + } + else { + $definitions[$key] = $value; + } + } + return $definitions; + } /** - * The name of the entity type class. - * - * This is not provided manually, it will be added by the discovery mechanism. - * - * @var string */ - public $class; - - /** - * The name of the entity type's base table. - * - * @todo This is only used by \Drupal\Core\Entity\DatabaseStorageController. - * - * @var string - */ - public $base_table; - - /** - * An associative array where the keys are the names of different controller - * types (listed below) and the values are the names of the classes that - * implement that controller: - * - storage: The name of the class that is used to load the objects. The - * class must implement \Drupal\Core\Entity\EntityStorageControllerInterface. - * - form: An associative array where the keys are the names of the different - * form operations (such as 'create', 'edit', or 'delete') and the values - * are the names of the controller classes for those operations. The name of - * the operation is passed also to the form controller's constructor, so - * that one class can be used for multiple entity forms when the forms are - * similar. The classes must implement - * \Drupal\Core\Entity\EntityFormControllerInterface - * - list: The name of the class that provides listings of the entities. The - * class must implement \Drupal\Core\Entity\EntityListControllerInterface. - * - render: The name of the class that is used to render the entities. The - * class must implement \Drupal\Core\Entity\EntityRenderControllerInterface. - * - access: The name of the class that is used for access checks. The class - * must implement \Drupal\Core\Entity\EntityAccessControllerInterface. - * Defaults to \Drupal\Core\Entity\EntityAccessController. - * - translation: The name of the controller class that should be used to - * handle the translation process. The class must implement - * \Drupal\content_translation\ContentTranslationControllerInterface. - * - * @todo Interfaces from outside \Drupal\Core or \Drupal\Component should not - * be used here. - * - * @var array - */ - public $controllers = array( - 'access' => 'Drupal\Core\Entity\EntityAccessController', - ); - - /** - * Boolean indicating whether fields can be attached to entities of this type. - * - * @var bool (optional) - */ - public $fieldable = FALSE; - - /** - * Boolean indicating if the persistent cache of field data should be used. - * - * The persistent cache should usually only be disabled if a higher level - * persistent cache is available for the entity type. Defaults to TRUE. - * - * @var bool (optional) - */ - public $field_cache = TRUE; - - /** - * The human-readable name of the type. - * - * @ingroup plugin_translatable - * - * @var \Drupal\Core\Annotation\Translation - */ - public $label; - - /** - * The human-readable name of the entity bundles, e.g. Vocabulary. - * - * @ingroup plugin_translatable - * - * @var \Drupal\Core\Annotation\Translation - */ - public $bundle_label; - - /** - * The name of a function that returns the label of the entity. - * - * The function takes an entity and optional langcode argument, and returns - * the label of the entity. If langcode is omitted, the entity's default - * language is used. The entity label is the main string associated with an - * entity; for example, the title of a node or the subject of a comment. If - * there is an entity object property that defines the label, use the 'label' - * element of the 'entity_keys' return value component to provide this - * information (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\Core\Entity\EntityInterface::label() method, which implements this - * logic. - * - * @var string (optional) - */ - public $label_callback; - - /** - * Boolean indicating whether entities should be statically cached during a page request. - * - * @todo This is only used by \Drupal\Core\Entity\DatabaseStorageController. - * - * @var bool (optional) - */ - public $static_cache = TRUE; - - /** - * Boolean indicating whether entities of this type have multilingual support. - * - * At an entity level, this indicates language support and at a bundle level - * this indicates translation support. - * - * @var bool (optional) - */ - public $translatable = FALSE; - - /** - * @todo content_translation_entity_info_alter() uses this but it is undocumented. - * - * @var array - */ - public $translation = array(); - - /** - * An array describing how the Field API can extract certain information from - * objects of this entity type: - * - id: The name of the property that contains the primary ID of the entity. - * Every entity object passed to the Field API must have this property and - * its value must be numeric. - * - revision: (optional) The name of the property that contains the revision - * ID of the entity. The Field API assumes that all revision IDs are unique - * across all entities of a type. This entry can be omitted if the entities - * of this type are not versionable. - * - bundle: (optional) The name of the property that contains the bundle name - * for the entity. The bundle name defines which set of fields are attached - * to the entity (e.g. what nodes call "content type"). This entry can be - * omitted if this entity type exposes a single bundle (such that all - * entities have the same collection of fields). The name of this single - * bundle will be the same as the entity type. - * - label: The name of the property that contains the entity label. For - * example, if the entity's label is located in $entity->subject, then - * 'subject' should be specified here. If complex logic is required to build - * the label, a 'label_callback' should be defined instead (see the - * $label_callback block above for details). - * - uuid (optional): The name of the property that contains the universally - * unique identifier of the entity, which is used to distinctly identify an - * entity across different systems. - * - * @var array - */ - public $entity_keys = array( - 'revision' => '', - 'bundle' => '', - ); - - /** - * An array describing how the Field API can extract the information it needs - * from the bundle objects for this type (e.g Vocabulary objects for terms; - * not applicable for nodes): - * - bundle: The name of the property that contains the name of the bundle - * object. - * - * This entry can be omitted if this type's bundles do not exist as standalone - * objects. - * - * @var array - */ - public $bundle_keys; - - /** - * The base router path for the entity type's field administration page. - * - * If the entity type has a bundle, include {bundle} in the path. - * - * For example, the node entity type specifies - * "admin/structure/types/manage/{bundle}" as its base field admin path. - * - * @var string (optional) - */ - public $route_base_path; - - /** - * The prefix for the bundles of this entity type. - * - * For example, the comment bundle is prefixed with 'comment_node_'. - * - * @var string (optional) - */ - public $bundle_prefix; - - /** - * The base menu router path to which the entity admin user interface responds. - * - * It can be used to generate UI links and to attach additional router items - * to the entity UI in a generic fashion. - * - * @var string (optional) - */ - public $menu_base_path; - - /** - * The menu router path to be used to view the entity. - * - * @var string (optional) - */ - public $menu_view_path; - - /** - * The menu router path to be used to edit the entity. - * - * @var string (optional) - */ - public $menu_edit_path; - - /** - * A string identifying the menu loader in the router path. - * - * @var string (optional) - */ - public $menu_path_wildcard; - - /** - * Link templates using the URI template syntax. - * - * Links are an array of standard link relations to the URI template that - * should be used for them. Where possible, link relationships should use - * established IANA relationships rather than custom relationships. - * - * Every entity type should, at minimum, define "canonical", which is the - * pattern for URIs to that entity. Even if the entity will have no HTML page - * exposed to users it should still have a canonical URI in order to be - * compatible with web services. Entities that will be user-editable via an - * HTML page must also define an "edit-form" relationship. - * - * By default, the following placeholders are supported: - * - entityType: The machine name of the entity type. - * - bundle: The bundle machine name of the entity. - * - id: The unique ID of the entity. - * - uuid: The UUID of the entity. - * - [entityType]: The entity type itself will also be a valid token for the - * ID of the entity. For instance, a placeholder of {node} used on the Node - * class would have the same value as {id}. This is generally preferred - * over "id" for better self-documentation. - * - * Specific entity types may also expand upon this list by overriding the - * uriPlaceholderReplacements() method. - * - * @link http://www.iana.org/assignments/link-relations/link-relations.xml @endlink - * @link http://tools.ietf.org/html/rfc6570 @endlink - * - * @var array - */ - public $links = array( - 'canonical' => '/entity/{entityType}/{id}', - ); - - /** - * Specifies whether a module exposing permissions for the current entity type - * should use entity-type level granularity, bundle level granularity or just - * skip this entity. The allowed values are respectively "entity_type", - * "bundle" or FALSE. - * - * @var string|bool (optional) - */ - public $permission_granularity = 'entity_type'; + public function get() { + return $this->definition; + } } diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php index e2dc1b4..bce8420 100644 --- a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php +++ b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php @@ -11,6 +11,7 @@ use PDO; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Entity\Query\QueryInterface; +use Drupal\Core\Entity\EntityType; use Drupal\Component\Uuid\Uuid; use Drupal\Component\Utility\NestedArray; use Drupal\Core\Database\Connection; @@ -61,7 +62,7 @@ class DatabaseStorageController extends EntityStorageControllerBase { /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $entity_type, $entity_info, @@ -79,31 +80,20 @@ public static function createInstance(ContainerInterface $container, $entity_typ * @param \Drupal\Core\Database\Connection $database * The database connection to be used. */ - public function __construct($entity_type, array $entity_info, Connection $database) { + public function __construct($entity_type, EntityType $entity_info, Connection $database) { parent::__construct($entity_type, $entity_info); $this->database = $database; // Check if the entity type supports IDs. - if (isset($this->entityInfo['entity_keys']['id'])) { - $this->idKey = $this->entityInfo['entity_keys']['id']; - } - else { - $this->idKey = FALSE; - } - + $this->idKey = $this->entityInfo->getKey('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; - } + $this->uuidKey = $this->entityInfo->getKey('uuid'); // 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']; + $this->revisionKey = $this->entityInfo->getKey('revision'); + if ($this->revisionKey) { + $this->revisionTable = $this->entityInfo->getRevisionTable(); } else { $this->revisionKey = FALSE; @@ -139,11 +129,12 @@ public function loadMultiple(array $ids = NULL) { // Build and execute the query. $query_result = $this->buildQuery($ids)->execute(); - if (!empty($this->entityInfo['class'])) { + $entity_class = $this->getRecordClass(); + if (!empty($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['class'], array(array(), $this->entityType)); + $query_result->setFetchMode(PDO::FETCH_CLASS, $entity_class, array(array(), $this->entityType)); } $queried_entities = $query_result->fetchAllAssoc($this->idKey); } @@ -192,11 +183,11 @@ public function loadRevision($revision_id) { // Build and execute the query. $query_result = $this->buildQuery(array(), $revision_id)->execute(); - if (!empty($this->entityInfo['class'])) { + if ($entity_class = $this->entityInfo->getClass()) { // 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['class'], array(array(), $this->entityType)); + $query_result->setFetchMode(PDO::FETCH_CLASS, $entity_class, array(array(), $this->entityType)); } $queried_entities = $query_result->fetchAllAssoc($this->idKey); @@ -274,7 +265,8 @@ protected function buildPropertyQuery(QueryInterface $entity_query, array $value * A SelectQuery object for loading the entity. */ protected function buildQuery($ids, $revision_id = FALSE) { - $query = $this->database->select($this->entityInfo['base_table'], 'base'); + $base_table = $this->entityInfo->getBaseTable(); + $query = $this->database->select($this->entityInfo->getBaseTable(), 'base'); $query->addTag($this->entityType . '_load_multiple'); @@ -286,11 +278,11 @@ protected function buildQuery($ids, $revision_id = FALSE) { } // Add fields from the {entity} table. - $entity_fields = drupal_schema_fields_sql($this->entityInfo['base_table']); + $entity_fields = drupal_schema_fields_sql($base_table); if ($this->revisionKey) { // Add all fields from the {entity_revision} table. - $entity_revision_fields = drupal_map_assoc(drupal_schema_fields_sql($this->entityInfo['revision_table'])); + $entity_revision_fields = drupal_map_assoc(drupal_schema_fields_sql($this->entityInfo->getRevisionTable())); // The id field is provided by entity, so remove it. unset($entity_revision_fields[$this->idKey]); @@ -336,7 +328,7 @@ protected function buildQuery($ids, $revision_id = FALSE) { */ protected function attachLoad(&$queried_entities, $load_revision = FALSE) { // Attach fields. - if ($this->entityInfo['fieldable']) { + if ($this->entityInfo->isFieldable()) { if ($load_revision) { field_attach_load_revision($this->entityType, $queried_entities); } @@ -363,7 +355,7 @@ protected function attachLoad(&$queried_entities, $load_revision = FALSE) { * Implements \Drupal\Core\Entity\EntityStorageControllerInterface::create(). */ public function create(array $values) { - $entity_class = $this->entityInfo['class']; + $entity_class = $this->entityInfo->getClass(); $entity_class::preCreate($this, $values); $entity = new $entity_class($values, $this->entityType); @@ -393,14 +385,14 @@ public function delete(array $entities) { $transaction = $this->database->startTransaction(); try { - $entity_class = $this->entityInfo['class']; + $entity_class = $this->entityInfo->getClass(); $entity_class::preDelete($this, $entities); foreach ($entities as $id => $entity) { $this->invokeHook('predelete', $entity); } $ids = array_keys($entities); - $this->database->delete($this->entityInfo['base_table']) + $this->database->delete($this->entityInfo->getBaseTable()) ->condition($this->idKey, $ids, 'IN') ->execute(); @@ -445,7 +437,7 @@ public function save(EntityInterface $entity) { if (!$entity->isNew()) { if ($entity->isDefaultRevision()) { - $return = drupal_write_record($this->entityInfo['base_table'], $entity, $this->idKey); + $return = drupal_write_record($this->entityInfo->getBaseTable(), $entity, $this->idKey); } else { // @todo, should a different value be returned when saving an entity @@ -461,7 +453,7 @@ public function save(EntityInterface $entity) { $this->invokeHook('update', $entity); } else { - $return = drupal_write_record($this->entityInfo['base_table'], $entity); + $return = drupal_write_record($this->entityInfo->getBaseTable(), $entity); if ($this->revisionKey) { $this->saveRevision($entity); } @@ -513,7 +505,7 @@ protected function saveRevision(EntityInterface $entity) { if ($entity->isNewRevision()) { drupal_write_record($this->revisionTable, $record); if ($entity->isDefaultRevision()) { - $this->database->update($this->entityInfo['base_table']) + $this->database->update($this->entityInfo->getBaseTable()) ->fields(array($this->revisionKey => $record[$this->revisionKey])) ->condition($this->idKey, $entity->id()) ->execute(); @@ -543,7 +535,7 @@ protected function invokeHook($hook, EntityInterface $entity) { if ($function == 'field_attach_revision_delete') { $function = 'field_attach_delete_revision'; } - if (!empty($this->entityInfo['fieldable']) && function_exists($function)) { + if ($this->entityInfo->isFieldable() && function_exists($function)) { $function($entity); } // Invoke the hook. @@ -566,4 +558,15 @@ public function baseFieldDefinitions() { public function getQueryServiceName() { return 'entity.query.sql'; } + + /** + * Returns the class which should be used in the load class as conversion. + * + * @return string + * Returns the class or an empty string to disable the conversion. + */ + protected function getRecordClass() { + return $this->entityInfo->getClass(); + } + } diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php b/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php index 143a2ab..89127c1 100644 --- a/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php +++ b/core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php @@ -12,6 +12,7 @@ use Drupal\Core\Entity\Query\QueryInterface; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityType; use Drupal\Core\Entity\DatabaseStorageController; use Drupal\Core\Entity\EntityStorageException; use Drupal\Component\Uuid\Uuid; @@ -53,21 +54,15 @@ class DatabaseStorageControllerNG extends DatabaseStorageController { /** * Overrides DatabaseStorageController::__construct(). */ - public function __construct($entity_type, array $entity_info, Connection $database) { + public function __construct($entity_type, EntityType $entity_info, Connection $database) { parent::__construct($entity_type,$entity_info, $database); - $this->bundleKey = !empty($this->entityInfo['entity_keys']['bundle']) ? $this->entityInfo['entity_keys']['bundle'] : FALSE; - $this->entityClass = $this->entityInfo['class']; + $this->bundleKey = $this->entityInfo->getKey('bundle'); + $this->entityClass = $this->entityInfo->getClass(); // Check if the entity type has a dedicated table for properties. - if (!empty($this->entityInfo['data_table'])) { - $this->dataTable = $this->entityInfo['data_table']; + if ($data_table = $this->entityInfo->getDataTable()) { + $this->dataTable = $data_table; } - - // Work-a-round to let load() get stdClass storage records without having to - // override it. We map storage records to entities in - // DatabaseStorageControllerNG:: mapFromStorageRecords(). - // @todo: Remove this once this is moved in the main controller. - unset($this->entityInfo['class']); } /** @@ -165,7 +160,7 @@ protected function buildPropertyQuery(QueryInterface $entity_query, array $value * {@inheritdoc} */ protected function buildQuery($ids, $revision_id = FALSE) { - $query = $this->database->select($this->entityInfo['base_table'], 'base'); + $query = $this->database->select($this->entityInfo->getBaseTable(), 'base'); $is_revision_query = $this->revisionKey && ($revision_id || !$this->dataTable); $query->addTag($this->entityType . '_load_multiple'); @@ -178,11 +173,11 @@ protected function buildQuery($ids, $revision_id = FALSE) { } // Add fields from the {entity} table. - $entity_fields = drupal_schema_fields_sql($this->entityInfo['base_table']); + $entity_fields = drupal_schema_fields_sql($this->entityInfo->getBaseTable()); if ($is_revision_query) { // Add all fields from the {entity_revision} table. - $entity_revision_fields = drupal_map_assoc(drupal_schema_fields_sql($this->entityInfo['revision_table'])); + $entity_revision_fields = drupal_map_assoc(drupal_schema_fields_sql($this->entityInfo->getRevisionTable())); // The ID field is provided by entity, so remove it. unset($entity_revision_fields[$this->idKey]); @@ -290,10 +285,10 @@ protected function attachPropertyData(array &$entities, $revision_id = FALSE) { $field_definition = \Drupal::entityManager()->getFieldDefinitions($this->entityType); $translations = array(); if ($this->revisionTable) { - $data_fields = array_flip(array_diff(drupal_schema_fields_sql($this->entityInfo['revision_table']), drupal_schema_fields_sql($this->entityInfo['base_table']))); + $data_fields = array_flip(array_diff(drupal_schema_fields_sql($this->entityInfo->getRevisionTable()), drupal_schema_fields_sql($this->entityInfo->getBaseTable()))); } else { - $data_fields = array_flip(drupal_schema_fields_sql($this->entityInfo['data_table'])); + $data_fields = array_flip(drupal_schema_fields_sql($this->entityInfo->getDataTable())); } foreach ($data as $values) { @@ -348,10 +343,10 @@ public function save(EntityInterface $entity) { // Create the storage record to be saved. $record = $this->mapToStorageRecord($entity); - + $base_table = $this->entityInfo->getBaseTable(); if (!$entity->isNew()) { if ($entity->isDefaultRevision()) { - $return = drupal_write_record($this->entityInfo['base_table'], $record, $this->idKey); + $return = drupal_write_record($base_table, $record, $this->idKey); } else { // @todo, should a different value be returned when saving an entity @@ -373,7 +368,7 @@ public function save(EntityInterface $entity) { } } else { - $return = drupal_write_record($this->entityInfo['base_table'], $record); + $return = drupal_write_record($base_table, $record); $entity->{$this->idKey}->value = $record->{$this->idKey}; if ($this->revisionKey) { $record->{$this->revisionKey} = $this->saveRevision($entity); @@ -444,7 +439,7 @@ protected function saveRevision(EntityInterface $entity) { if ($entity->isNewRevision()) { drupal_write_record($this->revisionTable, $record); if ($entity->isDefaultRevision()) { - $this->database->update($this->entityInfo['base_table']) + $this->database->update($this->entityInfo->getBaseTable()) ->fields(array($this->revisionKey => $record->{$this->revisionKey})) ->condition($this->idKey, $record->{$this->idKey}) ->execute(); @@ -500,7 +495,7 @@ protected function savePropertyData(EntityInterface $entity) { */ protected function mapToStorageRecord(EntityInterface $entity) { $record = new \stdClass(); - foreach (drupal_schema_fields_sql($this->entityInfo['base_table']) as $name) { + foreach (drupal_schema_fields_sql($this->entityInfo->getBaseTable()) as $name) { $record->$name = $entity->$name->value; } return $record; @@ -518,7 +513,7 @@ protected function mapToStorageRecord(EntityInterface $entity) { protected function mapToRevisionStorageRecord(EntityInterface $entity) { $record = new \stdClass(); $definitions = $entity->getPropertyDefinitions(); - foreach (drupal_schema_fields_sql($this->entityInfo['revision_table']) as $name) { + foreach (drupal_schema_fields_sql($this->entityInfo->getRevisionTable()) as $name) { if (isset($definitions[$name]) && isset($entity->$name->value)) { $record->$name = $entity->$name->value; } @@ -543,10 +538,10 @@ protected function mapToDataStorageRecord(EntityInterface $entity, $langcode) { // non-translatable properties are replicated for each language. $translation = $entity->getTranslation($langcode); $definitions = $translation->getPropertyDefinitions(); - $schema = drupal_get_schema($this->entityInfo['data_table']); + $schema = drupal_get_schema($this->entityInfo->getDataTable()); $record = new \stdClass(); - foreach (drupal_schema_fields_sql($this->entityInfo['data_table']) as $name) { + foreach (drupal_schema_fields_sql($this->entityInfo->getDataTable()) as $name) { $info = $schema['fields'][$name]; $value = isset($definitions[$name]) && isset($translation->$name->value) ? $translation->$name->value : NULL; $record->$name = drupal_schema_get_field_value($info, $value); @@ -581,7 +576,7 @@ public function delete(array $entities) { } $ids = array_keys($entities); - $this->database->delete($this->entityInfo['base_table']) + $this->database->delete($this->entityInfo->getBaseTable()) ->condition($this->idKey, $ids) ->execute(); @@ -614,4 +609,13 @@ public function delete(array $entities) { throw new EntityStorageException($e->getMessage(), $e->getCode(), $e); } } + + /** + * {@inheritdoc} + */ + protected function getRecordClass() { + // Override to disable the record conversion. + return ''; + } + } diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php index 33a62ce..daea8c2 100644 --- a/core/lib/Drupal/Core/Entity/Entity.php +++ b/core/lib/Drupal/Core/Entity/Entity.php @@ -102,7 +102,7 @@ public function isNew() { */ public function isNewRevision() { $info = $this->entityInfo(); - return $this->newRevision || (!empty($info['entity_keys']['revision']) && !$this->getRevisionId()); + return $this->newRevision || ($info->getKey('revision') && !$this->getRevisionId()); } /** @@ -139,11 +139,14 @@ public function bundle() { 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); + $label_callback = $entity_info->getLabelCallback(); + if (function_exists($label_callback)) { + $label = $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']}; + elseif ($label_key = $entity_info->getKey('label')) { + if (isset($this->{$label_key})) { + $label = $this->$label_key; + } } return $label; } @@ -160,8 +163,8 @@ public function uri() { if (isset($bundles[$bundle]['uri_callback'])) { $uri_callback = $bundles[$bundle]['uri_callback']; } - elseif (isset($entity_info['uri_callback'])) { - $uri_callback = $entity_info['uri_callback']; + elseif ($entity_info->getUriCallback()) { + $uri_callback = $entity_info->getUriCallback(); } // Invoke the callback to get the URI. If there is no callback, use the @@ -191,7 +194,7 @@ public function uri() { */ public function uriRelationships() { $entity_info = $this->entityInfo(); - return isset($entity_info['links']) ? array_keys($entity_info['links']) : array(); + return isset($entity_info->links) ? array_keys($entity_info->links) : array(); } /** @@ -324,7 +327,7 @@ public function getTranslationLanguages($include_default = TRUE) { $languages = array($default_language->id => $default_language); $entity_info = $this->entityInfo(); - if ($entity_info['fieldable']) { + if ($entity_info->isFieldable()) { // 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) { @@ -367,18 +370,18 @@ public function delete() { public function createDuplicate() { $duplicate = clone $this; $entity_info = $this->entityInfo(); - $duplicate->{$entity_info['entity_keys']['id']} = NULL; + $duplicate->{$entity_info->getKey('id')} = NULL; // Check if the entity type supports UUIDs and generate a new one if so. - if (!empty($entity_info['entity_keys']['uuid'])) { + if ($entity_info->getKey('uuid')) { $uuid = new Uuid(); - $duplicate->{$entity_info['entity_keys']['uuid']} = $uuid->generate(); + $duplicate->{$entity_info->getKey('uuid')} = $uuid->generate(); } return $duplicate; } /** - * Implements \Drupal\Core\Entity\EntityInterface::entityInfo(). + * {@inheritdoc} */ public function entityInfo() { return \Drupal::entityManager()->getDefinition($this->entityType()); diff --git a/core/lib/Drupal/Core/Entity/EntityControllerInterface.php b/core/lib/Drupal/Core/Entity/EntityControllerInterface.php index 79232c1..8fa95c5 100644 --- a/core/lib/Drupal/Core/Entity/EntityControllerInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityControllerInterface.php @@ -8,6 +8,7 @@ namespace Drupal\Core\Entity; use Drupal\Core\Entity\EntityStorageControllerInterface; +use Drupal\Core\Entity\EntityType; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -38,6 +39,6 @@ * @return static * A new instance of the entity controller. */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info); + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info); } diff --git a/core/lib/Drupal/Core/Entity/EntityCreateAccessCheck.php b/core/lib/Drupal/Core/Entity/EntityCreateAccessCheck.php index 2cce92a..9edf9f6 100644 --- a/core/lib/Drupal/Core/Entity/EntityCreateAccessCheck.php +++ b/core/lib/Drupal/Core/Entity/EntityCreateAccessCheck.php @@ -65,7 +65,7 @@ public function access(Route $route, Request $request) { /** * Prepare the values passed into the storage controller. * - * @param array $definition + * @param \Drupal\Core\Entity\EntityType $definition * The entity type definition. * @param \Symfony\Component\HttpFoundation\Request $request * The request object. @@ -75,7 +75,7 @@ public function access(Route $route, Request $request) { * @return array * An array of values to be used when creating the entity. */ - protected function prepareEntityValues(array $definition, Request $request, $bundle = NULL) { + protected function prepareEntityValues(EntityType $definition, Request $request, $bundle = NULL) { $values = array(); if ($bundle && isset($definition['entity_keys']['bundle'])) { $values[$definition['entity_keys']['bundle']] = $bundle; diff --git a/core/lib/Drupal/Core/Entity/EntityFormController.php b/core/lib/Drupal/Core/Entity/EntityFormController.php index 36fb318..f3b913c 100644 --- a/core/lib/Drupal/Core/Entity/EntityFormController.php +++ b/core/lib/Drupal/Core/Entity/EntityFormController.php @@ -54,7 +54,7 @@ public function __construct(ModuleHandlerInterface $module_handler) { /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $container->get('module_handler') ); @@ -180,7 +180,7 @@ public function form(array $form, array &$form_state) { // @todo Exploit the Field API to generate the default widgets for the // entity properties. $info = $entity->entityInfo(); - if (!empty($info['fieldable'])) { + if ($info->isfieldable()) { field_attach_form($entity, $form, $form_state, $this->getFormLangcode($form_state)); } diff --git a/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php b/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php index 3b064f6..832067c 100644 --- a/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php +++ b/core/lib/Drupal/Core/Entity/EntityFormControllerNG.php @@ -27,7 +27,7 @@ public function form(array $form, array &$form_state) { // @todo Exploit the Field API to generate the default widgets for the // entity fields. $info = $entity->entityInfo(); - if (!empty($info['fieldable'])) { + if ($info->isFieldable()) { field_attach_form($entity, $form, $form_state, $this->getFormLangcode($form_state)); } @@ -60,7 +60,7 @@ public function buildEntity(array $form, array &$form_state) { // field API without changing existing entity fields that are not being // edited by this form. Values of fields handled by field API are copied // by field_attach_extract_form_values() below. - $values_excluding_fields = $info['fieldable'] ? array_diff_key($form_state['values'], field_info_instances($entity_type, $entity->bundle())) : $form_state['values']; + $values_excluding_fields = $info->isFieldable() ? array_diff_key($form_state['values'], field_info_instances($entity_type, $entity->bundle())) : $form_state['values']; $definitions = $entity->getPropertyDefinitions(); foreach ($values_excluding_fields as $key => $value) { if (isset($definitions[$key])) { @@ -76,7 +76,7 @@ public function buildEntity(array $form, array &$form_state) { } // Invoke field API for copying field values. - if ($info['fieldable']) { + if ($info->isFieldable()) { field_attach_extract_form_values($entity, $form, $form_state); } return $entity; diff --git a/core/lib/Drupal/Core/Entity/EntityInterface.php b/core/lib/Drupal/Core/Entity/EntityInterface.php index e965b8e..f29f810 100644 --- a/core/lib/Drupal/Core/Entity/EntityInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityInterface.php @@ -254,7 +254,7 @@ public function createDuplicate(); /** * Returns the info of the type of the entity. * - * @see entity_get_info() + * @return \Drupal\Core\Entity\EntityType */ public function entityInfo(); diff --git a/core/lib/Drupal/Core/Entity/EntityListController.php b/core/lib/Drupal/Core/Entity/EntityListController.php index 88b2207..c82c3bf 100644 --- a/core/lib/Drupal/Core/Entity/EntityListController.php +++ b/core/lib/Drupal/Core/Entity/EntityListController.php @@ -39,7 +39,7 @@ class EntityListController implements EntityListControllerInterface, EntityContr /** * The entity info array. * - * @var array + * @var \Drupal\Core\Entity\Annotation\EntityType * * @see entity_get_info() */ @@ -48,7 +48,7 @@ class EntityListController implements EntityListControllerInterface, EntityContr /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $entity_type, $entity_info, @@ -62,14 +62,14 @@ public static function createInstance(ContainerInterface $container, $entity_typ * * @param string $entity_type * The type of entity to be listed. - * @param array $entity_info + * @param \Drupal\Core\Entity\EntityType $entity_info * An array of entity info for the entity type. * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage * The entity storage controller class. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke hooks on. */ - public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler) { + public function __construct($entity_type, EntityType $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler) { $this->entityType = $entity_type; $this->storage = $storage; $this->entityInfo = $entity_info; @@ -186,7 +186,7 @@ public function render() { '#theme' => 'table', '#header' => $this->buildHeader(), '#rows' => array(), - '#empty' => t('There is no @label yet.', array('@label' => $this->entityInfo['label'])), + '#empty' => t('There is no @label yet.', array('@label' => $this->entityInfo->getLabel())), ); foreach ($this->load() as $entity) { if ($row = $this->buildRow($entity)) { diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php index 4766a91..d81193e 100644 --- a/core/lib/Drupal/Core/Entity/EntityManager.php +++ b/core/lib/Drupal/Core/Entity/EntityManager.php @@ -7,16 +7,12 @@ namespace Drupal\Core\Entity; -use Drupal\Component\Plugin\PluginManagerBase; -use Drupal\Component\Plugin\Factory\DefaultFactory; +use Drupal\Core\AnnotationReader; +use Drupal\Core\Entity\EntityTypes; use Drupal\Component\Utility\NestedArray; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Language\LanguageManager; use Drupal\Core\Language\Language; -use Drupal\Core\Plugin\Discovery\AlterDecorator; -use Drupal\Core\Plugin\Discovery\CacheDecorator; -use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery; -use Drupal\Core\Plugin\Discovery\InfoHookDecorator; use Drupal\Core\Cache\CacheBackendInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -34,7 +30,7 @@ * @see entity_get_info() * @see hook_entity_info_alter() */ -class EntityManager extends PluginManagerBase { +class EntityManager { /** * The injection container that should be passed into the controller factory. @@ -44,6 +40,13 @@ class EntityManager extends PluginManagerBase { protected $container; /** + * Stores all entity types objects. + * + * @var \Drupal\Core\Entity\EntityType[] + */ + protected $entity_types; + + /** * Contains instantiated controllers keyed by controller type and entity type. * * @var array @@ -112,12 +115,7 @@ public function __construct(\Traversable $namespaces, ContainerInterface $contai $this->cache = $cache; $this->languageManager = $language_manager; - $this->discovery = new AnnotatedClassDiscovery('Core/Entity', $namespaces, $annotation_namespaces, 'Drupal\Core\Entity\Annotation\EntityType'); - $this->discovery = new InfoHookDecorator($this->discovery, 'entity_info'); - $this->discovery = new AlterDecorator($this->discovery, 'entity_info'); - $this->discovery = new CacheDecorator($this->discovery, 'entity_info:' . $this->languageManager->getLanguage(Language::TYPE_INTERFACE)->id, 'cache', CacheBackendInterface::CACHE_PERMANENT, array('entity_info' => TRUE)); - - $this->factory = new DefaultFactory($this->discovery); + $this->annotation_reader = new AnnotationReader('Core/Entity', $namespaces, $annotation_namespaces, 'Drupal\Core\Entity\Annotation\EntityType'); $this->container = $container; } @@ -133,8 +131,7 @@ public function __construct(\Traversable $namespaces, ContainerInterface $contai * Returns TRUE if the entity type has the controller, else FALSE. */ public function hasController($entity_type, $controller_type) { - $definition = $this->getDefinition($entity_type); - return !empty($definition['controllers'][$controller_type]); + return $this->getDefinition($entity_type)->hasController($controller_type); } /** @@ -153,7 +150,7 @@ public function hasController($entity_type, $controller_type) { */ public function getControllerClass($entity_type, $controller_type, $nested = NULL) { $definition = $this->getDefinition($entity_type); - $definition = $definition['controllers']; + $definition = $definition->getControllers(); if (empty($definition[$controller_type])) { throw new \InvalidArgumentException(sprintf('The entity (%s) did not specify a %s.', $entity_type, $controller_type)); } @@ -199,16 +196,7 @@ public function getStorageController($entity_type) { * A list controller instance. */ public function getListController($entity_type) { - if (!isset($this->controllers['listing'][$entity_type])) { - $class = $this->getControllerClass($entity_type, 'list'); - if (in_array('Drupal\Core\Entity\EntityControllerInterface', class_implements($class))) { - $this->controllers['listing'][$entity_type] = $class::createInstance($this->container, $entity_type, $this->getDefinition($entity_type)); - } - else { - $this->controllers['listing'][$entity_type] = new $class($entity_type, $this->getStorageController($entity_type)); - } - } - return $this->controllers['listing'][$entity_type]; + return $this->getController($entity_type, 'list'); } /** @@ -328,13 +316,13 @@ public function getAdminPath($entity_type, $bundle) { $admin_path = ''; $entity_info = $this->getDefinition($entity_type); // Check for an entity type's admin base path. - if (isset($entity_info['route_base_path'])) { + if ($route_base_path = $entity_info->getRouteBasePath()) { // If the entity type has a bundle prefix, strip it out of the path. - if (isset($entity_info['bundle_prefix'])) { - $bundle = str_replace($entity_info['bundle_prefix'], '', $bundle); + if ($bundle_prefix = $entity_info->getBundlePrefix()) { + $bundle = str_replace($bundle_prefix, '', $bundle); } // Replace any dynamic 'bundle' portion of the path with the actual bundle. - $admin_path = str_replace('{bundle}', $bundle, $entity_info['route_base_path']); + $admin_path = str_replace('{bundle}', $bundle, $route_base_path); } return $admin_path; @@ -454,4 +442,42 @@ public function clearCachedFieldDefinitions() { $this->cache->deleteTags(array('entity_field_info' => TRUE)); } + public function getDefinitions() { + return $this->entityTypes()->findAll(); + } + + /** + * Returns the entity Type object for a given entity type. + * + * @param string $name + * The name of the entity type. + * + * @return \Drupal\Core\Entity\EntityType + */ + public function getDefinition($name) { + try { + return $this->entityTypes()->findByName($name); + } + catch (\RuntimeException $e) { + return FALSE; + } + } + + public function clearCachedDefinitions() { + } + + protected function entityTypes() { + if (!isset($this->entity_types)) { + $this->entity_types = new EntityTypes; + } + return $this->entity_types; + } + + protected function getAnnotationReader() { + if (!isset($this->annotation_reader)) { + $this->annotation_reader = new \Drupal\Core\AnnotationReader(); + } + return $this->annotation_reader; + } + } diff --git a/core/lib/Drupal/Core/Entity/EntityNG.php b/core/lib/Drupal/Core/Entity/EntityNG.php index a6768e8..e2f6236 100644 --- a/core/lib/Drupal/Core/Entity/EntityNG.php +++ b/core/lib/Drupal/Core/Entity/EntityNG.php @@ -222,7 +222,7 @@ public function uuid() { public function uri($rel = 'canonical') { $entity_info = $this->entityInfo(); - $link_templates = isset($entity_info['links']) ? $entity_info['links'] : array(); + $link_templates = isset($entity_info->links) ? $entity_info->links : array(); if (isset($link_templates[$rel])) { $template = $link_templates[$rel]; @@ -581,7 +581,7 @@ public function addTranslation($langcode, array $values = array()) { // Instantiate a new empty entity so default values will be populated in the // specified language. $info = $this->entityInfo(); - $default_values = array($info['entity_keys']['bundle'] => $this->bundle, 'langcode' => $langcode); + $default_values = array($info->getKey('bundle') => $this->bundle, 'langcode' => $langcode); $entity = \Drupal::entityManager() ->getStorageController($this->entityType()) ->create($default_values); @@ -780,16 +780,16 @@ public function createDuplicate() { $duplicate = clone $this; $entity_info = $this->entityInfo(); - $duplicate->{$entity_info['entity_keys']['id']}->value = NULL; + $duplicate->{$entity_info->getKey('id')}->value = NULL; // Check if the entity type supports UUIDs and generate a new one if so. - if (!empty($entity_info['entity_keys']['uuid'])) { - $duplicate->{$entity_info['entity_keys']['uuid']}->applyDefaultValue(); + if ($entity_info->hasKey('uuid')) { + $duplicate->{$entity_info->getKey('uuid')}->applyDefaultValue(); } // Check whether the entity type supports revisions and initialize it if so. - if (!empty($entity_info['entity_keys']['revision'])) { - $duplicate->{$entity_info['entity_keys']['revision']}->value = NULL; + if ($entity_info->hasKey('revision')) { + $duplicate->{$entity_info->getKey('revision')}->value = NULL; } return $duplicate; @@ -823,11 +823,13 @@ public function label($langcode = NULL) { if (!isset($langcode)) { $langcode = $this->activeLangcode; } - if (isset($entity_info['label_callback']) && function_exists($entity_info['label_callback'])) { - $label = $entity_info['label_callback']($this->entityType, $this, $langcode); + if (($label_callback = $entity_info->getLabelCallback()) && function_exists($label_callback)) { + $label = $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']}->value; + elseif ($label_key = $entity_info->getKey('label')) { + if (isset($this->{$label_key})) { + $label = $this->{$label_key}->value; + } } return $label; } diff --git a/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php b/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php index ea4e06c..d71fc7f 100644 --- a/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php +++ b/core/lib/Drupal/Core/Entity/EntityStorageControllerBase.php @@ -38,7 +38,7 @@ /** * Array of information about the entity. * - * @var array + * @var \Drupal\Core\Entity\EntityType * * @see entity_get_info() */ @@ -74,14 +74,14 @@ * * @param string $entity_type * The entity type for which the instance is created. - * @param array $entity_info + * @param \Drupal\Core\Entity\EntityType $entity_info * An array of entity info for the entity type. */ public function __construct($entity_type, $entity_info) { $this->entityType = $entity_type; $this->entityInfo = $entity_info; // Check if the entity type supports static caching of loaded entities. - $this->cache = !empty($this->entityInfo['static_cache']); + $this->cache = $this->entityInfo->staticCacheable(); } /** diff --git a/core/lib/Drupal/Core/Entity/EntityType.php b/core/lib/Drupal/Core/Entity/EntityType.php new file mode 100644 index 0000000..eb84608 --- /dev/null +++ b/core/lib/Drupal/Core/Entity/EntityType.php @@ -0,0 +1,737 @@ + array(), + 'list' => NULL, + 'render' => NULL, + 'access' => 'Drupal\Core\Entity\EntityAccessController', + ); + + /** + * Boolean indicating whether fields can be attached to entities of this type. + * + * @var bool (optional) + */ + public $fieldable = FALSE; + + /** + * Boolean indicating if the persistent cache of field data should be used. + * + * The persistent cache should usually only be disabled if a higher level + * persistent cache is available for the entity type. Defaults to TRUE. + * + * @var bool (optional) + */ + public $field_cache = TRUE; + + /** + * The human-readable name of the type. + * + * @ingroup plugin_translatable + * + * @var \Drupal\Core\Annotation\Translation + */ + public $label; + + /** + * The human-readable name of the entity bundles, e.g. Vocabulary. + * + * @ingroup plugin_translatable + * + * @var \Drupal\Core\Annotation\Translation + */ + public $bundle_label; + + /** + * The name of a function that returns the label of the entity. + * + * The function takes an entity and optional langcode argument, and returns + * the label of the entity. If langcode is omitted, the entity's default + * language is used. The entity label is the main string associated with an + * entity; for example, the title of a node or the subject of a comment. If + * there is an entity object property that defines the label, use the 'label' + * element of the 'entity_keys' return value component to provide this + * information (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\Core\Entity\EntityInterface::label() method, which implements this + * logic. + * + * @var string (optional) + */ + public $label_callback; + + /** + * Boolean indicating whether entities should be statically cached during a page request. + * + * @todo This is only used by \Drupal\Core\Entity\DatabaseStorageController. + * + * @var bool (optional) + */ + public $static_cache = TRUE; + + /** + * Boolean indicating whether entities of this type have multilingual support. + * + * At an entity level, this indicates language support and at a bundle level + * this indicates translation support. + * + * @var bool (optional) + */ + public $translatable = FALSE; + + /** + * @todo content_translation_entity_info_alter() uses this but it is undocumented. + * + * @var array + */ + public $translation = array(); + + /** + * An array describing how the Field API can extract certain information from + * objects of this entity type: + * - id: The name of the property that contains the primary ID of the entity. + * Every entity object passed to the Field API must have this property and + * its value must be numeric. + * - revision: (optional) The name of the property that contains the revision + * ID of the entity. The Field API assumes that all revision IDs are unique + * across all entities of a type. This entry can be omitted if the entities + * of this type are not versionable. + * - bundle: (optional) The name of the property that contains the bundle name + * for the entity. The bundle name defines which set of fields are attached + * to the entity (e.g. what nodes call "content type"). This entry can be + * omitted if this entity type exposes a single bundle (such that all + * entities have the same collection of fields). The name of this single + * bundle will be the same as the entity type. + * - label: The name of the property that contains the entity label. For + * example, if the entity's label is located in $entity->subject, then + * 'subject' should be specified here. If complex logic is required to build + * the label, a 'label_callback' should be defined instead (see the + * $label_callback block above for details). + * - uuid (optional): The name of the property that contains the universally + * unique identifier of the entity, which is used to distinctly identify an + * entity across different systems. + * + * @var array + */ + public $entity_keys = array( + 'revision' => '', + 'bundle' => '', + ); + + /** + * An array describing how the Field API can extract the information it needs + * from the bundle objects for this type (e.g Vocabulary objects for terms; + * not applicable for nodes): + * - bundle: The name of the property that contains the name of the bundle + * object. + * + * This entry can be omitted if this type's bundles do not exist as standalone + * objects. + * + * @var array + */ + public $bundle_keys; + + /** + * The base router path for the entity type's field administration page. + * + * If the entity type has a bundle, include {bundle} in the path. + * + * For example, the node entity type specifies + * "admin/structure/types/manage/{bundle}" as its base field admin path. + * + * @var string (optional) + */ + public $route_base_path; + + /** + * The prefix for the bundles of this entity type. + * + * For example, the comment bundle is prefixed with 'comment_node_'. + * + * @var string (optional) + */ + public $bundle_prefix; + + /** + * The base menu router path to which the entity admin user interface responds. + * + * It can be used to generate UI links and to attach additional router items + * to the entity UI in a generic fashion. + * + * @var string (optional) + */ + public $menu_base_path; + + /** + * The menu router path to be used to view the entity. + * + * @var string (optional) + */ + public $menu_view_path; + + /** + * The menu router path to be used to edit the entity. + * + * @var string (optional) + */ + public $menu_edit_path; + + /** + * A string identifying the menu loader in the router path. + * + * @var string (optional) + */ + public $menu_path_wildcard; + + /** + * Link templates using the URI template syntax. + * + * Links are an array of standard link relations to the URI template that + * should be used for them. Where possible, link relationships should use + * established IANA relationships rather than custom relationships. + * + * Every entity type should, at minimum, define "canonical", which is the + * pattern for URIs to that entity. Even if the entity will have no HTML page + * exposed to users it should still have a canonical URI in order to be + * compatible with web services. Entities that will be user-editable via an + * HTML page must also define an "edit-form" relationship. + * + * By default, the following placeholders are supported: + * - entityType: The machine name of the entity type. + * - bundle: The bundle machine name of the entity. + * - id: The unique ID of the entity. + * - uuid: The UUID of the entity. + * - [entityType]: The entity type itself will also be a valid token for the + * ID of the entity. For instance, a placeholder of {node} used on the Node + * class would have the same value as {id}. This is generally preferred + * over "id" for better self-documentation. + * + * Specific entity types may also expand upon this list by overriding the + * uriPlaceholderReplacements() method. + * + * @link http://www.iana.org/assignments/link-relations/link-relations.xml @endlink + * @link http://tools.ietf.org/html/rfc6570 @endlink + * + * @var array + */ + public $links = array( + 'canonical' => '/entity/{entityType}/{id}', + ); + + /** + * Specifies whether a module exposing permissions for the current entity type + * should use entity-type level granularity, bundle level granularity or just + * skip this entity. The allowed values are respectively "entity_type", + * "bundle" or FALSE. + * + * @var string|bool (optional) + */ + public $permission_granularity = 'entity_type'; + + /** + * @todo + */ + public $config_prefix; + + /** + * Constructs a EntityType object. + * + * Builds up the plugin definition and invokes the get() method for any + * classed annotations that were used. + */ + public function __construct($values) { + foreach ($values as $key => $value) { + $this->{$key} = $value; + } + } + + /** + * Returns the name of the module providing the entity type. + * + * @return string + */ + public function getModule() { + return $this->module; + } + + /** + * Returns the name of the entity type class. + * + * This is not provided manually, it will be added by the discovery mechanism. + * + * @return string + */ + public function getClass() { + return $this->class; + } + + /** + * Sets the name of the entity type class. + * + * @param string $class + * The class + full namespace of the entity type. + * + * @return string + */ + public function setClass($class) { + return $this->class = $class; + } + + /** + * The name of the entity type's base table. + * + * @todo This is only used by \Drupal\Core\Entity\DatabaseStorageController. + * + * @return string + */ + public function getBaseTable() { + return $this->base_table; + } + + /** + * Whether the entity type has a base table + * + * @return bool + * Returns TRUE if the entity type has a base table else FALSE. + */ + public function hasBaseTable() { + return isset($this->base_table); + } + + /** + * The data table of the entity type. + * + * @return string|FALSE + * Returns the data table else FALSE. + */ + public function getDataTable() { + return $this->hasDataTable() ? $this->data_table : FALSE; + } + + /** + * Whether the entity type has a data table. + * + * @return bool + * Returns TRUE if the entity type has a data table else FALSE. + */ + public function hasDataTable() { + return isset($this->data_table); + } + + /** + * Whether the entity type has a revision table. + * + * @return bool + * Returns TRUE if the entity type has a revision table else FALSE. + */ + public function hasRevisionTable() { + return isset($this->revision_table); + } + + /** + * The revision table of the entity type. + * + * @return string|FALSE + * Returns the revision table else FALSE. + */ + public function getRevisionTable() { + return $this->hasRevisionTable() ? $this->revision_table : FALSE; + } + + /** + * An associative array where the keys are the names of different controller + * types (listed below) and the values are the names of the classes that + * implement that controller: + * - storage: The name of the class that is used to load the objects. The + * class must implement \Drupal\Core\Entity\EntityStorageControllerInterface. + * - form: An associative array where the keys are the names of the different + * form operations (such as 'create', 'edit', or 'delete') and the values + * are the names of the controller classes for those operations. The name of + * the operation is passed also to the form controller's constructor, so + * that one class can be used for multiple entity forms when the forms are + * similar. The classes must implement + * \Drupal\Core\Entity\EntityFormControllerInterface + * - list: The name of the class that provides listings of the entities. The + * class must implement \Drupal\Core\Entity\EntityListControllerInterface. + * - render: The name of the class that is used to render the entities. The + * class must implement \Drupal\Core\Entity\EntityRenderControllerInterface. + * - access: The name of the class that is used for access checks. The class + * must implement \Drupal\Core\Entity\EntityAccessControllerInterface. + * Defaults to \Drupal\Core\Entity\EntityAccessController. + * - translation: The name of the controller class that should be used to + * handle the translation process. The class must implement + * \Drupal\translation_entity\EntityTranslationControllerInterface. + * + * @todo Interfaces from outside \Drupal\Core or \Drupal\Component should not + * be used here. + * + * @return array + */ + public function getControllers() { + return $this->controllers + array( + 'form' => array(), + 'list' => '', + 'render' => '', + 'access' => 'Drupal\Core\Entity\EntityAccessController', + ); + } + + public function getController($controller) { + $controllers = $this->getControllers(); + return $controllers[$controller]; + } + + public function setController($controller, $value) { + return $this->controllers[$controller] = $value; + } + + public function hasController($controller) { + $controllers = $this->getControllers(); + return isset($controllers[$controller]); + } + + /** + * Boolean indicating whether fields can be attached to entities of this type. + * + * @return bool (optional) + * Returns TRUE if the entity type can has fields, otherwise FALSE. + */ + public function isFieldable() { + return isset($this->fieldable) ? $this->fieldable : FALSE; + } + + /** + * Boolean indicating if the persistent cache of field data should be used. + * + * The persistent cache should usually only be disabled if a higher level + * persistent cache is available for the entity type. Defaults to TRUE. + * + * @return bool (optional) + * Returns TRUE if fields on this entity type can be cached, otherwise FALSE. + */ + public function fieldsCacheable() { + return isset($this->field_cache) ? $this->field_cache : TRUE; + } + + /** + * The human-readable name of the type. + */ + public function getLabel() { + return $this->label; + } + + /** + * The human-readable name of the entity bundles, e.g. Vocabulary. + */ + public function getBundleLable() { + return $this->bundle_label; + } + + /** + * The name of a function that returns the label of the entity. + * + * The function takes an entity and optional langcode argument, and returns + * the label of the entity. If langcode is omitted, the entity's default + * language is used. The entity label is the main string associated with an + * entity; for example, the title of a node or the subject of a comment. If + * there is an entity object property that defines the label, use the 'label' + * element of the 'entity_keys' return value component to provide this + * information (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\Core\Entity\EntityInterface::label() method, which implements this + * logic. + * + * @return callable + * A callback for the label. + */ + public function getLabelCallback() { + return isset($this->label_callback) ? $this->label_callback : ''; + } + + public function getUriCallback() { + return $this->uri_callback; + } + + public function setUriCallback($callback) { + return $this->uri_callback = $callback; + } + + /** + * Boolean indicating whether entities should be statically cached during a page request. + * + * @todo This is only used by \Drupal\Core\Entity\DatabaseStorageController. + * + * @return bool (optional) + * Returns TRUE if the entity type should be statically cached, otherwise FALSE. + */ + public function staticCacheable() { + return isset($this->static_cache) ? $this->static_cache : TRUE; + } + + /** + * An array describing how the Field API can extract certain information from + * objects of this entity type: + * - id: The name of the property that contains the primary ID of the entity. + * Every entity object passed to the Field API must have this property and + * its value must be numeric. + * - revision: (optional) The name of the property that contains the revision + * ID of the entity. The Field API assumes that all revision IDs are unique + * across all entities of a type. This entry can be omitted if the entities + * of this type are not versionable. + * - bundle: (optional) The name of the property that contains the bundle name + * for the entity. The bundle name defines which set of fields are attached + * to the entity (e.g. what nodes call "content type"). This entry can be + * omitted if this entity type exposes a single bundle (such that all + * entities have the same collection of fields). The name of this single + * bundle will be the same as the entity type. + * - label: The name of the property that contains the entity label. For + * example, if the entity's label is located in $entity->subject, then + * 'subject' should be specified here. If complex logic is required to build + * the label, a 'label_callback' should be defined instead (see the + * $label_callback block above for details). + * - uuid (optional): The name of the property that contains the universally + * unique identifier of the entity, which is used to distinctly identify an + * entity across different systems. + * + * @var array + */ + public function getKeys() { + return $this->entity_keys + array('revision' => '', 'bundle' => ''); + } + + public function getKey($key) { + $keys = $this->getKeys(); + return isset($keys[$key]) ? $keys[$key] : FALSE ; + } + + public function hasKey($key) { + $keys = $this->getKeys(); + return isset($keys[$key]); + } + + /** + * Get all bundle keys defined on the annotation. + * + * @return array + * An array describing how the Field API can extract the information it needs + * from the bundle objects for this type (e.g Vocabulary objects for terms; + * not applicable for nodes): + * - bundle: The name of the property that contains the name of the bundle + * object. + */ + public function getBundleKeys() { + return isset($this->bundle_keys) ? $this->bundle_keys : array(); + } + + /** + * Returns a single bundle key. + * + * @param string $name + * The name of the bundle key. + * + * @return string + * The value of the bundle key. + */ + public function getBundleKey($name) { + return isset($this->bundle_keys[$name]) ? $this->bundle_keys[$name] : ''; + } + + public function getConfigPrefix() { + return isset($this->config_prefix) ? $this->config_prefix : ''; + } + + /** + * Get the base router path for the entity type's field administration page. + * + * @return string + * The router base path. + * + * @see \Drupal\Core\Entity\Annotation\EntityType::$route_base_path + */ + public function getRouteBasePath() { + return isset($this->route_base_path) ? $this->route_base_path : NULL; + } + + /** + * Get the prefix for the bundles of this entity type. + * + * @return string + * The prefix. + * + * @see \Drupal\Core\Entity\Annotation\EntityType::$bundle_prefix + */ + public function getBundlePrefix() { + return isset($this->bundle_prefix) ? $this->bundle_prefix : ''; + } + + /** + * Get the base menu router path for entity admin user interface paths. + * + * @return string + * The base menu router path. + * + * @see \Drupal\Core\Entity\Annotation\EntityType::$menu_base_path + */ + public function getMenuBasePath() { + return isset($this->menu_base_path) ? $this->menu_base_path : ''; + } + + /** + * Get the menu router path to be used to view the entity. + * + * @return string + * A menu router path. + * + * @see \Drupal\Core\Entity\Annotation\EntityType::$menu_view_path + */ + public function getMenuViewPath() { + return isset($this->menu_view_path) ? $this->menu_view_path : ''; + } + + /** + * Get the menu router path to be uesd to edit the entity. + * + * @return string + * A menu router path. + * + * @see \Drupal\Core\Entity\Annotation\EntityType::$menu_edit_path + */ + public function getMenuEditPath() { + return isset($this->menu_edit_path) ? $this->menu_edit_path : ''; + } + + /** + * Get the identifier in the router path. + * + * @return string + * A identifier. + * + * @see \Drupal\Core\Entity\Annotation\EntityType::$menu_path_wildcard + */ + public function getMenuPathWildcard() { + return isset($this->menu_path_wildcard) ? $this->menu_path_wildcard : ''; + } + + /** + * Returns the granularity of the permissions. + * + * @return string|FALSE + * Returns either "entity_type", "bundle" or FALSE. + * + * @see \Drupal\Core\Entity\Annotation\EntityType::$permission_granularity + */ + public function getPermissionGranularity() { + return $this->permission_granularity; + } + + /** + * Returns whether the entity type is translatable. + * + * @return bool + * Returns TRUE if the entity type is translatable, otherwise FALSE. + * + * @see \Drupal\Core\Entity\Annotation\\Drupal\Core\Entity\Annotation\EntityType::$translatable + */ + public function isTranslatable() { + return isset($this->translatable) ? (bool) $this->translatable : FALSE; + } + + public function setTranslatable($bool = TRUE) { + $this->translatable = $bool; + } + + /** + * @todo + * + * @see \Drupal\Core\Entity\Annotation\\Drupal\Core\Entity\Annotation\EntityType::$translation + */ + public function getTranslation() { + return isset($this->translation) ? $this->translation : array(); + } + + /** + * Returns an arbitrary value of the entity type definition. + * + * @param string $name + * The name of the entity type definition. + * + * @return mixed + * The value of the entity type definition. + */ + public function get($name) { + return isset($this->values[$name]) ? $this->values[$name] : NULL; + } + +} diff --git a/core/lib/Drupal/Core/Entity/EntityTypes.php b/core/lib/Drupal/Core/Entity/EntityTypes.php new file mode 100644 index 0000000..a1b1610 --- /dev/null +++ b/core/lib/Drupal/Core/Entity/EntityTypes.php @@ -0,0 +1,112 @@ +preloaded) { + $class_mappings = $this->loadMappingsFromFiles(); + foreach ($class_mappings as $name => $class) { + $this->types[$name] = $this->factory($class); + } + $this->invokeHooks(); + $this->preloaded = TRUE; + } + return $this->types; + } + + public function findByName($name) { + if (isset($this->types[$name])) { + return $this->types[$name]; + } + + if ($class = $this->getClassFromEntityName($name)) { + $this->types[$name] = $this->factory($class); + $this->invokeHooks(); + return $this->types[$name]; + } + else { + throw new \RuntimeException(sprintf("No such entity type %s!", $name)); + } + } + + protected function factory($class) { + $values = $this->getAnnotation($class) + array('class' => $class); + return new EntityType($values); + } + + protected function invokeHooks() { + foreach ($this->moduleHandler()->getImplementations('entity_info') as $module) { + $function = $module . '_entity_info'; + $function($this->types); + } + $this->moduleHandler()->alter('entity_info', $this->types); + } + + protected function getClassFromEntityName($name) { + $class_mappings = $this->loadMappingsFromFiles(); + return isset($class_mappings[$name]) ? $class_mappings[$name] : FALSE; + } + + protected function loadMappingsFromFiles() { + if (empty($this->class_mapping)) { + $all = $this->fileFinder()->findAll(); + $this->class_mapping = call_user_func_array("array_merge", $all); + } + return $this->class_mapping; + } + + protected function name() { + return 'entity'; + } + + protected function getAnnotation($classname) { + $entity_type_annotation = $this->getAnnotationReader() + ->getClassAnnotation($classname, 'Drupal\Core\Entity\Annotation\EntityType'); + return $entity_type_annotation->get(); + } + + protected function fileFinder() { + if (!isset($this->file_finder)) { + $this->file_finder = new YamlDiscovery($this->name(), $this->directories()); + } + return $this->file_finder; + } + + protected function directories() { + return $this->moduleHandler()->getModuleDirectories(); + } + + protected function moduleHandler() { + return \Drupal::moduleHandler(); + } + + protected function getAnnotationReader() { + if (!isset($this->annotation_reader)) { + $this->annotation_reader = new AnnotationReader(); + } + return $this->annotation_reader; + } + +} diff --git a/core/lib/Drupal/Core/Entity/Plugin/DataType/Deriver/EntityDeriver.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/Deriver/EntityDeriver.php index 67ebea6..bf753c8 100644 --- a/core/lib/Drupal/Core/Entity/Plugin/DataType/Deriver/EntityDeriver.php +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/Deriver/EntityDeriver.php @@ -43,8 +43,8 @@ public function getDerivativeDefinitions(array $base_plugin_definition) { // Add definitions for each entity type and bundle. foreach (entity_get_info() as $entity_type => $info) { $this->derivatives[$entity_type] = array( - 'label' => $info['label'], - 'class' => $info['class'], + 'label' => $info->getLabel(), + 'class' => $info->getClass(), 'constraints' => array('EntityType' => $entity_type), ) + $base_plugin_definition; @@ -53,7 +53,7 @@ public function getDerivativeDefinitions(array $base_plugin_definition) { if ($bundle !== $entity_type) { $this->derivatives[$entity_type . ':' . $bundle] = array( 'label' => $bundle_info['label'], - 'class' => $info['class'], + 'class' => $info->getClass(), 'constraints' => array( 'EntityType' => $entity_type, 'Bundle' => $bundle, diff --git a/core/lib/Drupal/Core/Entity/Query/Sql/Query.php b/core/lib/Drupal/Core/Entity/Query/Sql/Query.php index 6fbae92..1193286 100644 --- a/core/lib/Drupal/Core/Entity/Query/Sql/Query.php +++ b/core/lib/Drupal/Core/Entity/Query/Sql/Query.php @@ -21,7 +21,7 @@ class Query extends QueryBase implements QueryInterface { /** * Contains the entity info for the entity type of that query. * - * @var array + * @var \Drupal\Core\Entity\Annotation\EntityType * * @see \Drupal\Core\Entity\EntityManager */ @@ -117,19 +117,19 @@ public function execute() { protected function prepare() { $entity_type = $this->entityType; $this->entityInfo = $this->entityManager->getDefinition($entity_type); - if (!isset($this->entityInfo['base_table'])) { + if (!($base_table = $this->entityInfo->getBaseTable())) { throw new QueryException("No base table, invalid query."); } - $base_table = $this->entityInfo['base_table']; + $base_table = $base_table; $simple_query = TRUE; - if (isset($this->entityInfo['data_table'])) { + if ($this->entityInfo->getDataTable()) { $simple_query = FALSE; } $this->sqlQuery = $this->connection->select($base_table, 'base_table', array('conjunction' => $this->conjunction)); $this->sqlQuery->addMetaData('entity_type', $entity_type); - $id_field = $this->entityInfo['entity_keys']['id']; + $id_field = $this->entityInfo->getKey('id'); // Add the key field for fetchAllKeyed(). - if (empty($this->entityInfo['entity_keys']['revision'])) { + if (!($this->entityInfo->getKey('revision'))) { // When there is no revision support, the key field is the entity key. $this->sqlFields["base_table.$id_field"] = array('base_table', $id_field); // Now add the value column for fetchAllKeyed(). This is always the @@ -138,7 +138,7 @@ protected function prepare() { } else { // When there is revision support, the key field is the revision key. - $revision_field = $this->entityInfo['entity_keys']['revision']; + $revision_field = $this->entityInfo->getKey('revision'); $this->sqlFields["base_table.$revision_field"] = array('base_table', $revision_field); // Now add the value column for fetchAllKeyed(). This is always the // entity id. diff --git a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php index 2f7156a..84d593d 100644 --- a/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php +++ b/core/lib/Drupal/Core/Entity/Query/Sql/Tables.php @@ -86,16 +86,16 @@ function addField($field, $type, $langcode) { for ($key = 0; $key <= $count; $key ++) { // If there is revision support and only the current revision is being // queried then use the revision id. Otherwise, the entity id will do. - if (!empty($entity_info['entity_keys']['revision']) && $age == FIELD_LOAD_CURRENT) { + if ($revision_key = $entity_info->getKey('revision') && $age == FIELD_LOAD_CURRENT) { // This contains the relevant SQL field to be used when joining entity // tables. - $entity_id_field = $entity_info['entity_keys']['revision']; + $entity_id_field = $revision_key; // This contains the relevant SQL field to be used when joining field // tables. $field_id_field = 'revision_id'; } else { - $entity_id_field = $entity_info['entity_keys']['id']; + $entity_id_field = $entity_info->getKey('id'); $field_id_field = 'entity_id'; } // This can either be the name of an entity property (non-configurable @@ -166,11 +166,12 @@ function addField($field, $type, $langcode) { // finds the property first. The data table is prefered, which is why // it gets added before the base table. $entity_tables = array(); - if (isset($entity_info['data_table'])) { + if ($data_table = $entity_info->getDataTable()) { $this->sqlQuery->addMetaData('simple_query', FALSE); - $entity_tables[$entity_info['data_table']] = drupal_get_schema($entity_info['data_table']); + $entity_tables[$entity_info->getDataTable()] = drupal_get_schema($data_table); } - $entity_tables[$entity_info['base_table']] = drupal_get_schema($entity_info['base_table']); + $entity_base_table = $entity_info->getBaseTable(); + $entity_tables[$entity_base_table] = drupal_get_schema($entity_base_table); $sql_column = $specifier; $table = $this->ensureEntityTable($index_prefix, $specifier, $type, $langcode, $base_table, $entity_id_field, $entity_tables); } @@ -184,8 +185,8 @@ function addField($field, $type, $langcode) { $values = array(); // If there are bundles, pick one. It does not matter which, // properties exist on all bundles. - if (!empty($entity_info['entity keys']['bundle'])) { - $values[$entity_info['entity keys']['bundle']] = key(entity_get_bundles('node')); + if ($bundle_key = $entity_info->getKey('bundle')) { + $values[$bundle_key] = key(entity_get_bundles('node')); } $entity = entity_create($entity_type, $values); $propertyDefinitions = $entity->$specifier->getPropertyDefinitions(); @@ -198,8 +199,8 @@ function addField($field, $type, $langcode) { $entity_type = $propertyDefinitions[$relationship_specifier]['constraints']['EntityType']; $entity_info = entity_get_info($entity_type); // Add the new entity base table using the table and sql column. - $join_condition= '%alias.' . $entity_info['entity_keys']['id'] . " = $table.$sql_column"; - $base_table = $this->sqlQuery->leftJoin($entity_info['base_table'], NULL, $join_condition); + $join_condition= '%alias.' . $entity_info->getKey('id') . " = $table.$sql_column"; + $base_table = $this->sqlQuery->leftJoin($entity_info->getBaseTable(), NULL, $join_condition); $propertyDefinitions = array(); $key++; $index_prefix .= "$next_index_prefix."; diff --git a/core/lib/Drupal/Core/Extension/ModuleHandler.php b/core/lib/Drupal/Core/Extension/ModuleHandler.php index c510192..578d4d1 100644 --- a/core/lib/Drupal/Core/Extension/ModuleHandler.php +++ b/core/lib/Drupal/Core/Extension/ModuleHandler.php @@ -900,4 +900,11 @@ public function uninstall($module_list = array(), $uninstall_dependents = TRUE) return TRUE; } + public function getModuleDirectories() { + $dirs = array(); + foreach ($this->getModuleList() as $module => $filename) { + $dirs[$module] = dirname($filename); + } + return $dirs; + } } diff --git a/core/lib/Drupal/Core/ParamConverter/EntityConverter.php b/core/lib/Drupal/Core/ParamConverter/EntityConverter.php index 50b7d7c..a8f0ff2 100644 --- a/core/lib/Drupal/Core/ParamConverter/EntityConverter.php +++ b/core/lib/Drupal/Core/ParamConverter/EntityConverter.php @@ -71,8 +71,6 @@ public function process(array &$variables, Route $route, array &$converted) { $options = $route->getOptions(); $configuredTypes = isset($options['converters']) ? $options['converters'] : array(); - $entityTypes = array_keys($this->entityManager->getDefinitions()); - foreach ($variable_names as $name) { // Do not process this variable if it's already marked as converted. if (in_array($name, $converted)) { @@ -88,7 +86,7 @@ public function process(array &$variables, Route $route, array &$converted) { $type = $name; } - if (in_array($type, $entityTypes)) { + if ($this->entityManager->getDefinition($type)) { $value = $variables[$name]; $storageController = $this->entityManager->getStorageController($type); diff --git a/core/modules/action/action.module b/core/modules/action/action.module index 58bb4a8..8778a68 100644 --- a/core/modules/action/action.module +++ b/core/modules/action/action.module @@ -71,8 +71,12 @@ function action_menu() { * Implements hook_entity_info(). */ function action_entity_info(&$entity_info) { - $entity_info['action']['controllers']['form']['add'] = 'Drupal\action\ActionAddFormController'; - $entity_info['action']['controllers']['form']['edit'] = 'Drupal\action\ActionEditFormController'; - $entity_info['action']['controllers']['form']['delete'] = 'Drupal\action\Form\ActionDeleteForm'; - $entity_info['action']['controllers']['list'] = 'Drupal\action\ActionListController'; + if (isset($entity_info['action'])) { + $controllers = $entity_info['action']->getController('form'); + $controllers['add'] = 'Drupal\action\ActionAddFormController'; + $controllers['edit'] = 'Drupal\action\ActionEditFormController'; + $controllers['delete'] = 'Drupal\action\Form\ActionDeleteForm'; + $entity_info['action']->setController('form', $controllers); + $entity_info['action']->setController('list', 'Drupal\action\ActionListController'); + } } diff --git a/core/modules/action/lib/Drupal/action/ActionAddFormController.php b/core/modules/action/lib/Drupal/action/ActionAddFormController.php index 56d7bbf..f206681 100644 --- a/core/modules/action/lib/Drupal/action/ActionAddFormController.php +++ b/core/modules/action/lib/Drupal/action/ActionAddFormController.php @@ -45,7 +45,7 @@ public function __construct(ModuleHandlerInterface $module_handler, EntityStorag /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $container->get('module_handler'), $container->get('plugin.manager.entity')->getStorageController($entity_type), diff --git a/core/modules/action/lib/Drupal/action/ActionFormControllerBase.php b/core/modules/action/lib/Drupal/action/ActionFormControllerBase.php index ff48164..3828ce0 100644 --- a/core/modules/action/lib/Drupal/action/ActionFormControllerBase.php +++ b/core/modules/action/lib/Drupal/action/ActionFormControllerBase.php @@ -12,6 +12,7 @@ use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Action\ConfigurableActionInterface; use Drupal\Core\Entity\EntityStorageControllerInterface; +use Drupal\Core\Entity\EntityType; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -50,7 +51,7 @@ public function __construct(ModuleHandlerInterface $module_handler, EntityStorag /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $container->get('module_handler'), $container->get('plugin.manager.entity')->getStorageController($entity_type) diff --git a/core/modules/action/lib/Drupal/action/ActionListController.php b/core/modules/action/lib/Drupal/action/ActionListController.php index f3d5848..8a80d88 100644 --- a/core/modules/action/lib/Drupal/action/ActionListController.php +++ b/core/modules/action/lib/Drupal/action/ActionListController.php @@ -13,6 +13,7 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Config\Entity\ConfigEntityListController; use Drupal\Core\Entity\EntityStorageControllerInterface; +use Drupal\Core\Entity\EntityType; use \Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\action\Form\ActionAdminManageForm; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -39,7 +40,7 @@ class ActionListController extends ConfigEntityListController implements EntityC * * @param string $entity_type * The entity type. - * @param array $entity_info + * @param \Drupal\Core\Entity\EntityType $entity_info * An array of entity info for the entity type. * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage * The action storage controller. @@ -48,7 +49,7 @@ class ActionListController extends ConfigEntityListController implements EntityC * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke hooks on. */ - public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, ActionManager $action_manager, ModuleHandlerInterface $module_handler) { + public function __construct($entity_type, EntityType $entity_info, EntityStorageControllerInterface $storage, ActionManager $action_manager, ModuleHandlerInterface $module_handler) { parent::__construct($entity_type, $entity_info, $storage, $module_handler); $this->actionManager = $action_manager; @@ -57,7 +58,7 @@ public function __construct($entity_type, array $entity_info, EntityStorageContr /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $entity_type, $entity_info, diff --git a/core/modules/aggregator/aggregator.entity.yml b/core/modules/aggregator/aggregator.entity.yml new file mode 100644 index 0000000..4cc34a8 --- /dev/null +++ b/core/modules/aggregator/aggregator.entity.yml @@ -0,0 +1,2 @@ +aggregator_feed: Drupal\aggregator\Plugin\Core\Entity\Feed +aggregator_item: Drupal\aggregator\Plugin\Core\Entity\Item \ No newline at end of file diff --git a/core/modules/block/block.entity.yml b/core/modules/block/block.entity.yml new file mode 100644 index 0000000..265be2e --- /dev/null +++ b/core/modules/block/block.entity.yml @@ -0,0 +1 @@ +block: Drupal\block\Plugin\Core\Entity\Block \ No newline at end of file diff --git a/core/modules/block/custom_block/custom_block.entity.yml b/core/modules/block/custom_block/custom_block.entity.yml new file mode 100644 index 0000000..3fa9aae --- /dev/null +++ b/core/modules/block/custom_block/custom_block.entity.yml @@ -0,0 +1,2 @@ +custom_block: Drupal\custom_block\Plugin\Core\Entity\CustomBlock +custom_block_type: Drupal\custom_block\Plugin\Core\Entity\CustomBlockType \ No newline at end of file diff --git a/core/modules/block/custom_block/custom_block.module b/core/modules/block/custom_block/custom_block.module index 4e55a85..6913ca4 100644 --- a/core/modules/block/custom_block/custom_block.module +++ b/core/modules/block/custom_block/custom_block.module @@ -146,8 +146,8 @@ function custom_block_load($id) { */ function custom_block_entity_info_alter(&$types) { // Add a translation handler for fields if the language module is enabled. - if (module_exists('language')) { - $types['custom_block']['translation']['custom_block'] = TRUE; + if (isset($types['custom_block']) && module_exists('language')) { + $types['custom_block']->translation['custom_block'] = TRUE; } } diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Form/CustomBlockTypeDeleteForm.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Form/CustomBlockTypeDeleteForm.php index 7e595d2..5c89b97 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/Form/CustomBlockTypeDeleteForm.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Form/CustomBlockTypeDeleteForm.php @@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityConfirmFormBase; use Drupal\Core\Entity\EntityControllerInterface; +use Drupal\Core\Entity\EntityType; use Drupal\Core\Entity\Query\QueryFactory; use Drupal\Core\Extension\ModuleHandlerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -42,7 +43,7 @@ public function __construct(ModuleHandlerInterface $module_handler, QueryFactory /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $container->get('module_handler'), $container->get('entity.query') diff --git a/core/modules/breakpoint/breakpoint.entity.yml b/core/modules/breakpoint/breakpoint.entity.yml new file mode 100644 index 0000000..97aadfb --- /dev/null +++ b/core/modules/breakpoint/breakpoint.entity.yml @@ -0,0 +1,2 @@ +breakpoint: Drupal\breakpoint\Plugin\Core\Entity\Breakpoint +breakpoint_group: Drupal\breakpoint\Plugin\Core\Entity\BreakpointGroup \ No newline at end of file diff --git a/core/modules/breakpoint/breakpoint.module b/core/modules/breakpoint/breakpoint.module index ce3c894..b3daa6c 100644 --- a/core/modules/breakpoint/breakpoint.module +++ b/core/modules/breakpoint/breakpoint.module @@ -192,7 +192,7 @@ function _breakpoint_delete_breakpoints($list, $source_type) { // Remove the breakpoint.breakpoint part of the breakpoint identifier. foreach ($ids as &$id) { - $id = ConfigStorageController::getIDFromConfigName($id, $entity_info['config_prefix']); + $id = ConfigStorageController::getIDFromConfigName($id, $entity_info->getConfigPrefix()); } $breakpoint_groups = entity_load_multiple('breakpoint_group', $ids); @@ -207,7 +207,7 @@ function _breakpoint_delete_breakpoints($list, $source_type) { // Remove the breakpoint.breakpoint part of the breakpoint identifier. foreach ($breakpoint_ids as &$breakpoint_id) { - $breakpoint_id = ConfigStorageController::getIDFromConfigName($breakpoint_id, $entity_info['config_prefix']); + $breakpoint_id = ConfigStorageController::getIDFromConfigName($breakpoint_id, $entity_info->getConfigPrefix()); } $breakpoints = entity_load_multiple('breakpoint', $breakpoint_ids); diff --git a/core/modules/comment/comment.entity.yml b/core/modules/comment/comment.entity.yml new file mode 100644 index 0000000..1d98438 --- /dev/null +++ b/core/modules/comment/comment.entity.yml @@ -0,0 +1 @@ +comment: Drupal\comment\Plugin\Core\Entity\Comment \ No newline at end of file diff --git a/core/modules/comment/tests/modules/comment_test/comment_test.module b/core/modules/comment/tests/modules/comment_test/comment_test.module index 8e903db..47831ca 100644 --- a/core/modules/comment/tests/modules/comment_test/comment_test.module +++ b/core/modules/comment/tests/modules/comment_test/comment_test.module @@ -10,8 +10,8 @@ * Implements hook_entity_info_alter(). */ function comment_test_entity_info_alter(&$info) { - if (language_multilingual()) { + if (isset($info['comment']) && language_multilingual()) { // Enable language handling for comment fields. - $info['comment']['translation']['comment_test'] = TRUE; + $info['comment']->translation['comment_test'] = TRUE; } } diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php index 8be1055..cb2e8e0 100644 --- a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php +++ b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityUnitTest.php @@ -36,13 +36,13 @@ public function testStorageControllerMethods() { $controller = $this->container->get('plugin.manager.entity')->getStorageController('config_test'); $info = entity_get_info('config_test'); - $expected = $info['config_prefix'] . '.'; + $expected = $info->getConfigPrefix() . '.'; $this->assertIdentical($controller->getConfigPrefix(), $expected); // Test the static extractID() method. $expected_id = 'test_id'; - $config_name = $info['config_prefix'] . '.' . $expected_id; - $this->assertIdentical($controller::getIDFromConfigName($config_name, $info['config_prefix']), $expected_id); + $config_name = $info->getConfigPrefix() . '.' . $expected_id; + $this->assertIdentical($controller::getIDFromConfigName($config_name, $info->getConfigPrefix()), $expected_id); // Create three entities, two with the same style. $style = $this->randomName(8); diff --git a/core/modules/config/tests/config_test/config_test.entity.yml b/core/modules/config/tests/config_test/config_test.entity.yml new file mode 100644 index 0000000..680cfa8 --- /dev/null +++ b/core/modules/config/tests/config_test/config_test.entity.yml @@ -0,0 +1,2 @@ +config_query_test: Drupal\config_test\Plugin\Core\Entity\ConfigQueryTest +config_test: Drupal\config_test\Plugin\Core\Entity\ConfigTest \ No newline at end of file diff --git a/core/modules/config/tests/config_test/config_test.module b/core/modules/config/tests/config_test/config_test.module index 41e7c62..e48cff5 100644 --- a/core/modules/config/tests/config_test/config_test.module +++ b/core/modules/config/tests/config_test/config_test.module @@ -88,13 +88,17 @@ function config_test_config_test_create(ConfigTest $config_test) { * Implements hook_entity_info_alter(). */ function config_test_entity_info_alter(&$entity_info) { + if (!isset($entity_info['config_test'])) { + return; + } + // The 'translatable' entity key is not supposed to change over time. In this // case we can safely do it because we set it once and we do not change it for // all the duration of the test session. - $entity_info['config_test']['translatable'] = Drupal::service('state')->get('config_test.translatable'); + $entity_info['config_test']->translatable = Drupal::service('state')->get('config_test.translatable'); // Create a clone of config_test that does not have a status. $entity_info['config_test_no_status'] = $entity_info['config_test']; - unset($entity_info['config_test_no_status']['entity_keys']['status']); - $entity_info['config_test_no_status']['config_prefix'] = 'config_test.no_status'; + unset($entity_info['config_test_no_status']->entity_keys['status']); + $entity_info['config_test_no_status']->config_prefix = 'config_test.no_status'; } diff --git a/core/modules/contact/contact.entity.yml b/core/modules/contact/contact.entity.yml new file mode 100644 index 0000000..00f2bf0 --- /dev/null +++ b/core/modules/contact/contact.entity.yml @@ -0,0 +1,2 @@ +contact_category: Drupal\contact\Plugin\Core\Entity\Category +contact_message: Drupal\contact\Plugin\Core\Entity\Message \ No newline at end of file diff --git a/core/modules/content_translation/content_translation.admin.inc b/core/modules/content_translation/content_translation.admin.inc index 63e71fc..f932658 100644 --- a/core/modules/content_translation/content_translation.admin.inc +++ b/core/modules/content_translation/content_translation.admin.inc @@ -84,7 +84,7 @@ function _content_translation_form_language_content_settings_form_alter(array &$ // Only show the checkbox to enable translation if the bundles in the // entity might have fields and if there are fields to translate. - if (!empty($entity_info['fieldable'])) { + if ($entity_info->fieldsCacheable()) { $fields = field_info_instances($entity_type, $bundle); if ($fields) { $form['settings'][$entity_type][$bundle]['translatable'] = array( @@ -446,7 +446,7 @@ function content_translation_translatable_batch($translatable, $field_name, &$co $query = Drupal::entityQuery($entity_type); $result = $query ->exists($query_field) - ->sort($info['entity_keys']['id']) + ->sort($info->getKey('id')) ->range($offset, 10) ->execute(); diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module index a6988cf..a3f7278 100644 --- a/core/modules/content_translation/content_translation.module +++ b/core/modules/content_translation/content_translation.module @@ -75,38 +75,44 @@ function content_translation_language_types_info_alter(array &$language_types) { */ function content_translation_entity_info_alter(array &$entity_info) { // Provide defaults for translation info. - foreach ($entity_info as $entity_type => &$info) { - if (empty($info['translatable'])) { + /** @var $entity_info \Drupal\Core\Entity\EntityType[] */ + foreach ($entity_info as $entity_type => $info) { + if (!$info->isTranslatable()) { continue; } - if (!isset($info['translation']['content_translation'])) { - $info['translation']['content_translation'] = array(); + if (!isset($info->translation['content_translation'])) { + $info->translation['content_translation'] = array(); } // Every fieldable entity type must have a translation controller class, no // matter if it is enabled for translation or not. As a matter of fact we // might need it to correctly switch field translatability when a field is // shared accross different entities. - $info['controllers'] += array('translation' => 'Drupal\content_translation\ContentTranslationController'); + $info->setController('translation', 'Drupal\content_translation\ContentTranslationController'); // If no menu base path is provided we default to the usual // "entity_type/%entity_type" pattern. - if (!isset($info['menu_base_path'])) { + if (!$info->getMenuBasePath()) { $path = "$entity_type/%$entity_type"; - $info['menu_base_path'] = $path; + $info->menu_base_path = $path; } - $path = $info['menu_base_path']; + $path = $info->getMenuBasePath(); - $info += array( + $default_info = array( 'menu_view_path' => $path, 'menu_edit_path' => "$path/edit", 'menu_path_wildcard' => "%$entity_type", ); + foreach ($default_info as $key => $value) { + if (!isset($info->{$key})) { + $info->{$key} = $value; + } + } $entity_position = count(explode('/', $path)) - 1; - $info['translation']['content_translation'] += array( + $info->translation['content_translation'] += array( 'access_callback' => 'content_translation_translate_access', 'access_arguments' => array($entity_position), ); @@ -135,10 +141,10 @@ function content_translation_menu() { foreach (entity_get_info() as $entity_type => $info) { // Provide the translation UI only for enabled types. if (content_translation_enabled($entity_type)) { - $path = $info['menu_base_path']; + $path = $info->getMenuBasePath(); $entity_position = count(explode('/', $path)) - 1; $keys = array_flip(array('theme_callback', 'theme_arguments', 'access_callback', 'access_arguments', 'load_arguments')); - $menu_info = array_intersect_key($info['translation']['content_translation'], $keys) + array('file' => 'content_translation.pages.inc'); + $menu_info = array_intersect_key($info->translation['content_translation'], $keys) + array('file' => 'content_translation.pages.inc'); $item = array(); // Plugin annotations cannot contain spaces, thus we need to restore them @@ -216,7 +222,7 @@ function content_translation_menu_alter(array &$items) { // Check that the declared menu base paths are actually valid. foreach (entity_get_info() as $entity_type => $info) { if (content_translation_enabled($entity_type)) { - $path = $info['menu_base_path']; + $path = $info->getMenuBasePath(); // If the base path is not defined we cannot provide the translation UI // for this entity type. In some cases the actual base path might not have @@ -229,12 +235,11 @@ function content_translation_menu_alter(array &$items) { $items["$path/translations/add/%language/%language"], $items["$path/translations/delete/%language"] ); - $t_args = array('@entity_type' => isset($info['label']) ? $info['label'] : $entity_type); + $t_args = array('@entity_type' => $info->getLabel() ?: $entity_type); watchdog('content translation', 'The entities of type @entity_type do not define a valid base path: it will not be possible to translate them.', $t_args, WATCHDOG_WARNING); } else { - $entity_position = count(explode('/', $path)) - 1; - $edit_path = $info['menu_edit_path']; + $edit_path = $info->getMenuEditPath(); if (isset($items[$edit_path])) { // If the edit path is a default local task we need to find the parent @@ -450,7 +455,7 @@ function content_translation_enabled($entity_type, $bundle = NULL) { $enabled = FALSE; $info = entity_get_info($entity_type); - if (!empty($info['translatable'])) { + if ($info->isTranslatable()) { $bundles = !empty($bundle) ? array($bundle) : array_keys(entity_get_bundles($entity_type)); foreach ($bundles as $bundle) { if (content_translation_get_config($entity_type, $bundle, 'enabled')) { @@ -481,7 +486,7 @@ function content_translation_types_translatable() { // Check whether the required paths are defined. We need to strip out the // menu loader and replace it with a plain "%" as router items have no // menu loader in them. - $path = _content_translation_menu_strip_loaders($info['menu_base_path']); + $path = _content_translation_menu_strip_loaders($info->getMenuBasePath()); if (!empty($items[$path]) && !empty($items[$path . '/translations'])) { $entity_types[$entity_type] = $entity_type; } @@ -503,7 +508,8 @@ function content_translation_types_translatable() { function content_translation_controller($entity_type) { $entity_info = entity_get_info($entity_type); // @todo Throw an exception if the key is missing. - return new $entity_info['controllers']['translation']($entity_type, $entity_info); + $translation_controller = $entity_info->getController('translation'); + return new $translation_controller($entity_type, $entity_info); } /** @@ -565,10 +571,10 @@ function content_translation_permission() { // Create a translate permission for each enabled entity type and (optionally) // bundle. foreach (entity_get_info() as $entity_type => $info) { - if (!empty($info['permission_granularity'])) { - $t_args = array('@entity_label' => drupal_strtolower(t($info['label']))); + if ($permission_granularity = $info->getPermissionGranularity()) { + $t_args = array('@entity_label' => drupal_strtolower(t($info->getLabel()))); - switch ($info['permission_granularity']) { + switch ($permission_granularity) { case 'bundle': foreach (entity_get_bundles($entity_type) as $bundle => $bundle_info) { if (content_translation_enabled($entity_type, $bundle)) { diff --git a/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php b/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php index 6948642..bd084e1 100644 --- a/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php +++ b/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php @@ -73,6 +73,7 @@ public function retranslate(EntityInterface $entity, $langcode = NULL) { * Implements ContentTranslationControllerInterface::getBasePath(). */ public function getBasePath(EntityInterface $entity) { + // @fixme How to replace this. return $this->getPathInstance($this->entityInfo['menu_base_path'], $entity->id()); } @@ -80,6 +81,7 @@ public function getBasePath(EntityInterface $entity) { * Implements ContentTranslationControllerInterface::getEditPath(). */ public function getEditPath(EntityInterface $entity) { + // @fixme How to replace this. return isset($this->entityInfo['menu_edit_path']) ? $this->getPathInstance($this->entityInfo['menu_edit_path'], $entity->id()) : FALSE; } @@ -87,6 +89,7 @@ public function getEditPath(EntityInterface $entity) { * Implements ContentTranslationControllerInterface::getViewPath(). */ public function getViewPath(EntityInterface $entity) { + // @fixme How to replace this. return isset($this->entityInfo['menu_view_path']) ? $this->getPathInstance($this->entityInfo['menu_view_path'], $entity->id()) : FALSE; } @@ -100,8 +103,8 @@ public function getTranslationAccess(EntityInterface $entity, $op) { $translate_permission = TRUE; // If no permission granularity is defined this entity type does not need an // explicit translate permission. - if (!user_access('translate any entity') && !empty($info['permission_granularity'])) { - $translate_permission = user_access($info['permission_granularity'] == 'bundle' ? "translate {$entity->bundle()} {$entity->entityType()}" : "translate {$entity->entityType()}"); + if (!user_access('translate any entity') && $info->get('permission_granularity')) { + $translate_permission = user_access($info->get('permission_granularity') == 'bundle' ? "translate {$entity->bundle()} {$entity->entityType()}" : "translate {$entity->entityType()}"); } return $translate_permission && user_access("$op content translations"); } @@ -512,6 +515,7 @@ protected function entityFormTitle(EntityInterface $entity) { * The instantiated path. */ protected function getPathInstance($path, $entity_id) { + // @fixme How to replace this. $wildcard = $this->entityInfo['menu_path_wildcard']; return str_replace($wildcard, $entity_id, $path); } diff --git a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationTestBase.php b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationTestBase.php index b635c45..cecdf3c 100644 --- a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationTestBase.php +++ b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationTestBase.php @@ -199,8 +199,8 @@ protected function createEntity($values, $langcode, $bundle_name = NULL) { $entity_values = $values; $entity_values['langcode'] = $langcode; $info = entity_get_info($this->entityType); - if (!empty($info['entity_keys']['bundle'])) { - $entity_values[$info['entity_keys']['bundle']] = $bundle_name ?: $this->bundle; + if ($bundle_key = $info->getKey('bundle')) { + $entity_values[$bundle_key] = $bundle_name ?: $this->bundle; } $controller = $this->container->get('plugin.manager.entity')->getStorageController($this->entityType); if (!($controller instanceof DatabaseStorageControllerNG)) { diff --git a/core/modules/editor/editor.entity.yml b/core/modules/editor/editor.entity.yml new file mode 100644 index 0000000..f83ab0a --- /dev/null +++ b/core/modules/editor/editor.entity.yml @@ -0,0 +1 @@ +editor: Drupal\editor\Plugin\Core\Entity\Editor \ No newline at end of file diff --git a/core/modules/entity/entity.entity.yml b/core/modules/entity/entity.entity.yml new file mode 100644 index 0000000..c16421f --- /dev/null +++ b/core/modules/entity/entity.entity.yml @@ -0,0 +1,4 @@ +entity_display: Drupal\entity\Plugin\Core\Entity\EntityDisplay +entity_form_display: Drupal\entity\Plugin\Core\Entity\EntityFormDisplay +form_mode: Drupal\entity\Plugin\Core\Entity\EntityFormMode +view_mode: Drupal\entity\Plugin\Core\Entity\EntityViewMode \ No newline at end of file diff --git a/core/modules/entity/entity.module b/core/modules/entity/entity.module index ad9d17b..b25816b 100644 --- a/core/modules/entity/entity.module +++ b/core/modules/entity/entity.module @@ -19,7 +19,7 @@ function entity_entity_bundle_rename($entity_type, $bundle_old, $bundle_new) { if ($bundle_old !== $bundle_new) { $ids = config_get_storage_names_with_prefix('entity.display.' . $entity_type . '.' . $bundle_old); foreach ($ids as $id) { - $id = ConfigStorageController::getIDFromConfigName($id, $entity_info['config_prefix']); + $id = ConfigStorageController::getIDFromConfigName($id, $entity_info->getConfigPrefix()); $display = entity_load('entity_display', $id); $new_id = $entity_type . '.' . $bundle_new . '.' . $display->mode; $display->id = $new_id; @@ -33,7 +33,7 @@ function entity_entity_bundle_rename($entity_type, $bundle_old, $bundle_new) { if ($bundle_old !== $bundle_new) { $ids = config_get_storage_names_with_prefix('entity.form_display.' . $entity_type . '.' . $bundle_old); foreach ($ids as $id) { - $id = ConfigStorageController::getIDFromConfigName($id, $entity_info['config_prefix']); + $id = ConfigStorageController::getIDFromConfigName($id, $entity_info->getConfigPrefix()); $form_display = entity_load('entity_form_display', $id); $new_id = $entity_type . '.' . $bundle_new . '.' . $form_display->mode; $form_display->id = $new_id; @@ -51,7 +51,7 @@ function entity_entity_bundle_delete($entity_type, $bundle) { $entity_info = entity_get_info('entity_display'); $ids = config_get_storage_names_with_prefix('entity.display.' . $entity_type . '.' . $bundle); foreach ($ids as &$id) { - $id = ConfigStorageController::getIDFromConfigName($id, $entity_info['config_prefix']); + $id = ConfigStorageController::getIDFromConfigName($id, $entity_info->getConfigPrefix()); } entity_delete_multiple('entity_display', $ids); @@ -59,7 +59,7 @@ function entity_entity_bundle_delete($entity_type, $bundle) { $entity_info = entity_get_info('entity_form_display'); $ids = config_get_storage_names_with_prefix('entity.form_display.' . $entity_type . '.' . $bundle); foreach ($ids as &$id) { - $id = ConfigStorageController::getIDFromConfigName($id, $entity_info['config_prefix']); + $id = ConfigStorageController::getIDFromConfigName($id, $entity_info->getConfigPrefix()); } entity_delete_multiple('entity_form_display', $ids); } diff --git a/core/modules/entity_reference/entity_reference.install b/core/modules/entity_reference/entity_reference.install index c40d3ea..954098b 100644 --- a/core/modules/entity_reference/entity_reference.install +++ b/core/modules/entity_reference/entity_reference.install @@ -31,12 +31,12 @@ function entity_reference_field_schema($field) { ); // Create a foreign key to the target entity type base type. - $entity_manager = Drupal::service('plugin.manager.entity'); + $entity_manager = Drupal::entityManager(); if (is_subclass_of($entity_manager->getControllerClass($field['settings']['target_type'], 'storage'), 'Drupal\Core\Entity\DatabaseStorageController')) { $entity_info = $entity_manager->getDefinition($field['settings']['target_type']); - $base_table = $entity_info['base_table']; - $id_column = $entity_info['entity_keys']['id']; + $base_table = $entity_info->getBaseTable(); + $id_column = $entity_info->getKey('id'); $schema['foreign keys'][$base_table] = array( 'table' => $base_table, diff --git a/core/modules/entity_reference/entity_reference.module b/core/modules/entity_reference/entity_reference.module index 54a7bac..18e456e 100644 --- a/core/modules/entity_reference/entity_reference.module +++ b/core/modules/entity_reference/entity_reference.module @@ -139,8 +139,9 @@ function entity_reference_field_settings_form($field, $instance) { // @todo As the database schema can currently only store numeric IDs of // referenced entities and configuration entities have string IDs, prevent // configuration entities from being referenced. - if (!is_subclass_of($entity_info['class'], '\Drupal\Core\Config\Entity\ConfigEntityInterface')) { - $entity_type_options[$entity_type] = $entity_info['label']; + + if (!is_subclass_of($entity_info->getClass(), '\Drupal\Core\Config\Entity\ConfigEntityInterface')) { + $entity_type_options[$entity_type] = $entity_info->getLabel(); } } diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Derivative/SelectionBase.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Derivative/SelectionBase.php index a1d7991..5c22acc 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Derivative/SelectionBase.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Derivative/SelectionBase.php @@ -27,7 +27,7 @@ public function getDerivativeDefinitions(array $base_plugin_definition) { foreach (entity_get_info() as $entity_type => $info) { if (!in_array($entity_type, $supported_entities)) { $this->derivatives[$entity_type] = $base_plugin_definition; - $this->derivatives[$entity_type]['label'] = t('@entity_type selection', array('@entity_type' => $info['label'])); + $this->derivatives[$entity_type]['label'] = t('@entity_type selection', array('@entity_type' => $info->getLabel())); } } return parent::getDerivativeDefinitions($base_plugin_definition); diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionBase.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionBase.php index de4729c..2471ade 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionBase.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionBase.php @@ -70,7 +70,7 @@ public static function settingsForm(&$field, &$instance) { 'auto_create' => FALSE, ); - if (!empty($entity_info['entity_keys']['bundle'])) { + if ($entity_info->getKey('bundle')) { $bundle_options = array(); foreach ($bundles as $bundle_name => $bundle_info) { $bundle_options[$bundle_name] = $bundle_info['label']; @@ -105,7 +105,7 @@ public static function settingsForm(&$field, &$instance) { // @todo Use Entity::getPropertyDefinitions() when all entity types are // converted to the new Field API. - $fields = drupal_map_assoc(drupal_schema_fields_sql($entity_info['base_table'])); + $fields = drupal_map_assoc(drupal_schema_fields_sql($entity_info->getBaseTable())); foreach (field_info_instances($field['settings']['target_type']) as $bundle_instances) { foreach ($bundle_instances as $instance_name => $instance_info) { $field_info = field_info_field($instance_name); @@ -200,7 +200,7 @@ public function validateReferenceableEntities(array $ids) { $entity_info = entity_get_info($target_type); $query = $this->buildEntityQuery(); $result = $query - ->condition($entity_info['entity_keys']['id'], $ids, 'IN') + ->condition($entity_info->getKey('id'), $ids, 'IN') ->execute(); } @@ -261,12 +261,13 @@ public function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') { $entity_info = entity_get_info($target_type); $query = \Drupal::entityQuery($target_type); + if (!empty($handler_settings['target_bundles'])) { - $query->condition($entity_info['entity_keys']['bundle'], $handler_settings['target_bundles'], 'IN'); + $query->condition($entity_info->getKey('bundle'), $handler_settings['target_bundles'], 'IN'); } - if (isset($match) && isset($entity_info['entity_keys']['label'])) { - $query->condition($entity_info['entity_keys']['label'], $match, $match_operator); + if (isset($match) && $entity_info->getKey('label')) { + $query->condition($entity_info->getKey('label'), $match, $match_operator); } // Add entity-access tag. diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php index 9798a53..2b8dd38 100644 --- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php +++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php @@ -164,8 +164,8 @@ protected function createNewEntity($label, $uid) { } $entity_info = $entity_manager->getDefinition($target_type); - $bundle_key = $entity_info['entity_keys']['bundle']; - $label_key = $entity_info['entity_keys']['label']; + $bundle_key = $entity_info->getKey('bundle'); + $label_key = $entity_info->getKey('label'); return $entity_manager->getStorageController($target_type)->create(array( $label_key => $label, diff --git a/core/modules/field/field.attach.inc b/core/modules/field/field.attach.inc index 5ed17ff..c4201f3 100644 --- a/core/modules/field/field.attach.inc +++ b/core/modules/field/field.attach.inc @@ -584,7 +584,7 @@ function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $ $info = entity_get_info($entity_type); // Only the most current revision of non-deleted fields for cacheable entity // types can be cached. - $cache_read = $load_current && $info['field_cache'] && !$load_deleted; + $cache_read = $load_current && $info->fieldsCacheable() && !$load_deleted; // In addition, do not write to the cache when loading a single field. $cache_write = $cache_read && !isset($options['instance']); @@ -927,7 +927,7 @@ function field_attach_update(EntityInterface $entity) { } $entity_info = $entity->entityInfo(); - if ($entity_info['field_cache']) { + if ($entity_info->fieldsCacheable()) { cache('field')->delete('field:' . $entity->entityType() . ':' . $entity->id()); } } @@ -960,7 +960,7 @@ function field_attach_delete(EntityInterface $entity) { } $entity_info = $entity->entityInfo(); - if ($entity_info['field_cache']) { + if ($entity_info->fieldsCacheable()) { cache('field')->delete('field:' . $entity->entityType() . ':' . $entity->id()); } } diff --git a/core/modules/field/field.entity.yml b/core/modules/field/field.entity.yml new file mode 100644 index 0000000..04ba6db --- /dev/null +++ b/core/modules/field/field.entity.yml @@ -0,0 +1,2 @@ +field_entity: Drupal\field\Plugin\Core\Entity\Field +field_instance: Drupal\field\Plugin\Core\Entity\FieldInstance \ No newline at end of file diff --git a/core/modules/field/field.module b/core/modules/field/field.module index 92a2c45..b181436 100644 --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -234,7 +234,7 @@ function field_system_info_alter(&$info, $file, $type) { */ function field_entity_create(EntityInterface $entity) { $info = $entity->entityInfo(); - if (!empty($info['fieldable'])) { + if ($info->isFieldable()) { field_populate_default_values($entity, $entity->language()->id); } } @@ -910,8 +910,8 @@ function field_extract_bundle($entity_type, $bundle) { } $info = entity_get_info($entity_type); - if (is_object($bundle) && isset($info['bundle_keys']['bundle']) && isset($bundle->{$info['bundle_keys']['bundle']})) { - return $bundle->{$info['bundle_keys']['bundle']}; + if (is_object($bundle) && $info->getBundleKey('bundle') && isset($bundle->{$info->getBundleKey('bundle')})) { + return $bundle->{$info->getBundleKey('bundle')}; } } @@ -1103,14 +1103,14 @@ function theme_field($variables) { function _field_create_entity_from_ids($ids) { $id_properties = array(); $info = entity_get_info($ids->entity_type); - if (isset($info['entity_keys']['id'])) { - $id_properties[$info['entity_keys']['id']] = $ids->entity_id; + if ($id_key = $info->getKey('id')) { + $id_properties[$id_key] = $ids->entity_id; } - if (!empty($info['entity_keys']['revision']) && isset($ids->revision_id)) { - $id_properties[$info['entity_keys']['revision']] = $ids->revision_id; + if ($revision_key = $info->getKey('revision')) { + $id_properties[$revision_key] = $ids->revision_id; } - if (!empty($info['entity_keys']['bundle']) && isset($ids->bundle)) { - $id_properties[$info['entity_keys']['bundle']] = $ids->bundle; + if ($bundle_key = $info->getKey('bundle')) { + $id_properties[$bundle_key] = $ids->bundle; } return entity_create($ids->entity_type, $id_properties); } diff --git a/core/modules/field/field.multilingual.inc b/core/modules/field/field.multilingual.inc index ca33a31..b2a18bb 100644 --- a/core/modules/field/field.multilingual.inc +++ b/core/modules/field/field.multilingual.inc @@ -196,7 +196,7 @@ function field_is_translatable($entity_type, $field) { */ function field_has_translation_handler($entity_type, $handler = NULL) { $info = entity_get_info($entity_type); - return !empty($info['translatable']); + return $info->isTranslatable(); } /** diff --git a/core/modules/field/field.views.inc b/core/modules/field/field.views.inc index 5a1f4f3..3aeeb05 100644 --- a/core/modules/field/field.views.inc +++ b/core/modules/field/field.views.inc @@ -115,7 +115,7 @@ function field_views_field_default_views_data($field) { // Build the relationships between the field table and the entity tables. foreach ($field['bundles'] as $entity => $bundles) { $entity_info = entity_get_info($entity); - $groups[$entity] = $entity_info['label']; + $groups[$entity] = $entity_info->getLabel(); // Override Node to Content. if ($groups[$entity] == t('Node')) { @@ -127,18 +127,22 @@ function field_views_field_default_views_data($field) { $group_name = $groups[$entity]; } - if (!isset($entity_info['base_table'])) { + if (!$entity_info->hasBaseTable()) { continue; } - $entity_tables[$entity_info['base_table']] = $entity; - $current_tables[$entity] = $entity_info['base_table']; - if (isset($entity_info['revision_table'])) { - $entity_tables[$entity_info['revision_table']] = $entity; - $revision_tables[$entity] = $entity_info['revision_table']; + $base_table = $entity_info->getBaseTable(); + $entity_tables[$base_table] = $entity; + $current_tables[$entity] = $base_table; + + // TODO: Working around a bug, this should be the opposite check + if (!$entity_info->hasRevisionTable()) { + $revision_table = $entity_info->getRevisionTable(); + $entity_tables[$revision_table] = $entity; + $revision_tables[$entity] = $revision_table; } - $data[$current_table]['table']['join'][$entity_info['base_table']] = array( - 'left_field' => $entity_info['entity_keys']['id'], + $data[$current_table]['table']['join'][$base_table] = array( + 'left_field' => $entity_info->getKey('id'), 'field' => 'entity_id', 'extra' => array( array('field' => 'entity_type', 'value' => $entity), @@ -146,9 +150,9 @@ function field_views_field_default_views_data($field) { ), ); - if (!empty($entity_info['entity_keys']['revision']) && !empty($entity_info['revision_table'])) { - $data[$revision_table]['table']['join'][$entity_info['revision_table']] = array( - 'left_field' => $entity_info['entity_keys']['revision'], + if ($revision_key = $entity_info->getKey('revision') && !empty($revision_table)) { + $data[$revision_table]['table']['join'][$revision_table] = array( + 'left_field' => $revision_key, 'field' => 'revision_id', 'extra' => array( array('field' => 'entity_type', 'value' => $entity), diff --git a/core/modules/field/lib/Drupal/field/FieldInstanceStorageController.php b/core/modules/field/lib/Drupal/field/FieldInstanceStorageController.php index f9ce249..244016b 100644 --- a/core/modules/field/lib/Drupal/field/FieldInstanceStorageController.php +++ b/core/modules/field/lib/Drupal/field/FieldInstanceStorageController.php @@ -10,6 +10,7 @@ use Drupal\Core\Config\Config; use Drupal\Core\Config\Entity\ConfigStorageController; use Drupal\Core\Entity\Query\QueryFactory; +use Drupal\Core\Entity\EntityType; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Core\Config\ConfigFactory; use Drupal\Core\Config\StorageInterface; @@ -66,7 +67,7 @@ class FieldInstanceStorageController extends ConfigStorageController { * @param \Drupal\Core\KeyValueStore\KeyValueStoreInterface $state * The state key value store. */ - public function __construct($entity_type, array $entity_info, ConfigFactory $config_factory, StorageInterface $config_storage, QueryFactory $entity_query_factory, EntityManager $entity_manager, ModuleHandler $module_handler, KeyValueStoreInterface $state) { + public function __construct($entity_type, EntityType $entity_info, ConfigFactory $config_factory, StorageInterface $config_storage, QueryFactory $entity_query_factory, EntityManager $entity_manager, ModuleHandler $module_handler, KeyValueStoreInterface $state) { parent::__construct($entity_type, $entity_info, $config_factory, $config_storage, $entity_query_factory); $this->entityManager = $entity_manager; $this->moduleHandler = $module_handler; @@ -76,7 +77,7 @@ public function __construct($entity_type, array $entity_info, ConfigFactory $con /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $entity_type, $entity_info, diff --git a/core/modules/field/lib/Drupal/field/FieldStorageController.php b/core/modules/field/lib/Drupal/field/FieldStorageController.php index 41efe60..1043e16 100644 --- a/core/modules/field/lib/Drupal/field/FieldStorageController.php +++ b/core/modules/field/lib/Drupal/field/FieldStorageController.php @@ -10,6 +10,7 @@ use Drupal\Core\Config\Config; use Drupal\Core\Config\Entity\ConfigStorageController; use Drupal\Core\Entity\Query\QueryFactory; +use Drupal\Core\Entity\EntityType; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Core\Config\ConfigFactory; use Drupal\Core\Config\StorageInterface; @@ -61,7 +62,7 @@ class FieldStorageController extends ConfigStorageController { * @param \Drupal\Core\KeyValueStore\KeyValueStoreInterface $state * The state key value store. */ - public function __construct($entity_type, array $entity_info, ConfigFactory $config_factory, StorageInterface $config_storage, QueryFactory $entity_query_factory, EntityManager $entity_manager, ModuleHandler $module_handler, KeyValueStoreInterface $state) { + public function __construct($entity_type, EntityType $entity_info, ConfigFactory $config_factory, StorageInterface $config_storage, QueryFactory $entity_query_factory, EntityManager $entity_manager, ModuleHandler $module_handler, KeyValueStoreInterface $state) { parent::__construct($entity_type, $entity_info, $config_factory, $config_storage, $entity_query_factory); $this->entityManager = $entity_manager; @@ -72,7 +73,7 @@ public function __construct($entity_type, array $entity_info, ConfigFactory $con /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $entity_type, $entity_info, diff --git a/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/Field.php b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/Field.php index 1bb1ae4..4bac2ba 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/Field.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/Field.php @@ -346,7 +346,7 @@ protected function saveNew() { // collisions with existing entity properties, but some is better than // none. foreach ($entity_manager->getDefinitions() as $type => $info) { - if (in_array($this->id, $info['entity_keys'])) { + if ($info->hasKey($this->id)) { throw new FieldException(format_string('Attempt to create field %id which is reserved by entity type %type.', array('%id' => $this->id, '%type' => $type))); } } @@ -741,7 +741,7 @@ public function hasData() { foreach ($this->getBundles() as $entity_type => $bundle) { // Entity Query throws an exception if there is no base table. $entity_info = \Drupal::entityManager()->getDefinition($entity_type); - if (!isset($entity_info['base_table'])) { + if (!$entity_info->hasBaseTable()) { continue; } $query = $factory->get($entity_type); diff --git a/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php b/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php index ebf9722..eca7779 100644 --- a/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/TranslationTest.php @@ -148,7 +148,7 @@ function testTranslatableFieldSaveLoad() { // Enable field translations for nodes. field_test_entity_info_translatable('node', TRUE); $entity_info = entity_get_info('node'); - $this->assertTrue(count($entity_info['translatable']), 'Nodes are translatable.'); + $this->assertTrue(count($entity_info->fieldsCacheable()), 'Nodes are translatable.'); // Prepare the field translations. $entity_type = 'entity_test'; 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 4cea03a..3dfa25c 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 @@ -24,11 +24,53 @@ function field_test_entity_info() { */ function field_test_entity_info_alter(&$entity_info) { foreach (field_test_entity_info_translatable() as $entity_type => $translatable) { - $entity_info[$entity_type]['translatable'] = $translatable; + $entity_info[$entity_type]->setTranslatable($translatable); } } /** + * Implements hook_entity_view_mode_info_alter(). + */ +function field_test_entity_view_mode_info_alter(&$view_modes) { + $entity_info = entity_get_info(); + foreach ($entity_info as $entity_type => $info) { + if ($entity_info[$entity_type]->getModule() == 'field_test') { + $view_modes[$entity_type] = array( + 'full' => array( + 'label' => t('Full object'), + 'status' => TRUE, + ), + 'teaser' => array( + 'label' => t('Teaser'), + 'status' => TRUE, + ), + ); + } + } +} + +/** + * Implements hook_entity_bundle_info(). + */ +function field_test_entity_bundle_info() { + $bundles = array(); + + $entity_info = entity_get_info(); + foreach ($entity_info as $entity_type => $info) { + if ($info->getModule() == 'field_test') { + $bundles[$entity_type] = Drupal::state()->get('field_test_bundles') ?: array('test_bundle' => array('label' => 'Test Bundle')); + } + } + + $bundles['test_entity_bundle']['test_entity_2'] = array('label' => 'Test entity 2'); + + $bundles['test_entity_bundle_key']['bundle1'] = array('label' => 'Bundle1'); + $bundles['test_entity_bundle_key']['bundle2'] = array('label' => 'Bundle2'); + + return $bundles; +} + +/** * Helper function to enable entity translations. */ function field_test_entity_info_translatable($entity_type = NULL, $translatable = NULL) { diff --git a/core/modules/field_ui/field_ui.module b/core/modules/field_ui/field_ui.module index 2040df2..259a2e9 100644 --- a/core/modules/field_ui/field_ui.module +++ b/core/modules/field_ui/field_ui.module @@ -66,9 +66,9 @@ function field_ui_menu() { // Create tabs for all possible bundles. foreach (entity_get_info() as $entity_type => $entity_info) { - if ($entity_info['fieldable'] && isset($entity_info['route_base_path'])) { + // @fixme How to replace this. + if ($entity_info->fieldsCacheable() && $path = $entity_info->getRouteBasePath()) { // Extract path information from the entity type. - $path = $entity_info['route_base_path']; $default_path = preg_replace('/{' . DRUPAL_PHP_FUNCTION_PATTERN . '}/', '%', $path); // This is the position of the %field_ui_instance placeholder in the // items below. @@ -162,18 +162,18 @@ function field_ui_permission() { $permissions = array(); foreach (entity_get_info() as $entity_type => $entity_info) { - if ($entity_info['fieldable']) { + if ($entity_info->fieldsCacheable()) { // Create a permission for each fieldable entity to manage // the fields and the display. $permissions['administer ' . $entity_type . ' fields'] = array( - 'title' => t('%entity_label: Administer fields', array('%entity_label' => $entity_info['label'])), + 'title' => t('%entity_label: Administer fields', array('%entity_label' => $entity_info->getLabel())), 'restrict access' => TRUE, ); $permissions['administer ' . $entity_type . ' form display'] = array( - 'title' => t('%entity_label: Administer form display', array('%entity_label' => $entity_info['label'])) + 'title' => t('%entity_label: Administer form display', array('%entity_label' => $entity_info->getLabel())) ); $permissions['administer ' . $entity_type . ' display'] = array( - 'title' => t('%entity_label: Administer display', array('%entity_label' => $entity_info['label'])) + 'title' => t('%entity_label: Administer display', array('%entity_label' => $entity_info->getLabel())), ); } } @@ -253,8 +253,14 @@ function field_ui_element_info() { * Implements hook_entity_info(). */ function field_ui_entity_info(&$entity_info) { - $entity_info['field_instance']['controllers']['form']['delete'] = 'Drupal\field_ui\Form\FieldDeleteForm'; - $entity_info['field_entity']['controllers']['list'] = 'Drupal\field_ui\FieldListController'; + if (isset($entity_info['field_instance'])) { + $controllers = $entity_info['field_instance']->getController('form'); + $controllers['delete'] = 'Drupal\field_ui\Form\FieldDeleteForm'; + $entity_info['field_instance']->setController('form', $controllers); + } + if (isset($entity_info['field_entity'])) { + $entity_info['field_entity']->setController('list', 'Drupal\field_ui\FieldListController'); + } } /** diff --git a/core/modules/field_ui/lib/Drupal/field_ui/FieldListController.php b/core/modules/field_ui/lib/Drupal/field_ui/FieldListController.php index cd3d640..ccfc722 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/FieldListController.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/FieldListController.php @@ -10,6 +10,7 @@ use Drupal\Core\Config\Entity\ConfigEntityListController; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityManager; +use Drupal\Core\Entity\EntityType; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\field\FieldInfo; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -52,7 +53,7 @@ class FieldListController extends ConfigEntityListController { * * @param string $entity_type * The type of entity to be listed. - * @param array $entity_info + * @param \Drupal\Core\Entity\EntityType $entity_info * An array of entity info for the entity type. * @param \Drupal\Core\Entity\EntityManager $entity_manager * The entity manager. @@ -61,7 +62,7 @@ class FieldListController extends ConfigEntityListController { * @param \Drupal\field\FieldInfo $field_info * The field info service. */ - public function __construct($entity_type, array $entity_info, EntityManager $entity_manager, ModuleHandlerInterface $module_handler, FieldInfo $field_info) { + public function __construct($entity_type, EntityType $entity_info, EntityManager $entity_manager, ModuleHandlerInterface $module_handler, FieldInfo $field_info) { parent::__construct($entity_type, $entity_info, $entity_manager->getStorageController($entity_type), $module_handler); $this->fieldTypes = field_info_field_types(); @@ -73,7 +74,7 @@ public function __construct($entity_type, array $entity_info, EntityManager $ent /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $entity_type, $entity_info, diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldDeleteForm.php b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldDeleteForm.php index e53eec9..252eea4 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldDeleteForm.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldDeleteForm.php @@ -11,6 +11,7 @@ use Drupal\Core\Entity\EntityControllerInterface; use Drupal\Core\Entity\EntityManager; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Entity\EntityType; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -41,7 +42,7 @@ public function __construct(ModuleHandlerInterface $module_handler, EntityManage /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $container->get('module_handler'), $container->get('plugin.manager.entity') diff --git a/core/modules/field_ui/lib/Drupal/field_ui/OverviewBase.php b/core/modules/field_ui/lib/Drupal/field_ui/OverviewBase.php index 67b742b..6d76490 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/OverviewBase.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/OverviewBase.php @@ -76,8 +76,9 @@ public static function create(ContainerInterface $container) { */ public function buildForm(array $form, array &$form_state, $entity_type = NULL, $bundle = NULL) { $entity_info = $this->entityManager->getDefinition($entity_type); - if (!empty($entity_info['bundle_prefix'])) { - $bundle = $entity_info['bundle_prefix'] . $bundle; + // @fixme How to replace this. + if ($prefix = $entity_info->getBundlePrefix()) { + $bundle = $prefix . $bundle; } $this->entity_type = $entity_type; diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Routing/RouteSubscriber.php b/core/modules/field_ui/lib/Drupal/field_ui/Routing/RouteSubscriber.php index e994202..3b80caf 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/Routing/RouteSubscriber.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/Routing/RouteSubscriber.php @@ -50,9 +50,8 @@ public function routes(RouteBuildEvent $event) { $collection = $event->getRouteCollection(); foreach ($this->manager->getDefinitions() as $entity_type => $entity_info) { $defaults = array(); - if ($entity_info['fieldable'] && isset($entity_info['route_base_path'])) { - $path = $entity_info['route_base_path']; - + // @fixme How to replace this. + if ($entity_info->fieldsCacheable() && $path = $entity_info->getRouteBasePath()) { $route = new Route( "$path/fields/{field_instance}", array('_form' => '\Drupal\field_ui\Form\FieldInstanceEditForm'), @@ -76,7 +75,7 @@ public function routes(RouteBuildEvent $event) { // If the entity type has no bundles, use the entity type. $defaults['entity_type'] = $entity_type; - if (empty($entity_info['entity_keys']['bundle'])) { + if (!$entity_info->getKey('bundle')) { $defaults['bundle'] = $entity_type; } $route = new Route( diff --git a/core/modules/field_ui/tests/modules/field_ui_test/field_ui_test.entity.yml b/core/modules/field_ui/tests/modules/field_ui_test/field_ui_test.entity.yml new file mode 100644 index 0000000..8461d7d --- /dev/null +++ b/core/modules/field_ui/tests/modules/field_ui_test/field_ui_test.entity.yml @@ -0,0 +1 @@ +field_ui_test_no_bundle: Drupal\field_ui_test\Plugin\Core\Entity\FieldUITestNoBundle \ No newline at end of file diff --git a/core/modules/file/file.entity.yml b/core/modules/file/file.entity.yml new file mode 100644 index 0000000..d23af3e --- /dev/null +++ b/core/modules/file/file.entity.yml @@ -0,0 +1 @@ +file: Drupal\file\Plugin\Core\Entity\File \ No newline at end of file diff --git a/core/modules/file/file.module b/core/modules/file/file.module index 0d66adb..e472cb1 100644 --- a/core/modules/file/file.module +++ b/core/modules/file/file.module @@ -1577,7 +1577,7 @@ function file_get_file_references(File $file, $field = NULL, $age = FIELD_LOAD_R // The usage table contains usage of every revision. If we are looking // for every revision or the entity does not support revisions then // every usage is already a match. - $match_entity_type = $age == FIELD_LOAD_REVISION || !isset($entity_info['entity_keys']['revision']); + $match_entity_type = $age == FIELD_LOAD_REVISION || !$entity_info->getKey('revision'); $entities = entity_load_multiple($entity_type, $entity_ids); foreach ($entities as $entity) { $bundle = $entity->bundle(); diff --git a/core/modules/file/file.views.inc b/core/modules/file/file.views.inc index 5c2743f..d2c7332 100644 --- a/core/modules/file/file.views.inc +++ b/core/modules/file/file.views.inc @@ -478,7 +478,7 @@ function file_field_views_data_views_data_alter(&$data, $field) { $pseudo_field_name = 'reverse_' . $field['field_name'] . '_' . $entity_type; list($label, $all_labels) = field_views_field_label($field['field_name']); - $entity = $entity_info['label']; + $entity = $entity_info->getLabel(); if ($entity == t('Node')) { $entity = t('Content'); } @@ -490,8 +490,8 @@ function file_field_views_data_views_data_alter(&$data, $field) { 'field_name' => $field['field_name'], 'field table' => _field_sql_storage_tablename($field), 'field field' => $field['field_name'] . '_target_id', - 'base' => $entity_info['base_table'], - 'base field' => $entity_info['entity_keys']['id'], + 'base' => $entity_info->getBaseTable(), + 'base field' => $entity_info->getKey('id'), 'label' => t('!field_name', array('!field_name' => $field['field_name'])), 'join_extra' => array( 0 => array( diff --git a/core/modules/file/lib/Drupal/file/FileStorageController.php b/core/modules/file/lib/Drupal/file/FileStorageController.php index 10ba8d3..9fb2fdf 100644 --- a/core/modules/file/lib/Drupal/file/FileStorageController.php +++ b/core/modules/file/lib/Drupal/file/FileStorageController.php @@ -18,7 +18,7 @@ class FileStorageController extends DatabaseStorageControllerNG implements FileS * {@inheritdoc} */ public function spaceUsed($uid = NULL, $status = FILE_STATUS_PERMANENT) { - $query = $this->database->select($this->entityInfo['base_table'], 'f') + $query = $this->database->select($this->entityInfo->getBaseTable(), 'f') ->condition('f.status', $status); $query->addExpression('SUM(f.filesize)', 'filesize'); if (isset($uid)) { @@ -33,7 +33,7 @@ public function spaceUsed($uid = NULL, $status = FILE_STATUS_PERMANENT) { public function retrieveTemporaryFiles() { // Use separate placeholders for the status to avoid a bug in some versions // of PHP. See http://drupal.org/node/352956. - return $this->database->query('SELECT fid FROM {' . $this->entityInfo['base_table'] . '} WHERE status <> :permanent AND timestamp < :timestamp', array( + return $this->database->query('SELECT fid FROM {' . $this->entityInfo->getBaseTable() . '} WHERE status <> :permanent AND timestamp < :timestamp', array( ':permanent' => FILE_STATUS_PERMANENT, ':timestamp' => REQUEST_TIME - DRUPAL_MAXIMUM_TEMP_FILE_AGE )); diff --git a/core/modules/filter/filter.entity.yml b/core/modules/filter/filter.entity.yml new file mode 100644 index 0000000..29c0437 --- /dev/null +++ b/core/modules/filter/filter.entity.yml @@ -0,0 +1 @@ +filter_format: Drupal\filter\Plugin\Core\Entity\FilterFormat \ No newline at end of file diff --git a/core/modules/filter/lib/Drupal/filter/FilterFormatFormControllerBase.php b/core/modules/filter/lib/Drupal/filter/FilterFormatFormControllerBase.php index 98495d5..f9faad4 100644 --- a/core/modules/filter/lib/Drupal/filter/FilterFormatFormControllerBase.php +++ b/core/modules/filter/lib/Drupal/filter/FilterFormatFormControllerBase.php @@ -10,6 +10,7 @@ use Drupal\Core\Config\ConfigFactory; use Drupal\Core\Entity\EntityControllerInterface; use Drupal\Core\Entity\EntityFormController; +use Drupal\Core\Entity\EntityType; use Drupal\Core\Entity\Query\QueryFactory; use Drupal\Core\Extension\ModuleHandlerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -52,7 +53,7 @@ public function __construct(ModuleHandlerInterface $module_handler, ConfigFactor /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $container->get('module_handler'), $container->get('config.factory'), diff --git a/core/modules/filter/lib/Drupal/filter/FilterFormatListController.php b/core/modules/filter/lib/Drupal/filter/FilterFormatListController.php index c8df5e6..b8adde9 100644 --- a/core/modules/filter/lib/Drupal/filter/FilterFormatListController.php +++ b/core/modules/filter/lib/Drupal/filter/FilterFormatListController.php @@ -12,6 +12,7 @@ use Drupal\Core\Config\Entity\ConfigEntityListController; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageControllerInterface; +use Drupal\Core\Entity\EntityType; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\FormInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -33,7 +34,7 @@ class FilterFormatListController extends ConfigEntityListController implements F * * @param string $entity_type * The type of entity to be listed. - * @param array $entity_info + * @param \Drupal\Core\Entity\EntityType $entity_info * An array of entity info for the entity type. * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage * The entity storage controller class. @@ -42,7 +43,7 @@ class FilterFormatListController extends ConfigEntityListController implements F * @param \Drupal\Core\Config\ConfigFactory $config_factory * The config factory. */ - public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, ConfigFactory $config_factory) { + public function __construct($entity_type, EntityType $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, ConfigFactory $config_factory) { parent::__construct($entity_type, $entity_info, $storage, $module_handler); $this->configFactory = $config_factory; @@ -51,7 +52,7 @@ public function __construct($entity_type, array $entity_info, EntityStorageContr /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $entity_type, $entity_info, diff --git a/core/modules/image/image.entity.yml b/core/modules/image/image.entity.yml new file mode 100644 index 0000000..261ab0c --- /dev/null +++ b/core/modules/image/image.entity.yml @@ -0,0 +1 @@ +image_style: Drupal\image\Plugin\Core\Entity\ImageStyle \ No newline at end of file diff --git a/core/modules/image/image.views.inc b/core/modules/image/image.views.inc index 2e70c08..6733c5b 100644 --- a/core/modules/image/image.views.inc +++ b/core/modules/image/image.views.inc @@ -41,7 +41,7 @@ function image_field_views_data_views_data_alter(&$data, $field) { $pseudo_field_name = 'reverse_' . $field['field_name'] . '_' . $entity_type; list($label, $all_labels) = field_views_field_label($field['field_name']); - $entity = $entity_info['label']; + $entity = $entity_info->getLabel(); if ($entity == t('Node')) { $entity = t('Content'); } @@ -53,8 +53,8 @@ function image_field_views_data_views_data_alter(&$data, $field) { 'field_name' => $field['field_name'], 'field table' => _field_sql_storage_tablename($field), 'field field' => $field['field_name'] . '_target_id', - 'base' => $entity_info['base_table'], - 'base field' => $entity_info['entity_keys']['id'], + 'base' => $entity_info->getBaseTable(), + 'base field' => $entity_info->getKey('id'), 'label' => t('!field_name', array('!field_name' => $field['field_name'])), 'join_extra' => array( 0 => array( diff --git a/core/modules/language/language.admin.inc b/core/modules/language/language.admin.inc index 10506c6..928e4b2 100644 --- a/core/modules/language/language.admin.inc +++ b/core/modules/language/language.admin.inc @@ -837,7 +837,7 @@ function language_content_settings_form(array $form, array $form_state, array $s $default = array(); foreach ($supported as $entity_type) { - $labels[$entity_type] = isset($entity_info[$entity_type]['label']) ? $entity_info[$entity_type]['label'] : $entity_type; + $labels[$entity_type] = $entity_info[$entity_type]->getLabel() ? $entity_info[$entity_type]->getLabel() : $entity_type; $default[$entity_type] = FALSE; // Check whether we have any custom setting. @@ -877,7 +877,7 @@ function language_content_settings_form(array $form, array $form_state, array $s '#type' => 'container', '#entity_type' => $entity_type, '#theme' => 'language_content_settings_table', - '#bundle_label' => isset($info['bundle_label']) ? $info['bundle_label'] : $label, + '#bundle_label' => $info->getBundleLable() ?: $label, '#states' => array( 'visible' => array( ':input[name="entity_types[' . $entity_type . ']"]' => array('checked' => TRUE), diff --git a/core/modules/language/language.entity.yml b/core/modules/language/language.entity.yml new file mode 100644 index 0000000..3e34199 --- /dev/null +++ b/core/modules/language/language.entity.yml @@ -0,0 +1 @@ +language_entity: Drupal\language\Plugin\Core\Entity\Language diff --git a/core/modules/language/language.module b/core/modules/language/language.module index 15093fd..381fc60 100644 --- a/core/modules/language/language.module +++ b/core/modules/language/language.module @@ -204,7 +204,7 @@ function language_theme() { function language_entity_supported() { $supported = array(); foreach (entity_get_info() as $entity_type => $info) { - if (!empty($info['translatable'])) { + if ($info->isTranslatable()) { $supported[$entity_type] = $entity_type; } } diff --git a/core/modules/layout/layout.entity.yml b/core/modules/layout/layout.entity.yml new file mode 100644 index 0000000..dfed2bb --- /dev/null +++ b/core/modules/layout/layout.entity.yml @@ -0,0 +1,2 @@ +display: Drupal\layout\Plugin\Core\Entity\Display +unbound_display: Drupal\layout\Plugin\Core\Entity\UnboundDisplay \ No newline at end of file diff --git a/core/modules/menu/lib/Drupal/menu/Form/MenuDeleteForm.php b/core/modules/menu/lib/Drupal/menu/Form/MenuDeleteForm.php index febf8b9..0671065 100644 --- a/core/modules/menu/lib/Drupal/menu/Form/MenuDeleteForm.php +++ b/core/modules/menu/lib/Drupal/menu/Form/MenuDeleteForm.php @@ -12,6 +12,7 @@ use Drupal\Core\Entity\EntityControllerInterface; use Drupal\Core\Entity\EntityStorageControllerInterface; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Entity\EntityType; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -52,7 +53,7 @@ public function __construct(ModuleHandlerInterface $module_handler, EntityStorag /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $container->get('module_handler'), $container->get('plugin.manager.entity')->getStorageController('menu_link'), diff --git a/core/modules/menu/menu.module b/core/modules/menu/menu.module index af081e5..ef2dd8d 100644 --- a/core/modules/menu/menu.module +++ b/core/modules/menu/menu.module @@ -146,16 +146,21 @@ function menu_menu() { * Implements hook_entity_info(). */ function menu_entity_info(&$entity_info) { - $entity_info['menu']['controllers']['list'] = 'Drupal\menu\MenuListController'; - $entity_info['menu']['controllers']['access'] = 'Drupal\menu\MenuAccessController'; - $entity_info['menu']['uri_callback'] = 'menu_uri'; - $entity_info['menu']['controllers']['form'] = array( - 'default' => 'Drupal\menu\MenuFormController', - 'delete' => 'Drupal\menu\Form\MenuDeleteForm', - ); - - $entity_info['menu_link']['controllers']['form']['delete'] = 'Drupal\menu\Form\MenuLinkDeleteForm'; - $entity_info['menu_link']['controllers']['form']['reset'] = 'Drupal\menu\Form\MenuLinkResetForm'; + if (isset($entity_info['menu'])) { + $entity_info['menu']->setController('list', 'Drupal\menu\MenuListController'); + $entity_info['menu']->setController('access', 'Drupal\menu\MenuAccessController'); + $entity_info['menu']->setUriCallback('menu_uri'); + $controllers = $entity_info['menu']->getController('form'); + $controllers['default'] = 'Drupal\menu\MenuFormController'; + $controllers['delete'] = 'Drupal\menu\Form\MenuDeleteForm'; + $entity_info['menu']->setController('form', $controllers); + } + if (isset($entity_info['menu_link'])) { + $controllers = $entity_info['menu_link']->getController('form'); + $controllers['delete'] = 'Drupal\menu\Form\MenuLinkDeleteForm'; + $controllers['reset'] = 'Drupal\menu\Form\MenuLinkResetForm'; + $entity_info['menu_link']->setController('form', $controllers); + } } /** diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php index 8eb4458..d47d699 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkFormController.php @@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityControllerInterface; use Drupal\Core\Entity\EntityFormController; +use Drupal\Core\Entity\EntityType; use Drupal\Core\Language\Language; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Path\AliasManagerInterface; @@ -45,10 +46,14 @@ class MenuLinkFormController extends EntityFormController implements EntityContr /** * Constructs a new MenuLinkFormController object. * - * @param \Drupal\Core\Extension\ModuleHandlerInterface + * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler service. + * @param MenuLinkStorageControllerInterface $menu_link_storage_controller + * The menu link storage. * @param \Drupal\Core\Path\AliasManagerInterface $path_alias_manager * The path alias manager. + * @param \Drupal\Core\Routing\UrlGenerator $url_generator + * The URL generator. */ public function __construct(ModuleHandlerInterface $module_handler, MenuLinkStorageControllerInterface $menu_link_storage_controller, AliasManagerInterface $path_alias_manager, UrlGenerator $url_generator) { parent::__construct($module_handler); @@ -60,7 +65,7 @@ public function __construct(ModuleHandlerInterface $module_handler, MenuLinkStor /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info, $operation = NULL) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info, $operation = NULL) { return new static( $container->get('module_handler'), $container->get('plugin.manager.entity')->getStorageController('menu_link'), diff --git a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php index 43d54ce..eb22422 100644 --- a/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php +++ b/core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorageController.php @@ -9,6 +9,7 @@ use Drupal\Core\Entity\DatabaseStorageController; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityType; use Drupal\Core\Entity\EntityStorageException; use Drupal\Core\Database\Connection; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -55,7 +56,7 @@ class MenuLinkStorageController extends DatabaseStorageController implements Men * @param \Symfony\Cmf\Component\Routing\RouteProviderInterface $route_provider * The route provider service. */ - public function __construct($entity_type, array $entity_info, Connection $database, RouteProviderInterface $route_provider) { + public function __construct($entity_type, EntityType $entity_info, Connection $database, RouteProviderInterface $route_provider) { parent::__construct($entity_type, $entity_info, $database); $this->routeProvider = $route_provider; @@ -80,7 +81,7 @@ public function create(array $values) { /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $entity_type, $entity_info, @@ -143,8 +144,6 @@ protected function attachLoad(&$menu_links, $load_revision = FALSE) { * Overrides DatabaseStorageController::save(). */ public function save(EntityInterface $entity) { - $entity_class = $this->entityInfo['class']; - // We return SAVED_UPDATED by default because the logic below might not // update the entity if its values haven't changed, so returning FALSE // would be confusing in that situation. @@ -158,7 +157,7 @@ public function save(EntityInterface $entity) { } if ($entity->isNew()) { - $entity->mlid = $this->database->insert($this->entityInfo['base_table'])->fields(array('menu_name' => 'tools'))->execute(); + $entity->mlid = $this->database->insert($this->entityInfo->getBaseTable())->fields(array('menu_name' => 'tools'))->execute(); $entity->enforceIsNew(); } @@ -175,7 +174,7 @@ public function save(EntityInterface $entity) { // $entity may have additional keys left over from building a router entry. // The intersect removes the extra keys, allowing a meaningful comparison. if ($entity->isNew() || (array_intersect_key(get_object_vars($entity), get_object_vars($entity->original)) != get_object_vars($entity->original))) { - $return = drupal_write_record($this->entityInfo['base_table'], $entity, $this->idKey); + $return = drupal_write_record($this->entityInfo->getBaseTable(), $entity, $this->idKey); if ($return) { if (!$entity->isNew()) { @@ -239,11 +238,11 @@ public function loadUpdatedCustomized(array $router_paths) { ); $query_result = $query->execute(); - if (!empty($this->entityInfo['class'])) { + if ($entity_class = $this->entityInfo->getClass()) { // 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['class'], array(array(), $this->entityType)); + $query_result->setFetchMode(\PDO::FETCH_CLASS, $entity_class, array(array(), $this->entityType)); } return $query_result->fetchAllAssoc($this->idKey); @@ -319,7 +318,7 @@ public function findChildrenRelativeDepth(EntityInterface $entity) { * {@inheritdoc} */ public function moveChildren(EntityInterface $entity) { - $query = $this->database->update($this->entityInfo['base_table']); + $query = $this->database->update($this->entityInfo->getBaseTable()); $query->fields(array('menu_name' => $entity->menu_name)); diff --git a/core/modules/menu_link/menu_link.entity.yml b/core/modules/menu_link/menu_link.entity.yml new file mode 100644 index 0000000..d96bef1 --- /dev/null +++ b/core/modules/menu_link/menu_link.entity.yml @@ -0,0 +1 @@ +menu_link: Drupal\menu_link\Plugin\Core\Entity\MenuLink \ No newline at end of file diff --git a/core/modules/node/lib/Drupal/node/Form/NodeDeleteForm.php b/core/modules/node/lib/Drupal/node/Form/NodeDeleteForm.php index 5a3fdb0..14f4203 100644 --- a/core/modules/node/lib/Drupal/node/Form/NodeDeleteForm.php +++ b/core/modules/node/lib/Drupal/node/Form/NodeDeleteForm.php @@ -10,6 +10,7 @@ use Drupal\Core\Entity\EntityControllerInterface; use Drupal\Core\Entity\EntityNGConfirmFormBase; use Drupal\Core\Entity\EntityStorageControllerInterface; +use Drupal\Core\Entity\EntityType; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Routing\PathBasedGeneratorInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -54,7 +55,7 @@ public function __construct(ModuleHandlerInterface $module_handler, PathBasedGen /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $container->get('module_handler'), $container->get('url_generator'), diff --git a/core/modules/node/lib/Drupal/node/Form/NodeTypeDeleteConfirm.php b/core/modules/node/lib/Drupal/node/Form/NodeTypeDeleteConfirm.php index d159b3d..a44508e 100644 --- a/core/modules/node/lib/Drupal/node/Form/NodeTypeDeleteConfirm.php +++ b/core/modules/node/lib/Drupal/node/Form/NodeTypeDeleteConfirm.php @@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityConfirmFormBase; use Drupal\Core\Entity\EntityControllerInterface; +use Drupal\Core\Entity\EntityType; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Database\Connection; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -42,7 +43,7 @@ public function __construct(ModuleHandlerInterface $module_handler, Connection $ /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $container->get('module_handler'), $container->get('database') diff --git a/core/modules/node/lib/Drupal/node/NodeAccessController.php b/core/modules/node/lib/Drupal/node/NodeAccessController.php index c0106a7..c46f565 100644 --- a/core/modules/node/lib/Drupal/node/NodeAccessController.php +++ b/core/modules/node/lib/Drupal/node/NodeAccessController.php @@ -7,16 +7,14 @@ namespace Drupal\node; -use Drupal\Core\Database\Connection; -use Drupal\Core\Database\Query\SelectInterface; use Drupal\Core\Entity\EntityControllerInterface; +use Drupal\Core\Entity\EntityType; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Language\Language; use Drupal\Core\Entity\EntityAccessController; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityNG; use Drupal\Core\Session\AccountInterface; -use Drupal\user\Plugin\Core\Entity\User; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -27,7 +25,7 @@ class NodeAccessController extends EntityAccessController implements NodeAccessC /** * The node grant storage. * - * @var \Drupal\node\NodeGrantStorageControllerInterface + * @var \Drupal\node\NodeGrantDatabaseStorageInterface */ protected $grantStorage; @@ -43,6 +41,8 @@ class NodeAccessController extends EntityAccessController implements NodeAccessC * * @param \Drupal\node\NodeGrantDatabaseStorageInterface $grant_storage * The node grant storage. + * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler + * The module handler. */ public function __construct(NodeGrantDatabaseStorageInterface $grant_storage, ModuleHandlerInterface $module_handler) { $this->grantStorage = $grant_storage; @@ -52,7 +52,7 @@ public function __construct(NodeGrantDatabaseStorageInterface $grant_storage, Mo /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $container->get('node.grant_storage'), $container->get('module_handler') diff --git a/core/modules/node/lib/Drupal/node/NodeStorageController.php b/core/modules/node/lib/Drupal/node/NodeStorageController.php index c3ccc3c..aaae6d6 100644 --- a/core/modules/node/lib/Drupal/node/NodeStorageController.php +++ b/core/modules/node/lib/Drupal/node/NodeStorageController.php @@ -86,7 +86,7 @@ protected function invokeHook($hook, EntityInterface $node) { if ($function == 'field_attach_revision_delete') { $function = 'field_attach_delete_revision'; } - if (!empty($this->entityInfo['fieldable']) && function_exists($function)) { + if ($this->entityInfo->isFieldable() && function_exists($function)) { $function($node); } diff --git a/core/modules/node/lib/Drupal/node/NodeTypeListController.php b/core/modules/node/lib/Drupal/node/NodeTypeListController.php index d6be67d..db59b6b 100644 --- a/core/modules/node/lib/Drupal/node/NodeTypeListController.php +++ b/core/modules/node/lib/Drupal/node/NodeTypeListController.php @@ -8,6 +8,7 @@ use Drupal\Core\Config\Entity\ConfigEntityListController; use Drupal\Core\Entity\EntityControllerInterface; +use Drupal\Core\Entity\EntityType; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Core\Entity\EntityStorageControllerInterface; use Drupal\Core\Extension\ModuleHandlerInterface; @@ -33,7 +34,7 @@ class NodeTypeListController extends ConfigEntityListController implements Entit * * @param string $entity_type * The type of entity to be listed. - * @param array $entity_info + * @param \Drupal\Core\Entity\EntityType $entity_info * An array of entity info for the entity type. * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage * The entity storage controller class. @@ -42,14 +43,14 @@ class NodeTypeListController extends ConfigEntityListController implements Entit * @param \Drupal\Core\Routing\PathBasedGeneratorInterface $url_generator * The url generator service. */ - public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, PathBasedGeneratorInterface $url_generator) { + public function __construct($entity_type, EntityType $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, PathBasedGeneratorInterface $url_generator) { parent::__construct($entity_type, $entity_info, $storage, $module_handler); $this->urlGenerator = $url_generator; } /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $entity_type, $entity_info, diff --git a/core/modules/node/node.entity.yml b/core/modules/node/node.entity.yml new file mode 100644 index 0000000..0398afd --- /dev/null +++ b/core/modules/node/node.entity.yml @@ -0,0 +1,2 @@ +node: Drupal\node\Plugin\Core\Entity\Node +node_type: Drupal\node\Plugin\Core\Entity\NodeType \ No newline at end of file diff --git a/core/modules/node/tests/modules/node_test/node_test.module b/core/modules/node/tests/modules/node_test/node_test.module index 12e0eed..84dde36 100644 --- a/core/modules/node/tests/modules/node_test/node_test.module +++ b/core/modules/node/tests/modules/node_test/node_test.module @@ -185,7 +185,7 @@ function node_test_node_insert(EntityInterface $node) { * Implements hook_entity_info_alter(). */ function node_test_entity_info_alter(&$entity_info) { - if (Drupal::state()->get('node_test.storage_controller')) { - $entity_info['node']['class'] = 'Drupal\node_test\NodeTest'; + if (isset($entity_info['node']) && Drupal::state()->get('node_test.storage_controller')) { + $entity_info['node']->setClass('Drupal\node_test\NodeTest'); } } diff --git a/core/modules/picture/lib/Drupal/picture/PictureMappingListController.php b/core/modules/picture/lib/Drupal/picture/PictureMappingListController.php index 0b63462..6754c93 100644 --- a/core/modules/picture/lib/Drupal/picture/PictureMappingListController.php +++ b/core/modules/picture/lib/Drupal/picture/PictureMappingListController.php @@ -19,7 +19,7 @@ class PictureMappingListController extends ConfigEntityListController { * Overrides Drupal\config\EntityListControllerBase::hookMenu(). */ public function hookMenu() { - $path = $this->entityInfo['list path']; + $path = $this->entityInfo->get('list_path'); $items = parent::hookMenu(); // Override the access callback. diff --git a/core/modules/picture/picture.entity.yml b/core/modules/picture/picture.entity.yml new file mode 100644 index 0000000..56860c2 --- /dev/null +++ b/core/modules/picture/picture.entity.yml @@ -0,0 +1 @@ +picture_mapping: Drupal\picture\Plugin\Core\Entity\PictureMapping \ No newline at end of file diff --git a/core/modules/rdf/rdf.entity.yml b/core/modules/rdf/rdf.entity.yml new file mode 100644 index 0000000..47ed7b1 --- /dev/null +++ b/core/modules/rdf/rdf.entity.yml @@ -0,0 +1 @@ +rdf_mapping: Drupal\rdf\Plugin\Core\Entity\RdfMapping diff --git a/core/modules/rest/lib/Drupal/rest/LinkManager/TypeLinkManager.php b/core/modules/rest/lib/Drupal/rest/LinkManager/TypeLinkManager.php index 6802282..66fb4ea 100644 --- a/core/modules/rest/lib/Drupal/rest/LinkManager/TypeLinkManager.php +++ b/core/modules/rest/lib/Drupal/rest/LinkManager/TypeLinkManager.php @@ -83,7 +83,7 @@ protected function writeCache() { $entity_info = entity_get_info(); foreach (entity_get_bundles() as $entity_type => $bundles) { $entity_type_info = $entity_info[$entity_type]; - $reflection = new \ReflectionClass($entity_type_info['class']); + $reflection = new \ReflectionClass($entity_type_info->getClass()); // Only content entities are supported currently. // @todo Consider supporting config entities. if ($reflection->implementsInterface('\Drupal\Core\Config\Entity\ConfigEntityInterface')) { diff --git a/core/modules/rest/lib/Drupal/rest/Plugin/Derivative/EntityDerivative.php b/core/modules/rest/lib/Drupal/rest/Plugin/Derivative/EntityDerivative.php index 310d843..72e5034 100644 --- a/core/modules/rest/lib/Drupal/rest/Plugin/Derivative/EntityDerivative.php +++ b/core/modules/rest/lib/Drupal/rest/Plugin/Derivative/EntityDerivative.php @@ -43,8 +43,8 @@ public function getDerivativeDefinitions(array $base_plugin_definition) { $this->derivatives[$entity_type] = array( 'id' => 'entity:' . $entity_type, 'entity_type' => $entity_type, - 'serialization_class' => $entity_info['class'], - 'label' => $entity_info['label'], + 'serialization_class' => $entity_info->getClass(), + 'label' => $entity_info->getLabel(), ); $this->derivatives[$entity_type] += $base_plugin_definition; } diff --git a/core/modules/rest/lib/Drupal/rest/Plugin/rest/resource/EntityResource.php b/core/modules/rest/lib/Drupal/rest/Plugin/rest/resource/EntityResource.php index 504fc59..09a6cd7 100644 --- a/core/modules/rest/lib/Drupal/rest/Plugin/rest/resource/EntityResource.php +++ b/core/modules/rest/lib/Drupal/rest/Plugin/rest/resource/EntityResource.php @@ -144,7 +144,7 @@ public function patch($id, EntityInterface $entity = NULL) { } $info = $original_entity->entityInfo(); // Make sure that the entity ID is the one provided in the URL. - $entity->{$info['entity_keys']['id']} = $id; + $entity->{$info->getKey('id')} = $id; // Overwrite the received properties. foreach ($entity as $field_name => $field) { diff --git a/core/modules/shortcut/lib/Drupal/shortcut/Form/ShortcutDeleteForm.php b/core/modules/shortcut/lib/Drupal/shortcut/Form/ShortcutDeleteForm.php index aec4a4e..7bd4e47 100644 --- a/core/modules/shortcut/lib/Drupal/shortcut/Form/ShortcutDeleteForm.php +++ b/core/modules/shortcut/lib/Drupal/shortcut/Form/ShortcutDeleteForm.php @@ -10,6 +10,7 @@ use Drupal\Core\Entity\EntityConfirmFormBase; use Drupal\Core\Entity\EntityControllerInterface; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\Entity\EntityType; use Drupal\shortcut\ShortcutStorageControllerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Core\Database\Connection; @@ -46,7 +47,7 @@ public function __construct(ModuleHandlerInterface $module_handler, Connection $ /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $container->get('module_handler'), $container->get('database'), diff --git a/core/modules/shortcut/shortcut.entity.yml b/core/modules/shortcut/shortcut.entity.yml new file mode 100644 index 0000000..a21802e --- /dev/null +++ b/core/modules/shortcut/shortcut.entity.yml @@ -0,0 +1 @@ +shortcut: Drupal\shortcut\Plugin\Core\Entity\Shortcut \ No newline at end of file diff --git a/core/modules/system/lib/Drupal/system/DateFormatListController.php b/core/modules/system/lib/Drupal/system/DateFormatListController.php index e08c825..8776540 100644 --- a/core/modules/system/lib/Drupal/system/DateFormatListController.php +++ b/core/modules/system/lib/Drupal/system/DateFormatListController.php @@ -12,6 +12,7 @@ use Drupal\Core\Datetime\Date; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageControllerInterface; +use Drupal\Core\Entity\EntityType; use Drupal\Core\Extension\ModuleHandlerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -32,7 +33,7 @@ class DateFormatListController extends ConfigEntityListController { * * @param string $entity_type * The type of entity to be listed. - * @param array $entity_info + * @param \Drupal\Core\Entity\EntityType $entity_info * An array of entity info for the entity type. * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage * The entity storage controller class. @@ -41,7 +42,7 @@ class DateFormatListController extends ConfigEntityListController { * @param \Drupal\Core\Datetime\Date $date_service * The date service. */ - public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, Date $date_service) { + public function __construct($entity_type, EntityType $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler, Date $date_service) { parent::__construct($entity_type, $entity_info, $storage, $module_handler); $this->dateService = $date_service; @@ -50,7 +51,7 @@ public function __construct($entity_type, array $entity_info, EntityStorageContr /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $entity_type, $entity_info, diff --git a/core/modules/system/lib/Drupal/system/Form/DateFormatDeleteForm.php b/core/modules/system/lib/Drupal/system/Form/DateFormatDeleteForm.php index 3d3dfc7..24c077c 100644 --- a/core/modules/system/lib/Drupal/system/Form/DateFormatDeleteForm.php +++ b/core/modules/system/lib/Drupal/system/Form/DateFormatDeleteForm.php @@ -11,6 +11,7 @@ use Drupal\Core\Datetime\Date; use Drupal\Core\Entity\EntityConfirmFormBase; use Drupal\Core\Entity\EntityControllerInterface; +use Drupal\Core\Entity\EntityType; use Drupal\Core\Extension\ModuleHandlerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -43,7 +44,7 @@ public function __construct(ModuleHandlerInterface $module_handler, Date $date_s /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $container->get('module_handler'), $container->get('date') diff --git a/core/modules/system/lib/Drupal/system/Form/DateFormatFormBase.php b/core/modules/system/lib/Drupal/system/Form/DateFormatFormBase.php index 4d347c5..b335ee9 100644 --- a/core/modules/system/lib/Drupal/system/Form/DateFormatFormBase.php +++ b/core/modules/system/lib/Drupal/system/Form/DateFormatFormBase.php @@ -11,6 +11,7 @@ use Drupal\Core\Ajax\ReplaceCommand; use Drupal\Core\Datetime\Date; use Drupal\Core\Entity\EntityControllerInterface; +use Drupal\Core\Entity\EntityType; use Drupal\Core\Extension\ModuleHandlerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Core\Datetime\DrupalDateTime; @@ -66,7 +67,7 @@ function __construct(ModuleHandlerInterface $module_handler, QueryFactory $query /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $container->get('module_handler'), $container->get('entity.query'), diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiInfoTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiInfoTest.php index cf7d9cf..b7a65d6 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiInfoTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityApiInfoTest.php @@ -28,6 +28,7 @@ public static function getInfo() { function testEntityInfoChanges() { module_enable(array('entity_cache_test')); $entity_info = entity_get_info(); + // @fixme How to replace this. $this->assertTrue(isset($entity_info['entity_cache_test']), 'Test entity type found.'); // Change the label of the test entity type and make sure changes appear @@ -42,6 +43,7 @@ function testEntityInfoChanges() { // Disable the providing module and make sure the entity type is gone. module_disable(array('entity_cache_test', 'entity_cache_test_dependency')); $entity_info = entity_get_info(); + // @fixme How to replace this. $this->assertFalse(isset($entity_info['entity_cache_test']), 'Entity type of the providing module is gone.'); } diff --git a/core/modules/system/system.entity.yml b/core/modules/system/system.entity.yml new file mode 100644 index 0000000..f64bbf2 --- /dev/null +++ b/core/modules/system/system.entity.yml @@ -0,0 +1,3 @@ +action: Drupal\system\Plugin\Core\Entity\Action +menu: Drupal\system\Plugin\Core\Entity\Menu +date_format: Drupal\system\Plugin\Core\Entity\DateFormat diff --git a/core/modules/system/tests/modules/entity_cache_test_dependency/entity_cache_test_dependency.entity.yml b/core/modules/system/tests/modules/entity_cache_test_dependency/entity_cache_test_dependency.entity.yml new file mode 100644 index 0000000..49c1dae --- /dev/null +++ b/core/modules/system/tests/modules/entity_cache_test_dependency/entity_cache_test_dependency.entity.yml @@ -0,0 +1 @@ +entity_cache_test: Drupal\entity_cache_test_dependency\Plugin\Core\Entity\EntityCacheTest \ No newline at end of file diff --git a/core/modules/system/tests/modules/entity_test/entity_test.entity.yml b/core/modules/system/tests/modules/entity_test/entity_test.entity.yml new file mode 100644 index 0000000..9fdbcd3 --- /dev/null +++ b/core/modules/system/tests/modules/entity_test/entity_test.entity.yml @@ -0,0 +1,10 @@ +entity_test: Drupal\entity_test\Plugin\Core\Entity\EntityTest +entity_test_cache: Drupal\entity_test\Plugin\Core\Entity\EntityTestCache +entity_test_default_access: Drupal\entity_test\Plugin\Core\Entity\EntityTestDefaultAccess +entity_test_label: Drupal\entity_test\Plugin\Core\Entity\EntityTestLabel +entity_test_label_callback: Drupal\entity_test\Plugin\Core\Entity\EntityTestLabelCallback +entity_test_mul: Drupal\entity_test\Plugin\Core\Entity\EntityTestMul +entity_test_mulrev: Drupal\entity_test\Plugin\Core\Entity\EntityTestMulRev +entity_test_no_label: Drupal\entity_test\Plugin\Core\Entity\EntityTestNoLabel +entity_test_render: Drupal\entity_test\Plugin\Core\Entity\EntityTestRender +entity_test_rev: Drupal\entity_test\Plugin\Core\Entity\EntityTestRev \ No newline at end of file diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module index 05498f7..4f341d0 100644 --- a/core/modules/system/tests/modules/entity_test/entity_test.module +++ b/core/modules/system/tests/modules/entity_test/entity_test.module @@ -60,8 +60,10 @@ function entity_test_entity_types($filter = NULL) { function entity_test_entity_info_alter(&$info) { // Optionally specify a translation handler for testing translations. if (Drupal::state()->get('entity_test.translation')) { - foreach(entity_test_entity_types() as $entity_type) { - $info[$entity_type]['translation'][$entity_type] = TRUE; + foreach (entity_test_entity_types() as $entity_type) { + if (isset($info[$entity_type])) { + $info[$entity_type]->translation[$entity_type] = TRUE; + } } } } @@ -130,7 +132,7 @@ function entity_test_entity_bundle_info() { $bundles = array(); $entity_info = entity_get_info(); foreach ($entity_info as $entity_type => $info) { - if ($info['module'] == 'entity_test') { + if ($info->getModule() == 'entity_test') { $bundles[$entity_type] = Drupal::state()->get($entity_type . '.bundles') ?: array($entity_type => array('label' => 'Entity Test Bundle')); } } @@ -143,7 +145,7 @@ function entity_test_entity_bundle_info() { function entity_test_entity_view_mode_info_alter(&$view_modes) { $entity_info = entity_get_info(); foreach ($entity_info as $entity_type => $info) { - if ($entity_info[$entity_type]['module'] == 'entity_test') { + if ($info->getModule() == 'entity_test') { $view_modes[$entity_type] = array( 'full' => array( 'label' => t('Full object'), diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestFormController.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestFormController.php index 1dbb859..8765a5e 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestFormController.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestFormController.php @@ -50,7 +50,7 @@ public function form(array $form, array &$form_state) { // @todo: Is there a better way to check if an entity type is revisionable? $entity_info = $entity->entityInfo(); - if (!empty($entity_info['entity_keys']['revision']) && !$entity->isNew()) { + if ($entity_info->getKey('revision') && !$entity->isNew()) { $form['revision'] = array( '#type' => 'checkbox', '#title' => t('Create new revision'), diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Plugin/Core/Entity/EntityTest.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Plugin/Core/Entity/EntityTest.php index 332b322..bd31ca0 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Plugin/Core/Entity/EntityTest.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Plugin/Core/Entity/EntityTest.php @@ -93,7 +93,7 @@ protected function init() { */ public function label($langcode = Language::LANGCODE_DEFAULT) { $info = $this->entityInfo(); - if (isset($info['entity_keys']['label']) && $info['entity_keys']['label'] == 'name') { + if ($info->getKey('label') == 'name') { return $this->getTranslation($langcode)->name->value; } else { diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Plugin/Core/Entity/EntityTestCache.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Plugin/Core/Entity/EntityTestCache.php index c40b11e..73edfc4 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Plugin/Core/Entity/EntityTestCache.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Plugin/Core/Entity/EntityTestCache.php @@ -93,7 +93,7 @@ protected function init() { */ public function label($langcode = Language::LANGCODE_DEFAULT) { $info = $this->entityInfo(); - if (isset($info['entity_keys']['label']) && $info['entity_keys']['label'] == 'name') { + if ($info->getKey('label') == 'name') { return $this->getTranslation($langcode)->name->value; } else { diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Access/TaxonomyTermCreateAccess.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Access/TaxonomyTermCreateAccess.php index dbf7d06..a562b17 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Access/TaxonomyTermCreateAccess.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Access/TaxonomyTermCreateAccess.php @@ -8,6 +8,7 @@ namespace Drupal\taxonomy\Access; use Drupal\Core\Entity\EntityCreateAccessCheck; +use Drupal\Core\Entity\EntityType; use Symfony\Component\HttpFoundation\Request; /** @@ -23,7 +24,7 @@ class TaxonomyTermCreateAccess extends EntityCreateAccessCheck { /** * {@inheritdoc} */ - protected function prepareEntityValues(array $definition, Request $request, $bundle = NULL) { + protected function prepareEntityValues(EntityType $definition, Request $request, $bundle = NULL) { $values = array(); if ($vocabulary = $request->attributes->get('taxonomy_vocabulary')) { $values = parent::prepareEntityValues($definition, $request, $vocabulary->id()); diff --git a/core/modules/taxonomy/taxonomy.entity.yml b/core/modules/taxonomy/taxonomy.entity.yml new file mode 100644 index 0000000..329048f --- /dev/null +++ b/core/modules/taxonomy/taxonomy.entity.yml @@ -0,0 +1,2 @@ +taxonomy_term: Drupal\taxonomy\Plugin\Core\Entity\Term +taxonomy_vocabulary: Drupal\taxonomy\Plugin\Core\Entity\Vocabulary \ No newline at end of file diff --git a/core/modules/taxonomy/taxonomy.views.inc b/core/modules/taxonomy/taxonomy.views.inc index 5646268..387585e 100644 --- a/core/modules/taxonomy/taxonomy.views.inc +++ b/core/modules/taxonomy/taxonomy.views.inc @@ -369,7 +369,7 @@ function taxonomy_field_views_data_views_data_alter(&$data, $field) { $pseudo_field_name = 'reverse_' . $field['field_name'] . '_' . $entity_type; list($label, $all_labels) = field_views_field_label($field['field_name']); - $entity = $entity_info['label']; + $entity = $entity_info->getLabel(); if ($entity == t('Node')) { $entity = t('Content'); } @@ -381,8 +381,8 @@ function taxonomy_field_views_data_views_data_alter(&$data, $field) { 'field_name' => $field['field_name'], 'field table' => _field_sql_storage_tablename($field), 'field field' => $field['field_name'] . '_target_id', - 'base' => $entity_info['base_table'], - 'base field' => $entity_info['entity_keys']['id'], + 'base' => $entity_info->getBaseTable(), + 'base field' => $entity_info->getKey('id'), 'label' => t('!field_name', array('!field_name' => $field['field_name'])), 'join_extra' => array( 0 => array( diff --git a/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php b/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php index 0a2b900..aec3e06 100644 --- a/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php +++ b/core/modules/text/lib/Drupal/text/Tests/Formatter/TextPlainUnitTest.php @@ -105,7 +105,7 @@ function setUp() { */ protected function createEntity($values = array()) { $info = entity_get_info($this->entity_type); - $bundle_key = $info['entity_keys']['bundle']; + $bundle_key = $info->getKey('bundle'); $entity = entity_create($this->entity_type, $values + array( $bundle_key => $this->bundle, )); diff --git a/core/modules/tour/tour.entity.yml b/core/modules/tour/tour.entity.yml new file mode 100644 index 0000000..c86dbe4 --- /dev/null +++ b/core/modules/tour/tour.entity.yml @@ -0,0 +1 @@ +tour: Drupal\tour\Plugin\Core\Entity\Tour \ No newline at end of file diff --git a/core/modules/user/lib/Drupal/user/RoleListController.php b/core/modules/user/lib/Drupal/user/RoleListController.php index a2250f5..e1a8a73 100644 --- a/core/modules/user/lib/Drupal/user/RoleListController.php +++ b/core/modules/user/lib/Drupal/user/RoleListController.php @@ -91,7 +91,7 @@ public function buildForm(array $form, array &$form_state) { $form['entities'] = array( '#type' => 'table', '#header' => $this->buildHeader(), - '#empty' => t('There is no @label yet.', array('@label' => $this->entityInfo['label'])), + '#empty' => t('There is no @label yet.', array('@label' => $this->entityInfo->getLabel())), '#tabledrag' => array( array('order', 'sibling', 'weight'), ), diff --git a/core/modules/user/lib/Drupal/user/UserStorageController.php b/core/modules/user/lib/Drupal/user/UserStorageController.php index 8b4653c..c5eb7bd 100644 --- a/core/modules/user/lib/Drupal/user/UserStorageController.php +++ b/core/modules/user/lib/Drupal/user/UserStorageController.php @@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityBCDecorator; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityType; use Drupal\Core\Password\PasswordInterface; use Drupal\Core\Database\Connection; use Drupal\user\UserDataInterface; @@ -61,7 +62,7 @@ public function __construct($entity_type, $entity_info, Connection $database, Pa /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $entity_type, $entity_info, @@ -161,7 +162,7 @@ protected function invokeHook($hook, EntityInterface $entity) { if ($function == 'field_attach_revision_delete') { $function = 'field_attach_delete_revision'; } - if (!empty($this->entityInfo['fieldable']) && function_exists($function)) { + if ($this->entityInfo->isFieldable() && function_exists($function)) { $function($entity->getBCEntity()); } diff --git a/core/modules/user/user.entity.yml b/core/modules/user/user.entity.yml new file mode 100644 index 0000000..e8ec6c8 --- /dev/null +++ b/core/modules/user/user.entity.yml @@ -0,0 +1,2 @@ +user: Drupal\user\Plugin\Core\Entity\User +user_role: Drupal\user\Plugin\Core\Entity\Role \ No newline at end of file diff --git a/core/modules/views/lib/Drupal/views/Plugin/Derivative/ViewsEntityRow.php b/core/modules/views/lib/Drupal/views/Plugin/Derivative/ViewsEntityRow.php index 5da356b..8e3a991 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/Derivative/ViewsEntityRow.php +++ b/core/modules/views/lib/Drupal/views/Plugin/Derivative/ViewsEntityRow.php @@ -46,13 +46,13 @@ public function getDerivativeDefinitions(array $base_plugin_definition) { $views_data = Views::viewsData(); foreach ($entity_types as $entity_type => $entity_info) { // Just add support for entity types which have a views integration. - if (isset($entity_info['base_table']) && $views_data->get($entity_info['base_table']) && \Drupal::entityManager()->hasController($entity_type, 'render')) { + if ($entity_info->hasBaseTable() && $views_data->get($entity_info->getBaseTable()) && \Drupal::entityManager()->hasController($entity_type, 'render')) { $this->derivatives[$entity_type] = array( 'id' => 'entity:' . $entity_type, 'module' => 'views', - 'title' => $entity_info['label'], - 'help' => t('Display the @label', array('@label' => $entity_info['label'])), - 'base' => array($entity_info['base_table']), + 'title' => $entity_info->getLabel(), + 'help' => t('Display the @label', array('@label' => $entity_info->getLabel())), + 'base' => array($entity_info->getBaseTable()), 'entity_type' => $entity_type, 'display_types' => array('normal'), 'class' => $base_plugin_definition['class'], diff --git a/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/ViewsSelection.php b/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/ViewsSelection.php index e9db07e..e5b0b29 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/ViewsSelection.php +++ b/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/ViewsSelection.php @@ -67,7 +67,7 @@ public static function settingsForm(&$field, &$instance) { $options = array(); foreach ($displays as $data) { list($view, $display_id) = $data; - if ($view->storage->get('base_table') == $entity_info['base_table']) { + if ($view->storage->get('base_table') == $entity_info->getBaseTable()) { $name = $view->storage->get('id'); $display = $view->storage->get('display'); $options[$name . ':' . $display_id] = $name . ' - ' . $display[$display_id]['display_title']; diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php index b0cbb7b..8f3c848 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/display/DisplayPluginBase.php @@ -1572,9 +1572,9 @@ public function buildOptionsForm(&$form, &$form_state) { $entity_tables = array(); $has_translation_handlers = FALSE; foreach ($entities as $type => $entity_info) { - $entity_tables[] = $entity_info['base_table']; + $entity_tables[] = $entity_info->getBaseTable(); - if (!empty($entity_info['translation'])) { + if (!empty($entity_info->translation)) { $has_translation_handlers = TRUE; } } diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/filter/Bundle.php b/core/modules/views/lib/Drupal/views/Plugin/views/filter/Bundle.php index 3c1f54f..4234ad2 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/filter/Bundle.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/filter/Bundle.php @@ -30,7 +30,7 @@ class Bundle extends InOperator { /** * The entity info for the entity type. * - * @var array + * @var \Drupal\Core\Entity\Annotation\EntityType */ protected $entityInfo; @@ -42,7 +42,7 @@ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$o $this->entityType = $this->getEntityType(); $this->entityInfo = entity_get_info($this->entityType); - $this->real_field = $this->entityInfo['entity_keys']['bundle']; + $this->real_field = $this->entityInfo->getKey('bundle'); } /** @@ -51,7 +51,7 @@ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$o public function getValueOptions() { if (!isset($this->value_options)) { $types = entity_get_bundles($this->entityType); - $this->value_title = t('@entity types', array('@entity' => $this->entityInfo['label'])); + $this->value_title = t('@entity types', array('@entity' => $this->entityInfo->getLabel())); $options = array(); foreach ($types as $type => $info) { diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/query/Sql.php b/core/modules/views/lib/Drupal/views/Plugin/views/query/Sql.php index 8162b2c..f7862a2 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/query/Sql.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/query/Sql.php @@ -1262,7 +1262,7 @@ public function query($get_count = FALSE) { foreach ($entity_tables as $table_alias => $table) { $info = entity_get_info($table['entity_type']); - $base_field = empty($table['revision']) ? $info['entity_keys']['id'] : $info['entity_keys']['revision']; + $base_field = empty($table['revision']) ? $info->getKey('id') : $info->getKey('revision'); $this->addField($table_alias, $base_field, '', $params); } } @@ -1497,7 +1497,7 @@ public function getEntityTables() { // Determine which of the tables are revision tables. foreach ($entity_tables as $table_alias => $table) { $info = entity_get_info($table['entity_type']); - if (isset($info['revision table']) && $info['revision table'] == $table['base']) { + if ($info->hasRevisionTable() && $info->getRevisionTable() == $table['base']) { $entity_tables[$table_alias]['revision'] = TRUE; } } @@ -1530,7 +1530,7 @@ function loadEntities(&$results) { foreach ($entity_tables as $table_alias => $table) { $entity_type = $table['entity_type']; $info = entity_get_info($entity_type); - $id_key = empty($table['revision']) ? $info['entity_keys']['id'] : $info['entity_keys']['revision']; + $id_key = empty($table['revision']) ? $info->getKey('id') : $info->getKey('revision'); $id_alias = $this->getFieldAlias($table_alias, $id_key); foreach ($results as $index => $result) { diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/row/EntityRow.php b/core/modules/views/lib/Drupal/views/Plugin/views/row/EntityRow.php index 10ae792..cb52a40 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/row/EntityRow.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/row/EntityRow.php @@ -78,8 +78,8 @@ public function init(ViewExecutable $view, DisplayPluginBase $display, array &$o $this->entityType = $this->definition['entity_type']; $this->entityInfo = $this->entityManager->getDefinition($this->entityType); - $this->base_table = $this->entityInfo['base_table']; - $this->base_field = $this->entityInfo['entity_keys']['id']; + $this->base_table = $this->entityInfo->getBaseTable(); + $this->base_field = $this->entityInfo->getKey('id'); } /** diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/wizard/WizardPluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/wizard/WizardPluginBase.php index a84eb92..86b0181 100644 --- a/core/modules/views/lib/Drupal/views/Plugin/views/wizard/WizardPluginBase.php +++ b/core/modules/views/lib/Drupal/views/Plugin/views/wizard/WizardPluginBase.php @@ -120,7 +120,7 @@ public function __construct(array $configuration, $plugin_id, array $plugin_defi $entities = entity_get_info(); foreach ($entities as $entity_type => $entity_info) { - if (isset($entity_info['base_table']) && $this->base_table == $entity_info['base_table']) { + if ($this->base_table == $entity_info->getBaseTable()) { $this->entity_info = $entity_info; $this->entity_type = $entity_type; } @@ -559,7 +559,7 @@ protected function buildFilters(&$form, &$form_state) { $bundles = entity_get_bundles($this->entity_type); // If the current base table support bundles and has more than one (like user). - if (isset($this->entity_info['bundle_keys']) && !empty($bundles)) { + if ($this->entity_info && $this->entity_info->getBundleKeys() && !empty($bundles)) { // Get all bundles and their human readable names. $options = array('all' => t('All')); foreach ($bundles as $type => $bundle) { @@ -833,7 +833,7 @@ protected function defaultDisplayFiltersUser(array $form, array &$form_state) { $filters = array(); if (!empty($form_state['values']['show']['type']) && $form_state['values']['show']['type'] != 'all') { - $bundle_key = $this->entity_info['bundle_keys']['bundle']; + $bundle_key = $this->entity_info->getBundleKey('bundle'); // Figure out the table where $bundle_key lives. It may not be the same as // the base table for the view; the taxonomy vocabulary machine_name, for // example, is stored in taxonomy_vocabulary, not taxonomy_term_data. diff --git a/core/modules/views/lib/Drupal/views/Tests/ViewStorageTest.php b/core/modules/views/lib/Drupal/views/Tests/ViewStorageTest.php index 1cfd62a..2990457 100644 --- a/core/modules/views/lib/Drupal/views/Tests/ViewStorageTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/ViewStorageTest.php @@ -7,6 +7,7 @@ namespace Drupal\views\Tests; +use Drupal\Core\Entity\EntityType; use Drupal\views\ViewStorageController; use Drupal\views\Plugin\Core\Entity\View; use Drupal\views\Plugin\views\display\Page; @@ -76,7 +77,7 @@ function testConfigurationEntityCRUD() { $this->controller = $this->container->get('plugin.manager.entity')->getStorageController('view'); // Confirm that an info array has been returned. - $this->assertTrue(!empty($this->info) && is_array($this->info), 'The View info array is loaded.'); + $this->assertTrue($this->info instanceof EntityType, 'The View info array is loaded.'); // Confirm we have the correct controller class. $this->assertTrue($this->controller instanceof ViewStorageController, 'The correct controller is loaded.'); diff --git a/core/modules/views/views.entity.yml b/core/modules/views/views.entity.yml new file mode 100644 index 0000000..a455017 --- /dev/null +++ b/core/modules/views/views.entity.yml @@ -0,0 +1 @@ +view: Drupal\views\Plugin\Core\Entity\View \ No newline at end of file diff --git a/core/modules/views/views.views.inc b/core/modules/views/views.views.inc index 99d23c1..d1ab497 100644 --- a/core/modules/views/views.views.inc +++ b/core/modules/views/views.views.inc @@ -109,8 +109,8 @@ function views_views_data() { // Registers an entity area handler per entity type. foreach (entity_get_info() as $entity_type => $entity_info) { // Exclude entity types, which cannot be rendered. - if (!empty($entity_info['controllers']['render'])) { - $label = $entity_info['label']; + if (!$entity_info->hasController('render')) { + $label = $entity_info->getLabel(); $data['views']['entity_' . $entity_type] = array( 'title' => t('Rendered entity - @label', array('@label' => $label)), 'help' => t('Displays a rendered @label entity in an area.', array('@label' => $label)), diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Form/BreakLockForm.php b/core/modules/views_ui/lib/Drupal/views_ui/Form/BreakLockForm.php index a161caf..2fcedb0 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/Form/BreakLockForm.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/Form/BreakLockForm.php @@ -10,6 +10,7 @@ use Drupal\Core\Entity\EntityConfirmFormBase; use Drupal\Core\Entity\EntityControllerInterface; use Drupal\Core\Entity\EntityManager; +use Drupal\Core\Entity\EntityType; use Drupal\user\TempStoreFactory; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Request; @@ -49,7 +50,7 @@ public function __construct(EntityManager $entity_manager, TempStoreFactory $tem /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $container->get('plugin.manager.entity'), $container->get('user.tempstore') diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewAddFormController.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewAddFormController.php index 4ad9376..a277b5f 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/ViewAddFormController.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewAddFormController.php @@ -8,6 +8,7 @@ namespace Drupal\views_ui; use Drupal\Core\Entity\EntityControllerInterface; +use Drupal\Core\Entity\EntityType; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\views\Plugin\views\wizard\WizardPluginBase; use Drupal\views\Plugin\views\wizard\WizardException; @@ -43,7 +44,7 @@ public function __construct(ModuleHandlerInterface $module_handler, ViewsPluginM /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $container->get('module_handler'), $container->get('plugin.manager.views.wizard') diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewEditFormController.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewEditFormController.php index 015a855..523f329 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/ViewEditFormController.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewEditFormController.php @@ -10,6 +10,7 @@ use Drupal\Core\Ajax\AjaxResponse; use Drupal\Core\Ajax\HtmlCommand; use Drupal\Core\Ajax\ReplaceCommand; +use Drupal\Core\Entity\EntityType; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Component\Utility\NestedArray; use Drupal\views\ViewExecutable; @@ -57,7 +58,7 @@ public function __construct(ModuleHandlerInterface $module_handler, TempStoreFac /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info, $operation = NULL) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info, $operation = NULL) { return new static( $container->get('module_handler'), $container->get('user.tempstore'), diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewListController.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewListController.php index 909aad0..cf2f55d 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/ViewListController.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewListController.php @@ -13,6 +13,7 @@ use Drupal\Core\Config\Entity\ConfigEntityListController; use Drupal\Core\Entity\EntityControllerInterface; use Drupal\Core\Entity\EntityStorageControllerInterface; +use Drupal\Core\Entity\EntityType; use Drupal\Core\Extension\ModuleHandlerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -31,7 +32,7 @@ class ViewListController extends ConfigEntityListController implements EntityCon /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $entity_type, $container->get('plugin.manager.entity')->getStorageController($entity_type), @@ -48,14 +49,14 @@ public static function createInstance(ContainerInterface $container, $entity_typ * The type of entity to be listed. * @param \Drupal\Core\Entity\EntityStorageControllerInterface $storage. * The entity storage controller class. - * @param array $entity_info + * @param \Drupal\Core\Entity\EntityType $entity_info * An array of entity info for this entity type. * @param \Drupal\Component\Plugin\PluginManagerInterface $display_manager * The views display plugin manager to use. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler. */ - public function __construct($entity_type, EntityStorageControllerInterface $storage, $entity_info, PluginManagerInterface $display_manager, ModuleHandlerInterface $module_handler) { + public function __construct($entity_type, EntityStorageControllerInterface $storage, EntityType $entity_info, PluginManagerInterface $display_manager, ModuleHandlerInterface $module_handler) { parent::__construct($entity_type, $entity_info, $storage, $module_handler); $this->displayManager = $display_manager; diff --git a/core/modules/views_ui/lib/Drupal/views_ui/ViewPreviewFormController.php b/core/modules/views_ui/lib/Drupal/views_ui/ViewPreviewFormController.php index 4ac5b8c..fc76297 100644 --- a/core/modules/views_ui/lib/Drupal/views_ui/ViewPreviewFormController.php +++ b/core/modules/views_ui/lib/Drupal/views_ui/ViewPreviewFormController.php @@ -8,6 +8,7 @@ namespace Drupal\views_ui; use Drupal\Core\Entity\EntityControllerInterface; +use Drupal\Core\Entity\EntityType; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\user\TempStoreFactory; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -41,7 +42,7 @@ public function __construct(ModuleHandlerInterface $module_handler, TempStoreFac /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + public static function createInstance(ContainerInterface $container, $entity_type, EntityType $entity_info) { return new static( $container->get('module_handler'), $container->get('user.tempstore') diff --git a/core/modules/views_ui/views_ui.module b/core/modules/views_ui/views_ui.module index 4d039c3..d9b3d67 100644 --- a/core/modules/views_ui/views_ui.module +++ b/core/modules/views_ui/views_ui.module @@ -5,6 +5,7 @@ * Provide structure for the administrative interface to Views. */ +use Drupal\Core\Entity\EntityType; use Drupal\views\ViewExecutable; use Drupal\views\ViewStorageInterface; use Drupal\views_ui\ViewUI; @@ -95,17 +96,17 @@ function views_ui_menu() { * Implements hook_entity_info(). */ function views_ui_entity_info(&$entity_info) { - $entity_info['view']['controllers'] += array( - 'list' => 'Drupal\views_ui\ViewListController', - 'form' => array( - 'edit' => 'Drupal\views_ui\ViewEditFormController', - 'add' => 'Drupal\views_ui\ViewAddFormController', - 'preview' => 'Drupal\views_ui\ViewPreviewFormController', - 'clone' => 'Drupal\views_ui\ViewCloneFormController', - 'delete' => 'Drupal\views_ui\ViewDeleteFormController', - 'break_lock' => 'Drupal\views_ui\Form\BreakLockForm', - ), - ); + if (isset($entity_info['view'])) { + $controllers = $entity_info['view']->getController('form'); + $controllers['edit'] = 'Drupal\views_ui\ViewEditFormController'; + $controllers['add'] = 'Drupal\views_ui\ViewAddFormController'; + $controllers['preview'] = 'Drupal\views_ui\ViewPreviewFormController'; + $controllers['clone'] = 'Drupal\views_ui\ViewCloneFormController'; + $controllers['delete'] = 'Drupal\views_ui\ViewDeleteFormController'; + $controllers['break_lock'] = 'Drupal\views_ui\Form\BreakLockForm'; + $entity_info['view']->setController('form', $controllers); + $entity_info['view']->setController('list', 'Drupal\views_ui\ViewListController'); + } } /** diff --git a/core/tests/Drupal/Tests/Core/AnnotationReaderTest.php b/core/tests/Drupal/Tests/Core/AnnotationReaderTest.php new file mode 100644 index 0000000..16d8eb8 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/AnnotationReaderTest.php @@ -0,0 +1,44 @@ + 'Annotation reader tesst', + 'description' => '.', + 'group' => 'core' + ); + } + + public function setUp() { + $this->reader = new AnnotationReader; + $this->reader->setLoader(test_classloader()); + } + + public function testGetClassAnnotation() { + $res = $this->reader->getClassAnnotation('Drupal\Tests\Core\TestAnnotationClass', 'Drupal\Core\Entity\Annotation\EntityType'); + $expected = new EntityType(array('id' => "test", 'label' => "Test")); + $this->assertEquals($expected, $res); + } + + public function testGetClassAnnotationCache() { + $reader_mock = $this->getMock('Doctrine\Common\Annotations\AnnotationReader'); + $return_annotation = new EntityType(array('id' => "test", 'label' => "Test")); + $reader_mock->expects($this->once()) + ->method('getClassAnnotations') + ->will($this->returnValue($return_annotation)); + $this->reader->setReader($reader_mock); + + // Expectation is to only call $reader_mock once, so this would fail if the + // cache wasn't working correctly. + $this->reader->getClassAnnotations('Drupal\Tests\Core\TestAnnotationClass'); + $this->reader->getClassAnnotations('Drupal\Tests\Core\TestAnnotationClass'); + } +} diff --git a/core/tests/Drupal/Tests/Core/TestAnnotationClass.php b/core/tests/Drupal/Tests/Core/TestAnnotationClass.php new file mode 100644 index 0000000..f7e4994 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/TestAnnotationClass.php @@ -0,0 +1,17 @@ +add('Drupal\\', __DIR__); -$loader->add('Drupal\Core', __DIR__ . "/../../core/lib"); -$loader->add('Drupal\Component', __DIR__ . "/../../core/lib"); +function test_classloader() { + // Register the namespaces we'll need to autoload from. + $loader = require __DIR__ . "/../vendor/autoload.php"; + $loader->add('Drupal\\', __DIR__); + $loader->add('Drupal\Core', __DIR__ . "/../../core/lib"); + $loader->add('Drupal\Component', __DIR__ . "/../../core/lib"); -foreach (scandir(__DIR__ . "/../modules") as $module) { - $loader->add('Drupal\\' . $module, __DIR__ . "/../modules/" . $module . "/lib"); - // Add test module classes. - $test_modules_dir = __DIR__ . "/../modules/$module/tests/modules"; - if (is_dir($test_modules_dir)) { - foreach (scandir($test_modules_dir) as $test_module) { - $loader->add('Drupal\\' . $test_module, $test_modules_dir . '/' . $test_module . '/lib'); + foreach (scandir(__DIR__ . "/../modules") as $module) { + $loader->add('Drupal\\' . $module, __DIR__ . "/../modules/" . $module . "/lib"); + // Add test module classes. + $test_modules_dir = __DIR__ . "/../modules/$module/tests/modules"; + if (is_dir($test_modules_dir)) { + foreach (scandir($test_modules_dir) as $test_module) { + $loader->add('Drupal\\' . $test_module, $test_modules_dir . '/' . $test_module . '/lib'); + } } } + return $loader; } +test_classloader(); require __DIR__ . "/../../core/lib/Drupal.php"; // Look into removing this later. define('REQUEST_TIME', (int) $_SERVER['REQUEST_TIME']);