8000 [Workflow] Introduce concept of SupprtStrategyInterface to allow othe… · symfony/symfony@1843012 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1843012

Browse files
andesklyrixx
authored andcommitted
[Workflow] Introduce concept of SupprtStrategyInterface to allow other support checks than class instance
1 parent 5921530 commit 1843012

File tree

8 files changed

+162
-18
lines changed

8 files changed

+162
-18
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,6 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode)
280280
->end()
281281
->end()
282282
->arrayNode('supports')
283-
->isRequired()
284283
->beforeNormalization()
285284
->ifString()
286285
->then(function ($v) { return array($v); })
293292
->end()
294293
->end()
295294
->end()
295+
->scalarNode('support_strategy')
296+
->cannotBeEmpty()
297+
->end()
296298
->scalarNode('initial_place')->defaultNull()->end()
297299
->arrayNode('places')
298300
->isRequired()
@@ -353,6 +355,10 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode)
353355
->end()
354356
->end()
355357
->end()
358+
->validate()
359+
->ifTrue(function ($v) { return isset($v['supports']) && isset($v['support_strategy']); })
360+
->thenInvalid('"supports" and "support_strategy" cannot be used together.')
361+
->end()
356362
->end()
357363
->end()
358364
->end()

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
3737
use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer;
3838
use Symfony\Component\Workflow;
39+
use Symfony\Component\Workflow\SupportStrategy\ClassInstanceSupportStrategy;
3940
use Symfony\Component\Yaml\Yaml;
4041

4142
/**
@@ -475,8 +476,14 @@ private function registerWorkflowConfiguration(array $workflows, ContainerBuilde
475476
$container->setDefinition(sprintf('%s.definition', $workflowId), $definitionDefinition);
476477

477478
// Add workflow to Registry
478-
foreach ($workflow['supports'] as $supportedClass) {
479-
$registryDefinition->addMethodCall('add', array(new Reference($workflowId), $supportedClass));
479+
if (isset($workflow['supports'])) {
480+
foreach ($workflow['supports'] as $supportedClassName) {
481+
$strategyDefinition = new Definition(ClassInstanceSupportStrategy::class, array($supportedClassName));
482+
$strategyDefinition->setPublic(false);
483+
$registryDefinition->addMethodCall('add', array(new Reference($workflowId), $strategyDefinition));
484+
}
485+
} elseif (isset($workflow['support_strategy'])) {
486+
$registryDefinition->addMethodCall('add', array(new Reference($workflowId), new Reference($workflow['support_strategy'])));
480487
}
481488
}
482489
}

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,16 @@ public function testWorkflows()
168168
$this->assertCount(9, $stateMachineDefinition->getArgument(1));
169169
$this->assertSame('start', $stateMachineDefinition->getArgument(2));
170170

171+
171172
$serviceMarkingStoreWorkflowDefinition = $container->getDefinition('workflow.service_marking_store_workflow');
172173
/** @var Reference $markingStoreRef */
173174
$markingStoreRef = $serviceMarkingStoreWorkflowDefinition->getArgument(1);
174175
$this->assertInstanceOf(Reference::class, $markingStoreRef);
175176
$this->assertEquals('workflow_service', (string) $markingStoreRef);
177+
178+
$this->assertTrue($container->hasDefinition('workflow.registry', 'Workflow registry is registered as a service'));
179+
$registryDefinition = $container->getDefinition('workflow.registry');
180+
$this->assertGreaterThan(0, count($registryDefinition->getMethodCalls()));
176181
}
177182

178183
/**

src/Symfony/Component/Workflow/Registry.php

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Workflow;
1313

1414
use Symfony\Component\Workflow\Exception\InvalidArgumentException;
15+
use Symfony\Component\Workflow\SupportStrategy\SupportStrategyInterface;
1516

1617
/**
1718
* @author Fabien Potencier <fabien@symfony.com>
@@ -22,12 +23,16 @@ class Registry
2223
private $workflows = array();
2324

2425
/**
25-
* @param Workflow $workflow
26-
* @param string $className
26+
* @param Workflow $workflow
27+
* @param string|SupportStrategyInterface $supportStrategy
2728
*/
28-
public function add(Workflow $workflow, $className)
29+
public function add(Workflow $workflow, $supportStrategy)
2930
{
30-
$this->workflows[] = array($workflow, $className);
31+
if (!$supportStrategy instanceof SupportStrategyInterface) {
32+
@trigger_error('Support of class name string was deprecated after version 3.2 and won\'t work anymore in 4.0.', E_USER_DEPRECATED);
33+
}
34+
35+
$this->workflows[] = array($workflow, $supportStrategy);
3136
}
3237

3338
/**
@@ -40,8 +45,8 @@ public function get($subject, $workflowName = null)
4045
{
4146
$matched = null;
4247

43-
foreach ($this->workflows as list($workflow, $className)) {
44-
if ($this->supports($workflow, $className, $subject, $workflowName)) {
48+
foreach ($this->workflows as list($workflow, $supportStrategy)) {
49+
if ($this->supports($workflow, $supportStrategy, $subject, $workflowName)) {
4550
if ($matched) {
4651
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.');
4752
}
@@ -56,16 +61,19 @@ public function get($subject, $workflowName = null)
5661
return $matched;
5762
}
5863

59-
private function supports(Workflow $workflow, $className, $subject, $name)
64+
private function supports(Workflow $workflow, $supportStrategy, $subject, $workflowName)
6065
{
61-
if (!$subject instanceof $className) {
66+
if (is_string($supportStrategy) && !$subject instanceof $supportStrategy) {
67+
return false;
68+
}
69+
if ($supportStrategy instanceof SupportStrategyInterface && !$supportStrategy->supports($workflow, $subject)) {
6270
return false;
6371
}
6472

65-
if (null === $name) {
73+
if (null === $workflowName) {
6674
return true;
6775
}
6876

69-
return $name === $workflow->getName();
77+
return $workflowName === $workflow->getName();
7078
}
7179
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace Symfony\Component\Workflow\SupportStrategy;
4+
5+
use Symfony\Component\Workflow\Workflow;
6+
7+
class ClassInstanceSupportStrategy implements SupportStrategyInterface
8+
{
9+
private $className;
10+
11+
public function __construct($className)
12+
{
13+
$this->className = $className;
14+
}
15+
16+
/**
17+
* {@inheritdoc}
18+
*/
19+
public function supports(Workflow $workflow, $subject)
20+
{
21+
return $subject instanceof $this->className;
22+
}
23+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Workflow\SupportStrategy;
13+
14+
use Symfony\Component\Workflow\Workflow;
15+
16+
interface SupportStrategyInterface
17+
{
18+
/**
19+
* @param Workflow $workflow
20+
* @param object $subject
21+
*
22+
* @return bool
23+
*/
24+
public function supports(Workflow $workflow, $subject);
25+
}

src/Symfony/Component/Workflow/Tests/RegistryTest.php

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Symfony\Component\Workflow\Definition;
77
use Symfony\Component\Workflow\MarkingStore\MarkingStoreInterface;
88
use Symfony\Component\Workflow\Registry;
9+
use Symfony\Component\Workflow\SupportStrategy\SupportStrategyInterface;
910
use Symfony\Component\Workflow\Workflow;
1011

1112
class RegistryTest extends \PHPUnit_Framework_TestCase
@@ -14,13 +15,11 @@ class RegistryTest extends \PHPUnit_Framework_TestCase
1415

1516
protected function setUp()
1617
{
17-
$workflows = array();
18-
1918
$this->registry = new Registry();
2019

21-
$this->registry->add(new Workflow(new Definition(array(), array()), $this->getMockBuilder(MarkingStoreInterface::class)->getMock(), $this->getMockBuilder(EventDispatcherInterface::class)->getMock(), 'workflow1'), Subject1::class);
22-
$this->registry->add(new Workflow(new Definition(array(), array()), $this->getMockBuilder(MarkingStoreInterface::class)->getMock(), $this->getMockBuilder(EventDispatcherInterface::class)->getMock(), 'workflow2'), Subject2::class);
23-
$this->registry->add(new Workflow(new Definition(array(), array()), $this->getMockBuilder(MarkingStoreInterface::class)->getMock(), $this->getMockBuilder(EventDispatcherInterface::class)->getMock(), 'workflow3'), Subject2::class);
20+
$this->registry->add(new Workflow(new Definition(array(), array()), $this->getMockBuilder(MarkingStoreInterface::class)->getMock(), $this->getMockBuilder(EventDispatcherInterface::class)->getMock(), 'workflow1'), $this->createSupportStrategy(Subject1::class));
21+
$this->registry->add(new Workflow(new Definition(array(), array()), $this->getMockBuilder(MarkingStoreInterface::class)->getMock(), $this->getMockBuilder(EventDispatcherInterface::class)->getMock(), 'workflow2'), $this->createSupportStrategy(Subject2::class));
22+
$this->registry->add(new Workflow(new Definition(array(), array()), $this->getMockBuilder(MarkingStoreInterface::class)->getMock(), $this->getMockBuilder(EventDispatcherInterface::class)->getMock(), 'workflow3'), $this->createSupportStrategy(Subject2::class));
2423
}
2524

2625
protected function tearDown()
@@ -64,6 +63,40 @@ public function testGetWithNoMatch()
6463
$this->assertInstanceOf(Workflow::class, $w1);
6564
$this->assertSame('workflow1', $w1->getName());
6665
}
66+
67+
/**
68+
* @group legacy
69+
*/
70+
public function testGetWithSuccessLegacyStrategy()
71+
{
72+
$registry = new Registry();
73+
74+
$registry->add(new Workflow(new Definition(array(), array()), $this->getMockBuilder(MarkingStoreInterface::class)->getMock(), $this->getMockBuilder(EventDispatcherInterface::class)->getMock(), 'workflow1'), Subject1::class);
75+
$registry->add(new Workflow(new Definition(array(), array()), $this->getMockBuilder(MarkingStoreInterface::class)->getMock(), $this->getMockBuilder(EventDispatcherInterface::class)->getMock(), 'workflow2'), Subject2::class);
76+
77+
$workflow = $registry->get(new Subject1());
78+
$this->assertInstanceOf(Workflow::class, $workflow);
79+
$this->assertSame('workflow1', $workflow->getName());
80+
81+
$workflow = $registry->get(new Subject1(), 'workflow1');
82+
$this->assertInstanceOf(Workflow::class, $workflow);
83+
$this->assertSame('workflow1', $workflow->getName());
84+
85+
$workflow = $registry->get(new Subject2(), 'workflow2');
86+
$this->assertInstanceOf(Workflow::class, $workflow);
87+
$this->assertSame('workflow2', $workflow->getName());
88+
}
89+
90+
private function createSupportStrategy($supportedClassName)
91+
{
92+
$strategy = $this->getMockBuilder(SupportStrategyInterface::class)->getMock();
93+
$strategy->expects($this->any())->method('supports')
94+
->will($this->returnCallback(function ($workflow, $subject) use ($supportedClassName) {
95+
return $subject instanceof $supportedClassName;
96+
}));
97+
98+
return $strategy;
99+
}
67100
}
68101

69102
class Subject1
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Symfony\Component\Workflow\Tests\SupportStrategy;
4+
5+
use Symfony\Component\Workflow\SupportStrategy\ClassInstanceSupportStrategy;
6+
use Symfony\Component\Workflow\Workflow;
7+
8+
class ClassInstanceSupportStrategyTest extends \PHPUnit_Framework_TestCase
9+
{
10+
public function testSupportsIfClassInstance()
11+
{
12+
$strategy = new ClassInstanceSupportStrategy('Symfony\Component\Workflow\Tests\SupportStrategy\Subject1');
13+
14+
$this->assertTrue($strategy->supports($this->getWorkflow(), new Subject1()));
15+
}
16+
17+
public function testSupportsIfNotClassInstance()
18+
{
19+
$strategy = new ClassInstanceSupportStrategy('Symfony\Component\Workflow\Tests\SupportStrategy\Subject2');
20+
21+
$this->assertFalse($strategy->supports($this->getWorkflow(), new Subject1()));
22+
}
23+
24+
private function getWorkflow()
25+
{
26+
return $this->getMockBuilder(Workflow::class)
27+
->disableOriginalConstructor()
28+
->getMock();
29+
}
30+
}
31+
32+
class Subject1
33+
{
34+
}
35+
class Subject2
36+
{
37+
}

0 commit comments

Comments
 (0)
0