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