428 lines
12 KiB
PHP
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);
|
|
}
|
|
}
|