[Workflow] Introduce concept of SupprtStrategyInterface to allow other support checks than class instance
This commit is contained in:
parent
5921530a1a
commit
184301206f
@ -280,7 +280,6 @@ class Configuration implements ConfigurationInterface
|
|||||||
->end()
|
->end()
|
||||||
->end()
|
->end()
|
||||||
->arrayNode('supports')
|
->arrayNode('supports')
|
||||||
->isRequired()
|
|
||||||
->beforeNormalization()
|
->beforeNormalization()
|
||||||
->ifString()
|
->ifString()
|
||||||
->then(function ($v) { return array($v); })
|
->then(function ($v) { return array($v); })
|
||||||
@ -293,6 +292,9 @@ class Configuration implements ConfigurationInterface
|
|||||||
->end()
|
->end()
|
||||||
->end()
|
->end()
|
||||||
->end()
|
->end()
|
||||||
|
->scalarNode('support_strategy')
|
||||||
|
->cannotBeEmpty()
|
||||||
|
->end()
|
||||||
->scalarNode('initial_place')->defaultNull()->end()
|
->scalarNode('initial_place')->defaultNull()->end()
|
||||||
->arrayNode('places')
|
->arrayNode('places')
|
||||||
->isRequired()
|
->isRequired()
|
||||||
@ -353,6 +355,10 @@ class Configuration implements ConfigurationInterface
|
|||||||
->end()
|
->end()
|
||||||
->end()
|
->end()
|
||||||
->end()
|
->end()
|
||||||
|
->validate()
|
||||||
|
->ifTrue(function ($v) { return isset($v['supports']) && isset($v['support_strategy']); })
|
||||||
|
->thenInvalid('"supports" and "support_strategy" cannot be used together.')
|
||||||
|
->end()
|
||||||
->end()
|
->end()
|
||||||
->end()
|
->end()
|
||||||
->end()
|
->end()
|
||||||
|
@ -36,6 +36,7 @@ use Symfony\Component\Serializer\Normalizer\DataUriNormalizer;
|
|||||||
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
|
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
|
||||||
use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer;
|
use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer;
|
||||||
use Symfony\Component\Workflow;
|
use Symfony\Component\Workflow;
|
||||||
|
use Symfony\Component\Workflow\SupportStrategy\ClassInstanceSupportStrategy;
|
||||||
use Symfony\Component\Yaml\Yaml;
|
use Symfony\Component\Yaml\Yaml;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -475,8 +476,14 @@ class FrameworkExtension extends Extension
|
|||||||
$container->setDefinition(sprintf('%s.definition', $workflowId), $definitionDefinition);
|
$container->setDefinition(sprintf('%s.definition', $workflowId), $definitionDefinition);
|
||||||
|
|
||||||
// Add workflow to Registry
|
// Add workflow to Registry
|
||||||
foreach ($workflow['supports'] as $supportedClass) {
|
if (isset($workflow['supports'])) {
|
||||||
$registryDefinition->addMethodCall('add', array(new Reference($workflowId), $supportedClass));
|
foreach ($workflow['supports'] as $supportedClassName) {
|
||||||
|
$strategyDefinition = new Definition(ClassInstanceSupportStrategy::class, array($supportedClassName));
|
||||||
|
$strategyDefinition->setPublic(false);
|
||||||
|
$registryDefinition->addMethodCall('add', array(new Reference($workflowId), $strategyDefinition));
|
||||||
|
}
|
||||||
|
} elseif (isset($workflow['support_strategy'])) {
|
||||||
|
$registryDefinition->addMethodCall('add', array(new Reference($workflowId), new Reference($workflow['support_strategy'])));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,11 +168,16 @@ abstract class FrameworkExtensionTest extends TestCase
|
|||||||
$this->assertCount(9, $stateMachineDefinition->getArgument(1));
|
$this->assertCount(9, $stateMachineDefinition->getArgument(1));
|
||||||
$this->assertSame('start', $stateMachineDefinition->getArgument(2));
|
$this->assertSame('start', $stateMachineDefinition->getArgument(2));
|
||||||
|
|
||||||
|
|
||||||
$serviceMarkingStoreWorkflowDefinition = $container->getDefinition('workflow.service_marking_store_workflow');
|
$serviceMarkingStoreWorkflowDefinition = $container->getDefinition('workflow.service_marking_store_workflow');
|
||||||
/** @var Reference $markingStoreRef */
|
/** @var Reference $markingStoreRef */
|
||||||
$markingStoreRef = $serviceMarkingStoreWorkflowDefinition->getArgument(1);
|
$markingStoreRef = $serviceMarkingStoreWorkflowDefinition->getArgument(1);
|
||||||
$this->assertInstanceOf(Reference::class, $markingStoreRef);
|
$this->assertInstanceOf(Reference::class, $markingStoreRef);
|
||||||
$this->assertEquals('workflow_service', (string) $markingStoreRef);
|
$this->assertEquals('workflow_service', (string) $markingStoreRef);
|
||||||
|
|
||||||
|
$this->assertTrue($container->hasDefinition('workflow.registry', 'Workflow registry is registered as a service'));
|
||||||
|
$registryDefinition = $container->getDefinition('workflow.registry');
|
||||||
|
$this->assertGreaterThan(0, count($registryDefinition->getMethodCalls()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
namespace Symfony\Component\Workflow;
|
namespace Symfony\Component\Workflow;
|
||||||
|
|
||||||
use Symfony\Component\Workflow\Exception\InvalidArgumentException;
|
use Symfony\Component\Workflow\Exception\InvalidArgumentException;
|
||||||
|
use Symfony\Component\Workflow\SupportStrategy\SupportStrategyInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
@ -22,12 +23,16 @@ class Registry
|
|||||||
private $workflows = array();
|
private $workflows = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Workflow $workflow
|
* @param Workflow $workflow
|
||||||
* @param string $className
|
* @param string|SupportStrategyInterface $supportStrategy
|
||||||
*/
|
*/
|
||||||
public function add(Workflow $workflow, $className)
|
public function add(Workflow $workflow, $supportStrategy)
|
||||||
{
|
{
|
||||||
$this->workflows[] = array($workflow, $className);
|
if (!$supportStrategy instanceof SupportStrategyInterface) {
|
||||||
|
@trigger_error('Support of class name string was deprecated after version 3.2 and won\'t work anymore in 4.0.', E_USER_DEPRECATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->workflows[] = array($workflow, $supportStrategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,8 +45,8 @@ class Registry
|
|||||||
{
|
{
|
||||||
$matched = null;
|
$matched = null;
|
||||||
|
|
||||||
foreach ($this->workflows as list($workflow, $className)) {
|
foreach ($this->workflows as list($workflow, $supportStrategy)) {
|
||||||
if ($this->supports($workflow, $className, $subject, $workflowName)) {
|
if ($this->supports($workflow, $supportStrategy, $subject, $workflowName)) {
|
||||||
if ($matched) {
|
if ($matched) {
|
||||||
throw new InvalidArgumentException('At least two workflows match this subject. Set a different name on each and use the second (name) argument of this method.');
|
throw new InvalidArgumentException('At least two workflows match this subject. Set a different name on each and use the second (name) argument of this method.');
|
||||||
}
|
}
|
||||||
@ -56,16 +61,19 @@ class Registry
|
|||||||
return $matched;
|
return $matched;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function supports(Workflow $workflow, $className, $subject, $name)
|
private function supports(Workflow $workflow, $supportStrategy, $subject, $workflowName)
|
||||||
{
|
{
|
||||||
if (!$subject instanceof $className) {
|
if (is_string($supportStrategy) && !$subject instanceof $supportStrategy) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($supportStrategy instanceof SupportStrategyInterface && !$supportStrategy->supports($workflow, $subject)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null === $name) {
|
if (null === $workflowName) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $name === $workflow->getName();
|
return $workflowName === $workflow->getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Workflow\SupportStrategy;
|
||||||
|
|
||||||
|
use Symfony\Component\Workflow\Workflow;
|
||||||
|
|
||||||
|
class ClassInstanceSupportStrategy implements SupportStrategyInterface
|
||||||
|
{
|
||||||
|
private $className;
|
||||||
|
|
||||||
|
public function __construct($className)
|
||||||
|
{
|
||||||
|
$this->className = $className;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function supports(Workflow $workflow, $subject)
|
||||||
|
{
|
||||||
|
return $subject instanceof $this->className;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Workflow\SupportStrategy;
|
||||||
|
|
||||||
|
use Symfony\Component\Workflow\Workflow;
|
||||||
|
|
||||||
|
interface SupportStrategyInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param Workflow $workflow
|
||||||
|
* @param object $subject
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function supports(Workflow $workflow, $subject);
|
||||||
|
}
|
@ -6,6 +6,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
|||||||
use Symfony\Component\Workflow\Definition;
|
use Symfony\Component\Workflow\Definition;
|
||||||
use Symfony\Component\Workflow\MarkingStore\MarkingStoreInterface;
|
use Symfony\Component\Workflow\MarkingStore\MarkingStoreInterface;
|
||||||
use Symfony\Component\Workflow\Registry;
|
use Symfony\Component\Workflow\Registry;
|
||||||
|
use Symfony\Component\Workflow\SupportStrategy\SupportStrategyInterface;
|
||||||
use Symfony\Component\Workflow\Workflow;
|
use Symfony\Component\Workflow\Workflow;
|
||||||
|
|
||||||
class RegistryTest extends \PHPUnit_Framework_TestCase
|
class RegistryTest extends \PHPUnit_Framework_TestCase
|
||||||
@ -14,13 +15,11 @@ class RegistryTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
protected function setUp()
|
protected function setUp()
|
||||||
{
|
{
|
||||||
$workflows = array();
|
|
||||||
|
|
||||||
$this->registry = new Registry();
|
$this->registry = new Registry();
|
||||||
|
|
||||||
$this->registry->add(new Workflow(new Definition(array(), array()), $this->getMockBuilder(MarkingStoreInterface::class)->getMock(), $this->getMockBuilder(EventDispatcherInterface::class)->getMock(), 'workflow1'), Subject1::class);
|
$this->registry->add(new Workflow(new Definition(array(), array()), $this->getMockBuilder(MarkingStoreInterface::class)->getMock(), $this->getMockBuilder(EventDispatcherInterface::class)->getMock(), 'workflow1'), $this->createSupportStrategy(Subject1::class));
|
||||||
$this->registry->add(new Workflow(new Definition(array(), array()), $this->getMockBuilder(MarkingStoreInterface::class)->getMock(), $this->getMockBuilder(EventDispatcherInterface::class)->getMock(), 'workflow2'), Subject2::class);
|
$this->registry->add(new Workflow(new Definition(array(), array()), $this->getMockBuilder(MarkingStoreInterface::class)->getMock(), $this->getMockBuilder(EventDispatcherInterface::class)->getMock(), 'workflow2'), $this->createSupportStrategy(Subject2::class));
|
||||||
$this->registry->add(new Workflow(new Definition(array(), array()), $this->getMockBuilder(MarkingStoreInterface::class)->getMock(), $this->getMockBuilder(EventDispatcherInterface::class)->getMock(), 'workflow3'), Subject2::class);
|
$this->registry->add(new Workflow(new Definition(array(), array()), $this->getMockBuilder(MarkingStoreInterface::class)->getMock(), $this->getMockBuilder(EventDispatcherInterface::class)->getMock(), 'workflow3'), $this->createSupportStrategy(Subject2::class));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function tearDown()
|
protected function tearDown()
|
||||||
@ -64,6 +63,40 @@ class RegistryTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertInstanceOf(Workflow::class, $w1);
|
$this->assertInstanceOf(Workflow::class, $w1);
|
||||||
$this->assertSame('workflow1', $w1->getName());
|
$this->assertSame('workflow1', $w1->getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group legacy
|
||||||
|
*/
|
||||||
|
public function testGetWithSuccessLegacyStrategy()
|
||||||
|
{
|
||||||
|
$registry = new Registry();
|
||||||
|
|
||||||
|
$registry->add(new Workflow(new Definition(array(), array()), $this->getMockBuilder(MarkingStoreInterface::class)->getMock(), $this->getMockBuilder(EventDispatcherInterface::class)->getMock(), 'workflow1'), Subject1::class);
|
||||||
|
$registry->add(new Workflow(new Definition(array(), array()), $this->getMockBuilder(MarkingStoreInterface::class)->getMock(), $this->getMockBuilder(EventDispatcherInterface::class)->getMock(), 'workflow2'), Subject2::class);
|
||||||
|
|
||||||
|
$workflow = $registry->get(new Subject1());
|
||||||
|
$this->assertInstanceOf(Workflow::class, $workflow);
|
||||||
|
$this->assertSame('workflow1', $workflow->getName());
|
||||||
|
|
||||||
|
$workflow = $registry->get(new Subject1(), 'workflow1');
|
||||||
|
$this->assertInstanceOf(Workflow::class, $workflow);
|
||||||
|
$this->assertSame('workflow1', $workflow->getName());
|
||||||
|
|
||||||
|
$workflow = $registry->get(new Subject2(), 'workflow2');
|
||||||
|
$this->assertInstanceOf(Workflow::class, $workflow);
|
||||||
|
$this->assertSame('workflow2', $workflow->getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createSupportStrategy($supportedClassName)
|
||||||
|
{
|
||||||
|
$strategy = $this->getMockBuilder(SupportStrategyInterface::class)->getMock();
|
||||||
|
$strategy->expects($this->any())->method('supports')
|
||||||
|
->will($this->returnCallback(function ($workflow, $subject) use ($supportedClassName) {
|
||||||
|
return $subject instanceof $supportedClassName;
|
||||||
|
}));
|
||||||
|
|
||||||
|
return $strategy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Subject1
|
class Subject1
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Symfony\Component\Workflow\Tests\SupportStrategy;
|
||||||
|
|
||||||
|
use Symfony\Component\Workflow\SupportStrategy\ClassInstanceSupportStrategy;
|
||||||
|
use Symfony\Component\Workflow\Workflow;
|
||||||
|
|
||||||
|
class ClassInstanceSupportStrategyTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
public function testSupportsIfClassInstance()
|
||||||
|
{
|
||||||
|
$strategy = new ClassInstanceSupportStrategy('Symfony\Component\Workflow\Tests\SupportStrategy\Subject1');
|
||||||
|
|
||||||
|
$this->assertTrue($strategy->supports($this->getWorkflow(), new Subject1()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testSupportsIfNotClassInstance()
|
||||||
|
{
|
||||||
|
$strategy = new ClassInstanceSupportStrategy('Symfony\Component\Workflow\Tests\SupportStrategy\Subject2');
|
||||||
|
|
||||||
|
$this->assertFalse($strategy->supports($this->getWorkflow(), new Subject1()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getWorkflow()
|
||||||
|
{
|
||||||
|
return $this->getMockBuilder(Workflow::class)
|
||||||
|
->disableOriginalConstructor()
|
||||||
|
->getMock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Subject1
|
||||||
|
{
|
||||||
|
}
|
||||||
|
class Subject2
|
||||||
|
{
|
||||||
|
}
|
Reference in New Issue
Block a user