/**
  * {@inheritdoc}
  */
 public function buildForm(array $form, FormStateInterface $form_state, ContentEntityInterface $entity = NULL)
 {
     /** @var \Drupal\content_moderation\Entity\ModerationState $current_state */
     $current_state = $entity->moderation_state->entity;
     $transitions = $this->validation->getValidTransitions($entity, $this->currentUser());
     // Exclude self-transitions.
     $transitions = array_filter($transitions, function (ModerationStateTransition $transition) use($current_state) {
         return $transition->getToState() != $current_state->id();
     });
     $target_states = [];
     /** @var ModerationStateTransition $transition */
     foreach ($transitions as $transition) {
         $target_states[$transition->getToState()] = $transition->label();
     }
     if (!count($target_states)) {
         return $form;
     }
     if ($current_state) {
         $form['current'] = ['#type' => 'item', '#title' => $this->t('Status'), '#markup' => $current_state->label()];
     }
     // Persist the entity so we can access it in the submit handler.
     $form_state->set('entity', $entity);
     $form['new_state'] = ['#type' => 'select', '#title' => $this->t('Moderate'), '#options' => $target_states];
     $form['revision_log'] = ['#type' => 'textfield', '#title' => $this->t('Log message'), '#size' => 30];
     $form['submit'] = ['#type' => 'submit', '#value' => $this->t('Apply')];
     $form['#theme'] = ['entity_moderation_form'];
     return $form;
 }
 /**
  * {@inheritdoc}
  */
 public function validate($value, Constraint $constraint)
 {
     /** @var \Drupal\Core\Entity\EntityInterface $entity */
     $entity = $value->getEntity();
     // Ignore entities that are not subject to moderation anyway.
     if (!$this->moderationInformation->isModeratedEntity($entity)) {
         return;
     }
     // Ignore entities that are being created for the first time.
     if ($entity->isNew()) {
         return;
     }
     // Ignore entities that are being moderated for the first time, such as
     // when they existed before moderation was enabled for this entity type.
     if ($this->isFirstTimeModeration($entity)) {
         return;
     }
     $original_entity = $this->moderationInformation->getLatestRevision($entity->getEntityTypeId(), $entity->id());
     if (!$entity->isDefaultTranslation() && $original_entity->hasTranslation($entity->language()->getId())) {
         $original_entity = $original_entity->getTranslation($entity->language()->getId());
     }
     if ($entity->moderation_state->target_id) {
         $new_state_id = $entity->moderation_state->target_id;
     } else {
         $new_state_id = $default = $this->moderationInformation->loadBundleEntity($entity->getEntityType()->getBundleEntityType(), $entity->bundle())->getThirdPartySetting('content_moderation', 'default_moderation_state');
     }
     if ($new_state_id) {
         $new_state = ModerationStateEntity::load($new_state_id);
     }
     // @todo - what if $new_state_id references something that does not exist or
     //   is null.
     if (!$this->validation->isTransitionAllowed($original_entity->moderation_state->entity, $new_state)) {
         $this->context->addViolation($constraint->message, ['%from' => $original_entity->moderation_state->entity->label(), '%to' => $new_state->label()]);
     }
 }
 /**
  * {@inheritdoc}
  */
 public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state)
 {
     /** @var ContentEntityInterface $entity */
     $entity = $items->getEntity();
     /* @var \Drupal\Core\Config\Entity\ConfigEntityInterface $bundle_entity */
     $bundle_entity = $this->entityTypeManager->getStorage($entity->getEntityType()->getBundleEntityType())->load($entity->bundle());
     if (!$this->moderationInformation->isModeratedEntity($entity)) {
         // @todo https://www.drupal.org/node/2779933 write a test for this.
         return $element + ['#access' => FALSE];
     }
     $default = $items->get($delta)->value ?: $bundle_entity->getThirdPartySetting('content_moderation', 'default_moderation_state', FALSE);
     /** @var \Drupal\content_moderation\ModerationStateInterface $default_state */
     $default_state = $this->entityTypeManager->getStorage('moderation_state')->load($default);
     if (!$default || !$default_state) {
         throw new \UnexpectedValueException(sprintf('The %s bundle has an invalid moderation state configuration, moderation states are enabled but no default is set.', $bundle_entity->label()));
     }
     $transitions = $this->validator->getValidTransitions($entity, $this->currentUser);
     $target_states = [];
     /** @var \Drupal\content_moderation\Entity\ModerationStateTransition $transition */
     foreach ($transitions as $transition) {
         $target_states[$transition->getToState()] = $transition->label();
     }
     // @todo https://www.drupal.org/node/2779933 write a test for this.
     $element += ['#access' => FALSE, '#type' => 'select', '#options' => $target_states, '#default_value' => $default, '#published' => $default ? $default_state->isPublishedState() : FALSE, '#key_column' => $this->column];
     $element['#element_validate'][] = array(get_class($this), 'validateElement');
     // Use the dropbutton.
     $element['#process'][] = [get_called_class(), 'processActions'];
     return $element;
 }
 /**
  * @covers ::isTransitionAllowed
  * @covers ::calculatePossibleTransitions
  *
  * @dataProvider providerIsTransitionAllowedWithInValidTransition
  */
 public function testIsTransitionAllowedWithInValidTransition($from_id, $to_id)
 {
     $storage = $this->setupStateStorage();
     $state_transition_validation = new StateTransitionValidation($this->setupEntityTypeManager($storage), $this->setupQueryFactory());
     $this->assertFalse($state_transition_validation->isTransitionAllowed($storage->load($from_id), $storage->load($to_id)));
 }