Upgraded drupal core with security updates
[yaffs-website] / web / core / lib / Drupal / Core / Entity / entity.api.php
1 <?php
2
3 /**
4  * @file
5  * Hooks and documentation related to entities.
6  */
7
8 use Drupal\Core\Access\AccessResult;
9 use Drupal\Core\Entity\ContentEntityInterface;
10 use Drupal\Core\Entity\DynamicallyFieldableEntityStorageInterface;
11 use Drupal\Core\Field\BaseFieldDefinition;
12 use Drupal\Core\Render\Element;
13 use Drupal\language\Entity\ContentLanguageSettings;
14 use Drupal\node\Entity\NodeType;
15
16 /**
17  * @defgroup entity_crud Entity CRUD, editing, and view hooks
18  * @{
19  * Hooks used in various entity operations.
20  *
21  * Entity create, read, update, and delete (CRUD) operations are performed by
22  * entity storage classes; see the
23  * @link entity_api Entity API topic @endlink for more information. Most
24  * entities use or extend the default classes:
25  * \Drupal\Core\Entity\Sql\SqlContentEntityStorage for content entities, and
26  * \Drupal\Core\Config\Entity\ConfigEntityStorage for configuration entities.
27  * For these entities, there is a set of hooks that is invoked for each
28  * CRUD operation, which module developers can implement to affect these
29  * operations; these hooks are actually invoked from methods on
30  * \Drupal\Core\Entity\EntityStorageBase.
31  *
32  * For content entities, viewing and rendering are handled by a view builder
33  * class; see the @link entity_api Entity API topic @endlink for more
34  * information. Most view builders extend or use the default class
35  * \Drupal\Core\Entity\EntityViewBuilder.
36  *
37  * Entity editing (including adding new entities) is handled by entity form
38  * classes; see the @link entity_api Entity API topic @endlink for more
39  * information. Most entity editing forms extend base classes
40  * \Drupal\Core\Entity\EntityForm or \Drupal\Core\Entity\ContentEntityForm.
41  * Note that many other operations, such as confirming deletion of entities,
42  * also use entity form classes.
43  *
44  * This topic lists all of the entity CRUD and view operations, and the hooks
45  * and other operations that are invoked (in order) for each operation. Some
46  * notes:
47  * - Whenever an entity hook is invoked, there is both a type-specific entity
48  *   hook, and a generic entity hook. For instance, during a create operation on
49  *   a node, first hook_node_create() and then hook_entity_create() would be
50  *   invoked.
51  * - The entity-type-specific hooks are represented in the list below as
52  *   hook_ENTITY_TYPE_... (hook_ENTITY_TYPE_create() in this example). To
53  *   implement one of these hooks for an entity whose machine name is "foo",
54  *   define a function called mymodule_foo_create(), for instance. Also note
55  *   that the entity or array of entities that are passed into a specific-type
56  *   hook are of the specific entity class, not the generic Entity class, so in
57  *   your implementation, you can make the $entity argument something like $node
58  *   and give it a specific type hint (which should normally be to the specific
59  *   interface, such as \Drupal\Node\NodeInterface for nodes).
60  * - $storage in the code examples is assumed to be an entity storage
61  *   class. See the @link entity_api Entity API topic @endlink for
62  *   information on how to instantiate the correct storage class for an
63  *   entity type.
64  * - $view_builder in the code examples is assumed to be an entity view builder
65  *   class. See the @link entity_api Entity API topic @endlink for
66  *   information on how to instantiate the correct view builder class for
67  *   an entity type.
68  * - During many operations, static methods are called on the entity class,
69  *   which implements \Drupal\Entity\EntityInterface.
70  *
71  * @section create Create operations
72  * To create an entity:
73  * @code
74  * $entity = $storage->create();
75  *
76  * // Add code here to set properties on the entity.
77  *
78  * // Until you call save(), the entity is just in memory.
79  * $entity->save();
80  * @endcode
81  * There is also a shortcut method on entity classes, which creates an entity
82  * with an array of provided property values: \Drupal\Core\Entity::create().
83  *
84  * Hooks invoked during the create operation:
85  * - hook_ENTITY_TYPE_create()
86  * - hook_entity_create()
87  *
88  * See @ref save below for the save portion of the operation.
89  *
90  * @section load Read/Load operations
91  * To load (read) a single entity:
92  * @code
93  * $entity = $storage->load($id);
94  * @endcode
95  * To load multiple entities:
96  * @code
97  * $entities = $storage->loadMultiple($ids);
98  * @endcode
99  * Since load() calls loadMultiple(), these are really the same operation.
100  * Here is the order of hooks and other operations that take place during
101  * entity loading:
102  * - Entity is loaded from storage.
103  * - postLoad() is called on the entity class, passing in all of the loaded
104  *   entities.
105  * - hook_entity_load()
106  * - hook_ENTITY_TYPE_load()
107  *
108  * When an entity is loaded, normally the default entity revision is loaded.
109  * It is also possible to load a different revision, for entities that support
110  * revisions, with this code:
111  * @code
112  * $entity = $storage->loadRevision($revision_id);
113  * @endcode
114  * This involves the same hooks and operations as regular entity loading.
115  *
116  * @section save Save operations
117  * To update an existing entity, you will need to load it, change properties,
118  * and then save; as described above, when creating a new entity, you will also
119  * need to save it. Here is the order of hooks and other events that happen
120  * during an entity save:
121  * - preSave() is called on the entity object, and field objects.
122  * - hook_ENTITY_TYPE_presave()
123  * - hook_entity_presave()
124  * - Entity is saved to storage.
125  * - For updates on content entities, if there is a translation added that
126  *   was not previously present:
127  *   - hook_ENTITY_TYPE_translation_insert()
128  *   - hook_entity_translation_insert()
129  * - For updates on content entities, if there was a translation removed:
130  *   - hook_ENTITY_TYPE_translation_delete()
131  *   - hook_entity_translation_delete()
132  * - postSave() is called on the entity object.
133  * - hook_ENTITY_TYPE_insert() (new) or hook_ENTITY_TYPE_update() (update)
134  * - hook_entity_insert() (new) or hook_entity_update() (update)
135  *
136  * Some specific entity types invoke hooks during preSave() or postSave()
137  * operations. Examples:
138  * - Field configuration preSave(): hook_field_storage_config_update_forbid()
139  * - Node postSave(): hook_node_access_records() and
140  *   hook_node_access_records_alter()
141  * - Config entities that are acting as entity bundles in postSave():
142  *   hook_entity_bundle_create()
143  * - Comment: hook_comment_publish() and hook_comment_unpublish() as
144  *   appropriate.
145  *
146  * @section edit Editing operations
147  * When an entity's add/edit form is used to add or edit an entity, there
148  * are several hooks that are invoked:
149  * - hook_entity_prepare_form()
150  * - hook_ENTITY_TYPE_prepare_form()
151  * - hook_entity_form_display_alter() (for content entities only)
152  *
153  * @section delete Delete operations
154  * To delete one or more entities, load them and then delete them:
155  * @code
156  * $entities = $storage->loadMultiple($ids);
157  * $storage->delete($entities);
158  * @endcode
159  *
160  * During the delete operation, the following hooks and other events happen:
161  * - preDelete() is called on the entity class.
162  * - hook_ENTITY_TYPE_predelete()
163  * - hook_entity_predelete()
164  * - Entity and field information is removed from storage.
165  * - postDelete() is called on the entity class.
166  * - hook_ENTITY_TYPE_delete()
167  * - hook_entity_delete()
168  *
169  * Some specific entity types invoke hooks during the delete process. Examples:
170  * - Entity bundle postDelete(): hook_entity_bundle_delete()
171  *
172  * Individual revisions of an entity can also be deleted:
173  * @code
174  * $storage->deleteRevision($revision_id);
175  * @endcode
176  * This operation invokes the following operations and hooks:
177  * - Revision is loaded (see @ref load above).
178  * - Revision and field information is removed from the database.
179  * - hook_ENTITY_TYPE_revision_delete()
180  * - hook_entity_revision_delete()
181  *
182  * @section view View/render operations
183  * To make a render array for a loaded entity:
184  * @code
185  * // You can omit the language ID if the default language is being used.
186  * $build = $view_builder->view($entity, 'view_mode_name', $language->getId());
187  * @endcode
188  * You can also use the viewMultiple() method to view multiple entities.
189  *
190  * Hooks invoked during the operation of building a render array:
191  * - hook_entity_view_mode_alter()
192  * - hook_ENTITY_TYPE_build_defaults_alter()
193  * - hook_entity_build_defaults_alter()
194  *
195  * View builders for some types override these hooks, notably:
196  * - The Tour view builder does not invoke any hooks.
197  * - The Block view builder invokes hook_block_view_alter() and
198  *   hook_block_view_BASE_BLOCK_ID_alter(). Note that in other view builders,
199  *   the view alter hooks are run later in the process.
200  *
201  * During the rendering operation, the default entity viewer runs the following
202  * hooks and operations in the pre-render step:
203  * - hook_entity_view_display_alter()
204  * - hook_entity_prepare_view()
205  * - Entity fields are loaded, and render arrays are built for them using
206  *   their formatters.
207  * - hook_entity_display_build_alter()
208  * - hook_ENTITY_TYPE_view()
209  * - hook_entity_view()
210  * - hook_ENTITY_TYPE_view_alter()
211  * - hook_entity_view_alter()
212  *
213  * Some specific builders have specific hooks:
214  * - The Node view builder invokes hook_node_links_alter().
215  * - The Comment view builder invokes hook_comment_links_alter().
216  *
217  * After this point in rendering, the theme system takes over. See the
218  * @link theme_render Theme system and render API topic @endlink for more
219  * information.
220  *
221  * @section misc Other entity hooks
222  * Some types of entities invoke hooks for specific operations:
223  * - Searching nodes:
224  *   - hook_ranking()
225  *   - Query is executed to find matching nodes
226  *   - Resulting node is loaded
227  *   - Node render array is built
228  *   - comment_node_update_index() is called (this adds "N comments" text)
229  *   - hook_node_search_result()
230  * - Search indexing nodes:
231  *   - Node is loaded
232  *   - Node render array is built
233  *   - hook_node_update_index()
234  * @}
235  */
236
237 /**
238  * @defgroup entity_api Entity API
239  * @{
240  * Describes how to define and manipulate content and configuration entities.
241  *
242  * Entities, in Drupal, are objects that are used for persistent storage of
243  * content and configuration information. See the
244  * @link info_types Information types topic @endlink for an overview of the
245  * different types of information, and the
246  * @link config_api Configuration API topic @endlink for more about the
247  * configuration API.
248  *
249  * Each entity is an instance of a particular "entity type". Some content entity
250  * types have sub-types, which are known as "bundles", while for other entity
251  * types, there is only a single bundle. For example, the Node content entity
252  * type, which is used for the main content pages in Drupal, has bundles that
253  * are known as "content types", while the User content type, which is used for
254  * user accounts, has only one bundle.
255  *
256  * The sections below have more information about entities and the Entity API;
257  * for more detailed information, see
258  * https://www.drupal.org/developing/api/entity.
259  *
260  * @section define Defining an entity type
261  * Entity types are defined by modules, using Drupal's Plugin API (see the
262  * @link plugin_api Plugin API topic @endlink for more information about plugins
263  * in general). Here are the steps to follow to define a new entity type:
264  * - Choose a unique machine name, or ID, for your entity type. This normally
265  *   starts with (or is the same as) your module's machine name. It should be
266  *   as short as possible, and may not exceed 32 characters.
267  * - Define an interface for your entity's get/set methods, usually extending
268  *   either \Drupal\Core\Config\Entity\ConfigEntityInterface or
269  *   \Drupal\Core\Entity\ContentEntityInterface.
270  * - Define a class for your entity, implementing your interface and extending
271  *   either \Drupal\Core\Config\Entity\ConfigEntityBase or
272  *   \Drupal\Core\Entity\ContentEntityBase, with annotation for
273  *   \@ConfigEntityType or \@ContentEntityType in its documentation block.
274  * - The 'id' annotation gives the entity type ID, and the 'label' annotation
275  *   gives the human-readable name of the entity type. If you are defining a
276  *   content entity type that uses bundles, the 'bundle_label' annotation gives
277  *   the human-readable name to use for a bundle of this entity type (for
278  *   example, "Content type" for the Node entity).
279  * - The annotation will refer to several handler classes, which you will also
280  *   need to define:
281  *   - list_builder: Define a class that extends
282  *     \Drupal\Core\Config\Entity\ConfigEntityListBuilder (for configuration
283  *     entities) or \Drupal\Core\Entity\EntityListBuilder (for content
284  *     entities), to provide an administrative overview for your entities.
285  *   - add and edit forms, or default form: Define a class (or two) that
286  *     extend(s) \Drupal\Core\Entity\EntityForm to provide add and edit forms
287  *     for your entities. For content entities, base class
288  *     \Drupal\Core\Entity\ContentEntityForm is a better starting point.
289  *   - delete form: Define a class that extends
290  *     \Drupal\Core\Entity\EntityConfirmFormBase to provide a delete
291  *     confirmation form for your entities.
292  *   - view_builder: For content entities and config entities that need to be
293  *     viewed, define a class that implements
294  *     \Drupal\Core\Entity\EntityViewBuilderInterface (usually extending
295  *     \Drupal\Core\Entity\EntityViewBuilder), to display a single entity.
296  *   - translation: For translatable content entities (if the 'translatable'
297  *     annotation has value TRUE), define a class that extends
298  *     \Drupal\content_translation\ContentTranslationHandler, to translate
299  *     the content. Configuration translation is handled automatically by the
300  *     Configuration Translation module, without the need of a handler class.
301  *   - access: If your configuration entity has complex permissions, you might
302  *     need an access control handling, implementing
303  *     \Drupal\Core\Entity\EntityAccessControlHandlerInterface, but most entities
304  *     can just use the 'admin_permission' annotation instead. Note that if you
305  *     are creating your own access control handler, you should override the
306  *     checkAccess() and checkCreateAccess() methods, not access().
307  *   - storage: A class implementing
308  *     \Drupal\Core\Entity\EntityStorageInterface. If not specified, content
309  *     entities will use \Drupal\Core\Entity\Sql\SqlContentEntityStorage, and
310  *     config entities will use \Drupal\Core\Config\Entity\ConfigEntityStorage.
311  *     You can extend one of these classes to provide custom behavior.
312  *   - views_data: A class implementing \Drupal\views\EntityViewsDataInterface
313  *     to provide views data for the entity type. You can autogenerate most of
314  *     the views data by extending \Drupal\views\EntityViewsData.
315  * - For content entities, the annotation will refer to a number of database
316  *   tables and their fields. These annotation properties, such as 'base_table',
317  *   'data_table', 'entity_keys', etc., are documented on
318  *   \Drupal\Core\Entity\EntityType.
319  * - For content entities that are displayed on their own pages, the annotation
320  *   will refer to a 'uri_callback' function, which takes an object of the
321  *   entity interface you have defined as its parameter, and returns routing
322  *   information for the entity page; see node_uri() for an example. You will
323  *   also need to add a corresponding route to your module's routing.yml file;
324  *   see the entity.node.canonical route in node.routing.yml for an example, and see
325  *   @ref sec_routes below for some notes.
326  * - Optionally, instead of defining routes, routes can be auto generated by
327  *   providing a route handler. See @ref sec_routes. Otherwise, define routes
328  *   and links for the various URLs associated with the entity.
329  *   These go into the 'links' annotation, with the link type as the key, and
330  *   the path of this link template as the value. The corresponding route
331  *   requires the following route name:
332  *   "entity.$entity_type_id.$link_template_type". See @ref sec_routes below for
333  *   some routing notes. Typical link types are:
334  *   - canonical: Default link, either to view (if entities are viewed on their
335  *     own pages) or edit the entity.
336  *   - delete-form: Confirmation form to delete the entity.
337  *   - edit-form: Editing form.
338  *   - Other link types specific to your entity type can also be defined.
339  * - If your content entity is fieldable, provide 'field_ui_base_route'
340  *   annotation, giving the name of the route that the Manage Fields, Manage
341  *   Display, and Manage Form Display pages from the Field UI module will be
342  *   attached to. This is usually the bundle settings edit page, or an entity
343  *   type settings page if there are no bundles.
344  * - If your content entity has bundles, you will also need to define a second
345  *   plugin to handle the bundles. This plugin is itself a configuration entity
346  *   type, so follow the steps here to define it. The machine name ('id'
347  *   annotation) of this configuration entity class goes into the
348  *   'bundle_entity_type' annotation on the entity type class. For example, for
349  *   the Node entity, the bundle class is \Drupal\node\Entity\NodeType, whose
350  *   machine name is 'node_type'. This is the annotation value for
351  *   'bundle_entity_type' on the \Drupal\node\Entity\Node class. Also, the
352  *   bundle config entity type annotation must have a 'bundle_of' entry,
353  *   giving the machine name of the entity type it is acting as a bundle for.
354  *   These machine names are considered permanent, they may not be renamed.
355  * - Additional annotations can be seen on entity class examples such as
356  *   \Drupal\node\Entity\Node (content) and \Drupal\user\Entity\Role
357  *   (configuration). These annotations are documented on
358  *   \Drupal\Core\Entity\EntityType.
359  *
360  * @section sec_routes Entity routes
361  * Entity routes can be defined in *.routing.yml files, like any other route:
362  * see the @link routing Routing API @endlink topic for more information.
363  * Another option for entity routes is to use a route provider class, and
364  * reference it in the annotations on the entity class: see the end of this
365  * section for an example.
366  *
367  * It's possible to use both a YAML file and a provider class for entity
368  * routes, at the same time. Avoid duplicating route names between the two:
369  * if a duplicate route name is found in both locations, the one in the YAML
370  * file takes precedence; regardless, such duplication can be confusing.
371  *
372  * Here's an example YAML route specification, for the block configure form:
373  * @code
374  * entity.block.edit_form:
375  *   path: '/admin/structure/block/manage/{block}'
376  *   defaults:
377  *     _entity_form: 'block.default'
378  *     _title: 'Configure block'
379  *   requirements:
380  *     _entity_access: 'block.update'
381  * @endcode
382  * Some notes on this example:
383  * - path: The {block} in the path is a placeholder, which (for an entity) must
384  *   always take the form of {machine_name_of_entity_type}. In the URL, the
385  *   placeholder value will be the ID of an entity item. When the route is used,
386  *   the entity system will load the corresponding entity item and pass it in as
387  *   an object to the controller for the route.
388  * - defaults: For entity form routes, use _entity_form rather than the generic
389  *   _controller or _form. The value is composed of the entity type machine name
390  *   and a form handler type from the entity annotation (see @ref define above
391  *   more more on handlers and annotation). So, in this example, block.default
392  *   refers to the 'default' form handler on the block entity type, whose
393  *   annotation contains:
394  *   @code
395  *   handlers = {
396  *     "form" = {
397  *       "default" = "Drupal\block\BlockForm",
398  *   @endcode
399  * If instead of YAML you want to use a route provider class:
400  * - \Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider provides canonical,
401  *   edit-form, and delete-form routes.
402  * - \Drupal\Core\Entity\Routing\AdminHtmlRouteProvider provides the same
403  *   routes, set up to use the administrative theme for edit and delete pages.
404  * - You can also create your own class, extending one of these two classes if
405  *   you only want to modify their behaviour slightly.
406  *
407  * To register any route provider class, add lines like the following to your
408  * entity class annotation:
409  * @code
410  * handlers = {
411  *   "route_provider" = {
412  *     "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider",
413  * @endcode
414  *
415  * @section bundle Defining a content entity bundle
416  * For entity types that use bundles, such as Node (bundles are content types)
417  * and Taxonomy (bundles are vocabularies), modules and install profiles can
418  * define bundles by supplying default configuration in their config/install
419  * directories. (See the @link config_api Configuration API topic @endlink for
420  * general information about configuration.)
421  *
422  * There are several good examples of this in Drupal Core:
423  * - The Forum module defines a content type in node.type.forum.yml and a
424  *   vocabulary in taxonomy.vocabulary.forums.yml
425  * - The Book module defines a content type in node.type.book.yml
426  * - The Standard install profile defines Page and Article content types in
427  *   node.type.page.yml and node.type.article.yml, a Tags vocabulary in
428  *   taxonomy.vocabulary.tags.yml, and a Node comment type in
429  *   comment.type.comment.yml. This profile's configuration is especially
430  *   instructive, because it also adds several fields to the Article type, and
431  *   it sets up view and form display modes for the node types.
432  *
433  * @section load_query Loading, querying, and rendering entities
434  * To load entities, use the entity storage manager, which is an object
435  * implementing \Drupal\Core\Entity\EntityStorageInterface that you can
436  * retrieve with:
437  * @code
438  * $storage = \Drupal::entityManager()->getStorage('your_entity_type');
439  * // Or if you have a $container variable:
440  * $storage = $container->get('entity.manager')->getStorage('your_entity_type');
441  * @endcode
442  * Here, 'your_entity_type' is the machine name of your entity type ('id'
443  * annotation on the entity class), and note that you should use dependency
444  * injection to retrieve this object if possible. See the
445  * @link container Services and Dependency Injection topic @endlink for more
446  * about how to properly retrieve services.
447  *
448  * To query to find entities to load, use an entity query, which is a object
449  * implementing \Drupal\Core\Entity\Query\QueryInterface that you can retrieve
450  * with:
451  * @code
452  * // Simple query:
453  * $query = \Drupal::entityQuery('your_entity_type');
454  * // Or, if you have a $container variable:
455  * $storage = $container->get('entity_type.manager')->getStorage('your_entity_type');
456  * $query = $storage->getQuery();
457  * @endcode
458  * If you need aggregation, there is an aggregate query available, which
459  * implements \Drupal\Core\Entity\Query\QueryAggregateInterface:
460  * @code
461  * $query \Drupal::entityQueryAggregate('your_entity_type');
462  * // Or:
463  * $query = $storage->getAggregateQuery('your_entity_type');
464  * @endcode
465  *
466  * In either case, you can then add conditions to your query, using methods
467  * like condition(), exists(), etc. on $query; add sorting, pager, and range
468  * if needed, and execute the query to return a list of entity IDs that match
469  * the query.
470  *
471  * Here is an example, using the core File entity:
472  * @code
473  * $fids = Drupal::entityQuery('file')
474  *   ->condition('status', FILE_STATUS_PERMANENT, '<>')
475  *   ->condition('changed', REQUEST_TIME - $age, '<')
476  *   ->range(0, 100)
477  *   ->execute();
478  * $files = $storage->loadMultiple($fids);
479  * @endcode
480  *
481  * The normal way of viewing entities is by using a route, as described in the
482  * sections above. If for some reason you need to render an entity in code in a
483  * particular view mode, you can use an entity view builder, which is an object
484  * implementing \Drupal\Core\Entity\EntityViewBuilderInterface that you can
485  * retrieve with:
486  * @code
487  * $view_builder = \Drupal::entityManager()->getViewBuilder('your_entity_type');
488  * // Or if you have a $container variable:
489  * $view_builder = $container->get('entity.manager')->getViewBuilder('your_entity_type');
490  * @endcode
491  * Then, to build and render the entity:
492  * @code
493  * // You can omit the language ID, by default the current content language will
494  * // be used. If no translation is available for the current language, fallback
495  * // rules will be used.
496  * $build = $view_builder->view($entity, 'view_mode_name', $language->getId());
497  * // $build is a render array.
498  * $rendered = drupal_render($build);
499  * @endcode
500  *
501  * @section sec_access Access checking on entities
502  * Entity types define their access permission scheme in their annotation.
503  * Access permissions can be quite complex, so you should not assume any
504  * particular permission scheme. Instead, once you have an entity object
505  * loaded, you can check for permission for a particular operation (such as
506  * 'view') at the entity or field level by calling:
507  * @code
508  * $entity->access($operation);
509  * $entity->nameOfField->access($operation);
510  * @endcode
511  * The interface related to access checking in entities and fields is
512  * \Drupal\Core\Access\AccessibleInterface.
513  *
514  * The default entity access control handler invokes two hooks while checking
515  * access on a single entity: hook_entity_access() is invoked first, and
516  * then hook_ENTITY_TYPE_access() (where ENTITY_TYPE is the machine name
517  * of the entity type). If no module returns a TRUE or FALSE value from
518  * either of these hooks, then the entity's default access checking takes
519  * place. For create operations (creating a new entity), the hooks that
520  * are invoked are hook_entity_create_access() and
521  * hook_ENTITY_TYPE_create_access() instead.
522  *
523  * The Node entity type has a complex system for determining access, which
524  * developers can interact with. This is described in the
525  * @link node_access Node access topic. @endlink
526  *
527  * @see i18n
528  * @see entity_crud
529  * @see \Drupal\Core\Entity\EntityManagerInterface::getTranslationFromContext()
530  * @}
531  */
532
533 /**
534  * @addtogroup hooks
535  * @{
536  */
537
538 /**
539  * Control entity operation access.
540  *
541  * @param \Drupal\Core\Entity\EntityInterface $entity
542  *   The entity to check access to.
543  * @param string $operation
544  *   The operation that is to be performed on $entity.
545  * @param \Drupal\Core\Session\AccountInterface $account
546  *   The account trying to access the entity.
547  *
548  * @return \Drupal\Core\Access\AccessResultInterface
549  *   The access result. The final result is calculated by using
550  *   \Drupal\Core\Access\AccessResultInterface::orIf() on the result of every
551  *   hook_entity_access() and hook_ENTITY_TYPE_access() implementation, and the
552  *   result of the entity-specific checkAccess() method in the entity access
553  *   control handler. Be careful when writing generalized access checks shared
554  *   between routing and entity checks: routing uses the andIf() operator. So
555  *   returning an isNeutral() does not determine entity access at all but it
556  *   always ends up denying access while routing.
557  *
558  * @see \Drupal\Core\Entity\EntityAccessControlHandler
559  * @see hook_entity_create_access()
560  * @see hook_ENTITY_TYPE_access()
561  *
562  * @ingroup entity_api
563  */
564 function hook_entity_access(\Drupal\Core\Entity\EntityInterface $entity, $operation, \Drupal\Core\Session\AccountInterface $account) {
565   // No opinion.
566   return AccessResult::neutral();
567 }
568
569 /**
570  * Control entity operation access for a specific entity type.
571  *
572  * @param \Drupal\Core\Entity\EntityInterface $entity
573  *   The entity to check access to.
574  * @param string $operation
575  *   The operation that is to be performed on $entity.
576  * @param \Drupal\Core\Session\AccountInterface $account
577  *   The account trying to access the entity.
578  *
579  * @return \Drupal\Core\Access\AccessResultInterface
580  *   The access result. hook_entity_access() has detailed documentation.
581  *
582  * @see \Drupal\Core\Entity\EntityAccessControlHandler
583  * @see hook_ENTITY_TYPE_create_access()
584  * @see hook_entity_access()
585  *
586  * @ingroup entity_api
587  */
588 function hook_ENTITY_TYPE_access(\Drupal\Core\Entity\EntityInterface $entity, $operation, \Drupal\Core\Session\AccountInterface $account) {
589   // No opinion.
590   return AccessResult::neutral();
591 }
592
593 /**
594  * Control entity create access.
595  *
596  * @param \Drupal\Core\Session\AccountInterface $account
597  *   The account trying to access the entity.
598  * @param array $context
599  *   An associative array of additional context values. By default it contains
600  *   language and the entity type ID:
601  *   - entity_type_id - the entity type ID.
602  *   - langcode - the current language code.
603  * @param string $entity_bundle
604  *   The entity bundle name.
605  *
606  * @return \Drupal\Core\Access\AccessResultInterface
607  *   The access result.
608  *
609  * @see \Drupal\Core\Entity\EntityAccessControlHandler
610  * @see hook_entity_access()
611  * @see hook_ENTITY_TYPE_create_access()
612  *
613  * @ingroup entity_api
614  */
615 function hook_entity_create_access(\Drupal\Core\Session\AccountInterface $account, array $context, $entity_bundle) {
616   // No opinion.
617   return AccessResult::neutral();
618 }
619
620 /**
621  * Control entity create access for a specific entity type.
622  *
623  * @param \Drupal\Core\Session\AccountInterface $account
624  *   The account trying to access the entity.
625  * @param array $context
626  *   An associative array of additional context values. By default it contains
627  *   language:
628  *   - langcode - the current language code.
629  * @param string $entity_bundle
630  *   The entity bundle name.
631  *
632  * @return \Drupal\Core\Access\AccessResultInterface
633  *   The access result.
634  *
635  * @see \Drupal\Core\Entity\EntityAccessControlHandler
636  * @see hook_ENTITY_TYPE_access()
637  * @see hook_entity_create_access()
638  *
639  * @ingroup entity_api
640  */
641 function hook_ENTITY_TYPE_create_access(\Drupal\Core\Session\AccountInterface $account, array $context, $entity_bundle) {
642   // No opinion.
643   return AccessResult::neutral();
644 }
645
646 /**
647  * Add to entity type definitions.
648  *
649  * Modules may implement this hook to add information to defined entity types,
650  * as defined in \Drupal\Core\Entity\EntityTypeInterface.
651  *
652  * To alter existing information or to add information dynamically, use
653  * hook_entity_type_alter().
654  *
655  * @param \Drupal\Core\Entity\EntityTypeInterface[] $entity_types
656  *   An associative array of all entity type definitions, keyed by the entity
657  *   type name. Passed by reference.
658  *
659  * @see \Drupal\Core\Entity\Entity
660  * @see \Drupal\Core\Entity\EntityTypeInterface
661  * @see hook_entity_type_alter()
662  */
663 function hook_entity_type_build(array &$entity_types) {
664   /** @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
665   // Add a form for a custom node form without overriding the default
666   // node form. To override the default node form, use hook_entity_type_alter().
667   $entity_types['node']->setFormClass('mymodule_foo', 'Drupal\mymodule\NodeFooForm');
668 }
669
670 /**
671  * Alter the entity type definitions.
672  *
673  * Modules may implement this hook to alter the information that defines an
674  * entity type. All properties that are available in
675  * \Drupal\Core\Entity\Annotation\EntityType and all the ones additionally
676  * provided by modules can be altered here.
677  *
678  * Do not use this hook to add information to entity types, unless one of the
679  * following is true:
680  * - You are filling in default values.
681  * - You need to dynamically add information only in certain circumstances.
682  * - Your hook needs to run after hook_entity_type_build() implementations.
683  * Use hook_entity_type_build() instead in all other cases.
684  *
685  * @param \Drupal\Core\Entity\EntityTypeInterface[] $entity_types
686  *   An associative array of all entity type definitions, keyed by the entity
687  *   type name. Passed by reference.
688  *
689  * @see \Drupal\Core\Entity\Entity
690  * @see \Drupal\Core\Entity\EntityTypeInterface
691  */
692 function hook_entity_type_alter(array &$entity_types) {
693   /** @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
694   // Set the controller class for nodes to an alternate implementation of the
695   // Drupal\Core\Entity\EntityStorageInterface interface.
696   $entity_types['node']->setStorageClass('Drupal\mymodule\MyCustomNodeStorage');
697 }
698
699 /**
700  * Alter the view modes for entity types.
701  *
702  * @param array $view_modes
703  *   An array of view modes, keyed first by entity type, then by view mode name.
704  *
705  * @see \Drupal\Core\Entity\EntityManagerInterface::getAllViewModes()
706  * @see \Drupal\Core\Entity\EntityManagerInterface::getViewModes()
707  */
708 function hook_entity_view_mode_info_alter(&$view_modes) {
709   $view_modes['user']['full']['status'] = TRUE;
710 }
711
712 /**
713  * Describe the bundles for entity types.
714  *
715  * @return array
716  *   An associative array of all entity bundles, keyed by the entity
717  *   type name, and then the bundle name, with the following keys:
718  *   - label: The human-readable name of the bundle.
719  *   - uri_callback: The same as the 'uri_callback' key defined for the entity
720  *     type in the EntityManager, but for the bundle only. When determining
721  *     the URI of an entity, if a 'uri_callback' is defined for both the
722  *     entity type and the bundle, the one for the bundle is used.
723  *   - translatable: (optional) A boolean value specifying whether this bundle
724  *     has translation support enabled. Defaults to FALSE.
725  *
726  * @see \Drupal\Core\Entity\EntityTypeBundleInfo::getBundleInfo()
727  * @see hook_entity_bundle_info_alter()
728  */
729 function hook_entity_bundle_info() {
730   $bundles['user']['user']['label'] = t('User');
731   return $bundles;
732 }
733
734 /**
735  * Alter the bundles for entity types.
736  *
737  * @param array $bundles
738  *   An array of bundles, keyed first by entity type, then by bundle name.
739  *
740  * @see Drupal\Core\Entity\EntityTypeBundleInfo::getBundleInfo()
741  * @see hook_entity_bundle_info()
742  */
743 function hook_entity_bundle_info_alter(&$bundles) {
744   $bundles['user']['user']['label'] = t('Full account');
745 }
746
747 /**
748  * Act on entity_bundle_create().
749  *
750  * This hook is invoked after the operation has been performed.
751  *
752  * @param string $entity_type_id
753  *   The type of $entity; e.g. 'node' or 'user'.
754  * @param string $bundle
755  *   The name of the bundle.
756  *
757  * @see entity_crud
758  */
759 function hook_entity_bundle_create($entity_type_id, $bundle) {
760   // When a new bundle is created, the menu needs to be rebuilt to add the
761   // Field UI menu item tabs.
762   \Drupal::service('router.builder')->setRebuildNeeded();
763 }
764
765 /**
766  * Act on entity_bundle_delete().
767  *
768  * This hook is invoked after the operation has been performed.
769  *
770  * @param string $entity_type_id
771  *   The type of entity; for example, 'node' or 'user'.
772  * @param string $bundle
773  *   The bundle that was just deleted.
774  *
775  * @ingroup entity_crud
776  */
777 function hook_entity_bundle_delete($entity_type_id, $bundle) {
778   // Remove the settings associated with the bundle in my_module.settings.
779   $config = \Drupal::config('my_module.settings');
780   $bundle_settings = $config->get('bundle_settings');
781   if (isset($bundle_settings[$entity_type_id][$bundle])) {
782     unset($bundle_settings[$entity_type_id][$bundle]);
783     $config->set('bundle_settings', $bundle_settings);
784   }
785 }
786
787 /**
788  * Acts when creating a new entity.
789  *
790  * This hook runs after a new entity object has just been instantiated.
791  *
792  * @param \Drupal\Core\Entity\EntityInterface $entity
793  *   The entity object.
794  *
795  * @ingroup entity_crud
796  * @see hook_ENTITY_TYPE_create()
797  */
798 function hook_entity_create(\Drupal\Core\Entity\EntityInterface $entity) {
799   \Drupal::logger('example')->info('Entity created: @label', ['@label' => $entity->label()]);
800 }
801
802 /**
803  * Acts when creating a new entity of a specific type.
804  *
805  * This hook runs after a new entity object has just been instantiated.
806  *
807  * @param \Drupal\Core\Entity\EntityInterface $entity
808  *   The entity object.
809  *
810  * @ingroup entity_crud
811  * @see hook_entity_create()
812  */
813 function hook_ENTITY_TYPE_create(\Drupal\Core\Entity\EntityInterface $entity) {
814   \Drupal::logger('example')->info('ENTITY_TYPE created: @label', ['@label' => $entity->label()]);
815 }
816
817 /**
818  * Act on entities when loaded.
819  *
820  * This is a generic load hook called for all entity types loaded via the
821  * entity API.
822  *
823  * hook_entity_storage_load() should be used to load additional data for
824  * content entities.
825  *
826  * @param \Drupal\Core\Entity\EntityInterface[] $entities
827  *   The entities keyed by entity ID.
828  * @param string $entity_type_id
829  *   The type of entities being loaded (i.e. node, user, comment).
830  *
831  * @ingroup entity_crud
832  * @see hook_ENTITY_TYPE_load()
833  */
834 function hook_entity_load(array $entities, $entity_type_id) {
835   foreach ($entities as $entity) {
836     $entity->foo = mymodule_add_something($entity);
837   }
838 }
839
840 /**
841  * Act on entities of a specific type when loaded.
842  *
843  * @param array $entities
844  *   The entities keyed by entity ID.
845  *
846  * @ingroup entity_crud
847  * @see hook_entity_load()
848  */
849 function hook_ENTITY_TYPE_load($entities) {
850   foreach ($entities as $entity) {
851     $entity->foo = mymodule_add_something($entity);
852   }
853 }
854
855 /**
856  * Act on content entities when loaded from the storage.
857  *
858  * The results of this hook will be cached.
859  *
860  * @param \Drupal\Core\Entity\EntityInterface[] $entities
861  *   The entities keyed by entity ID.
862  * @param string $entity_type
863  *   The type of entities being loaded (i.e. node, user, comment).
864  *
865  * @see hook_entity_load()
866  */
867 function hook_entity_storage_load(array $entities, $entity_type) {
868   foreach ($entities as $entity) {
869     $entity->foo = mymodule_add_something_uncached($entity);
870   }
871 }
872
873 /**
874  * Act on content entities of a given type when loaded from the storage.
875  *
876  * The results of this hook will be cached if the entity type supports it.
877  *
878  * @param \Drupal\Core\Entity\EntityInterface[] $entities
879  *   The entities keyed by entity ID.
880  *
881  * @see hook_entity_storage_load()
882  */
883 function hook_ENTITY_TYPE_storage_load(array $entities) {
884   foreach ($entities as $entity) {
885     $entity->foo = mymodule_add_something_uncached($entity);
886   }
887 }
888
889 /**
890  * Act on an entity before it is created or updated.
891  *
892  * You can get the original entity object from $entity->original when it is an
893  * update of the entity.
894  *
895  * @param \Drupal\Core\Entity\EntityInterface $entity
896  *   The entity object.
897  *
898  * @ingroup entity_crud
899  * @see hook_ENTITY_TYPE_presave()
900  */
901 function hook_entity_presave(Drupal\Core\Entity\EntityInterface $entity) {
902   if ($entity instanceof ContentEntityInterface && $entity->isTranslatable()) {
903     $route_match = \Drupal::routeMatch();
904     \Drupal::service('content_translation.synchronizer')->synchronizeFields($entity, $entity->language()->getId(), $route_match->getParameter('source_langcode'));
905   }
906 }
907
908 /**
909  * Act on a specific type of entity before it is created or updated.
910  *
911  * You can get the original entity object from $entity->original when it is an
912  * update of the entity.
913  *
914  * @param \Drupal\Core\Entity\EntityInterface $entity
915  *   The entity object.
916  *
917  * @ingroup entity_crud
918  * @see hook_entity_presave()
919  */
920 function hook_ENTITY_TYPE_presave(Drupal\Core\Entity\EntityInterface $entity) {
921   if ($entity->isTranslatable()) {
922     $route_match = \Drupal::routeMatch();
923     \Drupal::service('content_translation.synchronizer')->synchronizeFields($entity, $entity->language()->getId(), $route_match->getParameter('source_langcode'));
924   }
925 }
926
927 /**
928  * Respond to creation of a new entity.
929  *
930  * This hook runs once the entity has been stored. Note that hook
931  * implementations may not alter the stored entity data.
932  *
933  * @param \Drupal\Core\Entity\EntityInterface $entity
934  *   The entity object.
935  *
936  * @ingroup entity_crud
937  * @see hook_ENTITY_TYPE_insert()
938  */
939 function hook_entity_insert(Drupal\Core\Entity\EntityInterface $entity) {
940   // Insert the new entity into a fictional table of all entities.
941   db_insert('example_entity')
942     ->fields([
943       'type' => $entity->getEntityTypeId(),
944       'id' => $entity->id(),
945       'created' => REQUEST_TIME,
946       'updated' => REQUEST_TIME,
947     ])
948     ->execute();
949 }
950
951 /**
952  * Respond to creation of a new entity of a particular type.
953  *
954  * This hook runs once the entity has been stored. Note that hook
955  * implementations may not alter the stored entity data.
956  *
957  * @param \Drupal\Core\Entity\EntityInterface $entity
958  *   The entity object.
959  *
960  * @ingroup entity_crud
961  * @see hook_entity_insert()
962  */
963 function hook_ENTITY_TYPE_insert(Drupal\Core\Entity\EntityInterface $entity) {
964   // Insert the new entity into a fictional table of this type of entity.
965   db_insert('example_entity')
966     ->fields([
967       'id' => $entity->id(),
968       'created' => REQUEST_TIME,
969       'updated' => REQUEST_TIME,
970     ])
971     ->execute();
972 }
973
974 /**
975  * Respond to updates to an entity.
976  *
977  * This hook runs once the entity storage has been updated. Note that hook
978  * implementations may not alter the stored entity data. Get the original entity
979  * object from $entity->original.
980  *
981  * @param \Drupal\Core\Entity\EntityInterface $entity
982  *   The entity object.
983  *
984  * @ingroup entity_crud
985  * @see hook_ENTITY_TYPE_update()
986  */
987 function hook_entity_update(Drupal\Core\Entity\EntityInterface $entity) {
988   // Update the entity's entry in a fictional table of all entities.
989   db_update('example_entity')
990     ->fields([
991       'updated' => REQUEST_TIME,
992     ])
993     ->condition('type', $entity->getEntityTypeId())
994     ->condition('id', $entity->id())
995     ->execute();
996 }
997
998 /**
999  * Respond to updates to an entity of a particular type.
1000  *
1001  * This hook runs once the entity storage has been updated. Note that hook
1002  * implementations may not alter the stored entity data. Get the original entity
1003  * object from $entity->original.
1004  *
1005  * @param \Drupal\Core\Entity\EntityInterface $entity
1006  *   The entity object.
1007  *
1008  * @ingroup entity_crud
1009  * @see hook_entity_update()
1010  */
1011 function hook_ENTITY_TYPE_update(Drupal\Core\Entity\EntityInterface $entity) {
1012   // Update the entity's entry in a fictional table of this type of entity.
1013   db_update('example_entity')
1014     ->fields([
1015       'updated' => REQUEST_TIME,
1016     ])
1017     ->condition('id', $entity->id())
1018     ->execute();
1019 }
1020
1021 /**
1022  * Acts when creating a new entity translation.
1023  *
1024  * This hook runs after a new entity translation object has just been
1025  * instantiated.
1026  *
1027  * @param \Drupal\Core\Entity\EntityInterface $translation
1028  *   The entity object.
1029  *
1030  * @ingroup entity_crud
1031  * @see hook_ENTITY_TYPE_translation_create()
1032  */
1033 function hook_entity_translation_create(\Drupal\Core\Entity\EntityInterface $translation) {
1034   \Drupal::logger('example')->info('Entity translation created: @label', ['@label' => $translation->label()]);
1035 }
1036
1037 /**
1038  * Acts when creating a new entity translation of a specific type.
1039  *
1040  * This hook runs after a new entity translation object has just been
1041  * instantiated.
1042  *
1043  * @param \Drupal\Core\Entity\EntityInterface $translation
1044  *   The entity object.
1045  *
1046  * @ingroup entity_crud
1047  * @see hook_entity_translation_create()
1048  */
1049 function hook_ENTITY_TYPE_translation_create(\Drupal\Core\Entity\EntityInterface $translation) {
1050   \Drupal::logger('example')->info('ENTITY_TYPE translation created: @label', ['@label' => $translation->label()]);
1051 }
1052
1053 /**
1054  * Respond to creation of a new entity translation.
1055  *
1056  * This hook runs once the entity translation has been stored. Note that hook
1057  * implementations may not alter the stored entity translation data.
1058  *
1059  * @param \Drupal\Core\Entity\EntityInterface $translation
1060  *   The entity object of the translation just stored.
1061  *
1062  * @ingroup entity_crud
1063  * @see hook_ENTITY_TYPE_translation_insert()
1064  */
1065 function hook_entity_translation_insert(\Drupal\Core\Entity\EntityInterface $translation) {
1066   $variables = [
1067     '@language' => $translation->language()->getName(),
1068     '@label' => $translation->getUntranslated()->label(),
1069   ];
1070   \Drupal::logger('example')->notice('The @language translation of @label has just been stored.', $variables);
1071 }
1072
1073 /**
1074  * Respond to creation of a new entity translation of a particular type.
1075  *
1076  * This hook runs once the entity translation has been stored. Note that hook
1077  * implementations may not alter the stored entity translation data.
1078  *
1079  * @param \Drupal\Core\Entity\EntityInterface $translation
1080  *   The entity object of the translation just stored.
1081  *
1082  * @ingroup entity_crud
1083  * @see hook_entity_translation_insert()
1084  */
1085 function hook_ENTITY_TYPE_translation_insert(\Drupal\Core\Entity\EntityInterface $translation) {
1086   $variables = [
1087     '@language' => $translation->language()->getName(),
1088     '@label' => $translation->getUntranslated()->label(),
1089   ];
1090   \Drupal::logger('example')->notice('The @language translation of @label has just been stored.', $variables);
1091 }
1092
1093 /**
1094  * Respond to entity translation deletion.
1095  *
1096  * This hook runs once the entity translation has been deleted from storage.
1097  *
1098  * @param \Drupal\Core\Entity\EntityInterface $translation
1099  *   The original entity object.
1100  *
1101  * @ingroup entity_crud
1102  * @see hook_ENTITY_TYPE_translation_delete()
1103  */
1104 function hook_entity_translation_delete(\Drupal\Core\Entity\EntityInterface $translation) {
1105   $variables = [
1106     '@language' => $translation->language()->getName(),
1107     '@label' => $translation->label(),
1108   ];
1109   \Drupal::logger('example')->notice('The @language translation of @label has just been deleted.', $variables);
1110 }
1111
1112 /**
1113  * Respond to entity translation deletion of a particular type.
1114  *
1115  * This hook runs once the entity translation has been deleted from storage.
1116  *
1117  * @param \Drupal\Core\Entity\EntityInterface $translation
1118  *   The original entity object.
1119  *
1120  * @ingroup entity_crud
1121  * @see hook_entity_translation_delete()
1122  */
1123 function hook_ENTITY_TYPE_translation_delete(\Drupal\Core\Entity\EntityInterface $translation) {
1124   $variables = [
1125     '@language' => $translation->language()->getName(),
1126     '@label' => $translation->label(),
1127   ];
1128   \Drupal::logger('example')->notice('The @language translation of @label has just been deleted.', $variables);
1129 }
1130
1131 /**
1132  * Act before entity deletion.
1133  *
1134  * @param \Drupal\Core\Entity\EntityInterface $entity
1135  *   The entity object for the entity that is about to be deleted.
1136  *
1137  * @ingroup entity_crud
1138  * @see hook_ENTITY_TYPE_predelete()
1139  */
1140 function hook_entity_predelete(Drupal\Core\Entity\EntityInterface $entity) {
1141   // Count references to this entity in a custom table before they are removed
1142   // upon entity deletion.
1143   $id = $entity->id();
1144   $type = $entity->getEntityTypeId();
1145   $count = db_select('example_entity_data')
1146     ->condition('type', $type)
1147     ->condition('id', $id)
1148     ->countQuery()
1149     ->execute()
1150     ->fetchField();
1151
1152   // Log the count in a table that records this statistic for deleted entities.
1153   db_merge('example_deleted_entity_statistics')
1154     ->key(['type' => $type, 'id' => $id])
1155     ->fields(['count' => $count])
1156     ->execute();
1157 }
1158
1159 /**
1160  * Act before entity deletion of a particular entity type.
1161  *
1162  * @param \Drupal\Core\Entity\EntityInterface $entity
1163  *   The entity object for the entity that is about to be deleted.
1164  *
1165  * @ingroup entity_crud
1166  * @see hook_entity_predelete()
1167  */
1168 function hook_ENTITY_TYPE_predelete(Drupal\Core\Entity\EntityInterface $entity) {
1169   // Count references to this entity in a custom table before they are removed
1170   // upon entity deletion.
1171   $id = $entity->id();
1172   $type = $entity->getEntityTypeId();
1173   $count = db_select('example_entity_data')
1174     ->condition('type', $type)
1175     ->condition('id', $id)
1176     ->countQuery()
1177     ->execute()
1178     ->fetchField();
1179
1180   // Log the count in a table that records this statistic for deleted entities.
1181   db_merge('example_deleted_entity_statistics')
1182     ->key(['type' => $type, 'id' => $id])
1183     ->fields(['count' => $count])
1184     ->execute();
1185 }
1186
1187 /**
1188  * Respond to entity deletion.
1189  *
1190  * This hook runs once the entity has been deleted from the storage.
1191  *
1192  * @param \Drupal\Core\Entity\EntityInterface $entity
1193  *   The entity object for the entity that has been deleted.
1194  *
1195  * @ingroup entity_crud
1196  * @see hook_ENTITY_TYPE_delete()
1197  */
1198 function hook_entity_delete(Drupal\Core\Entity\EntityInterface $entity) {
1199   // Delete the entity's entry from a fictional table of all entities.
1200   db_delete('example_entity')
1201     ->condition('type', $entity->getEntityTypeId())
1202     ->condition('id', $entity->id())
1203     ->execute();
1204 }
1205
1206 /**
1207  * Respond to entity deletion of a particular type.
1208  *
1209  * This hook runs once the entity has been deleted from the storage.
1210  *
1211  * @param \Drupal\Core\Entity\EntityInterface $entity
1212  *   The entity object for the entity that has been deleted.
1213  *
1214  * @ingroup entity_crud
1215  * @see hook_entity_delete()
1216  */
1217 function hook_ENTITY_TYPE_delete(Drupal\Core\Entity\EntityInterface $entity) {
1218   // Delete the entity's entry from a fictional table of all entities.
1219   db_delete('example_entity')
1220     ->condition('type', $entity->getEntityTypeId())
1221     ->condition('id', $entity->id())
1222     ->execute();
1223 }
1224
1225 /**
1226  * Respond to entity revision deletion.
1227  *
1228  * This hook runs once the entity revision has been deleted from the storage.
1229  *
1230  * @param \Drupal\Core\Entity\EntityInterface $entity
1231  *   The entity object for the entity revision that has been deleted.
1232  *
1233  * @ingroup entity_crud
1234  * @see hook_ENTITY_TYPE_revision_delete()
1235  */
1236 function hook_entity_revision_delete(Drupal\Core\Entity\EntityInterface $entity) {
1237   $referenced_files_by_field = _editor_get_file_uuids_by_field($entity);
1238   foreach ($referenced_files_by_field as $field => $uuids) {
1239     _editor_delete_file_usage($uuids, $entity, 1);
1240   }
1241 }
1242
1243 /**
1244  * Respond to entity revision deletion of a particular type.
1245  *
1246  * This hook runs once the entity revision has been deleted from the storage.
1247  *
1248  * @param \Drupal\Core\Entity\EntityInterface $entity
1249  *   The entity object for the entity revision that has been deleted.
1250  *
1251  * @ingroup entity_crud
1252  * @see hook_entity_revision_delete()
1253  */
1254 function hook_ENTITY_TYPE_revision_delete(Drupal\Core\Entity\EntityInterface $entity) {
1255   $referenced_files_by_field = _editor_get_file_uuids_by_field($entity);
1256   foreach ($referenced_files_by_field as $field => $uuids) {
1257     _editor_delete_file_usage($uuids, $entity, 1);
1258   }
1259 }
1260
1261 /**
1262  * Act on entities being assembled before rendering.
1263  *
1264  * @param &$build
1265  *   A renderable array representing the entity content. The module may add
1266  *   elements to $build prior to rendering. The structure of $build is a
1267  *   renderable array as expected by drupal_render().
1268  * @param \Drupal\Core\Entity\EntityInterface $entity
1269  *   The entity object.
1270  * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display
1271  *   The entity view display holding the display options configured for the
1272  *   entity components.
1273  * @param $view_mode
1274  *   The view mode the entity is rendered in.
1275  *
1276  * @see hook_entity_view_alter()
1277  * @see hook_ENTITY_TYPE_view()
1278  *
1279  * @ingroup entity_crud
1280  */
1281 function hook_entity_view(array &$build, \Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display, $view_mode) {
1282   // Only do the extra work if the component is configured to be displayed.
1283   // This assumes a 'mymodule_addition' extra field has been defined for the
1284   // entity bundle in hook_entity_extra_field_info().
1285   if ($display->getComponent('mymodule_addition')) {
1286     $build['mymodule_addition'] = [
1287       '#markup' => mymodule_addition($entity),
1288       '#theme' => 'mymodule_my_additional_field',
1289     ];
1290   }
1291 }
1292
1293 /**
1294  * Act on entities of a particular type being assembled before rendering.
1295  *
1296  * @param &$build
1297  *   A renderable array representing the entity content. The module may add
1298  *   elements to $build prior to rendering. The structure of $build is a
1299  *   renderable array as expected by drupal_render().
1300  * @param \Drupal\Core\Entity\EntityInterface $entity
1301  *   The entity object.
1302  * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display
1303  *   The entity view display holding the display options configured for the
1304  *   entity components.
1305  * @param $view_mode
1306  *   The view mode the entity is rendered in.
1307  *
1308  * @see hook_ENTITY_TYPE_view_alter()
1309  * @see hook_entity_view()
1310  *
1311  * @ingroup entity_crud
1312  */
1313 function hook_ENTITY_TYPE_view(array &$build, \Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display, $view_mode) {
1314   // Only do the extra work if the component is configured to be displayed.
1315   // This assumes a 'mymodule_addition' extra field has been defined for the
1316   // entity bundle in hook_entity_extra_field_info().
1317   if ($display->getComponent('mymodule_addition')) {
1318     $build['mymodule_addition'] = [
1319       '#markup' => mymodule_addition($entity),
1320       '#theme' => 'mymodule_my_additional_field',
1321     ];
1322   }
1323 }
1324
1325 /**
1326  * Alter the results of the entity build array.
1327  *
1328  * This hook is called after the content has been assembled in a structured
1329  * array and may be used for doing processing which requires that the complete
1330  * entity content structure has been built.
1331  *
1332  * If a module wishes to act on the rendered HTML of the entity rather than the
1333  * structured content array, it may use this hook to add a #post_render
1334  * callback. Alternatively, it could also implement hook_preprocess_HOOK() for
1335  * the particular entity type template, if there is one (e.g., node.html.twig).
1336  *
1337  * See the @link themeable Default theme implementations topic @endlink and
1338  * drupal_render() for details.
1339  *
1340  * @param array &$build
1341  *   A renderable array representing the entity content.
1342  * @param \Drupal\Core\Entity\EntityInterface $entity
1343  *   The entity object being rendered.
1344  * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display
1345  *   The entity view display holding the display options configured for the
1346  *   entity components.
1347  *
1348  * @ingroup entity_crud
1349  *
1350  * @see hook_entity_view()
1351  * @see hook_ENTITY_TYPE_view_alter()
1352  */
1353 function hook_entity_view_alter(array &$build, Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display) {
1354   if ($build['#view_mode'] == 'full' && isset($build['an_additional_field'])) {
1355     // Change its weight.
1356     $build['an_additional_field']['#weight'] = -10;
1357
1358     // Add a #post_render callback to act on the rendered HTML of the entity.
1359     $build['#post_render'][] = 'my_module_node_post_render';
1360   }
1361 }
1362
1363 /**
1364  * Alter the results of the entity build array for a particular entity type.
1365  *
1366  * This hook is called after the content has been assembled in a structured
1367  * array and may be used for doing processing which requires that the complete
1368  * entity content structure has been built.
1369  *
1370  * If a module wishes to act on the rendered HTML of the entity rather than the
1371  * structured content array, it may use this hook to add a #post_render
1372  * callback. Alternatively, it could also implement hook_preprocess_HOOK() for
1373  * the particular entity type template, if there is one (e.g., node.html.twig).
1374  *
1375  * See the @link themeable Default theme implementations topic @endlink and
1376  * drupal_render() for details.
1377  *
1378  * @param array &$build
1379  *   A renderable array representing the entity content.
1380  * @param \Drupal\Core\Entity\EntityInterface $entity
1381  *   The entity object being rendered.
1382  * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display
1383  *   The entity view display holding the display options configured for the
1384  *   entity components.
1385  *
1386  * @ingroup entity_crud
1387  *
1388  * @see hook_ENTITY_TYPE_view()
1389  * @see hook_entity_view_alter()
1390  */
1391 function hook_ENTITY_TYPE_view_alter(array &$build, Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display) {
1392   if ($build['#view_mode'] == 'full' && isset($build['an_additional_field'])) {
1393     // Change its weight.
1394     $build['an_additional_field']['#weight'] = -10;
1395
1396     // Add a #post_render callback to act on the rendered HTML of the entity.
1397     $build['#post_render'][] = 'my_module_node_post_render';
1398   }
1399 }
1400
1401 /**
1402  * Act on entities as they are being prepared for view.
1403  *
1404  * Allows you to operate on multiple entities as they are being prepared for
1405  * view. Only use this if attaching the data during the entity loading phase
1406  * is not appropriate, for example when attaching other 'entity' style objects.
1407  *
1408  * @param string $entity_type_id
1409  *   The type of entities being viewed (i.e. node, user, comment).
1410  * @param array $entities
1411  *   The entities keyed by entity ID.
1412  * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface[] $displays
1413  *   The array of entity view displays holding the display options configured
1414  *   for the entity components, keyed by bundle name.
1415  * @param string $view_mode
1416  *   The view mode.
1417  *
1418  * @ingroup entity_crud
1419  */
1420 function hook_entity_prepare_view($entity_type_id, array $entities, array $displays, $view_mode) {
1421   // Load a specific node into the user object for later theming.
1422   if (!empty($entities) && $entity_type_id == 'user') {
1423     // Only do the extra work if the component is configured to be
1424     // displayed. This assumes a 'mymodule_addition' extra field has been
1425     // defined for the entity bundle in hook_entity_extra_field_info().
1426     $ids = [];
1427     foreach ($entities as $id => $entity) {
1428       if ($displays[$entity->bundle()]->getComponent('mymodule_addition')) {
1429         $ids[] = $id;
1430       }
1431     }
1432     if ($ids) {
1433       $nodes = mymodule_get_user_nodes($ids);
1434       foreach ($ids as $id) {
1435         $entities[$id]->user_node = $nodes[$id];
1436       }
1437     }
1438   }
1439 }
1440
1441 /**
1442  * Change the view mode of an entity that is being displayed.
1443  *
1444  * @param string $view_mode
1445  *   The view_mode that is to be used to display the entity.
1446  * @param \Drupal\Core\Entity\EntityInterface $entity
1447  *   The entity that is being viewed.
1448  * @param array $context
1449  *   Array with additional context information, currently only contains the
1450  *   langcode the entity is viewed in.
1451  *
1452  * @ingroup entity_crud
1453  */
1454 function hook_entity_view_mode_alter(&$view_mode, Drupal\Core\Entity\EntityInterface $entity, $context) {
1455   // For nodes, change the view mode when it is teaser.
1456   if ($entity->getEntityTypeId() == 'node' && $view_mode == 'teaser') {
1457     $view_mode = 'my_custom_view_mode';
1458   }
1459 }
1460
1461 /**
1462  * Alter entity renderable values before cache checking in drupal_render().
1463  *
1464  * Invoked for a specific entity type.
1465  *
1466  * The values in the #cache key of the renderable array are used to determine if
1467  * a cache entry exists for the entity's rendered output. Ideally only values
1468  * that pertain to caching should be altered in this hook.
1469  *
1470  * @param array &$build
1471  *   A renderable array containing the entity's caching and view mode values.
1472  * @param \Drupal\Core\Entity\EntityInterface $entity
1473  *   The entity that is being viewed.
1474  * @param string $view_mode
1475  *   The view_mode that is to be used to display the entity.
1476  *
1477  * @see drupal_render()
1478  * @see \Drupal\Core\Entity\EntityViewBuilder
1479  * @see hook_entity_build_defaults_alter()
1480  *
1481  * @ingroup entity_crud
1482  */
1483 function hook_ENTITY_TYPE_build_defaults_alter(array &$build, \Drupal\Core\Entity\EntityInterface $entity, $view_mode) {
1484
1485 }
1486
1487 /**
1488  * Alter entity renderable values before cache checking in drupal_render().
1489  *
1490  * The values in the #cache key of the renderable array are used to determine if
1491  * a cache entry exists for the entity's rendered output. Ideally only values
1492  * that pertain to caching should be altered in this hook.
1493  *
1494  * @param array &$build
1495  *   A renderable array containing the entity's caching and view mode values.
1496  * @param \Drupal\Core\Entity\EntityInterface $entity
1497  *   The entity that is being viewed.
1498  * @param string $view_mode
1499  *   The view_mode that is to be used to display the entity.
1500  *
1501  * @see drupal_render()
1502  * @see \Drupal\Core\Entity\EntityViewBuilder
1503  * @see hook_ENTITY_TYPE_build_defaults_alter()
1504  *
1505  * @ingroup entity_crud
1506  */
1507 function hook_entity_build_defaults_alter(array &$build, \Drupal\Core\Entity\EntityInterface $entity, $view_mode) {
1508
1509 }
1510
1511 /**
1512  * Alter the settings used for displaying an entity.
1513  *
1514  * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display
1515  *   The entity view display that will be used to display the entity
1516  *   components.
1517  * @param array $context
1518  *   An associative array containing:
1519  *   - entity_type: The entity type, e.g., 'node' or 'user'.
1520  *   - bundle: The bundle, e.g., 'page' or 'article'.
1521  *   - view_mode: The view mode, e.g., 'full', 'teaser', etc.
1522  *
1523  * @ingroup entity_crud
1524  */
1525 function hook_entity_view_display_alter(\Drupal\Core\Entity\Display\EntityViewDisplayInterface $display, array $context) {
1526   // Leave field labels out of the search index.
1527   if ($context['entity_type'] == 'node' && $context['view_mode'] == 'search_index') {
1528     foreach ($display->getComponents() as $name => $options) {
1529       if (isset($options['label'])) {
1530         $options['label'] = 'hidden';
1531         $display->setComponent($name, $options);
1532       }
1533     }
1534   }
1535 }
1536
1537 /**
1538  * Alter the render array generated by an EntityDisplay for an entity.
1539  *
1540  * @param array $build
1541  *   The renderable array generated by the EntityDisplay.
1542  * @param array $context
1543  *   An associative array containing:
1544  *   - entity: The entity being rendered.
1545  *   - view_mode: The view mode; for example, 'full' or 'teaser'.
1546  *   - display: The EntityDisplay holding the display options.
1547  *
1548  * @ingroup entity_crud
1549  */
1550 function hook_entity_display_build_alter(&$build, $context) {
1551   // Append RDF term mappings on displayed taxonomy links.
1552   foreach (Element::children($build) as $field_name) {
1553     $element = &$build[$field_name];
1554     if ($element['#field_type'] == 'entity_reference' && $element['#formatter'] == 'entity_reference_label') {
1555       foreach ($element['#items'] as $delta => $item) {
1556         $term = $item->entity;
1557         if (!empty($term->rdf_mapping['rdftype'])) {
1558           $element[$delta]['#options']['attributes']['typeof'] = $term->rdf_mapping['rdftype'];
1559         }
1560         if (!empty($term->rdf_mapping['name']['predicates'])) {
1561           $element[$delta]['#options']['attributes']['property'] = $term->rdf_mapping['name']['predicates'];
1562         }
1563       }
1564     }
1565   }
1566 }
1567
1568 /**
1569  * Acts on an entity object about to be shown on an entity form.
1570  *
1571  * This can be typically used to pre-fill entity values or change the form state
1572  * before the entity form is built. It is invoked just once when first building
1573  * the entity form. Rebuilds will not trigger a new invocation.
1574  *
1575  * @param \Drupal\Core\Entity\EntityInterface $entity
1576  *   The entity that is about to be shown on the form.
1577  * @param $operation
1578  *   The current operation.
1579  * @param \Drupal\Core\Form\FormStateInterface $form_state
1580  *   The current state of the form.
1581  *
1582  * @see \Drupal\Core\Entity\EntityForm::prepareEntity()
1583  * @see hook_ENTITY_TYPE_prepare_form()
1584  *
1585  * @ingroup entity_crud
1586  */
1587 function hook_entity_prepare_form(\Drupal\Core\Entity\EntityInterface $entity, $operation, \Drupal\Core\Form\FormStateInterface $form_state) {
1588   if ($operation == 'edit') {
1589     $entity->label->value = 'Altered label';
1590     $form_state->set('label_altered', TRUE);
1591   }
1592 }
1593
1594 /**
1595  * Acts on a particular type of entity object about to be in an entity form.
1596  *
1597  * This can be typically used to pre-fill entity values or change the form state
1598  * before the entity form is built. It is invoked just once when first building
1599  * the entity form. Rebuilds will not trigger a new invocation.
1600  *
1601  * @param \Drupal\Core\Entity\EntityInterface $entity
1602  *   The entity that is about to be shown on the form.
1603  * @param $operation
1604  *   The current operation.
1605  * @param \Drupal\Core\Form\FormStateInterface $form_state
1606  *   The current state of the form.
1607  *
1608  * @see \Drupal\Core\Entity\EntityForm::prepareEntity()
1609  * @see hook_entity_prepare_form()
1610  *
1611  * @ingroup entity_crud
1612  */
1613 function hook_ENTITY_TYPE_prepare_form(\Drupal\Core\Entity\EntityInterface $entity, $operation, \Drupal\Core\Form\FormStateInterface $form_state) {
1614   if ($operation == 'edit') {
1615     $entity->label->value = 'Altered label';
1616     $form_state->set('label_altered', TRUE);
1617   }
1618 }
1619
1620 /**
1621  * Alter the settings used for displaying an entity form.
1622  *
1623  * @param \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display
1624  *   The entity_form_display object that will be used to display the entity form
1625  *   components.
1626  * @param array $context
1627  *   An associative array containing:
1628  *   - entity_type: The entity type, e.g., 'node' or 'user'.
1629  *   - bundle: The bundle, e.g., 'page' or 'article'.
1630  *   - form_mode: The form mode; e.g., 'default', 'profile', 'register', etc.
1631  *
1632  * @ingroup entity_crud
1633  */
1634 function hook_entity_form_display_alter(\Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display, array $context) {
1635   // Hide the 'user_picture' field from the register form.
1636   if ($context['entity_type'] == 'user' && $context['form_mode'] == 'register') {
1637     $form_display->setComponent('user_picture', [
1638       'region' => 'hidden',
1639     ]);
1640   }
1641 }
1642
1643 /**
1644  * Provides custom base field definitions for a content entity type.
1645  *
1646  * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
1647  *   The entity type definition.
1648  *
1649  * @return \Drupal\Core\Field\FieldDefinitionInterface[]
1650  *   An array of field definitions, keyed by field name.
1651  *
1652  * @see hook_entity_base_field_info_alter()
1653  * @see hook_entity_bundle_field_info()
1654  * @see hook_entity_bundle_field_info_alter()
1655  * @see \Drupal\Core\Field\FieldDefinitionInterface
1656  * @see \Drupal\Core\Entity\EntityManagerInterface::getFieldDefinitions()
1657  */
1658 function hook_entity_base_field_info(\Drupal\Core\Entity\EntityTypeInterface $entity_type) {
1659   if ($entity_type->id() == 'node') {
1660     $fields = [];
1661     $fields['mymodule_text'] = BaseFieldDefinition::create('string')
1662       ->setLabel(t('The text'))
1663       ->setDescription(t('A text property added by mymodule.'))
1664       ->setComputed(TRUE)
1665       ->setClass('\Drupal\mymodule\EntityComputedText');
1666
1667     return $fields;
1668   }
1669 }
1670
1671 /**
1672  * Alter base field definitions for a content entity type.
1673  *
1674  * @param \Drupal\Core\Field\FieldDefinitionInterface[] $fields
1675  *   The array of base field definitions for the entity type.
1676  * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
1677  *   The entity type definition.
1678  *
1679  * @see hook_entity_base_field_info()
1680  * @see hook_entity_bundle_field_info()
1681  * @see hook_entity_bundle_field_info_alter()
1682  *
1683  * @todo WARNING: This hook will be changed in
1684  * https://www.drupal.org/node/2346329.
1685  */
1686 function hook_entity_base_field_info_alter(&$fields, \Drupal\Core\Entity\EntityTypeInterface $entity_type) {
1687   // Alter the mymodule_text field to use a custom class.
1688   if ($entity_type->id() == 'node' && !empty($fields['mymodule_text'])) {
1689     $fields['mymodule_text']->setClass('\Drupal\anothermodule\EntityComputedText');
1690   }
1691 }
1692
1693 /**
1694  * Provides field definitions for a specific bundle within an entity type.
1695  *
1696  * Bundle fields either have to override an existing base field, or need to
1697  * provide a field storage definition via hook_entity_field_storage_info()
1698  * unless they are computed.
1699  *
1700  * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
1701  *   The entity type definition.
1702  * @param string $bundle
1703  *   The bundle.
1704  * @param \Drupal\Core\Field\FieldDefinitionInterface[] $base_field_definitions
1705  *   The list of base field definitions for the entity type.
1706  *
1707  * @return \Drupal\Core\Field\FieldDefinitionInterface[]
1708  *   An array of bundle field definitions, keyed by field name.
1709  *
1710  * @see hook_entity_base_field_info()
1711  * @see hook_entity_base_field_info_alter()
1712  * @see hook_entity_field_storage_info()
1713  * @see hook_entity_field_storage_info_alter()
1714  * @see hook_entity_bundle_field_info_alter()
1715  * @see \Drupal\Core\Field\FieldDefinitionInterface
1716  * @see \Drupal\Core\Entity\EntityManagerInterface::getFieldDefinitions()
1717  *
1718  * @todo WARNING: This hook will be changed in
1719  * https://www.drupal.org/node/2346347.
1720  */
1721 function hook_entity_bundle_field_info(\Drupal\Core\Entity\EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) {
1722   // Add a property only to nodes of the 'article' bundle.
1723   if ($entity_type->id() == 'node' && $bundle == 'article') {
1724     $fields = [];
1725     $fields['mymodule_text_more'] = BaseFieldDefinition::create('string')
1726       ->setLabel(t('More text'))
1727       ->setComputed(TRUE)
1728       ->setClass('\Drupal\mymodule\EntityComputedMoreText');
1729     return $fields;
1730   }
1731 }
1732
1733 /**
1734  * Alter bundle field definitions.
1735  *
1736  * @param \Drupal\Core\Field\FieldDefinitionInterface[] $fields
1737  *   The array of bundle field definitions.
1738  * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
1739  *   The entity type definition.
1740  * @param string $bundle
1741  *   The bundle.
1742  *
1743  * @see hook_entity_base_field_info()
1744  * @see hook_entity_base_field_info_alter()
1745  * @see hook_entity_bundle_field_info()
1746  *
1747  * @todo WARNING: This hook will be changed in
1748  * https://www.drupal.org/node/2346347.
1749  */
1750 function hook_entity_bundle_field_info_alter(&$fields, \Drupal\Core\Entity\EntityTypeInterface $entity_type, $bundle) {
1751   if ($entity_type->id() == 'node' && $bundle == 'article' && !empty($fields['mymodule_text'])) {
1752     // Alter the mymodule_text field to use a custom class.
1753     $fields['mymodule_text']->setClass('\Drupal\anothermodule\EntityComputedText');
1754   }
1755 }
1756
1757 /**
1758  * Provides field storage definitions for a content entity type.
1759  *
1760  * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
1761  *   The entity type definition.
1762  *
1763  * @return \Drupal\Core\Field\FieldStorageDefinitionInterface[]
1764  *   An array of field storage definitions, keyed by field name.
1765  *
1766  * @see hook_entity_field_storage_info_alter()
1767  * @see \Drupal\Core\Field\FieldStorageDefinitionInterface
1768  * @see \Drupal\Core\Entity\EntityManagerInterface::getFieldStorageDefinitions()
1769  */
1770 function hook_entity_field_storage_info(\Drupal\Core\Entity\EntityTypeInterface $entity_type) {
1771   if (\Drupal::entityManager()->getStorage($entity_type->id()) instanceof DynamicallyFieldableEntityStorageInterface) {
1772     // Query by filtering on the ID as this is more efficient than filtering
1773     // on the entity_type property directly.
1774     $ids = \Drupal::entityQuery('field_storage_config')
1775       ->condition('id', $entity_type->id() . '.', 'STARTS_WITH')
1776       ->execute();
1777     // Fetch all fields and key them by field name.
1778     $field_storages = FieldStorageConfig::loadMultiple($ids);
1779     $result = [];
1780     foreach ($field_storages as $field_storage) {
1781       $result[$field_storage->getName()] = $field_storage;
1782     }
1783
1784     return $result;
1785   }
1786 }
1787
1788 /**
1789  * Alter field storage definitions for a content entity type.
1790  *
1791  * @param \Drupal\Core\Field\FieldStorageDefinitionInterface[] $fields
1792  *   The array of field storage definitions for the entity type.
1793  * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
1794  *   The entity type definition.
1795  *
1796  * @see hook_entity_field_storage_info()
1797  */
1798 function hook_entity_field_storage_info_alter(&$fields, \Drupal\Core\Entity\EntityTypeInterface $entity_type) {
1799   // Alter the max_length setting.
1800   if ($entity_type->id() == 'node' && !empty($fields['mymodule_text'])) {
1801     $fields['mymodule_text']->setSetting('max_length', 128);
1802   }
1803 }
1804
1805 /**
1806  * Declares entity operations.
1807  *
1808  * @param \Drupal\Core\Entity\EntityInterface $entity
1809  *   The entity on which the linked operations will be performed.
1810  *
1811  * @return array
1812  *   An operations array as returned by
1813  *   EntityListBuilderInterface::getOperations().
1814  *
1815  * @see \Drupal\Core\Entity\EntityListBuilderInterface::getOperations()
1816  */
1817 function hook_entity_operation(\Drupal\Core\Entity\EntityInterface $entity) {
1818   $operations = [];
1819   $operations['translate'] = [
1820     'title' => t('Translate'),
1821     'url' => \Drupal\Core\Url::fromRoute('foo_module.entity.translate'),
1822     'weight' => 50,
1823   ];
1824
1825   return $operations;
1826 }
1827
1828 /**
1829  * Alter entity operations.
1830  *
1831  * @param array $operations
1832  *   Operations array as returned by
1833  *   \Drupal\Core\Entity\EntityListBuilderInterface::getOperations().
1834  * @param \Drupal\Core\Entity\EntityInterface $entity
1835  *   The entity on which the linked operations will be performed.
1836  */
1837 function hook_entity_operation_alter(array &$operations, \Drupal\Core\Entity\EntityInterface $entity) {
1838   // Alter the title and weight.
1839   $operations['translate']['title'] = t('Translate @entity_type', [
1840     '@entity_type' => $entity->getEntityTypeId(),
1841   ]);
1842   $operations['translate']['weight'] = 99;
1843 }
1844
1845 /**
1846  * Control access to fields.
1847  *
1848  * This hook is invoked from
1849  * \Drupal\Core\Entity\EntityAccessControlHandler::fieldAccess() to let modules
1850  * grant or deny operations on fields.
1851  *
1852  * @param string $operation
1853  *   The operation to be performed. See
1854  *   \Drupal\Core\Entity\EntityAccessControlHandlerInterface::fieldAccess()
1855  *   for possible values.
1856  * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
1857  *   The field definition.
1858  * @param \Drupal\Core\Session\AccountInterface $account
1859  *   The user account to check.
1860  * @param \Drupal\Core\Field\FieldItemListInterface $items
1861  *   (optional) The entity field object on which the operation is to be
1862  *   performed.
1863  *
1864  * @return \Drupal\Core\Access\AccessResultInterface
1865  *   The access result.
1866  *
1867  * @see \Drupal\Core\Entity\EntityAccessControlHandlerInterface::fieldAccess()
1868  */
1869 function hook_entity_field_access($operation, \Drupal\Core\Field\FieldDefinitionInterface $field_definition, \Drupal\Core\Session\AccountInterface $account, \Drupal\Core\Field\FieldItemListInterface $items = NULL) {
1870   if ($field_definition->getName() == 'field_of_interest' && $operation == 'edit') {
1871     return AccessResult::allowedIfHasPermission($account, 'update field of interest');
1872   }
1873   return AccessResult::neutral();
1874 }
1875
1876 /**
1877  * Alter the default access behavior for a given field.
1878  *
1879  * Use this hook to override access grants from another module. Note that the
1880  * original default access flag is masked under the ':default' key.
1881  *
1882  * @param \Drupal\Core\Access\AccessResultInterface[] $grants
1883  *   An array of grants gathered by hook_entity_field_access(). The array is
1884  *   keyed by the module that defines the field's access control; the values are
1885  *   grant responses for each module (\Drupal\Core\Access\AccessResult).
1886  * @param array $context
1887  *   Context array on the performed operation with the following keys:
1888  *   - operation: The operation to be performed (string).
1889  *   - field_definition: The field definition object
1890  *     (\Drupal\Core\Field\FieldDefinitionInterface)
1891  *   - account: The user account to check access for
1892  *     (Drupal\user\Entity\User).
1893  *   - items: (optional) The entity field items
1894  *     (\Drupal\Core\Field\FieldItemListInterface).
1895  */
1896 function hook_entity_field_access_alter(array &$grants, array $context) {
1897   /** @var \Drupal\Core\Field\FieldDefinitionInterface $field_definition */
1898   $field_definition = $context['field_definition'];
1899   if ($field_definition->getName() == 'field_of_interest' && $grants['node']->isForbidden()) {
1900     // Override node module's restriction to no opinion (neither allowed nor
1901     // forbidden). We don't want to provide our own access hook, we only want to
1902     // take out node module's part in the access handling of this field. We also
1903     // don't want to switch node module's grant to
1904     // AccessResultInterface::isAllowed() , because the grants of other modules
1905     // should still decide on their own if this field is accessible or not
1906     $grants['node'] = AccessResult::neutral()->inheritCacheability($grants['node']);
1907   }
1908 }
1909
1910 /**
1911  * Acts when initializing a fieldable entity object.
1912  *
1913  * This hook runs after a new entity object or a new entity translation object
1914  * has just been instantiated. It can be used to set initial values, e.g. to
1915  * provide defaults.
1916  *
1917  * @param \Drupal\Core\Entity\FieldableEntityInterface $entity
1918  *   The entity object.
1919  *
1920  * @ingroup entity_crud
1921  * @see hook_ENTITY_TYPE_field_values_init()
1922  */
1923 function hook_entity_field_values_init(\Drupal\Core\Entity\FieldableEntityInterface $entity) {
1924   if ($entity instanceof \Drupal\Core\Entity\ContentEntityInterface && !$entity->foo->value) {
1925     $entity->foo->value = 'some_initial_value';
1926   }
1927 }
1928
1929 /**
1930  * Acts when initializing a fieldable entity object.
1931  *
1932  * This hook runs after a new entity object or a new entity translation object
1933  * has just been instantiated. It can be used to set initial values, e.g. to
1934  * provide defaults.
1935  *
1936  * @param \Drupal\Core\Entity\FieldableEntityInterface $entity
1937  *   The entity object.
1938  *
1939  * @ingroup entity_crud
1940  * @see hook_entity_field_values_init()
1941  */
1942 function hook_ENTITY_TYPE_field_values_init(\Drupal\Core\Entity\FieldableEntityInterface $entity) {
1943   if (!$entity->foo->value) {
1944     $entity->foo->value = 'some_initial_value';
1945   }
1946 }
1947
1948 /**
1949  * Exposes "pseudo-field" components on content entities.
1950  *
1951  * Field UI's "Manage fields" and "Manage display" pages let users re-order
1952  * fields, but also non-field components. For nodes, these include elements
1953  * exposed by modules through hook_form_alter(), for instance.
1954  *
1955  * Content entities or modules that want to have their components supported
1956  * should expose them using this hook. The user-defined settings (weight,
1957  * visible) are automatically applied when entities or entity forms are
1958  * rendered.
1959  *
1960  * @see hook_entity_extra_field_info_alter()
1961  *
1962  * @return array
1963  *   The array structure is identical to that of the return value of
1964  *   \Drupal\Core\Entity\EntityFieldManagerInterface::getExtraFields().
1965  */
1966 function hook_entity_extra_field_info() {
1967   $extra = [];
1968   $module_language_enabled = \Drupal::moduleHandler()->moduleExists('language');
1969   $description = t('Node module element');
1970
1971   foreach (NodeType::loadMultiple() as $bundle) {
1972
1973     // Add also the 'language' select if Language module is enabled and the
1974     // bundle has multilingual support.
1975     // Visibility of the ordering of the language selector is the same as on the
1976     // node/add form.
1977     if ($module_language_enabled) {
1978       $configuration = ContentLanguageSettings::loadByEntityTypeBundle('node', $bundle->id());
1979       if ($configuration->isLanguageAlterable()) {
1980         $extra['node'][$bundle->id()]['form']['language'] = [
1981           'label' => t('Language'),
1982           'description' => $description,
1983           'weight' => 0,
1984         ];
1985       }
1986     }
1987     $extra['node'][$bundle->id()]['display']['language'] = [
1988       'label' => t('Language'),
1989       'description' => $description,
1990       'weight' => 0,
1991       'visible' => FALSE,
1992     ];
1993   }
1994
1995   return $extra;
1996 }
1997
1998 /**
1999  * Alter "pseudo-field" components on content entities.
2000  *
2001  * @param array $info
2002  *   The array structure is identical to that of the return value of
2003  *   \Drupal\Core\Entity\EntityManagerInterface::getExtraFields().
2004  *
2005  * @see hook_entity_extra_field_info()
2006  */
2007 function hook_entity_extra_field_info_alter(&$info) {
2008   // Force node title to always be at the top of the list by default.
2009   foreach (NodeType::loadMultiple() as $bundle) {
2010     if (isset($info['node'][$bundle->id()]['form']['title'])) {
2011       $info['node'][$bundle->id()]['form']['title']['weight'] = -20;
2012     }
2013   }
2014 }
2015
2016 /**
2017  * @} End of "addtogroup hooks".
2018  */