Issue #2830581 by alexpott, Sam152, timmillwood, xjm: Fix ContentModeration workflow type to calculate correct dependencies
parent
22d62194b3
commit
758f01b6f6
|
@ -3,13 +3,16 @@
|
|||
namespace Drupal\content_moderation\Plugin\WorkflowType;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\content_moderation\ContentModerationState;
|
||||
use Drupal\workflows\Plugin\WorkflowTypeBase;
|
||||
use Drupal\workflows\StateInterface;
|
||||
use Drupal\workflows\WorkflowInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Attaches workflows to content entity types and their bundles.
|
||||
|
@ -23,10 +26,37 @@ use Drupal\workflows\WorkflowInterface;
|
|||
* },
|
||||
* )
|
||||
*/
|
||||
class ContentModeration extends WorkflowTypeBase {
|
||||
class ContentModeration extends WorkflowTypeBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* Creates an instance of the ContentModeration WorkflowType plugin.
|
||||
*/
|
||||
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('entity_type.manager')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -193,11 +223,59 @@ class ContentModeration extends WorkflowTypeBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function calculateDependencies() {
|
||||
// @todo : Implement calculateDependencies() method.
|
||||
return [];
|
||||
$dependencies = parent::calculateDependencies();
|
||||
foreach ($this->getEntityTypes() as $entity_type_id) {
|
||||
$entity_definition = $this->entityTypeManager->getDefinition($entity_type_id);
|
||||
foreach ($this->getBundlesForEntityType($entity_type_id) as $bundle) {
|
||||
$dependency = $entity_definition->getBundleConfigDependency($bundle);
|
||||
$dependencies[$dependency['type']][] = $dependency['name'];
|
||||
}
|
||||
}
|
||||
return $dependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function onDependencyRemoval(array $dependencies) {
|
||||
$changed = parent::onDependencyRemoval($dependencies);
|
||||
|
||||
// When bundle config entities are removed, ensure they are cleaned up from
|
||||
// the workflow.
|
||||
foreach ($dependencies['config'] as $removed_config) {
|
||||
if ($entity_type_id = $removed_config->getEntityType()->getBundleOf()) {
|
||||
$bundle_id = $removed_config->id();
|
||||
$this->removeEntityTypeAndBundle($entity_type_id, $bundle_id);
|
||||
$changed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// When modules that provide entity types are removed, ensure they are also
|
||||
// removed from the workflow.
|
||||
if (!empty($dependencies['module'])) {
|
||||
// Gather all entity definitions provided by the dependent modules which
|
||||
// are being removed.
|
||||
$module_entity_definitions = [];
|
||||
foreach ($this->entityTypeManager->getDefinitions() as $entity_definition) {
|
||||
if (in_array($entity_definition->getProvider(), $dependencies['module'])) {
|
||||
$module_entity_definitions[] = $entity_definition;
|
||||
}
|
||||
}
|
||||
|
||||
// For all entity types provided by the uninstalled modules, remove any
|
||||
// configuration for those types.
|
||||
foreach ($module_entity_definitions as $module_entity_definition) {
|
||||
foreach ($this->getBundlesForEntityType($module_entity_definition->id()) as $bundle) {
|
||||
$this->removeEntityTypeAndBundle($module_entity_definition->id(), $bundle);
|
||||
$changed = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $changed;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -387,6 +387,48 @@ class ContentModerationStateTest extends KernelTestBase {
|
|||
\Drupal::entityDefinitionUpdateManager()->applyUpdates();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the dependencies of the workflow when using content moderation.
|
||||
*/
|
||||
public function testWorkflowDependencies() {
|
||||
$node_type = NodeType::create([
|
||||
'type' => 'example',
|
||||
]);
|
||||
$node_type->save();
|
||||
|
||||
$workflow = Workflow::load('editorial');
|
||||
// Test both a config and non-config based bundle and entity type.
|
||||
$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'example');
|
||||
$workflow->getTypePlugin()->addEntityTypeAndBundle('entity_test_rev', 'entity_test_rev');
|
||||
$workflow->save();
|
||||
|
||||
$this->assertEquals([
|
||||
'module' => [
|
||||
'content_moderation',
|
||||
'entity_test',
|
||||
],
|
||||
'config' => [
|
||||
'node.type.example',
|
||||
],
|
||||
], $workflow->getDependencies());
|
||||
|
||||
$entity_types = $workflow->getTypePlugin()->getEntityTypes();
|
||||
$this->assertTrue(in_array('node', $entity_types));
|
||||
$this->assertTrue(in_array('entity_test_rev', $entity_types));
|
||||
|
||||
// Delete the node type and ensure it is removed from the workflow.
|
||||
$node_type->delete();
|
||||
$workflow = Workflow::load('editorial');
|
||||
$entity_types = $workflow->getTypePlugin()->getEntityTypes();
|
||||
$this->assertFalse(in_array('node', $entity_types));
|
||||
|
||||
// Uninstall entity test and ensure it's removed from the workflow.
|
||||
$this->container->get('config.manager')->uninstall('module', 'entity_test');
|
||||
$workflow = Workflow::load('editorial');
|
||||
$entity_types = $workflow->getTypePlugin()->getEntityTypes();
|
||||
$this->assertFalse(in_array('entity_test_rev', $entity_types));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads the entity after clearing the static cache.
|
||||
*
|
||||
|
|
|
@ -520,4 +520,14 @@ class Workflow extends ConfigEntityBase implements WorkflowInterface, EntityWith
|
|||
return !empty($this->status) && !empty($this->states);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function onDependencyRemoval(array $dependencies) {
|
||||
$changed = $this->getTypePlugin()->onDependencyRemoval($dependencies);
|
||||
// Ensure the parent method is called in order to process dependencies that
|
||||
// affect third party settings.
|
||||
return parent::onDependencyRemoval($dependencies) || $changed;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -138,4 +138,11 @@ abstract class WorkflowTypeBase extends PluginBase implements WorkflowTypeInterf
|
|||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function onDependencyRemoval(array $dependencies) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ interface WorkflowTypeInterface extends PluginInspectionInterface, DerivativeIns
|
|||
* @param \Drupal\workflows\WorkflowInterface $workflow
|
||||
* The workflow to initialize.
|
||||
*
|
||||
* @return \Drupal\workflows\WorkflowInterface $workflow
|
||||
* @return \Drupal\workflows\WorkflowInterface
|
||||
* The initialized workflow.
|
||||
*
|
||||
* @see \Drupal\workflows\Form\WorkflowAddForm::save()
|
||||
|
@ -62,7 +62,7 @@ interface WorkflowTypeInterface extends PluginInspectionInterface, DerivativeIns
|
|||
* @param \Drupal\workflows\StateInterface $state
|
||||
* The state object to decorate.
|
||||
*
|
||||
* @return \Drupal\workflows\StateInterface $state
|
||||
* @return \Drupal\workflows\StateInterface
|
||||
* The decorated state object.
|
||||
*/
|
||||
public function decorateState(StateInterface $state);
|
||||
|
@ -80,7 +80,7 @@ interface WorkflowTypeInterface extends PluginInspectionInterface, DerivativeIns
|
|||
* @param \Drupal\workflows\TransitionInterface $transition
|
||||
* The transition object to decorate.
|
||||
*
|
||||
* @return \Drupal\workflows\TransitionInterface $transition
|
||||
* @return \Drupal\workflows\TransitionInterface
|
||||
* The decorated transition object.
|
||||
*/
|
||||
public function decorateTransition(TransitionInterface $transition);
|
||||
|
@ -144,4 +144,19 @@ interface WorkflowTypeInterface extends PluginInspectionInterface, DerivativeIns
|
|||
*/
|
||||
public function getRequiredStates();
|
||||
|
||||
/**
|
||||
* Informs the plugin that a dependency of the workflow will be deleted.
|
||||
*
|
||||
* @param array $dependencies
|
||||
* An array of dependencies that will be deleted keyed by dependency type.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the workflow settings have been changed, FALSE if not.
|
||||
*
|
||||
* @see \Drupal\Core\Config\ConfigEntityInterface::onDependencyRemoval()
|
||||
*
|
||||
* @todo https://www.drupal.org/node/2579743 make part of a generic interface.
|
||||
*/
|
||||
public function onDependencyRemoval(array $dependencies);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
workflows.workflow.*.third_party.workflow_third_party_settings_test:
|
||||
type: ignore
|
|
@ -0,0 +1,8 @@
|
|||
name: 'Workflow Third Party Settings Test'
|
||||
type: module
|
||||
description: 'Allows third party settings on workflows to be tested.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
core: 8.x
|
||||
dependencies:
|
||||
- workflows
|
|
@ -79,4 +79,13 @@ class ComplexTestType extends WorkflowTypeBase {
|
|||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function onDependencyRemoval(array $dependencies) {
|
||||
// Always return TRUE to allow the logic in
|
||||
// \Drupal\workflows\Entity\Workflow::onDependencyRemoval() to be tested.
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\workflows\Kernel;
|
||||
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\workflows\Entity\Workflow;
|
||||
|
||||
/**
|
||||
* Tests configuration dependencies in workflows.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\workflows\Entity\Workflow
|
||||
*
|
||||
* @group workflows
|
||||
*/
|
||||
class WorkflowDependenciesTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['system', 'workflows', 'workflow_type_test', 'workflow_third_party_settings_test'];
|
||||
|
||||
/**
|
||||
* Tests \Drupal\workflows\Entity\Workflow::onDependencyRemoval().
|
||||
*/
|
||||
public function testOnDependencyRemoval() {
|
||||
// Create a workflow that has a dependency on a third party setting.
|
||||
$workflow = Workflow::create(['id' => 'test3', 'type' => 'workflow_type_complex_test']);
|
||||
$workflow->setThirdPartySetting('workflow_third_party_settings_test', 'key', 'value');
|
||||
$workflow->save();
|
||||
$this->assertSame(['workflow_third_party_settings_test', 'workflow_type_test'], $workflow->getDependencies()['module']);
|
||||
|
||||
// Uninstall workflow_third_party_settings_test to ensure
|
||||
// \Drupal\workflows\Entity\Workflow::onDependencyRemoval() works as
|
||||
// expected.
|
||||
\Drupal::service('module_installer')->uninstall(['node', 'workflow_third_party_settings_test']);
|
||||
$workflow = \Drupal::entityTypeManager()->getStorage('workflow')->loadUnchanged($workflow->id());
|
||||
$this->assertSame(['workflow_type_test'], $workflow->getDependencies()['module']);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue