class EntityDrupalWrapper in Entity API 7
Provides a wrapper for entities registrered in hook_entity_info().
The wrapper eases applying getter and setter callbacks of entity properties specified in hook_entity_property_info().
Hierarchy
- class \EntityMetadataWrapper
- class \EntityStructureWrapper implements \IteratorAggregate
- class \EntityDrupalWrapper
- class \EntityStructureWrapper implements \IteratorAggregate
Expanded class hierarchy of EntityDrupalWrapper
File
- includes/
entity.wrapper.inc, line 590 - Provides wrappers allowing easy usage of the entity metadata.
View source
class EntityDrupalWrapper extends EntityStructureWrapper {
/**
* Contains the entity id.
*/
protected $id = FALSE;
protected $bundle;
protected $entityInfo;
/**
* Construct a new EntityDrupalWrapper object.
*
* @param $type
* The type of the passed data.
* @param $data
* Optional. The entity to wrap or its identifier.
* @param $info
* Optional. Used internally to pass info about properties down the tree.
*/
public function __construct($type, $data = NULL, $info = array()) {
parent::__construct($type, $data, $info);
$this
->setUp();
}
protected function setUp() {
$this->propertyInfo = entity_get_property_info($this->type) + array(
'properties' => array(),
);
$info = $this->info + array(
'property info' => array(),
'bundle' => NULL,
);
$this->propertyInfo['properties'] += $info['property info'];
$this->bundle = $info['bundle'];
$this->entityInfo = entity_get_info($this->type);
if (isset($this->bundle)) {
$this
->spotBundleInfo(FALSE);
}
}
/**
* Sets the entity internally accepting both the entity id and object.
*/
protected function setEntity($data) {
// For entities we allow getter callbacks to return FALSE, which we
// interpret like NULL values as unset properties.
if (isset($data) && $data !== FALSE && !is_object($data)) {
$this->id = $data;
$this->data = FALSE;
}
elseif (is_object($data) && $data instanceof EntityDrupalWrapper) {
// We got a wrapped entity passed, so take over its values.
$this->id = $data->id;
$this->data = $data->data;
// For generic entity references, also update the entity type accordingly.
if ($this->info['type'] == 'entity') {
$this->type = $data->type;
}
}
elseif (is_object($data)) {
// We got the entity object passed.
$this->data = $data;
$id = entity_id($this->type, $data);
$this->id = isset($id) ? $id : FALSE;
}
else {
$this->id = FALSE;
$this->data = NULL;
}
}
/**
* Used to lazy-load bundle info. So the wrapper can be loaded e.g. just
* for setting without the data being loaded.
*/
protected function spotInfo() {
if (!$this->propertyInfoAltered) {
if ($this->info['type'] == 'entity' && $this
->dataAvailable() && $this
->value()) {
// Add in entity-type specific details.
$this
->setUp();
}
$this
->spotBundleInfo(TRUE);
parent::spotInfo();
$this->propertyInfoAltered = TRUE;
}
}
/**
* Tries to determine the bundle and adds in the according property info.
*
* @param $load
* Whether the entity should be loaded to spot the info if necessary.
*/
protected function spotBundleInfo($load = TRUE) {
// Like entity_extract_ids() assume the entity type if no key is given.
if (empty($this->entityInfo['entity keys']['bundle']) && $this->type != 'entity') {
$this->bundle = $this->type;
}
elseif (!$this->bundle && $load && $this
->dataAvailable()) {
try {
if ($entity = $this
->value()) {
list($id, $vid, $bundle) = entity_extract_ids($this->type, $entity);
$this->bundle = $bundle;
}
} catch (EntityMetadataWrapperException $e) {
// Loading data failed, so we cannot derive the used bundle.
}
}
if ($this->bundle && isset($this->propertyInfo['bundles'][$this->bundle])) {
$bundle_info = (array) $this->propertyInfo['bundles'][$this->bundle] + array(
'properties' => array(),
);
// Allow bundles to re-define existing properties, such that the bundle
// can add in more bundle-specific details like the bundle of a referenced
// entity.
$this->propertyInfo['properties'] = $bundle_info['properties'] + $this->propertyInfo['properties'];
}
}
/**
* Returns the identifier of the wrapped entity.
*
* @see entity_id()
*/
public function getIdentifier() {
return $this
->dataAvailable() ? $this
->value(array(
'identifier' => TRUE,
)) : NULL;
}
/**
* Returns the bundle of an entity, or FALSE if it has no bundles.
*/
public function getBundle() {
if ($this
->dataAvailable()) {
$this
->spotInfo();
return $this->bundle;
}
}
/**
* Overridden.
*
* @param $options
* An array of options. Known keys:
* - identifier: If set to TRUE, the entity identifier is returned.
*/
public function value(array $options = array()) {
// Try loading the data via the getter callback if there is none yet.
if (!isset($this->data)) {
$this
->setEntity(parent::value());
}
if (!empty($options['identifier'])) {
return $this->id;
}
elseif (!$this->data && !empty($this->id)) {
// Lazy load the entity if necessary.
$return = entity_load($this->type, array(
$this->id,
));
// In case the entity cannot be loaded, we return NULL just as for empty
// properties.
$this->data = $return ? reset($return) : NULL;
}
return $this->data;
}
/**
* Returns the entity prepared for rendering.
*
* @see entity_view()
*/
public function view($view_mode = 'full', $langcode = NULL, $page = NULL) {
return entity_view($this
->type(), array(
$this
->value(),
), $view_mode, $langcode, $page);
}
/**
* Overridden to support setting the entity by either the object or the id.
*/
public function set($value) {
if (!$this
->validate($value)) {
throw new EntityMetadataWrapperException(t('Invalid data value given. Be sure it matches the required data type and format. Value at !location: !value.', array(
// An exception's message is output through check_plain().
'!value' => is_array($value) || is_object($value) ? var_export($value, TRUE) : $value,
'!location' => $this
->debugIdentifierLocation(),
)));
}
if ($this->info['type'] == 'entity' && $value === $this) {
// Nothing to do.
return $this;
}
$previous_id = $this->id;
$previous_type = $this->type;
// Set value, so we get the identifier and pass it to the normal setter.
$this
->clear();
$this
->setEntity($value);
// Generally, we have to update the parent only if the entity reference
// has changed. In case of a generic entity reference, we pass the entity
// wrapped. Else we just pass the id of the entity to the setter callback.
if ($this->info['type'] == 'entity' && ($previous_id != $this->id || $previous_type != $this->type)) {
// We need to clone the wrapper we pass through as value, so it does not
// get cleared when the current wrapper instance gets cleared.
$this
->updateParent(clone $this);
}
elseif ($this->id === FALSE && !$this->data) {
$this
->updateParent(NULL);
}
elseif ($previous_id !== $this->id) {
$this
->updateParent($this->id);
}
return $this;
}
/**
* Overridden.
*/
public function clear() {
$this->id = NULL;
$this->bundle = isset($this->info['bundle']) ? $this->info['bundle'] : NULL;
if ($this->type != $this->info['type']) {
// Reset entity info / property info based upon the info provided during
// the creation of the wrapper.
$this->type = $this->info['type'];
$this
->setUp();
}
parent::clear();
}
/**
* Overridden.
*/
public function type() {
// In case of a generic entity wrapper, load the data first to determine
// the type of the concrete entity.
if ($this
->dataAvailable() && $this->info['type'] == 'entity') {
try {
$this
->value(array(
'identifier' => TRUE,
));
} catch (EntityMetadataWrapperException $e) {
// If loading data fails, we cannot determine the concrete entity type.
}
}
return $this->type;
}
/**
* {@inheritdoc}
*
* Note that this method checks property access, but can be used for checking
* entity access *only* if the wrapper is not a property (i.e. has no parent
* wrapper).
* To be safe, better use EntityDrupalWrapper::entityAccess() for checking
* entity access.
*/
public function access($op, $account = NULL) {
if (!empty($this->info['parent'])) {
// If this is a property, make sure the user is able to view the
// currently referenced entity also.
if ($this
->entityAccess('view', $account) === FALSE) {
return FALSE;
}
if (parent::access($op, $account) === FALSE) {
return FALSE;
}
// If access is unknown, we return TRUE.
return TRUE;
}
else {
// This is not a property, so fallback on entity access.
if ($op == 'edit') {
// If the operation is "edit" determine if its actually a "create" for
// new un-saved entities, or an "update" for existing ones.
return $this
->entityAccess($this
->getIdentifier() ? 'update' : 'create', $account);
}
return $this
->entityAccess('view', $account);
}
}
/**
* Checks whether the operation $op is allowed on the entity.
*
* @see entity_access()
*/
public function entityAccess($op, $account = NULL) {
$entity = $this
->dataAvailable() ? $this
->value() : NULL;
// The value() method could return FALSE on entities such as user 0, so we
// need to use NULL instead to conform to the expectations of
// entity_access().
if ($entity === FALSE) {
$entity = NULL;
}
return entity_access($op, $this->type, $entity, $account);
}
/**
* Permanently save the wrapped entity.
*
* @throws EntityMetadataWrapperException
* If the entity type does not support saving.
*
* @return EntityDrupalWrapper
*/
public function save() {
if ($this->data) {
if (!entity_type_supports($this->type, 'save')) {
throw new EntityMetadataWrapperException("There is no information about how to save entities of type " . check_plain($this->type) . '.');
}
entity_save($this->type, $this->data);
// On insert, update the identifier afterwards.
if (!$this->id) {
list($this->id, , ) = entity_extract_ids($this->type, $this->data);
}
}
// If the entity hasn't been loaded yet, don't bother saving it.
return $this;
}
/**
* Permanently delete the wrapped entity.
*
* @return EntityDrupalWrapper
*/
public function delete() {
if ($this
->dataAvailable() && $this
->value()) {
$return = entity_delete($this->type, $this->id);
if ($return === FALSE) {
throw new EntityMetadataWrapperException("There is no information about how to delete entities of type " . check_plain($this->type) . '.');
}
}
return $this;
}
/**
* Gets the info about the wrapped entity.
*/
public function entityInfo() {
return $this->entityInfo;
}
/**
* Returns the name of the key used by the entity for given entity key.
*
* @param $name
* One of 'id', 'name', 'bundle' or 'revision'.
*
* @return string
* The name of the key used by the entity.
*/
public function entityKey($name) {
return isset($this->entityInfo['entity keys'][$name]) ? $this->entityInfo['entity keys'][$name] : FALSE;
}
/**
* Returns the entity label.
*
* @see entity_label()
*/
public function label() {
if ($entity = $this
->value()) {
return entity_label($this->type, $entity);
}
}
/**
* Returns a string to use to identify this wrapper in error messages.
*/
public function debugIdentifierLocation() {
// An entity wrapper can be at the top of the chain or a part of it.
if (isset($this->info['name'])) {
// This wrapper is part of a chain, eg in the position node->author.
// Return the name.
$debug = $this->info['name'];
}
else {
// This is a wrapper for an actual entity: return its type and id.
$debug = $this->info['type'] . '(' . $this
->getIdentifier() . ')';
}
if (isset($this->info['parent'])) {
$debug = $this->info['parent']
->debugIdentifierLocation() . '->' . $debug;
}
return $debug;
}
/**
* Prepare for serializiation.
*/
public function __sleep() {
$vars = parent::__sleep();
// Don't serialize the loaded entity and its property info.
unset($vars['data'], $vars['propertyInfo'], $vars['propertyInfoAltered'], $vars['entityInfo']);
// In case the entity is not saved yet, serialize the unsaved data.
if ($this
->dataAvailable() && $this->id === FALSE) {
$vars['data'] = 'data';
}
return $vars;
}
public function __wakeup() {
$this
->setUp();
if ($this->id !== FALSE) {
// Make sure data is set, so the entity will be loaded when needed.
$this->data = FALSE;
}
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
EntityDrupalWrapper:: |
protected | property | ||
EntityDrupalWrapper:: |
protected | property | ||
EntityDrupalWrapper:: |
protected | property | Contains the entity id. | |
EntityDrupalWrapper:: |
public | function |
Note that this method checks property access, but can be used for checking
entity access *only* if the wrapper is not a property (i.e. has no parent
wrapper).
To be safe, better use EntityDrupalWrapper::entityAccess() for checking
entity access. Overrides EntityMetadataWrapper:: |
|
EntityDrupalWrapper:: |
public | function |
Overridden. Overrides EntityStructureWrapper:: |
|
EntityDrupalWrapper:: |
public | function |
Returns a string to use to identify this wrapper in error messages. Overrides EntityMetadataWrapper:: |
|
EntityDrupalWrapper:: |
public | function | Permanently delete the wrapped entity. | |
EntityDrupalWrapper:: |
public | function | Checks whether the operation $op is allowed on the entity. | |
EntityDrupalWrapper:: |
public | function | Gets the info about the wrapped entity. | |
EntityDrupalWrapper:: |
public | function | Returns the name of the key used by the entity for given entity key. | |
EntityDrupalWrapper:: |
public | function | Returns the bundle of an entity, or FALSE if it has no bundles. | |
EntityDrupalWrapper:: |
public | function |
Returns the identifier of the wrapped entity. Overrides EntityStructureWrapper:: |
|
EntityDrupalWrapper:: |
public | function |
Returns the entity label. Overrides EntityMetadataWrapper:: |
|
EntityDrupalWrapper:: |
public | function | Permanently save the wrapped entity. | |
EntityDrupalWrapper:: |
public | function |
Overridden to support setting the entity by either the object or the id. Overrides EntityMetadataWrapper:: |
|
EntityDrupalWrapper:: |
protected | function | Sets the entity internally accepting both the entity id and object. | |
EntityDrupalWrapper:: |
protected | function | ||
EntityDrupalWrapper:: |
protected | function | Tries to determine the bundle and adds in the according property info. | |
EntityDrupalWrapper:: |
protected | function |
Used to lazy-load bundle info. So the wrapper can be loaded e.g. just
for setting without the data being loaded. Overrides EntityStructureWrapper:: |
|
EntityDrupalWrapper:: |
public | function |
Overridden. Overrides EntityMetadataWrapper:: |
|
EntityDrupalWrapper:: |
public | function |
Overridden. Overrides EntityMetadataWrapper:: |
|
EntityDrupalWrapper:: |
public | function | Returns the entity prepared for rendering. | |
EntityDrupalWrapper:: |
public | function |
Construct a new EntityDrupalWrapper object. Overrides EntityStructureWrapper:: |
|
EntityDrupalWrapper:: |
public | function |
Prepare for serializiation. Overrides EntityStructureWrapper:: |
|
EntityDrupalWrapper:: |
public | function | ||
EntityMetadataWrapper:: |
protected | property | ||
EntityMetadataWrapper:: |
protected | property | ||
EntityMetadataWrapper:: |
protected | property | ||
EntityMetadataWrapper:: |
protected | property | 1 | |
EntityMetadataWrapper:: |
protected | function | Returns whether data is available to work with. | |
EntityMetadataWrapper:: |
public | function | Gets info about the wrapped data. | |
EntityMetadataWrapper:: |
public | function | Returns the options list specifying possible values for the property, if defined. | |
EntityMetadataWrapper:: |
public | function | Returns the raw, unprocessed data. Most times this is the same as returned by value(), however for already processed and sanitized textual data, this will return the unprocessed data in contrast to value(). | |
EntityMetadataWrapper:: |
protected | function | Updates the parent data structure of a data property with the latest data value. | |
EntityMetadataWrapper:: |
public | function | Returns whether $value is a valid value to set. | 1 |
EntityMetadataWrapper:: |
public | function | ||
EntityStructureWrapper:: |
protected | property | ||
EntityStructureWrapper:: |
protected | property | ||
EntityStructureWrapper:: |
protected | property | ||
EntityStructureWrapper:: |
public | function | Get the wrapper for a property. | |
EntityStructureWrapper:: |
public | function | ||
EntityStructureWrapper:: |
public | function | Gets the info about the given property. | |
EntityStructureWrapper:: |
public | function | Gets the language used for retrieving properties. | |
EntityStructureWrapper:: |
protected | function | Gets the raw value of a property. | |
EntityStructureWrapper:: |
protected | function | Gets the value of a property. | |
EntityStructureWrapper:: |
public | function | Sets a new language to use for retrieving properties. | |
EntityStructureWrapper:: |
protected | function | ||
EntityStructureWrapper:: |
public | function | Returns a reference on the property info. | |
EntityStructureWrapper:: |
protected | function | Sets a property. | |
EntityStructureWrapper:: |
public | function | Magic method: Get a wrapper for a property. | |
EntityStructureWrapper:: |
public | function | Magic method: Can be used to check if a property is known. | |
EntityStructureWrapper:: |
public | function | Magic method: Set a property. |