Newer
Older
Dries Buytaert
committed
<?php
/**
* @file
* Hooks provided the Entity module.
*/
/**
* @addtogroup hooks
* @{
*/
/**
Angie Byron
committed
* Add to entity type definitions.
*
* Modules may implement this hook to add information to defined entity types.
*
* @param array $entity_info
* An associative array of all entity type definitions, keyed by the entity
* type name. Passed by reference.
*
* @see \Drupal\Core\Entity\Entity
* @see \Drupal\Core\Entity\EntityManager
* @see entity_get_info()
*/
function hook_entity_info(&$entity_info) {
Dries Buytaert
committed
// Add a form controller for a custom node form without overriding the default
// node form. To override the default node form, use hook_entity_info_alter()
// to alter $entity_info['node']['controllers']['form']['default'].
$entity_info['node']['controllers']['form']['mymodule_foo'] = 'Drupal\mymodule\NodeFooFormController';
Dries Buytaert
committed
}
/**
* Alter the view modes for entity types.
*
* @param array $view_modes
* An array of view modes, keyed first by entity type, then by view mode name.
*
* @see entity_get_view_modes()
* @see hook_entity_view_mode_info()
*/
function hook_entity_view_mode_info_alter(&$view_modes) {
Alex Pott
committed
$view_modes['user']['full']['status'] = TRUE;
Dries Buytaert
committed
}
/**
* Describe the bundles for entity types.
*
* @return array
* An associative array of all entity bundles, keyed by the entity
* type name, and then the bundle name, with the following keys:
* - label: The human-readable name of the bundle.
* - uri_callback: The same as the 'uri_callback' key defined for the entity
* type in the EntityManager, but for the bundle only. When determining
* the URI of an entity, if a 'uri_callback' is defined for both the
* entity type and the bundle, the one for the bundle is used.
Angie Byron
committed
* - translatable: (optional) A boolean value specifying whether this bundle
* has translation support enabled. Defaults to FALSE.
Dries Buytaert
committed
*
* @see entity_get_bundles()
* @see hook_entity_bundle_info_alter()
*/
function hook_entity_bundle_info() {
Alex Pott
committed
$bundles['user']['user']['label'] = t('User');
Dries Buytaert
committed
return $bundles;
}
/**
* Alter the bundles for entity types.
*
* @param array $bundles
* An array of bundles, keyed first by entity type, then by bundle name.
*
* @see entity_get_bundles()
* @see hook_entity_bundle_info()
*/
function hook_entity_bundle_info_alter(&$bundles) {
$bundles['user']['user']['label'] = t('Full account');
Angie Byron
committed
}
Angie Byron
committed
/**
* Act on entity_bundle_create().
*
* This hook is invoked after the operation has been performed.
*
* @param string $entity_type
* The type of $entity; e.g. 'node' or 'user'.
* @param string $bundle
* The name of the bundle.
*/
function hook_entity_bundle_create($entity_type, $bundle) {
// When a new bundle is created, the menu needs to be rebuilt to add the
// Field UI menu item tabs.
Drupal::state()->set('menu_rebuild_needed', TRUE);
Angie Byron
committed
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
}
/**
* Act on entity_bundle_rename().
*
* This hook is invoked after the operation has been performed.
*
* @param string $entity_type
* The entity type to which the bundle is bound.
* @param string $bundle_old
* The previous name of the bundle.
* @param string $bundle_new
* The new name of the bundle.
*/
function hook_entity_bundle_rename($entity_type, $bundle_old, $bundle_new) {
// Update the settings associated with the bundle in my_module.settings.
$config = config('my_module.settings');
$bundle_settings = $config->get('bundle_settings');
if (isset($bundle_settings[$entity_type][$bundle_old])) {
$bundle_settings[$entity_type][$bundle_new] = $bundle_settings[$entity_type][$bundle_old];
unset($bundle_settings[$entity_type][$bundle_old]);
$config->set('bundle_settings', $bundle_settings);
}
}
/**
* Act on entity_bundle_delete().
*
* This hook is invoked after the operation has been performed.
*
* @param string $entity_type
* The type of entity; for example, 'node' or 'user'.
* @param string $bundle
* The bundle that was just deleted.
*/
function hook_entity_bundle_delete($entity_type, $bundle) {
// Remove the settings associated with the bundle in my_module.settings.
$config = config('my_module.settings');
$bundle_settings = $config->get('bundle_settings');
if (isset($bundle_settings[$entity_type][$bundle])) {
unset($bundle_settings[$entity_type][$bundle]);
$config->set('bundle_settings', $bundle_settings);
}
}
Angie Byron
committed
/**
* Alter the entity type definitions.
Dries Buytaert
committed
*
* Modules may implement this hook to alter the information that defines an
Angie Byron
committed
* entity type. All properties that are available in
Angie Byron
committed
* \Drupal\Core\Entity\EntityManager can be altered here.
*
Angie Byron
committed
* Do not use this hook to add information to entity types. Use
* hook_entity_info() for that instead.
*
Angie Byron
committed
* @param array $entity_info
* An associative array of all entity type definitions, keyed by the entity
Angie Byron
committed
* type name. Passed by reference.
Dries Buytaert
committed
*
Angie Byron
committed
* @see \Drupal\Core\Entity\Entity
* @see \Drupal\Core\Entity\EntityManager
* @see entity_get_info()
Dries Buytaert
committed
*/
function hook_entity_info_alter(&$entity_info) {
// Set the controller class for nodes to an alternate implementation of the
// Drupal\Core\Entity\EntityStorageControllerInterface interface.
$entity_info['node']['controllers']['storage'] = 'Drupal\mymodule\MyCustomNodeStorageController';
Dries Buytaert
committed
}
Angie Byron
committed
/**
* Act on a newly created entity.
*
* This hook runs after a new entity object has just been instantiated. It can
* be used to set initial values, e.g. to provide defaults.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity object.
*/
function hook_entity_create(\Drupal\Core\Entity\EntityInterface $entity) {
// @todo Remove the check for EntityNG once all entity types have been
// converted to it.
if (!isset($entity->foo) && ($entity instanceof \Drupal\Core\Entity\EntityNG)) {
$entity->foo->value = 'some_initial_value';
}
}
Dries Buytaert
committed
/**
* Act on entities when loaded.
*
* This is a generic load hook called for all entity types loaded via the
* entity API.
*
* @param array $entities
Dries Buytaert
committed
* The entities keyed by entity ID.
* @param string $entity_type
Dries Buytaert
committed
* The type of entities being loaded (i.e. node, user, comment).
*/
function hook_entity_load($entities, $entity_type) {
Dries Buytaert
committed
foreach ($entities as $entity) {
$entity->foo = mymodule_add_something($entity);
Dries Buytaert
committed
}
}
/**
* Act on an entity before it is about to be created or updated.
*
* @param Drupal\Core\Entity\EntityInterface $entity
Dries Buytaert
committed
* The entity object.
*/
function hook_entity_presave(Drupal\Core\Entity\EntityInterface $entity) {
Dries Buytaert
committed
$entity->changed = REQUEST_TIME;
}
/**
* Act on entities when inserted.
*
* @param Drupal\Core\Entity\EntityInterface $entity
Dries Buytaert
committed
* The entity object.
*/
function hook_entity_insert(Drupal\Core\Entity\EntityInterface $entity) {
Dries Buytaert
committed
// Insert the new entity into a fictional table of all entities.
db_insert('example_entity')
->fields(array(
'type' => $entity->entityType(),
'id' => $entity->id(),
Dries Buytaert
committed
'created' => REQUEST_TIME,
'updated' => REQUEST_TIME,
))
->execute();
}
/**
* Act on entities when updated.
*
* @param Drupal\Core\Entity\EntityInterface $entity
Dries Buytaert
committed
* The entity object.
*/
function hook_entity_update(Drupal\Core\Entity\EntityInterface $entity) {
Dries Buytaert
committed
// Update the entity's entry in a fictional table of all entities.
db_update('example_entity')
->fields(array(
'updated' => REQUEST_TIME,
))
->condition('type', $entity->entityType())
->condition('id', $entity->id())
Dries Buytaert
committed
->execute();
}
/**
catch
committed
* Act before entity deletion.
*
* This hook runs after the entity type-specific predelete hook.
Dries Buytaert
committed
*
* @param Drupal\Core\Entity\EntityInterface $entity
catch
committed
* The entity object for the entity that is about to be deleted.
*/
function hook_entity_predelete(Drupal\Core\Entity\EntityInterface $entity) {
catch
committed
// Count references to this entity in a custom table before they are removed
// upon entity deletion.
$id = $entity->id();
$type = $entity->entityType();
catch
committed
$count = db_select('example_entity_data')
->condition('type', $type)
->condition('id', $id)
->countQuery()
->execute()
->fetchField();
// Log the count in a table that records this statistic for deleted entities.
$ref_count_record = (object) array(
'count' => $count,
'type' => $type,
'id' => $id,
);
drupal_write_record('example_deleted_entity_statistics', $ref_count_record);
}
/**
* Respond to entity deletion.
*
* This hook runs after the entity type-specific delete hook.
*
* @param Drupal\Core\Entity\EntityInterface $entity
catch
committed
* The entity object for the entity that has been deleted.
Dries Buytaert
committed
*/
function hook_entity_delete(Drupal\Core\Entity\EntityInterface $entity) {
Dries Buytaert
committed
// Delete the entity's entry from a fictional table of all entities.
db_delete('example_entity')
->condition('type', $entity->entityType())
->condition('id', $entity->id())
Dries Buytaert
committed
->execute();
}
/**
* Alter or execute an Drupal\Core\Entity\Query\EntityQueryInterface.
Dries Buytaert
committed
*
* @param \Drupal\Core\Entity\Query\QueryInterface $query
Dries Buytaert
committed
* Note the $query->altered attribute which is TRUE in case the query has
* already been altered once. This happens with cloned queries.
* If there is a pager, then such a cloned query will be executed to count
* all elements. This query can be detected by checking for
* ($query->pager && $query->count), allowing the driver to return 0 from
* the count query and disable the pager.
*/
function hook_entity_query_alter(\Drupal\Core\Entity\Query\QueryInterface $query) {
// @todo: code example.
Dries Buytaert
committed
}
/**
* Act on entities being assembled before rendering.
*
Angie Byron
committed
* @param \Drupal\Core\Entity\EntityInterface $entity
Dries Buytaert
committed
* The entity object.
Angie Byron
committed
* @param \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display
* The entity_display object holding the display options configured for the
* entity components.
Dries Buytaert
committed
* @param $view_mode
* The view mode the entity is rendered in.
* @param $langcode
* The language code used for rendering.
*
* The module may add elements to $entity->content prior to rendering. The
* structure of $entity->content is a renderable array as expected by
* drupal_render().
*
* @see hook_entity_view_alter()
* @see hook_comment_view()
* @see hook_node_view()
* @see hook_user_view()
*/
Angie Byron
committed
function hook_entity_view(\Drupal\Core\Entity\EntityInterface $entity, \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display, $view_mode, $langcode) {
// Only do the extra work if the component is configured to be displayed.
// This assumes a 'mymodule_addition' extra field has been defined for the
// entity bundle in hook_field_extra_fields().
if ($display->getComponent('mymodule_addition')) {
$entity->content['mymodule_addition'] = array(
'#markup' => mymodule_addition($entity),
'#theme' => 'mymodule_my_additional_field',
);
}
Dries Buytaert
committed
}
/**
* Alter the results of ENTITY_view().
*
* This hook is called after the content has been assembled in a structured
* array and may be used for doing processing which requires that the complete
* entity content structure has been built.
*
* If a module wishes to act on the rendered HTML of the entity rather than the
* structured content array, it may use this hook to add a #post_render
Jennifer Hodgdon
committed
* callback. Alternatively, it could also implement hook_preprocess_HOOK() for
Alex Pott
committed
* the particular entity type template, if there is one (e.g., node.html.twig).
Dries Buytaert
committed
* See drupal_render() and theme() for details.
*
* @param $build
* A renderable array representing the entity content.
* @param Drupal\Core\Entity\EntityInterface $entity
* The entity object being rendered.
Angie Byron
committed
* @param \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display
* The entity_display object holding the display options configured for the
* entity components.
Dries Buytaert
committed
*
* @see hook_entity_view()
* @see hook_comment_view_alter()
* @see hook_node_view_alter()
* @see hook_taxonomy_term_view_alter()
* @see hook_user_view_alter()
*/
Angie Byron
committed
function hook_entity_view_alter(&$build, Drupal\Core\Entity\EntityInterface $entity, \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display) {
Dries Buytaert
committed
if ($build['#view_mode'] == 'full' && isset($build['an_additional_field'])) {
// Change its weight.
$build['an_additional_field']['#weight'] = -10;
// Add a #post_render callback to act on the rendered HTML of the entity.
$build['#post_render'][] = 'my_module_node_post_render';
}
}
/**
* Act on entities as they are being prepared for view.
*
* Allows you to operate on multiple entities as they are being prepared for
* view. Only use this if attaching the data during the entity loading phase
Dries Buytaert
committed
* is not appropriate, for example when attaching other 'entity' style objects.
*
* @param string $entity_type
* The type of entities being viewed (i.e. node, user, comment).
Angie Byron
committed
* @param array $entities
* The entities keyed by entity ID.
* @param array $display
* The array of entity_display objects holding the display options configured
* for the entity components, keyed by bundle name.
* @param string $view_mode
* The view mode.
Dries Buytaert
committed
*/
Angie Byron
committed
function hook_entity_prepare_view($entity_type, array $entities, array $displays, $view_mode) {
Dries Buytaert
committed
// Load a specific node into the user object for later theming.
if (!empty($entities) && $entity_type == 'user') {
Angie Byron
committed
// Only do the extra work if the component is configured to be
// displayed. This assumes a 'mymodule_addition' extra field has been
// defined for the entity bundle in hook_field_extra_fields().
$ids = array();
foreach ($entities as $id => $entity) {
if ($displays[$entity->bundle()]->getComponent('mymodule_addition')) {
$ids[] = $id;
}
}
if ($ids) {
$nodes = mymodule_get_user_nodes($ids);
foreach ($ids as $id) {
$entities[$id]->user_node = $nodes[$id];
}
Dries Buytaert
committed
}
}
}
Angie Byron
committed
/**
* Change the view mode of an entity that is being displayed.
*
* @param string $view_mode
* The view_mode that is to be used to display the entity.
* @param Drupal\Core\Entity\EntityInterface $entity
Angie Byron
committed
* The entity that is being viewed.
* @param array $context
* Array with additional context information, currently only contains the
* langcode the entity is viewed in.
*/
function hook_entity_view_mode_alter(&$view_mode, Drupal\Core\Entity\EntityInterface $entity, $context) {
Angie Byron
committed
// For nodes, change the view mode when it is teaser.
if ($entity->entityType() == 'node' && $view_mode == 'teaser') {
$view_mode = 'my_custom_view_mode';
}
}
Dries Buytaert
committed
/**
* Alters the settings used for displaying an entity.
*
* @param \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display
* The entity_display object that will be used to display the entity
* components.
* @param array $context
* An associative array containing:
* - entity_type: The entity type, e.g., 'node' or 'user'.
* - bundle: The bundle, e.g., 'page' or 'article'.
* - view_mode: The view mode, e.g. 'full', 'teaser'...
*/
function hook_entity_display_alter(\Drupal\entity\Plugin\Core\Entity\EntityDisplay $display, array $context) {
// Leave field labels out of the search index.
if ($context['entity_type'] == 'node' && $context['view_mode'] == 'search_index') {
foreach ($display->getComponents() as $name => $options) {
if (isset($options['label'])) {
$options['label'] = 'hidden';
$display->setComponent($name, $options);
}
}
}
}
Alex Pott
committed
/**
* Alters the settings used for displaying an entity form.
*
* @param \Drupal\entity\Plugin\Core\Entity\EntityFormDisplay $form_display
* The entity_form_display object that will be used to display the entity form
* components.
* @param array $context
* An associative array containing:
* - entity_type: The entity type, e.g., 'node' or 'user'.
* - bundle: The bundle, e.g., 'page' or 'article'.
* - form_mode: The form mode, e.g. 'default', 'profile', 'register'...
*/
function hook_entity_form_display_alter(\Drupal\entity\Plugin\Core\Entity\EntityFormDisplay $form_display, array $context) {
// Hide the 'user_picture' field from the register form.
if ($context['entity_type'] == 'user' && $context['form_mode'] == 'register') {
$form_display->setComponent('user_picture', array(
'type' => 'hidden',
));
}
}
Dries Buytaert
committed
/**
Dries Buytaert
committed
* Define custom entity fields.
Dries Buytaert
committed
*
* @param string $entity_type
Dries Buytaert
committed
* The entity type for which to define entity fields.
Dries Buytaert
committed
*
* @return array
Dries Buytaert
committed
* An array of entity field information having the following optional entries:
* - definitions: An array of field definitions to add all entities of this
* type, keyed by field name. See
* \Drupal\Core\Entity\EntityManager::getFieldDefinitions() for a list of
* supported keys in field definitions.
* - optional: An array of field definitions for optional entity fields, keyed
* by field name. Optional fields are fields that only exist for certain
* bundles of the entity type.
* - bundle map: An array keyed by bundle name, containing the names of
* optional fields that entities of this bundle have.
*
Dries Buytaert
committed
* @see hook_entity_field_info_alter()
Dries Buytaert
committed
* @see \Drupal\Core\Entity\EntityManager::getFieldDefinitions()
* @see \Drupal\Core\TypedData\TypedDataManager::create()
Dries Buytaert
committed
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
*/
function hook_entity_field_info($entity_type) {
if (mymodule_uses_entity_type($entity_type)) {
$info = array();
$info['definitions']['mymodule_text'] = array(
'type' => 'string_item',
'list' => TRUE,
'label' => t('The text'),
'description' => t('A text property added by mymodule.'),
'computed' => TRUE,
'class' => '\Drupal\mymodule\EntityComputedText',
);
if ($entity_type == 'node') {
// Add a property only to entities of the 'article' bundle.
$info['optional']['mymodule_text_more'] = array(
'type' => 'string_item',
'list' => TRUE,
'label' => t('More text'),
'computed' => TRUE,
'class' => '\Drupal\mymodule\EntityComputedMoreText',
);
$info['bundle map']['article'][0] = 'mymodule_text_more';
}
return $info;
}
}
/**
Dries Buytaert
committed
* Alter defined entity fields.
Dries Buytaert
committed
*
* @param array $info
Dries Buytaert
committed
* The entity field info array as returned by hook_entity_field_info().
Dries Buytaert
committed
* @param string $entity_type
Dries Buytaert
committed
* The entity type for which entity fields are defined.
Dries Buytaert
committed
*
* @see hook_entity_field_info()
*/
function hook_entity_field_info_alter(&$info, $entity_type) {
if (!empty($info['definitions']['mymodule_text'])) {
// Alter the mymodule_text property to use a custom class.
$info['definitions']['mymodule_text']['class'] = '\Drupal\anothermodule\EntityComputedText';
}
}
/**
* Alter entity operations.
*
* @param array $operations
* Operations array as returned by
* \Drupal\Core\Entity\EntityStorageControllerInterface::getOperations().
* @param \Drupal\Core\Entity\EntityInterface $entity
* The entity on which the linked operations will be performed.
*/
function hook_entity_operation_alter(array &$operations, \Drupal\Core\Entity\EntityInterface $entity) {
$uri = $entity->uri();
$operations['translate'] = array(
'title' => t('Translate'),
'href' => $uri['path'] . '/translate',
'weight' => 50,
);
}
/**
* Control access to fields.
*
* This hook is invoked from \Drupal\Core\Entity\Field\Type\Field::access() to
* let modules grant or deny operations on fields.
*
* @param string $operation
* The operation to be performed. See
* \Drupal\Core\TypedData\AccessibleInterface::access() for possible values.
* @param \Drupal\Core\Entity\Field\Type\Field $field
* The entity field object on which the operation is to be performed.
* @param \Drupal\Core\Session\AccountInterface $account
* The user account to check.
*
* @return bool|NULL
* TRUE if access should be allowed, FALSE if access should be denied and NULL
* if the implementation has no opinion.
*/
function hook_entity_field_access($operation, $field, \Drupal\Core\Session\AccountInterface $account) {
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
if ($field->getName() == 'field_of_interest' && $operation == 'update') {
return user_access('update field of interest', $account);
}
}
/**
* Alters the default access behaviour for a given field.
*
* Use this hook to override access grants from another module. Note that the
* original default access flag is masked under the ':default' key.
*
* @param array $grants
* An array of grants gathered by hook_entity_field_access(). The array is
* keyed by the module that defines the field's access control; the values are
* grant responses for each module (Boolean or NULL).
* @param array $context
* Context array on the performed operation with the following keys:
* - operation: The operation to be performed (string).
* - field: The entity field object (\Drupal\Core\Entity\Field\Type\Field).
* - account: The user account to check access for
* (Drupal\user\Plugin\Core\Entity\User).
*/
function hook_entity_field_access_alter(array &$grants, array $context) {
$field = $context['field'];
if ($field->getName() == 'field_of_interest' && $grants['node'] === FALSE) {
// Override node module's restriction to no opinion. We don't want to
// provide our own access hook, we only want to take out node module's part
// in the access handling of this field. We also don't want to switch node
// module's grant to TRUE, because the grants of other modules should still
// decide on their own if this field is accessible or not.
$grants['node'] = NULL;
}
}