Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
project
drupal
Commits
5f67fd1d
Commit
5f67fd1d
authored
Jun 20, 2013
by
Dries
Browse files
Issue
#1893820
by fago, das-peter, Berdir: Manage entity field definitions in the entity manager.
parent
98b6331e
Changes
9
Hide whitespace changes
Inline
Side-by-side
core/core.services.yml
View file @
5f67fd1d
...
...
@@ -150,7 +150,7 @@ services:
-
{
name
:
persist
}
plugin.manager.entity
:
class
:
Drupal\Core\Entity\EntityManager
arguments
:
[
'
@container.namespaces'
,
'
@service_container'
]
arguments
:
[
'
@container.namespaces'
,
'
@service_container'
,
'
@module_handler'
,
'
@cache.cache'
,
'
@language_manager'
]
plugin.manager.archiver
:
class
:
Drupal\Core\Archiver\ArchiverManager
arguments
:
[
'
@container.namespaces'
,
'
@cache.cache'
,
'
@language_manager'
,
'
@module_handler'
]
...
...
core/includes/entity.api.php
View file @
5f67fd1d
...
...
@@ -473,26 +473,26 @@ function hook_entity_form_display_alter(\Drupal\entity\Plugin\Core\Entity\Entity
}
/**
* Define custom entity
propertie
s.
* Define custom entity
field
s.
*
* @param string $entity_type
* The entity type for which to define entity
propertie
s.
* The entity type for which to define entity
field
s.
*
* @return array
* An array of property information having the following optional entries:
* - definitions: An array of property definitions to add all entities of this
* type, keyed by property name. See
* Drupal\Core\TypedData\TypedDataManager::create() for a list of supported
* keys in property definitions.
* - optional: An array of property definitions for optional properties keyed
* by property name. Optional properties are properties that only exist for
* certain bundles of the entity type.
* - bundle map: An array keyed by bundle name containing the names of
* optional properties that entities of this bundle have.
*
* @see Drupal\Core\TypedData\TypedDataManager::create()
* An array of entity field information having the following optional entries:
* - definitions: An array of field definitions to add all entities of this
* type, keyed by field name. See
* \Drupal\Core\Entity\EntityManager::getFieldDefinitions() for a list of
* supported keys in field definitions.
* - optional: An array of field definitions for optional entity fields, keyed
* by field name. Optional fields are fields that only exist for certain
* bundles of the entity type.
* - bundle map: An array keyed by bundle name, containing the names of
* optional fields that entities of this bundle have.
*
* @see hook_entity_field_info_alter()
* @see Drupal\Core\Entity\StorageControllerInterface::getPropertyDefinitions()
* @see \Drupal\Core\Entity\EntityManager::getFieldDefinitions()
* @see \Drupal\Core\TypedData\TypedDataManager::create()
*/
function
hook_entity_field_info
(
$entity_type
)
{
if
(
mymodule_uses_entity_type
(
$entity_type
))
{
...
...
@@ -521,12 +521,12 @@ function hook_entity_field_info($entity_type) {
}
/**
* Alter defined entity
propertie
s.
* Alter defined entity
field
s.
*
* @param array $info
* The
property
info array as returned by hook_entity_field_info().
* The
entity field
info array as returned by hook_entity_field_info().
* @param string $entity_type
* The entity type for which entity
propertie
s are defined.
* The entity type for which entity
field
s are defined.
*
* @see hook_entity_field_info()
*/
...
...
core/lib/Drupal/Core/Config/Entity/ConfigStorageController.php
View file @
5f67fd1d
...
...
@@ -401,9 +401,10 @@ public function save(EntityInterface $entity) {
}
/**
*
Implements Drupal\Core\Entity\EntityStorageControllerInterface::getFieldDefinitions().
*
{@inheritdoc}
*/
public
function
getFieldDefinitions
(
array
$constraints
)
{
public
function
baseFieldDefinitions
()
{
// @todo: Define abstract once all entity types have been converted.
return
array
();
}
...
...
core/lib/Drupal/Core/Entity/DatabaseStorageController.php
View file @
5f67fd1d
...
...
@@ -26,22 +26,6 @@
*/
class
DatabaseStorageController
extends
EntityStorageControllerBase
{
/**
* An array of field information, i.e. containing definitions.
*
* @var array
*
* @see hook_entity_field_info()
*/
protected
$entityFieldInfo
;
/**
* Static cache of field definitions per bundle.
*
* @var array
*/
protected
$fieldDefinitions
;
/**
* Name of entity's revision database table field, if it supports revisions.
*
...
...
@@ -555,64 +539,10 @@ protected function invokeHook($hook, EntityInterface $entity) {
}
/**
* Implements \Drupal\Core\Entity\EntityStorageControllerInterface::getFieldDefinitions().
*/
public
function
getFieldDefinitions
(
array
$constraints
)
{
if
(
!
isset
(
$this
->
entityFieldInfo
))
{
// First, try to load from cache.
$cid
=
'entity_field_definitions:'
.
$this
->
entityType
.
':'
.
language
(
Language
::
TYPE_INTERFACE
)
->
langcode
;
if
(
$cache
=
cache
()
->
get
(
$cid
))
{
$this
->
entityFieldInfo
=
$cache
->
data
;
}
else
{
$this
->
entityFieldInfo
=
array
(
'definitions'
=>
$this
->
baseFieldDefinitions
(),
// Contains definitions of optional (per-bundle) fields.
'optional'
=>
array
(),
// An array keyed by bundle name containing the optional fields added
// by the bundle.
'bundle map'
=>
array
(),
);
// Invoke hooks.
$result
=
module_invoke_all
(
$this
->
entityType
.
'_property_info'
);
$this
->
entityFieldInfo
=
NestedArray
::
mergeDeep
(
$this
->
entityFieldInfo
,
$result
);
$result
=
module_invoke_all
(
'entity_field_info'
,
$this
->
entityType
);
$this
->
entityFieldInfo
=
NestedArray
::
mergeDeep
(
$this
->
entityFieldInfo
,
$result
);
$hooks
=
array
(
'entity_field_info'
,
$this
->
entityType
.
'_property_info'
);
drupal_alter
(
$hooks
,
$this
->
entityFieldInfo
,
$this
->
entityType
);
// Enforce fields to be multiple by default.
foreach
(
$this
->
entityFieldInfo
[
'definitions'
]
as
&
$definition
)
{
$definition
[
'list'
]
=
TRUE
;
}
foreach
(
$this
->
entityFieldInfo
[
'optional'
]
as
&
$definition
)
{
$definition
[
'list'
]
=
TRUE
;
}
cache
()
->
set
(
$cid
,
$this
->
entityFieldInfo
,
CacheBackendInterface
::
CACHE_PERMANENT
,
array
(
'entity_info'
=>
TRUE
));
}
}
$bundle
=
!
empty
(
$constraints
[
'Bundle'
])
?
$constraints
[
'Bundle'
]
:
FALSE
;
// Add in per-bundle fields.
if
(
!
isset
(
$this
->
fieldDefinitions
[
$bundle
]))
{
$this
->
fieldDefinitions
[
$bundle
]
=
$this
->
entityFieldInfo
[
'definitions'
];
if
(
$bundle
&&
isset
(
$this
->
entityFieldInfo
[
'bundle map'
][
$bundle
]))
{
$this
->
fieldDefinitions
[
$bundle
]
+=
array_intersect_key
(
$this
->
entityFieldInfo
[
'optional'
],
array_flip
(
$this
->
entityFieldInfo
[
'bundle map'
][
$bundle
]));
}
}
return
$this
->
fieldDefinitions
[
$bundle
];
}
/**
* Defines the base properties of the entity type.
*
* @todo: Define abstract once all entity types have been converted.
* {@inheritdoc}
*/
public
function
baseFieldDefinitions
()
{
// @todo: Define abstract once all entity types have been converted.
return
array
();
}
...
...
core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php
View file @
5f67fd1d
...
...
@@ -309,7 +309,7 @@ protected function attachPropertyData(array &$entities, $revision_id = FALSE) {
}
$data
=
$query
->
execute
();
$field_definition
=
$this
->
getFieldDefinitions
(
array
()
);
$field_definition
=
\
Drupal
::
entityManager
()
->
getFieldDefinitions
(
$this
->
entityType
);
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'
])));
}
...
...
core/lib/Drupal/Core/Entity/EntityManager.php
View file @
5f67fd1d
...
...
@@ -9,6 +9,9 @@
use
Drupal\Component\Plugin\PluginManagerBase
;
use
Drupal\Component\Plugin\Factory\DefaultFactory
;
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
;
...
...
@@ -47,6 +50,43 @@ class EntityManager extends PluginManagerBase {
*/
protected
$controllers
=
array
();
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected
$moduleHandler
;
/**
* The cache backend to use.
*
* @var \Drupal\Core\Cache\CacheBackendInterface
*/
protected
$cache
;
/**
* The language manager.
*
* @var \Drupal\Core\Language\LanguageManager
*/
protected
$languageManager
;
/**
* An array of field information per entity type, i.e. containing definitions.
*
* @var array
*
* @see hook_entity_field_info()
*/
protected
$entityFieldInfo
;
/**
* Static cache of field definitions per bundle and entity type.
*
* @var array
*/
protected
$fieldDefinitions
;
/**
* Constructs a new Entity plugin manager.
*
...
...
@@ -55,16 +95,27 @@ class EntityManager extends PluginManagerBase {
* keyed by the corresponding namespace to look for plugin implementations,
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
* The service container this object should use.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
* @param \Drupal\Core\Cache\CacheBackendInterface $cache
* The cache backend to use.
* @param \Drupal\Core\Language\LanguageManager $language_manager
* The language manager.
*/
public
function
__construct
(
\
Traversable
$namespaces
,
ContainerInterface
$container
)
{
public
function
__construct
(
\
Traversable
$namespaces
,
ContainerInterface
$container
,
ModuleHandlerInterface
$module_handler
,
CacheBackendInterface
$cache
,
LanguageManager
$language_manager
)
{
// Allow the plugin definition to be altered by hook_entity_info_alter().
$annotation_namespaces
=
array
(
'Drupal\Core\Entity\Annotation'
=>
DRUPAL_ROOT
.
'/core/lib'
,
);
$this
->
moduleHandler
=
$module_handler
;
$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:'
.
l
anguage
(
Language
::
TYPE_INTERFACE
)
->
langcode
,
'cache'
,
CacheBackendInterface
::
CACHE_PERMANENT
,
array
(
'entity_info'
=>
TRUE
));
$this
->
discovery
=
new
CacheDecorator
(
$this
->
discovery
,
'entity_info:'
.
$this
->
languageManager
->
getL
anguage
(
Language
::
TYPE_INTERFACE
)
->
langcode
,
'cache'
,
CacheBackendInterface
::
CACHE_PERMANENT
,
array
(
'entity_info'
=>
TRUE
));
$this
->
factory
=
new
DefaultFactory
(
$this
->
discovery
);
$this
->
container
=
$container
;
...
...
@@ -289,4 +340,118 @@ public function getAdminPath($entity_type, $bundle) {
return
$admin_path
;
}
/**
* Gets an array of entity field definitions.
*
* If a bundle is passed, fields specific to this bundle are included. Entity
* fields are always multi-valued, so 'list' is TRUE for each returned field
* definition.
*
* @param string $entity_type
* The entity type to get field definitions for.
* @param string $bundle
* (optional) The entity bundle for which to get field definitions. If NULL
* is passed, no bundle-specific fields are included. Defaults to NULL.
*
* @return array
* An array of field definitions of entity fields, keyed by field
* name. In addition to the typed data definition keys as described at
* \Drupal\Core\TypedData\TypedDataManager::create() the following keys are
* supported:
* - queryable: Whether the field is queryable via QueryInterface.
* Defaults to TRUE if 'computed' is FALSE or not set, to FALSE otherwise.
* - translatable: Whether the field is translatable. Defaults to FALSE.
* - configurable: A boolean indicating whether the field is configurable
* via field.module. Defaults to FALSE.
*
* @see \Drupal\Core\TypedData\TypedDataManager::create()
* @see \Drupal\Core\Entity\EntityManager::getFieldDefinitionsByConstraints()
*/
public
function
getFieldDefinitions
(
$entity_type
,
$bundle
=
NULL
)
{
if
(
!
isset
(
$this
->
entityFieldInfo
[
$entity_type
]))
{
// First, try to load from cache.
$cid
=
'entity_field_definitions:'
.
$entity_type
.
':'
.
$this
->
languageManager
->
getLanguage
(
Language
::
TYPE_INTERFACE
)
->
langcode
;
if
(
$cache
=
$this
->
cache
->
get
(
$cid
))
{
$this
->
entityFieldInfo
[
$entity_type
]
=
$cache
->
data
;
}
else
{
$this
->
entityFieldInfo
[
$entity_type
]
=
array
(
'definitions'
=>
$this
->
getStorageController
(
$entity_type
)
->
baseFieldDefinitions
(),
// Contains definitions of optional (per-bundle) fields.
'optional'
=>
array
(),
// An array keyed by bundle name containing the optional fields added
// by the bundle.
'bundle map'
=>
array
(),
);
// Invoke hooks.
$result
=
$this
->
moduleHandler
->
invokeAll
(
$entity_type
.
'_field_info'
);
$this
->
entityFieldInfo
[
$entity_type
]
=
NestedArray
::
mergeDeep
(
$this
->
entityFieldInfo
[
$entity_type
],
$result
);
$result
=
$this
->
moduleHandler
->
invokeAll
(
'entity_field_info'
,
array
(
$entity_type
));
$this
->
entityFieldInfo
[
$entity_type
]
=
NestedArray
::
mergeDeep
(
$this
->
entityFieldInfo
[
$entity_type
],
$result
);
$hooks
=
array
(
'entity_field_info'
,
$entity_type
.
'_field_info'
);
$this
->
moduleHandler
->
alter
(
$hooks
,
$this
->
entityFieldInfo
[
$entity_type
],
$entity_type
);
// Enforce fields to be multiple by default.
foreach
(
$this
->
entityFieldInfo
[
$entity_type
][
'definitions'
]
as
&
$definition
)
{
$definition
[
'list'
]
=
TRUE
;
}
foreach
(
$this
->
entityFieldInfo
[
$entity_type
][
'optional'
]
as
&
$definition
)
{
$definition
[
'list'
]
=
TRUE
;
}
$this
->
cache
->
set
(
$cid
,
$this
->
entityFieldInfo
[
$entity_type
],
CacheBackendInterface
::
CACHE_PERMANENT
,
array
(
'entity_info'
=>
TRUE
,
'entity_field_info'
=>
TRUE
));
}
}
if
(
!
$bundle
)
{
return
$this
->
entityFieldInfo
[
$entity_type
][
'definitions'
];
}
else
{
// Add in per-bundle fields.
if
(
!
isset
(
$this
->
fieldDefinitions
[
$entity_type
][
$bundle
]))
{
$this
->
fieldDefinitions
[
$entity_type
][
$bundle
]
=
$this
->
entityFieldInfo
[
$entity_type
][
'definitions'
];
if
(
isset
(
$this
->
entityFieldInfo
[
$entity_type
][
'bundle map'
][
$bundle
]))
{
$this
->
fieldDefinitions
[
$entity_type
][
$bundle
]
+=
array_intersect_key
(
$this
->
entityFieldInfo
[
$entity_type
][
'optional'
],
array_flip
(
$this
->
entityFieldInfo
[
$entity_type
][
'bundle map'
][
$bundle
]));
}
}
return
$this
->
fieldDefinitions
[
$entity_type
][
$bundle
];
}
}
/**
* Gets an array of entity field definitions based on validation constraints.
*
* @param string $entity_type
* The entity type to get field definitions for.
* @param array $constraints
* An array of entity constraints as used for entities in typed data
* definitions, i.e. an array optionally including a 'Bundle' key.
* For example the constraints used by an entity reference could be:
* @code
* array(
* 'Bundle' => 'article',
* )
* @endcode
*
* @return array
* An array of field definitions of entity fields, keyed by field
* name.
*
* @see \Drupal\Core\Entity\EntityManager::getFieldDefinitions()
*/
public
function
getFieldDefinitionsByConstraints
(
$entity_type
,
array
$constraints
)
{
// @todo: Add support for specifying multiple bundles.
return
$this
->
getFieldDefinitions
(
$entity_type
,
isset
(
$constraints
[
'Bundle'
])
?
$constraints
[
'Bundle'
]
:
NULL
);
}
/**
* Clears static and persistent field definition caches.
*/
public
function
clearCachedFieldDefinitions
()
{
unset
(
$this
->
entityFieldInfo
);
unset
(
$this
->
fieldDefinitions
);
$this
->
cache
->
deleteTags
(
array
(
'entity_field_info'
=>
TRUE
));
}
}
core/lib/Drupal/Core/Entity/EntityNG.php
View file @
5f67fd1d
...
...
@@ -281,10 +281,8 @@ public function getPropertyDefinition($name) {
*/
public
function
getPropertyDefinitions
()
{
if
(
!
isset
(
$this
->
fieldDefinitions
))
{
$this
->
fieldDefinitions
=
\
Drupal
::
entityManager
()
->
getStorageController
(
$this
->
entityType
)
->
getFieldDefinitions
(
array
(
'EntityType'
=>
$this
->
entityType
,
'Bundle'
=>
$this
->
bundle
,
));
$bundle
=
$this
->
bundle
!=
$this
->
entityType
?
$this
->
bundle
:
NULL
;
$this
->
fieldDefinitions
=
\
Drupal
::
entityManager
()
->
getFieldDefinitions
(
$this
->
entityType
,
$bundle
);
}
return
$this
->
fieldDefinitions
;
}
...
...
core/lib/Drupal/Core/Entity/EntityStorageControllerInterface.php
View file @
5f67fd1d
...
...
@@ -126,46 +126,16 @@ public function delete(array $entities);
public
function
save
(
EntityInterface
$entity
);
/**
* Gets an array of entity field definitions.
*
* If a 'bundle' key is present in the given entity definition, fields
* specific to this bundle are included.
* Entity fields are always multi-valued, so 'list' is TRUE for each
* returned field definition.
*
* @param array $constraints
* An array of entity constraints as used for entities in typed data
* definitions, i.e. an array having an 'entity type' and optionally a
* 'bundle' key. For example:
* @code
* array(
* 'EntityType' => 'node',
* 'Bundle' => 'article',
* )
* @endcode
* Defines the base fields of the entity type.
*
* @return array
* An array of field definitions of entity fields, keyed by field
* name. In addition to the typed data definition keys as described at
* \Drupal::typedData()->create() the follow keys are supported:
* - queryable: Whether the field is queryable via QueryInterface.
* Defaults to TRUE if 'computed' is FALSE or not set, to FALSE otherwise.
* - translatable: Whether the field is translatable. Defaults to FALSE.
* - configurable: A boolean indicating whether the field is configurable
* via field.module. Defaults to FALSE.
* - property_constraints: An array of constraint arrays applying to the
* field item properties, keyed by property name. E.g. the following
* validates the value property to have a maximum length of 128:
* @code
* array(
* 'value' => array('Length' => array('max' => 128)),
* )
* @endcode
*
* @see Drupal\Core\TypedData\TypedDataManager::create()
* @see \Drupal::typedData()
* An array of entity field definitions as specified by
* \Drupal\Core\Entity\EntityManager::getFieldDefinitions(), keyed by field
* name.
*
* @see \Drupal\Core\Entity\EntityManager::getFieldDefinitions()
*/
public
function
get
FieldDefinitions
(
array
$constraints
);
public
function
base
FieldDefinitions
();
/**
* Gets the name of the service for the query for this entity storage.
...
...
core/lib/Drupal/Core/Entity/Field/Type/EntityWrapper.php
View file @
5f67fd1d
...
...
@@ -178,7 +178,7 @@ public function getPropertyDefinition($name) {
*/
public
function
getPropertyDefinitions
()
{
// @todo: Support getting definitions if multiple bundles are specified.
return
\
Drupal
::
entityManager
()
->
get
Storage
Contr
oller
(
$this
->
entityType
)
->
getFieldDefinitions
(
$this
->
definition
[
'constraints'
]);
return
\
Drupal
::
entityManager
()
->
get
FieldDefinitionsBy
Con
s
tr
aints
(
$this
->
entityType
,
$this
->
definition
[
'constraints'
]);
}
/**
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment