diff -u b/core/modules/content_moderation/content_moderation.info.yml b/core/modules/content_moderation/content_moderation.info.yml --- b/core/modules/content_moderation/content_moderation.info.yml +++ b/core/modules/content_moderation/content_moderation.info.yml @@ -9 +9 @@ - - workflow \ No newline at end of file + - workflow diff -u b/core/modules/workflow/src/Form/WorkflowDeleteForm.php b/core/modules/workflow/src/Form/WorkflowDeleteForm.php --- b/core/modules/workflow/src/Form/WorkflowDeleteForm.php +++ b/core/modules/workflow/src/Form/WorkflowDeleteForm.php @@ -15,7 +15,7 @@ * {@inheritdoc} */ public function getQuestion() { - return $this->t('Are you sure you want to delete %name?', array('%name' => $this->entity->label())); + return $this->t('Are you sure you want to delete %name?', ['%name' => $this->entity->label()]); } /** diff -u b/core/modules/workflow/src/Form/WorkflowEditForm.php b/core/modules/workflow/src/Form/WorkflowEditForm.php --- b/core/modules/workflow/src/Form/WorkflowEditForm.php +++ b/core/modules/workflow/src/Form/WorkflowEditForm.php @@ -44,41 +44,41 @@ 'weight' => $this->t('Weight'), 'operations' => $this->t('Operations') ]; - $form['states_container'] = array( + $form['states_container'] = [ '#type' => 'details', '#title' => $this->t('States'), '#open' => TRUE, '#collapsible' => 'FALSE', - ); + ]; $form['states_container']['description'] = [ '#prefix' => '

', '#markup' => $this->t('@todo describe what a state is.'), '#suffix' => '

', ]; - $form['states_container']['states'] = array( + $form['states_container']['states'] = [ '#type' => 'table', '#header' => $header, '#title' => $this->t('States'), '#empty' => $this->t('There are no states yet.'), - '#tabledrag' => array( - array( + '#tabledrag' => [ + [ 'action' => 'order', 'relationship' => 'sibling', 'group' => 'state-weight', - ), - ), - ); + ], + ], + ]; foreach ($workflow->getStates() as $state) { $links['edit'] = [ 'title' => $this->t('Edit'), 'url' => Url::fromRoute('entity.workflow.edit_state_form', ['workflow' => $workflow->id(), 'workflow_state' => $state->id()]), 'attributes' => ['aria-label' => $this->t('Edit @state state', ['@state' => $state->label()])], ]; - $links['delete'] = array( + $links['delete'] = [ 'title' => t('Delete'), 'url' => Url::fromRoute('entity.workflow.delete_state_form', ['workflow' => $workflow->id(), 'workflow_state' => $state->id()]), 'attributes' => ['aria-label' => $this->t('Delete @state state', ['@state' => $state->label()])], - ); + ]; $form['states_container']['states'][$state->id()] = [ '#attributes' => ['class' => ['draggable']], 'state' => ['#markup' => $state->label()], @@ -96,9 +96,9 @@ ], ]; } - $form['states_container']['state_add'] = array( + $form['states_container']['state_add'] = [ '#markup' => $workflow->toLink($this->t('Add a new state'), 'add-state-form')->toString(), - ); + ]; $header = [ 'state' => $this->t('From'), @@ -106,33 +106,33 @@ 'label' => $this->t('Label'), 'operations' => $this->t('Operations') ]; - $form['transitions_container'] = array( + $form['transitions_container'] = [ '#type' => 'details', '#title' => $this->t('Transitions'), '#open' => TRUE, - ); + ]; $form['transitions_container']['description'] = [ '#prefix' => '

', '#markup' => $this->t('@todo describe what a transition is.'), '#suffix' => '

', ]; - $form['transitions_container']['transitions'] = array( + $form['transitions_container']['transitions'] = [ '#type' => 'table', '#header' => $header, '#title' => $this->t('Transitions'), '#empty' => $this->t('There are no transitions yet.'), - ); + ]; foreach ($workflow->getTransitions() as $transition) { $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 from @from_state to @to_state', ['@from_state' => $transition->from()->label(), '@to_state' => $transition->to()->label()])], ]; - $links['delete'] = array( + $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 from @from_state to @to_state', ['@from_state' => $transition->from()->label(), '@to_state' => $transition->to()->label()])], - ); + ]; $form['transitions_container']['transitions'][$transition->id()] = [ 'to' => ['#markup' => $transition->from()->label()], 'from' => ['#markup' => $transition->to()->label()], @@ -143,9 +143,9 @@ ], ]; } - $form['transitions_container']['transition_add'] = array( + $form['transitions_container']['transition_add'] = [ '#markup' => $workflow->toLink($this->t('Add a new transition'), 'add-transition-form')->toString(), - ); + ]; return $form; } diff -u b/core/modules/workflow/src/Form/WorkflowStateAddForm.php b/core/modules/workflow/src/Form/WorkflowStateAddForm.php --- b/core/modules/workflow/src/Form/WorkflowStateAddForm.php +++ b/core/modules/workflow/src/Form/WorkflowStateAddForm.php @@ -19,29 +19,29 @@ /* @var \Drupal\workflow\WorkflowInterface $workflow */ $workflow = $this->getEntity(); - $form['label'] = array( + $form['label'] = [ '#type' => 'textfield', '#title' => $this->t('Label'), '#maxlength' => 255, '#default_value' => '', '#description' => $this->t('Label for the state.'), '#required' => TRUE, - ); + ]; - $form['id'] = array( + $form['id'] = [ '#type' => 'machine_name', - '#machine_name' => array( + '#machine_name' => [ 'exists' => [$this, 'exists'], - ), - ); + ], + ]; - $form['transition_to_self_label'] = array( + $form['transition_to_self_label'] = [ '#type' => 'textfield', '#title' => $this->t('Label'), '#maxlength' => 255, '#default_value' => '', '#description' => $this->t('Label for the transition to self. If this is left blank a transition will not be created.'), - ); + ]; // Add additional form fields from the workflow type plugin. $form['type_settings'] = [ @@ -115,11 +115,11 @@ * {@inheritdoc} */ protected function actions(array $form, FormStateInterface $form_state) { - $actions['submit'] = array( + $actions['submit'] = [ '#type' => 'submit', '#value' => $this->t('Save'), - '#submit' => array('::submitForm', '::save'), - ); + '#submit' => ['::submitForm', '::save'], + ]; return $actions; } diff -u b/core/modules/workflow/src/Form/WorkflowStateDeleteForm.php b/core/modules/workflow/src/Form/WorkflowStateDeleteForm.php --- b/core/modules/workflow/src/Form/WorkflowStateDeleteForm.php +++ b/core/modules/workflow/src/Form/WorkflowStateDeleteForm.php @@ -37,7 +37,7 @@ * {@inheritdoc} */ public function getQuestion() { - return $this->t('Are you sure you want to delete %state from %workflow?', array('%state' => $this->workflow->getState($this->stateId)->label(), '%workflow' => $this->workflow->label())); + return $this->t('Are you sure you want to delete %state from %workflow?', ['%state' => $this->workflow->getState($this->stateId)->label(), '%workflow' => $this->workflow->label()]); } /** diff -u b/core/modules/workflow/src/Form/WorkflowStateEditForm.php b/core/modules/workflow/src/Form/WorkflowStateEditForm.php --- b/core/modules/workflow/src/Form/WorkflowStateEditForm.php +++ b/core/modules/workflow/src/Form/WorkflowStateEditForm.php @@ -36,23 +36,23 @@ /* @var \Drupal\workflow\WorkflowInterface $workflow */ $workflow = $this->getEntity(); $state = $workflow->getState($this->stateId); - $form['label'] = array( + $form['label'] = [ '#type' => 'textfield', '#title' => $this->t('Label'), '#maxlength' => 255, '#default_value' => $state->label(), '#description' => $this->t('Label for the state.'), '#required' => TRUE, - ); + ]; - $form['id'] = array( + $form['id'] = [ '#type' => 'machine_name', '#default_value' => $this->stateId, - '#machine_name' => array( + '#machine_name' => [ 'exists' => [$this, 'exists'], - ), + ], '#disabled' => TRUE, - ); + ]; // Add additional form fields from the workflow type plugin. $form['type_settings'] = [ @@ -78,13 +78,13 @@ 'workflow_transition' => $transition->id() ]), ]; - $links['delete'] = array( + $links['delete'] = [ 'title' => t('Delete'), 'url' => Url::fromRoute('entity.workflow.delete_transition_form', [ 'workflow' => $workflow->id(), 'workflow_transition' => $transition->id() ]), - ); + ]; $form['transitions'][$transition->id()] = [ 'label' => [ '#markup' => $transition->label(), @@ -142,25 +142,25 @@ * {@inheritdoc} */ protected function actions(array $form, FormStateInterface $form_state) { - $actions['submit'] = array( + $actions['submit'] = [ '#type' => 'submit', '#value' => $this->t('Save'), - '#submit' => array('::submitForm', '::save'), - ); + '#submit' => ['::submitForm', '::save'], + ]; - $actions['delete'] = array( + $actions['delete'] = [ '#type' => 'link', '#title' => $this->t('Delete'), // Deleting a state is editing a workflow. '#access' => $this->entity->access('edit'), - '#attributes' => array( - 'class' => array('button', 'button--danger'), - ), + '#attributes' => [ + 'class' => ['button', 'button--danger'], + ], '#url' => Url::fromRoute('entity.workflow.delete_state_form', [ 'workflow' => $this->entity->id(), 'workflow_state' => $this->stateId ]) - ); + ]; return $actions; } diff -u b/core/modules/workflow/src/Form/WorkflowTransitionAddForm.php b/core/modules/workflow/src/Form/WorkflowTransitionAddForm.php --- b/core/modules/workflow/src/Form/WorkflowTransitionAddForm.php +++ b/core/modules/workflow/src/Form/WorkflowTransitionAddForm.php @@ -20,14 +20,14 @@ /* @var \Drupal\workflow\WorkflowInterface $workflow */ $workflow = $this->getEntity(); - $form['label'] = array( + $form['label'] = [ '#type' => 'textfield', '#title' => $this->t('Label'), '#maxlength' => 255, '#default_value' => '', '#description' => $this->t('Label for the transition.'), '#required' => TRUE, - ); + ]; // @todo add some ajax to ensure that only valid transitions are selectable. $states = array_map([State::class, 'labelCallback'], $workflow->getStates()); @@ -122,11 +122,11 @@ * {@inheritdoc} */ protected function actions(array $form, FormStateInterface $form_state) { - $actions['submit'] = array( + $actions['submit'] = [ '#type' => 'submit', '#value' => $this->t('Save'), - '#submit' => array('::submitForm', '::save'), - ); + '#submit' => ['::submitForm', '::save'], + ]; return $actions; } diff -u b/core/modules/workflow/src/Form/WorkflowTransitionDeleteForm.php b/core/modules/workflow/src/Form/WorkflowTransitionDeleteForm.php --- b/core/modules/workflow/src/Form/WorkflowTransitionDeleteForm.php +++ b/core/modules/workflow/src/Form/WorkflowTransitionDeleteForm.php @@ -44,7 +44,7 @@ * {@inheritdoc} */ public function getQuestion() { - return $this->t('Are you sure you want to delete the transition from %from to %to from %workflow?', array('%from' => $this->transition->from()->label(), '%to' => $this->transition->to()->label(), '%workflow' => $this->workflow->label())); + return $this->t('Are you sure you want to delete the transition from %from to %to from %workflow?', ['%from' => $this->transition->from()->label(), '%to' => $this->transition->to()->label(), '%workflow' => $this->workflow->label()]); } /** diff -u b/core/modules/workflow/src/Form/WorkflowTransitionEditForm.php b/core/modules/workflow/src/Form/WorkflowTransitionEditForm.php --- b/core/modules/workflow/src/Form/WorkflowTransitionEditForm.php +++ b/core/modules/workflow/src/Form/WorkflowTransitionEditForm.php @@ -37,14 +37,14 @@ /* @var \Drupal\workflow\WorkflowInterface $workflow */ $workflow = $this->getEntity(); $transition = $workflow->getTransition($this->transitionId); - $form['label'] = array( + $form['label'] = [ '#type' => 'textfield', '#title' => $this->t('Label'), '#maxlength' => 255, '#default_value' => $transition->label(), '#description' => $this->t('Label for the transition.'), '#required' => TRUE, - ); + ]; $form['id'] = [ '#type' => 'hidden', @@ -121,25 +121,25 @@ * {@inheritdoc} */ protected function actions(array $form, FormStateInterface $form_state) { - $actions['submit'] = array( + $actions['submit'] = [ '#type' => 'submit', '#value' => $this->t('Save'), - '#submit' => array('::submitForm', '::save'), - ); + '#submit' => ['::submitForm', '::save'], + ]; - $actions['delete'] = array( + $actions['delete'] = [ '#type' => 'link', '#title' => $this->t('Delete'), // Deleting a transition is editing a workflow. '#access' => $this->entity->access('edit'), - '#attributes' => array( - 'class' => array('button', 'button--danger'), - ), + '#attributes' => [ + 'class' => ['button', 'button--danger'], + ], '#url' => Url::fromRoute('entity.workflow.delete_transition_form', [ 'workflow' => $this->entity->id(), 'workflow_transition' => $this->transitionId ]) - ); + ]; return $actions; } diff -u b/core/modules/workflow/tests/src/Unit/StateTest.php b/core/modules/workflow/tests/src/Unit/StateTest.php --- b/core/modules/workflow/tests/src/Unit/StateTest.php +++ b/core/modules/workflow/tests/src/Unit/StateTest.php @@ -5,6 +5,8 @@ use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Tests\UnitTestCase; use Drupal\workflow\Entity\Workflow; +use Drupal\workflow\State; +use Drupal\workflow\WorkflowInterface; use Drupal\workflow\WorkflowTypeInterface; use Drupal\workflow\WorkflowTypeManager; use Prophecy\Argument; @@ -36,6 +38,24 @@ } /** + * @covers ::__construct + * @covers ::id + * @covers ::label + * @covers ::weight + */ + public function testGetters() { + $state = new State( + $this->prophesize(WorkflowInterface::class)->reveal(), + 'draft', + 'Draft', + 3 + ); + $this->assertEquals('draft', $state->id()); + $this->assertEquals('Draft', $state->label()); + $this->assertEquals(3, $state->weight()); + } + + /** * @covers ::canTransitionTo */ public function testCanTransitionTo() { @@ -54,9 +74,6 @@ /** * @covers ::getTransitionTo - * @covers \Drupal\workflow\Transition::from - * @covers \Drupal\workflow\Transition::to - * @covers \Drupal\workflow\Transition::label */ public function testGetTransitionTo() { $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow'); @@ -66,8 +83,6 @@ ->addTransition('draft', 'published', 'Publish'); $state = $workflow->getState('draft'); $transition = $state->getTransitionTo('published'); - $this->assertEquals($state, $transition->from()); - $this->assertEquals($workflow->getState('published'), $transition->to()); $this->assertEquals('Publish', $transition->label()); } @@ -84,8 +99,6 @@ /** * @covers ::getTransitions - * @covers \Drupal\workflow\Transition::from - * @covers \Drupal\workflow\Transition::to */ public function testGetTransitions() { $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow'); @@ -99,10 +112,20 @@ $state = $workflow->getState('draft'); $transitions = $state->getTransitions(); $this->assertCount(2, $transitions); - $this->assertEquals('draft', $transitions['draft-draft']->from()->id()); - $this->assertEquals('draft', $transitions['draft-draft']->to()->id()); - $this->assertEquals('draft', $transitions['draft-published']->from()->id()); - $this->assertEquals('published', $transitions['draft-published']->to()->id()); + $this->assertEquals('Create new draft', $transitions['draft-draft']->label()); + $this->assertEquals('Publish', $transitions['draft-published']->label()); + } + + /** + * @covers ::labelCallback + */ + public function testLabelCallback() { + $workflow = $this->prophesize(WorkflowInterface::class)->reveal(); + $states = [ + new State($workflow, 'draft', 'Draft'), + new State($workflow, 'published', 'Published'), + ]; + $this->assertEquals(['Draft', 'Published'], array_map([State::class, 'labelCallback'], $states)); } } diff -u b/core/modules/workflow/tests/src/Unit/WorkflowTest.php b/core/modules/workflow/tests/src/Unit/WorkflowTest.php --- b/core/modules/workflow/tests/src/Unit/WorkflowTest.php +++ b/core/modules/workflow/tests/src/Unit/WorkflowTest.php @@ -18,6 +18,9 @@ */ class WorkflowTest extends UnitTestCase { + /** + * {@inheritdoc} + */ protected function setUp() { parent::setUp(); // Create a container so that the plugin manager and workflow type can be @@ -339,7 +342,7 @@ /** - * @covers ::getState + * @covers ::getTransition */ public function testGetTransition() { $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow'); @@ -362,7 +365,7 @@ } /** - * @covers ::getState + * @covers ::getTransition */ public function testGetTransitionException() { $this->setExpectedException(\InvalidArgumentException::class, "The transition 'transition_that_does_not_exist' does not exist in workflow 'test'"); @@ -371,6 +374,52 @@ } /** + * @covers ::getTransitionsForState + */ + public function testGetTransitionsForState() { + $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('draft', 'draft', 'Create new draft') + ->addTransition('draft', 'published', 'Publish') + ->addTransition('published', 'published', 'Publish') + ->addTransition('published', 'archived', 'Archive') + ->addTransition('archived', 'draft', 'Create new draft'); + + $this->assertEquals(['draft-draft', 'draft-published'], array_keys($workflow->getTransitionsForState('draft'))); + $this->assertEquals(['draft-draft', 'archived-draft'], array_keys($workflow->getTransitionsForState('draft', 'to'))); + $this->assertEquals(['archived-draft'], array_keys($workflow->getTransitionsForState('archived', 'from'))); + $this->assertEquals(['published-archived'], array_keys($workflow->getTransitionsForState('archived', 'to'))); + } + + + /** + * @covers ::getTransitionFromStateToState + * @covers ::hasTransitionFromStateToState + */ + public function testGetTransitionsFromStateToState() { + $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('draft', 'draft', 'Create new draft') + ->addTransition('draft', 'published', 'Publish') + ->addTransition('published', 'published', 'Publish') + ->addTransition('published', 'archived', 'Archive') + ->addTransition('archived', 'draft', 'Create new draft'); + + $this->assertTrue($workflow->hasTransitionFromStateToState('draft', 'published')); + $this->assertFalse($workflow->hasTransitionFromStateToState('archived', 'archived')); + $transition = $workflow->getTransitionFromStateToState('published', 'archived'); + $this->assertEquals('Archive', $transition->label()); + } + + /** * @covers ::setTransitionLabel */ public function testSetTransitionLabel() { only in patch2: unchanged: --- /dev/null +++ b/core/modules/workflow/tests/src/Unit/TransitionTest.php @@ -0,0 +1,71 @@ +prophesize(WorkflowTypeInterface::class); + $workflow_type->decorateState(Argument::any())->willReturnArgument(0); + $workflow_type->decorateTransition(Argument::any())->willReturnArgument(0); + $workflow_manager = $this->prophesize(WorkflowTypeManager::class); + $workflow_manager->createInstance('test_type', Argument::any())->willReturn($workflow_type->reveal()); + $container->set('workflow.plugin.manager.workflow_type', $workflow_manager->reveal()); + \Drupal::setContainer($container); + } + + /** + * @covers ::__construct + * @covers ::id + * @covers ::label + */ + public function testGetters() { + $state = new Transition( + $this->prophesize(WorkflowInterface::class)->reveal(), + 'draft-published', + 'draft', + 'published', + 'Publish' + ); + $this->assertEquals('draft-published', $state->id()); + $this->assertEquals('Publish', $state->label()); + } + + /** + * @covers ::from + * @covers ::to + */ + public function testFromAndTo() { + $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow'); + $workflow + ->addState('draft', 'Draft') + ->addState('published', 'Published') + ->addTransition('draft', 'published', 'Publish'); + $state = $workflow->getState('draft'); + $transition = $state->getTransitionTo('published'); + $this->assertEquals($state, $transition->from()); + $this->assertEquals($workflow->getState('published'), $transition->to()); + } + +}