Commit 814aed20 authored by alexpott's avatar alexpott

Issue #2005716 by tim.plunkett, msonnabaum, dawehner, alexpott, effulgentsia:...

Issue #2005716 by tim.plunkett, msonnabaum, dawehner, alexpott, effulgentsia: Promote EntityType to a domain object.
parent 18cc78af
......@@ -7,6 +7,7 @@
use Drupal\Core\Config\Context\FreeConfigContext;
use Drupal\Core\Config\FileStorage;
use Drupal\Core\Config\StorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Symfony\Component\Yaml\Dumper;
/**
......@@ -202,8 +203,8 @@ function config_context_leave() {
* Either the entity type name, or NULL if none match.
*/
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);
$entities = array_filter(\Drupal::entityManager()->getDefinitions(), function (EntityTypeInterface $entity_info) use ($name) {
return ($config_prefix = $entity_info->getConfigPrefix()) && strpos($name, $config_prefix . '.') === 0;
});
return key($entities);
}
......
......@@ -266,11 +266,10 @@ function entity_revision_delete($entity_type, $revision_id) {
* @see \Drupal\Core\Entity\EntityManagerInterface
*/
function entity_load_by_uuid($entity_type, $uuid, $reset = FALSE) {
$entity_info = entity_get_info($entity_type);
if (empty($entity_info['entity_keys']['uuid'])) {
$entity_info = \Drupal::entityManager()->getDefinition($entity_type);
if (!$uuid_key = $entity_info->getKey('uuid')) {
throw new EntityStorageException("Entity type $entity_type does not support UUIDs.");
}
$uuid_key = $entity_info['entity_keys']['uuid'];
$controller = \Drupal::entityManager()->getStorageController($entity_type);
if ($reset) {
......
<?php
/**
* @file
* Contains \Drupal\Component\Annotation\AnnotationBase.
*/
namespace Drupal\Component\Annotation;
/**
* Provides a base class for classed annotations.
*/
abstract class AnnotationBase implements AnnotationInterface {
/**
* The annotated class ID.
*
* @var string
*/
public $id;
/**
* The class used for this annotated class.
*
* @var string
*/
protected $class;
/**
* The provider of the annotated class.
*
* @var string
*/
protected $provider;
/**
* {@inheritdoc}
*/
public function getProvider() {
return $this->provider;
}
/**
* {@inheritdoc}
*/
public function setProvider($provider) {
$this->provider = $provider;
}
/**
* {@inheritdoc}
*/
public function getId() {
return $this->id;
}
/**
* {@inheritdoc}
*/
public function getClass() {
return $this->class;
}
/**
* {@inheritdoc}
*/
public function setClass($class) {
$this->class = $class;
}
}
......@@ -17,4 +17,39 @@ interface AnnotationInterface {
*/
public function get();
/**
* Returns the name of the provider of the annotated class.
*
* @return string
*/
public function getProvider();
/**
* Sets the name of the provider of the annotated class.
*
* @param string $provider
*/
public function setProvider($provider);
/**
* Returns the unique ID for this annotated class.
*
* @return string
*/
public function getId();
/**
* Returns the class of the annotated class.
*
* @return string
*/
public function getClass();
/**
* Sets the class of the annotated class.
*
* @param string $class
*/
public function setClass($class);
}
......@@ -71,10 +71,45 @@ protected function parse(array $values) {
}
/**
* Implements Drupal\Core\Annotation\AnnotationInterface::get().
* {@inheritdoc}
*/
public function get() {
return $this->definition;
}
/**
* {@inheritdoc}
*/
public function getProvider() {
return isset($this->definition['provider']) ? $this->definition['provider'] : FALSE;
}
/**
* {@inheritdoc}
*/
public function setProvider($provider) {
$this->definition['provider'] = $provider;
}
/**
* {@inheritdoc}
*/
public function getId() {
return $this->definition['id'];
}
/**
* {@inheritdoc}
*/
public function getClass() {
return $this->definition['class'];
}
/**
* {@inheritdoc}
*/
public function setClass($class) {
$this->definition['class'] = $class;
}
}
......@@ -7,6 +7,7 @@
namespace Drupal\Component\Annotation\Plugin\Discovery;
use Drupal\Component\Annotation\AnnotationInterface;
use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
use Drupal\Component\Annotation\Reflection\MockFileFinder;
use Doctrine\Common\Annotations\SimpleAnnotationReader;
......@@ -115,12 +116,12 @@ public function getDefinitions() {
$finder = MockFileFinder::create($fileinfo->getPathName());
$parser = new StaticReflectionParser($class, $finder, TRUE);
/** @var $annotation \Drupal\Component\Annotation\AnnotationInterface */
if ($annotation = $reader->getClassAnnotation($parser->getReflectionClass(), $this->pluginDefinitionAnnotationName)) {
$this->prepareAnnotationDefinition($annotation, $class);
// AnnotationInterface::get() returns the array definition
// instead of requiring us to work with the annotation object.
$definition = $annotation->get();
$definition['class'] = $class;
$definitions[$definition['id']] = $definition;
$definitions[$annotation->getId()] = $annotation->get();
}
}
}
......@@ -134,6 +135,18 @@ public function getDefinitions() {
return $definitions;
}
/**
* Prepares the annotation definition.
*
* @param \Drupal\Component\Annotation\AnnotationInterface $annotation
* The annotation derived from the plugin.
* @param string $class
* The class used for the plugin.
*/
protected function prepareAnnotationDefinition(AnnotationInterface $annotation, $class) {
$annotation->setClass($class);
}
/**
* Returns an array of PSR-0 namespaces to search for plugin classes.
*/
......
......@@ -12,7 +12,7 @@
*
* @Annotation
*/
class PluginID implements AnnotationInterface {
class PluginID extends AnnotationBase {
/**
* The plugin ID.
......@@ -29,7 +29,16 @@ class PluginID implements AnnotationInterface {
public function get() {
return array(
'id' => $this->value,
'class' => $this->class,
'provider' => $this->provider,
);
}
/**
* {@inheritdoc}
*/
public function getId() {
return $this->value;
}
}
......@@ -7,7 +7,7 @@
namespace Drupal\Core\Annotation;
use Drupal\Component\Annotation\AnnotationInterface;
use Drupal\Component\Annotation\AnnotationBase;
/**
* @defgroup plugin_translatable Translatable plugin metadata
......@@ -45,7 +45,7 @@
*
* @ingroup plugin_translatable
*/
class Translation implements AnnotationInterface {
class Translation extends AnnotationBase {
/**
* The translation of the value passed to the constructor of the class.
......
......@@ -23,7 +23,7 @@ public function load() {
// Sort the entities using the entity class's sort() method.
// See \Drupal\Core\Config\Entity\ConfigEntityBase::sort().
uasort($entities, array($this->entityInfo['class'], 'sort'));
uasort($entities, array($this->entityInfo->getClass(), 'sort'));
return $entities;
}
......@@ -41,7 +41,7 @@ public function getOperations(EntityInterface $entity) {
$operations['edit']['href'] = $uri['path'];
}
if (isset($this->entityInfo['entity_keys']['status'])) {
if ($this->entityInfo->hasKey('status')) {
if (!$entity->status()) {
$operations['enable'] = array(
'title' => t('Enable'),
......
......@@ -13,6 +13,7 @@
use Drupal\Core\Config\Config;
use Drupal\Core\Config\ConfigFactory;
use Drupal\Core\Config\StorageInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\Query\QueryFactory;
use Drupal\Component\Uuid\UuidInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
......@@ -79,10 +80,8 @@ class ConfigStorageController extends EntityStorageControllerBase {
/**
* Constructs a ConfigStorageController object.
*
* @param string $entity_type
* The entity type for which the instance is created.
* @param array $entity_info
* An array of entity info for the entity type.
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_info
* The entity info for the entity type.
* @param \Drupal\Core\Config\ConfigFactory $config_factory
* The config factory service.
* @param \Drupal\Core\Config\StorageInterface $config_storage
......@@ -92,17 +91,11 @@ class ConfigStorageController extends EntityStorageControllerBase {
* @param \Drupal\Component\Uuid\UuidInterface $uuid_service
* The UUID service.
*/
public function __construct($entity_type, array $entity_info, ConfigFactory $config_factory, StorageInterface $config_storage, QueryFactory $entity_query_factory, UuidInterface $uuid_service) {
parent::__construct($entity_type, $entity_info);
public function __construct(EntityTypeInterface $entity_info, ConfigFactory $config_factory, StorageInterface $config_storage, QueryFactory $entity_query_factory, UuidInterface $uuid_service) {
parent::__construct($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;
......@@ -113,9 +106,8 @@ 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, EntityTypeInterface $entity_info) {
return new static(
$entity_type,
$entity_info,
$container->get('config.factory'),
$container->get('config.storage'),
......@@ -208,7 +200,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() . '.';
}
/**
......@@ -249,7 +241,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.
......@@ -276,7 +268,7 @@ protected function buildQuery($ids, $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.
......@@ -314,7 +306,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 $entity) {
$this->invokeHook('predelete', $entity);
......@@ -458,7 +450,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->setSyncing(TRUE);
$entity->original = clone $entity;
......@@ -489,7 +481,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->setSyncing(TRUE);
$entity->delete();
......
......@@ -9,6 +9,7 @@
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityStorageControllerInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormInterface;
......@@ -41,12 +42,12 @@ abstract class DraggableListController extends ConfigEntityListController implem
/**
* {@inheritdoc}
*/
public function __construct($entity_type, array $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler) {
parent::__construct($entity_type, $entity_info, $storage, $module_handler);
public function __construct(EntityTypeInterface $entity_info, EntityStorageControllerInterface $storage, ModuleHandlerInterface $module_handler) {
parent::__construct($entity_info, $storage, $module_handler);
// Check if the entity type supports weighting.
if (!empty($this->entityInfo['entity_keys']['weight'])) {
$this->weightKey = $this->entityInfo['entity_keys']['weight'];
if ($this->entityInfo->hasKey('weight')) {
$this->weightKey = $this->entityInfo->getKey('weight');
}
}
......@@ -99,7 +100,7 @@ public function buildForm(array $form, array &$form_state) {
$form[$this->entitiesKey] = 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(
'action' => 'order',
......
......@@ -86,7 +86,7 @@ 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();
......
......@@ -179,8 +179,7 @@ public function setNewRevision($value = TRUE) {
* {@inheritdoc}
*/
public function isNewRevision() {
$info = $this->entityInfo();
return $this->newRevision || (!empty($info['entity_keys']['revision']) && !$this->getRevisionId());
return $this->newRevision || ($this->entityInfo()->hasKey('revision') && !$this->getRevisionId());
}
/**
......@@ -712,7 +711,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);
......@@ -898,17 +897,17 @@ 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'])) {
if ($entity_info->hasKey('uuid')) {
// @todo Inject the UUID service into the Entity class once possible.
$duplicate->{$entity_info['entity_keys']['uuid']}->value = \Drupal::service('uuid')->generate();
$duplicate->{$entity_info->getKey('uuid')}->value = \Drupal::service('uuid')->generate();
}
// 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;
......@@ -954,11 +953,12 @@ 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, $langcode);
// @todo Convert to is_callable() and call_user_func().
if (($label_callback = $entity_info->getLabelCallback()) && function_exists($label_callback)) {
$label = $label_callback($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')) && isset($this->{$label_key})) {
$label = $this->{$label_key}->value;
}
return $label;
}
......
......@@ -50,8 +50,7 @@ public function form(array $form, array &$form_state) {
$entity = $this->entity;
// @todo Exploit the Field API to generate the default widgets for the
// entity fields.
$info = $entity->entityInfo();
if (!empty($info['fieldable'])) {
if ($entity->entityInfo()->isFieldable()) {
field_attach_form($entity, $form, $form_state, $this->getFormLangcode($form_state));
}
......@@ -132,14 +131,14 @@ public function isDefaultFormLangcode(array $form_state) {
public function buildEntity(array $form, array &$form_state) {
$entity = clone $this->entity;
$entity_type = $entity->entityType();
$info = entity_get_info($entity_type);
$info = \Drupal::entityManager()->getDefinition($entity_type);
// @todo Exploit the Entity Field API to process the submitted field values.
// Copy top-level form values that are entity fields but not handled by
// 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])) {
......@@ -155,7 +154,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, array('langcode' => $this->getFormLangcode($form_state)));
}
return $entity;
......
......@@ -9,6 +9,7 @@
use Drupal\Component\Uuid\UuidInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\Core\Language\Language;
use Drupal\Component\Utility\NestedArray;
......@@ -60,9 +61,8 @@ class DatabaseStorageController extends EntityStorageControllerBase {
/**
* {@inheritdoc}
*/
public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) {
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_info) {
return new static(
$entity_type,
$entity_info,
$container->get('database'),
$container->get('uuid')
......@@ -72,36 +72,24 @@ public static function createInstance(ContainerInterface $container, $entity_typ
/**
* Constructs a DatabaseStorageController object.
*
* @param string $entity_type
* The entity type for which the instance is created.
* @param array $entity_info
* An array of entity info for the entity type.
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_info
* The entity info for the entity type.
* @param \Drupal\Core\Database\Connection $database
* The database connection to be used.
* @param \Drupal\Component\Uuid\UuidInterface $uuid_service
* The UUID service.
*/
public function __construct($entity_type, array $entity_info, Connection $database, UuidInterface $uuid_service) {
parent::__construct($entity_type, $entity_info);
public function __construct(EntityTypeInterface $entity_info, Connection $database, UuidInterface $uuid_service) {
parent::__construct($entity_info);
$this->database = $database;
$this->uuidService = $uuid_service;
// 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');
}
/**
......@@ -133,11 +121,11 @@ public function loadMultiple(array $ids = NULL) {
// Build and execute the query.
$query_result = $this->buildQuery($ids)->execute();
if (!empty($this->entityInfo['class'])) {
if ($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, $class, array(array(), $this->entityType));
}
$queried_entities = $query_result->fetchAllAssoc($this->idKey);
}
......@@ -229,12 +217,12 @@ protected function buildPropertyQuery(QueryInterface $entity_query, array $value