all contrib module security updates done
This commit is contained in:
@@ -107,7 +107,7 @@ interface EntityAPIControllerInterface extends DrupalEntityControllerInterface {
|
||||
* content language of the current request.
|
||||
* @param $page
|
||||
* (optional) If set will control if the entity is rendered: if TRUE
|
||||
* the entity will be rendered without its title, so that it can be embeded
|
||||
* the entity will be rendered without its title, so that it can be embedded
|
||||
* in another context. If FALSE the entity will be displayed with its title
|
||||
* in a mode suitable for lists.
|
||||
* If unset, the page mode will be enabled if the current path is the URI
|
||||
@@ -171,7 +171,7 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
|
||||
if ($this->revisionKey) {
|
||||
// Compare revision id of the base and revision table, if equal then this
|
||||
// is the default revision.
|
||||
$query->addExpression('base.' . $this->revisionKey . ' = revision.' . $this->revisionKey, $this->defaultRevisionKey);
|
||||
$query->addExpression('CASE WHEN base.' . $this->revisionKey . ' = revision.' . $this->revisionKey . ' THEN 1 ELSE 0 END', $this->defaultRevisionKey);
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
@@ -373,10 +373,7 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
|
||||
// Do nothing, in case invalid or no ids have been passed.
|
||||
return;
|
||||
}
|
||||
// This transaction causes troubles on MySQL, see
|
||||
// http://drupal.org/node/1007830. So we deactivate this by default until
|
||||
// is shipped in a point release.
|
||||
// $transaction = isset($transaction) ? $transaction : db_transaction();
|
||||
$transaction = isset($transaction) ? $transaction : db_transaction();
|
||||
|
||||
try {
|
||||
$ids = array_keys($entities);
|
||||
@@ -400,9 +397,7 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
|
||||
db_ignore_slave();
|
||||
}
|
||||
catch (Exception $e) {
|
||||
if (isset($transaction)) {
|
||||
$transaction->rollback();
|
||||
}
|
||||
$transaction->rollback();
|
||||
watchdog_exception($this->entityType, $e);
|
||||
throw $e;
|
||||
}
|
||||
@@ -587,6 +582,30 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
|
||||
$entity->content = $content;
|
||||
$langcode = isset($langcode) ? $langcode : $GLOBALS['language_content']->language;
|
||||
|
||||
// Allow modules to change the view mode.
|
||||
$context = array(
|
||||
'entity_type' => $this->entityType,
|
||||
'entity' => $entity,
|
||||
'langcode' => $langcode,
|
||||
);
|
||||
drupal_alter('entity_view_mode', $view_mode, $context);
|
||||
// Make sure the used view-mode gets stored.
|
||||
$entity->content += array('#view_mode' => $view_mode);
|
||||
|
||||
// By default add in properties for all defined extra fields.
|
||||
if ($extra_field_controller = entity_get_extra_fields_controller($this->entityType)) {
|
||||
$wrapper = entity_metadata_wrapper($this->entityType, $entity);
|
||||
$extra = $extra_field_controller->fieldExtraFields();
|
||||
$type_extra = &$extra[$this->entityType][$this->entityType]['display'];
|
||||
$bundle_extra = &$extra[$this->entityType][$wrapper->getBundle()]['display'];
|
||||
|
||||
foreach ($wrapper as $name => $property) {
|
||||
if (isset($type_extra[$name]) || isset($bundle_extra[$name])) {
|
||||
$this->renderEntityProperty($wrapper, $name, $property, $view_mode, $langcode, $entity->content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add in fields.
|
||||
if (!empty($this->entityInfo['fieldable'])) {
|
||||
// Perform the preparation tasks if they have not been performed yet.
|
||||
@@ -608,6 +627,24 @@ class EntityAPIController extends DrupalDefaultEntityController implements Entit
|
||||
return $build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a single entity property.
|
||||
*/
|
||||
protected function renderEntityProperty($wrapper, $name, $property, $view_mode, $langcode, &$content) {
|
||||
$info = $property->info();
|
||||
|
||||
$content[$name] = array(
|
||||
'#label_hidden' => FALSE,
|
||||
'#label' => $info['label'],
|
||||
'#entity_wrapped' => $wrapper,
|
||||
'#theme' => 'entity_property',
|
||||
'#property_name' => $name,
|
||||
'#access' => $property->access('view'),
|
||||
'#entity_type' => $this->entityType,
|
||||
);
|
||||
$content['#attached']['css']['entity.theme'] = drupal_get_path('module', 'entity') . '/theme/entity.theme.css';
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements EntityAPIControllerInterface.
|
||||
*/
|
||||
|
||||
@@ -5,6 +5,168 @@
|
||||
* Provides a base class for entities.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interface for class based entities.
|
||||
*/
|
||||
interface EntityInterface {
|
||||
|
||||
/**
|
||||
* Returns the internal, numeric identifier.
|
||||
*
|
||||
* Returns the numeric identifier, even if the entity type has specified a
|
||||
* name key. In the latter case, the numeric identifier is supposed to be used
|
||||
* when dealing generically with entities or internally to refer to an entity,
|
||||
* i.e. in a relational database. If unsure, use Entity:identifier().
|
||||
*/
|
||||
public function internalIdentifier();
|
||||
|
||||
/**
|
||||
* Returns the entity identifier, i.e. the entities name or numeric id.
|
||||
*
|
||||
* @return
|
||||
* The identifier of the entity. If the entity type makes use of a name key,
|
||||
* the name is returned, else the numeric id.
|
||||
*
|
||||
* @see entity_id()
|
||||
*/
|
||||
public function identifier();
|
||||
|
||||
/**
|
||||
* Returns the info of the type of the entity.
|
||||
*
|
||||
* @see entity_get_info()
|
||||
*/
|
||||
public function entityInfo();
|
||||
|
||||
/**
|
||||
* Returns 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 EntityMetadataWrapper of the entity.
|
||||
*
|
||||
* @return EntityDrupalWrapper
|
||||
* An EntityMetadataWrapper containing the entity.
|
||||
*/
|
||||
public function wrapper();
|
||||
|
||||
/**
|
||||
* Returns the label of the entity.
|
||||
*
|
||||
* Modules may alter the label by specifying another 'label callback' using
|
||||
* hook_entity_info_alter().
|
||||
*
|
||||
* @see entity_label()
|
||||
*/
|
||||
public function label();
|
||||
|
||||
/**
|
||||
* Returns the uri of the entity just as entity_uri().
|
||||
*
|
||||
* Modules may alter the uri by specifying another 'uri callback' using
|
||||
* hook_entity_info_alter().
|
||||
*
|
||||
* @see entity_uri()
|
||||
*/
|
||||
public function uri();
|
||||
|
||||
/**
|
||||
* Checks if the entity has a certain exportable status.
|
||||
*
|
||||
* @param $status
|
||||
* A status constant, i.e. one of ENTITY_CUSTOM, ENTITY_IN_CODE,
|
||||
* ENTITY_OVERRIDDEN or ENTITY_FIXED.
|
||||
*
|
||||
* @return bool
|
||||
* For exportable entities TRUE if the entity has the status, else FALSE.
|
||||
* In case the entity is not exportable, NULL is returned.
|
||||
*
|
||||
* @see entity_has_status()
|
||||
*/
|
||||
public function hasStatus($status);
|
||||
|
||||
/**
|
||||
* Permanently saves the entity.
|
||||
*
|
||||
* @see entity_save()
|
||||
*/
|
||||
public function save();
|
||||
|
||||
/**
|
||||
* Permanently deletes the entity.
|
||||
*
|
||||
* @see entity_delete()
|
||||
*/
|
||||
public function delete();
|
||||
|
||||
/**
|
||||
* Exports the entity.
|
||||
*
|
||||
* @see entity_export()
|
||||
*/
|
||||
public function export($prefix = '');
|
||||
|
||||
/**
|
||||
* Generate an array for rendering the entity.
|
||||
*
|
||||
* @see entity_view()
|
||||
*/
|
||||
public function view($view_mode = 'full', $langcode = NULL, $page = NULL);
|
||||
|
||||
/**
|
||||
* Builds a structured array representing the entity's content.
|
||||
*
|
||||
* @see entity_build_content()
|
||||
*/
|
||||
public function buildContent($view_mode = 'full', $langcode = NULL);
|
||||
|
||||
/**
|
||||
* Gets the raw, translated value of a property or field.
|
||||
*
|
||||
* Supports retrieving field translations as well as i18n string translations.
|
||||
*
|
||||
* Note that this returns raw data values, which might not reflect what
|
||||
* has been declared for hook_entity_property_info() as no 'getter callbacks'
|
||||
* are invoked or no referenced entities are loaded. For retrieving values
|
||||
* reflecting the property info make use of entity metadata wrappers, see
|
||||
* entity_metadata_wrapper().
|
||||
*
|
||||
* @param $property
|
||||
* The name of the property to return; e.g., 'title'.
|
||||
* @param $langcode
|
||||
* (optional) The language code of the language to which the value should
|
||||
* be translated. If set to NULL, the default display language is being
|
||||
* used.
|
||||
*
|
||||
* @return
|
||||
* The raw, translated property value; or the raw, un-translated value if no
|
||||
* translation is available.
|
||||
*
|
||||
* @todo Implement an analogous setTranslation() method for updating.
|
||||
*/
|
||||
public function getTranslation($property, $langcode = NULL);
|
||||
|
||||
/**
|
||||
* Checks whether the entity is the default revision.
|
||||
*
|
||||
* @return Boolean
|
||||
*
|
||||
* @see entity_revision_is_default()
|
||||
*/
|
||||
public function isDefaultRevision();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A common class for entities.
|
||||
*
|
||||
@@ -25,17 +187,16 @@
|
||||
* public $count = 0;
|
||||
* @endcode
|
||||
*/
|
||||
class Entity {
|
||||
class Entity implements EntityInterface {
|
||||
|
||||
protected $entityType;
|
||||
protected $entityInfo;
|
||||
protected $idKey, $nameKey, $statusKey;
|
||||
protected $defaultLabel = FALSE;
|
||||
protected $wrapper;
|
||||
|
||||
/**
|
||||
* Creates a new entity.
|
||||
*
|
||||
* @see entity_create()
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __construct(array $values = array(), $entityType = NULL) {
|
||||
if (empty($entityType)) {
|
||||
@@ -56,68 +217,60 @@ class Entity {
|
||||
$this->entityInfo = entity_get_info($this->entityType);
|
||||
$this->idKey = $this->entityInfo['entity keys']['id'];
|
||||
$this->nameKey = isset($this->entityInfo['entity keys']['name']) ? $this->entityInfo['entity keys']['name'] : $this->idKey;
|
||||
$this->statusKey = empty($info['entity keys']['status']) ? 'status' : $info['entity keys']['status'];
|
||||
$this->statusKey = empty($this->entityInfo['entity keys']['status']) ? 'status' : $this->entityInfo['entity keys']['status'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the internal, numeric identifier.
|
||||
*
|
||||
* Returns the numeric identifier, even if the entity type has specified a
|
||||
* name key. In the latter case, the numeric identifier is supposed to be used
|
||||
* when dealing generically with entities or internally to refer to an entity,
|
||||
* i.e. in a relational database. If unsure, use Entity:identifier().
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function internalIdentifier() {
|
||||
return isset($this->{$this->idKey}) ? $this->{$this->idKey} : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entity identifier, i.e. the entities name or numeric id.
|
||||
*
|
||||
* @return
|
||||
* The identifier of the entity. If the entity type makes use of a name key,
|
||||
* the name is returned, else the numeric id.
|
||||
*
|
||||
* @see entity_id()
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function identifier() {
|
||||
return isset($this->{$this->nameKey}) ? $this->{$this->nameKey} : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the info of the type of the entity.
|
||||
*
|
||||
* @see entity_get_info()
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function entityInfo() {
|
||||
return $this->entityInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of the entity.
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function entityType() {
|
||||
return $this->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.
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function bundle() {
|
||||
return !empty($this->entityInfo['entity keys']['bundle']) ? $this->{$this->entityInfo['entity keys']['bundle']} : $this->entityType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the label of the entity.
|
||||
*
|
||||
* Modules may alter the label by specifying another 'label callback' using
|
||||
* hook_entity_info_alter().
|
||||
*
|
||||
* @see entity_label()
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function wrapper() {
|
||||
if (empty($this->wrapper)) {
|
||||
$this->wrapper = entity_metadata_wrapper($this->entityType, $this);
|
||||
}
|
||||
elseif ($this->wrapper->value() !== $this) {
|
||||
// Wrapper has been modified outside, so let's better create a new one.
|
||||
$this->wrapper = entity_metadata_wrapper($this->entityType, $this);
|
||||
}
|
||||
return $this->wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function label() {
|
||||
// If the default label flag is enabled, this is being invoked recursively.
|
||||
@@ -147,12 +300,7 @@ class Entity {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the uri of the entity just as entity_uri().
|
||||
*
|
||||
* Modules may alter the uri by specifying another 'uri callback' using
|
||||
* hook_entity_info_alter().
|
||||
*
|
||||
* @see entity_uri()
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function uri() {
|
||||
if (isset($this->entityInfo['uri callback']) && $this->entityInfo['uri callback'] == 'entity_class_uri') {
|
||||
@@ -170,17 +318,7 @@ class Entity {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the entity has a certain exportable status.
|
||||
*
|
||||
* @param $status
|
||||
* A status constant, i.e. one of ENTITY_CUSTOM, ENTITY_IN_CODE,
|
||||
* ENTITY_OVERRIDDEN or ENTITY_FIXED.
|
||||
*
|
||||
* @return
|
||||
* For exportable entities TRUE if the entity has the status, else FALSE.
|
||||
* In case the entity is not exportable, NULL is returned.
|
||||
*
|
||||
* @see entity_has_status()
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasStatus($status) {
|
||||
if (!empty($this->entityInfo['exportable'])) {
|
||||
@@ -189,18 +327,14 @@ class Entity {
|
||||
}
|
||||
|
||||
/**
|
||||
* Permanently saves the entity.
|
||||
*
|
||||
* @see entity_save()
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function save() {
|
||||
return entity_get_controller($this->entityType)->save($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Permanently deletes the entity.
|
||||
*
|
||||
* @see entity_delete()
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function delete() {
|
||||
$id = $this->identifier();
|
||||
@@ -210,55 +344,28 @@ class Entity {
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports the entity.
|
||||
*
|
||||
* @see entity_export()
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function export($prefix = '') {
|
||||
return entity_get_controller($this->entityType)->export($this, $prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an array for rendering the entity.
|
||||
*
|
||||
* @see entity_view()
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function view($view_mode = 'full', $langcode = NULL, $page = NULL) {
|
||||
return entity_get_controller($this->entityType)->view(array($this), $view_mode, $langcode, $page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a structured array representing the entity's content.
|
||||
*
|
||||
* @see entity_build_content()
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildContent($view_mode = 'full', $langcode = NULL) {
|
||||
return entity_get_controller($this->entityType)->buildContent($this, $view_mode, $langcode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the raw, translated value of a property or field.
|
||||
*
|
||||
* Supports retrieving field translations as well as i18n string translations.
|
||||
*
|
||||
* Note that this returns raw data values, which might not reflect what
|
||||
* has been declared for hook_entity_property_info() as no 'getter callbacks'
|
||||
* are invoked or no referenced entities are loaded. For retrieving values
|
||||
* reflecting the property info make use of entity metadata wrappers, see
|
||||
* entity_metadata_wrapper().
|
||||
*
|
||||
* @param $property_name
|
||||
* The name of the property to return; e.g., 'title'.
|
||||
* @param $langcode
|
||||
* (optional) The language code of the language to which the value should
|
||||
* be translated. If set to NULL, the default display language is being
|
||||
* used.
|
||||
*
|
||||
* @return
|
||||
* The raw, translated property value; or the raw, un-translated value if no
|
||||
* translation is available.
|
||||
*
|
||||
* @todo Implement an analogous setTranslation() method for updating.
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTranslation($property, $langcode = NULL) {
|
||||
$all_info = entity_get_all_property_info($this->entityType);
|
||||
@@ -278,11 +385,7 @@ class Entity {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the entity is the default revision.
|
||||
*
|
||||
* @return Boolean
|
||||
*
|
||||
* @see entity_revision_is_default()
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isDefaultRevision() {
|
||||
if (!empty($this->entityInfo['entity keys']['revision'])) {
|
||||
|
||||
@@ -69,7 +69,7 @@ function entity_property_info_defaults() {
|
||||
* (optiona) The entity type to return properties for.
|
||||
*
|
||||
* @return
|
||||
* An array of info about properties. If the type is ommitted, all known
|
||||
* An array of info about properties. If the type is omitted, all known
|
||||
* properties are returned.
|
||||
*/
|
||||
function entity_get_all_property_info($entity_type = NULL) {
|
||||
@@ -251,7 +251,11 @@ function entity_property_verify_data_type($data, $type) {
|
||||
return TRUE;
|
||||
}
|
||||
elseif (isset($info[$type]['entity keys']['name'])) {
|
||||
return entity_property_verify_data_type($data, 'token');
|
||||
// Read the data type of the name key from the metadata if available.
|
||||
$key = $info[$type]['entity keys']['name'];
|
||||
$property_info = entity_get_property_info($type);
|
||||
$property_type = isset($property_info['properties'][$key]['type']) ? $property_info['properties'][$key]['type'] : 'token';
|
||||
return entity_property_verify_data_type($data, $property_type);
|
||||
}
|
||||
return entity_property_verify_data_type($data, empty($info[$type]['fieldable']) ? 'text' : 'integer');
|
||||
}
|
||||
@@ -392,7 +396,12 @@ function entity_property_verbatim_get($data, array $options, $name, $type, $info
|
||||
*/
|
||||
function entity_property_verbatim_date_get($data, array $options, $name, $type, $info) {
|
||||
$name = isset($info['schema field']) ? $info['schema field'] : $name;
|
||||
return is_numeric($data[$name]) ? $data[$name] : strtotime($data[$name], REQUEST_TIME);
|
||||
if (is_array($data) || (is_object($data) && $data instanceof ArrayAccess)) {
|
||||
return is_numeric($data[$name]) ? $data[$name] : strtotime($data[$name], REQUEST_TIME);
|
||||
}
|
||||
elseif (is_object($data)) {
|
||||
return is_numeric($data->$name) ? $data->$name : strtotime($data->$name, REQUEST_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -503,6 +512,8 @@ function entity_property_text_formatted_info() {
|
||||
'label' => t('Text format'),
|
||||
'options list' => 'entity_metadata_field_text_formats',
|
||||
'getter callback' => 'entity_property_verbatim_get',
|
||||
'setter callback' => 'entity_property_verbatim_set',
|
||||
'setter permissions' => 'administer filters',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,12 +6,16 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Default controller for providing UI.
|
||||
* Default UI controller providing admin UI.
|
||||
*
|
||||
* This controller suites best for managing configuration entities.
|
||||
* For a controller suiting content entities, see EntityContentUIController.
|
||||
*/
|
||||
class EntityDefaultUIController {
|
||||
|
||||
protected $entityType;
|
||||
protected $entityInfo, $path;
|
||||
protected $id_count;
|
||||
|
||||
/**
|
||||
* Defines the number of entries to show per page in overview table.
|
||||
@@ -30,7 +34,8 @@ class EntityDefaultUIController {
|
||||
*/
|
||||
public function hook_menu() {
|
||||
$items = array();
|
||||
$id_count = count(explode('/', $this->path));
|
||||
// Set this on the object so classes that extend hook_menu() can use it.
|
||||
$this->id_count = count(explode('/', $this->path));
|
||||
$wildcard = isset($this->entityInfo['admin ui']['menu wildcard']) ? $this->entityInfo['admin ui']['menu wildcard'] : '%entity_object';
|
||||
$plural_label = isset($this->entityInfo['plural label']) ? $this->entityInfo['plural label'] : $this->entityInfo['label'] . 's';
|
||||
|
||||
@@ -60,12 +65,12 @@ class EntityDefaultUIController {
|
||||
$items[$this->path . '/manage/' . $wildcard] = array(
|
||||
'title' => 'Edit',
|
||||
'title callback' => 'entity_label',
|
||||
'title arguments' => array($this->entityType, $id_count + 1),
|
||||
'title arguments' => array($this->entityType, $this->id_count + 1),
|
||||
'page callback' => 'entity_ui_get_form',
|
||||
'page arguments' => array($this->entityType, $id_count + 1),
|
||||
'page arguments' => array($this->entityType, $this->id_count + 1),
|
||||
'load arguments' => array($this->entityType),
|
||||
'access callback' => 'entity_access',
|
||||
'access arguments' => array('update', $this->entityType, $id_count + 1),
|
||||
'access arguments' => array('update', $this->entityType, $this->id_count + 1),
|
||||
);
|
||||
$items[$this->path . '/manage/' . $wildcard . '/edit'] = array(
|
||||
'title' => 'Edit',
|
||||
@@ -77,7 +82,7 @@ class EntityDefaultUIController {
|
||||
$items[$this->path . '/manage/' . $wildcard . '/clone'] = array(
|
||||
'title' => 'Clone',
|
||||
'page callback' => 'entity_ui_get_form',
|
||||
'page arguments' => array($this->entityType, $id_count + 1, 'clone'),
|
||||
'page arguments' => array($this->entityType, $this->id_count + 1, 'clone'),
|
||||
'load arguments' => array($this->entityType),
|
||||
'access callback' => 'entity_access',
|
||||
'access arguments' => array('create', $this->entityType),
|
||||
@@ -85,10 +90,10 @@ class EntityDefaultUIController {
|
||||
// Menu item for operations like revert and delete.
|
||||
$items[$this->path . '/manage/' . $wildcard . '/%'] = array(
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array($this->entityType . '_operation_form', $this->entityType, $id_count + 1, $id_count + 2),
|
||||
'page arguments' => array($this->entityType . '_operation_form', $this->entityType, $this->id_count + 1, $this->id_count + 2),
|
||||
'load arguments' => array($this->entityType),
|
||||
'access callback' => 'entity_access',
|
||||
'access arguments' => array('delete', $this->entityType, $id_count + 1),
|
||||
'access arguments' => array('delete', $this->entityType, $this->id_count + 1),
|
||||
'file' => 'includes/entity.ui.inc',
|
||||
);
|
||||
|
||||
@@ -122,8 +127,8 @@ class EntityDefaultUIController {
|
||||
* Use per bundle form ids if possible, such that easy per bundle alterations
|
||||
* are supported too.
|
||||
*
|
||||
* Note that for performance reasons, this method is only invoked for forms,
|
||||
* which receive the entity_type as first argument. Thus any forms added, must
|
||||
* Note that for performance reasons, this method is invoked only for forms
|
||||
* which receive the entity_type as first argument. Thus any forms added must
|
||||
* follow that pattern.
|
||||
*
|
||||
* @see entity_forms()
|
||||
@@ -492,6 +497,128 @@ class EntityDefaultUIController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UI controller providing UI for content entities.
|
||||
*
|
||||
* For a controller providing UI for bundleable content entities, see
|
||||
* EntityBundleableUIController.
|
||||
* For a controller providing admin UI for configuration entities, see
|
||||
* EntityDefaultUIController.
|
||||
*/
|
||||
class EntityContentUIController extends EntityDefaultUIController {
|
||||
|
||||
/**
|
||||
* Provides definitions for implementing hook_menu().
|
||||
*/
|
||||
public function hook_menu() {
|
||||
$items = parent::hook_menu();
|
||||
$wildcard = isset($this->entityInfo['admin ui']['menu wildcard']) ? $this->entityInfo['admin ui']['menu wildcard'] : '%entity_object';
|
||||
|
||||
// Unset the manage entity path, as the provided UI is for admin entities.
|
||||
unset($items[$this->path]);
|
||||
|
||||
$defaults = array(
|
||||
'file' => $this->entityInfo['admin ui']['file'],
|
||||
'file path' => isset($this->entityInfo['admin ui']['file path']) ? $this->entityInfo['admin ui']['file path'] : drupal_get_path('module', $this->entityInfo['module']),
|
||||
);
|
||||
|
||||
// Add view, edit and delete menu items for content entities.
|
||||
$items[$this->path . '/' . $wildcard] = array(
|
||||
'title callback' => 'entity_ui_get_page_title',
|
||||
'title arguments' => array('view', $this->entityType, $this->id_count),
|
||||
'page callback' => 'entity_ui_entity_page_view',
|
||||
'page arguments' => array($this->id_count),
|
||||
'load arguments' => array($this->entityType),
|
||||
'access callback' => 'entity_access',
|
||||
'access arguments' => array('view', $this->entityType, $this->id_count),
|
||||
) + $defaults;
|
||||
$items[$this->path . '/' . $wildcard . '/view'] = array(
|
||||
'title' => 'View',
|
||||
'type' => MENU_DEFAULT_LOCAL_TASK,
|
||||
'load arguments' => array($this->entityType),
|
||||
'weight' => -10,
|
||||
) + $defaults;
|
||||
$items[$this->path . '/' . $wildcard . '/edit'] = array(
|
||||
'page callback' => 'entity_ui_get_form',
|
||||
'page arguments' => array($this->entityType, $this->id_count),
|
||||
'load arguments' => array($this->entityType),
|
||||
'access callback' => 'entity_access',
|
||||
'access arguments' => array('edit', $this->entityType, $this->id_count),
|
||||
'title' => 'Edit',
|
||||
'type' => MENU_LOCAL_TASK,
|
||||
'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
|
||||
) + $defaults;
|
||||
$items[$this->path . '/' . $wildcard . '/delete'] = array(
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array($this->entityType . '_operation_form', $this->entityType, $this->id_count, 'delete'),
|
||||
'load arguments' => array($this->entityType),
|
||||
'access callback' => 'entity_access',
|
||||
'access arguments' => array('delete', $this->entityType, $this->id_count),
|
||||
'title' => 'Delete',
|
||||
'type' => MENU_LOCAL_TASK,
|
||||
'context' => MENU_CONTEXT_INLINE,
|
||||
'file' => $this->entityInfo['admin ui']['file'],
|
||||
'file path' => isset($this->entityInfo['admin ui']['file path']) ? $this->entityInfo['admin ui']['file path'] : drupal_get_path('module', $this->entityInfo['module']),
|
||||
) + $defaults;
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Operation form submit callback.
|
||||
*/
|
||||
public function operationFormSubmit($form, &$form_state) {
|
||||
parent::operationFormSubmit($form, $form_state);
|
||||
// The manage entity path is unset for the content entity UI.
|
||||
$form_state['redirect'] = '<front>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UI controller providing UI for bundleable content entities.
|
||||
*
|
||||
* Adds a bundle selection page to the entity/add path, analogously to the
|
||||
* node/add path.
|
||||
*/
|
||||
class EntityBundleableUIController extends EntityContentUIController {
|
||||
|
||||
/**
|
||||
* Provides definitions for implementing hook_menu().
|
||||
*/
|
||||
public function hook_menu() {
|
||||
$items = parent::hook_menu();
|
||||
|
||||
// Extend the 'add' path.
|
||||
$items[$this->path . '/add'] = array(
|
||||
'title callback' => 'entity_ui_get_action_title',
|
||||
'title arguments' => array('add', $this->entityType),
|
||||
'page callback' => 'entity_ui_bundle_add_page',
|
||||
'page arguments' => array($this->entityType),
|
||||
'access callback' => 'entity_access',
|
||||
'access arguments' => array('create', $this->entityType),
|
||||
'type' => MENU_LOCAL_ACTION,
|
||||
);
|
||||
$items[$this->path . '/add/%'] = array(
|
||||
'title callback' => 'entity_ui_get_action_title',
|
||||
'title arguments' => array('add', $this->entityType, $this->id_count + 1),
|
||||
'page callback' => 'entity_ui_get_bundle_add_form',
|
||||
'page arguments' => array($this->entityType, $this->id_count + 1),
|
||||
'access callback' => 'entity_access',
|
||||
'access arguments' => array('create', $this->entityType),
|
||||
);
|
||||
|
||||
if (!empty($this->entityInfo['admin ui']['file'])) {
|
||||
// Add in the include file for the entity form.
|
||||
foreach (array('/add', '/add/%') as $path_end) {
|
||||
$items[$this->path . $path_end]['file'] = $this->entityInfo['admin ui']['file'];
|
||||
$items[$this->path . $path_end]['file path'] = isset($this->entityInfo['admin ui']['file path']) ? $this->entityInfo['admin ui']['file path'] : drupal_get_path('module', $this->entityInfo['module']);
|
||||
}
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Form builder function for the overview form.
|
||||
*
|
||||
@@ -518,7 +645,7 @@ function entity_ui_operation_form($form, &$form_state, $entity_type, $entity, $o
|
||||
*/
|
||||
function entity_ui_main_form_defaults($form, &$form_state, $entity = NULL, $op = NULL) {
|
||||
// Now equals entity_ui_form_defaults() but is still here to keep backward
|
||||
// compatability.
|
||||
// compatibility.
|
||||
return entity_ui_form_defaults($form, $form_state, $form_state['entity_type'], $entity, $op);
|
||||
}
|
||||
|
||||
@@ -597,39 +724,6 @@ function entity_ui_controller_form_submit($form, &$form_state) {
|
||||
entity_ui_controller($form_state['entity_type'])->$method($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the page title for the passed operation.
|
||||
*/
|
||||
function entity_ui_get_page_title($op, $entity_type, $entity = NULL) {
|
||||
$label = entity_label($entity_type, $entity);
|
||||
switch ($op) {
|
||||
case 'edit':
|
||||
return t('Edit @label', array('@label' => $label));
|
||||
case 'clone':
|
||||
return t('Clone @label', array('@label' => $label));
|
||||
case 'revert':
|
||||
return t('Revert @label', array('@label' => $label));
|
||||
case 'delete':
|
||||
return t('Delete @label', array('@label' => $label));
|
||||
case 'export':
|
||||
return t('Export @label', array('@label' => $label));
|
||||
}
|
||||
return entity_ui_get_action_title($op, $entity_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the page/menu title for local action operations.
|
||||
*/
|
||||
function entity_ui_get_action_title($op, $entity_type) {
|
||||
$info = entity_get_info($entity_type);
|
||||
switch ($op) {
|
||||
case 'add':
|
||||
return t('Add @entity_type', array('@entity_type' => drupal_strtolower($info['label'])));
|
||||
case 'import':
|
||||
return t('Import @entity_type', array('@entity_type' => drupal_strtolower($info['label'])));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit builder for the main entity form, which extracts the form values and updates the entity.
|
||||
*
|
||||
@@ -666,7 +760,8 @@ function entity_ui_validate_machine_name($element, &$form_state) {
|
||||
function theme_entity_ui_overview_item($variables) {
|
||||
$output = $variables['url'] ? l($variables['label'], $variables['url']['path'], $variables['url']['options']) : check_plain($variables['label']);
|
||||
if ($variables['name']) {
|
||||
$output .= ' <small> (' . t('Machine name') . ': ' . check_plain($variables['name']) . ')</small>';
|
||||
$output .= ' <small>(' . t('Machine name') . ': ' . check_plain($variables['name']) . ')</small>';
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +119,11 @@ abstract class EntityMetadataWrapper {
|
||||
*/
|
||||
public function set($value) {
|
||||
if (!$this->validate($value)) {
|
||||
throw new EntityMetadataWrapperException('Invalid data value given. Be sure it matches the required data type and format.');
|
||||
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(),
|
||||
)));
|
||||
}
|
||||
$this->clear();
|
||||
$this->data = $value;
|
||||
@@ -228,13 +232,24 @@ abstract class EntityMetadataWrapper {
|
||||
* If there is no access information for this property, TRUE is returned.
|
||||
*/
|
||||
public function access($op, $account = NULL) {
|
||||
if (empty($this->info['parent']) && $this instanceof EntityDrupalWrapper) {
|
||||
// If there is no parent just incorporate entity based access.
|
||||
return $this->entityAccess($op == 'edit' ? 'update' : 'view', $account);
|
||||
}
|
||||
return !empty($this->info['parent']) ? $this->info['parent']->propertyAccess($this->info['name'], $op, $account) : TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string to use to identify this wrapper in error messages.
|
||||
*
|
||||
* @return
|
||||
* A string that identifies this wrapper and its chain of ancestors, of the
|
||||
* form 'grandparentidentifier->parentidentifier->identifier'.
|
||||
*/
|
||||
public function debugIdentifierLocation() {
|
||||
$debug = $this->info['name'];
|
||||
if (isset($this->info['parent'])) {
|
||||
$debug = $this->info['parent']->debugIdentifierLocation() . '->' . $debug;
|
||||
}
|
||||
return $debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare for serializiation.
|
||||
*/
|
||||
@@ -500,19 +515,15 @@ class EntityStructureWrapper extends EntityMetadataWrapper implements IteratorAg
|
||||
|
||||
protected function propertyAccess($name, $op, $account = NULL) {
|
||||
$info = $this->getPropertyInfo($name);
|
||||
// If the property should be accessed and it's an entity, make sure the user
|
||||
// is allowed to view that entity.
|
||||
if ($op == 'view' && $this->$name instanceof EntityDrupalWrapper && !$this->$name->entityAccess($op, $account)) {
|
||||
return FALSE;
|
||||
}
|
||||
// If a property should be edited and this is an entity, make sure the user
|
||||
// has update access for this entity.
|
||||
|
||||
// If a property should be edited and this is part of an entity, make sure
|
||||
// the user has update access for this entity.
|
||||
if ($op == 'edit') {
|
||||
$entity = $this;
|
||||
while (!($entity instanceof EntityDrupalWrapper) && isset($entity->info['parent'])) {
|
||||
$entity = $entity->info['parent'];
|
||||
}
|
||||
if ($entity instanceof EntityDrupalWrapper && !$entity->entityAccess('update', $account)) {
|
||||
if ($entity instanceof EntityDrupalWrapper && $entity->entityAccess('update', $account) === FALSE) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@@ -523,6 +534,7 @@ class EntityStructureWrapper extends EntityMetadataWrapper implements IteratorAg
|
||||
elseif ($op == 'edit' && isset($info['setter permission'])) {
|
||||
return user_access($info['setter permission'], $account);
|
||||
}
|
||||
// If access is unknown, we return TRUE.
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -662,7 +674,7 @@ class EntityDrupalWrapper extends EntityStructureWrapper {
|
||||
$this->bundle = $this->type;
|
||||
}
|
||||
// Detect the bundle if not set yet and add in properties from the bundle.
|
||||
elseif (!$this->bundle && !empty($this->entityInfo['fieldable']) && $load && $this->dataAvailable()) {
|
||||
elseif (!$this->bundle && $load && $this->dataAvailable()) {
|
||||
try {
|
||||
if ($entity = $this->value()) {
|
||||
list($id, $vid, $bundle) = entity_extract_ids($this->type, $entity);
|
||||
@@ -741,7 +753,11 @@ class EntityDrupalWrapper extends EntityStructureWrapper {
|
||||
*/
|
||||
public function set($value) {
|
||||
if (!$this->validate($value)) {
|
||||
throw new EntityMetadataWrapperException('Invalid data value given. Be sure it matches the required data type and format.');
|
||||
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.
|
||||
@@ -766,7 +782,7 @@ class EntityDrupalWrapper extends EntityStructureWrapper {
|
||||
elseif ($this->id === FALSE && !$this->data) {
|
||||
$this->updateParent(NULL);
|
||||
}
|
||||
elseif ($previous_id != $this->id) {
|
||||
elseif ($previous_id !== $this->id) {
|
||||
$this->updateParent($this->id);
|
||||
}
|
||||
return $this;
|
||||
@@ -804,6 +820,39 @@ class EntityDrupalWrapper extends EntityStructureWrapper {
|
||||
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.
|
||||
*
|
||||
@@ -811,6 +860,12 @@ class EntityDrupalWrapper extends EntityStructureWrapper {
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -882,6 +937,27 @@ class EntityDrupalWrapper extends EntityStructureWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@@ -1025,8 +1101,11 @@ class EntityListWrapper extends EntityMetadataWrapper implements IteratorAggrega
|
||||
// Support setting lists of fully loaded entities.
|
||||
if ($this->isEntityList && $values && is_object(reset($values))) {
|
||||
foreach ($values as $key => $value) {
|
||||
list($id, $vid, $bundle) = entity_extract_ids($this->itemType, $value);
|
||||
$values[$key] = $id;
|
||||
// Ignore outdated NULL value references in lists of entities.
|
||||
if (isset($value)) {
|
||||
list($id, $vid, $bundle) = entity_extract_ids($this->itemType, $value);
|
||||
$values[$key] = $id;
|
||||
}
|
||||
}
|
||||
}
|
||||
return parent::set($values);
|
||||
@@ -1037,7 +1116,7 @@ class EntityListWrapper extends EntityMetadataWrapper implements IteratorAggrega
|
||||
*/
|
||||
public function getIterator() {
|
||||
// In case there is no data available, just iterate over the first item.
|
||||
return new EntityMetadataWrapperIterator($this, $this->dataAvailable() ? array_keys(parent::value()) : array(0));
|
||||
return new EntityMetadataWrapperIterator($this, ($this->dataAvailable() && is_array(parent::value())) ? array_keys(parent::value()) : array(0));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user