EntityType.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940
  1. <?php
  2. namespace Drupal\Core\Entity;
  3. use Drupal\Component\Plugin\Definition\PluginDefinition;
  4. use Drupal\Core\DependencyInjection\DependencySerializationTrait;
  5. use Drupal\Core\Entity\Exception\EntityTypeIdLengthException;
  6. use Drupal\Core\StringTranslation\StringTranslationTrait;
  7. use Drupal\Core\StringTranslation\TranslatableMarkup;
  8. /**
  9. * Provides an implementation of an entity type and its metadata.
  10. *
  11. * @ingroup entity_api
  12. */
  13. class EntityType extends PluginDefinition implements EntityTypeInterface {
  14. use DependencySerializationTrait;
  15. use StringTranslationTrait;
  16. /**
  17. * Indicates whether entities should be statically cached.
  18. *
  19. * @var bool
  20. */
  21. protected $static_cache = TRUE;
  22. /**
  23. * Indicates whether the rendered output of entities should be cached.
  24. *
  25. * @var bool
  26. */
  27. protected $render_cache = TRUE;
  28. /**
  29. * Indicates if the persistent cache of field data should be used.
  30. *
  31. * @var bool
  32. */
  33. protected $persistent_cache = TRUE;
  34. /**
  35. * An array of entity keys.
  36. *
  37. * @var array
  38. */
  39. protected $entity_keys = [];
  40. /**
  41. * The unique identifier of this entity type.
  42. *
  43. * @var string
  44. */
  45. protected $id;
  46. /**
  47. * The name of the original entity type class.
  48. *
  49. * This is only set if the class name is changed.
  50. *
  51. * @var string
  52. */
  53. protected $originalClass;
  54. /**
  55. * An array of handlers.
  56. *
  57. * @var array
  58. */
  59. protected $handlers = [];
  60. /**
  61. * The name of the default administrative permission.
  62. *
  63. * @var string
  64. */
  65. protected $admin_permission;
  66. /**
  67. * The permission granularity level.
  68. *
  69. * The allowed values are respectively "entity_type" or "bundle".
  70. *
  71. * @var string
  72. */
  73. protected $permission_granularity = 'entity_type';
  74. /**
  75. * Link templates using the URI template syntax.
  76. *
  77. * @var array
  78. */
  79. protected $links = [];
  80. /**
  81. * The name of a callback that returns the label of the entity.
  82. *
  83. * @var callable|null
  84. *
  85. * @deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Override the
  86. * EntityInterface::label() method instead for dynamic labels.
  87. *
  88. * @see \Drupal\Core\Entity\EntityInterface::label()
  89. */
  90. protected $label_callback = NULL;
  91. /**
  92. * The name of the entity type which provides bundles.
  93. *
  94. * @var string
  95. */
  96. protected $bundle_entity_type = NULL;
  97. /**
  98. * The name of the entity type for which bundles are provided.
  99. *
  100. * @var string|null
  101. */
  102. protected $bundle_of = NULL;
  103. /**
  104. * The human-readable name of the entity bundles, e.g. Vocabulary.
  105. *
  106. * @var string|null
  107. */
  108. protected $bundle_label = NULL;
  109. /**
  110. * The name of the entity type's base table.
  111. *
  112. * @var string|null
  113. */
  114. protected $base_table = NULL;
  115. /**
  116. * The name of the entity type's revision data table.
  117. *
  118. * @var string|null
  119. */
  120. protected $revision_data_table = NULL;
  121. /**
  122. * The name of the entity type's revision table.
  123. *
  124. * @var string|null
  125. */
  126. protected $revision_table = NULL;
  127. /**
  128. * The name of the entity type's data table.
  129. *
  130. * @var string|null
  131. */
  132. protected $data_table = NULL;
  133. /**
  134. * Indicates whether the entity data is internal.
  135. *
  136. * @var bool
  137. */
  138. protected $internal = FALSE;
  139. /**
  140. * Indicates whether entities of this type have multilingual support.
  141. *
  142. * @var bool
  143. */
  144. protected $translatable = FALSE;
  145. /**
  146. * Indicates whether the revision form fields should be added to the form.
  147. *
  148. * @var bool
  149. */
  150. protected $show_revision_ui = FALSE;
  151. /**
  152. * The human-readable name of the type.
  153. *
  154. * @var string|\Drupal\Core\StringTranslation\TranslatableMarkup
  155. *
  156. * @see \Drupal\Core\Entity\EntityTypeInterface::getLabel()
  157. */
  158. protected $label = '';
  159. /**
  160. * The human-readable label for a collection of entities of the type.
  161. *
  162. * @var string|\Drupal\Core\StringTranslation\TranslatableMarkup
  163. *
  164. * @see \Drupal\Core\Entity\EntityTypeInterface::getCollectionLabel()
  165. */
  166. protected $label_collection = '';
  167. /**
  168. * The indefinite singular name of the type.
  169. *
  170. * @var string|\Drupal\Core\StringTranslation\TranslatableMarkup
  171. *
  172. * @see \Drupal\Core\Entity\EntityTypeInterface::getSingularLabel()
  173. */
  174. protected $label_singular = '';
  175. /**
  176. * The indefinite plural name of the type.
  177. *
  178. * @var string|\Drupal\Core\StringTranslation\TranslatableMarkup
  179. *
  180. * @see \Drupal\Core\Entity\EntityTypeInterface::getPluralLabel()
  181. */
  182. protected $label_plural = '';
  183. /**
  184. * A definite singular/plural name of the type.
  185. *
  186. * Needed keys: "singular" and "plural".
  187. *
  188. * @var string|\Drupal\Core\StringTranslation\TranslatableMarkup
  189. *
  190. * @see \Drupal\Core\Entity\EntityTypeInterface::getCountLabel()
  191. */
  192. protected $label_count = [];
  193. /**
  194. * A callable that can be used to provide the entity URI.
  195. *
  196. * @var callable|null
  197. */
  198. protected $uri_callback = NULL;
  199. /**
  200. * The machine name of the entity type group.
  201. *
  202. * @var string
  203. */
  204. protected $group;
  205. /**
  206. * The human-readable name of the entity type group.
  207. *
  208. * @var string|\Drupal\Core\StringTranslation\TranslatableMarkup
  209. *
  210. * @see \Drupal\Core\Entity\EntityTypeInterface::getGroupLabel()
  211. */
  212. protected $group_label;
  213. /**
  214. * The route name used by field UI to attach its management pages.
  215. *
  216. * @var string
  217. */
  218. protected $field_ui_base_route;
  219. /**
  220. * Indicates whether this entity type is commonly used as a reference target.
  221. *
  222. * This is used by the Entity reference field to promote an entity type in the
  223. * add new field select list in Field UI.
  224. *
  225. * @var bool
  226. */
  227. protected $common_reference_target = FALSE;
  228. /**
  229. * The list cache contexts for this entity type.
  230. *
  231. * @var string[]
  232. */
  233. protected $list_cache_contexts = [];
  234. /**
  235. * The list cache tags for this entity type.
  236. *
  237. * @var string[]
  238. */
  239. protected $list_cache_tags = [];
  240. /**
  241. * Entity constraint definitions.
  242. *
  243. * @var array[]
  244. */
  245. protected $constraints = [];
  246. /**
  247. * Any additional properties and values.
  248. *
  249. * @var array
  250. */
  251. protected $additional = [];
  252. /**
  253. * Constructs a new EntityType.
  254. *
  255. * @param array $definition
  256. * An array of values from the annotation.
  257. *
  258. * @throws \Drupal\Core\Entity\Exception\EntityTypeIdLengthException
  259. * Thrown when attempting to instantiate an entity type with too long ID.
  260. */
  261. public function __construct($definition) {
  262. // Throw an exception if the entity type ID is longer than 32 characters.
  263. if (mb_strlen($definition['id']) > static::ID_MAX_LENGTH) {
  264. throw new EntityTypeIdLengthException('Attempt to create an entity type with an ID longer than ' . static::ID_MAX_LENGTH . " characters: {$definition['id']}.");
  265. }
  266. foreach ($definition as $property => $value) {
  267. $this->set($property, $value);
  268. }
  269. // Ensure defaults.
  270. $this->entity_keys += [
  271. 'revision' => '',
  272. 'bundle' => '',
  273. 'langcode' => '',
  274. 'default_langcode' => 'default_langcode',
  275. 'revision_translation_affected' => 'revision_translation_affected',
  276. ];
  277. $this->handlers += [
  278. 'access' => 'Drupal\Core\Entity\EntityAccessControlHandler',
  279. ];
  280. if (isset($this->handlers['storage'])) {
  281. $this->checkStorageClass($this->handlers['storage']);
  282. }
  283. // Automatically add the "EntityChanged" constraint if the entity type
  284. // tracks the changed time.
  285. if ($this->entityClassImplements(EntityChangedInterface::class)) {
  286. $this->addConstraint('EntityChanged');
  287. }
  288. // Automatically add the "EntityUntranslatableFields" constraint if we have
  289. // an entity type supporting translatable fields and pending revisions.
  290. if ($this->entityClassImplements(ContentEntityInterface::class)) {
  291. $this->addConstraint('EntityUntranslatableFields');
  292. }
  293. // Ensure a default list cache tag is set.
  294. if (empty($this->list_cache_tags)) {
  295. $this->list_cache_tags = [$definition['id'] . '_list'];
  296. }
  297. }
  298. /**
  299. * {@inheritdoc}
  300. */
  301. public function get($property) {
  302. if (property_exists($this, $property)) {
  303. $value = isset($this->{$property}) ? $this->{$property} : NULL;
  304. }
  305. else {
  306. $value = isset($this->additional[$property]) ? $this->additional[$property] : NULL;
  307. }
  308. return $value;
  309. }
  310. /**
  311. * {@inheritdoc}
  312. */
  313. public function set($property, $value) {
  314. if (property_exists($this, $property)) {
  315. $this->{$property} = $value;
  316. }
  317. else {
  318. $this->additional[$property] = $value;
  319. }
  320. return $this;
  321. }
  322. /**
  323. * {@inheritdoc}
  324. */
  325. public function isInternal() {
  326. return $this->internal;
  327. }
  328. /**
  329. * {@inheritdoc}
  330. */
  331. public function isStaticallyCacheable() {
  332. return $this->static_cache;
  333. }
  334. /**
  335. * {@inheritdoc}
  336. */
  337. public function isRenderCacheable() {
  338. return $this->render_cache;
  339. }
  340. /**
  341. * {@inheritdoc}
  342. */
  343. public function isPersistentlyCacheable() {
  344. return $this->persistent_cache;
  345. }
  346. /**
  347. * {@inheritdoc}
  348. */
  349. public function getKeys() {
  350. return $this->entity_keys;
  351. }
  352. /**
  353. * {@inheritdoc}
  354. */
  355. public function getKey($key) {
  356. $keys = $this->getKeys();
  357. return isset($keys[$key]) ? $keys[$key] : FALSE;
  358. }
  359. /**
  360. * {@inheritdoc}
  361. */
  362. public function hasKey($key) {
  363. $keys = $this->getKeys();
  364. return !empty($keys[$key]);
  365. }
  366. /**
  367. * {@inheritdoc}
  368. */
  369. public function getOriginalClass() {
  370. return $this->originalClass ?: $this->class;
  371. }
  372. /**
  373. * {@inheritdoc}
  374. */
  375. public function setClass($class) {
  376. if (!$this->originalClass && $this->class) {
  377. // If the original class is currently not set, set it to the current
  378. // class, assume that is the original class name.
  379. $this->originalClass = $this->class;
  380. }
  381. return parent::setClass($class);
  382. }
  383. /**
  384. * {@inheritdoc}
  385. */
  386. public function entityClassImplements($interface) {
  387. return is_subclass_of($this->getClass(), $interface);
  388. }
  389. /**
  390. * {@inheritdoc}
  391. */
  392. public function isSubclassOf($class) {
  393. @trigger_error(__METHOD__ . '() is deprecated in drupal:8.3.0 and is removed from drupal:10.0.0. Use Drupal\Core\Entity\EntityTypeInterface::entityClassImplements() instead. See https://www.drupal.org/node/2842808', E_USER_DEPRECATED);
  394. return $this->entityClassImplements($class);
  395. }
  396. /**
  397. * {@inheritdoc}
  398. */
  399. public function getHandlerClasses() {
  400. return $this->handlers;
  401. }
  402. /**
  403. * {@inheritdoc}
  404. */
  405. public function getHandlerClass($handler_type, $nested = FALSE) {
  406. if ($this->hasHandlerClass($handler_type, $nested)) {
  407. $handlers = $this->getHandlerClasses();
  408. return $nested ? $handlers[$handler_type][$nested] : $handlers[$handler_type];
  409. }
  410. return NULL;
  411. }
  412. /**
  413. * {@inheritdoc}
  414. */
  415. public function setHandlerClass($handler_type, $value) {
  416. $this->handlers[$handler_type] = $value;
  417. return $this;
  418. }
  419. /**
  420. * {@inheritdoc}
  421. */
  422. public function hasHandlerClass($handler_type, $nested = FALSE) {
  423. $handlers = $this->getHandlerClasses();
  424. if (!isset($handlers[$handler_type]) || ($nested && !isset($handlers[$handler_type][$nested]))) {
  425. return FALSE;
  426. }
  427. $handler = $handlers[$handler_type];
  428. if ($nested) {
  429. $handler = $handler[$nested];
  430. }
  431. return class_exists($handler);
  432. }
  433. /**
  434. * {@inheritdoc}
  435. */
  436. public function getStorageClass() {
  437. return $this->getHandlerClass('storage');
  438. }
  439. /**
  440. * {@inheritdoc}
  441. */
  442. public function setStorageClass($class) {
  443. $this->checkStorageClass($class);
  444. $this->handlers['storage'] = $class;
  445. return $this;
  446. }
  447. /**
  448. * Checks that the provided class is compatible with the current entity type.
  449. *
  450. * @param string $class
  451. * The class to check.
  452. */
  453. protected function checkStorageClass($class) {
  454. // Nothing to check by default.
  455. }
  456. /**
  457. * {@inheritdoc}
  458. */
  459. public function getFormClass($operation) {
  460. return $this->getHandlerClass('form', $operation);
  461. }
  462. /**
  463. * {@inheritdoc}
  464. */
  465. public function setFormClass($operation, $class) {
  466. $this->handlers['form'][$operation] = $class;
  467. return $this;
  468. }
  469. /**
  470. * {@inheritdoc}
  471. */
  472. public function hasFormClasses() {
  473. return !empty($this->handlers['form']);
  474. }
  475. /**
  476. * {@inheritdoc}
  477. */
  478. public function hasRouteProviders() {
  479. return !empty($this->handlers['route_provider']);
  480. }
  481. /**
  482. * {@inheritdoc}
  483. */
  484. public function getListBuilderClass() {
  485. return $this->getHandlerClass('list_builder');
  486. }
  487. /**
  488. * {@inheritdoc}
  489. */
  490. public function setListBuilderClass($class) {
  491. $this->handlers['list_builder'] = $class;
  492. return $this;
  493. }
  494. /**
  495. * {@inheritdoc}
  496. */
  497. public function hasListBuilderClass() {
  498. return $this->hasHandlerClass('list_builder');
  499. }
  500. /**
  501. * {@inheritdoc}
  502. */
  503. public function getViewBuilderClass() {
  504. return $this->getHandlerClass('view_builder');
  505. }
  506. /**
  507. * {@inheritdoc}
  508. */
  509. public function setViewBuilderClass($class) {
  510. $this->handlers['view_builder'] = $class;
  511. return $this;
  512. }
  513. /**
  514. * {@inheritdoc}
  515. */
  516. public function hasViewBuilderClass() {
  517. return $this->hasHandlerClass('view_builder');
  518. }
  519. /**
  520. * {@inheritdoc}
  521. */
  522. public function getRouteProviderClasses() {
  523. return !empty($this->handlers['route_provider']) ? $this->handlers['route_provider'] : [];
  524. }
  525. /**
  526. * {@inheritdoc}
  527. */
  528. public function getAccessControlClass() {
  529. return $this->getHandlerClass('access');
  530. }
  531. /**
  532. * {@inheritdoc}
  533. */
  534. public function setAccessClass($class) {
  535. $this->handlers['access'] = $class;
  536. return $this;
  537. }
  538. /**
  539. * {@inheritdoc}
  540. */
  541. public function getAdminPermission() {
  542. return $this->admin_permission ?: FALSE;
  543. }
  544. /**
  545. * {@inheritdoc}
  546. */
  547. public function getPermissionGranularity() {
  548. return $this->permission_granularity;
  549. }
  550. /**
  551. * {@inheritdoc}
  552. */
  553. public function getLinkTemplates() {
  554. return $this->links;
  555. }
  556. /**
  557. * {@inheritdoc}
  558. */
  559. public function getLinkTemplate($key) {
  560. $links = $this->getLinkTemplates();
  561. return isset($links[$key]) ? $links[$key] : FALSE;
  562. }
  563. /**
  564. * {@inheritdoc}
  565. */
  566. public function hasLinkTemplate($key) {
  567. $links = $this->getLinkTemplates();
  568. return isset($links[$key]);
  569. }
  570. /**
  571. * {@inheritdoc}
  572. */
  573. public function setLinkTemplate($key, $path) {
  574. if ($path[0] !== '/') {
  575. throw new \InvalidArgumentException('Link templates accepts paths, which have to start with a leading slash.');
  576. }
  577. $this->links[$key] = $path;
  578. return $this;
  579. }
  580. /**
  581. * {@inheritdoc}
  582. */
  583. public function getLabelCallback() {
  584. @trigger_error('EntityType::getLabelCallback() is deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Override the EntityInterface::label() method instead for dynamic labels. See https://www.drupal.org/node/3050794', E_USER_DEPRECATED);
  585. return $this->label_callback;
  586. }
  587. /**
  588. * {@inheritdoc}
  589. */
  590. public function setLabelCallback($callback) {
  591. @trigger_error('EntityType::setLabelCallback() is deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Override the EntityInterface::label() method instead for dynamic labels. See https://www.drupal.org/node/3050794', E_USER_DEPRECATED);
  592. $this->label_callback = $callback;
  593. return $this;
  594. }
  595. /**
  596. * {@inheritdoc}
  597. */
  598. public function hasLabelCallback() {
  599. @trigger_error('EntityType::hasabelCallback() is deprecated in drupal:8.0.0 and is removed from drupal:9.0.0. Override the EntityInterface::label() method instead for dynamic labels. See https://www.drupal.org/node/3050794', E_USER_DEPRECATED);
  600. return isset($this->label_callback);
  601. }
  602. /**
  603. * {@inheritdoc}
  604. */
  605. public function getBundleEntityType() {
  606. return $this->bundle_entity_type;
  607. }
  608. /**
  609. * {@inheritdoc}
  610. */
  611. public function getBundleOf() {
  612. return $this->bundle_of;
  613. }
  614. /**
  615. * {@inheritdoc}
  616. */
  617. public function getBundleLabel() {
  618. // If there is no bundle label defined, try to provide some sensible
  619. // fallbacks.
  620. if (!empty($this->bundle_label)) {
  621. return (string) $this->bundle_label;
  622. }
  623. elseif ($bundle_entity_type_id = $this->getBundleEntityType()) {
  624. return (string) \Drupal::entityTypeManager()->getDefinition($bundle_entity_type_id)->getLabel();
  625. }
  626. return (string) new TranslatableMarkup('@type_label bundle', ['@type_label' => $this->getLabel()], [], $this->getStringTranslation());
  627. }
  628. /**
  629. * {@inheritdoc}
  630. */
  631. public function getBaseTable() {
  632. return $this->base_table;
  633. }
  634. /**
  635. * {@inheritdoc}
  636. */
  637. public function showRevisionUi() {
  638. return $this->isRevisionable() && $this->show_revision_ui;
  639. }
  640. /**
  641. * {@inheritdoc}
  642. */
  643. public function isTranslatable() {
  644. return !empty($this->translatable);
  645. }
  646. /**
  647. * {@inheritdoc}
  648. */
  649. public function isRevisionable() {
  650. // Entity types are revisionable if a revision key has been specified.
  651. return $this->hasKey('revision');
  652. }
  653. /**
  654. * {@inheritdoc}
  655. */
  656. public function getRevisionDataTable() {
  657. return $this->revision_data_table;
  658. }
  659. /**
  660. * {@inheritdoc}
  661. */
  662. public function getRevisionTable() {
  663. return $this->revision_table;
  664. }
  665. /**
  666. * {@inheritdoc}
  667. */
  668. public function getDataTable() {
  669. return $this->data_table;
  670. }
  671. /**
  672. * {@inheritdoc}
  673. */
  674. public function getLabel() {
  675. return $this->label;
  676. }
  677. /**
  678. * {@inheritdoc}
  679. */
  680. public function getLowercaseLabel() {
  681. @trigger_error('EntityType::getLowercaseLabel() is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Instead, you should call getSingularLabel(). See https://www.drupal.org/node/3075567', E_USER_DEPRECATED);
  682. return mb_strtolower($this->getLabel());
  683. }
  684. /**
  685. * {@inheritdoc}
  686. */
  687. public function getCollectionLabel() {
  688. if (empty($this->label_collection)) {
  689. $label = $this->getLabel();
  690. $this->label_collection = new TranslatableMarkup('@label entities', ['@label' => $label], [], $this->getStringTranslation());
  691. }
  692. return $this->label_collection;
  693. }
  694. /**
  695. * {@inheritdoc}
  696. */
  697. public function getSingularLabel() {
  698. if (empty($this->label_singular)) {
  699. $lowercase_label = mb_strtolower($this->getLabel());
  700. $this->label_singular = $lowercase_label;
  701. }
  702. return $this->label_singular;
  703. }
  704. /**
  705. * {@inheritdoc}
  706. */
  707. public function getPluralLabel() {
  708. if (empty($this->label_plural)) {
  709. $lowercase_label = $this->getSingularLabel();
  710. $this->label_plural = new TranslatableMarkup('@label entities', ['@label' => $lowercase_label], [], $this->getStringTranslation());
  711. }
  712. return $this->label_plural;
  713. }
  714. /**
  715. * {@inheritdoc}
  716. */
  717. public function getCountLabel($count) {
  718. if (empty($this->label_count)) {
  719. return $this->formatPlural($count, '@count @label', '@count @label entities', ['@label' => $this->getSingularLabel()], ['context' => 'Entity type label']);
  720. }
  721. $options = [];
  722. if (isset($this->label_count['context'])) {
  723. $options['context'] = $this->label_count['context'];
  724. }
  725. return $this->formatPlural($count, $this->label_count['singular'], $this->label_count['plural'], [], $options);
  726. }
  727. /**
  728. * {@inheritdoc}
  729. */
  730. public function getUriCallback() {
  731. return $this->uri_callback;
  732. }
  733. /**
  734. * {@inheritdoc}
  735. */
  736. public function setUriCallback($callback) {
  737. $this->uri_callback = $callback;
  738. return $this;
  739. }
  740. /**
  741. * {@inheritdoc}
  742. */
  743. public function getGroup() {
  744. return $this->group;
  745. }
  746. /**
  747. * {@inheritdoc}
  748. */
  749. public function getGroupLabel() {
  750. return !empty($this->group_label) ? $this->group_label : $this->t('Other', [], ['context' => 'Entity type group']);
  751. }
  752. /**
  753. * {@inheritdoc}
  754. */
  755. public function getListCacheContexts() {
  756. return $this->list_cache_contexts;
  757. }
  758. /**
  759. * {@inheritdoc}
  760. */
  761. public function getListCacheTags() {
  762. return $this->list_cache_tags;
  763. }
  764. /**
  765. * {@inheritdoc}
  766. */
  767. public function getConfigDependencyKey() {
  768. // Return 'content' for the default implementation as important distinction
  769. // is that dependencies on other configuration entities are hard
  770. // dependencies and have to exist before creating the dependent entity.
  771. return 'content';
  772. }
  773. /**
  774. * {@inheritdoc}
  775. */
  776. public function isCommonReferenceTarget() {
  777. return $this->common_reference_target;
  778. }
  779. /**
  780. * {@inheritdoc}
  781. */
  782. public function getConstraints() {
  783. return $this->constraints;
  784. }
  785. /**
  786. * {@inheritdoc}
  787. */
  788. public function setConstraints(array $constraints) {
  789. $this->constraints = $constraints;
  790. return $this;
  791. }
  792. /**
  793. * {@inheritdoc}
  794. */
  795. public function addConstraint($constraint_name, $options = NULL) {
  796. $this->constraints[$constraint_name] = $options;
  797. return $this;
  798. }
  799. /**
  800. * {@inheritdoc}
  801. */
  802. public function getBundleConfigDependency($bundle) {
  803. // If this entity type uses entities to manage its bundles then depend on
  804. // the bundle entity.
  805. if ($bundle_entity_type_id = $this->getBundleEntityType()) {
  806. if (!$bundle_entity = \Drupal::entityTypeManager()->getStorage($bundle_entity_type_id)->load($bundle)) {
  807. throw new \LogicException(sprintf('Missing bundle entity, entity type %s, entity id %s.', $bundle_entity_type_id, $bundle));
  808. }
  809. $config_dependency = [
  810. 'type' => 'config',
  811. 'name' => $bundle_entity->getConfigDependencyName(),
  812. ];
  813. }
  814. else {
  815. // Depend on the provider of the entity type.
  816. $config_dependency = [
  817. 'type' => 'module',
  818. 'name' => $this->getProvider(),
  819. ];
  820. }
  821. return $config_dependency;
  822. }
  823. }