[Workflow] Fixed code and tests

This commit is contained in:
Grégoire Pineau 2017-01-18 15:08:35 +01:00
parent 184301206f
commit 134a58b4c4
18 changed files with 206 additions and 25 deletions

View File

@ -59,3 +59,9 @@ TwigBridge
* The `TwigRendererEngine::setEnvironment()` method has been deprecated and will be removed * The `TwigRendererEngine::setEnvironment()` method has been deprecated and will be removed
in 4.0. Pass the Twig Environment as second argument of the constructor instead. in 4.0. Pass the Twig Environment as second argument of the constructor instead.
Workflow
--------
* Deprecated class name support in `WorkflowRegistry::add()` as second parameter.
Wrap the class name in an instance of ClassInstanceSupportStrategy instead.

View File

@ -395,3 +395,8 @@ Ldap
---- ----
* The `RenameEntryInterface` has been deprecated, and merged with `EntryManagerInterface` * The `RenameEntryInterface` has been deprecated, and merged with `EntryManagerInterface`
Workflow
--------
* Removed class name support in `WorkflowRegistry::add()` as second parameter.

View File

@ -15,6 +15,7 @@ use Symfony\Bridge\Twig\Extension\WorkflowExtension;
use Symfony\Component\Workflow\Definition; use Symfony\Component\Workflow\Definition;
use Symfony\Component\Workflow\Marking; use Symfony\Component\Workflow\Marking;
use Symfony\Component\Workflow\Registry; use Symfony\Component\Workflow\Registry;
use Symfony\Component\Workflow\SupportStrategy\ClassInstanceSupportStrategy;
use Symfony\Component\Workflow\Transition; use Symfony\Component\Workflow\Transition;
use Symfony\Component\Workflow\Workflow; use Symfony\Component\Workflow\Workflow;
@ -37,7 +38,7 @@ class WorkflowExtensionTest extends \PHPUnit_Framework_TestCase
$workflow = new Workflow($definition); $workflow = new Workflow($definition);
$registry = new Registry(); $registry = new Registry();
$registry->add($workflow, \stdClass::class); $registry->add($workflow, new ClassInstanceSupportStrategy(\stdClass::class));
$this->extension = new WorkflowExtension($registry); $this->extension = new WorkflowExtension($registry);
} }

View File

@ -295,7 +295,9 @@ class Configuration implements ConfigurationInterface
->scalarNode('support_strategy') ->scalarNode('support_strategy')
->cannotBeEmpty() ->cannotBeEmpty()
->end() ->end()
->scalarNode('initial_place')->defaultNull()->end() ->scalarNode('initial_place')
->defaultNull()
->end()
->arrayNode('places') ->arrayNode('places')
->isRequired() ->isRequired()
->requiresAtLeastOneElement() ->requiresAtLeastOneElement()
@ -356,9 +358,17 @@ class Configuration implements ConfigurationInterface
->end() ->end()
->end() ->end()
->validate() ->validate()
->ifTrue(function ($v) { return isset($v['supports']) && isset($v['support_strategy']); }) ->ifTrue(function ($v) {
return $v['supports'] && isset($v['support_strategy']);
})
->thenInvalid('"supports" and "support_strategy" cannot be used together.') ->thenInvalid('"supports" and "support_strategy" cannot be used together.')
->end() ->end()
->validate()
->ifTrue(function ($v) {
return !$v['supports'] && !isset($v['support_strategy']);
})
->thenInvalid('"supports" or "support_strategy" should be configured.')
->end()
->end() ->end()
->end() ->end()
->end() ->end()

View File

@ -476,7 +476,7 @@ 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
if (isset($workflow['supports'])) { if ($workflow['supports']) {
foreach ($workflow['supports'] as $supportedClassName) { foreach ($workflow['supports'] as $supportedClassName) {
$strategyDefinition = new Definition(ClassInstanceSupportStrategy::class, array($supportedClassName)); $strategyDefinition = new Definition(ClassInstanceSupportStrategy::class, array($supportedClassName));
$strategyDefinition->setPublic(false); $strategyDefinition->setPublic(false);

View File

@ -232,13 +232,14 @@
<xsd:complexType name="workflow"> <xsd:complexType name="workflow">
<xsd:sequence> <xsd:sequence>
<xsd:element name="marking-store" type="marking_store" /> <xsd:element name="marking-store" type="marking_store" />
<xsd:element name="support" type="xsd:string" minOccurs="1" maxOccurs="unbounded" /> <xsd:element name="support" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="place" type="xsd:string" minOccurs="1" maxOccurs="unbounded" /> <xsd:element name="place" type="xsd:string" minOccurs="1" maxOccurs="unbounded" />
<xsd:element name="transition" type="transition" minOccurs="1" maxOccurs="unbounded" /> <xsd:element name="transition" type="transition" minOccurs="1" maxOccurs="unbounded" />
</xsd:sequence> </xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" /> <xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="type" type="workflow_type" /> <xsd:attribute name="type" type="workflow_type" />
<xsd:attribute name="initial-place" type="xsd:string" /> <xsd:attribute name="initial-place" type="xsd:string" />
<xsd:attribute name="support-strategy" type="xsd:string" />
</xsd:complexType> </xsd:complexType>
<xsd:complexType name="marking_store"> <xsd:complexType name="marking_store">

View File

@ -0,0 +1,31 @@
<?php
use Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest;
$container->loadFromExtension('framework', array(
'workflows' => array(
'my_workflow' => array(
'marking_store' => array(
'type' => 'multiple_state',
),
'supports' => array(
FrameworkExtensionTest::class,
),
'support_strategy' => 'foobar',
'places' => array(
'first',
'last',
),
'transitions' => array(
'go' => array(
'from' => array(
'first',
),
'to' => array(
'last',
),
),
),
),
),
));

View File

@ -0,0 +1,27 @@
<?php
use Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest;
$container->loadFromExtension('framework', array(
'workflows' => array(
'my_workflow' => array(
'marking_store' => array(
'type' => 'multiple_state',
),
'places' => array(
'first',
'last',
),
'transitions' => array(
'go' => array(
'from' => array(
'first',
),
'to' => array(
'last',
),
),
),
),
),
));

View File

@ -0,0 +1,21 @@
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:framework="http://symfony.com/schema/dic/symfony"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
<framework:config>
<framework:workflow name="my_workflow" support-strategy="foobar">
<framework:marking-store type="multiple_state"/>
<framework:support>Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest</framework:support>
<framework:place>first</framework:place>
<framework:place>last</framework:place>
<framework:transition name="foobar">
<framework:from>a</framework:from>
<framework:to>a</framework:to>
</framework:transition>
</framework:workflow>
</framework:config>
</container>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:framework="http://symfony.com/schema/dic/symfony"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
<framework:config>
<framework:workflow name="my_workflow">
<framework:marking-store type="multiple_state"/>
<framework:place>first</framework:place>
<framework:place>last</framework:place>
<framework:transition name="foobar">
<framework:from>a</framework:from>
<framework:to>a</framework:to>
</framework:transition>
</framework:workflow>
</framework:config>
</container>

View File

@ -0,0 +1,17 @@
framework:
workflows:
my_workflow:
marking_store:
type: multiple_state
supports:
- Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
support_strategy: foobar
places:
- first
- last
transitions:
go:
from:
- first
to:
- last

View File

@ -0,0 +1,14 @@
framework:
workflows:
my_workflow:
marking_store:
type: multiple_state
places:
- first
- last
transitions:
go:
from:
- first
to:
- last

View File

@ -168,7 +168,6 @@ 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);
@ -189,6 +188,24 @@ abstract class FrameworkExtensionTest extends TestCase
$this->createContainerFromFile('workflow_with_type_and_service'); $this->createContainerFromFile('workflow_with_type_and_service');
} }
/**
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
* @expectedExceptionMessage "supports" and "support_strategy" cannot be used together.
*/
public function testWorkflowCannotHaveBothSupportsAndSupportStrategy()
{
$this->createContainerFromFile('workflow_with_support_and_support_strategy');
}
/**
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
* @expectedExceptionMessage "supports" or "support_strategy" should be configured.
*/
public function testWorkflowShouldHaveOneOfSupportsAndSupportStrategy()
{
$this->createContainerFromFile('workflow_without_support_and_support_strategy');
}
/** /**
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
* @expectedExceptionMessage "arguments" and "service" cannot be used together. * @expectedExceptionMessage "arguments" and "service" cannot be used together.

View File

@ -1,2 +1,8 @@
CHANGELOG CHANGELOG
========= =========
3.3.0
-----
* Deprecated class name support in `WorkflowRegistry::add()` as second parameter.
Wrap the class name in an instance of ClassInstanceSupportStrategy instead.

View File

@ -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\ClassInstanceSupportStrategy;
use Symfony\Component\Workflow\SupportStrategy\SupportStrategyInterface; use Symfony\Component\Workflow\SupportStrategy\SupportStrategyInterface;
/** /**
@ -30,6 +31,8 @@ class Registry
{ {
if (!$supportStrategy instanceof SupportStrategyInterface) { 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); @trigger_error('Support of class name string was deprecated after version 3.2 and won\'t work anymore in 4.0.', E_USER_DEPRECATED);
$supportStrategy = new ClassInstanceSupportStrategy($supportStrategy);
} }
$this->workflows[] = array($workflow, $supportStrategy); $this->workflows[] = array($workflow, $supportStrategy);
@ -63,17 +66,10 @@ class Registry
private function supports(Workflow $workflow, $supportStrategy, $subject, $workflowName) private function supports(Workflow $workflow, $supportStrategy, $subject, $workflowName)
{ {
if (is_string($supportStrategy) && !$subject instanceof $supportStrategy) { if (null !== $workflowName && $workflowName !== $workflow->getName()) {
return false;
}
if ($supportStrategy instanceof SupportStrategyInterface && !$supportStrategy->supports($workflow, $subject)) {
return false; return false;
} }
if (null === $workflowName) { return $supportStrategy->supports($workflow, $subject);
return true;
}
return $workflowName === $workflow->getName();
} }
} }

View File

@ -4,10 +4,16 @@ namespace Symfony\Component\Workflow\SupportStrategy;
use Symfony\Component\Workflow\Workflow; use Symfony\Component\Workflow\Workflow;
class ClassInstanceSupportStrategy implements SupportStrategyInterface /**
* @author Andreas Kleemann <akleemann@inviqa.com>
*/
final class ClassInstanceSupportStrategy implements SupportStrategyInterface
{ {
private $className; private $className;
/**
* @param string $className a FQCN
*/
public function __construct($className) public function __construct($className)
{ {
$this->className = $className; $this->className = $className;

View File

@ -13,6 +13,9 @@ namespace Symfony\Component\Workflow\SupportStrategy;
use Symfony\Component\Workflow\Workflow; use Symfony\Component\Workflow\Workflow;
/**
* @author Andreas Kleemann <akleemann@inviqa.com>
*/
interface SupportStrategyInterface interface SupportStrategyInterface
{ {
/** /**

View File

@ -11,17 +11,17 @@ class ClassInstanceSupportStrategyTest extends \PHPUnit_Framework_TestCase
{ {
$strategy = new ClassInstanceSupportStrategy('Symfony\Component\Workflow\Tests\SupportStrategy\Subject1'); $strategy = new ClassInstanceSupportStrategy('Symfony\Component\Workflow\Tests\SupportStrategy\Subject1');
$this->assertTrue($strategy->supports($this->getWorkflow(), new Subject1())); $this->assertTrue($strategy->supports($this->createWorkflow(), new Subject1()));
} }
public function testSupportsIfNotClassInstance() public function testSupportsIfNotClassInstance()
{ {
$strategy = new ClassInstanceSupportStrategy('Symfony\Component\Workflow\Tests\SupportStrategy\Subject2'); $strategy = new ClassInstanceSupportStrategy('Symfony\Component\Workflow\Tests\SupportStrategy\Subject2');
$this->assertFalse($strategy->supports($this->getWorkflow(), new Subject1())); $this->assertFalse($strategy->supports($this->createWorkflow(), new Subject1()));
} }
private function getWorkflow() private function createWorkflow()
{ {
return $this->getMockBuilder(Workflow::class) return $this->getMockBuilder(Workflow::class)
->disableOriginalConstructor() ->disableOriginalConstructor()