Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
D
drupal
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Custom Issue Tracker
Custom Issue Tracker
Labels
Merge Requests
292
Merge Requests
292
Requirements
Requirements
List
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Analytics
Analytics
Code Review
Insights
Issue
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
project
drupal
Commits
1a5d1fc7
Commit
1a5d1fc7
authored
Apr 22, 2014
by
alexpott
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue
#2225955
by tim.plunkett, Berdir: Improve the DX of writing entity storage classes.
parent
5e4b8a11
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
591 additions
and
667 deletions
+591
-667
core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php
core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php
+35
-158
core/lib/Drupal/Core/Config/Entity/ConfigEntityType.php
core/lib/Drupal/Core/Config/Entity/ConfigEntityType.php
+5
-0
core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php
core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php
+152
-226
core/lib/Drupal/Core/Entity/ContentEntityNullStorage.php
core/lib/Drupal/Core/Entity/ContentEntityNullStorage.php
+24
-0
core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
+2
-20
core/lib/Drupal/Core/Entity/EntityDatabaseStorage.php
core/lib/Drupal/Core/Entity/EntityDatabaseStorage.php
+50
-180
core/lib/Drupal/Core/Entity/EntityStorageBase.php
core/lib/Drupal/Core/Entity/EntityStorageBase.php
+279
-30
core/modules/comment/lib/Drupal/comment/CommentStorage.php
core/modules/comment/lib/Drupal/comment/CommentStorage.php
+3
-3
core/modules/menu_link/lib/Drupal/menu_link/MenuLinkStorage.php
...odules/menu_link/lib/Drupal/menu_link/MenuLinkStorage.php
+4
-6
core/modules/user/lib/Drupal/user/UserStorage.php
core/modules/user/lib/Drupal/user/UserStorage.php
+12
-13
core/tests/Drupal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
...upal/Tests/Core/Config/Entity/ConfigEntityStorageTest.php
+25
-31
No files found.
core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php
View file @
1a5d1fc7
...
...
@@ -17,8 +17,6 @@
use
Drupal\Core\Config\StorageInterface
;
use
Drupal\Core\Config\Entity\Exception\ConfigEntityIdLengthException
;
use
Drupal\Core\Entity\EntityTypeInterface
;
use
Drupal\Core\Entity\EntityStorageException
;
use
Drupal\Core\Entity\Query\QueryFactory
;
use
Drupal\Component\Uuid\UuidInterface
;
use
Drupal\Core\Language\LanguageManagerInterface
;
use
Symfony\Component\DependencyInjection\ContainerInterface
;
...
...
@@ -56,11 +54,9 @@ class ConfigEntityStorage extends EntityStorageBase implements ConfigEntityStora
const
MAX_ID_LENGTH
=
166
;
/**
* The UUID service.
*
* @var \Drupal\Component\Uuid\UuidInterface
* {@inheritdoc}
*/
protected
$uuid
Service
;
protected
$uuid
Key
=
'uuid'
;
/**
* Name of the entity's status key or FALSE if a status is not supported.
...
...
@@ -107,7 +103,6 @@ class ConfigEntityStorage extends EntityStorageBase implements ConfigEntityStora
public
function
__construct
(
EntityTypeInterface
$entity_type
,
ConfigFactoryInterface
$config_factory
,
StorageInterface
$config_storage
,
UuidInterface
$uuid_service
,
LanguageManagerInterface
$language_manager
)
{
parent
::
__construct
(
$entity_type
);
$this
->
idKey
=
$this
->
entityType
->
getKey
(
'id'
);
$this
->
statusKey
=
$this
->
entityType
->
getKey
(
'status'
);
$this
->
configFactory
=
$config_factory
;
...
...
@@ -129,53 +124,6 @@ public static function createInstance(ContainerInterface $container, EntityTypeI
);
}
/**
* {@inheritdoc}
*/
public
function
loadMultiple
(
array
$ids
=
NULL
)
{
$entities
=
array
();
// Create a new variable which is either a prepared version of the $ids
// array for later comparison with the entity cache, or FALSE if no $ids
// were passed.
$passed_ids
=
!
empty
(
$ids
)
?
array_flip
(
$ids
)
:
FALSE
;
// Load any remaining entities. This is the case if $ids is set to NULL (so
// we load all entities).
if
(
$ids
===
NULL
||
$ids
)
{
$queried_entities
=
$this
->
buildQuery
(
$ids
);
}
// Pass all entities loaded from the database through $this->postLoad(),
// which calls the
// entity type specific load callback, for example hook_node_type_load().
if
(
!
empty
(
$queried_entities
))
{
$this
->
postLoad
(
$queried_entities
);
$entities
+=
$queried_entities
;
}
// Ensure that the returned array is ordered the same as the original
// $ids array if this was passed in and remove any invalid ids.
if
(
$passed_ids
)
{
// Remove any invalid ids from the array.
$passed_ids
=
array_intersect_key
(
$passed_ids
,
$entities
);
foreach
(
$entities
as
$entity
)
{
$passed_ids
[
$entity
->
id
()]
=
$entity
;
}
$entities
=
$passed_ids
;
}
return
$entities
;
}
/**
* {@inheritdoc}
*/
public
function
load
(
$id
)
{
$entities
=
$this
->
loadMultiple
(
array
(
$id
));
return
isset
(
$entities
[
$id
])
?
$entities
[
$id
]
:
NULL
;
}
/**
* Implements Drupal\Core\Entity\EntityStorageInterface::loadRevision().
*/
...
...
@@ -205,28 +153,9 @@ public static function getIDFromConfigName($config_name, $config_prefix) {
}
/**
* Builds the query to load the entity.
*
* This has full revision support. For entities requiring special queries,
* the class can be extended, and the default query can be constructed by
* calling parent::buildQuery(). This is usually necessary when the object
* being loaded needs to be augmented with additional data from another
* table, such as loading node type into comments or vocabulary machine name
* into terms, however it can also support $conditions on different tables.
* See Drupal\comment\CommentStorage::buildQuery() or
* Drupal\taxonomy\TermStorage::buildQuery() for examples.
*
* @param $ids
* An array of entity IDs, or NULL to load all entities.
* @param $revision_id
* The ID of the revision to load, or FALSE if this query is asking for the
* most current revision(s).
*
* @return SelectQuery
* A SelectQuery object for loading the entity.
* {@inheritdoc}
*/
protected
function
buildQuery
(
$ids
,
$revision_id
=
FALSE
)
{
$config_class
=
$this
->
entityType
->
getClass
();
protected
function
doLoadMultiple
(
array
$ids
=
NULL
)
{
$prefix
=
$this
->
getConfigPrefix
();
// Get the names of the configuration entities we are going to load.
...
...
@@ -242,70 +171,36 @@ protected function buildQuery($ids, $revision_id = FALSE) {
}
// Load all of the configuration entities.
$re
sult
=
array
();
$re
cords
=
array
();
foreach
(
$this
->
configFactory
->
loadMultiple
(
$names
)
as
$config
)
{
$re
sult
[
$config
->
get
(
$this
->
idKey
)]
=
new
$config_class
(
$config
->
get
(),
$this
->
entityTypeId
);
$re
cords
[
$config
->
get
(
$this
->
idKey
)]
=
$config
->
get
(
);
}
return
$
result
;
return
$
this
->
mapFromStorageRecords
(
$records
)
;
}
/**
*
Implements Drupal\Core\Entity\EntityStorageInterface::create().
*
{@inheritdoc}
*/
public
function
create
(
array
$values
=
array
())
{
$class
=
$this
->
entityType
->
getClass
();
$class
::
preCreate
(
$this
,
$values
);
protected
function
doCreate
(
array
$values
)
{
// Set default language to site default if not provided.
$values
+=
array
(
'langcode'
=>
$this
->
languageManager
->
getDefaultLanguage
()
->
id
);
$entity
=
new
$class
(
$values
,
$this
->
entityTypeId
);
// Mark this entity as new, so isNew() returns TRUE. This does not check
// whether a configuration entity with the same ID (if any) already exists.
$entity
->
enforceIsNew
();
// Assign a new UUID if there is none yet.
if
(
!
$entity
->
uuid
())
{
$entity
->
set
(
'uuid'
,
$this
->
uuidService
->
generate
());
}
$entity
->
postCreate
(
$this
);
// Modules might need to add or change the data initially held by the new
// entity object, for instance to fill-in default values.
$this
->
invokeHook
(
'create'
,
$entity
);
$entity
=
new
$this
->
entityClass
(
$values
,
$this
->
entityTypeId
);
// Default status to enabled.
if
(
!
empty
(
$this
->
statusKey
)
&&
!
isset
(
$entity
->
{
$this
->
statusKey
}))
{
$entity
->
{
$this
->
statusKey
}
=
TRUE
;
}
return
$entity
;
}
/**
*
Implements Drupal\Core\Entity\EntityStorageInterface::delete().
*
{@inheritdoc}
*/
public
function
delete
(
array
$entities
)
{
if
(
!
$entities
)
{
// If no IDs or invalid IDs were passed, do nothing.
return
;
}
$entity_class
=
$this
->
entityType
->
getClass
();
$entity_class
::
preDelete
(
$this
,
$entities
);
foreach
(
$entities
as
$entity
)
{
$this
->
invokeHook
(
'predelete'
,
$entity
);
}
protected
function
doDelete
(
$entities
)
{
foreach
(
$entities
as
$entity
)
{
$config
=
$this
->
configFactory
->
get
(
$this
->
getConfigPrefix
()
.
$entity
->
id
());
$config
->
delete
();
}
$entity_class
::
postDelete
(
$this
,
$entities
);
foreach
(
$entities
as
$entity
)
{
$this
->
invokeHook
(
'delete'
,
$entity
);
}
}
/**
...
...
@@ -315,32 +210,16 @@ public function delete(array $entities) {
* When attempting to save a configuration entity that has no ID.
*/
public
function
save
(
EntityInterface
$entity
)
{
$prefix
=
$this
->
getConfigPrefix
();
// Configuration entity IDs are strings, and '0' is a valid ID.
$id
=
$entity
->
id
();
if
(
$id
===
NULL
||
$id
===
''
)
{
throw
new
EntityMalformedException
(
'The entity does not have an ID.'
);
}
// Load the stored entity, if any.
// At this point, the original ID can only be NULL or a valid ID.
if
(
$entity
->
getOriginalId
()
!==
NULL
)
{
$id
=
$entity
->
getOriginalId
();
}
$config
=
$this
->
configFactory
->
get
(
$prefix
.
$id
);
// Prevent overwriting an existing configuration file if the entity is new.
if
(
$entity
->
isNew
()
&&
!
$config
->
isNew
())
{
throw
new
EntityStorageException
(
String
::
format
(
'@type entity with ID @id already exists.'
,
array
(
'@type'
=>
$this
->
entityTypeId
,
'@id'
=>
$id
)));
}
if
(
!
$config
->
isNew
()
&&
!
isset
(
$entity
->
original
))
{
$entity
->
original
=
$this
->
loadUnchanged
(
$id
);
}
// Check the configuration entity ID length.
// @see \Drupal\Core\Config\Entity\ConfigEntityStorage::MAX_ID_LENGTH
// @todo Consider moving this to a protected method on the parent class, and
// abstracting it for all entity types.
if
(
strlen
(
$entity
->
{
$this
->
idKey
})
>
self
::
MAX_ID_LENGTH
)
{
throw
new
ConfigEntityIdLengthException
(
String
::
format
(
'Configuration entity ID @id exceeds maximum allowed length of @length characters.'
,
array
(
'@id'
=>
$entity
->
{
$this
->
idKey
},
...
...
@@ -348,9 +227,15 @@ public function save(EntityInterface $entity) {
)));
}
$entity
->
preSave
(
$this
);
$this
->
invokeHook
(
'presave'
,
$entity
);
return
parent
::
save
(
$entity
);
}
/**
* {@inheritdoc}
*/
protected
function
doSave
(
$id
,
EntityInterface
$entity
)
{
$is_new
=
$entity
->
isNew
();
$prefix
=
$this
->
getConfigPrefix
();
if
(
$id
!==
$entity
->
id
())
{
// Renaming a config object needs to cater for:
// - Storage needs to access the original object.
...
...
@@ -358,34 +243,26 @@ public function save(EntityInterface $entity) {
// - All instances of the object need to be renamed.
$config
=
$this
->
configFactory
->
rename
(
$prefix
.
$id
,
$prefix
.
$entity
->
id
());
}
else
{
$config
=
$this
->
configFactory
->
get
(
$prefix
.
$id
);
}
// Retrieve the desired properties and set them in config.
foreach
(
$entity
->
toArray
()
as
$key
=>
$value
)
{
$config
->
set
(
$key
,
$value
);
}
$config
->
save
();
if
(
!
$config
->
isNew
())
{
$return
=
SAVED_UPDATED
;
$config
->
save
();
$entity
->
postSave
(
$this
,
TRUE
);
$this
->
invokeHook
(
'update'
,
$entity
);
}
else
{
$return
=
SAVED_NEW
;
$config
->
save
();
$entity
->
enforceIsNew
(
FALSE
);
$entity
->
postSave
(
$this
,
FALSE
);
$this
->
invokeHook
(
'insert'
,
$entity
);
}
// After saving, this is now the "original entity", and subsequent saves
// will be updates instead of inserts, and updates must always be able to
// correctly identify the original entity.
$entity
->
setOriginalId
(
$entity
->
id
());
unset
(
$entity
->
original
);
return
$is_new
?
SAVED_NEW
:
SAVED_UPDATED
;
}
return
$return
;
/**
* {@inheritdoc}
*/
protected
function
has
(
$id
,
EntityInterface
$entity
)
{
$prefix
=
$this
->
getConfigPrefix
();
$config
=
$this
->
configFactory
->
get
(
$prefix
.
$id
);
return
!
$config
->
isNew
();
}
/**
...
...
core/lib/Drupal/Core/Config/Entity/ConfigEntityType.php
View file @
1a5d1fc7
...
...
@@ -55,6 +55,11 @@ class ConfigEntityType extends EntityType {
*/
protected
$config_prefix
;
/**
* {@inheritdoc}
*/
protected
$static_cache
=
FALSE
;
/**
* {@inheritdoc}
*/
...
...
core/lib/Drupal/Core/Entity/ContentEntityDatabaseStorage.php
View file @
1a5d1fc7
...
...
@@ -58,13 +58,6 @@ class ContentEntityDatabaseStorage extends ContentEntityStorageBase {
*/
protected
$revisionDataTable
;
/**
* Whether this entity type should use the static cache.
*
* @var boolean
*/
protected
$cache
;
/**
* Active database connection.
*
...
...
@@ -106,11 +99,6 @@ public function __construct(EntityTypeInterface $entity_type, Connection $databa
$this
->
database
=
$database
;
$this
->
fieldInfo
=
$field_info
;
// Check if the entity type supports IDs.
if
(
$this
->
entityType
->
hasKey
(
'id'
))
{
$this
->
idKey
=
$this
->
entityType
->
getKey
(
'id'
);
}
// Check if the entity type supports UUIDs.
$this
->
uuidKey
=
$this
->
entityType
->
getKey
(
'uuid'
);
...
...
@@ -134,74 +122,27 @@ public function __construct(EntityTypeInterface $entity_type, Connection $databa
/**
* {@inheritdoc}
*/
public
function
loadMultiple
(
array
$ids
=
NULL
)
{
$entities
=
array
();
// Create a new variable which is either a prepared version of the $ids
// array for later comparison with the entity cache, or FALSE if no $ids
// were passed. The $ids array is reduced as items are loaded from cache,
// and we need to know if it's empty for this reason to avoid querying the
// database when all requested entities are loaded from cache.
$passed_ids
=
!
empty
(
$ids
)
?
array_flip
(
$ids
)
:
FALSE
;
// Try to load entities from the static cache, if the entity type supports
// static caching.
if
(
$this
->
cache
&&
$ids
)
{
$entities
+=
$this
->
cacheGet
(
$ids
);
// If any entities were loaded, remove them from the ids still to load.
if
(
$passed_ids
)
{
$ids
=
array_keys
(
array_diff_key
(
$passed_ids
,
$entities
));
}
}
// Load any remaining entities from the database. This is the case if $ids
// is set to NULL (so we load all entities) or if there are any ids left to
// load.
if
(
$ids
===
NULL
||
$ids
)
{
// Build and execute the query.
$query_result
=
$this
->
buildQuery
(
$ids
)
->
execute
();
$queried_entities
=
$query_result
->
fetchAllAssoc
(
$this
->
idKey
);
}
// Pass all entities loaded from the database through $this->postLoad(),
// which attaches fields (if supported by the entity type) and calls the
// entity type specific load callback, for example hook_node_load().
if
(
!
empty
(
$queried_entities
))
{
$this
->
postLoad
(
$queried_entities
);
$entities
+=
$queried_entities
;
}
if
(
$this
->
cache
)
{
// Add entities to the cache.
if
(
!
empty
(
$queried_entities
))
{
$this
->
cacheSet
(
$queried_entities
);
}
}
// Ensure that the returned array is ordered the same as the original
// $ids array if this was passed in and remove any invalid ids.
if
(
$passed_ids
)
{
// Remove any invalid ids from the array.
$passed_ids
=
array_intersect_key
(
$passed_ids
,
$entities
);
foreach
(
$entities
as
$entity
)
{
$passed_ids
[
$entity
->
id
()]
=
$entity
;
}
$entities
=
$passed_ids
;
}
return
$entities
;
}
protected
function
doLoadMultiple
(
array
$ids
=
NULL
)
{
// Build and execute the query.
$records
=
$this
->
buildQuery
(
$ids
)
->
execute
()
->
fetchAllAssoc
(
$this
->
idKey
);
/**
* {@inheritdoc}
*/
public
function
load
(
$id
)
{
$entities
=
$this
->
loadMultiple
(
array
(
$id
));
return
isset
(
$entities
[
$id
])
?
$entities
[
$id
]
:
NULL
;
return
$this
->
mapFromStorageRecords
(
$records
);
}
/**
* Maps from storage records to entity objects.
*
* This will attach fields, if the entity is fieldable. It calls
* hook_entity_load() for modules which need to add data to all entities.
* It also calls hook_TYPE_load() on the loaded entities. For example
* hook_node_load() or hook_user_load(). If your hook_TYPE_load()
* expects special parameters apart from the queried entities, you can set
* $this->hookLoadArguments prior to calling the method.
* See Drupal\node\NodeStorage::attachLoad() for an example.
*
* @param array $records
* Associative array of query results, keyed on the entity ID.
*
...
...
@@ -209,6 +150,10 @@ public function load($id) {
* An array of entity objects implementing the EntityInterface.
*/
protected
function
mapFromStorageRecords
(
array
$records
)
{
if
(
!
$records
)
{
return
array
();
}
$entities
=
array
();
foreach
(
$records
as
$id
=>
$record
)
{
$entities
[
$id
]
=
array
();
...
...
@@ -237,6 +182,12 @@ protected function mapFromStorageRecords(array $records) {
}
}
$this
->
attachPropertyData
(
$entities
);
// Attach field values.
if
(
$this
->
entityType
->
isFieldable
())
{
$this
->
loadFieldItems
(
$entities
);
}
return
$entities
;
}
...
...
@@ -319,15 +270,14 @@ protected function attachPropertyData(array &$entities) {
public
function
loadRevision
(
$revision_id
)
{
// Build and execute the query.
$query_result
=
$this
->
buildQuery
(
array
(),
$revision_id
)
->
execute
();
$
queried_entitie
s
=
$query_result
->
fetchAllAssoc
(
$this
->
idKey
);
$
record
s
=
$query_result
->
fetchAllAssoc
(
$this
->
idKey
);
// Pass the loaded entities from the database through $this->postLoad(),
// which attaches fields (if supported by the entity type) and calls the
// entity type specific load callback, for example hook_node_load().
if
(
!
empty
(
$queried_entities
))
{
$this
->
postLoad
(
$queried_
entities
);
if
(
!
empty
(
$records
))
{
// Convert the raw records to entity objects.
$entities
=
$this
->
mapFromStorageRecords
(
$records
);
$this
->
postLoad
(
$entities
);
return
reset
(
$
entities
);
}
return
reset
(
$queried_entities
);
}
/**
...
...
@@ -388,7 +338,7 @@ protected function buildPropertyQuery(QueryInterface $entity_query, array $value
* The ID of the revision to load, or FALSE if this query is asking for the
* most current revision(s).
*
* @return
SelectQuery
* @return
\Drupal\Core\Database\Query\Select
* A SelectQuery object for loading the entity.
*/
protected
function
buildQuery
(
$ids
,
$revision_id
=
FALSE
)
{
...
...
@@ -437,32 +387,6 @@ protected function buildQuery($ids, $revision_id = FALSE) {
return
$query
;
}
/**
* Attaches data to entities upon loading.
*
* This will attach fields, if the entity is fieldable. It calls
* hook_entity_load() for modules which need to add data to all entities.
* It also calls hook_TYPE_load() on the loaded entities. For example
* hook_node_load() or hook_user_load(). If your hook_TYPE_load()
* expects special parameters apart from the queried entities, you can set
* $this->hookLoadArguments prior to calling the method.
* See Drupal\node\NodeStorage::attachLoad() for an example.
*
* @param $queried_entities
* Associative array of query results, keyed on the entity ID.
*/
protected
function
postLoad
(
array
&
$queried_entities
)
{
// Map the loaded records into entity objects and according fields.
$queried_entities
=
$this
->
mapFromStorageRecords
(
$queried_entities
);
// Attach field values.
if
(
$this
->
entityType
->
isFieldable
())
{
$this
->
loadFieldItems
(
$queried_entities
);
}
parent
::
postLoad
(
$queried_entities
);
}
/**
* Implements \Drupal\Core\Entity\EntityStorageInterface::delete().
*/
...
...
@@ -474,48 +398,8 @@ public function delete(array $entities) {
$transaction
=
$this
->
database
->
startTransaction
();
try
{
$entity_class
=
$this
->
entityClass
;
$entity_class
::
preDelete
(
$this
,
$entities
);
foreach
(
$entities
as
$entity
)
{
$this
->
invokeHook
(
'predelete'
,
$entity
);
}
$ids
=
array_keys
(
$entities
);
$this
->
database
->
delete
(
$this
->
entityType
->
getBaseTable
())
->
condition
(
$this
->
idKey
,
$ids
)
->
execute
();
parent
::
delete
(
$entities
);
if
(
$this
->
revisionTable
)
{
$this
->
database
->
delete
(
$this
->
revisionTable
)
->
condition
(
$this
->
idKey
,
$ids
)
->
execute
();
}
if
(
$this
->
dataTable
)
{
$this
->
database
->
delete
(
$this
->
dataTable
)
->
condition
(
$this
->
idKey
,
$ids
)
->
execute
();
}
if
(
$this
->
revisionDataTable
)
{
$this
->
database
->
delete
(
$this
->
revisionDataTable
)
->
condition
(
$this
->
idKey
,
$ids
)
->
execute
();
}
foreach
(
$entities
as
$entity
)
{
$this
->
invokeFieldMethod
(
'delete'
,
$entity
);
$this
->
deleteFieldItems
(
$entity
);
}
// Reset the cache as soon as the changes have been applied.
$this
->
resetCache
(
$ids
);
$entity_class
::
postDelete
(
$this
,
$entities
);
foreach
(
$entities
as
$entity
)
{
$this
->
invokeHook
(
'delete'
,
$entity
);
}
// Ignore slave server temporarily.
db_ignore_slave
();
}
...
...
@@ -529,92 +413,53 @@ public function delete(array $entities) {
/**
* {@inheritdoc}
*/
public
function
save
(
EntityInterface
$entity
)
{
$transaction
=
$this
->
database
->
startTransaction
();
try
{
// Sync the changes made in the fields array to the internal values array.
$entity
->
updateOriginalValues
();
protected
function
doDelete
(
$entities
)
{
$ids
=
array_keys
(
$entities
);
// Load the stored entity, if any.
if
(
!
$entity
->
isNew
()
&&
!
isset
(
$entity
->
original
))
{
$id
=
$entity
->
id
();
if
(
$entity
->
getOriginalId
()
!==
NULL
)
{
$id
=
$entity
->
getOriginalId
();
}
$entity
->
original
=
$this
->
loadUnchanged
(
$id
);
}
$this
->
database
->
delete
(
$this
->
entityType
->
getBaseTable
())
->
condition
(
$this
->
idKey
,
$ids
)
->
execute
();
$entity
->
preSave
(
$this
);
$this
->
invokeFieldMethod
(
'preSave'
,
$entity
);
$this
->
invokeHook
(
'presave'
,
$entity
);
if
(
$this
->
revisionTable
)
{
$this
->
database
->
delete
(
$this
->
revisionTable
)
->
condition
(
$this
->
idKey
,
$ids
)
->
execute
();
}
// Create the storage record to be saved.
$record
=
$this
->
mapToStorageRecord
(
$entity
);
if
(
$this
->
dataTable
)
{
$this
->
database
->
delete
(
$this
->
dataTable
)
->
condition
(
$this
->
idKey
,
$ids
)
->
execute
();
}
if
(
!
$entity
->
isNew
())
{
if
(
$entity
->
isDefaultRevision
())
{