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
3a7bfeac
Commit
3a7bfeac
authored
Sep 16, 2013
by
catch
Browse files
Issue
#1983554
by plach, effulgentsia, Berdir: Remove BC-mode from EntityNG .
parent
2de01f4f
Changes
32
Hide whitespace changes
Inline
Side-by-side
core/lib/Drupal/Core/Entity/DatabaseStorageController.php
View file @
3a7bfeac
...
...
@@ -9,6 +9,7 @@
use
Drupal\Core\Database\Connection
;
use
Drupal\Core\Entity\Query\QueryInterface
;
use
Drupal\Core\Language\Language
;
use
Drupal\Component\Utility\NestedArray
;
use
Drupal\Component\Uuid\Uuid
;
use
Drupal\field\FieldInfo
;
...
...
@@ -569,15 +570,20 @@ protected function doLoadFieldItems($entities, $age) {
}
// Load field data.
$all_langcodes
=
array_keys
(
language_list
());
foreach
(
$fields
as
$field_name
=>
$field
)
{
$table
=
$load_current
?
static
::
_fieldTableName
(
$field
)
:
static
::
_fieldRevisionTableName
(
$field
);
// If the field is translatable ensure that only values having valid
// languages are retrieved. Since we are loading values for multiple
// entities, we cannot limit the query to the available translations.
$langcodes
=
$field
[
'translatable'
]
?
$all_langcodes
:
array
(
Language
::
LANGCODE_NOT_SPECIFIED
);
$results
=
$this
->
database
->
select
(
$table
,
't'
)
->
fields
(
't'
)
->
condition
(
$load_current
?
'entity_id'
:
'revision_id'
,
$ids
,
'IN'
)
->
condition
(
'langcode'
,
field_available_languages
(
$this
->
entityType
,
$field
),
'IN'
)
->
orderBy
(
'delta'
)
->
condition
(
'deleted'
,
0
)
->
condition
(
'langcode'
,
$langcodes
,
'IN'
)
->
orderBy
(
'delta'
)
->
execute
();
$delta_count
=
array
();
...
...
@@ -597,7 +603,7 @@ protected function doLoadFieldItems($entities, $age) {
}
// Add the item to the field values for the entity.
$entities
[
$row
->
entity_id
]
->
{
$field_name
}
[
$row
->
langcode
]
[
]
=
$item
;
$entities
[
$row
->
entity_id
]
->
getTranslation
(
$row
->
langcode
)
->
{
$field_name
}[
$delta_count
[
$row
->
entity_id
]
[
$row
->
langcode
]]
=
$item
;
$delta_count
[
$row
->
entity_id
][
$row
->
langcode
]
++
;
}
}
...
...
@@ -621,29 +627,19 @@ protected function doSaveFieldItems(EntityInterface $entity, $update) {
$table_name
=
static
::
_fieldTableName
(
$field
);
$revision_name
=
static
::
_fieldRevisionTableName
(
$field
);
$all_langcodes
=
field_available_languages
(
$entity_type
,
$field
);
$field_langcodes
=
array_intersect
(
$all_langcodes
,
array_keys
((
array
)
$entity
->
$field_name
));
// Delete and insert, rather than update, in case a value was added.
if
(
$update
)
{
// Delete language codes present in the incoming $entity->$field_name.
// Delete all language codes if $entity->$field_name is empty.
$langcodes
=
!
empty
(
$entity
->
$field_name
)
?
$field_langcodes
:
$all_langcodes
;
if
(
$langcodes
)
{
// Only overwrite the field's base table if saving the default revision
// of an entity.
if
(
$entity
->
isDefaultRevision
())
{
$this
->
database
->
delete
(
$table_name
)
->
condition
(
'entity_id'
,
$id
)
->
condition
(
'langcode'
,
$langcodes
,
'IN'
)
->
execute
();
}
$this
->
database
->
delete
(
$revision_name
)
// Only overwrite the field's base table if saving the default revision
// of an entity.
if
(
$entity
->
isDefaultRevision
())
{
$this
->
database
->
delete
(
$table_name
)
->
condition
(
'entity_id'
,
$id
)
->
condition
(
'revision_id'
,
$vid
)
->
condition
(
'langcode'
,
$langcodes
,
'IN'
)
->
execute
();
}
$this
->
database
->
delete
(
$revision_name
)
->
condition
(
'entity_id'
,
$id
)
->
condition
(
'revision_id'
,
$vid
)
->
execute
();
}
// Prepare the multi-insert query.
...
...
@@ -655,8 +651,12 @@ protected function doSaveFieldItems(EntityInterface $entity, $update) {
$query
=
$this
->
database
->
insert
(
$table_name
)
->
fields
(
$columns
);
$revision_query
=
$this
->
database
->
insert
(
$revision_name
)
->
fields
(
$columns
);
foreach
(
$field_langcodes
as
$langcode
)
{
$items
=
(
array
)
$entity
->
{
$field_name
}[
$langcode
];
$langcodes
=
$field
[
'translatable'
]
?
array_keys
(
$entity
->
getTranslationLanguages
())
:
array
(
Language
::
LANGCODE_NOT_SPECIFIED
);
foreach
(
$langcodes
as
$langcode
)
{
$items
=
$entity
->
getTranslation
(
$langcode
)
->
{
$field_name
}
->
getValue
();
if
(
!
isset
(
$items
))
{
continue
;
}
$delta_count
=
0
;
foreach
(
$items
as
$delta
=>
$item
)
{
// We now know we have someting to insert.
...
...
core/lib/Drupal/Core/Entity/DatabaseStorageControllerNG.php
View file @
3a7bfeac
...
...
@@ -330,9 +330,6 @@ protected function attachPropertyData(array &$entities, $revision_id = FALSE) {
public
function
save
(
EntityInterface
$entity
)
{
$transaction
=
$this
->
database
->
startTransaction
();
try
{
// Ensure we are dealing with the actual entity.
$entity
=
$entity
->
getNGEntity
();
// Sync the changes made in the fields array to the internal values array.
$entity
->
updateOriginalValues
();
...
...
@@ -572,11 +569,6 @@ public function delete(array $entities) {
$entity_class
=
$this
->
entityClass
;
$entity_class
::
preDelete
(
$this
,
$entities
);
// Ensure we are dealing with the actual entities.
foreach
(
$entities
as
$id
=>
$entity
)
{
$entities
[
$id
]
=
$entity
->
getNGEntity
();
}
foreach
(
$entities
as
$entity
)
{
$this
->
invokeHook
(
'predelete'
,
$entity
);
}
...
...
core/lib/Drupal/Core/Entity/Entity.php
View file @
3a7bfeac
...
...
@@ -412,20 +412,6 @@ public function getExportProperties() {
return
array
();
}
/**
* Implements \Drupal\Core\Entity\EntityInterface::getBCEntity().
*/
public
function
getBCEntity
()
{
return
$this
;
}
/**
* Implements \Drupal\Core\Entity\EntityInterface::getNGEntity().
*/
public
function
getNGEntity
()
{
return
$this
;
}
/**
* {@inheritdoc}
*/
...
...
core/lib/Drupal/Core/Entity/EntityBCDecorator.php
deleted
100644 → 0
View file @
2de01f4f
<?php
/**
* @file
* Contains \Drupal\Core\Entity\EntityBCDecorator.
*/
namespace
Drupal\Core\Entity
;
use
Drupal\Core\Language\Language
;
use
Drupal\Core\Entity\EntityInterface
;
use
Drupal\Core\TypedData\TypedDataInterface
;
use
Drupal\Core\Session\AccountInterface
;
/**
* Provides backwards compatible (BC) access to entity fields.
*
* Allows using entities converted to the new Entity Field API with the previous
* way of accessing fields or properties. For example, via the backwards
* compatible (BC) decorator you can do:
* @code
* $node->title = $value;
* $node->body[LANGUAGE_NONE][0]['value'] = $value;
* @endcode
* Without the BC decorator the same assignment would have to look like this:
* @code
* $node->title->value = $value;
* $node->body->value = $value;
* @endcode
* Without the BC decorator the language always default to the entity language,
* whereas a specific translation can be access via the getTranslation() method.
*
* The BC decorator should be only used during conversion to the new entity
* field API, such that existing code can be converted iteratively. Any new code
* should directly use the new entity field API and avoid using the
* EntityBCDecorator, if possible.
*
* @todo: Remove once everything is converted to use the new entity field API.
*/
class
EntityBCDecorator
implements
\
IteratorAggregate
,
EntityInterface
{
/**
* The EntityInterface object being decorated.
*
* @var \Drupal\Core\Entity\EntityInterface
*/
protected
$decorated
;
/**
* Local cache for field definitions.
*
* @var array
*/
protected
$definitions
;
/**
* Constructs a Drupal\Core\Entity\EntityCompatibilityDecorator object.
*
* @param \Drupal\Core\Entity\EntityInterface $decorated
* The decorated entity.
* @param array &$definitions
* An array of field definitions.
*/
function
__construct
(
EntityNG
$decorated
,
array
&
$definitions
)
{
$this
->
decorated
=
$decorated
;
$this
->
definitions
=
&
$definitions
;
}
/**
* Overrides Entity::getNGEntity().
*/
public
function
getNGEntity
()
{
return
$this
->
decorated
;
}
/**
* Overrides Entity::getBCEntity().
*/
public
function
getBCEntity
()
{
return
$this
;
}
/**
* Implements the magic method for getting object properties.
*
* Directly accesses the plain field values, as done in Drupal 7.
*/
public
function
&
__get
(
$name
)
{
// Directly return the original property.
if
(
$name
==
'original'
)
{
return
$this
->
decorated
->
values
[
$name
];
}
// We access the protected 'values' and 'fields' properties of the decorated
// entity via the magic getter - which returns them by reference for us. We
// do so, as providing references to these arrays would make $entity->values
// and $entity->fields reference themselves, which is problematic during
// __clone() (this is something we cannot work-a-round easily as an unset()
// on the variable is problematic in conjunction with the magic
// getter/setter).
if
(
!
empty
(
$this
->
decorated
->
fields
[
$name
]))
{
// Any field value set via the new Entity Field API will be stored inside
// the field objects managed by the entity, thus we need to ensure
// $this->decorated->values reflects the latest values first.
foreach
(
$this
->
decorated
->
fields
[
$name
]
as
$langcode
=>
$field
)
{
// Only set if it's not empty, otherwise there can be ghost values.
if
(
!
$field
->
isEmpty
())
{
$this
->
decorated
->
values
[
$name
][
$langcode
]
=
$field
->
getValue
(
TRUE
);
}
}
// The returned values might be changed by reference, so we need to remove
// the field object to avoid the field object and the value getting out of
// sync. That way, the next field object instantiated by EntityNG will
// receive the possibly updated value.
unset
(
$this
->
decorated
->
fields
[
$name
]);
}
// When accessing values for entity properties that have been converted to
// an entity field, provide direct access to the plain value. This makes it
// possible to use the BC-decorator with properties; e.g., $node->title.
if
(
isset
(
$this
->
definitions
[
$name
])
&&
empty
(
$this
->
definitions
[
$name
][
'configurable'
]))
{
if
(
!
isset
(
$this
->
decorated
->
values
[
$name
][
Language
::
LANGCODE_DEFAULT
]))
{
$this
->
decorated
->
values
[
$name
][
Language
::
LANGCODE_DEFAULT
][
0
][
'value'
]
=
NULL
;
}
if
(
is_array
(
$this
->
decorated
->
values
[
$name
][
Language
::
LANGCODE_DEFAULT
]))
{
// We need to ensure the key doesn't matter. Mostly it's 'value' but
// e.g. EntityReferenceItem uses target_id - so just take the first one.
if
(
isset
(
$this
->
decorated
->
values
[
$name
][
Language
::
LANGCODE_DEFAULT
][
0
])
&&
is_array
(
$this
->
decorated
->
values
[
$name
][
Language
::
LANGCODE_DEFAULT
][
0
]))
{
return
$this
->
decorated
->
values
[
$name
][
Language
::
LANGCODE_DEFAULT
][
0
][
current
(
array_keys
(
$this
->
decorated
->
values
[
$name
][
Language
::
LANGCODE_DEFAULT
][
0
]))];
}
}
return
$this
->
decorated
->
values
[
$name
][
Language
::
LANGCODE_DEFAULT
];
}
else
{
// Allow accessing field values in an entity default language other than
// Language::LANGCODE_DEFAULT by mapping the values to
// Language::LANGCODE_DEFAULT. This is necessary as EntityNG always keys
// default language values with Language::LANGCODE_DEFAULT while field API
// expects them to be keyed by langcode.
$langcode
=
$this
->
decorated
->
getUntranslated
()
->
language
()
->
id
;
if
(
$langcode
!=
Language
::
LANGCODE_DEFAULT
&&
isset
(
$this
->
decorated
->
values
[
$name
])
&&
is_array
(
$this
->
decorated
->
values
[
$name
]))
{
if
(
isset
(
$this
->
decorated
->
values
[
$name
][
Language
::
LANGCODE_DEFAULT
])
&&
!
isset
(
$this
->
decorated
->
values
[
$name
][
$langcode
]))
{
$this
->
decorated
->
values
[
$name
][
$langcode
]
=
&
$this
->
decorated
->
values
[
$name
][
Language
::
LANGCODE_DEFAULT
];
}
}
if
(
!
isset
(
$this
->
decorated
->
values
[
$name
]))
{
$this
->
decorated
->
values
[
$name
]
=
NULL
;
}
return
$this
->
decorated
->
values
[
$name
];
}
}
/**
* Implements the magic method for setting object properties.
*
* Directly writes to the plain field values, as done by Drupal 7.
*/
public
function
__set
(
$name
,
$value
)
{
$defined
=
isset
(
$this
->
definitions
[
$name
]);
// When updating values for entity properties that have been converted to
// an entity field, directly write to the plain value. This makes it
// possible to use the BC-decorator with properties; e.g., $node->title.
if
(
$defined
&&
empty
(
$this
->
definitions
[
$name
][
'configurable'
]))
{
$this
->
decorated
->
values
[
$name
][
Language
::
LANGCODE_DEFAULT
]
=
$value
;
}
else
{
if
(
$defined
&&
is_array
(
$value
))
{
// If field API sets a value with a langcode in entity language, move it
// to Language::LANGCODE_DEFAULT.
// This is necessary as EntityNG always keys default language values
// with Language::LANGCODE_DEFAULT while field API expects them to be
// keyed by langcode.
foreach
(
$value
as
$langcode
=>
$data
)
{
if
(
$langcode
!=
Language
::
LANGCODE_DEFAULT
&&
$langcode
==
$this
->
decorated
->
language
()
->
id
)
{
$value
[
Language
::
LANGCODE_DEFAULT
]
=
$data
;
unset
(
$value
[
$langcode
]);
}
}
}
$this
->
decorated
->
values
[
$name
]
=
$value
;
}
// Remove the field object to avoid the field object and the value getting
// out of sync. That way, the next field object instantiated by EntityNG
// will hold the updated value.
unset
(
$this
->
decorated
->
fields
[
$name
]);
$this
->
decorated
->
onChange
(
$name
);
}
/**
* Implements the magic method for isset().
*/
public
function
__isset
(
$name
)
{
$value
=
$this
->
__get
(
$name
);
return
isset
(
$value
);
}
/**
* Implements the magic method for unset().
*/
public
function
__unset
(
$name
)
{
// Set the value to NULL.
$value
=
&
$this
->
__get
(
$name
);
$value
=
NULL
;
}
/**
* Implements the magic method for clone().
*/
function
__clone
()
{
$this
->
decorated
=
clone
$this
->
decorated
;
}
/**
* Forwards the call to the decorated entity.
*/
public
function
uriRelationships
()
{
return
$this
->
decorated
->
uriRelationships
();
}
/**
* Forwards the call to the decorated entity.
*/
public
function
access
(
$operation
=
'view'
,
AccountInterface
$account
=
NULL
)
{
return
$this
->
decorated
->
access
(
$operation
,
$account
);
}
/**
* Forwards the call to the decorated entity.
*/
public
function
get
(
$property_name
)
{
// Ensure this works with not yet defined fields.
if
(
!
isset
(
$this
->
definitions
[
$property_name
]))
{
return
$this
->
__get
(
$property_name
);
}
return
$this
->
decorated
->
get
(
$property_name
);
}
/**
* Forwards the call to the decorated entity.
*/
public
function
set
(
$property_name
,
$value
,
$notify
=
TRUE
)
{
// Ensure this works with not yet defined fields.
if
(
!
isset
(
$this
->
definitions
[
$property_name
]))
{
return
$this
->
__set
(
$property_name
,
$value
);
}
return
$this
->
decorated
->
set
(
$property_name
,
$value
);
}
/**
* Forwards the call to the decorated entity.
*/
public
function
getProperties
(
$include_computed
=
FALSE
)
{
return
$this
->
decorated
->
getProperties
(
$include_computed
);
}
/**
* Forwards the call to the decorated entity.
*/
public
function
getPropertyValues
()
{
return
$this
->
decorated
->
getPropertyValues
();
}
/**
* Forwards the call to the decorated entity.
*/
public
function
setPropertyValues
(
$values
)
{
return
$this
->
decorated
->
setPropertyValues
(
$values
);
}
/**
* Forwards the call to the decorated entity.
*/
public
function
getPropertyDefinition
(
$name
)
{
return
$this
->
decorated
->
getPropertyDefinition
(
$name
);
}
/**
* Forwards the call to the decorated entity.
*/
public
function
getPropertyDefinitions
()
{
return
$this
->
decorated
->
getPropertyDefinitions
();
}
/**
* Forwards the call to the decorated entity.
*/
public
function
isEmpty
()
{
return
$this
->
decorated
->
isEmpty
();
}
/**
* Forwards the call to the decorated entity.
*/
public
function
getIterator
()
{
return
$this
->
decorated
->
getIterator
();
}
/**
* Forwards the call to the decorated entity.
*/
public
function
id
()
{
return
$this
->
decorated
->
id
();
}
/**
* Forwards the call to the decorated entity.
*/
public
function
uuid
()
{
return
$this
->
decorated
->
uuid
();
}
/**
* Forwards the call to the decorated entity.
*/
public
function
isNew
()
{
return
$this
->
decorated
->
isNew
();
}
/**
* Forwards the call to the decorated entity.
*/
public
function
isNewRevision
()
{
return
$this
->
decorated
->
isNewRevision
();
}
/**
* Forwards the call to the decorated entity.
*/
public
function
setNewRevision
(
$value
=
TRUE
)
{
return
$this
->
decorated
->
setNewRevision
(
$value
);
}
/**
* Forwards the call to the decorated entity.
*/
public
function
enforceIsNew
(
$value
=
TRUE
)
{
return
$this
->
decorated
->
enforceIsNew
(
$value
);
}
/**
* Forwards the call to the decorated entity.
*/
public
function
entityType
()
{
return
$this
->
decorated
->
entityType
();
}
/**
* Forwards the call to the decorated entity.
*/
public
function
bundle
()
{
return
$this
->
decorated
->
bundle
();
}
/**
* Forwards the call to the decorated entity.
*/
public
function
label
(
$langcode
=
NULL
)
{
return
$this
->
decorated
->
label
(
$langcode
);
}
/**
* Forwards the call to the decorated entity.
*/
public
function
uri
(
$rel
=
'canonical'
)
{
return
$this
->
decorated
->
uri
(
$rel
);
}
/**
* Forwards the call to the decorated entity.
*/
public
function
save
()
{
return
$this
->
decorated
->
save
();
}
/**
* Forwards the call to the decorated entity.
*/
public
function
delete
()
{
return
$this
->
decorated
->
delete
();
}
/**
* Forwards the call to the decorated entity.
*/
public
function
createDuplicate
()
{
return
$this
->
decorated
->
createDuplicate
();
}
/**
* Forwards the call to the decorated entity.
*/
public
function
entityInfo
()
{
return
$this
->
decorated
->
entityInfo
();
}
/**
* Forwards the call to the decorated entity.
*/
public
function
getRevisionId
()
{
return
$this
->
decorated
->
getRevisionId
();
}
/**
* Forwards the call to the decorated entity.
*/
public
function
isDefaultRevision
(
$new_value
=
NULL
)
{
return
$this
->
decorated
->
isDefaultRevision
(
$new_value
);
}
/**
* Forwards the call to the decorated entity.
*/
public
function
language
()
{
return
$this
->
decorated
->
language
();
}
/**
* Forwards the call to the decorated entity.
*/
public
function
getTranslationLanguages
(
$include_default
=
TRUE
)
{
return
$this
->
decorated
->
getTranslationLanguages
(
$include_default
);
}
/**
* Forwards the call to the decorated entity.
*/
public
function
getTranslation
(
$langcode
)
{
return
$this
->
decorated
->
getTranslation
(
$langcode
);
}
/**
* Forwards the call to the decorated entity.
*/
public
function
getDefinition
()
{
return
$this
->
decorated
->
getDefinition
();
}
/**
* Forwards the call to the decorated entity.
*/
public
function
getValue
()
{
return
$this
->
decorated
->
getValue
();
}
/**
* Forwards the call to the decorated entity.
*/
public
function
setValue
(
$value
,
$notify
=
TRUE
)
{
return
$this
->
decorated
->
setValue
(
$value
,
$notify
);
}
/**
* Forwards the call to the decorated entity.
*/
public
function
getString
()
{
return
$this
->
decorated
->
getString
();
}
/**
* Forwards the call to the decorated entity.
*/
public
function
getConstraints
()
{
return
$this
->
decorated
->
getConstraints
();
}
/**
* Forwards the call to the decorated entity.