drupal/core/modules/entity/entity.class.inc

428 lines
12 KiB
PHP

<?php
/**
* @file
* Provides an interface and a base class for entities.
*/
/**
* Defines a common interface for all entity objects.
*/
interface EntityInterface {
/**
* Constructs a new entity object.
*
* @param $values
* An array of values to set, keyed by property name. If the entity type
* has bundles, the bundle key has to be specified.
* @param $entity_type
* The type of the entity to create.
*/
public function __construct(array $values, $entity_type);
/**
* Returns the entity identifier (the entity's machine name or numeric ID).
*
* @return
* The identifier of the entity, or NULL if the entity does not yet have
* an identifier.
*/
public function id();
/**
* Returns whether the entity is new.
*
* Usually an entity is new if no ID exists for it yet. However, entities may
* be enforced to be new with existing IDs too.
*
* @return
* TRUE if the entity is new, or FALSE if the entity has already been saved.
*
* @see EntityInterface::enforceIsNew()
*/
public function isNew();
/**
* Enforces an entity to be new.
*
* Allows migrations to create entities with pre-defined IDs by forcing the
* entity to be new before saving.
*
* @param bool $value
* (optional) Whether the entity should be forced to be new. Defaults to
* TRUE.
*
* @see EntityInterface::isNew()
*/
public function enforceIsNew($value = TRUE);
/**
* Returns the type of the entity.
*
* @return
* The type of the entity.
*/
public function entityType();
/**
* Returns the bundle of the entity.
*
* @return
* The bundle of the entity. Defaults to the entity type if the entity type
* does not make use of different bundles.
*/
public function bundle();
/**
* Returns the label of the entity.
*
* @return
* The label of the entity, or NULL if there is no label defined.
*/
public function label();
/**
* Returns the URI elements of the entity.
*
* @return
* An array containing the 'path' and 'options' keys used to build the URI
* of the entity, and matching the signature of url(). NULL if the entity
* has no URI of its own.
*/
public function uri();
/**
* Returns the default language of a language-specific entity.
*
* @return
* The language object of the entity's default language, or FALSE if the
* entity is not language-specific.
*
* @see EntityInterface::translations()
*/
public function language();
/**
* Returns the languages the entity is translated to.
*
* @return
* An array of language objects, keyed by language codes.
*
* @see EntityInterface::language()
*/
public function translations();
/**
* Returns the value of an entity property.
*
* @param $property_name
* The name of the property to return; e.g., 'title'.
* @param $langcode
* (optional) If the property is translatable, the language code of the
* language that should be used for getting the property. If set to NULL,
* the entity's default language is being used.
*
* @return
* The property value, or NULL if it is not defined.
*
* @see EntityInterface::language()
*/
public function get($property_name, $langcode = NULL);
/**
* Sets the value of an entity property.
*
* @param $property_name
* The name of the property to set; e.g., 'title'.
* @param $value
* The value to set, or NULL to unset the property.
* @param $langcode
* (optional) If the property is translatable, the language code of the
* language that should be used for getting the property. If set to
* NULL, the entity's default language is being used.
*
* @see EntityInterface::language()
*/
public function set($property_name, $value, $langcode = NULL);
/**
* Saves an entity permanently.
*
* @return
* Either SAVED_NEW or SAVED_UPDATED, depending on the operation performed.
*
* @throws EntityStorageException
* In case of failures an exception is thrown.
*/
public function save();
/**
* Deletes an entity permanently.
*
* @throws EntityStorageException
* In case of failures an exception is thrown.
*/
public function delete();
/**
* Creates a duplicate of the entity.
*
* @return EntityInterface
* A clone of the current entity with all identifiers unset, so saving
* it inserts a new entity into the storage system.
*/
public function createDuplicate();
/**
* Returns the info of the type of the entity.
*
* @see entity_get_info()
*/
public function entityInfo();
}
/**
* Defines a base entity class.
*
* Default implementation of EntityInterface.
*
* This class can be used as-is by simple entity types. Entity types requiring
* special handling can extend the class.
*/
class Entity implements EntityInterface {
/**
* The language code of the entity's default language.
*
* @var string
*/
public $langcode = LANGUAGE_NOT_SPECIFIED;
/**
* The entity type.
*
* @var string
*/
protected $entityType;
/**
* Boolean indicating whether the entity should be forced to be new.
*
* @var bool
*/
protected $enforceIsNew;
/**
* Constructs a new entity object.
*/
public function __construct(array $values = array(), $entity_type) {
$this->entityType = $entity_type;
// Set initial values.
foreach ($values as $key => $value) {
$this->$key = $value;
}
}
/**
* Implements EntityInterface::id().
*/
public function id() {
return isset($this->id) ? $this->id : NULL;
}
/**
* Implements EntityInterface::isNew().
*/
public function isNew() {
return !empty($this->enforceIsNew) || !$this->id();
}
/**
* Implements EntityInterface::enforceIsNew().
*/
public function enforceIsNew($value = TRUE) {
$this->enforceIsNew = $value;
}
/**
* Implements EntityInterface::entityType().
*/
public function entityType() {
return $this->entityType;
}
/**
* Implements EntityInterface::bundle().
*/
public function bundle() {
return $this->entityType;
}
/**
* Implements EntityInterface::label().
*
* @see entity_label()
*/
public function label() {
$label = FALSE;
$entity_info = $this->entityInfo();
if (isset($entity_info['label callback']) && function_exists($entity_info['label callback'])) {
$label = $entity_info['label callback']($this->entityType, $this);
}
elseif (!empty($entity_info['entity keys']['label']) && isset($this->{$entity_info['entity keys']['label']})) {
$label = $this->{$entity_info['entity keys']['label']};
}
return $label;
}
/**
* Implements EntityInterface::uri().
*
* @see entity_uri()
*/
public function uri() {
$bundle = $this->bundle();
// A bundle-specific callback takes precedence over the generic one for the
// entity type.
$entity_info = $this->entityInfo();
if (isset($entity_info['bundles'][$bundle]['uri callback'])) {
$uri_callback = $entity_info['bundles'][$bundle]['uri callback'];
}
elseif (isset($entity_info['uri callback'])) {
$uri_callback = $entity_info['uri callback'];
}
else {
return NULL;
}
// Invoke the callback to get the URI. If there is no callback, return NULL.
if (isset($uri_callback) && function_exists($uri_callback)) {
$uri = $uri_callback($this);
// Pass the entity data to url() so that alter functions do not need to
// look up this entity again.
$uri['options']['entity_type'] = $this->entityType;
$uri['options']['entity'] = $this;
return $uri;
}
}
/**
* Implements EntityInterface::language().
*/
public function language() {
// @todo: Check for language.module instead, once Field API language
// handling depends upon it too.
return module_exists('locale') ? language_load($this->langcode) : FALSE;
}
/**
* Implements EntityInterface::translations().
*/
public function translations() {
$languages = array();
$entity_info = $this->entityInfo();
if ($entity_info['fieldable'] && ($default_language = $this->language())) {
// Go through translatable properties and determine all languages for
// which translated values are available.
foreach (field_info_instances($this->entityType, $this->bundle()) as $field_name => $instance) {
$field = field_info_field($field_name);
if (field_is_translatable($this->entityType, $field) && isset($this->$field_name)) {
foreach ($this->$field_name as $langcode => $value) {
$languages[$langcode] = TRUE;
}
}
}
// Remove the default language from the translations.
unset($languages[$default_language->langcode]);
$languages = array_intersect_key(language_list(), $languages);
}
return $languages;
}
/**
* Implements EntityInterface::get().
*/
public function get($property_name, $langcode = NULL) {
// Handle fields.
$entity_info = $this->entityInfo();
if ($entity_info['fieldable'] && field_info_instance($this->entityType, $property_name, $this->bundle())) {
$field = field_info_field($property_name);
$langcode = $this->getFieldLangcode($field, $langcode);
return isset($this->{$property_name}[$langcode]) ? $this->{$property_name}[$langcode] : NULL;
}
else {
// Handle properties being not fields.
// @todo: Add support for translatable properties being not fields.
return isset($this->{$property_name}) ? $this->{$property_name} : NULL;
}
}
/**
* Implements EntityInterface::set().
*/
public function set($property_name, $value, $langcode = NULL) {
// Handle fields.
$entity_info = $this->entityInfo();
if ($entity_info['fieldable'] && field_info_instance($this->entityType, $property_name, $this->bundle())) {
$field = field_info_field($property_name);
$langcode = $this->getFieldLangcode($field, $langcode);
$this->{$property_name}[$langcode] = $value;
}
else {
// Handle properties being not fields.
// @todo: Add support for translatable properties being not fields.
$this->{$property_name} = $value;
}
}
/**
* Determines the language code to use for accessing a field value in a certain language.
*/
protected function getFieldLangcode($field, $langcode = NULL) {
// Only apply the given langcode if the entity is language-specific.
// Otherwise translatable fields are handled as non-translatable fields.
if (field_is_translatable($this->entityType, $field) && ($default_language = $this->language())) {
// For translatable fields the values in default language are stored using
// the language code of the default language.
return isset($langcode) ? $langcode : $default_language->langcode;
}
else {
// Non-translatable fields always use LANGUAGE_NOT_SPECIFIED.
return LANGUAGE_NOT_SPECIFIED;
}
}
/**
* Implements EntityInterface::save().
*/
public function save() {
return entity_get_controller($this->entityType)->save($this);
}
/**
* Implements EntityInterface::delete().
*/
public function delete() {
if (!$this->isNew()) {
entity_get_controller($this->entityType)->delete(array($this->id()));
}
}
/**
* Implements EntityInterface::createDuplicate().
*/
public function createDuplicate() {
$duplicate = clone $this;
$duplicate->id = NULL;
return $duplicate;
}
/**
* Implements EntityInterface::entityInfo().
*/
public function entityInfo() {
return entity_get_info($this->entityType);
}
}