diff --git a/core/lib/Drupal/Core/Workflow/Entity/Workflow.php b/core/lib/Drupal/Core/Workflow/Entity/Workflow.php index 9cfc583..21389af 100644 --- a/core/lib/Drupal/Core/Workflow/Entity/Workflow.php +++ b/core/lib/Drupal/Core/Workflow/Entity/Workflow.php @@ -318,6 +318,9 @@ public function hasTransition($transition_id) { * {@inheritdoc} */ public function getTransitionsForState($state_id, $direction = 'from') { + if ($direction !== 'to' && $direction !== 'from') { + throw new \InvalidArgumentException("The direction '$direction' is invalid, the only valid values are 'to' and 'from'"); + } $transition_ids = array_keys(array_filter($this->transitions, function ($transition) use ($state_id, $direction) { return in_array($state_id, (array) $transition[$direction], TRUE); })); diff --git a/core/lib/Drupal/Core/Workflow/State.php b/core/lib/Drupal/Core/Workflow/State.php index 386e52e..d8dea01 100644 --- a/core/lib/Drupal/Core/Workflow/State.php +++ b/core/lib/Drupal/Core/Workflow/State.php @@ -83,7 +83,7 @@ public function weight() { * {@inheritdoc} */ public function canTransitionTo($to_state_id) { - return $this->workflow->hasTransitionFromStateToState($this->id, $to_state_id); + return $this->workflow->hasTransitionFromStateToState($this->id(), $to_state_id); } /** @@ -100,7 +100,7 @@ public function getTransitionTo($to_state_id) { * {@inheritdoc} */ public function getTransitions() { - return $this->workflow->getTransitionsForState($this->id); + return $this->workflow->getTransitionsForState($this->id()); } /** diff --git a/core/lib/Drupal/Core/Workflow/WorkflowInterface.php b/core/lib/Drupal/Core/Workflow/WorkflowInterface.php index 68873f5..853379e 100644 --- a/core/lib/Drupal/Core/Workflow/WorkflowInterface.php +++ b/core/lib/Drupal/Core/Workflow/WorkflowInterface.php @@ -262,7 +262,7 @@ public function setTransitionWeight($transition_id, $weight); * @throws \InvalidArgumentException * Thrown if the transition does not exist or the states do not exist. */ - public function setTransitionFromStates($transition_id, array $from_state_ids); + public function setTransitionFromStates($transition_id, array $from_state_ids); /** * Deletes a transition. diff --git a/core/modules/content_moderation/src/EntityTypeInfo.php b/core/modules/content_moderation/src/EntityTypeInfo.php index 25abf6a..501b84c 100644 --- a/core/modules/content_moderation/src/EntityTypeInfo.php +++ b/core/modules/content_moderation/src/EntityTypeInfo.php @@ -302,11 +302,10 @@ public function entityBaseFieldInfo(EntityTypeInterface $entity_type) { $fields = []; $fields['moderation_state'] = BaseFieldDefinition::create('string') - ->setLabel(t('Moderation state')) - ->setDescription(t('The moderation state of this piece of content.')) + ->setLabel($this->t('Moderation state')) + ->setDescription($this->t('The moderation state of this piece of content.')) ->setComputed(TRUE) ->setClass(ModerationStateFieldItemList::class) - ->setSetting('target_type', 'moderation_state') ->setDisplayOptions('view', [ 'label' => 'hidden', 'region' => 'hidden', diff --git a/core/modules/content_moderation/src/Form/BundleModerationConfigurationForm.php b/core/modules/content_moderation/src/Form/BundleModerationConfigurationForm.php index 6fa739c..2f50448 100644 --- a/core/modules/content_moderation/src/Form/BundleModerationConfigurationForm.php +++ b/core/modules/content_moderation/src/Form/BundleModerationConfigurationForm.php @@ -3,6 +3,7 @@ namespace Drupal\content_moderation\Form; use Drupal\content_moderation\Plugin\WorkflowType\ContentModeration; +use Drupal\Core\Entity\Query\QueryInterface; use Drupal\Core\Workflow\WorkflowInterface; use Drupal\Core\Entity\EntityForm; use Drupal\Core\Entity\EntityTypeManagerInterface; @@ -22,17 +23,28 @@ class BundleModerationConfigurationForm extends EntityForm { protected $entityTypeManager; /** + * The entity query object for workflow configuration entities. + * + * @var \Drupal\Core\Entity\Query\QueryInterface + */ + protected $entityQuery; + + /** * {@inheritdoc} */ - public function __construct(EntityTypeManagerInterface $entity_type_manager) { + public function __construct(EntityTypeManagerInterface $entity_type_manager, QueryInterface $entity_query) { $this->entityTypeManager = $entity_type_manager; + $this->entityQuery = $entity_query; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { - return new static($container->get('entity_type.manager')); + return new static( + $container->get('entity_type.manager'), + $container->get('entity.query')->get('workflow') + ); } /** @@ -52,22 +64,24 @@ public function form(array $form, FormStateInterface $form_state) { /* @var \Drupal\Core\Config\Entity\ConfigEntityInterface $bundle */ $bundle = $this->getEntity(); $bundle_of_entity_type = $this->entityTypeManager->getDefinition($bundle->getEntityType()->getBundleOf()); + $workflow_ids = $this->entityQuery->condition('type', 'content_moderation')->execute(); /* @var \Drupal\Core\Workflow\WorkflowInterface[] $workflows */ - $workflows = $this->entityTypeManager->getStorage('workflow')->loadMultiple(); + $workflows = $this->entityTypeManager->getStorage('workflow')->loadMultiple($workflow_ids); + // Get a list of all the possible workflows to apply to the bundle. $options = array_map(function (WorkflowInterface $workflow) { return $workflow->label(); - }, array_filter($workflows, function (WorkflowInterface $workflow) { - return $workflow->status() && $workflow->getTypePlugin() instanceof ContentModeration; - })); + }, $workflows); - $selected_workflow = array_reduce($workflows, function ($carry, WorkflowInterface $workflow) use ($bundle_of_entity_type, $bundle) { + // Determine if, and which, workflow is being applied to the bundle. + $selected_workflow = NULL; + foreach ($workflows as $workflow) { $plugin = $workflow->getTypePlugin(); if ($plugin instanceof ContentModeration && $plugin->appliesToEntityTypeAndBundle($bundle_of_entity_type->id(), $bundle->id())) { - return $workflow->id(); + $selected_workflow = $workflow->id(); + break; } - return $carry; - }); + } $form['workflow'] = [ '#type' => 'select', '#title' => $this->t('Select the workflow to apply'), @@ -93,13 +107,11 @@ public function form(array $form, FormStateInterface $form_state) { ]; // Add a special message when moderation is being disabled. - if ($selected_workflow) { - $form['enable_workflow_note'] = [ - '#type' => 'item', - '#description' => $this->t('After disabling moderation, any existing forward drafts will be accessible via the "Revisions" tab.'), - '#access' => !empty($selected_workflow) - ]; - } + $form['enable_workflow_note'] = [ + '#type' => 'item', + '#description' => $this->t('After disabling moderation, any existing forward drafts will be accessible via the "Revisions" tab.'), + '#access' => !empty($selected_workflow) + ]; return parent::form($form, $form_state); } diff --git a/core/modules/workflow_ui/src/Form/WorkflowAddForm.php b/core/modules/workflow_ui/src/Form/WorkflowAddForm.php index 62f3b29..07ce876 100644 --- a/core/modules/workflow_ui/src/Form/WorkflowAddForm.php +++ b/core/modules/workflow_ui/src/Form/WorkflowAddForm.php @@ -95,8 +95,6 @@ public function save(array $form, FormStateInterface $form_state) { * {@inheritdoc} */ protected function copyFormValuesToEntity(EntityInterface $entity, array $form, FormStateInterface $form_state) { - // This form can only set the workflow's ID, label and the weights for each - // state. /** @var \Drupal\Core\Workflow\WorkflowInterface $entity */ $values = $form_state->getValues(); $entity->set('label', $values['label']); diff --git a/core/modules/workflow_ui/src/Form/WorkflowEditForm.php b/core/modules/workflow_ui/src/Form/WorkflowEditForm.php index bc8dd1a..5cd4a3f 100644 --- a/core/modules/workflow_ui/src/Form/WorkflowEditForm.php +++ b/core/modules/workflow_ui/src/Form/WorkflowEditForm.php @@ -125,12 +125,12 @@ public function form(array $form, FormStateInterface $form_state) { $links['edit'] = [ 'title' => $this->t('Edit'), 'url' => Url::fromRoute('entity.workflow.edit_transition_form', ['workflow' => $workflow->id(), 'workflow_transition' => $transition->id()]), - 'attributes' => ['aria-label' => $this->t('Edit \'@transition\' transition', ['@transition' => $transition->label()])], + 'attributes' => ['aria-label' => $this->t('Edit @transition transition', ['@transition' => $transition->label()])], ]; $links['delete'] = [ 'title' => t('Delete'), 'url' => Url::fromRoute('entity.workflow.delete_transition_form', ['workflow' => $workflow->id(), 'workflow_transition' => $transition->id()]), - 'attributes' => ['aria-label' => $this->t('Delete \'@transition\' transition', ['@transition' => $transition->label()])], + 'attributes' => ['aria-label' => $this->t('Delete @transition transition', ['@transition' => $transition->label()])], ]; $form['transitions_container']['transitions'][$transition->id()] = [ '#attributes' => ['class' => ['draggable']], @@ -177,8 +177,6 @@ public function save(array $form, FormStateInterface $form_state) { * {@inheritdoc} */ protected function copyFormValuesToEntity(EntityInterface $entity, array $form, FormStateInterface $form_state) { - // This form can only set the workflow's ID, label and the weights for each - // state. /** @var \Drupal\Core\Workflow\WorkflowInterface $entity */ $values = $form_state->getValues(); $entity->set('label', $values['label']); diff --git a/core/modules/workflow_ui/workflow_ui.routing.yml b/core/modules/workflow_ui/workflow_ui.routing.yml index f1cfabc..b5d853b 100644 --- a/core/modules/workflow_ui/workflow_ui.routing.yml +++ b/core/modules/workflow_ui/workflow_ui.routing.yml @@ -44,4 +44,4 @@ entity.workflow.delete_transition_form: _form: '\Drupal\workflow_ui\Form\WorkflowTransitionDeleteForm' _title: 'Delete state' requirements: - _entity_access: 'workflow.edit' \ No newline at end of file + _entity_access: 'workflow.edit' diff --git a/core/tests/Drupal/Tests/Core/Workflow/WorkflowTest.php b/core/tests/Drupal/Tests/Core/Workflow/WorkflowTest.php index 1f20a68..24c01e8 100644 --- a/core/tests/Drupal/Tests/Core/Workflow/WorkflowTest.php +++ b/core/tests/Drupal/Tests/Core/Workflow/WorkflowTest.php @@ -450,6 +450,23 @@ public function testGetTransitionsForState() { $this->assertEquals(['archive'], array_keys($workflow->getTransitionsForState('archived', 'to'))); } + /** + * @covers ::getTransitionsForState + */ + public function testGetTransitionsForStateException() { + $this->setExpectedException(\InvalidArgumentException::class, "The direction 'invalid_value' is invalid, the only valid values are 'to' and 'from'"); + $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow'); + // By default states are ordered in the order added. + $workflow + ->addState('draft', 'Draft') + ->addState('published', 'Published') + ->addState('archived', 'Archived') + ->addTransition('create_new_draft', 'Create new draft', ['archived', 'draft'], 'draft') + ->addTransition('publish', 'Publish', ['draft', 'published'], 'published') + ->addTransition('archive', 'Archive', ['published'], 'archived'); + + $workflow->getTransitionsForState('draft', 'invalid_value'); + } /** * @covers ::getTransitionFromStateToState