Problem/Motivation
On Drupal 9.x, a call to `::getOriginalState($entity)` ( Drupal::service('content_moderation.moderation_information')->getOriginalState($entity)) on an `Entity` that belongs to a Bundle not under moderation (so has no workflow) produces
The website encountered an unexpected error. Please try again later.
Error: Call to a member function getTypePlugin() on null in Drupal\content_moderation\ModerationInformation->getOriginalState() (line 216 of core/modules/content_moderation/src/ModerationInformation.php).
The reason for that is chained method accessors where one of the intermediate results may be NULL.
https://git.drupalcode.org/project/drupal/-/blob/9.3.x/core/modules/cont...
Steps to reproduce
- Create a New Node Content Type/Bundle and leave it out of Moderation/no workflow.
- Create a test case like this (snippet not complete code) and give `$bundle` the machine name of your new bundle.
....
$entity = $this->entityTypeManager->getStorage('node')->create(array(
'type' => $bundle,
));
$bundle_label = $entity->type->entity->label() ?? $bundle;
if (\Drupal::moduleHandler()->moduleExists('content_moderation')) {
/** @var \Drupal\content_moderation\ModerationInformation $moderationInformation */
$moderationInformation = \Drupal::service('content_moderation.moderation_information');
if ($moderationInformation->canModerateEntitiesOfEntityType($entity->getEntityType()) {
$default = $moderationInformation->getOriginalState($entity);
}
It will fail on the last line with the error described above
Proposed resolution
Instead of
/**
* {@inheritdoc}
*/
public function getOriginalState(ContentEntityInterface $entity) {
$state = NULL;
$workflow_type = $this->getWorkflowForEntity($entity)->getTypePlugin();
if (!$entity->isNew() && !$this->isFirstTimeModeration($entity)) {
/** @var \Drupal\Core\Entity\ContentEntityInterface $original_entity */
$original_entity = $this->entityTypeManager->getStorage($entity->getEntityTypeId())->loadRevision($entity->getLoadedRevisionId());
if (!$entity->isDefaultTranslation() && $original_entity->hasTranslation($entity->language()->getId())) {
$original_entity = $original_entity->getTranslation($entity->language()->getId());
}
if ($workflow_type->hasState($original_entity->moderation_state->value)) {
$state = $workflow_type->getState($original_entity->moderation_state->value);
}
}
return $state ?: $workflow_type->getInitialState($entity);
}
This may be done (but needs an update to the Interface to allow this method to return `null` too)
/**
* {@inheritdoc}
*/
public function getOriginalState(ContentEntityInterface $entity) {
$state = NULL;
/** @var \Drupal\workflows\WorkflowInterface|null $workflow */
$workflow = $this->getWorkflowForEntity($entity);
if (!$entity->isNew() && !$this->isFirstTimeModeration($entity) && $workflow) {
$workflow_type = $workflow->getTypePlugin();
/** @var \Drupal\Core\Entity\ContentEntityInterface $original_entity */
$original_entity = $this->entityTypeManager->getStorage($entity->getEntityTypeId())->loadRevision($entity->getLoadedRevisionId());
if (!$entity->isDefaultTranslation() && $original_entity->hasTranslation($entity->language()->getId())) {
$original_entity = $original_entity->getTranslation($entity->language()->getId());
}
if ($workflow_type->hasState($original_entity->moderation_state->value)) {
$state = $workflow_type->getState($original_entity->moderation_state->value);
}
return $state ?: $workflow_type->getInitialState($entity);
}
return $state;
}
Remaining tasks
Get some feedback. Make request. Write tests?
User interface changes
None
API changes
None
Data model changes
None
Release notes snippet