Update Composer, update everything
This commit is contained in:
parent
ea3e94409f
commit
dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions
|
@ -5,4 +5,4 @@ package: Testing
|
|||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- workflows
|
||||
- drupal:workflows
|
||||
|
|
|
@ -6,6 +6,10 @@ workflow.type_settings.workflow_type_test:
|
|||
type: sequence
|
||||
sequence:
|
||||
type: ignore
|
||||
transitions:
|
||||
type: sequence
|
||||
sequence:
|
||||
type: ignore
|
||||
|
||||
workflow.type_settings.workflow_type_required_state_test:
|
||||
type: mapping
|
||||
|
@ -15,28 +19,54 @@ workflow.type_settings.workflow_type_required_state_test:
|
|||
type: sequence
|
||||
sequence:
|
||||
type: ignore
|
||||
transitions:
|
||||
type: sequence
|
||||
sequence:
|
||||
type: ignore
|
||||
|
||||
# @todo, inline this straight into "workflow.type_settings.workflow_type_complex_test"
|
||||
# after https://www.drupal.org/node/2871746 is resolved.
|
||||
workflows.state.complex_test_state:
|
||||
type: workflows.state
|
||||
mapping:
|
||||
extra:
|
||||
type: string
|
||||
label: 'Extra information'
|
||||
|
||||
workflows.state.complex_test_transition:
|
||||
type: workflows.transition
|
||||
mapping:
|
||||
extra:
|
||||
type: string
|
||||
label: 'Extra information'
|
||||
|
||||
workflow.type_settings.workflow_type_complex_test:
|
||||
type: mapping
|
||||
label: 'Workflow complex test type settings'
|
||||
mapping:
|
||||
example_setting:
|
||||
type: string
|
||||
label: 'Example setting'
|
||||
states:
|
||||
type: sequence
|
||||
label: 'Additional state configuration'
|
||||
label: 'States'
|
||||
sequence:
|
||||
type: mapping
|
||||
type: workflows.state.complex_test_state
|
||||
label: 'States'
|
||||
mapping:
|
||||
extra:
|
||||
type: string
|
||||
label: 'Extra information'
|
||||
transitions:
|
||||
type: sequence
|
||||
label: 'Additional transition configuration'
|
||||
label: 'Transitions'
|
||||
sequence:
|
||||
type: mapping
|
||||
label: 'Transitions'
|
||||
mapping:
|
||||
extra:
|
||||
type: string
|
||||
label: 'Extra information'
|
||||
type: workflows.state.complex_test_transition
|
||||
|
||||
workflow.type_settings.predefined_states_workflow_test_type:
|
||||
type: mapping
|
||||
label: 'Predefined states workflow test type'
|
||||
mapping:
|
||||
transitions:
|
||||
type: sequence
|
||||
label: 'Transitions'
|
||||
sequence:
|
||||
label: 'Transitions'
|
||||
type: workflows.transition
|
||||
|
|
|
@ -1,90 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\workflow_type_test;
|
||||
|
||||
use Drupal\workflows\StateInterface;
|
||||
|
||||
/**
|
||||
* A value object representing a workflow state.
|
||||
*/
|
||||
class DecoratedState implements StateInterface {
|
||||
|
||||
/**
|
||||
* The vanilla state object from the Workflow module.
|
||||
*
|
||||
* @var \Drupal\workflows\StateInterface
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* Extra information added to state.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $extra;
|
||||
|
||||
/**
|
||||
* DecoratedState constructor.
|
||||
*
|
||||
* @param \Drupal\workflows\StateInterface $state
|
||||
* The vanilla state object from the Workflow module.
|
||||
* @param string $extra
|
||||
* (optional) Extra information stored on the state. Defaults to ''.
|
||||
*/
|
||||
public function __construct(StateInterface $state, $extra = '') {
|
||||
$this->state = $state;
|
||||
$this->extra = $extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the extra information stored on the state.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getExtra() {
|
||||
return $this->extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function id() {
|
||||
return $this->state->id();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function label() {
|
||||
return $this->state->label();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function weight() {
|
||||
return $this->state->weight();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function canTransitionTo($to_state_id) {
|
||||
return $this->state->canTransitionTo($to_state_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTransitionTo($to_state_id) {
|
||||
return $this->state->getTransitionTo($to_state_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTransitions() {
|
||||
return $this->state->getTransitions();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\workflow_type_test;
|
||||
|
||||
use Drupal\workflows\TransitionInterface;
|
||||
|
||||
/**
|
||||
* A value object representing a workflow transition.
|
||||
*/
|
||||
class DecoratedTransition implements TransitionInterface {
|
||||
|
||||
/**
|
||||
* The vanilla transition object from the Workflow module.
|
||||
*
|
||||
* @var \Drupal\workflows\TransitionInterface
|
||||
*/
|
||||
protected $transition;
|
||||
|
||||
/**
|
||||
* Extra information added to transition.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $extra;
|
||||
|
||||
/**
|
||||
* DecoratedTransition constructor.
|
||||
*
|
||||
* @param \Drupal\workflows\TransitionInterface $transition
|
||||
* The vanilla transition object from the Workflow module.
|
||||
* @param string $extra
|
||||
* (optional) Extra information stored on the transition. Defaults to ''.
|
||||
*/
|
||||
public function __construct(TransitionInterface $transition, $extra = '') {
|
||||
$this->transition = $transition;
|
||||
$this->extra = $extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the extra information stored on the transition.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getExtra() {
|
||||
return $this->extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function id() {
|
||||
return $this->transition->id();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function label() {
|
||||
return $this->transition->label();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function from() {
|
||||
return $this->transition->from();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function to() {
|
||||
return $this->transition->to();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function weight() {
|
||||
return $this->transition->weight();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\workflow_type_test\Form;
|
||||
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\workflows\Plugin\WorkflowTypeConfigureFormBase;
|
||||
|
||||
/**
|
||||
* Form to configure the complex test workflow type.
|
||||
*
|
||||
* @see \Drupal\workflow_type_test\Plugin\WorkflowType\ComplexTestType
|
||||
*/
|
||||
class ComplexTestTypeConfigureForm extends WorkflowTypeConfigureFormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
$type_configuration = $this->workflowType->getConfiguration();
|
||||
$form['example_setting'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Example global workflow setting'),
|
||||
'#description' => $this->t('Extra information added to the workflow'),
|
||||
'#default_value' => $type_configuration['example_setting'],
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
|
||||
$type_configuration = $this->workflowType->getConfiguration();
|
||||
$type_configuration['example_setting'] = $form_state->getValue('example_setting');
|
||||
$this->workflowType->setConfiguration($type_configuration);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\workflow_type_test\Form;
|
||||
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\workflows\Plugin\WorkflowTypeStateFormBase;
|
||||
|
||||
/**
|
||||
* Form to configure the complex test workflow states.
|
||||
*
|
||||
* @see \Drupal\workflow_type_test\Plugin\WorkflowType\ComplexTestType
|
||||
*/
|
||||
class ComplexTestTypeStateForm extends WorkflowTypeStateFormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
$state = $form_state->get('state');
|
||||
$configuration = $this->workflowType->getConfiguration();
|
||||
$form['extra'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Extra'),
|
||||
'#description' => $this->t('Extra information added to state'),
|
||||
'#default_value' => $state && isset($configuration['states'][$state->id()]['extra']) ? $configuration['states'][$state->id()]['extra'] : '',
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\workflow_type_test\Form;
|
||||
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\workflows\Plugin\WorkflowTypeTransitionFormBase;
|
||||
|
||||
/**
|
||||
* Form to configure the complex test workflow states.
|
||||
*
|
||||
* @see \Drupal\workflow_type_test\Plugin\WorkflowType\ComplexTestType
|
||||
*/
|
||||
class ComplexTestTypeTransitionForm extends WorkflowTypeTransitionFormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
$transition = $form_state->get('transition');
|
||||
$configuration = $this->workflowType->getConfiguration();
|
||||
$form['extra'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Extra'),
|
||||
'#description' => $this->t('Extra information added to transition'),
|
||||
'#default_value' => $transition && isset($configuration['transitions'][$transition->id()]['extra']) ? $configuration['transitions'][$transition->id()]['extra'] : '',
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
}
|
|
@ -2,14 +2,8 @@
|
|||
|
||||
namespace Drupal\workflow_type_test\Plugin\WorkflowType;
|
||||
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\workflows\Plugin\WorkflowTypeBase;
|
||||
use Drupal\workflows\StateInterface;
|
||||
use Drupal\workflows\TransitionInterface;
|
||||
use Drupal\workflows\WorkflowInterface;
|
||||
use Drupal\workflow_type_test\DecoratedState;
|
||||
use Drupal\workflow_type_test\DecoratedTransition;
|
||||
|
||||
/**
|
||||
* Test workflow type.
|
||||
|
@ -17,68 +11,17 @@ use Drupal\workflow_type_test\DecoratedTransition;
|
|||
* @WorkflowType(
|
||||
* id = "workflow_type_complex_test",
|
||||
* label = @Translation("Workflow Type Complex Test"),
|
||||
* forms = {
|
||||
* "configure" = "\Drupal\workflow_type_test\Form\ComplexTestTypeConfigureForm",
|
||||
* "state" = "\Drupal\workflow_type_test\Form\ComplexTestTypeStateForm",
|
||||
* "transition" = "\Drupal\workflow_type_test\Form\ComplexTestTypeTransitionForm",
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class ComplexTestType extends WorkflowTypeBase {
|
||||
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function decorateState(StateInterface $state) {
|
||||
if (isset($this->configuration['states'][$state->id()])) {
|
||||
$state = new DecoratedState($state, $this->configuration['states'][$state->id()]['extra']);
|
||||
}
|
||||
else {
|
||||
$state = new DecoratedState($state);
|
||||
}
|
||||
return $state;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function decorateTransition(TransitionInterface $transition) {
|
||||
if (isset($this->configuration['transitions'][$transition->id()])) {
|
||||
$transition = new DecoratedTransition($transition, $this->configuration['transitions'][$transition->id()]['extra']);
|
||||
}
|
||||
else {
|
||||
$transition = new DecoratedTransition($transition);
|
||||
}
|
||||
return $transition;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildStateConfigurationForm(FormStateInterface $form_state, WorkflowInterface $workflow, StateInterface $state = NULL) {
|
||||
/** @var \Drupal\workflow_type_test\DecoratedState $state */
|
||||
$form = [];
|
||||
$form['extra'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Extra'),
|
||||
'#description' => $this->t('Extra information added to state'),
|
||||
'#default_value' => isset($state) ? $state->getExtra() : FALSE,
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildTransitionConfigurationForm(FormStateInterface $form_state, WorkflowInterface $workflow, TransitionInterface $transition = NULL) {
|
||||
/** @var \Drupal\workflow_type_test\DecoratedTransition $transition */
|
||||
$form = [];
|
||||
$form['extra'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Extra'),
|
||||
'#description' => $this->t('Extra information added to transition'),
|
||||
'#default_value' => isset($transition) ? $transition->getExtra() : FALSE,
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -88,4 +31,13 @@ class ComplexTestType extends WorkflowTypeBase {
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defaultConfiguration() {
|
||||
return parent::defaultConfiguration() + [
|
||||
'example_setting' => '',
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\workflow_type_test\Plugin\WorkflowType;
|
||||
|
||||
use Drupal\workflows\Plugin\WorkflowTypeBase;
|
||||
use Drupal\workflows\State;
|
||||
|
||||
/**
|
||||
* Test workflow type.
|
||||
*
|
||||
* @WorkflowType(
|
||||
* id = "predefined_states_workflow_test_type",
|
||||
* label = @Translation("Predefined States Workflow Test Type"),
|
||||
* required_states = {
|
||||
* "pay_blinds",
|
||||
* "bet",
|
||||
* "raise",
|
||||
* "fold",
|
||||
* }
|
||||
* )
|
||||
*/
|
||||
class PredefinedStatesWorkflowTestType extends WorkflowTypeBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getStates($state_ids = NULL) {
|
||||
return array_filter([
|
||||
'pay_blinds' => new State($this, 'pay_blinds', 'Pay Blinds'),
|
||||
'bet' => new State($this, 'bet', 'Bet'),
|
||||
'raise' => new State($this, 'raise', 'Raise'),
|
||||
'fold' => new State($this, 'fold', 'Fold'),
|
||||
], function ($state) use ($state_ids) {
|
||||
return is_array($state_ids) ? in_array($state->id(), $state_ids) : TRUE;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getState($state_id) {
|
||||
$states = $this->getStates();
|
||||
if (!isset($states[$state_id])) {
|
||||
throw new \InvalidArgumentException("The state '$state_id' does not exist in workflow.'");
|
||||
}
|
||||
return $states[$state_id];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasState($state_id) {
|
||||
$states = $this->getStates();
|
||||
return isset($states[$state_id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addState($state_id, $label) {
|
||||
// States cannot be added on this workflow.
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setStateLabel($state_id, $label) {
|
||||
// States cannot be altered on this workflow.
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setStateWeight($state_id, $weight) {
|
||||
// States cannot be altered on this workflow.
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function deleteState($state_id) {
|
||||
// States cannot be deleted on this workflow.
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defaultConfiguration() {
|
||||
return [
|
||||
'transitions' => [],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -4,7 +4,6 @@ namespace Drupal\workflow_type_test\Plugin\WorkflowType;
|
|||
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\workflows\Plugin\WorkflowTypeBase;
|
||||
use Drupal\workflows\WorkflowInterface;
|
||||
|
||||
/**
|
||||
* Test workflow type.
|
||||
|
@ -22,24 +21,32 @@ class RequiredStateTestType extends WorkflowTypeBase {
|
|||
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function initializeWorkflow(WorkflowInterface $workflow) {
|
||||
$workflow
|
||||
->addState('fresh', $this->t('Fresh'))
|
||||
->setStateWeight('fresh', -5)
|
||||
->addState('rotten', $this->t('Rotten'))
|
||||
->addTransition('rot', $this->t('Rot'), ['fresh'], 'rotten');
|
||||
return $workflow;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defaultConfiguration() {
|
||||
// No configuration is stored for the test type.
|
||||
return [];
|
||||
return [
|
||||
'states' => [
|
||||
'fresh' => [
|
||||
'label' => 'Fresh',
|
||||
'weight' => 0,
|
||||
],
|
||||
'rotten' => [
|
||||
'label' => 'Rotten',
|
||||
'weight' => 1,
|
||||
],
|
||||
],
|
||||
'transitions' => [
|
||||
'rot' => [
|
||||
'label' => 'Rot',
|
||||
'to' => 'rotten',
|
||||
'weight' => 0,
|
||||
'from' => [
|
||||
'fresh',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,14 +14,6 @@ use Drupal\workflows\Plugin\WorkflowTypeBase;
|
|||
*/
|
||||
class TestType extends WorkflowTypeBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function defaultConfiguration() {
|
||||
// No configuration is stored for the test type.
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -5,4 +5,4 @@ package: Testing
|
|||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- workflows
|
||||
- drupal:workflows
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Module file for workflow_type_test.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_workflow_type_info_alter().
|
||||
*/
|
||||
function workflow_type_test_workflow_type_info_alter(&$definitions) {
|
||||
// Allow tests to override the workflow type definitions.
|
||||
$state = \Drupal::state();
|
||||
if ($state->get('workflow_type_test.plugin_definitions') !== NULL) {
|
||||
$definitions = $state->get('workflow_type_test.plugin_definitions');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type plugin definitions override and clear the cache.
|
||||
*
|
||||
* @param array $definitions
|
||||
* Definitions to set.
|
||||
*/
|
||||
function workflow_type_test_set_definitions($definitions) {
|
||||
\Drupal::state()->set('workflow_type_test.plugin_definitions', $definitions);
|
||||
\Drupal::service('plugin.manager.workflows.type')->clearCachedDefinitions();
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\workflows\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
use Drupal\Tests\workflows\Functional\Rest\WorkflowResourceTestBase;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class WorkflowHalJsonAnonTest extends WorkflowResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['hal'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'hal_json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/hal+json';
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\workflows\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class WorkflowHalJsonBasicAuthTest extends WorkflowHalJsonAnonTest {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\workflows\Functional\Hal;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group hal
|
||||
*/
|
||||
class WorkflowHalJsonCookieTest extends WorkflowHalJsonAnonTest {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\workflows\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class WorkflowJsonAnonTest extends WorkflowResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\workflows\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class WorkflowJsonBasicAuthTest extends WorkflowResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\workflows\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class WorkflowJsonCookieTest extends WorkflowResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'application/json';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\workflows\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\EntityResource\EntityResourceTestBase;
|
||||
use Drupal\workflows\Entity\Workflow;
|
||||
|
||||
/**
|
||||
* ResourceTestBase for Workflow entity.
|
||||
*/
|
||||
abstract class WorkflowResourceTestBase extends EntityResourceTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'workflows',
|
||||
'workflow_type_test',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $entityTypeId = 'workflow';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $patchProtectedFieldNames = [];
|
||||
|
||||
/**
|
||||
* The Workflow entity.
|
||||
*
|
||||
* @var \Drupal\workflows\WorkflowInterface
|
||||
*/
|
||||
protected $entity;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUpAuthorization($method) {
|
||||
$this->grantPermissionsToTestedRole(['administer workflows']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createEntity() {
|
||||
$workflow = Workflow::create([
|
||||
'id' => 'rest_workflow',
|
||||
'label' => 'REST Worklow',
|
||||
'type' => 'workflow_type_complex_test',
|
||||
]);
|
||||
$workflow
|
||||
->getTypePlugin()
|
||||
->addState('draft', 'Draft')
|
||||
->addState('published', 'Published');
|
||||
$configuration = $workflow->getTypePlugin()->getConfiguration();
|
||||
$configuration['example_setting'] = 'foo';
|
||||
$configuration['states']['draft']['extra'] = 'bar';
|
||||
$workflow->getTypePlugin()->setConfiguration($configuration);
|
||||
$workflow->save();
|
||||
return $workflow;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getExpectedNormalizedEntity() {
|
||||
return [
|
||||
'dependencies' => [
|
||||
'module' => [
|
||||
'workflow_type_test',
|
||||
],
|
||||
],
|
||||
'id' => 'rest_workflow',
|
||||
'label' => 'REST Worklow',
|
||||
'langcode' => 'en',
|
||||
'status' => TRUE,
|
||||
'type' => 'workflow_type_complex_test',
|
||||
'type_settings' => [
|
||||
'states' => [
|
||||
'draft' => [
|
||||
'extra' => 'bar',
|
||||
'label' => 'Draft',
|
||||
'weight' => 0,
|
||||
],
|
||||
'published' => [
|
||||
'label' => 'Published',
|
||||
'weight' => 1,
|
||||
],
|
||||
],
|
||||
'transitions' => [],
|
||||
'example_setting' => 'foo',
|
||||
],
|
||||
'uuid' => $this->entity->uuid(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getNormalizedPostEntity() {
|
||||
// @todo Update in https://www.drupal.org/node/2300677.
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\workflows\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\AnonResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class WorkflowXmlAnonTest extends WorkflowResourceTestBase {
|
||||
|
||||
use AnonResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\workflows\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\BasicAuthResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class WorkflowXmlBasicAuthTest extends WorkflowResourceTestBase {
|
||||
|
||||
use BasicAuthResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['basic_auth'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'basic_auth';
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\workflows\Functional\Rest;
|
||||
|
||||
use Drupal\Tests\rest\Functional\CookieResourceTestTrait;
|
||||
use Drupal\Tests\rest\Functional\EntityResource\XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* @group rest
|
||||
*/
|
||||
class WorkflowXmlCookieTest extends WorkflowResourceTestBase {
|
||||
|
||||
use CookieResourceTestTrait;
|
||||
use XmlEntityNormalizationQuirksTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $format = 'xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $mimeType = 'text/xml; charset=UTF-8';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $auth = 'cookie';
|
||||
|
||||
}
|
|
@ -38,6 +38,7 @@ class WorkflowUiNoTypeTest extends BrowserTestBase {
|
|||
|
||||
$this->drupalGet('admin/config/workflow/workflows');
|
||||
$this->assertSession()->pageTextContains('There are no workflow types available. In order to create workflows you need to install a module that provides a workflow type. For example, the Content Moderation module provides a workflow type that enables workflows for content entities.');
|
||||
$this->assertSession()->linkExists('Content Moderation');
|
||||
$this->assertSession()->pageTextNotContains('Add workflow');
|
||||
|
||||
$this->container->get('module_installer')->install(['workflow_type_test']);
|
||||
|
@ -48,7 +49,7 @@ class WorkflowUiNoTypeTest extends BrowserTestBase {
|
|||
$this->drupalGet('admin/config/workflow/workflows');
|
||||
$this->assertSession()->pageTextNotContains('There are no workflow types available. In order to create workflows you need to install a module that provides a workflow type. For example, the Content Moderation module provides a workflow type that enables workflows for content entities.');
|
||||
$this->assertSession()->linkExists('Add workflow');
|
||||
$this->assertSession()->pageTextContains('There is no Workflow yet.');
|
||||
$this->assertSession()->pageTextContains('There are no workflows yet.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,10 +36,11 @@ class WorkflowUiTest extends BrowserTestBase {
|
|||
// Create a minimal workflow for testing.
|
||||
$workflow = Workflow::create(['id' => 'test', 'type' => 'workflow_type_test']);
|
||||
$workflow
|
||||
->getTypePlugin()
|
||||
->addState('draft', 'Draft')
|
||||
->addState('published', 'Published')
|
||||
->addTransition('publish', 'Publish', ['draft', 'published'], 'published')
|
||||
->save();
|
||||
->addTransition('publish', 'Publish', ['draft', 'published'], 'published');
|
||||
$workflow->save();
|
||||
|
||||
$paths = [
|
||||
'admin/config/workflow/workflows',
|
||||
|
@ -79,6 +80,31 @@ class WorkflowUiTest extends BrowserTestBase {
|
|||
$this->assertSession()->statusCodeEquals(403);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the machine name validation of the state add form.
|
||||
*/
|
||||
public function testStateMachineNameValidation() {
|
||||
Workflow::create([
|
||||
'id' => 'test_workflow',
|
||||
'type' => 'workflow_type_test',
|
||||
])->save();
|
||||
|
||||
$this->drupalLogin($this->createUser(['administer workflows']));
|
||||
|
||||
$this->drupalPostForm('admin/config/workflow/workflows/manage/test_workflow/add_state', [
|
||||
'label' => 'Test State',
|
||||
'id' => 'Invalid ID',
|
||||
], 'Save');
|
||||
$this->assertSession()->statusCodeEquals(200);
|
||||
$this->assertSession()->pageTextContains('The machine-readable name must contain only lowercase letters, numbers, and underscores.');
|
||||
|
||||
$this->drupalPostForm('admin/config/workflow/workflows/manage/test_workflow/add_transition', [
|
||||
'label' => 'Test Transition',
|
||||
'id' => 'Invalid ID',
|
||||
], 'Save');
|
||||
$this->assertSession()->pageTextContains('The machine-readable name must contain only lowercase letters, numbers, and underscores.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the creation of a workflow through the UI.
|
||||
*/
|
||||
|
@ -90,7 +116,7 @@ class WorkflowUiTest extends BrowserTestBase {
|
|||
$this->assertSession()->linkByHrefExists('admin/config/workflow/workflows');
|
||||
$this->clickLink('Workflows');
|
||||
$this->assertSession()->pageTextContains('Workflows');
|
||||
$this->assertSession()->pageTextContains('There is no Workflow yet.');
|
||||
$this->assertSession()->pageTextContains('There are no workflows yet.');
|
||||
$this->clickLink('Add workflow');
|
||||
$this->submitForm(['label' => 'Test', 'id' => 'test', 'workflow_type' => 'workflow_type_test'], 'Save');
|
||||
$this->assertSession()->pageTextContains('Created the Test Workflow.');
|
||||
|
@ -102,26 +128,28 @@ class WorkflowUiTest extends BrowserTestBase {
|
|||
$this->submitForm(['label' => 'Published', 'id' => 'published'], 'Save');
|
||||
$this->assertSession()->pageTextContains('Created Published state.');
|
||||
$workflow = $workflow_storage->loadUnchanged('test');
|
||||
$this->assertFalse($workflow->getState('published')->canTransitionTo('published'), 'No default transition from published to published exists.');
|
||||
$this->assertFalse($workflow->getTypePlugin()->getState('published')->canTransitionTo('published'), 'No default transition from published to published exists.');
|
||||
|
||||
$this->clickLink('Add a new state');
|
||||
// Don't create a draft to draft transition by default.
|
||||
$this->submitForm(['label' => 'Draft', 'id' => 'draft'], 'Save');
|
||||
$this->assertSession()->pageTextContains('Created Draft state.');
|
||||
$workflow = $workflow_storage->loadUnchanged('test');
|
||||
$this->assertFalse($workflow->getState('draft')->canTransitionTo('draft'), 'Can not transition from draft to draft');
|
||||
$this->assertFalse($workflow->getTypePlugin()->getState('draft')->canTransitionTo('draft'), 'Can not transition from draft to draft');
|
||||
|
||||
$this->clickLink('Add a new transition');
|
||||
$this->submitForm(['id' => 'publish', 'label' => 'Publish', 'from[draft]' => 'draft', 'to' => 'published'], 'Save');
|
||||
$this->assertSession()->pageTextContains('Created Publish transition.');
|
||||
$workflow = $workflow_storage->loadUnchanged('test');
|
||||
$this->assertTrue($workflow->getState('draft')->canTransitionTo('published'), 'Can transition from draft to published');
|
||||
$this->assertTrue($workflow->getTypePlugin()->getState('draft')->canTransitionTo('published'), 'Can transition from draft to published');
|
||||
|
||||
$this->clickLink('Add a new transition');
|
||||
$this->assertCount(2, $this->cssSelect('input[name="to"][type="radio"]'));
|
||||
$this->assertCount(0, $this->cssSelect('input[name="to"][checked="checked"][type="radio"]'));
|
||||
$this->submitForm(['id' => 'create_new_draft', 'label' => 'Create new draft', 'from[draft]' => 'draft', 'to' => 'draft'], 'Save');
|
||||
$this->assertSession()->pageTextContains('Created Create new draft transition.');
|
||||
$workflow = $workflow_storage->loadUnchanged('test');
|
||||
$this->assertTrue($workflow->getState('draft')->canTransitionTo('draft'), 'Can transition from draft to draft');
|
||||
$this->assertTrue($workflow->getTypePlugin()->getState('draft')->canTransitionTo('draft'), 'Can transition from draft to draft');
|
||||
|
||||
// The fist state to edit on the page should be published.
|
||||
$this->clickLink('Edit');
|
||||
|
@ -135,7 +163,7 @@ class WorkflowUiTest extends BrowserTestBase {
|
|||
$this->submitForm(['from[published]' => 'published'], 'Save');
|
||||
$this->assertSession()->pageTextContains('Saved Create new draft transition.');
|
||||
$workflow = $workflow_storage->loadUnchanged('test');
|
||||
$this->assertTrue($workflow->getState('published')->canTransitionTo('draft'), 'Can transition from published to draft');
|
||||
$this->assertTrue($workflow->getTypePlugin()->getState('published')->canTransitionTo('draft'), 'Can transition from published to draft');
|
||||
|
||||
// Try creating a duplicate transition.
|
||||
$this->clickLink('Add a new transition');
|
||||
|
@ -155,12 +183,12 @@ class WorkflowUiTest extends BrowserTestBase {
|
|||
|
||||
// Delete the transition.
|
||||
$workflow = $workflow_storage->loadUnchanged('test');
|
||||
$this->assertTrue($workflow->hasTransitionFromStateToState('published', 'published'), 'Can transition from published to published');
|
||||
$this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('published', 'published'), 'Can transition from published to published');
|
||||
$this->clickLink('Delete');
|
||||
$this->assertSession()->pageTextContains('Are you sure you want to delete Save and publish from Test?');
|
||||
$this->submitForm([], 'Delete');
|
||||
$workflow = $workflow_storage->loadUnchanged('test');
|
||||
$this->assertFalse($workflow->hasTransitionFromStateToState('published', 'published'), 'Cannot transition from published to published');
|
||||
$this->assertFalse($workflow->getTypePlugin()->hasTransitionFromStateToState('published', 'published'), 'Cannot transition from published to published');
|
||||
|
||||
// Try creating a duplicate state.
|
||||
$this->drupalGet('admin/config/workflow/workflows/manage/test');
|
||||
|
@ -170,26 +198,24 @@ class WorkflowUiTest extends BrowserTestBase {
|
|||
|
||||
// Ensure that weight changes the state ordering.
|
||||
$workflow = $workflow_storage->loadUnchanged('test');
|
||||
$this->assertEquals('published', $workflow->getTypePlugin()->getInitialState($workflow)->id());
|
||||
$this->assertEquals('published', $workflow->getTypePlugin()->getInitialState()->id());
|
||||
$this->drupalGet('admin/config/workflow/workflows/manage/test');
|
||||
$this->submitForm(['states[draft][weight]' => '-1'], 'Save');
|
||||
$workflow = $workflow_storage->loadUnchanged('test');
|
||||
$this->assertEquals('draft', $workflow->getTypePlugin()->getInitialState($workflow)->id());
|
||||
$this->assertEquals('draft', $workflow->getTypePlugin()->getInitialState()->id());
|
||||
|
||||
// This will take us to the list of workflows, so we need to edit the
|
||||
// workflow again.
|
||||
$this->clickLink('Edit');
|
||||
// Verify that we are still on the workflow edit page.
|
||||
$this->assertSession()->addressEquals('admin/config/workflow/workflows/manage/test');
|
||||
|
||||
// Ensure that weight changes the transition ordering.
|
||||
$this->assertEquals(['publish', 'create_new_draft'], array_keys($workflow->getTransitions()));
|
||||
$this->assertEquals(['publish', 'create_new_draft'], array_keys($workflow->getTypePlugin()->getTransitions()));
|
||||
$this->drupalGet('admin/config/workflow/workflows/manage/test');
|
||||
$this->submitForm(['transitions[create_new_draft][weight]' => '-1'], 'Save');
|
||||
$workflow = $workflow_storage->loadUnchanged('test');
|
||||
$this->assertEquals(['create_new_draft', 'publish'], array_keys($workflow->getTransitions()));
|
||||
$this->assertEquals(['create_new_draft', 'publish'], array_keys($workflow->getTypePlugin()->getTransitions()));
|
||||
|
||||
// This will take us to the list of workflows, so we need to edit the
|
||||
// workflow again.
|
||||
$this->clickLink('Edit');
|
||||
// Verify that we are still on the workflow edit page.
|
||||
$this->assertSession()->addressEquals('admin/config/workflow/workflows/manage/test');
|
||||
|
||||
// Ensure that a delete link for the published state exists before deleting
|
||||
// the draft state.
|
||||
|
@ -224,8 +250,8 @@ class WorkflowUiTest extends BrowserTestBase {
|
|||
$this->submitForm([], 'Delete');
|
||||
$this->assertSession()->pageTextContains('State Draft deleted.');
|
||||
$workflow = $workflow_storage->loadUnchanged('test');
|
||||
$this->assertFalse($workflow->hasState('draft'), 'Draft state deleted');
|
||||
$this->assertTrue($workflow->hasState('published'), 'Workflow still has published state');
|
||||
$this->assertFalse($workflow->getTypePlugin()->hasState('draft'), 'Draft state deleted');
|
||||
$this->assertTrue($workflow->getTypePlugin()->hasState('published'), 'Workflow still has published state');
|
||||
|
||||
// The last state cannot be deleted so the only delete link on the page will
|
||||
// be for the workflow.
|
||||
|
@ -234,69 +260,157 @@ class WorkflowUiTest extends BrowserTestBase {
|
|||
$this->assertSession()->pageTextContains('Are you sure you want to delete Test?');
|
||||
$this->submitForm([], 'Delete');
|
||||
$this->assertSession()->pageTextContains('Workflow Test deleted.');
|
||||
$this->assertSession()->pageTextContains('There is no Workflow yet.');
|
||||
$this->assertSession()->pageTextContains('There are no workflows yet.');
|
||||
$this->assertNull($workflow_storage->loadUnchanged('test'), 'The test workflow has been deleted');
|
||||
|
||||
// Ensure that workflow types that implement
|
||||
// \Drupal\workflows\WorkflowTypeInterface::initializeWorkflow() are
|
||||
// initialized correctly.
|
||||
// Ensure that workflow types with default configuration are initialized
|
||||
// correctly.
|
||||
$this->drupalGet('admin/config/workflow/workflows');
|
||||
$this->clickLink('Add workflow');
|
||||
$this->submitForm(['label' => 'Test 2', 'id' => 'test2', 'workflow_type' => 'workflow_type_required_state_test'], 'Save');
|
||||
$this->assertSession()->addressEquals('admin/config/workflow/workflows/manage/test2');
|
||||
$workflow = $workflow_storage->loadUnchanged('test2');
|
||||
$this->assertTrue($workflow->hasState('fresh'), 'The workflow has the "fresh" state');
|
||||
$this->assertTrue($workflow->hasState('rotten'), 'The workflow has the "rotten" state');
|
||||
$this->assertTrue($workflow->hasTransition('rot'), 'The workflow has the "rot" transition');
|
||||
$this->assertTrue($workflow->getTypePlugin()->hasState('fresh'), 'The workflow has the "fresh" state');
|
||||
$this->assertTrue($workflow->getTypePlugin()->hasState('rotten'), 'The workflow has the "rotten" state');
|
||||
$this->assertTrue($workflow->getTypePlugin()->hasTransition('rot'), 'The workflow has the "rot" transition');
|
||||
$this->assertSession()->pageTextContains('Fresh');
|
||||
$this->assertSession()->pageTextContains('Rotten');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that workflow types can add form fields to states and transitions.
|
||||
* Test the workflow configuration form.
|
||||
*/
|
||||
public function testWorkflowDecoration() {
|
||||
// Create a minimal workflow for testing.
|
||||
$workflow = Workflow::create(['id' => 'test', 'type' => 'workflow_type_complex_test']);
|
||||
public function testWorkflowConfigurationForm() {
|
||||
$workflow = Workflow::create(['id' => 'test', 'type' => 'workflow_type_complex_test', 'label' => 'Test']);
|
||||
$workflow
|
||||
->getTypePlugin()
|
||||
->addState('published', 'Published')
|
||||
->addTransition('publish', 'Publish', ['published'], 'published')
|
||||
->save();
|
||||
|
||||
$this->assertEquals('', $workflow->getState('published')->getExtra());
|
||||
$this->assertEquals('', $workflow->getTransition('publish')->getExtra());
|
||||
->addTransition('publish', 'Publish', ['published'], 'published');
|
||||
$workflow->save();
|
||||
|
||||
$this->drupalLogin($this->createUser(['administer workflows']));
|
||||
|
||||
// Add additional state information when editing.
|
||||
$this->drupalGet('admin/config/workflow/workflows/manage/test/state/published');
|
||||
$this->assertSession()->pageTextContains('Extra information added to state');
|
||||
$this->submitForm(['type_settings[workflow_type_complex_test][extra]' => 'Extra state information'], 'Save');
|
||||
|
||||
// Add additional transition information when editing.
|
||||
$this->drupalGet('admin/config/workflow/workflows/manage/test/transition/publish');
|
||||
$this->assertSession()->pageTextContains('Extra information added to transition');
|
||||
$this->submitForm(['type_settings[workflow_type_complex_test][extra]' => 'Extra transition information'], 'Save');
|
||||
// Add additional information to the workflow via the configuration form.
|
||||
$this->drupalGet('admin/config/workflow/workflows/manage/test');
|
||||
$this->assertSession()->pageTextContains('Example global workflow setting');
|
||||
$this->submitForm(['type_settings[example_setting]' => 'Extra global settings'], 'Save');
|
||||
|
||||
$workflow_storage = $this->container->get('entity_type.manager')->getStorage('workflow');
|
||||
/** @var \Drupal\workflows\WorkflowInterface $workflow */
|
||||
$workflow = $workflow_storage->loadUnchanged('test');
|
||||
$this->assertEquals('Extra state information', $workflow->getState('published')->getExtra());
|
||||
$this->assertEquals('Extra transition information', $workflow->getTransition('publish')->getExtra());
|
||||
$this->assertEquals('Extra global settings', $workflow->getTypePlugin()->getConfiguration()['example_setting']);
|
||||
}
|
||||
|
||||
// Add additional state information when adding.
|
||||
$this->drupalGet('admin/config/workflow/workflows/manage/test/add_state');
|
||||
$this->assertSession()->pageTextContains('Extra information added to state');
|
||||
$this->submitForm(['label' => 'Draft', 'id' => 'draft', 'type_settings[workflow_type_complex_test][extra]' => 'Extra state information on add'], 'Save');
|
||||
/**
|
||||
* Test a workflow, state, and transition can have a numeric ID and label.
|
||||
*/
|
||||
public function testNumericIds() {
|
||||
$this->drupalLogin($this->createUser(['administer workflows']));
|
||||
$this->drupalGet('admin/config/workflow/workflows');
|
||||
$this->clickLink('Add workflow');
|
||||
$this->submitForm(['label' => 123, 'id' => 123, 'workflow_type' => 'workflow_type_complex_test'], 'Save');
|
||||
|
||||
// Add additional transition information when adding.
|
||||
$this->drupalGet('admin/config/workflow/workflows/manage/test/add_transition');
|
||||
$this->assertSession()->pageTextContains('Extra information added to transition');
|
||||
$this->submitForm(['id' => 'draft_published', 'label' => 'Publish', 'from[draft]' => 'draft', 'to' => 'published', 'type_settings[workflow_type_complex_test][extra]' => 'Extra transition information on add'], 'Save');
|
||||
$this->assertSession()->addressEquals('admin/config/workflow/workflows/manage/123/add_state');
|
||||
|
||||
$workflow = $workflow_storage->loadUnchanged('test');
|
||||
$this->assertEquals('Extra state information on add', $workflow->getState('draft')->getExtra());
|
||||
$this->assertEquals('Extra transition information on add', $workflow->getTransition('draft_published')->getExtra());
|
||||
$this->submitForm(['label' => 456, 'id' => 456], 'Save');
|
||||
$this->assertSession()->pageTextContains('Created 456 state.');
|
||||
|
||||
$this->clickLink('Add a new state');
|
||||
$this->submitForm(['label' => 789, 'id' => 789], 'Save');
|
||||
$this->assertSession()->pageTextContains('Created 789 state.');
|
||||
|
||||
$this->clickLink('Add a new transition');
|
||||
$this->submitForm(['id' => 101112, 'label' => 101112, 'from[456]' => 456, 'to' => 789], 'Save');
|
||||
$this->assertSession()->pageTextContains('Created 101112 transition.');
|
||||
|
||||
$workflow = $this->container->get('entity_type.manager')->getStorage('workflow')->loadUnchanged(123);
|
||||
$this->assertEquals(123, $workflow->id());
|
||||
$this->assertEquals(456, $workflow->getTypePlugin()->getState(456)->id());
|
||||
$this->assertEquals(101112, $workflow->getTypePlugin()->getTransition(101112)->id());
|
||||
$this->assertEquals(789, $workflow->getTypePlugin()->getTransition(101112)->to()->id());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the sorting of states and transitions by weight and label.
|
||||
*/
|
||||
public function testSorting() {
|
||||
$workflow = Workflow::create(['id' => 'test', 'type' => 'workflow_type_complex_test', 'label' => 'Test']);
|
||||
$workflow
|
||||
->getTypePlugin()
|
||||
->setConfiguration([
|
||||
'states' => [
|
||||
'twoa' => [
|
||||
'label' => 'twoa',
|
||||
'weight' => 2,
|
||||
],
|
||||
'three' => [
|
||||
'label' => 'three',
|
||||
'weight' => 3,
|
||||
],
|
||||
'twob' => [
|
||||
'label' => 'twob',
|
||||
'weight' => 2,
|
||||
],
|
||||
'one' => [
|
||||
'label' => 'one',
|
||||
'weight' => 1,
|
||||
],
|
||||
],
|
||||
'transitions' => [
|
||||
'three' => [
|
||||
'label' => 'three',
|
||||
'from' => ['three'],
|
||||
'to' => 'three',
|
||||
'weight' => 3,
|
||||
],
|
||||
'twoa' => [
|
||||
'label' => 'twoa',
|
||||
'from' => ['twoa'],
|
||||
'to' => 'twoa',
|
||||
'weight' => 2,
|
||||
],
|
||||
'one' => [
|
||||
'label' => 'one',
|
||||
'from' => ['one'],
|
||||
'to' => 'one',
|
||||
'weight' => 1,
|
||||
],
|
||||
'twob' => [
|
||||
'label' => 'twob',
|
||||
'from' => ['twob'],
|
||||
'to' => 'twob',
|
||||
'weight' => 2,
|
||||
],
|
||||
],
|
||||
]);
|
||||
$workflow->save();
|
||||
|
||||
$this->drupalLogin($this->createUser(['administer workflows']));
|
||||
$this->drupalGet('admin/config/workflow/workflows/manage/test');
|
||||
$expected_states = ['one', 'twoa', 'twob', 'three'];
|
||||
$elements = $this->xpath('//details[@id="edit-states-container"]//table/tbody/tr');
|
||||
foreach ($elements as $key => $element) {
|
||||
$this->assertEquals($expected_states[$key], $element->find('xpath', 'td')->getText());
|
||||
}
|
||||
$expected_transitions = ['one', 'twoa', 'twob', 'three'];
|
||||
$elements = $this->xpath('//details[@id="edit-transitions-container"]//table/tbody/tr');
|
||||
foreach ($elements as $key => $element) {
|
||||
$this->assertEquals($expected_transitions[$key], $element->find('xpath', 'td')->getText());
|
||||
}
|
||||
|
||||
// Ensure that there are enough weights to satisfy the potential number of
|
||||
// states and transitions.
|
||||
$this->assertSession()
|
||||
->selectExists('states[three][weight]')
|
||||
->selectOption('2');
|
||||
$this->assertSession()
|
||||
->selectExists('states[three][weight]')
|
||||
->selectOption('-2');
|
||||
$this->assertSession()
|
||||
->selectExists('transitions[three][weight]')
|
||||
->selectOption('2');
|
||||
$this->assertSession()
|
||||
->selectExists('transitions[three][weight]')
|
||||
->selectOption('-2');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,13 +4,11 @@ namespace Drupal\Tests\workflows\Kernel;
|
|||
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\workflows\Entity\Workflow;
|
||||
use Drupal\workflow_type_test\DecoratedState;
|
||||
use Drupal\workflow_type_test\DecoratedTransition;
|
||||
|
||||
/**
|
||||
* Workflow entity tests that require modules or storage.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\workflows\Entity\Workflow
|
||||
* @coversDefaultClass \Drupal\workflow_type_test\Plugin\WorkflowType\ComplexTestType
|
||||
*
|
||||
* @group workflows
|
||||
*/
|
||||
|
@ -22,22 +20,7 @@ class ComplexWorkflowTypeTest extends KernelTestBase {
|
|||
public static $modules = ['workflows', 'workflow_type_test'];
|
||||
|
||||
/**
|
||||
* Tests a workflow type that decorates transitions and states.
|
||||
*
|
||||
* @covers ::getState
|
||||
* @covers ::getTransition
|
||||
*/
|
||||
public function testComplexType() {
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'workflow_type_complex_test'], 'workflow');
|
||||
$workflow
|
||||
->addState('draft', 'Draft')
|
||||
->addTransition('create_new_draft', 'Create new draft', ['draft'], 'draft');
|
||||
$this->assertInstanceOf(DecoratedState::class, $workflow->getState('draft'));
|
||||
$this->assertInstanceOf(DecoratedTransition::class, $workflow->getTransition('create_new_draft'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::loadMultipleByType
|
||||
* @covers \Drupal\workflows\Entity\Workflow::loadMultipleByType
|
||||
*/
|
||||
public function testLoadMultipleByType() {
|
||||
$workflow1 = new Workflow(['id' => 'test1', 'type' => 'workflow_type_complex_test'], 'workflow');
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\workflows\Kernel;
|
||||
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\workflows\Entity\Workflow;
|
||||
|
||||
/**
|
||||
* Test a predefined workflow based on something other than configuration.
|
||||
*
|
||||
* @group workflows
|
||||
*/
|
||||
class PredefinedWorkflowTypeTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['workflows', 'workflow_type_test'];
|
||||
|
||||
/**
|
||||
* Test a predefined workflow type.
|
||||
*/
|
||||
public function testPredefinedWorkflowType() {
|
||||
$workflow = Workflow::create([
|
||||
'id' => 'aces',
|
||||
'label' => 'Aces Workflow',
|
||||
'type' => 'predefined_states_workflow_test_type',
|
||||
'transitions' => [
|
||||
'bet' => [
|
||||
'label' => 'Bet',
|
||||
'from' => [
|
||||
'pay_blinds',
|
||||
],
|
||||
'to' => 'bet',
|
||||
],
|
||||
'raise' => [
|
||||
'label' => 'Raise',
|
||||
'from' => [
|
||||
'pay_blinds',
|
||||
],
|
||||
'to' => 'raise',
|
||||
],
|
||||
],
|
||||
]);
|
||||
$workflow->save();
|
||||
|
||||
// No states configuration is stored for this workflow.
|
||||
$configuration = $workflow->getTypePlugin()->getConfiguration();
|
||||
$this->assertFalse(isset($configuration['states']));
|
||||
}
|
||||
|
||||
}
|
|
@ -22,7 +22,6 @@ class RequiredStatesTest extends KernelTestBase {
|
|||
|
||||
/**
|
||||
* @covers ::getRequiredStates
|
||||
* @covers ::initializeWorkflow
|
||||
* @covers ::__construct
|
||||
*/
|
||||
public function testGetRequiredStates() {
|
||||
|
@ -30,15 +29,14 @@ class RequiredStatesTest extends KernelTestBase {
|
|||
'id' => 'test',
|
||||
'type' => 'workflow_type_required_state_test',
|
||||
], 'workflow');
|
||||
$workflow = $workflow->getTypePlugin()->initializeWorkflow($workflow);
|
||||
$workflow->save();
|
||||
$this->assertEquals(['fresh', 'rotten'], $workflow->getTypePlugin()
|
||||
->getRequiredStates());
|
||||
|
||||
// Ensure that the workflow has the default configuration.
|
||||
$this->assertTrue($workflow->hasState('rotten'));
|
||||
$this->assertTrue($workflow->hasState('fresh'));
|
||||
$this->assertTrue($workflow->hasTransitionFromStateToState('fresh', 'rotten'));
|
||||
$this->assertTrue($workflow->getTypePlugin()->hasState('rotten'));
|
||||
$this->assertTrue($workflow->getTypePlugin()->hasState('fresh'));
|
||||
$this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('fresh', 'rotten'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,11 +47,11 @@ class RequiredStatesTest extends KernelTestBase {
|
|||
'id' => 'test',
|
||||
'type' => 'workflow_type_required_state_test',
|
||||
], 'workflow');
|
||||
$workflow = $workflow->getTypePlugin()->initializeWorkflow($workflow);
|
||||
$workflow->save();
|
||||
// Ensure that required states can't be deleted.
|
||||
$this->setExpectedException(RequiredStateMissingException::class, "Required State Type Test' requires states with the ID 'fresh' in workflow 'test'");
|
||||
$workflow->deleteState('fresh')->save();
|
||||
$workflow->getTypePlugin()->deleteState('fresh');
|
||||
$workflow->save();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -63,6 +61,9 @@ class RequiredStatesTest extends KernelTestBase {
|
|||
$workflow = new Workflow([
|
||||
'id' => 'test',
|
||||
'type' => 'workflow_type_required_state_test',
|
||||
'type_settings' => [
|
||||
'states' => [],
|
||||
],
|
||||
], 'workflow');
|
||||
$this->setExpectedException(RequiredStateMissingException::class, "Required State Type Test' requires states with the ID 'fresh', 'rotten' in workflow 'test'");
|
||||
$workflow->save();
|
||||
|
@ -76,45 +77,49 @@ class RequiredStatesTest extends KernelTestBase {
|
|||
'id' => 'test',
|
||||
'type' => 'workflow_type_required_state_test',
|
||||
], 'workflow');
|
||||
$workflow = $workflow->getTypePlugin()->initializeWorkflow($workflow);
|
||||
$workflow->save();
|
||||
|
||||
// Ensure states added by default configuration can be changed.
|
||||
$this->assertEquals('Fresh', $workflow->getState('fresh')->label());
|
||||
$this->assertEquals('Fresh', $workflow->getTypePlugin()->getState('fresh')->label());
|
||||
$workflow
|
||||
->setStateLabel('fresh', 'Fresher')
|
||||
->save();
|
||||
$this->assertEquals('Fresher', $workflow->getState('fresh')->label());
|
||||
->getTypePlugin()
|
||||
->setStateLabel('fresh', 'Fresher');
|
||||
$workflow->save();
|
||||
$this->assertEquals('Fresher', $workflow->getTypePlugin()->getState('fresh')->label());
|
||||
|
||||
// Ensure transitions can be altered.
|
||||
$workflow
|
||||
->getTypePlugin()
|
||||
->addState('cooked', 'Cooked')
|
||||
->setTransitionFromStates('rot', ['fresh', 'cooked'])
|
||||
->save();
|
||||
$this->assertTrue($workflow->hasTransitionFromStateToState('fresh', 'rotten'));
|
||||
$this->assertTrue($workflow->hasTransitionFromStateToState('cooked', 'rotten'));
|
||||
->setTransitionFromStates('rot', ['fresh', 'cooked']);
|
||||
$workflow->save();
|
||||
$this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('fresh', 'rotten'));
|
||||
$this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('cooked', 'rotten'));
|
||||
|
||||
$workflow
|
||||
->setTransitionFromStates('rot', ['cooked'])
|
||||
->save();
|
||||
$this->assertFalse($workflow->hasTransitionFromStateToState('fresh', 'rotten'));
|
||||
$this->assertTrue($workflow->hasTransitionFromStateToState('cooked', 'rotten'));
|
||||
->getTypePlugin()
|
||||
->setTransitionFromStates('rot', ['cooked']);
|
||||
$workflow->save();
|
||||
$this->assertFalse($workflow->getTypePlugin()->hasTransitionFromStateToState('fresh', 'rotten'));
|
||||
$this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('cooked', 'rotten'));
|
||||
|
||||
// Ensure the default configuration does not cause ordering issues.
|
||||
$workflow->addTransition('cook', 'Cook', ['fresh'], 'cooked')->save();
|
||||
$workflow->getTypePlugin()->addTransition('cook', 'Cook', ['fresh'], 'cooked');
|
||||
$workflow->save();
|
||||
$this->assertSame([
|
||||
'cooked',
|
||||
'fresh',
|
||||
'rotten',
|
||||
], array_keys($workflow->get('states')));
|
||||
], array_keys($workflow->getTypePlugin()->getConfiguration()['states']));
|
||||
$this->assertSame([
|
||||
'cook',
|
||||
'rot',
|
||||
], array_keys($workflow->get('transitions')));
|
||||
], array_keys($workflow->getTypePlugin()->getConfiguration()['transitions']));
|
||||
|
||||
// Ensure that transitions can be deleted.
|
||||
$workflow->deleteTransition('rot')->save();
|
||||
$this->assertFalse($workflow->hasTransition('rot'));
|
||||
$workflow->getTypePlugin()->deleteTransition('rot');
|
||||
$workflow->save();
|
||||
$this->assertFalse($workflow->getTypePlugin()->hasTransition('rot'));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,218 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\workflows\Kernel;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Cache\Context\CacheContextsManager;
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\simpletest\UserCreationTrait;
|
||||
use Drupal\workflows\Entity\Workflow;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\workflows\WorkflowAccessControlHandler
|
||||
* @group workflows
|
||||
*/
|
||||
class WorkflowAccessControlHandlerTest extends KernelTestBase {
|
||||
|
||||
use UserCreationTrait;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = [
|
||||
'workflows',
|
||||
'workflow_type_test',
|
||||
'system',
|
||||
'user',
|
||||
];
|
||||
|
||||
/**
|
||||
* The workflow access control handler.
|
||||
*
|
||||
* @var \Drupal\workflows\WorkflowAccessControlHandler
|
||||
*/
|
||||
protected $accessControlHandler;
|
||||
|
||||
/**
|
||||
* A test admin user.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
/**
|
||||
* A non-privileged user.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->installEntitySchema('workflow');
|
||||
$this->installEntitySchema('user');
|
||||
$this->installSchema('system', ['sequences']);
|
||||
|
||||
$this->accessControlHandler = $this->container->get('entity_type.manager')->getAccessControlHandler('workflow');
|
||||
|
||||
// Create and discard user 1, which is special and bypasses all access
|
||||
// checking.
|
||||
$this->createUser([]);
|
||||
$this->user = $this->createUser([]);
|
||||
$this->adminUser = $this->createUser(['administer workflows']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::checkCreateAccess
|
||||
*/
|
||||
public function testCheckCreateAccess() {
|
||||
// A user must have the correct permission to create a workflow.
|
||||
$this->assertEquals(
|
||||
AccessResult::neutral()
|
||||
->addCacheContexts(['user.permissions'])
|
||||
->setReason("The 'administer workflows' permission is required.")
|
||||
->addCacheTags(['workflow_type_plugins']),
|
||||
$this->accessControlHandler->createAccess(NULL, $this->user, [], TRUE)
|
||||
);
|
||||
$this->assertEquals(
|
||||
AccessResult::allowed()
|
||||
->addCacheContexts(['user.permissions'])
|
||||
->addCacheTags(['workflow_type_plugins']),
|
||||
$this->accessControlHandler->createAccess(NULL, $this->adminUser, [], TRUE)
|
||||
);
|
||||
|
||||
// Remove all plugin types and ensure not even the admin user is allowed to
|
||||
// create a workflow.
|
||||
workflow_type_test_set_definitions([]);
|
||||
$this->accessControlHandler->resetCache();
|
||||
$this->assertEquals(
|
||||
AccessResult::neutral()
|
||||
->addCacheContexts(['user.permissions'])
|
||||
->addCacheTags(['workflow_type_plugins']),
|
||||
$this->accessControlHandler->createAccess(NULL, $this->adminUser, [], TRUE)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::checkAccess
|
||||
* @dataProvider checkAccessProvider
|
||||
*/
|
||||
public function testCheckAccess($user, $operation, $result, $states_to_create = []) {
|
||||
$workflow = Workflow::create([
|
||||
'type' => 'workflow_type_test',
|
||||
'id' => 'test_workflow',
|
||||
]);
|
||||
$workflow->save();
|
||||
$workflow_type = $workflow->getTypePlugin();
|
||||
foreach ($states_to_create as $state_id => $is_required) {
|
||||
$workflow_type->addState($state_id, $this->randomString());
|
||||
}
|
||||
\Drupal::state()->set('workflow_type_test.required_states', array_filter($states_to_create));
|
||||
$this->assertEquals($result, $this->accessControlHandler->access($workflow, $operation, $this->{$user}, TRUE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for ::testCheckAccess.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function checkAccessProvider() {
|
||||
$container = new ContainerBuilder();
|
||||
$cache_contexts_manager = $this->prophesize(CacheContextsManager::class);
|
||||
$cache_contexts_manager->assertValidTokens()->willReturn(TRUE);
|
||||
$cache_contexts_manager->reveal();
|
||||
$container->set('cache_contexts_manager', $cache_contexts_manager);
|
||||
\Drupal::setContainer($container);
|
||||
|
||||
return [
|
||||
'Admin view' => [
|
||||
'adminUser',
|
||||
'view',
|
||||
AccessResult::allowed()->addCacheContexts(['user.permissions']),
|
||||
],
|
||||
'Admin update' => [
|
||||
'adminUser',
|
||||
'update',
|
||||
AccessResult::allowed()->addCacheContexts(['user.permissions']),
|
||||
],
|
||||
'Admin delete' => [
|
||||
'adminUser',
|
||||
'delete',
|
||||
AccessResult::allowed()->addCacheContexts(['user.permissions']),
|
||||
],
|
||||
'Admin delete only state' => [
|
||||
'adminUser',
|
||||
'delete-state:foo',
|
||||
AccessResult::neutral()->addCacheTags(['config:workflows.workflow.test_workflow']),
|
||||
['foo' => FALSE],
|
||||
],
|
||||
'Admin delete one of two states' => [
|
||||
'adminUser',
|
||||
'delete-state:foo',
|
||||
AccessResult::allowed()
|
||||
->addCacheTags(['config:workflows.workflow.test_workflow'])
|
||||
->addCacheContexts(['user.permissions']),
|
||||
['foo' => FALSE, 'bar' => FALSE],
|
||||
],
|
||||
'Admin delete required state when there are >1 states' => [
|
||||
'adminUser',
|
||||
'delete-state:foo',
|
||||
AccessResult::allowed()
|
||||
->addCacheTags(['config:workflows.workflow.test_workflow'])
|
||||
->addCacheContexts(['user.permissions']),
|
||||
['foo' => TRUE, 'bar' => FALSE],
|
||||
],
|
||||
'User view' => [
|
||||
'user',
|
||||
'view',
|
||||
AccessResult::neutral()
|
||||
->addCacheContexts(['user.permissions'])
|
||||
->setReason("The 'administer workflows' permission is required."),
|
||||
],
|
||||
'User update' => [
|
||||
'user',
|
||||
'update',
|
||||
AccessResult::neutral()
|
||||
->addCacheContexts(['user.permissions'])
|
||||
->setReason("The 'administer workflows' permission is required."),
|
||||
],
|
||||
'User delete' => [
|
||||
'user',
|
||||
'delete',
|
||||
AccessResult::neutral()
|
||||
->addCacheContexts(['user.permissions'])
|
||||
->setReason("The 'administer workflows' permission is required."),
|
||||
],
|
||||
'User delete only state' => [
|
||||
'user',
|
||||
'delete-state:foo',
|
||||
AccessResult::neutral()->addCacheTags(['config:workflows.workflow.test_workflow']),
|
||||
['foo' => FALSE],
|
||||
],
|
||||
'User delete one of two states' => [
|
||||
'user',
|
||||
'delete-state:foo',
|
||||
AccessResult::neutral()
|
||||
->addCacheTags(['config:workflows.workflow.test_workflow'])
|
||||
->addCacheContexts(['user.permissions'])
|
||||
->setReason("The 'administer workflows' permission is required."),
|
||||
['foo' => FALSE, 'bar' => FALSE],
|
||||
],
|
||||
'User delete required state when there are >1 states' => [
|
||||
'user',
|
||||
'delete-state:foo',
|
||||
AccessResult::neutral()
|
||||
->addCacheTags(['config:workflows.workflow.test_workflow'])
|
||||
->addCacheContexts(['user.permissions'])
|
||||
->setReason("The 'administer workflows' permission is required."),
|
||||
['foo' => TRUE, 'bar' => FALSE],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -33,6 +33,7 @@ class WorkflowDependenciesTest extends KernelTestBase {
|
|||
// \Drupal\workflows\Entity\Workflow::onDependencyRemoval() works as
|
||||
// expected.
|
||||
\Drupal::service('module_installer')->uninstall(['node', 'workflow_third_party_settings_test']);
|
||||
/** @var \Drupal\workflows\WorkflowInterface $workflow */
|
||||
$workflow = \Drupal::entityTypeManager()->getStorage('workflow')->loadUnchanged($workflow->id());
|
||||
$this->assertSame(['workflow_type_test'], $workflow->getDependencies()['module']);
|
||||
}
|
||||
|
|
|
@ -2,14 +2,10 @@
|
|||
|
||||
namespace Drupal\Tests\workflows\Unit;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\workflows\Entity\Workflow;
|
||||
use Drupal\workflow_type_test\Plugin\WorkflowType\TestType;
|
||||
use Drupal\workflows\State;
|
||||
use Drupal\workflows\WorkflowInterface;
|
||||
use Drupal\workflows\WorkflowTypeInterface;
|
||||
use Drupal\workflows\WorkflowTypeManager;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\workflows\State
|
||||
|
@ -18,25 +14,6 @@ use Prophecy\Argument;
|
|||
*/
|
||||
class StateTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Sets up the Workflow Type manager so that workflow entities can be used.
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
// Create a container so that the plugin manager and workflow type can be
|
||||
// mocked.
|
||||
$container = new ContainerBuilder();
|
||||
$workflow_type = $this->prophesize(WorkflowTypeInterface::class);
|
||||
$workflow_type->decorateState(Argument::any())->willReturnArgument(0);
|
||||
$workflow_type->decorateTransition(Argument::any())->willReturnArgument(0);
|
||||
$workflow_type->deleteState(Argument::any())->willReturn(NULL);
|
||||
$workflow_type->deleteTransition(Argument::any())->willReturn(NULL);
|
||||
$workflow_manager = $this->prophesize(WorkflowTypeManager::class);
|
||||
$workflow_manager->createInstance('test_type', Argument::any())->willReturn($workflow_type->reveal());
|
||||
$container->set('plugin.manager.workflows.type', $workflow_manager->reveal());
|
||||
\Drupal::setContainer($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers ::id
|
||||
|
@ -45,7 +22,7 @@ class StateTest extends UnitTestCase {
|
|||
*/
|
||||
public function testGetters() {
|
||||
$state = new State(
|
||||
$this->prophesize(WorkflowInterface::class)->reveal(),
|
||||
$this->prophesize(WorkflowTypeInterface::class)->reveal(),
|
||||
'draft',
|
||||
'Draft',
|
||||
3
|
||||
|
@ -59,16 +36,16 @@ class StateTest extends UnitTestCase {
|
|||
* @covers ::canTransitionTo
|
||||
*/
|
||||
public function testCanTransitionTo() {
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow
|
||||
$workflow_type = new TestType([], '', []);
|
||||
$workflow_type
|
||||
->addState('draft', 'Draft')
|
||||
->addState('published', 'Published')
|
||||
->addTransition('publish', 'Publish', ['draft'], 'published');
|
||||
$state = $workflow->getState('draft');
|
||||
$state = $workflow_type->getState('draft');
|
||||
$this->assertTrue($state->canTransitionTo('published'));
|
||||
$this->assertFalse($state->canTransitionTo('some_other_state'));
|
||||
|
||||
$workflow->deleteTransition('publish');
|
||||
$workflow_type->deleteTransition('publish');
|
||||
$this->assertFalse($state->canTransitionTo('published'));
|
||||
}
|
||||
|
||||
|
@ -76,12 +53,12 @@ class StateTest extends UnitTestCase {
|
|||
* @covers ::getTransitionTo
|
||||
*/
|
||||
public function testGetTransitionTo() {
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow
|
||||
$workflow_type = new TestType([], '', []);
|
||||
$workflow_type
|
||||
->addState('draft', 'Draft')
|
||||
->addState('published', 'Published')
|
||||
->addTransition('publish', 'Publish', ['draft'], 'published');
|
||||
$state = $workflow->getState('draft');
|
||||
$state = $workflow_type->getState('draft');
|
||||
$transition = $state->getTransitionTo('published');
|
||||
$this->assertEquals('Publish', $transition->label());
|
||||
}
|
||||
|
@ -91,9 +68,9 @@ class StateTest extends UnitTestCase {
|
|||
*/
|
||||
public function testGetTransitionToException() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "Can not transition to 'published' state");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->addState('draft', 'Draft');
|
||||
$state = $workflow->getState('draft');
|
||||
$workflow_type = new TestType([], '', []);
|
||||
$workflow_type->addState('draft', 'Draft');
|
||||
$state = $workflow_type->getState('draft');
|
||||
$state->getTransitionTo('published');
|
||||
}
|
||||
|
||||
|
@ -101,15 +78,15 @@ class StateTest extends UnitTestCase {
|
|||
* @covers ::getTransitions
|
||||
*/
|
||||
public function testGetTransitions() {
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow
|
||||
$workflow_type = new TestType([], '', []);
|
||||
$workflow_type
|
||||
->addState('draft', 'Draft')
|
||||
->addState('published', 'Published')
|
||||
->addState('archived', 'Archived')
|
||||
->addTransition('create_new_draft', 'Create new draft', ['draft'], 'draft')
|
||||
->addTransition('publish', 'Publish', ['draft'], 'published')
|
||||
->addTransition('archive', 'Archive', ['published'], 'archived');
|
||||
$state = $workflow->getState('draft');
|
||||
$state = $workflow_type->getState('draft');
|
||||
$transitions = $state->getTransitions();
|
||||
$this->assertCount(2, $transitions);
|
||||
$this->assertEquals('Create new draft', $transitions['create_new_draft']->label());
|
||||
|
@ -120,10 +97,10 @@ class StateTest extends UnitTestCase {
|
|||
* @covers ::labelCallback
|
||||
*/
|
||||
public function testLabelCallback() {
|
||||
$workflow = $this->prophesize(WorkflowInterface::class)->reveal();
|
||||
$workflow_type = $this->prophesize(WorkflowTypeInterface::class)->reveal();
|
||||
$states = [
|
||||
new State($workflow, 'draft', 'Draft'),
|
||||
new State($workflow, 'published', 'Published'),
|
||||
new State($workflow_type, 'draft', 'Draft'),
|
||||
new State($workflow_type, 'published', 'Published'),
|
||||
];
|
||||
$this->assertEquals(['Draft', 'Published'], array_map([State::class, 'labelCallback'], $states));
|
||||
}
|
||||
|
|
|
@ -2,14 +2,10 @@
|
|||
|
||||
namespace Drupal\Tests\workflows\Unit;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\workflows\Entity\Workflow;
|
||||
use Drupal\workflow_type_test\Plugin\WorkflowType\TestType;
|
||||
use Drupal\workflows\Transition;
|
||||
use Drupal\workflows\WorkflowInterface;
|
||||
use Drupal\workflows\WorkflowTypeInterface;
|
||||
use Drupal\workflows\WorkflowTypeManager;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\workflows\Transition
|
||||
|
@ -18,23 +14,6 @@ use Prophecy\Argument;
|
|||
*/
|
||||
class TransitionTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* Sets up the Workflow Type manager so that workflow entities can be used.
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
// Create a container so that the plugin manager and workflow type can be
|
||||
// mocked.
|
||||
$container = new ContainerBuilder();
|
||||
$workflow_type = $this->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('plugin.manager.workflows.type', $workflow_manager->reveal());
|
||||
\Drupal::setContainer($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers ::id
|
||||
|
@ -42,7 +21,7 @@ class TransitionTest extends UnitTestCase {
|
|||
*/
|
||||
public function testGetters() {
|
||||
$state = new Transition(
|
||||
$this->prophesize(WorkflowInterface::class)->reveal(),
|
||||
$this->prophesize(WorkflowTypeInterface::class)->reveal(),
|
||||
'draft_published',
|
||||
'Publish',
|
||||
['draft'],
|
||||
|
@ -57,7 +36,7 @@ class TransitionTest extends UnitTestCase {
|
|||
* @covers ::to
|
||||
*/
|
||||
public function testFromAndTo() {
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow = new TestType([], '', []);
|
||||
$workflow
|
||||
->addState('draft', 'Draft')
|
||||
->addState('published', 'Published')
|
||||
|
|
|
@ -4,15 +4,15 @@ namespace Drupal\Tests\workflows\Unit;
|
|||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Drupal\workflow_type_test\Plugin\WorkflowType\TestType;
|
||||
use Drupal\workflows\Entity\Workflow;
|
||||
use Drupal\workflows\State;
|
||||
use Drupal\workflows\Transition;
|
||||
use Drupal\workflows\WorkflowTypeInterface;
|
||||
use Drupal\workflows\WorkflowTypeManager;
|
||||
use Prophecy\Argument;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\workflows\Entity\Workflow
|
||||
* @coversDefaultClass \Drupal\workflows\Plugin\WorkflowTypeBase
|
||||
*
|
||||
* @group workflows
|
||||
*/
|
||||
|
@ -26,11 +26,8 @@ class WorkflowTest extends UnitTestCase {
|
|||
// Create a container so that the plugin manager and workflow type can be
|
||||
// mocked.
|
||||
$container = new ContainerBuilder();
|
||||
$workflow_type = $this->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());
|
||||
$workflow_manager->createInstance('test_type', Argument::any())->willReturn(new TestType([], '', []));
|
||||
$container->set('plugin.manager.workflows.type', $workflow_manager->reveal());
|
||||
\Drupal::setContainer($container);
|
||||
}
|
||||
|
@ -41,30 +38,30 @@ class WorkflowTest extends UnitTestCase {
|
|||
*/
|
||||
public function testAddAndHasState() {
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$this->assertFalse($workflow->hasState('draft'));
|
||||
$this->assertFalse($workflow->getTypePlugin()->hasState('draft'));
|
||||
|
||||
// By default states are ordered in the order added.
|
||||
$workflow->addState('draft', 'Draft');
|
||||
$this->assertTrue($workflow->hasState('draft'));
|
||||
$this->assertFalse($workflow->hasState('published'));
|
||||
$this->assertEquals(0, $workflow->getState('draft')->weight());
|
||||
$workflow->getTypePlugin()->addState('draft', 'Draft');
|
||||
$this->assertTrue($workflow->getTypePlugin()->hasState('draft'));
|
||||
$this->assertFalse($workflow->getTypePlugin()->hasState('published'));
|
||||
$this->assertEquals(0, $workflow->getTypePlugin()->getState('draft')->weight());
|
||||
// Adding a state does not set up a transition to itself.
|
||||
$this->assertFalse($workflow->hasTransitionFromStateToState('draft', 'draft'));
|
||||
$this->assertFalse($workflow->getTypePlugin()->hasTransitionFromStateToState('draft', 'draft'));
|
||||
|
||||
// New states are added with a new weight 1 more than the current highest
|
||||
// weight.
|
||||
$workflow->addState('published', 'Published');
|
||||
$this->assertEquals(1, $workflow->getState('published')->weight());
|
||||
$workflow->getTypePlugin()->addState('published', 'Published');
|
||||
$this->assertEquals(1, $workflow->getTypePlugin()->getState('published')->weight());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::addState
|
||||
*/
|
||||
public function testAddStateException() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The state 'draft' already exists in workflow 'test'");
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The state 'draft' already exists in workflow.");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->addState('draft', 'Draft');
|
||||
$workflow->addState('draft', 'Draft');
|
||||
$workflow->getTypePlugin()->addState('draft', 'Draft');
|
||||
$workflow->getTypePlugin()->addState('draft', 'Draft');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -73,7 +70,7 @@ class WorkflowTest extends UnitTestCase {
|
|||
public function testAddStateInvalidIdException() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The state ID 'draft-draft' must contain only lowercase letters, numbers, and underscores");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->addState('draft-draft', 'Draft');
|
||||
$workflow->getTypePlugin()->addState('draft-draft', 'Draft');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -83,10 +80,11 @@ class WorkflowTest extends UnitTestCase {
|
|||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
|
||||
// Getting states works when there are none.
|
||||
$this->assertArrayEquals([], array_keys($workflow->getStates()));
|
||||
$this->assertArrayEquals([], array_keys($workflow->getStates([])));
|
||||
$this->assertArrayEquals([], array_keys($workflow->getTypePlugin()->getStates()));
|
||||
$this->assertArrayEquals([], array_keys($workflow->getTypePlugin()->getStates([])));
|
||||
|
||||
$workflow
|
||||
->getTypePlugin()
|
||||
->addState('draft', 'Draft')
|
||||
->addState('published', 'Published')
|
||||
->addState('archived', 'Archived');
|
||||
|
@ -96,36 +94,57 @@ class WorkflowTest extends UnitTestCase {
|
|||
'archived',
|
||||
'draft',
|
||||
'published',
|
||||
], array_keys($workflow->get('states')));
|
||||
], array_keys($workflow->getTypePlugin()->getConfiguration()['states']));
|
||||
|
||||
// Ensure we're returning state objects.
|
||||
$this->assertInstanceOf(State::class, $workflow->getStates()['draft']);
|
||||
$this->assertInstanceOf(State::class, $workflow->getTypePlugin()->getStates()['draft']);
|
||||
|
||||
// Passing in no IDs returns all states.
|
||||
$this->assertArrayEquals(['draft', 'published', 'archived'], array_keys($workflow->getStates()));
|
||||
$this->assertArrayEquals(['draft', 'published', 'archived'], array_keys($workflow->getTypePlugin()->getStates()));
|
||||
|
||||
// The order of states is by weight.
|
||||
$workflow->setStateWeight('published', -1);
|
||||
$this->assertArrayEquals(['published', 'draft', 'archived'], array_keys($workflow->getStates()));
|
||||
$workflow->getTypePlugin()->setStateWeight('published', -1);
|
||||
$this->assertArrayEquals(['published', 'draft', 'archived'], array_keys($workflow->getTypePlugin()->getStates()));
|
||||
|
||||
// The label is also used for sorting if weights are equal.
|
||||
$workflow->setStateWeight('archived', 0);
|
||||
$this->assertArrayEquals(['published', 'archived', 'draft'], array_keys($workflow->getStates()));
|
||||
$workflow->getTypePlugin()->setStateWeight('archived', 0);
|
||||
$this->assertArrayEquals(['published', 'archived', 'draft'], array_keys($workflow->getTypePlugin()->getStates()));
|
||||
|
||||
// You can limit the states returned by passing in states IDs.
|
||||
$this->assertArrayEquals(['archived', 'draft'], array_keys($workflow->getStates(['draft', 'archived'])));
|
||||
$this->assertArrayEquals(['archived', 'draft'], array_keys($workflow->getTypePlugin()->getStates(['draft', 'archived'])));
|
||||
|
||||
// An empty array does not load all states.
|
||||
$this->assertArrayEquals([], array_keys($workflow->getStates([])));
|
||||
$this->assertArrayEquals([], array_keys($workflow->getTypePlugin()->getStates([])));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test numeric IDs when added to a workflow.
|
||||
*/
|
||||
public function testNumericIdSorting() {
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow_type = $workflow->getTypePlugin();
|
||||
|
||||
$workflow_type->addState('1', 'One');
|
||||
$workflow_type->addState('2', 'Two');
|
||||
$workflow_type->addState('3', 'ZZZ');
|
||||
$workflow_type->addState('4', 'AAA');
|
||||
|
||||
$workflow_type->setStateWeight('1', 1);
|
||||
$workflow_type->setStateWeight('2', 2);
|
||||
$workflow_type->setStateWeight('3', 3);
|
||||
$workflow_type->setStateWeight('4', 3);
|
||||
|
||||
// Ensure numeric states are correctly sorted by weight first, label second.
|
||||
$this->assertEquals([1, 2, 4, 3], array_keys($workflow_type->getStates()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getStates
|
||||
*/
|
||||
public function testGetStatesException() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The state 'state_that_does_not_exist' does not exist in workflow 'test'");
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The state 'state_that_does_not_exist' does not exist in workflow.");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->getStates(['state_that_does_not_exist']);
|
||||
$workflow->getTypePlugin()->getStates(['state_that_does_not_exist']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -135,6 +154,7 @@ class WorkflowTest extends UnitTestCase {
|
|||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
// By default states are ordered in the order added.
|
||||
$workflow
|
||||
->getTypePlugin()
|
||||
->addState('draft', 'Draft')
|
||||
->addState('published', 'Published')
|
||||
->addState('archived', 'Archived')
|
||||
|
@ -142,27 +162,27 @@ class WorkflowTest extends UnitTestCase {
|
|||
->addTransition('publish', 'Publish', ['draft'], 'published');
|
||||
|
||||
// Ensure we're returning state objects and they are set up correctly
|
||||
$this->assertInstanceOf(State::class, $workflow->getState('draft'));
|
||||
$this->assertEquals('archived', $workflow->getState('archived')->id());
|
||||
$this->assertEquals('Archived', $workflow->getState('archived')->label());
|
||||
$this->assertInstanceOf(State::class, $workflow->getTypePlugin()->getState('draft'));
|
||||
$this->assertEquals('archived', $workflow->getTypePlugin()->getState('archived')->id());
|
||||
$this->assertEquals('Archived', $workflow->getTypePlugin()->getState('archived')->label());
|
||||
|
||||
$draft = $workflow->getState('draft');
|
||||
$draft = $workflow->getTypePlugin()->getState('draft');
|
||||
$this->assertTrue($draft->canTransitionTo('draft'));
|
||||
$this->assertTrue($draft->canTransitionTo('published'));
|
||||
$this->assertFalse($draft->canTransitionTo('archived'));
|
||||
$this->assertEquals('Publish', $draft->getTransitionTo('published')->label());
|
||||
$this->assertEquals(0, $draft->weight());
|
||||
$this->assertEquals(1, $workflow->getState('published')->weight());
|
||||
$this->assertEquals(2, $workflow->getState('archived')->weight());
|
||||
$this->assertEquals(1, $workflow->getTypePlugin()->getState('published')->weight());
|
||||
$this->assertEquals(2, $workflow->getTypePlugin()->getState('archived')->weight());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getState
|
||||
*/
|
||||
public function testGetStateException() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The state 'state_that_does_not_exist' does not exist in workflow 'test'");
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The state 'state_that_does_not_exist' does not exist in workflow.");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->getState('state_that_does_not_exist');
|
||||
$workflow->getTypePlugin()->getState('state_that_does_not_exist');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -170,19 +190,19 @@ class WorkflowTest extends UnitTestCase {
|
|||
*/
|
||||
public function testSetStateLabel() {
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->addState('draft', 'Draft');
|
||||
$this->assertEquals('Draft', $workflow->getState('draft')->label());
|
||||
$workflow->setStateLabel('draft', 'Unpublished');
|
||||
$this->assertEquals('Unpublished', $workflow->getState('draft')->label());
|
||||
$workflow->getTypePlugin()->addState('draft', 'Draft');
|
||||
$this->assertEquals('Draft', $workflow->getTypePlugin()->getState('draft')->label());
|
||||
$workflow->getTypePlugin()->setStateLabel('draft', 'Unpublished');
|
||||
$this->assertEquals('Unpublished', $workflow->getTypePlugin()->getState('draft')->label());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setStateLabel
|
||||
*/
|
||||
public function testSetStateLabelException() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The state 'draft' does not exist in workflow 'test'");
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The state 'draft' does not exist in workflow.");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->setStateLabel('draft', 'Draft');
|
||||
$workflow->getTypePlugin()->setStateLabel('draft', 'Draft');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -190,71 +210,70 @@ class WorkflowTest extends UnitTestCase {
|
|||
*/
|
||||
public function testSetStateWeight() {
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->addState('draft', 'Draft');
|
||||
$this->assertEquals(0, $workflow->getState('draft')->weight());
|
||||
$workflow->setStateWeight('draft', -10);
|
||||
$this->assertEquals(-10, $workflow->getState('draft')->weight());
|
||||
$workflow->getTypePlugin()->addState('draft', 'Draft');
|
||||
$this->assertEquals(0, $workflow->getTypePlugin()->getState('draft')->weight());
|
||||
$workflow->getTypePlugin()->setStateWeight('draft', -10);
|
||||
$this->assertEquals(-10, $workflow->getTypePlugin()->getState('draft')->weight());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setStateWeight
|
||||
*/
|
||||
public function testSetStateWeightException() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The state 'draft' does not exist in workflow 'test'");
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The state 'draft' does not exist in workflow.");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->setStateWeight('draft', 10);
|
||||
$workflow->getTypePlugin()->setStateWeight('draft', 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setStateWeight
|
||||
*/
|
||||
public function testSetStateWeightNonNumericException() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The weight 'foo' must be numeric for state 'Published'.");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->getTypePlugin()->addState('published', 'Published');
|
||||
$workflow->getTypePlugin()->setStateWeight('published', 'foo');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::deleteState
|
||||
*/
|
||||
public function testDeleteState() {
|
||||
// Create a container so that the plugin manager and workflow type can be
|
||||
// mocked and test that
|
||||
// \Drupal\workflows\WorkflowTypeInterface::deleteState() is called
|
||||
// correctly.
|
||||
$container = new ContainerBuilder();
|
||||
$workflow_type = $this->prophesize(WorkflowTypeInterface::class);
|
||||
$workflow_type->decorateState(Argument::any())->willReturnArgument(0);
|
||||
$workflow_type->decorateTransition(Argument::any())->willReturnArgument(0);
|
||||
$workflow_type->deleteState('draft')->shouldBeCalled();
|
||||
$workflow_type->deleteTransition('create_new_draft')->shouldBeCalled();
|
||||
$workflow_manager = $this->prophesize(WorkflowTypeManager::class);
|
||||
$workflow_manager->createInstance('test_type', Argument::any())->willReturn($workflow_type->reveal());
|
||||
$container->set('plugin.manager.workflows.type', $workflow_manager->reveal());
|
||||
\Drupal::setContainer($container);
|
||||
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow
|
||||
$workflow_type = new TestType([], '', []);
|
||||
$workflow_type
|
||||
->addState('draft', 'Draft')
|
||||
->addState('published', 'Published')
|
||||
->addState('archived', 'Archived')
|
||||
->addTransition('publish', 'Publish', ['draft', 'published'], 'published')
|
||||
->addTransition('create_new_draft', 'Create new draft', ['draft', 'published'], 'draft');
|
||||
$this->assertCount(2, $workflow->getStates());
|
||||
$this->assertCount(2, $workflow->getState('published')->getTransitions());
|
||||
$workflow->deleteState('draft');
|
||||
$this->assertFalse($workflow->hasState('draft'));
|
||||
$this->assertCount(1, $workflow->getStates());
|
||||
$this->assertCount(1, $workflow->getState('published')->getTransitions());
|
||||
->addTransition('create_new_draft', 'Create new draft', ['draft', 'published'], 'draft')
|
||||
->addTransition('archive', 'Archive', ['draft', 'published'], 'archived');
|
||||
$this->assertCount(3, $workflow_type->getStates());
|
||||
$this->assertCount(3, $workflow_type->getState('published')->getTransitions());
|
||||
$workflow_type->deleteState('draft');
|
||||
$this->assertFalse($workflow_type->hasState('draft'));
|
||||
$this->assertCount(2, $workflow_type->getStates());
|
||||
$this->assertCount(2, $workflow_type->getState('published')->getTransitions());
|
||||
$workflow_type->deleteState('published');
|
||||
$this->assertCount(0, $workflow_type->getTransitions());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::deleteState
|
||||
*/
|
||||
public function testDeleteStateException() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The state 'draft' does not exist in workflow 'test'");
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The state 'draft' does not exist in workflow.");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->deleteState('draft');
|
||||
$workflow->getTypePlugin()->deleteState('draft');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::deleteState
|
||||
*/
|
||||
public function testDeleteOnlyStateException() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The state 'draft' can not be deleted from workflow 'test' as it is the only state");
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The state 'draft' can not be deleted from workflow as it is the only state");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->addState('draft', 'Draft');
|
||||
$workflow->deleteState('draft');
|
||||
$workflow->getTypePlugin()->addState('draft', 'Draft');
|
||||
$workflow->getTypePlugin()->deleteState('draft');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -266,29 +285,30 @@ class WorkflowTest extends UnitTestCase {
|
|||
|
||||
// By default states are ordered in the order added.
|
||||
$workflow
|
||||
->getTypePlugin()
|
||||
->addState('draft', 'Draft')
|
||||
->addState('published', 'Published');
|
||||
|
||||
$this->assertFalse($workflow->getState('draft')->canTransitionTo('published'));
|
||||
$workflow->addTransition('publish', 'Publish', ['draft'], 'published');
|
||||
$this->assertTrue($workflow->getState('draft')->canTransitionTo('published'));
|
||||
$this->assertEquals(0, $workflow->getTransition('publish')->weight());
|
||||
$this->assertTrue($workflow->hasTransition('publish'));
|
||||
$this->assertFalse($workflow->hasTransition('draft'));
|
||||
$this->assertFalse($workflow->getTypePlugin()->getState('draft')->canTransitionTo('published'));
|
||||
$workflow->getTypePlugin()->addTransition('publish', 'Publish', ['draft'], 'published');
|
||||
$this->assertTrue($workflow->getTypePlugin()->getState('draft')->canTransitionTo('published'));
|
||||
$this->assertEquals(0, $workflow->getTypePlugin()->getTransition('publish')->weight());
|
||||
$this->assertTrue($workflow->getTypePlugin()->hasTransition('publish'));
|
||||
$this->assertFalse($workflow->getTypePlugin()->hasTransition('draft'));
|
||||
|
||||
$workflow->addTransition('save_publish', 'Save', ['published'], 'published');
|
||||
$this->assertEquals(1, $workflow->getTransition('save_publish')->weight());
|
||||
$workflow->getTypePlugin()->addTransition('save_publish', 'Save', ['published'], 'published');
|
||||
$this->assertEquals(1, $workflow->getTypePlugin()->getTransition('save_publish')->weight());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::addTransition
|
||||
*/
|
||||
public function testAddTransitionDuplicateException() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The transition 'publish' already exists in workflow 'test'");
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The transition 'publish' already exists in workflow.");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->addState('published', 'Published');
|
||||
$workflow->addTransition('publish', 'Publish', ['published'], 'published');
|
||||
$workflow->addTransition('publish', 'Publish', ['published'], 'published');
|
||||
$workflow->getTypePlugin()->addState('published', 'Published');
|
||||
$workflow->getTypePlugin()->addTransition('publish', 'Publish', ['published'], 'published');
|
||||
$workflow->getTypePlugin()->addTransition('publish', 'Publish', ['published'], 'published');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -297,31 +317,32 @@ class WorkflowTest extends UnitTestCase {
|
|||
public function testAddTransitionInvalidIdException() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The transition ID 'publish-publish' must contain only lowercase letters, numbers, and underscores");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->addState('published', 'Published');
|
||||
$workflow->addTransition('publish-publish', 'Publish', ['published'], 'published');
|
||||
$workflow->getTypePlugin()->addState('published', 'Published');
|
||||
$workflow->getTypePlugin()->addTransition('publish-publish', 'Publish', ['published'], 'published');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::addTransition
|
||||
*/
|
||||
public function testAddTransitionMissingFromException() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The state 'draft' does not exist in workflow 'test'");
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The state 'draft' does not exist in workflow.");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->addState('published', 'Published');
|
||||
$workflow->addTransition('publish', 'Publish', ['draft'], 'published');
|
||||
$workflow->getTypePlugin()->addState('published', 'Published');
|
||||
$workflow->getTypePlugin()->addTransition('publish', 'Publish', ['draft'], 'published');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::addTransition
|
||||
*/
|
||||
public function testAddTransitionDuplicateTransitionStatesException() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The 'publish' transition already allows 'draft' to 'published' transitions in workflow 'test'");
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The 'publish' transition already allows 'draft' to 'published' transitions in workflow.");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow
|
||||
->getTypePlugin()
|
||||
->addState('draft', 'Draft')
|
||||
->addState('published', 'Published');
|
||||
$workflow->addTransition('publish', 'Publish', ['draft', 'published'], 'published');
|
||||
$workflow->addTransition('draft_to_published', 'Publish a draft', ['draft'], 'published');
|
||||
$workflow->getTypePlugin()->addTransition('publish', 'Publish', ['draft', 'published'], 'published');
|
||||
$workflow->getTypePlugin()->addTransition('draft_to_published', 'Publish a draft', ['draft'], 'published');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -329,26 +350,26 @@ class WorkflowTest extends UnitTestCase {
|
|||
*/
|
||||
public function testAddTransitionConsistentAfterFromCatch() {
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->addState('published', 'Published');
|
||||
$workflow->getTypePlugin()->addState('published', 'Published');
|
||||
try {
|
||||
$workflow->addTransition('publish', 'Publish', ['draft'], 'published');
|
||||
$workflow->getTypePlugin()->addTransition('publish', 'Publish', ['draft'], 'published');
|
||||
}
|
||||
catch (\InvalidArgumentException $e) {
|
||||
}
|
||||
// Ensure that the workflow is not left in an inconsistent state after an
|
||||
// exception is thrown from Workflow::setTransitionFromStates() whilst
|
||||
// calling Workflow::addTransition().
|
||||
$this->assertFalse($workflow->hasTransition('publish'));
|
||||
$this->assertFalse($workflow->getTypePlugin()->hasTransition('publish'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::addTransition
|
||||
*/
|
||||
public function testAddTransitionMissingToException() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The state 'published' does not exist in workflow 'test'");
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The state 'published' does not exist in workflow.");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->addState('draft', 'Draft');
|
||||
$workflow->addTransition('publish', 'Publish', ['draft'], 'published');
|
||||
$workflow->getTypePlugin()->addState('draft', 'Draft');
|
||||
$workflow->getTypePlugin()->addTransition('publish', 'Publish', ['draft'], 'published');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -359,43 +380,43 @@ class WorkflowTest extends UnitTestCase {
|
|||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
|
||||
// Getting transitions works when there are none.
|
||||
$this->assertArrayEquals([], array_keys($workflow->getTransitions()));
|
||||
$this->assertArrayEquals([], array_keys($workflow->getTransitions([])));
|
||||
$this->assertArrayEquals([], array_keys($workflow->getTypePlugin()->getTransitions()));
|
||||
$this->assertArrayEquals([], array_keys($workflow->getTypePlugin()->getTransitions([])));
|
||||
|
||||
// By default states are ordered in the order added.
|
||||
$workflow
|
||||
->getTypePlugin()
|
||||
->addState('a', 'A')
|
||||
->addState('b', 'B')
|
||||
->addTransition('a_b', 'A to B', ['a'], 'b')
|
||||
->addTransition('a_a', 'A to A', ['a'], 'a');
|
||||
|
||||
// Transitions are stored in alphabetical key order in configuration.
|
||||
$this->assertArrayEquals(['a_a', 'a_b'], array_keys($workflow->get('transitions')));
|
||||
$this->assertArrayEquals(['a_a', 'a_b'], array_keys($workflow->getTypePlugin()->getConfiguration()['transitions']));
|
||||
|
||||
// Ensure we're returning transition objects.
|
||||
$this->assertInstanceOf(Transition::class, $workflow->getTransitions()['a_a']);
|
||||
$this->assertInstanceOf(Transition::class, $workflow->getTypePlugin()->getTransitions()['a_a']);
|
||||
|
||||
// Passing in no IDs returns all transitions.
|
||||
$this->assertArrayEquals(['a_b', 'a_a'], array_keys($workflow->getTransitions()));
|
||||
$this->assertArrayEquals(['a_b', 'a_a'], array_keys($workflow->getTypePlugin()->getTransitions()));
|
||||
|
||||
// The order of states is by weight.
|
||||
$workflow->setTransitionWeight('a_a', -1);
|
||||
$this->assertArrayEquals(['a_a', 'a_b'], array_keys($workflow->getTransitions()));
|
||||
$workflow->getTypePlugin()->setTransitionWeight('a_a', -1);
|
||||
$this->assertArrayEquals(['a_a', 'a_b'], array_keys($workflow->getTypePlugin()->getTransitions()));
|
||||
|
||||
// If all weights are equal it will fallback to labels.
|
||||
$workflow->setTransitionWeight('a_a', 0);
|
||||
$this->assertArrayEquals(['a_a', 'a_b'], array_keys($workflow->getTransitions()));
|
||||
$workflow->setTransitionLabel('a_b', 'A B');
|
||||
$this->assertArrayEquals(['a_b', 'a_a'], array_keys($workflow->getTransitions()));
|
||||
$workflow->getTypePlugin()->setTransitionWeight('a_a', 0);
|
||||
$this->assertArrayEquals(['a_a', 'a_b'], array_keys($workflow->getTypePlugin()->getTransitions()));
|
||||
$workflow->getTypePlugin()->setTransitionLabel('a_b', 'A B');
|
||||
$this->assertArrayEquals(['a_b', 'a_a'], array_keys($workflow->getTypePlugin()->getTransitions()));
|
||||
|
||||
// You can limit the states returned by passing in states IDs.
|
||||
$this->assertArrayEquals(['a_a'], array_keys($workflow->getTransitions(['a_a'])));
|
||||
$this->assertArrayEquals(['a_a'], array_keys($workflow->getTypePlugin()->getTransitions(['a_a'])));
|
||||
|
||||
// An empty array does not load all states.
|
||||
$this->assertArrayEquals([], array_keys($workflow->getTransitions([])));
|
||||
$this->assertArrayEquals([], array_keys($workflow->getTypePlugin()->getTransitions([])));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @covers ::getTransition
|
||||
*/
|
||||
|
@ -403,6 +424,7 @@ class WorkflowTest extends UnitTestCase {
|
|||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
// By default states are ordered in the order added.
|
||||
$workflow
|
||||
->getTypePlugin()
|
||||
->addState('draft', 'Draft')
|
||||
->addState('published', 'Published')
|
||||
->addState('archived', 'Archived')
|
||||
|
@ -410,22 +432,22 @@ class WorkflowTest extends UnitTestCase {
|
|||
->addTransition('publish', 'Publish', ['draft'], 'published');
|
||||
|
||||
// Ensure we're returning state objects and they are set up correctly
|
||||
$this->assertInstanceOf(Transition::class, $workflow->getTransition('create_new_draft'));
|
||||
$this->assertEquals('publish', $workflow->getTransition('publish')->id());
|
||||
$this->assertEquals('Publish', $workflow->getTransition('publish')->label());
|
||||
$this->assertInstanceOf(Transition::class, $workflow->getTypePlugin()->getTransition('create_new_draft'));
|
||||
$this->assertEquals('publish', $workflow->getTypePlugin()->getTransition('publish')->id());
|
||||
$this->assertEquals('Publish', $workflow->getTypePlugin()->getTransition('publish')->label());
|
||||
|
||||
$transition = $workflow->getTransition('publish');
|
||||
$this->assertEquals($workflow->getState('draft'), $transition->from()['draft']);
|
||||
$this->assertEquals($workflow->getState('published'), $transition->to());
|
||||
$transition = $workflow->getTypePlugin()->getTransition('publish');
|
||||
$this->assertEquals($workflow->getTypePlugin()->getState('draft'), $transition->from()['draft']);
|
||||
$this->assertEquals($workflow->getTypePlugin()->getState('published'), $transition->to());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getTransition
|
||||
*/
|
||||
public function testGetTransitionException() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The transition 'transition_that_does_not_exist' does not exist in workflow 'test'");
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The transition 'transition_that_does_not_exist' does not exist in workflow.");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->getTransition('transition_that_does_not_exist');
|
||||
$workflow->getTypePlugin()->getTransition('transition_that_does_not_exist');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -435,6 +457,7 @@ class WorkflowTest extends UnitTestCase {
|
|||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
// By default states are ordered in the order added.
|
||||
$workflow
|
||||
->getTypePlugin()
|
||||
->addState('draft', 'Draft')
|
||||
->addState('published', 'Published')
|
||||
->addState('archived', 'Archived')
|
||||
|
@ -442,15 +465,14 @@ class WorkflowTest extends UnitTestCase {
|
|||
->addTransition('publish', 'Publish', ['draft', 'published'], 'published')
|
||||
->addTransition('archive', 'Archive', ['published'], 'archived');
|
||||
|
||||
$this->assertEquals(['create_new_draft', 'publish'], array_keys($workflow->getTransitionsForState('draft')));
|
||||
$this->assertEquals(['create_new_draft'], array_keys($workflow->getTransitionsForState('draft', 'to')));
|
||||
$this->assertEquals(['publish', 'archive'], array_keys($workflow->getTransitionsForState('published')));
|
||||
$this->assertEquals(['publish'], array_keys($workflow->getTransitionsForState('published', 'to')));
|
||||
$this->assertEquals(['create_new_draft'], array_keys($workflow->getTransitionsForState('archived', 'from')));
|
||||
$this->assertEquals(['archive'], array_keys($workflow->getTransitionsForState('archived', 'to')));
|
||||
$this->assertEquals(['create_new_draft', 'publish'], array_keys($workflow->getTypePlugin()->getTransitionsForState('draft')));
|
||||
$this->assertEquals(['create_new_draft'], array_keys($workflow->getTypePlugin()->getTransitionsForState('draft', 'to')));
|
||||
$this->assertEquals(['publish', 'archive'], array_keys($workflow->getTypePlugin()->getTransitionsForState('published')));
|
||||
$this->assertEquals(['publish'], array_keys($workflow->getTypePlugin()->getTransitionsForState('published', 'to')));
|
||||
$this->assertEquals(['create_new_draft'], array_keys($workflow->getTypePlugin()->getTransitionsForState('archived', 'from')));
|
||||
$this->assertEquals(['archive'], array_keys($workflow->getTypePlugin()->getTransitionsForState('archived', 'to')));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @covers ::getTransitionFromStateToState
|
||||
* @covers ::hasTransitionFromStateToState
|
||||
|
@ -459,6 +481,7 @@ class WorkflowTest extends UnitTestCase {
|
|||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
// By default states are ordered in the order added.
|
||||
$workflow
|
||||
->getTypePlugin()
|
||||
->addState('draft', 'Draft')
|
||||
->addState('published', 'Published')
|
||||
->addState('archived', 'Archived')
|
||||
|
@ -466,9 +489,9 @@ class WorkflowTest extends UnitTestCase {
|
|||
->addTransition('publish', 'Publish', ['draft', 'published'], 'published')
|
||||
->addTransition('archive', 'Archive', ['published'], 'archived');
|
||||
|
||||
$this->assertTrue($workflow->hasTransitionFromStateToState('draft', 'published'));
|
||||
$this->assertFalse($workflow->hasTransitionFromStateToState('archived', 'archived'));
|
||||
$transition = $workflow->getTransitionFromStateToState('published', 'archived');
|
||||
$this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('draft', 'published'));
|
||||
$this->assertFalse($workflow->getTypePlugin()->hasTransitionFromStateToState('archived', 'archived'));
|
||||
$transition = $workflow->getTypePlugin()->getTransitionFromStateToState('published', 'archived');
|
||||
$this->assertEquals('Archive', $transition->label());
|
||||
}
|
||||
|
||||
|
@ -476,10 +499,11 @@ class WorkflowTest extends UnitTestCase {
|
|||
* @covers ::getTransitionFromStateToState
|
||||
*/
|
||||
public function testGetTransitionFromStateToStateException() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The transition from 'archived' to 'archived' does not exist in workflow 'test'");
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The transition from 'archived' to 'archived' does not exist in workflow.");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
// By default states are ordered in the order added.
|
||||
$workflow
|
||||
->getTypePlugin()
|
||||
->addState('draft', 'Draft')
|
||||
->addState('published', 'Published')
|
||||
->addState('archived', 'Archived')
|
||||
|
@ -487,7 +511,7 @@ class WorkflowTest extends UnitTestCase {
|
|||
->addTransition('publish', 'Publish', ['draft', 'published'], 'published')
|
||||
->addTransition('archive', 'Archive', ['published'], 'archived');
|
||||
|
||||
$workflow->getTransitionFromStateToState('archived', 'archived');
|
||||
$workflow->getTypePlugin()->getTransitionFromStateToState('archived', 'archived');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -496,22 +520,23 @@ class WorkflowTest extends UnitTestCase {
|
|||
public function testSetTransitionLabel() {
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow
|
||||
->getTypePlugin()
|
||||
->addState('draft', 'Draft')
|
||||
->addState('published', 'Published')
|
||||
->addTransition('publish', 'Publish', ['draft'], 'published');
|
||||
$this->assertEquals('Publish', $workflow->getTransition('publish')->label());
|
||||
$workflow->setTransitionLabel('publish', 'Publish!');
|
||||
$this->assertEquals('Publish!', $workflow->getTransition('publish')->label());
|
||||
$this->assertEquals('Publish', $workflow->getTypePlugin()->getTransition('publish')->label());
|
||||
$workflow->getTypePlugin()->setTransitionLabel('publish', 'Publish!');
|
||||
$this->assertEquals('Publish!', $workflow->getTypePlugin()->getTransition('publish')->label());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setTransitionLabel
|
||||
*/
|
||||
public function testSetTransitionLabelException() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The transition 'draft-published' does not exist in workflow 'test'");
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The transition 'draft-published' does not exist in workflow.");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->addState('published', 'Published');
|
||||
$workflow->setTransitionLabel('draft-published', 'Publish');
|
||||
$workflow->getTypePlugin()->addState('published', 'Published');
|
||||
$workflow->getTypePlugin()->setTransitionLabel('draft-published', 'Publish');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -520,22 +545,34 @@ class WorkflowTest extends UnitTestCase {
|
|||
public function testSetTransitionWeight() {
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow
|
||||
->getTypePlugin()
|
||||
->addState('draft', 'Draft')
|
||||
->addState('published', 'Published')
|
||||
->addTransition('publish', 'Publish', ['draft'], 'published');
|
||||
$this->assertEquals(0, $workflow->getTransition('publish')->weight());
|
||||
$workflow->setTransitionWeight('publish', 10);
|
||||
$this->assertEquals(10, $workflow->getTransition('publish')->weight());
|
||||
$this->assertEquals(0, $workflow->getTypePlugin()->getTransition('publish')->weight());
|
||||
$workflow->getTypePlugin()->setTransitionWeight('publish', 10);
|
||||
$this->assertEquals(10, $workflow->getTypePlugin()->getTransition('publish')->weight());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setTransitionWeight
|
||||
*/
|
||||
public function testSetTransitionWeightException() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The transition 'draft-published' does not exist in workflow 'test'");
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The transition 'draft-published' does not exist in workflow.");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->addState('published', 'Published');
|
||||
$workflow->setTransitionWeight('draft-published', 10);
|
||||
$workflow->getTypePlugin()->addState('published', 'Published');
|
||||
$workflow->getTypePlugin()->setTransitionWeight('draft-published', 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setTransitionWeight
|
||||
*/
|
||||
public function testSetTransitionWeightNonNumericException() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The weight 'foo' must be numeric for transition 'Publish'.");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->getTypePlugin()->addState('published', 'Published');
|
||||
$workflow->getTypePlugin()->addTransition('publish', 'Publish', [], 'published');
|
||||
$workflow->getTypePlugin()->setTransitionWeight('publish', 'foo');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -544,116 +581,106 @@ class WorkflowTest extends UnitTestCase {
|
|||
public function testSetTransitionFromStates() {
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow
|
||||
->getTypePlugin()
|
||||
->addState('draft', 'Draft')
|
||||
->addState('published', 'Published')
|
||||
->addState('archived', 'Archived')
|
||||
->addTransition('test', 'Test', ['draft'], 'draft');
|
||||
|
||||
$this->assertTrue($workflow->hasTransitionFromStateToState('draft', 'draft'));
|
||||
$this->assertFalse($workflow->hasTransitionFromStateToState('published', 'draft'));
|
||||
$this->assertFalse($workflow->hasTransitionFromStateToState('archived', 'draft'));
|
||||
$workflow->setTransitionFromStates('test', ['draft', 'published', 'archived']);
|
||||
$this->assertTrue($workflow->hasTransitionFromStateToState('draft', 'draft'));
|
||||
$this->assertTrue($workflow->hasTransitionFromStateToState('published', 'draft'));
|
||||
$this->assertTrue($workflow->hasTransitionFromStateToState('archived', 'draft'));
|
||||
$workflow->setTransitionFromStates('test', ['published', 'archived']);
|
||||
$this->assertFalse($workflow->hasTransitionFromStateToState('draft', 'draft'));
|
||||
$this->assertTrue($workflow->hasTransitionFromStateToState('published', 'draft'));
|
||||
$this->assertTrue($workflow->hasTransitionFromStateToState('archived', 'draft'));
|
||||
$this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('draft', 'draft'));
|
||||
$this->assertFalse($workflow->getTypePlugin()->hasTransitionFromStateToState('published', 'draft'));
|
||||
$this->assertFalse($workflow->getTypePlugin()->hasTransitionFromStateToState('archived', 'draft'));
|
||||
$workflow->getTypePlugin()->setTransitionFromStates('test', ['draft', 'published', 'archived']);
|
||||
$this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('draft', 'draft'));
|
||||
$this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('published', 'draft'));
|
||||
$this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('archived', 'draft'));
|
||||
$workflow->getTypePlugin()->setTransitionFromStates('test', ['published', 'archived']);
|
||||
$this->assertFalse($workflow->getTypePlugin()->hasTransitionFromStateToState('draft', 'draft'));
|
||||
$this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('published', 'draft'));
|
||||
$this->assertTrue($workflow->getTypePlugin()->hasTransitionFromStateToState('archived', 'draft'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setTransitionFromStates
|
||||
*/
|
||||
public function testSetTransitionFromStatesMissingTransition() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The transition 'test' does not exist in workflow 'test'");
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The transition 'test' does not exist in workflow.");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow
|
||||
->getTypePlugin()
|
||||
->addState('draft', 'Draft')
|
||||
->addState('published', 'Published')
|
||||
->addState('archived', 'Archived')
|
||||
->addTransition('create_new_draft', 'Create new draft', ['draft'], 'draft');
|
||||
|
||||
$workflow->setTransitionFromStates('test', ['draft', 'published', 'archived']);
|
||||
$workflow->getTypePlugin()->setTransitionFromStates('test', ['draft', 'published', 'archived']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setTransitionFromStates
|
||||
*/
|
||||
public function testSetTransitionFromStatesMissingState() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The state 'published' does not exist in workflow 'test'");
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The state 'published' does not exist in workflow.");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow
|
||||
->getTypePlugin()
|
||||
->addState('draft', 'Draft')
|
||||
->addState('archived', 'Archived')
|
||||
->addTransition('create_new_draft', 'Create new draft', ['draft'], 'draft');
|
||||
|
||||
$workflow->setTransitionFromStates('create_new_draft', ['draft', 'published', 'archived']);
|
||||
$workflow->getTypePlugin()->setTransitionFromStates('create_new_draft', ['draft', 'published', 'archived']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::setTransitionFromStates
|
||||
*/
|
||||
public function testSetTransitionFromStatesAlreadyExists() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The 'create_new_draft' transition already allows 'draft' to 'draft' transitions in workflow 'test'");
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The 'create_new_draft' transition already allows 'draft' to 'draft' transitions in workflow.");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow
|
||||
->getTypePlugin()
|
||||
->addState('draft', 'Draft')
|
||||
->addState('archived', 'Archived')
|
||||
->addState('needs_review', 'Needs Review')
|
||||
->addTransition('create_new_draft', 'Create new draft', ['draft'], 'draft')
|
||||
->addTransition('needs_review', 'Needs review', ['needs_review'], 'draft');
|
||||
|
||||
$workflow->setTransitionFromStates('needs_review', ['draft']);
|
||||
$workflow->getTypePlugin()->setTransitionFromStates('needs_review', ['draft']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::deleteTransition
|
||||
*/
|
||||
public function testDeleteTransition() {
|
||||
// Create a container so that the plugin manager and workflow type can be
|
||||
// mocked and test that
|
||||
// \Drupal\workflows\WorkflowTypeInterface::deleteState() is called
|
||||
// correctly.
|
||||
$container = new ContainerBuilder();
|
||||
$workflow_type = $this->prophesize(WorkflowTypeInterface::class);
|
||||
$workflow_type->decorateState(Argument::any())->willReturnArgument(0);
|
||||
$workflow_type->decorateTransition(Argument::any())->willReturnArgument(0);
|
||||
$workflow_type->deleteTransition('publish')->shouldBeCalled();
|
||||
$workflow_manager = $this->prophesize(WorkflowTypeManager::class);
|
||||
$workflow_manager->createInstance('test_type', Argument::any())->willReturn($workflow_type->reveal());
|
||||
$container->set('plugin.manager.workflows.type', $workflow_manager->reveal());
|
||||
\Drupal::setContainer($container);
|
||||
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow
|
||||
$workflow_type = new TestType([], '', []);
|
||||
$workflow_type
|
||||
->addState('draft', 'Draft')
|
||||
->addState('published', 'Published')
|
||||
->addTransition('create_new_draft', 'Create new draft', ['draft'], 'draft')
|
||||
->addTransition('publish', 'Publish', ['draft'], 'published');
|
||||
$this->assertTrue($workflow->getState('draft')->canTransitionTo('published'));
|
||||
$workflow->deleteTransition('publish');
|
||||
$this->assertFalse($workflow->getState('draft')->canTransitionTo('published'));
|
||||
$this->assertTrue($workflow->getState('draft')->canTransitionTo('draft'));
|
||||
$this->assertTrue($workflow_type->getState('draft')->canTransitionTo('published'));
|
||||
$workflow_type->deleteTransition('publish');
|
||||
$this->assertFalse($workflow_type->getState('draft')->canTransitionTo('published'));
|
||||
$this->assertTrue($workflow_type->getState('draft')->canTransitionTo('draft'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::deleteTransition
|
||||
*/
|
||||
public function testDeleteTransitionException() {
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The transition 'draft-published' does not exist in workflow 'test'");
|
||||
$this->setExpectedException(\InvalidArgumentException::class, "The transition 'draft-published' does not exist in workflow.");
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$workflow->addState('published', 'Published');
|
||||
$workflow->deleteTransition('draft-published');
|
||||
$workflow->getTypePlugin()->addState('published', 'Published');
|
||||
$workflow->getTypePlugin()->deleteTransition('draft-published');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::status
|
||||
* @covers \Drupal\workflows\Entity\Workflow::status
|
||||
*/
|
||||
public function testStatus() {
|
||||
$workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
|
||||
$this->assertFalse($workflow->status());
|
||||
$workflow->addState('published', 'Published');
|
||||
$workflow->getTypePlugin()->addState('published', 'Published');
|
||||
$this->assertTrue($workflow->status());
|
||||
}
|
||||
|
||||
|
|
Reference in a new issue