1. 8.2.x core/lib/Drupal/Core/Entity/entity.api.php
  2. 8.0.x core/lib/Drupal/Core/Entity/entity.api.php
  3. 8.1.x core/lib/Drupal/Core/Entity/entity.api.php
  4. 8.3.x core/lib/Drupal/Core/Entity/entity.api.php

Hooks and documentation related to entities.

File

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

Functions

Namesort descending Description
hook_entity_access Control entity operation access.
hook_entity_base_field_info Provides custom base field definitions for a content entity type.
hook_entity_base_field_info_alter Alter base field definitions for a content entity type.
hook_entity_build_defaults_alter Alter entity renderable values before cache checking in drupal_render().
hook_entity_bundle_create Act on entity_bundle_create().
hook_entity_bundle_delete Act on entity_bundle_delete().
hook_entity_bundle_field_info Provides field definitions for a specific bundle within an entity type.
hook_entity_bundle_field_info_alter Alter bundle field definitions.
hook_entity_bundle_info Describe the bundles for entity types.
hook_entity_bundle_info_alter Alter the bundles for entity types.
hook_entity_create Acts when creating a new entity.
hook_entity_create_access Control entity create access.
hook_entity_delete Respond to entity deletion.
hook_entity_display_build_alter Alter the render array generated by an EntityDisplay for an entity.
hook_entity_extra_field_info Exposes "pseudo-field" components on content entities.
hook_entity_extra_field_info_alter Alter "pseudo-field" components on content entities.
hook_entity_field_access Control access to fields.
hook_entity_field_access_alter Alter the default access behavior for a given field.
hook_entity_field_storage_info Provides field storage definitions for a content entity type.
hook_entity_field_storage_info_alter Alter field storage definitions for a content entity type.
hook_entity_field_values_init Acts when initializing a fieldable entity object.
hook_entity_form_display_alter Alter the settings used for displaying an entity form.
hook_entity_insert Respond to creation of a new entity.
hook_entity_load Act on entities when loaded.
hook_entity_operation Declares entity operations.
hook_entity_operation_alter Alter entity operations.
hook_entity_predelete Act before entity deletion.
hook_entity_prepare_form Acts on an entity object about to be shown on an entity form.
hook_entity_prepare_view Act on entities as they are being prepared for view.
hook_entity_presave Act on an entity before it is created or updated.
hook_entity_revision_delete Respond to entity revision deletion.
hook_entity_storage_load Act on content entities when loaded from the storage.
hook_entity_translation_create Acts when creating a new entity translation.
hook_entity_translation_delete Respond to entity translation deletion.
hook_entity_translation_insert Respond to creation of a new entity translation.
hook_ENTITY_TYPE_access Control entity operation access for a specific entity type.
hook_entity_type_alter Alter the entity type definitions.
hook_entity_type_build Add to entity type definitions.
hook_ENTITY_TYPE_build_defaults_alter Alter entity renderable values before cache checking in drupal_render().
hook_ENTITY_TYPE_create Acts when creating a new entity of a specific type.
hook_ENTITY_TYPE_create_access Control entity create access for a specific entity type.
hook_ENTITY_TYPE_delete Respond to entity deletion of a particular type.
hook_ENTITY_TYPE_field_values_init Acts when initializing a fieldable entity object.
hook_ENTITY_TYPE_insert Respond to creation of a new entity of a particular type.
hook_ENTITY_TYPE_load Act on entities of a specific type when loaded.
hook_ENTITY_TYPE_predelete Act before entity deletion of a particular entity type.
hook_ENTITY_TYPE_prepare_form Acts on a particular type of entity object about to be in an entity form.
hook_ENTITY_TYPE_presave Act on a specific type of entity before it is created or updated.
hook_ENTITY_TYPE_revision_delete Respond to entity revision deletion of a particular type.
hook_ENTITY_TYPE_storage_load Act on content entities of a given type when loaded from the storage.
hook_ENTITY_TYPE_translation_create Acts when creating a new entity translation of a specific type.
hook_ENTITY_TYPE_translation_delete Respond to entity translation deletion of a particular type.
hook_ENTITY_TYPE_translation_insert Respond to creation of a new entity translation of a particular type.
hook_ENTITY_TYPE_update Respond to updates to an entity of a particular type.
hook_ENTITY_TYPE_view Act on entities of a particular type being assembled before rendering.
hook_ENTITY_TYPE_view_alter Alter the results of the entity build array for a particular entity type.
hook_entity_update Respond to updates to an entity.
hook_entity_view Act on entities being assembled before rendering.
hook_entity_view_alter Alter the results of the entity build array.
hook_entity_view_display_alter Alter the settings used for displaying an entity.
hook_entity_view_mode_alter Change the view mode of an entity that is being displayed.
hook_entity_view_mode_info_alter Alter the view modes for entity types.