The EntityManager class was originally written to provide discovery for entity types.
It grew to be responsible for all methods around entities, entity types, entity fields, and entity type bundles.
In order to maintain backwards-compatibility, the EntityManager class remains intact, but contains no concrete method implementations, instead delegating all method calls to the appropriate service.
Following is a list of methods that were previously on EntityManagerInterface, organized by the interface they are now on.
Interface: \Drupal\Core\Entity\EntityTypeManagerInterface
Class: \Drupal\Core\Entity\EntityTypeManager
Service: entity_type.manager
Methods:
public function getAccessControlHandler($entity_type);
public function getStorage($entity_type);
public function getViewBuilder($entity_type);
public function getListBuilder($entity_type);
public function getFormObject($entity_type, $operation);
public function getRouteProviders($entity_type);
public function hasHandler($entity_type, $handler_type);
public function getHandler($entity_type, $handler_type);
public function createHandlerInstance($class, EntityTypeInterface $definition = NULL);
public function getDefinition($entity_type_id, $exception_on_invalid = TRUE);
public function getDefinitions();
Interface: \Drupal\Core\Entity\EntityTypeRepositoryInterface
Class: \Drupal\Core\Entity\EntityTypeRepository
Service: entity_type.repository
Methods:
public function getEntityTypeLabels($group = FALSE);
public function getEntityTypeFromClass($class_name);
Interface: \Drupal\Core\Entity\EntityTypeBundleInfoInterface
Class: \Drupal\Core\Entity\EntityTypeBundleInfo
Service: entity_type.bundle.info
Methods:
public function getAllBundleInfo();
public function getBundleInfo($entity_type);
public function clearCachedBundles();
Interface: \Drupal\Core\Entity\EntityDisplayRepositoryInterface
Class: \Drupal\Core\Entity\EntityDisplayRepository
Service: entity_display.repository
Methods:
public function getAllViewModes();
public function getViewModes($entity_type_id);
public function getAllFormModes();
public function getFormModes($entity_type_id);
public function getViewModeOptions($entity_type_id, $include_disabled = FALSE);
public function getFormModeOptions($entity_type_id, $include_disabled = FALSE);
public function getViewModeOptionsByBundle($entity_type_id, $bundle);
public function getFormModeOptionsByBundle($entity_type_id, $bundle);
public function clearDisplayModeInfo();
Interface: \Drupal\Core\Entity\EntityFieldManagerInterface
Class: \Drupal\Core\Entity\EntityFieldManager
Service: entity_field.manager
Methods:
public function getBaseFieldDefinitions($entity_type_id);
public function getFieldDefinitions($entity_type_id, $bundle);
public function getFieldStorageDefinitions($entity_type_id);
public function getFieldMap();
public function setFieldMap(array $field_map);
public function getFieldMapByFieldType($field_type);
public function clearCachedFieldDefinitions();
public function useCaches($use_caches = FALSE);
public function getExtraFields($entity_type_id, $bundle);
Interface: \Drupal\Core\Entity\EntityTypeListenerInterface
Class: \Drupal\Core\Entity\EntityTypeListener
Service: entity_type.listener
Methods:
public function onEntityTypeCreate(EntityTypeInterface $entity_type);
public function onEntityTypeUpdate(EntityTypeInterface $entity_type, EntityTypeInterface $original);
public function onEntityTypeDelete(EntityTypeInterface $entity_type);
Interface: \Drupal\Core\Entity\EntityInstalledDefinitionRepositoryInterface
Class: \Drupal\Core\Entity\EntityInstalledDefinitionRepository
Service: entity_definition.repository
Methods:
public function getLastInstalledDefinition($entity_type_id);
public function getLastInstalledFieldStorageDefinitions($entity_type_id);
Interface: \Drupal\Core\Entity\EntityRepositoryInterface
Class: \Drupal\Core\Entity\EntityRepository
Service: entity.repository
Methods:
public function loadEntityByUuid($entity_type_id, $uuid);
public function loadEntityByConfigTarget($entity_type_id, $target);
public function getTranslationFromContext(EntityInterface $entity, $langcode = NULL, $context = array());
Interface: \Drupal\Core\Entity\EntityBundleListenerInterface
Class: \Drupal\Core\Entity\EntityBundleListener
Service: entity_bundle.listener
Methods:
public function onBundleCreate($bundle, $entity_type_id);
public function onBundleRename($bundle, $bundle_new, $entity_type_id);
public function onBundleDelete($bundle, $entity_type_id);
Interface: \Drupal\Core\Field\FieldStorageDefinitionListenerInterface
Class: \Drupal\Core\Field\FieldStorageDefinitionListener
Service: field_storage_definition.listener
Methods:
public function onFieldStorageDefinitionCreate(FieldStorageDefinitionInterface $storage_definition);
public function onFieldStorageDefinitionUpdate(FieldStorageDefinitionInterface $storage_definition, FieldStorageDefinitionInterface $original);
public function onFieldStorageDefinitionDelete(FieldStorageDefinitionInterface $storage_definition);
Interface: \Drupal\Core\Field\FieldDefinitionListenerInterface
Class: \Drupal\Core\Field\FieldDefinitionListener
Service: field_definition.listener
Methods:
public function onFieldDefinitionCreate(FieldDefinitionInterface $field_definition);
public function onFieldDefinitionUpdate(FieldDefinitionInterface $field_definition, FieldDefinitionInterface $original);
public function onFieldDefinitionDelete(FieldDefinitionInterface $field_definition);
Cache Clearing
Note that EntityManagerInter::clearCachedDefinitions() invalidated entity type, field and bundle caches.. When replacing that, make sure to call the required combination of EntityTypeManagerInterface::clearCachedDefinitions(), EntityFieldManagerInterface::clearCachedFieldDefinitions() and EntityTypeBundleInfoInterface::clearCachedBundles(). However, in most cases, a manual cache clear is not necessary. Appropriate caches are automatically cleared when installing a new module, creating a new field or bundle.
Constructor changes
Entity manager has extremely wide usage throughout Drupal Core and contrib modules. All these constructors are being updated to rely on the replacement services instead. Whenever, possible, that is done in a BC compatible way:
1. If only a single new service is needed, typically EntityTypeManager, then it is used as a drop-in replacement as EntityManager also implements all interfaces of the replacement services. A @trigger_error() will eventually be triggered if any method is called on EntityManager instead of the non-deprecated replacement.
2. In case there are multiple replacement services necessary, any extra dependency is added as a new optional argument to the constructor, with a fallback to \Drupal::service().
Any contrib or custom module that extends from service classes, controllers, forms, plugins etc. that has the EntityManager service injected will need to update to the replacement service but can only do so after the parent class has been updated accordingly as well.
Some examples and common base classes are highlighted below.
ContentEntityForm (Drupal 8.6)
\Drupal\Core\Entity\ContentEntityForm now expects an implementation of \Drupal\Core\Entity\EntityRepositoryInterface (entity.repository service) as the first constructor argument instead of EntityManagerInterface. This change is backwards compatible since EntityManager implements both interfaces.
Comments
I don't think these docs are
I don't think these docs are up to date, I was confused about the service
entity_display.managerwhich does not appear to exist on Core, instead I usedentity_display.repositoryto get node view modes.Pimp your Drupal 8 Toolbar - make it badass.
Adaptivetheme - theming system for people who don't code.
I'm not sure change records
I'm not sure change records are kept up-to-date? They may just be a record of what was changed at a specific point in time.
EntityDisplayRepository
Jeff was right, the information above was incorrect. In comment #51 of the issue, it was mentioned that this was a repository rather than a manager. The code was then changed (see also the final commit) but the change record remained based on an older patch.
I updated the EntityDisplayRepository[Interface] part of the change record.
Documentation
As a community development team, we have to take documentation more seriously. I used to work for a place where code review wouldn't pass with decent comments in the code (as it increases maintainability). Obviously unit tests and documentation were also strict... the review would fail if you hadn't written tests and documentation. I know as developers, a lot of us dislike doing tests and even more so documentation, however it's essential.
I've noticed poor documentation in quite a few areas. We should probably enforce things a bit more. i.e. certain basic metrics can help, so if new lines are added, then a certain percentage of the code should be comments... of course this could just be a warning, rather than stopping people from submitting their changes, however I think it would improve the infamous Drupal learning curve.
I'm creating a module now, of course documentation doesn't please me, however I am committed to writing documentation, for the benefit of the community who might want to use the plugin. Usability is another concern... I could hack together the module ten times quicker if I wanted, however this would create future pain for others. I genuinely believe in good Koding Karma!
Confusing
Something that was, at one time, fairly simple to figure out and find documentation for has become quite a bit more confusing and hard to find. This is one of the top search results for this topic, so I want to take the time to post a solution I was able to put together using the new Methods.
My use case is getting a list of published nodes of a certain content type and publishing them to a page as XML to be consumed by a third party.
Here are my declarations. Some of them might be superfluous at this point, but I'm not done upgrading the code as of yet.
Here's the code to just feed the object into the XML
If you need to massage the data, then you'll have to fill an array and make edits there. Of course, you can still serialize a standard library array.
Hope this helps.
I'm not sure what "this topic
I'm not sure what "this topic" is exactly and how this issue made any of that harder. Literally the only change to your code that this change caused is Drupal::entityManager() to Drupal::entityTypeManager(), so exactly 4 extra characters. If you mean D7 to D8, then that's not related to this at all.
Also seems like a pretty neat way to create a custom XML output from nodes. Can't see how that would have been easier in D7. Certainly not with just core. You could use an entity query instead of loadProperties() then you can also sort them and add more complex conditions.
Or you could build the final array directly from the node object if you only need a handful of elements, with something like this:
See https://wizzlern.nl/sites/wizzlern.nl/files/artikel/drupal-content-entit... on how to work efficiently with content entities.
In the end, the difference is
In the end, the difference is very small, but figuring it out wasn't as evident for me as it might be for you. I posted this here so that anyone else confused about how to do it the new way could have something to go by.
Should be
Should be EntityTypeBundleInfo(Interface) not EntityTypeBundleManager(Interface)