diff --git a/sites/all/modules/contrib/dev/entity/README.txt b/sites/all/modules/contrib/dev/entity/README.txt
index ed048e42..745dd7fe 100644
--- a/sites/all/modules/contrib/dev/entity/README.txt
+++ b/sites/all/modules/contrib/dev/entity/README.txt
@@ -11,7 +11,15 @@ entity CRUD controller, which helps simplifying the creation of new entity types
This is an API module. You only need to enable it if a module depends on it or
you are interested in using it for development.
-This README is for interested developers. If you are not interested in
+Advanced usage:
+---------------
+You can optimize cache clearing performance by setting the variable
+'entity_rebuild_on_flush' to FALSE. This skips rebuilding of feature
+components and exported entities during cache flushing. Instead, it is triggered
+by the features module only; e.g., when features are reverted.
+
+
+The README below is for interested developers. If you are not interested in
developing, you may stop reading now.
--------------------------------------------------------------------------------
diff --git a/sites/all/modules/contrib/dev/entity/ctools/relationships/entity_property.inc b/sites/all/modules/contrib/dev/entity/ctools/relationships/entity_property.inc
new file mode 100644
index 00000000..6869146f
--- /dev/null
+++ b/sites/all/modules/contrib/dev/entity/ctools/relationships/entity_property.inc
@@ -0,0 +1,153 @@
+ t('Entity property or field (via Entity Metadata Wrapper)'),
+ 'description' => t('Creates any kind of context for entity properties and fields.'),
+ 'context' => 'entity_entity_property_context',
+ 'required context' => new ctools_context_required(t('Entity'), 'entity'),
+ 'edit form' => 'entity_entity_property_edit_form',
+ 'edit form validate' => 'entity_entity_property_edit_form_validate',
+ 'defaults' => array(
+ 'selector' => '',
+ 'target_context' => 'entity',
+ 'concatenator' => ','
+ ),
+);
+
+/**
+ * Return a new context based on an existing context.
+ */
+function entity_entity_property_context($context, $conf) {
+ $plugin = $conf['name'];
+
+ // If unset it wants a generic, unfilled context, which is just NULL.
+ if (empty($context->data)) {
+ return ctools_context_create_empty(isset($conf['target_context']) ? $conf['target_context'] : 'entity', NULL);
+ }
+
+ list($part1, $entity_type) = explode(':', $context->plugin);
+
+ if (isset($context->data) && $entity = $context->data) {
+ // Apply the selector.
+ $wrapper = entity_metadata_wrapper($entity_type, $entity);
+ $parts = explode(':', $conf['selector']);
+
+ try {
+ foreach ($parts as $part) {
+ if (!($wrapper instanceof EntityStructureWrapper || $wrapper instanceof EntityListWrapper)) {
+ $wrapper = NULL;
+ $value = NULL;
+ continue;
+ }
+ $wrapper = $wrapper->get($part);
+ }
+ }
+ catch (EntityMetadataWrapperException $e) {
+ $wrapper = NULL;
+ $value = NULL;
+ }
+
+ if (isset($wrapper)) {
+ $value = $wrapper->value();
+ }
+
+ // Massage list values.
+ if ($wrapper instanceof EntityListWrapper) {
+ $value = $wrapper[0]->value();
+ $argument = implode($conf['concatenator'], $wrapper->value(array('identifier' => TRUE)));
+ }
+ elseif ($wrapper instanceof EntityDrupalWrapper) {
+ $argument = $wrapper->getIdentifier();
+ }
+
+ // Bail out if we were unable to retrieve the value.
+ if (!isset($value)) {
+ return ctools_context_create_empty(isset($conf['target_context']) ? $conf['target_context'] : 'entity', NULL);
+ }
+
+ $context = ctools_context_create($conf['target_context'], $value);
+ // Provide a suiting argument if context is used as argument.
+ if (isset($argument)) {
+ $context->argument = $argument;
+ }
+ return $context;
+ }
+}
+
+function entity_entity_property_edit_form($form, &$form_state) {
+ $conf = $form_state['conf'];
+
+ $form['selector'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Data selector'),
+ '#description' => t('Any valid data selector, e.g. "title" to select a node\'s title, or "field_tags:1" to select the second tag.'),
+ '#default_value' => $conf['selector'],
+ '#required' => TRUE,
+ );
+ $form['concatenator'] = array(
+ '#title' => t('Concatenator (if multiple)'),
+ '#type' => 'select',
+ '#options' => array(',' => ', (AND)', '+' => '+ (OR)'),
+ '#default_value' => $conf['concatenator'],
+ '#prefix' => '
',
+ '#suffix' => '
',
+ '#description' => t("When the resulting value is multiple valued and the context is passed on to a view as argument, the value can be concatenated in the form of 1+2+3 (for OR) or 1,2,3 (for AND)."),
+ );
+ return $form;
+}
+
+function entity_entity_property_edit_form_validate($form, &$form_state) {
+ $context_key = $form_state['values']['context'];
+ $context = $form_state['contexts'][$context_key];
+ $entity_type = $context->type[2];
+
+ try {
+ $all_properties = entity_get_all_property_info($entity_type);
+ $wrapper = entity_metadata_wrapper($entity_type, NULL, array('property info' => $all_properties));
+ $parts = explode(':', $form_state['values']['selector']);
+ foreach ($parts as $part) {
+ if (!($wrapper instanceof EntityStructureWrapper || $wrapper instanceof EntityListWrapper)) {
+ form_set_error('selector', t('Unable to apply the data selector part %key.'. array('%key' => $part)));
+ continue;
+ }
+ $wrapper = $wrapper->get($part);
+ }
+ $type = entity_entity_property_map_data_type($wrapper->type());
+ $form_state['conf']['target_context'] = $type;
+ }
+ catch (EntityMetadataWrapperException $e) {
+ form_set_error('selector', t('Unable to apply the data selector on entity type %type. @reason', array('@reason' => $e->getMessage(), '%type' => $entity_type)));
+ }
+
+ // Auto-generate a sane identifier.
+ if ($form_state['values']['identifier'] == $form['identifier']['#default_value']) {
+ $form_state['values']['identifier'] = 'Entity property ' . $entity_type . ':' . check_plain($form_state['values']['selector']);
+ }
+}
+
+/**
+ * Maps an entity-property data type to ctools types.
+ */
+function entity_entity_property_map_data_type($type) {
+ // Remove list<> wrappers from types.
+ while ($item_type = entity_property_list_extract_type($type)) {
+ $type = $item_type;
+ }
+ // Massage data type of entites to c
+ if (entity_get_info($type)) {
+ $type = "entity:$type";
+ }
+ if ($type == 'text') {
+ $type = 'string';
+ }
+ return $type;
+}
diff --git a/sites/all/modules/contrib/dev/entity/entity.features.inc b/sites/all/modules/contrib/dev/entity/entity.features.inc
index e266aaf5..0ec3e618 100644
--- a/sites/all/modules/contrib/dev/entity/entity.features.inc
+++ b/sites/all/modules/contrib/dev/entity/entity.features.inc
@@ -7,6 +7,12 @@
/**
* Returns the configured entity features controller.
+ *
+ * @param string $type
+ * The entity type to get the controller for.
+ *
+ * @return EntityDefaultFeaturesController
+ * The configured entity features controller.
*/
function entity_features_get_controller($type) {
$static = &drupal_static(__FUNCTION__);
@@ -85,6 +91,7 @@ class EntityDefaultFeaturesController {
$fields = field_info_instances($this->info['bundle of'], $entity->{$this->bundleKey});
foreach ($fields as $name => $field) {
$pipe['field'][] = "{$field['entity_type']}-{$field['bundle']}-{$field['field_name']}";
+ $pipe['field_instance'][] = "{$field['entity_type']}-{$field['bundle']}-{$field['field_name']}";
}
}
}
@@ -125,9 +132,7 @@ class EntityDefaultFeaturesController {
*/
function revert($module = NULL) {
if ($defaults = features_get_default($this->type, $module)) {
- foreach ($defaults as $name => $entity) {
- entity_delete($this->type, $name);
- }
+ entity_delete_multiple($this->type, array_keys($defaults));
}
}
}
@@ -146,6 +151,8 @@ function entity_features_api() {
}
/**
+ * Implements hook_features_export_options().
+ *
* Features component callback.
*/
function entity_features_export_options($a1, $a2 = NULL) {
@@ -157,6 +164,8 @@ function entity_features_export_options($a1, $a2 = NULL) {
}
/**
+ * Implements hook_features_export().
+ *
* Features component callback.
*/
function entity_features_export($data, &$export, $module_name = '', $entity_type) {
@@ -164,6 +173,8 @@ function entity_features_export($data, &$export, $module_name = '', $entity_type
}
/**
+ * Implements hook_features_export_render().
+ *
* Features component callback.
*/
function entity_features_export_render($module, $data, $export = NULL, $entity_type) {
@@ -171,8 +182,23 @@ function entity_features_export_render($module, $data, $export = NULL, $entity_t
}
/**
+ * Implements hook_features_revert().
+ *
* Features component callback.
*/
function entity_features_revert($module = NULL, $entity_type) {
return entity_features_get_controller($entity_type)->revert($module);
}
+
+/**
+ * Implements hook_features_post_restore().
+ *
+ * Rebuild all defaults when a features rebuild is triggered - even the ones not
+ * handled by features itself.
+ */
+function entity_features_post_restore($op, $items = array()) {
+ if ($op == 'rebuild') {
+ // Use features rebuild to rebuild the features independent exports too.
+ entity_defaults_rebuild();
+ }
+}
diff --git a/sites/all/modules/contrib/dev/entity/entity.info b/sites/all/modules/contrib/dev/entity/entity.info
index ff88ce54..787db138 100644
--- a/sites/all/modules/contrib/dev/entity/entity.info
+++ b/sites/all/modules/contrib/dev/entity/entity.info
@@ -25,9 +25,9 @@ files[] = views/handlers/entity_views_handler_field_uri.inc
files[] = views/handlers/entity_views_handler_relationship_by_bundle.inc
files[] = views/handlers/entity_views_handler_relationship.inc
files[] = views/plugins/entity_views_plugin_row_entity_view.inc
-; Information added by Drupal.org packaging script on 2015-02-25
-version = "7.x-1.6"
+; Information added by Drupal.org packaging script on 2016-09-22
+version = "7.x-1.8"
core = "7.x"
project = "entity"
-datestamp = "1424876582"
+datestamp = "1474546503"
diff --git a/sites/all/modules/contrib/dev/entity/entity.install b/sites/all/modules/contrib/dev/entity/entity.install
index f6f8cc2f..118820b8 100644
--- a/sites/all/modules/contrib/dev/entity/entity.install
+++ b/sites/all/modules/contrib/dev/entity/entity.install
@@ -13,6 +13,14 @@ function entity_enable() {
entity_entitycache_installed_modules();
}
+/**
+ * Implements hook_uninstall().
+ */
+function entity_uninstall() {
+ // Delete variables.
+ variable_del('entity_rebuild_on_flush');
+}
+
/**
* The entity API modules have been merged into a single module.
*/
diff --git a/sites/all/modules/contrib/dev/entity/entity.module b/sites/all/modules/contrib/dev/entity/entity.module
index d4a882cd..d00afa46 100644
--- a/sites/all/modules/contrib/dev/entity/entity.module
+++ b/sites/all/modules/contrib/dev/entity/entity.module
@@ -184,8 +184,17 @@ function entity_ui_entity_page_view($entity) {
* Gets the page title for the passed operation.
*/
function entity_ui_get_page_title($op, $entity_type, $entity = NULL) {
- module_load_include('inc', 'entity', 'includes/entity.ui');
- $label = entity_label($entity_type, $entity);
+ if (isset($entity)) {
+ module_load_include('inc', 'entity', 'includes/entity.ui');
+ $label = entity_label($entity_type, $entity);
+ list(, , $bundle) = entity_extract_ids($entity_type, $entity);
+ }
+ else {
+ $info = entity_get_info($entity_type);
+ $label = $info['label'];
+ $bundle = NULL;
+ }
+
switch ($op) {
case 'view':
return $label;
@@ -200,12 +209,7 @@ function entity_ui_get_page_title($op, $entity_type, $entity = NULL) {
case 'export':
return t('Export @label', array('@label' => $label));
}
- if (isset($entity)) {
- list(, , $bundle) = entity_extract_ids($entity_type, $entity);
- }
- else {
- $bundle = NULL;
- }
+
return entity_ui_get_action_title($op, $entity_type, $bundle);
}
@@ -600,7 +604,7 @@ function entity_id($entity_type, $entity) {
* 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
@@ -1076,7 +1080,8 @@ function entity_flush_caches() {
// case of enabling or disabling modules we already rebuild defaults in
// entity_modules_enabled() and entity_modules_disabled(), so we do not need
// to do it again.
- if (current_path() != 'admin/modules/list/confirm') {
+ // Also check if rebuilding on cache flush is explicitly disabled.
+ if (current_path() != 'admin/modules/list/confirm' && variable_get('entity_rebuild_on_flush', TRUE)) {
entity_defaults_rebuild();
}
@@ -1372,7 +1377,7 @@ function entity_get_extra_fields_controller($type = NULL) {
* Returns a property wrapper for the given data.
*
* If an entity is wrapped, the wrapper can be used to retrieve further wrappers
- * for the entitity properties. For that the wrapper support chaining, e.g. you
+ * for the entity properties. For that the wrapper support chaining, e.g. you
* can use a node wrapper to get the node authors mail address:
*
* @code
@@ -1563,7 +1568,7 @@ function _entity_info_add_metadata(&$entity_info) {
* Implements hook_ctools_plugin_directory().
*/
function entity_ctools_plugin_directory($module, $plugin) {
- if ($module == 'ctools' && $plugin == 'content_types') {
- return 'ctools/content_types';
+ if ($module == 'ctools') {
+ return "ctools/$plugin";
}
}
diff --git a/sites/all/modules/contrib/dev/entity/entity.test b/sites/all/modules/contrib/dev/entity/entity.test
index 03c2551a..fd8cea12 100644
--- a/sites/all/modules/contrib/dev/entity/entity.test
+++ b/sites/all/modules/contrib/dev/entity/entity.test
@@ -1342,6 +1342,74 @@ class EntityMetadataNodeRevisionAccessTestCase extends DrupalWebTestCase {
}
}
+/**
+ * Tests basic entity_access() functionality for taxonomy terms.
+ */
+class EntityMetadataTaxonomyAccessTestCase extends EntityWebTestCase {
+ public static function getInfo() {
+ return array(
+ 'name' => 'Entity Metadata Taxonomy Access',
+ 'description' => 'Test entity_access() for taxonomy terms',
+ 'group' => 'Entity API',
+ );
+ }
+
+ /**
+ * Asserts entity_access() correctly grants or denies access.
+ */
+ function assertTaxonomyMetadataAccess($ops, $term, $account) {
+ foreach ($ops as $op => $result) {
+ $msg = t("entity_access() returns @result with operation '@op'.", array('@result' => $result ? 'TRUE' : 'FALSE', '@op' => $op));
+ $access = entity_access($op, 'taxonomy_term', $term, $account);
+ $this->assertEqual($result, $access, $msg);
+ }
+ }
+
+ /**
+ * @inheritdoc
+ */
+ function setUp() {
+ parent::setUp('entity', 'taxonomy');
+ // Clear permissions for authenticated users.
+ db_delete('role_permission')
+ ->condition('rid', DRUPAL_AUTHENTICATED_RID)
+ ->execute();
+ }
+
+ /**
+ * Runs basic tests for entity_access() function.
+ */
+ function testTaxonomyMetadataAccess() {
+ $vocab = $this->createVocabulary();
+ $term = entity_property_values_create_entity('taxonomy_term', array(
+ 'name' => $this->randomName(),
+ 'vocabulary' => $vocab,
+ ))->save()->value();
+ // Clear permissions static cache to get new taxonomy permissions.
+ drupal_static_reset('checkPermissions');
+
+ // Check assignment of view permissions.
+ $user1 = $this->drupalCreateUser(array('access content'));
+ $this->assertTaxonomyMetadataAccess(array('create' => FALSE, 'view' => TRUE, 'update' => FALSE, 'delete' => FALSE), $term, $user1);
+
+ // Check assignment of edit permissions.
+ $user2 = $this->drupalCreateUser(array('edit terms in ' . $vocab->vid));
+ $this->assertTaxonomyMetadataAccess(array('create' => FALSE, 'view' => FALSE, 'update' => TRUE, 'delete' => FALSE), $term, $user2);
+
+ // Check assignment of delete permissions.
+ $user3 = $this->drupalCreateUser(array('delete terms in ' . $vocab->vid));
+ $this->assertTaxonomyMetadataAccess(array('create' => FALSE, 'view' => FALSE, 'update' => FALSE, 'delete' => TRUE), $term, $user3);
+
+ // Check assignment of view, edit, delete permissions.
+ $user4 = $this->drupalCreateUser(array('access content', 'edit terms in ' . $vocab->vid, 'delete terms in ' . $vocab->vid));
+ $this->assertTaxonomyMetadataAccess(array('create' => FALSE, 'view' => TRUE, 'update' => TRUE, 'delete' => TRUE), $term, $user4);
+
+ // Check assignment of administration permissions.
+ $user5 = $this->drupalCreateUser(array('administer taxonomy'));
+ $this->assertTaxonomyMetadataAccess(array('create' => TRUE, 'view' => TRUE, 'update' => TRUE, 'delete' => TRUE), $term, $user5);
+ }
+}
+
/**
* Tests provided entity property info of the core modules.
*/
@@ -1466,6 +1534,7 @@ class EntityMetadataIntegrationTestCase extends EntityWebTestCase {
$book = array('bid' => $node->nid, 'plid' => $node->book['mlid']);
$node2 = $this->drupalCreateNode(array('type' => 'book', 'book' => $book));
$node3 = $this->drupalCreateNode(array('type' => 'page'));
+ $node4 = $this->drupalCreateNode(array('type' => 'book', 'book' => array('bid' => 0, 'plid' => -1)));
// Test whether the properties work.
$wrapper = entity_metadata_wrapper('node', $node2);
@@ -1477,6 +1546,10 @@ class EntityMetadataIntegrationTestCase extends EntityWebTestCase {
$wrapper = entity_metadata_wrapper('node', $node3);
$this->assertEmpty($wrapper, 'book');
$this->assertEmptyArray($wrapper, 'book_ancestors');
+
+ // Test a book node which is not contained in a hierarchy.
+ $wrapper = entity_metadata_wrapper('node', $node4);
+ $this->assertEmptyArray($wrapper, 'book_ancestors');
}
/**
diff --git a/sites/all/modules/contrib/dev/entity/entity_token.info b/sites/all/modules/contrib/dev/entity/entity_token.info
index b579ced1..cc732945 100644
--- a/sites/all/modules/contrib/dev/entity/entity_token.info
+++ b/sites/all/modules/contrib/dev/entity/entity_token.info
@@ -5,9 +5,9 @@ files[] = entity_token.tokens.inc
files[] = entity_token.module
dependencies[] = entity
-; Information added by Drupal.org packaging script on 2015-02-25
-version = "7.x-1.6"
+; Information added by Drupal.org packaging script on 2016-09-22
+version = "7.x-1.8"
core = "7.x"
project = "entity"
-datestamp = "1424876582"
+datestamp = "1474546503"
diff --git a/sites/all/modules/contrib/dev/entity/includes/entity.controller.inc b/sites/all/modules/contrib/dev/entity/includes/entity.controller.inc
index f675a63a..5e86b529 100644
--- a/sites/all/modules/contrib/dev/entity/includes/entity.controller.inc
+++ b/sites/all/modules/contrib/dev/entity/includes/entity.controller.inc
@@ -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
diff --git a/sites/all/modules/contrib/dev/entity/includes/entity.inc b/sites/all/modules/contrib/dev/entity/includes/entity.inc
index be24499d..2f504f36 100644
--- a/sites/all/modules/contrib/dev/entity/includes/entity.inc
+++ b/sites/all/modules/contrib/dev/entity/includes/entity.inc
@@ -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,7 +187,7 @@
* public $count = 0;
* @endcode
*/
-class Entity {
+class Entity implements EntityInterface {
protected $entityType;
protected $entityInfo;
@@ -34,9 +196,7 @@ class Entity {
protected $wrapper;
/**
- * Creates a new entity.
- *
- * @see entity_create()
+ * {@inheritdoc}
*/
public function __construct(array $values = array(), $entityType = NULL) {
if (empty($entityType)) {
@@ -61,62 +221,42 @@ class Entity {
}
/**
- * 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 EntityMetadataWrapper of the entity.
- *
- * @return EntityDrupalWrapper
- * An EntityMetadataWrapper containing the entity.
+ * {@inheritdoc}
*/
public function wrapper() {
if (empty($this->wrapper)) {
@@ -130,12 +270,7 @@ class Entity {
}
/**
- * 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 label() {
// If the default label flag is enabled, this is being invoked recursively.
@@ -165,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') {
@@ -188,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'])) {
@@ -207,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();
@@ -228,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);
@@ -296,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'])) {
diff --git a/sites/all/modules/contrib/dev/entity/includes/entity.property.inc b/sites/all/modules/contrib/dev/entity/includes/entity.property.inc
index 38e4fd7b..e8714e67 100644
--- a/sites/all/modules/contrib/dev/entity/includes/entity.property.inc
+++ b/sites/all/modules/contrib/dev/entity/includes/entity.property.inc
@@ -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) {
diff --git a/sites/all/modules/contrib/dev/entity/includes/entity.ui.inc b/sites/all/modules/contrib/dev/entity/includes/entity.ui.inc
index 1826da40..24e3c2b9 100644
--- a/sites/all/modules/contrib/dev/entity/includes/entity.ui.inc
+++ b/sites/all/modules/contrib/dev/entity/includes/entity.ui.inc
@@ -127,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()
@@ -645,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);
}
@@ -760,7 +760,7 @@ 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 .= ' (' . t('Machine name') . ': ' . check_plain($variables['name']) . ')';
+ $output .= ' (' . t('Machine name') . ': ' . check_plain($variables['name']) . ')';
}
return $output;
}
diff --git a/sites/all/modules/contrib/dev/entity/includes/entity.wrapper.inc b/sites/all/modules/contrib/dev/entity/includes/entity.wrapper.inc
index 06b89adf..6c262e69 100644
--- a/sites/all/modules/contrib/dev/entity/includes/entity.wrapper.inc
+++ b/sites/all/modules/contrib/dev/entity/includes/entity.wrapper.inc
@@ -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) : $value,
+ '!location' => $this->debugIdentifierLocation(),
+ )));
}
$this->clear();
$this->data = $value;
@@ -231,6 +235,21 @@ abstract class EntityMetadataWrapper {
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.
*/
@@ -734,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) : $value,
+ '!location' => $this->debugIdentifierLocation(),
+ )));
}
if ($this->info['type'] == 'entity' && $value === $this) {
// Nothing to do.
@@ -821,7 +844,12 @@ class EntityDrupalWrapper extends EntityStructureWrapper {
}
else {
// This is not a property, so fallback on entity access.
- return $this->entityAccess($op == 'edit' ? 'update' : 'view', $account);
+ 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);
}
}
@@ -909,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.
*/
diff --git a/sites/all/modules/contrib/dev/entity/modules/callbacks.inc b/sites/all/modules/contrib/dev/entity/modules/callbacks.inc
index 26f802e6..0c5c8eef 100644
--- a/sites/all/modules/contrib/dev/entity/modules/callbacks.inc
+++ b/sites/all/modules/contrib/dev/entity/modules/callbacks.inc
@@ -29,7 +29,7 @@ function entity_metadata_book_get_properties($node, array $options, $name, $enti
case 'book_ancestors':
$ancestors = array();
- while (!empty($node->book['plid'])) {
+ while (!empty($node->book['plid']) && $node->book['plid'] != -1) {
$link = book_link_load($node->book['plid']);
array_unshift($ancestors, $link['nid']);
$node = node_load($link['nid']);
@@ -670,9 +670,11 @@ function entity_metadata_field_file_validate_item($items, $context) {
function entity_metadata_no_hook_node_access($op, $node = NULL, $account = NULL) {
// First deal with the case where a $node is provided.
if (isset($node)) {
- if ($op == 'create') {
+ if (empty($node->vid) && in_array($op, array('create', 'update'))) {
+ // This is a new node or the original node.
if (isset($node->type)) {
- return node_access($op, $node->type, $account);
+ $op = !empty($node->is_new) && $node->is_new ? 'create' : 'update';
+ return node_access($op, $op == 'create' ? $node->type : $node, $account);
}
else {
throw new EntityMalformedException('Permission to create a node was requested but no node type was given.');
@@ -796,14 +798,35 @@ function entity_metadata_comment_properties_access($op, $property, $entity = NUL
* Access callback for the taxonomy entities.
*/
function entity_metadata_taxonomy_access($op, $entity = NULL, $account = NULL, $entity_type = NULL) {
- if ($entity_type == 'taxonomy_vocabulary') {
- return user_access('administer taxonomy', $account);
- }
- if (isset($entity) && $op == 'update' && !isset($account) && taxonomy_term_edit_access($entity)) {
+ // If user has administer taxonomy permission then no further checks.
+ if (user_access('administer taxonomy', $account)) {
return TRUE;
}
- if (user_access('administer taxonomy', $account) || user_access('access content', $account) && $op == 'view') {
- return TRUE;
+ switch ($op) {
+ case "view":
+ if (user_access('access content', $account)) {
+ return TRUE;
+ }
+ break;
+ case "update":
+ if ($entity_type == 'taxonomy_term') {
+ return user_access("edit terms in $entity->vid", $account);
+ }
+ break;
+ case "create":
+ if ($entity_type == 'taxonomy_term') {
+ // Check for taxonomy_access_fix contrib module which adds additional
+ // permissions to create new terms in a given vocabulary.
+ if (function_exists('taxonomy_access_fix_access')) {
+ return taxonomy_access_fix_access('add terms', $entity->vocabulary_machine_name);
+ }
+ }
+ break;
+ case "delete":
+ if ($entity_type == 'taxonomy_term') {
+ return user_access("delete terms in $entity->vid", $account);
+ }
+ break;
}
return FALSE;
}
diff --git a/sites/all/modules/contrib/dev/entity/modules/node.info.inc b/sites/all/modules/contrib/dev/entity/modules/node.info.inc
index 3512d9a0..f146a7e8 100644
--- a/sites/all/modules/contrib/dev/entity/modules/node.info.inc
+++ b/sites/all/modules/contrib/dev/entity/modules/node.info.inc
@@ -163,4 +163,10 @@ function entity_metadata_node_entity_property_info_alter(&$info) {
'auto creation' => 'entity_property_create_array',
'field' => TRUE,
);
+
+ // Make it a list if cardinality is not 1.
+ $field_body = field_info_field('body');
+ if (isset($field_body) && $field_body['cardinality'] != 1) {
+ $info['node']['properties']['body']['type'] = 'list';
+ }
}
diff --git a/sites/all/modules/contrib/dev/entity/tests/entity_feature.info b/sites/all/modules/contrib/dev/entity/tests/entity_feature.info
index 80d2a908..3e398961 100644
--- a/sites/all/modules/contrib/dev/entity/tests/entity_feature.info
+++ b/sites/all/modules/contrib/dev/entity/tests/entity_feature.info
@@ -6,9 +6,9 @@ files[] = entity_feature.module
dependencies[] = entity_test
hidden = TRUE
-; Information added by Drupal.org packaging script on 2015-02-25
-version = "7.x-1.6"
+; Information added by Drupal.org packaging script on 2016-09-22
+version = "7.x-1.8"
core = "7.x"
project = "entity"
-datestamp = "1424876582"
+datestamp = "1474546503"
diff --git a/sites/all/modules/contrib/dev/entity/tests/entity_test.info b/sites/all/modules/contrib/dev/entity/tests/entity_test.info
index d34326c9..f1562ac6 100644
--- a/sites/all/modules/contrib/dev/entity/tests/entity_test.info
+++ b/sites/all/modules/contrib/dev/entity/tests/entity_test.info
@@ -7,9 +7,9 @@ files[] = entity_test.install
dependencies[] = entity
hidden = TRUE
-; Information added by Drupal.org packaging script on 2015-02-25
-version = "7.x-1.6"
+; Information added by Drupal.org packaging script on 2016-09-22
+version = "7.x-1.8"
core = "7.x"
project = "entity"
-datestamp = "1424876582"
+datestamp = "1474546503"
diff --git a/sites/all/modules/contrib/dev/entity/tests/entity_test.module b/sites/all/modules/contrib/dev/entity/tests/entity_test.module
index 55855688..727797ae 100644
--- a/sites/all/modules/contrib/dev/entity/tests/entity_test.module
+++ b/sites/all/modules/contrib/dev/entity/tests/entity_test.module
@@ -2,7 +2,7 @@
/**
* @file
- * Test moduel for the entity API.
+ * Test module for the entity API.
*/
/**
diff --git a/sites/all/modules/contrib/dev/entity/tests/entity_test_i18n.info b/sites/all/modules/contrib/dev/entity/tests/entity_test_i18n.info
index 8adf04af..db1eb56a 100644
--- a/sites/all/modules/contrib/dev/entity/tests/entity_test_i18n.info
+++ b/sites/all/modules/contrib/dev/entity/tests/entity_test_i18n.info
@@ -5,9 +5,9 @@ dependencies[] = i18n_string
package = Multilingual - Internationalization
core = 7.x
hidden = TRUE
-; Information added by Drupal.org packaging script on 2015-02-25
-version = "7.x-1.6"
+; Information added by Drupal.org packaging script on 2016-09-22
+version = "7.x-1.8"
core = "7.x"
project = "entity"
-datestamp = "1424876582"
+datestamp = "1474546503"
diff --git a/sites/all/modules/contrib/dev/entity/theme/entity.theme.inc b/sites/all/modules/contrib/dev/entity/theme/entity.theme.inc
index 9238dfdb..fc0ba7c1 100644
--- a/sites/all/modules/contrib/dev/entity/theme/entity.theme.inc
+++ b/sites/all/modules/contrib/dev/entity/theme/entity.theme.inc
@@ -80,9 +80,12 @@ function template_preprocess_entity_property(&$variables, $hook) {
);
// Populate the content with sensible defaults.
- if (!isset($variables['content'])) {
+ if (!isset($element['#content'])) {
$variables['content'] = entity_property_default_render_value_by_type($element['#entity_wrapped']->{$element['#property_name']});
}
+ else {
+ $variables['content'] = $element['#content'];
+ }
}
/**
diff --git a/sites/all/modules/contrib/dev/entity/views/entity.views.inc b/sites/all/modules/contrib/dev/entity/views/entity.views.inc
index 59ebaa48..a0179c0c 100644
--- a/sites/all/modules/contrib/dev/entity/views/entity.views.inc
+++ b/sites/all/modules/contrib/dev/entity/views/entity.views.inc
@@ -605,6 +605,28 @@ class EntityDefaultViewsController {
);
break;
+ case 'duration':
+ $return += $description + array(
+ 'field' => array(
+ 'real field' => $views_field_name,
+ 'handler' => 'entity_views_handler_field_duration',
+ 'click sortable' => TRUE,
+ ),
+ 'sort' => array(
+ 'real field' => $views_field_name,
+ 'handler' => 'views_handler_sort',
+ ),
+ 'filter' => array(
+ 'real field' => $views_field_name,
+ 'handler' => 'views_handler_filter_numeric',
+ ),
+ 'argument' => array(
+ 'real field' => $views_field_name,
+ 'handler' => 'views_handler_argument_numeric',
+ ),
+ );
+ break;
+
case 'uri':
$return += $description + array(
'field' => array(
diff --git a/sites/all/modules/contrib/dev/entity/views/handlers/entity_views_field_handler_helper.inc b/sites/all/modules/contrib/dev/entity/views/handlers/entity_views_field_handler_helper.inc
index 0077f4a3..6bb4fbff 100644
--- a/sites/all/modules/contrib/dev/entity/views/handlers/entity_views_field_handler_helper.inc
+++ b/sites/all/modules/contrib/dev/entity/views/handlers/entity_views_field_handler_helper.inc
@@ -18,7 +18,7 @@ class EntityFieldHandlerHelper {
* Provide appropriate default options for a handler.
*/
public static function option_definition($handler) {
- if (entity_property_list_extract_type($handler->definition['type'])) {
+ if (isset($handler->definition['type']) && entity_property_list_extract_type($handler->definition['type'])) {
$options['list']['contains']['mode'] = array('default' => 'collapse');
$options['list']['contains']['separator'] = array('default' => ', ');
$options['list']['contains']['type'] = array('default' => 'ul');
@@ -32,7 +32,7 @@ class EntityFieldHandlerHelper {
* Provide an appropriate default option form for a handler.
*/
public static function options_form($handler, &$form, &$form_state) {
- if (entity_property_list_extract_type($handler->definition['type'])) {
+ if (isset($handler->definition['type']) && entity_property_list_extract_type($handler->definition['type'])) {
$form['list']['mode'] = array(
'#type' => 'select',
'#title' => t('List handling'),
diff --git a/sites/all/modules/contrib/dev/entity/views/plugins/entity_views_plugin_row_entity_view.inc b/sites/all/modules/contrib/dev/entity/views/plugins/entity_views_plugin_row_entity_view.inc
index db72b5f5..5e738a8c 100644
--- a/sites/all/modules/contrib/dev/entity/views/plugins/entity_views_plugin_row_entity_view.inc
+++ b/sites/all/modules/contrib/dev/entity/views/plugins/entity_views_plugin_row_entity_view.inc
@@ -88,6 +88,9 @@ class entity_views_plugin_row_entity_view extends views_plugin_row {
public function render($values) {
if ($entity = $this->get_value($values)) {
+ // Add the view object as views_plugin_row_node_view::render() would.
+ // Otherwise the views theme suggestions won't work properly.
+ $entity->view = $this->view;
$render = $this->rendered_content[entity_id($this->entity_type, $entity)];
return drupal_render($render);
}