- <?php
- * @file
- * Entity API for handling entities like nodes or users.
- */
-
- * Implements hook_modules_preenable().
- */
- function entity_modules_preenable() {
- entity_info_cache_clear();
- }
-
- * Implements hook_modules_disabled().
- */
- function entity_modules_disabled() {
- entity_info_cache_clear();
- }
-
- * Implements hook_modules_uninstalled().
- */
- function entity_modules_uninstalled($modules) {
-
-
- backdrop_register_shutdown_function('entity_info_cache_clear');
- }
-
- * Implements hook_flush_caches().
- */
- function entity_flush_caches() {
- $bins = array();
-
- $entities = entity_get_info();
- foreach ($entities as $type => $info) {
- if (isset($info['entity cache']) && $info['entity cache']) {
- $bins[] = 'cache_entity_' . $type;
- }
- }
-
- return $bins;
- }
-
- * Load a custom entity display mode by entity type and machine name.
- *
- * @param string $entity_type
- * The entity type of the display mode to be loaded, such as "node", "comment",
- * "user", or "taxonomy_term".
- * @param string $machine_name
- * Machine name of display mode.
- *
- * @return FALSE|array
- * Array representing the loaded display mode, or FALSE if not found.
- */
- function entity_view_mode_load($entity_type, $machine_name) {
- $view_modes = config_get('entity.view_modes', 'view_modes');
-
- if (!empty($view_modes[$entity_type][$machine_name])) {
-
- return $view_modes[$entity_type][$machine_name] + array('machine_name' => $machine_name);
- }
- else {
- $entity_info = entity_get_info($entity_type);
- if (!empty($entity_info['view modes'][$machine_name])) {
- return $entity_info['view modes'][$machine_name] + array('machine_name' => $machine_name);
- }
- }
-
- return FALSE;
- }
-
- * Save a custom display mode.
- *
- * @param string $entity_type
- * The entity type of the display mode to be saved, such as "node", "comment",
- * "user", or "taxonomy_term".
- * @param array $view_mode
- * Fully loaded display mode, ready for saving.
- */
- function entity_view_mode_save($entity_type, $view_mode) {
- $view_mode_name = $view_mode['machine_name'];
-
-
- if ($original = entity_view_mode_load($entity_type, $view_mode_name)) {
- $view_mode['original'] = $original;
- }
-
-
- if (!isset($view_mode['is_new'])) {
- $view_mode['is_new'] = empty($view_mode['original']);
- }
-
-
- $view_mode_invoke = module_invoke_all('entity_view_mode_presave', $view_mode, $entity_type);
- if (isset($view_mode_invoke)) {
- $view_mode = array_merge($view_mode, $view_mode_invoke);
- }
-
-
- $view_modes = config_get('entity.view_modes', 'view_modes');
- $view_modes[$entity_type][$view_mode_name] = array('label' => $view_mode['label']);
- config_set('entity.view_modes', 'view_modes', $view_modes);
-
-
- if ($view_mode['is_new']) {
- module_invoke_all('entity_view_mode_insert', $view_mode, $entity_type);
- }
- else {
- module_invoke_all('entity_view_mode_update', $view_mode, $entity_type);
- }
-
-
- unset($view_mode['original']);
- unset($view_mode['is_new']);
-
-
- entity_info_cache_clear();
- state_set('menu_rebuild_needed', TRUE);
- }
-
- * Delete a custom display mode.
- *
- * @param string $entity_type
- * The entity type of the display mode to be deleted, such as "node", "comment",
- * "user", or "taxonomy_term".
- * @param string $machine_name
- * Machine name of display mode.
- */
- function entity_view_mode_delete($entity_type, $machine_name) {
- if ($view_mode = entity_view_mode_load($entity_type, $machine_name)) {
- module_invoke_all('entity_view_mode_delete', $view_mode, $entity_type);
-
- $config = config('entity.view_modes');
- $view_modes = $config->get('view_modes');
- unset($view_modes[$entity_type][$machine_name]);
- $config->set('view_modes', $view_modes);
- $config->save();
-
-
- entity_info_cache_clear();
- state_set('menu_rebuild_needed', TRUE);
- }
- }
-
- * Helper function: checks if the display mode exists.
- *
- * This callback is used as a machine_name element "exists" callback.
- *
- * @param string $machine_name
- * The machine name of the display mode to check for.
- *
- * @return bool
- * Whether or not the machine name already exists.
- *
- * @see field_ui_view_mode_form().
- */
- function entity_view_mode_exists($machine_name, $element, $form_state) {
- $entity_info = entity_get_info($element['#entity_type']);
- return !empty($entity_info['view modes'][$machine_name]);
- }
-
- * Determines whether the given user has access to an entity.
- *
- * @param string $op
- * The operation to be performed on the entity. Possible values are:
- * - create
- * - view
- * - update
- * - delete
- * @param string $entity_type
- * The entity type of the entity to check for.
- * @param EntityInterface $entity
- * Optionally an entity to check access for. If no entity is given, it will be
- * determined whether access is allowed for all entities of the given type.
- * @param User $account
- * The user to check for. Leave it to NULL to check for the global user.
- *
- * @return bool
- * Whether access is allowed or not. If the entity type does not specify any
- * access information, NULL is returned.
- *
- * @see entity_type_supports()
- */
- function entity_access($op, $entity_type, EntityInterface $entity = NULL, User $account = NULL) {
- if (!in_array($op, array('create', 'view', 'update', 'delete'), TRUE)) {
-
- return FALSE;
- }
- if (!empty($entity)) {
- return $entity->access($op, $account);
- }
- elseif ($op == 'create') {
- $entity_info = entity_get_info($entity_type);
-
- $class = $entity_info['entity class'];
- $bundle = NULL;
- if ($entity !== NULL) {
- $bundle = $entity->bundle();
- }
- return $class::createAccess($bundle, $account);
- }
- }
-
- * Gets the entity info array of an entity type.
- *
- * @param $entity_type
- * The entity type, e.g. node, for which the info shall be returned, or NULL
- * to return an array with info about all types.
- *
- * @see hook_entity_info()
- * @see hook_entity_info_alter()
- */
- function entity_get_info($entity_type = NULL) {
- global $language;
-
-
- static $backdrop_static_fast;
- if (!isset($backdrop_static_fast)) {
- $backdrop_static_fast['entity_info'] = &backdrop_static(__FUNCTION__);
- }
- $entity_info = &$backdrop_static_fast['entity_info'];
-
-
-
- $langcode = $language->langcode;
-
- if (empty($entity_info)) {
- if ($cache = cache()->get("entity_info:$langcode")) {
- $entity_info = $cache->data;
- }
- else {
- $entity_info = module_invoke_all('entity_info');
-
- foreach ($entity_info as $name => $data) {
- $entity_info[$name] += array(
- 'fieldable' => FALSE,
- 'controller class' => 'DefaultEntityController',
- 'static cache' => TRUE,
- 'field cache' => TRUE,
- 'load hook' => $name . '_load',
- 'bundles' => array(),
- 'view modes' => array(),
- 'token type' => $name,
- 'entity keys' => array(),
- 'translation' => array(),
- );
- $entity_info[$name]['entity keys'] += array(
- 'revision' => '',
- 'bundle' => '',
- );
-
-
- if (empty($entity_info[$name]['entity keys']['bundle']) && empty($entity_info[$name]['bundles'])) {
- $entity_info[$name]['bundles'] = array($name => array('label' => $entity_info[$name]['label']));
- }
-
-
- if (isset($entity_info[$name]['base table'])) {
- $entity_info[$name]['schema_fields_sql']['base table'] = backdrop_schema_fields_sql($entity_info[$name]['base table']);
- if (isset($entity_info[$name]['revision table'])) {
- $entity_info[$name]['schema_fields_sql']['revision table'] = backdrop_schema_fields_sql($entity_info[$name]['revision table']);
- }
- }
-
- $view_mode_info = module_invoke_all('entity_view_mode_info');
- backdrop_alter('entity_view_mode_info', $view_mode_info);
-
-
-
- $config = config_get('entity.view_modes', 'view_modes');
- if ($config) {
- $view_mode_info = backdrop_array_merge_deep($view_mode_info, $config);
- }
-
-
-
- foreach ($view_mode_info as $type => $view_modes) {
- if (isset($entity_info[$type])) {
- if (!isset($entity_info[$type]['view modes'])) {
- $entity_info[$type]['view modes'] = array();
- }
- $entity_info[$type]['view modes'] = $entity_info[$type]['view modes'] + $view_modes;
- }
- }
-
-
-
- if (!empty($entity_info[$name]['fieldable'])) {
- if (!isset($entity_info[$name]['view modes']['token'])) {
- $entity_info[$name]['view modes']['token'] = array(
- 'label' => t('Tokens'),
- 'custom settings' => FALSE,
- );
- }
- }
-
- foreach ($entity_info[$name]['view modes'] as $view_mode => $view_mode_info) {
- $entity_info[$name]['view modes'][$view_mode] += array(
- 'custom settings' => FALSE,
- );
- }
- }
-
- backdrop_alter('entity_info', $entity_info);
- cache()->set("entity_info:$langcode", $entity_info);
- }
- }
-
- if (empty($entity_type)) {
- return $entity_info;
- }
- elseif (isset($entity_info[$entity_type])) {
- return $entity_info[$entity_type];
- }
- }
-
- * Resets the cached information about entity types.
- */
- function entity_info_cache_clear() {
- backdrop_static_reset('entity_get_info');
-
- cache()->deletePrefix('entity_info:');
- }
-
- * Extracts ID, revision ID, and bundle name from an entity.
- *
- * @param $entity_type
- * The entity type; e.g. 'node' or 'user'.
- * @param $entity
- * The entity from which to extract values.
- *
- * @return
- * A numerically indexed array (not a hash table) containing these
- * elements:
- * - 0: Primary ID of the entity.
- * - 1: Revision ID of the entity, or NULL if $entity_type is not versioned.
- * - 2: Bundle name of the entity.
- */
- function entity_extract_ids($entity_type, $entity) {
- $info = entity_get_info($entity_type);
-
-
- $id = isset($entity->{$info['entity keys']['id']}) ? $entity->{$info['entity keys']['id']} : NULL;
- $vid = ($info['entity keys']['revision'] && isset($entity->{$info['entity keys']['revision']})) ? $entity->{$info['entity keys']['revision']} : NULL;
-
- if (!empty($info['entity keys']['bundle'])) {
-
- if (!isset($entity->{$info['entity keys']['bundle']}) || $entity->{$info['entity keys']['bundle']} === '') {
- throw new EntityMalformedException(t('Missing bundle property on entity of type @entity_type.', array('@entity_type' => $entity_type)));
- }
- $bundle = $entity->{$info['entity keys']['bundle']};
- }
- else {
-
-
- $bundle = $entity_type;
- }
-
- return array($id, $vid, $bundle);
- }
-
- * Assembles an object structure with initial IDs.
- *
- * This function can be seen as reciprocal to entity_extract_ids().
- *
- * @param $entity_type
- * The entity type; e.g. 'node' or 'user'.
- * @param $ids
- * A numerically indexed array, as returned by entity_extract_ids(),
- * containing these elements:
- * - 0: Primary ID of the entity.
- * - 1: Revision ID of the entity, or NULL if $entity_type is not versioned.
- * - 2: Bundle name of the entity, or NULL if $entity_type has no bundles.
- *
- * @return
- * An entity object, initialized with the IDs provided.
- *
- * @deprecated since 1.15.0.
- */
- function entity_create_stub_entity($entity_type, $ids) {
- watchdog_deprecated_function('entity', __FUNCTION__);
-
- $values = array();
- $info = entity_get_info($entity_type);
- $values[$info['entity keys']['id']] = $ids[0];
- if (!empty($info['entity keys']['revision']) && isset($ids[1])) {
- $values[$info['entity keys']['revision']] = $ids[1];
- }
- if (!empty($info['entity keys']['bundle']) && isset($ids[2])) {
- $values[$info['entity keys']['bundle']] = $ids[2];
- }
- return isset($info['entity class']) ? entity_create($entity_type, $values) : (object) $values;
- }
-
- * Loads entities from the database.
- *
- * This function should be used whenever you need to load more than one entity
- * from the database. The entities are loaded into memory and will not require
- * database access if loaded again during the same page request.
- *
- * The actual loading is done through a class that has to implement the
- * EntityControllerInterface interface. By default, DefaultEntityController is
- * used. Entity types can specify that a different class should be used by
- * setting the 'controller class' key in hook_entity_info(). These classes can
- * either implement the EntityControllerInterface interface, or, most commonly,
- * extend the DefaultEntityController class. See node_entity_info() and the
- * NodeController in node.module as an example.
- *
- * @param $entity_type
- * The entity type to load, e.g. node or user.
- * @param $ids
- * An array of entity IDs, FALSE with no conditions to load all entities of
- * the requested entity type, or NULL with conditions to load all entities of
- * the requested entity type that meet the given conditions.
- * @param $conditions
- * (deprecated) An associative array of conditions on the base table, where
- * the keys are the database fields and the values are the values those
- * fields must have. Instead, it is preferable to use EntityFieldQuery to
- * retrieve a list of entity IDs loadable by this function.
- * @param $reset
- * Whether to reset the internal cache for the requested entity type.
- *
- * @return array
- * An array of entity objects indexed by their ids.
- *
- * @see hook_entity_info()
- * @see EntityControllerInterface
- * @see DefaultEntityController
- * @see EntityFieldQuery
- */
- function entity_load_multiple($entity_type, $ids = FALSE, $conditions = array(), $reset = FALSE) {
- if ($reset) {
- entity_get_controller($entity_type)->resetCache();
- }
- return entity_get_controller($entity_type)->load($ids, $conditions);
- }
-
- * Loads a single entity from the database.
- *
- * Prior to Backdrop 1.2.0, this function was actually used to load multiple
- * entities and no convenience function for loading a single entity existed.
- * The previous version of this function was renamed to entity_load_multiple()
- * and this function was written to preserve compatibility for modules
- * depending on the previous behavior.
- *
- * If this function is called with either an array of IDs or FALSE as the $id
- * parameter, the parameters are passed through to entity_load_multiple() and
- * its return value will be returned instead of a single entity.
- *
- * @param string $entity_type
- * The entity type to load, e.g. node or user.
- * @param int|array $id
- * The ID(s) of the entity to load.
- *
- * @return EntityInterface|bool
- * The fully loaded entity or FALSE if not found.
- *
- * @see entity_load_multiple()
- */
- function entity_load($entity_type, $id) {
- if (is_array($id) || $id === FALSE || $id === NULL) {
- return call_user_func_array('entity_load_multiple', func_get_args());
- }
- else {
- $result = entity_load_multiple($entity_type, array($id));
- return reset($result);
- }
- }
-
- * Loads the unchanged, i.e. not modified, entity from the database.
- *
- * Unlike entity_load() this function ensures the entity is directly loaded from
- * the database, thus bypassing any static cache. In particular, this function
- * is useful to determine changes by comparing the entity being saved to the
- * stored entity.
- *
- * @param $entity_type
- * The entity type to load, e.g. node or user.
- * @param $id
- * The ID of the entity to load.
- *
- * @return
- * The unchanged entity, or FALSE if the entity cannot be loaded.
- */
- function entity_load_unchanged($entity_type, $id) {
- entity_get_controller($entity_type)->resetCache(array($id));
- $result = entity_get_controller($entity_type)->load(array($id));
- return reset($result);
- }
-
- * Deletes multiple entities permanently.
- *
- * @param $entity_type
- * The type of the entity.
- * @param $ids
- * An array of entity IDs of the entities to delete.
- */
- function entity_delete_multiple($entity_type, $ids) {
- entity_get_controller($entity_type)->delete($ids);
- }
-
- * Constructs a new entity object, without permanently saving it.
- *
- * @param $entity_type
- * The type of the entity.
- * @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.
- *
- * @return EntityInterface
- * A new entity object.
- */
- function entity_create($entity_type, array $values) {
- return entity_get_controller($entity_type)->create($values);
- }
-
- * Gets the entity controller class for an entity type.
- *
- * @return EntityStorageControllerInterface
- */
- function entity_get_controller($entity_type) {
- $controllers = &backdrop_static(__FUNCTION__, array());
- if (!isset($controllers[$entity_type])) {
- $type_info = entity_get_info($entity_type);
- $class = $type_info['controller class'];
- $controllers[$entity_type] = new $class($entity_type);
- }
- return $controllers[$entity_type];
- }
-
- * Invokes hook_entity_prepare_view().
- *
- * If adding a new entity similar to nodes, comments or users, you should
- * invoke this function during the ENTITY_build_content() or
- * ENTITY_view_multiple() phases of rendering to allow other modules to alter
- * the objects during this phase. This is needed for situations where
- * information needs to be loaded outside of ENTITY_load() - particularly
- * when loading entities into one another - i.e. a user object into a node, due
- * to the potential for unwanted side-effects such as caching and infinite
- * recursion. By convention, entity_prepare_view() is called after
- * field_attach_prepare_view() to allow entity level hooks to act on content
- * loaded by field API.
- *
- * @param $entity_type
- * The type of entity, i.e. 'node', 'user'.
- * @param $entities
- * The entity objects which are being prepared for view, keyed by object ID.
- *
- * @see hook_entity_prepare_view()
- */
- function entity_prepare_view($entity_type, $entities) {
-
-
-
- $prepare = array();
- foreach ($entities as $id => $entity) {
- if (empty($entity->entity_view_prepared)) {
-
- $prepare[$id] = $entity;
-
-
- $entity->entity_view_prepared = TRUE;
- }
- }
-
- if (!empty($prepare)) {
- module_invoke_all('entity_prepare_view', $prepare, $entity_type);
- }
- }
-
- * Invoke hook_entity_view_mode_alter().
- *
- * If adding a new entity similar to nodes, comments or users, you should invoke
- * this function during the ENTITY_build_content() or ENTITY_view_multiple()
- * phases of rendering to allow other modules to alter the display mode during
- * this phase. This function needs to be called before
- * field_attach_prepare_view() to ensure that the correct content is loaded by
- * field API.
- *
- * @param $entity_type
- * The type of entity, i.e. 'node', 'user'.
- * @param $entities
- * The entity objects which are being prepared for view, keyed by object ID.
- * @param $view_mode
- * The original display mode e.g. 'full', 'teaser'...
- * @param $langcode
- * (optional) A language code to be used for rendering. Defaults to the global
- * content language of the current request.
- * @return
- * An associative array with arrays of entities keyed by display mode.
- *
- * @see hook_entity_view_mode_alter()
- */
- function entity_view_mode_prepare($entity_type, $entities, $view_mode, $langcode = NULL) {
- if (!isset($langcode)) {
- global $language_content;
- $langcode = $language_content->langcode;
- }
-
-
-
- $entities_by_view_mode = array();
- foreach ($entities as $id => $entity) {
- $entity_view_mode = $view_mode;
- if (empty($entity->entity_view_prepared)) {
-
-
- $context = array(
- 'entity_type' => $entity_type,
- 'entity' => $entity,
- 'langcode' => $langcode,
- );
- backdrop_alter('entity_view_mode', $entity_view_mode, $context);
- }
-
- $entities_by_view_mode[$entity_view_mode][$id] = $entity;
- }
-
- return $entities_by_view_mode;
- }
-
- * Returns the URI elements of an entity.
- *
- * @param $entity_type
- * The entity type; e.g. 'node' or 'user'.
- * @param $entity
- * The entity for which to generate a path.
- *
- * @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.
- */
- function entity_uri($entity_type, $entity) {
- return $entity->uri();
- }
-
- * Returns the label of an entity.
- *
- * See the 'label callback' component of the hook_entity_info() return value
- * for more information.
- *
- * @param $entity_type
- * The entity type; e.g., 'node' or 'user'.
- * @param $entity
- * The entity for which to generate the label.
- *
- * @return
- * The entity label, or FALSE if not found.
- */
- function entity_label($entity_type, $entity) {
- return $entity->label();
- }
-
- * Attaches field API validation to entity forms.
- */
- function entity_form_field_validate($entity_type, $form, &$form_state) {
-
-
-
-
-
- $pseudo_entity = (object) $form_state['values'];
- field_attach_form_validate($entity_type, $pseudo_entity, $form, $form_state);
- }
-
- * Copies submitted values to entity properties for simple entity forms.
- *
- * During the submission handling of an entity form's "Save", "Preview", and
- * possibly other buttons, the form state's entity needs to be updated with the
- * submitted form values. Each entity form implements its own builder function
- * for doing this, appropriate for the particular entity and form, whereas
- * modules may specify additional builder functions in $form['#entity_builders']
- * for copying the form values of added form elements to entity properties.
- * Many of the main entity builder functions can call this helper function to
- * re-use its logic of copying $form_state['values'][PROPERTY] values to
- * $entity->PROPERTY for all entries in $form_state['values'] that are not field
- * data, and calling field_attach_submit() to copy field data. Apart from that
- * this helper invokes any additional builder functions that have been specified
- * in $form['#entity_builders'].
- *
- * For some entity forms (e.g., forms with complex non-field data and forms that
- * simultaneously edit multiple entities), this behavior may be inappropriate,
- * so the builder function for such forms needs to implement the required
- * functionality instead of calling this function.
- */
- function entity_form_submit_build_entity($entity_type, $entity, $form, &$form_state) {
- $info = entity_get_info($entity_type);
- list(, , $bundle) = entity_extract_ids($entity_type, $entity);
-
-
-
-
- $values_excluding_fields = $info['fieldable'] ? array_diff_key($form_state['values'], field_info_instances($entity_type, $bundle)) : $form_state['values'];
- foreach ($values_excluding_fields as $key => $value) {
- $entity->$key = $value;
- }
-
-
- if (isset($form['#entity_builders'])) {
- foreach ($form['#entity_builders'] as $function) {
- $function($entity_type, $entity, $form, $form_state);
- }
- }
-
-
- if ($info['fieldable']) {
- field_attach_submit($entity_type, $entity, $form, $form_state);
- }
- }
-
- * Implements hook_autoload_info().
- */
- function entity_autoload_info() {
- return array(
- 'EntityInterface' => 'entity.class.inc',
- 'Entity' => 'entity.class.inc',
- 'EntityMalformedException' => 'entity.class.inc',
- 'EntityStorageControllerInterface' => 'entity.controller.inc',
- 'DefaultEntityController' => 'entity.controller.inc',
- 'EntityControllerInterface' => 'entity.controller.inc',
- 'EntityStorageException' => 'entity.controller.inc',
- 'EntityDatabaseStorageController' => 'entity.controller.inc',
- 'EntityFieldQueryException' => 'entity.query.inc',
- 'EntityFieldQuery' => 'entity.query.inc',
- );
- }
-
- * Implements hook_config_info().
- */
- function entity_config_info() {
- $prefixes['entity.view_modes'] = array(
- 'label' => t('Display mode settings'),
- 'group' => t('Entity'),
- );
- return $prefixes;
- }