[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()
|
||||
->arrayNode('supports')
|
||||
->isRequired()
|
||||
->beforeNormalization()
|
||||
->ifString()
|
||||
->then(function ($v) { return array($v); })
|
||||
@ -293,6 +292,9 @@ class Configuration implements ConfigurationInterface
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->scalarNode('support_strategy')
|
||||
->cannotBeEmpty()
|
||||
->end()
|
||||
->scalarNode('initial_place')->defaultNull()->end()
|
||||
->arrayNode('places')
|
||||
->isRequired()
|
||||
@ -353,6 +355,10 @@ class Configuration implements ConfigurationInterface
|
||||
->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()
|
||||
|
@ -36,6 +36,7 @@ use Symfony\Component\Serializer\Normalizer\DataUriNormalizer;
|
||||
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
|
||||
use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer;
|
||||
use Symfony\Component\Workflow;
|
||||
use Symfony\Component\Workflow\SupportStrategy\ClassInstanceSupportStrategy;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
/**
|
||||
@ -475,8 +476,14 @@ class FrameworkExtension extends Extension
|
||||
$container->setDefinition(sprintf('%s.definition', $workflowId), $definitionDefinition);
|
||||
|
||||
// Add workflow to Registry
|
||||
foreach ($workflow['supports'] as $supportedClass) {
|
||||
$registryDefinition->addMethodCall('add', array(new Reference($workflowId), $supportedClass));
|
||||
if (isset($workflow['supports'])) {
|
||||
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->assertSame('start', $stateMachineDefinition->getArgument(2));
|
||||
|
||||
|
||||
$serviceMarkingStoreWorkflowDefinition = $container->getDefinition('workflow.service_marking_store_workflow');
|
||||
/** @var Reference $markingStoreRef */
|
||||
$markingStoreRef = $serviceMarkingStoreWorkflowDefinition->getArgument(1);
|
||||
$this->assertInstanceOf(Reference::class, $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;
|
||||
|
||||
use Symfony\Component\Workflow\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Workflow\SupportStrategy\SupportStrategyInterface;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
@ -22,12 +23,16 @@ class Registry
|
||||
private $workflows = array();
|
||||
|
||||
/**
|
||||
* @param Workflow $workflow
|
||||
* @param string $className
|
||||
* @param Workflow $workflow
|
||||
* @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;
|
||||
|
||||
foreach ($this->workflows as list($workflow, $className)) {
|
||||
if ($this->supports($workflow, $className, $subject, $workflowName)) {
|
||||
foreach ($this->workflows as list($workflow, $supportStrategy)) {
|
||||
if ($this->supports($workflow, $supportStrategy, $subject, $workflowName)) {
|
||||
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.');
|
||||
}
|
||||
@ -56,16 +61,19 @@ class Registry
|
||||
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;
|
||||
}
|
||||
|
||||
if (null === $name) {
|
||||
if (null === $workflowName) {
|
||||
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\MarkingStore\MarkingStoreInterface;
|
||||
use Symfony\Component\Workflow\Registry;
|
||||
use Symfony\Component\Workflow\SupportStrategy\SupportStrategyInterface;
|
||||
use Symfony\Component\Workflow\Workflow;
|
||||
|
||||
class RegistryTest extends \PHPUnit_Framework_TestCase
|
||||
@ -14,13 +15,11 @@ class RegistryTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$workflows = array();
|
||||
|
||||
$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(), 'workflow2'), 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(), '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'), $this->createSupportStrategy(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()
|
||||
@ -64,6 +63,40 @@ class RegistryTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertInstanceOf(Workflow::class, $w1);
|
||||
$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
|
||||
|
@ -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