diff --git a/core/modules/content_moderation/src/Plugin/WorkflowType/ContentModeration.php b/core/modules/content_moderation/src/Plugin/WorkflowType/ContentModeration.php index 9f5c9a2..e7daf25 100644 --- a/core/modules/content_moderation/src/Plugin/WorkflowType/ContentModeration.php +++ b/core/modules/content_moderation/src/Plugin/WorkflowType/ContentModeration.php @@ -10,6 +10,7 @@ use Drupal\Core\Session\AccountInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\content_moderation\ContentModerationState; +use Drupal\workflows\Plugin\ConfigurableWorkflowTypeBase; use Drupal\workflows\Plugin\WorkflowTypeBase; use Drupal\workflows\StateInterface; use Drupal\workflows\WorkflowInterface; @@ -23,7 +24,7 @@ * label = @Translation("Content moderation"), * ) */ -class ContentModeration extends WorkflowTypeBase implements ContainerFactoryPluginInterface { +class ContentModeration extends ConfigurableWorkflowTypeBase implements ContainerFactoryPluginInterface { use StringTranslationTrait; @@ -168,8 +169,7 @@ public function appliesToEntityTypeAndBundle($entity_type_id, $bundle_id) { * The bundle ID to remove. */ public function removeEntityTypeAndBundle($entity_type_id, $bundle_id) { - $key = array_search($bundle_id, $this->configuration['entity_types'][$entity_type_id], TRUE); - if ($key !== FALSE) { + if (isset($this->configuration['entity_types'][$entity_type_id]) && $key = array_search($bundle_id, $this->configuration['entity_types'][$entity_type_id], TRUE)) { unset($this->configuration['entity_types'][$entity_type_id][$key]); if (empty($this->configuration['entity_types'][$entity_type_id])) { unset($this->configuration['entity_types'][$entity_type_id]); @@ -217,7 +217,7 @@ public function calculateDependencies() { /** * {@inheritdoc} */ - public function editForm(WorkflowInterface $workflow) { + public function buildConfigurationForm(array $form, FormStateInterface $form_state) { $form['attachments'] = [ '#type' => 'details', '#title' => $this->t('Select types to use this workflow'), @@ -257,22 +257,20 @@ public function editForm(WorkflowInterface $workflow) { } } } - return $form; } /** * {@inheritdoc} */ - public function editFormSave(WorkflowInterface &$workflow, array $form, FormStateInterface $formState) { - $type_plugin = $workflow->getTypePlugin(); - foreach ($formState->getValues()['attachments'] as $entity_type_id => $bundle_ids) { + public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { + foreach ($form_state->getValue('attachments') as $entity_type_id => $bundle_ids) { foreach ($bundle_ids as $bundle_id => $checked) { if ($checked) { - $type_plugin->addEntityTypeAndBundle($entity_type_id, $bundle_id); + $this->addEntityTypeAndBundle($entity_type_id, $bundle_id); } else { - $type_plugin->removeEntityTypeAndBundle($entity_type_id, $bundle_id); + $this->removeEntityTypeAndBundle($entity_type_id, $bundle_id); } } } diff --git a/core/modules/content_moderation/src/Tests/ModerationStateBlockTest.php b/core/modules/content_moderation/src/Tests/ModerationStateBlockTest.php index faf6934..e3817ad 100644 --- a/core/modules/content_moderation/src/Tests/ModerationStateBlockTest.php +++ b/core/modules/content_moderation/src/Tests/ModerationStateBlockTest.php @@ -52,7 +52,7 @@ public function testCustomBlockModeration() { $this->drupalLogin($this->rootUser); // Enable moderation for custom blocks. - $edit['attachments[block_content][basic]'] = TRUE; + $edit['type_settings[attachments][block_content][basic]'] = TRUE; $this->drupalPostForm('admin/config/workflow/workflows/manage/editorial', $edit, t('Save')); $this->assertText(t('Saved the Editorial workflow Workflow.')); diff --git a/core/modules/content_moderation/src/Tests/ModerationStateNodeTest.php b/core/modules/content_moderation/src/Tests/ModerationStateNodeTest.php index fe033bc..668da5a 100644 --- a/core/modules/content_moderation/src/Tests/ModerationStateNodeTest.php +++ b/core/modules/content_moderation/src/Tests/ModerationStateNodeTest.php @@ -53,7 +53,7 @@ public function testCreatingContent() { $this->assertText(t('The Moderated content moderated content has been deleted.')); // Disable content moderation. - $edit['attachments[node][moderated_content]'] = FALSE; + $edit['type_settings[attachments][node][moderated_content]'] = FALSE; $this->drupalPostForm('admin/config/workflow/workflows/manage/editorial', $edit, t('Save'));; // Ensure the parent environment is up-to-date. // @see content_moderation_workflow_insert() diff --git a/core/modules/content_moderation/src/Tests/ModerationStateTestBase.php b/core/modules/content_moderation/src/Tests/ModerationStateTestBase.php index 0765fb6..52dc4e7 100644 --- a/core/modules/content_moderation/src/Tests/ModerationStateTestBase.php +++ b/core/modules/content_moderation/src/Tests/ModerationStateTestBase.php @@ -116,7 +116,7 @@ protected function createContentTypeFromUi($content_type_name, $content_type_id, public function enableModerationThroughUi($content_type_id, $workflow_id = 'editorial') { $this->drupalGet('/admin/config/workflow/workflows'); $this->assertLinkByHref('admin/config/workflow/workflows/manage/' . $workflow_id); - $edit['attachments[node][' . $content_type_id . ']'] = TRUE; + $edit['type_settings[attachments][node][' . $content_type_id . ']'] = TRUE; $this->drupalPostForm('admin/config/workflow/workflows/manage/' . $workflow_id, $edit, t('Save')); // Ensure the parent environment is up-to-date. // @see content_moderation_workflow_insert() diff --git a/core/modules/workflows/src/ConfigurableWorkflowTypeInterface.php b/core/modules/workflows/src/ConfigurableWorkflowTypeInterface.php new file mode 100644 index 0000000..57585b2 --- /dev/null +++ b/core/modules/workflows/src/ConfigurableWorkflowTypeInterface.php @@ -0,0 +1,16 @@ + $workflow->toLink($this->t('Add a new transition'), 'add-transition-form')->toString(), ]; - $form += $workflow->getTypePlugin()->editForm($workflow); + $is_configurable = $workflow->getTypePlugin() instanceof ConfigurableWorkflowTypeInterface; + $form_state->set('is_configurable', $is_configurable); + + if ($is_configurable) { + $form['type_settings'] = [ + '#tree' => TRUE, + ]; + $sub_form_state = SubformState::createForSubform($form['type_settings'], $form, $form_state); + $form['type_settings'] += $workflow->getTypePlugin()->buildConfigurationForm($form['type_settings'], $sub_form_state); + } return $form; } @@ -187,11 +198,27 @@ public function form(array $form, FormStateInterface $form_state) { /** * {@inheritdoc} */ + public function validateForm(array &$form, FormStateInterface $form_state) { + /* @var \Drupal\workflows\WorkflowInterface $workflow */ + $workflow = $this->entity; + if ($form_state->get('is_configurable')) { + $sub_form_state = SubformState::createForSubform($form['type_settings'], $form, $form_state); + $workflow->getTypePlugin()->validateConfigurationForm($form['type_settings'], $sub_form_state); + } + } + + /** + * {@inheritdoc} + */ public function save(array $form, FormStateInterface $form_state) { /* @var \Drupal\workflows\WorkflowInterface $workflow */ $workflow = $this->entity; - $workflow->getTypePlugin()->editFormSave($workflow, $form, $form_state); + if ($form_state->get('is_configurable')) { + $sub_form_state = SubformState::createForSubform($form['type_settings'], $form, $form_state); + $workflow->getTypePlugin()->submitConfigurationForm($form['type_settings'], $sub_form_state); + } $workflow->save(); + drupal_set_message($this->t('Saved the %label Workflow.', ['%label' => $workflow->label()])); $form_state->setRedirectUrl($workflow->toUrl('collection')); } diff --git a/core/modules/workflows/src/Plugin/ConfigurableWorkflowTypeBase.php b/core/modules/workflows/src/Plugin/ConfigurableWorkflowTypeBase.php new file mode 100644 index 0000000..4dec6ce --- /dev/null +++ b/core/modules/workflows/src/Plugin/ConfigurableWorkflowTypeBase.php @@ -0,0 +1,30 @@ + '', + ]; + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, FormStateInterface $form_state) { + $form['example_setting'] = [ + '#type' => 'textfield', + '#title' => $this->t('Example global workflow setting'), + '#description' => $this->t('Extra information added to the workflow'), + '#default_value' => $this->configuration['example_setting'], + ]; + return $form; + } + + /** + * {@inheritdoc} + */ + public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { + $this->configuration['example_setting'] = $form_state->getValue('example_setting'); + } + } diff --git a/core/modules/workflows/tests/src/Functional/WorkflowUiTest.php b/core/modules/workflows/tests/src/Functional/WorkflowUiTest.php index ed5eb6f..5151056 100644 --- a/core/modules/workflows/tests/src/Functional/WorkflowUiTest.php +++ b/core/modules/workflows/tests/src/Functional/WorkflowUiTest.php @@ -213,6 +213,28 @@ public function testWorkflowCreation() { } /** + * Test the workflow configuration form. + */ + public function testWorkflowConfigurationForm() { + $workflow = Workflow::create(['id' => 'test', 'type' => 'workflow_type_complex_test', 'label' => 'Test']); + $workflow + ->addState('published', 'Published') + ->addTransition('publish', 'Publish', ['published'], 'published') + ->save(); + + $this->drupalLogin($this->createUser(['administer workflows'])); + + // 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'); + $workflow = $workflow_storage->loadUnchanged('test'); + $this->assertEquals('Extra global settings', $workflow->getTypePlugin()->getConfiguration()['example_setting']); + } + + /** * Tests that workflow types can add form fields to states and transitions. */ public function testWorkflowDecoration() {