Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit f46d93d

Browse filesBrowse files
committed
[Workflow] Add support for executing custom workflow definition validators during the container compilation
1 parent 2ffd266 commit f46d93d
Copy full SHA for f46d93d

File tree

10 files changed

+113
-1
lines changed
Filter options

10 files changed

+113
-1
lines changed

‎src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ CHANGELOG
1616
* Deprecate `session.sid_length` and `session.sid_bits_per_character` config options
1717
* Add the ability to use an existing service as a lock/semaphore resource
1818
* Add support for configuring multiple serializer instances via the configuration
19+
* Add support for executing custom workflow definition validators during the
20+
container compilation
1921

2022
7.1
2123
---
@@ -32,7 +34,6 @@ CHANGELOG
3234
* Add the `allowed_recipients` option for mailer to allow some users to receive
3335
emails even if `recipients` is defined.
3436
* Reset env vars when resetting the container
35-
3637
7.0
3738
---
3839

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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
+19Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
use Symfony\Component\Validator\Validation;
5050
use Symfony\Component\Webhook\Controller\WebhookController;
5151
use Symfony\Component\WebLink\HttpHeaderSerializer;
52+
use Symfony\Component\Workflow\Validator\DefinitionValidatorInterface;
5253
use Symfony\Component\Workflow\WorkflowEvents;
5354

5455
/**
@@ -381,6 +382,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void
381382
->useAttributeAsKey('name')
382383
->prototype('array')
383384
->fixXmlConfig('support')
385+
->fixXmlConfig('definition_validator')
384386
->fixXmlConfig('place')
385387
->fixXmlConfig('transition')
386388
->fixXmlConfig('event_to_dispatch', 'events_to_dispatch')
@@ -418,6 +420,23 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void
418420
->end()
419421
->end()
420422
->end()
423+
->arrayNode('definition_validators')
424+
->prototype('scalar')
425+
->cannotBeEmpty()
426+
->validate()
427+
->ifTrue(fn ($v) => !class_exists($v))
428+
->thenInvalid('The validation class %s does not exist.')
429+
->end()
430+
->validate()
431+
->ifTrue(fn ($v) => !is_a($v, DefinitionValidatorInterface::class, true))
432+
->thenInvalid(sprintf('The validation class %%s is not an instance of %s.', DefinitionValidatorInterface::class))
433+
->end()
434+
->validate()
435+
->ifTrue(fn ($v) => 1 <= (new \ReflectionClass($v))->getConstructor()?->getNumberOfRequiredParameters())
436+
->thenInvalid('The validation class %s constructor must not have any arguments.')
437+
->end()
438+
->end()
439+
->end()
421440
->scalarNode('support_strategy')
422441
->cannotBeEmpty()
423442
->end()

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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,10 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $
10541054
$realDefinition = new Workflow\Definition($places, $trs, $initialMarking);
10551055
$validator->validate($realDefinition, $name);
10561056

1057+
foreach ($workflow['definition_validators'] as $validatorClass) {
1058+
(new $validatorClass())->validate($realDefinition, $name);
1059+
}
1060+
10571061
// Add workflow to Registry
10581062
if ($workflow['supports']) {
10591063
foreach ($workflow['supports'] as $supportedClassName) {

‎src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@
397397
<xsd:element name="initial-marking" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
398398
<xsd:element name="marking-store" type="marking_store" minOccurs="0" maxOccurs="1" />
399399
<xsd:element name="support" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
400+
<xsd:element name="definition-validator" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
400401
<xsd:element name="event-to-dispatch" type="event_to_dispatch" minOccurs="0" maxOccurs="unbounded" />
401402
<xsd:element name="place" type="place" minOccurs="0" maxOccurs="unbounded" />
402403
<xsd:element name="transition" type="transition" minOccurs="0" maxOccurs="unbounded" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Fixtures\Workflow\Validator;
4+
5+
use Symfony\Component\Workflow\Definition;
6+
use Symfony\Component\Workflow\Validator\DefinitionValidatorInterface;
7+
8+
class DefinitionValidator implements DefinitionValidatorInterface
9+
{
10+
public static bool $called = false;
11+
12+
public function validate(Definition $definition, string $name): void
13+
{
14+
self::$called = true;
15+
}
16+
}
17+

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows.php
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
'supports' => [
1414
FrameworkExtensionTestCase::class,
1515
],
16+
'definition_validators' => [
17+
Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Fixtures\Workflow\Validator\DefinitionValidator::class,
18+
],
1619
'initial_marking' => ['draft'],
1720
'metadata' => [
1821
'title' => 'article workflow',

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows.xml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows.xml
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<framework:audit-trail enabled="true"/>
1414
<framework:initial-marking>draft</framework:initial-marking>
1515
<framework:support>Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTestCase</framework:support>
16+
<framework:definition-validator>Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Fixtures\Workflow\Validator\DefinitionValidator</framework:definition-validator>
1617
<framework:place name="draft" />
1718
<framework:place name="wait_for_journalist" />
1819
<framework:place name="approved_by_journalist" />

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows.yml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows.yml
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ framework:
99
type: workflow
1010
supports:
1111
- Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTestCase
12+
definition_validators:
13+
- Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Fixtures\Workflow\Validator\DefinitionValidator
1214
initial_marking: [draft]
1315
metadata:
1416
title: article workflow

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTestCase.php
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\Bridge\PhpUnit\ExpectUserDeprecationMessageTrait;
1717
use Symfony\Bundle\FrameworkBundle\DependencyInjection\FrameworkExtension;
1818
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
19+
use Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Fixtures\Workflow\Validator\DefinitionValidator;
1920
use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\DummyMessage;
2021
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
2122
use Symfony\Bundle\FullStack;
@@ -295,6 +296,8 @@ public function testProfilerCollectSerializerDataDefaultDisabled()
295296

296297
public function testWorkflows()
297298
{
299+
DefinitionValidator::$called = false;
300+
298301
$container = $this->createContainerFromFile('workflows');
299302

300303
$this->assertTrue($container->hasDefinition('workflow.article'), 'Workflow is registered as a service');
@@ -318,6 +321,7 @@ public function testWorkflows()
318321
], $tags['workflow'][0]['metadata'] ?? null);
319322

320323
$this->assertTrue($container->hasDefinition('workflow.article.definition'), 'Workflow definition is registered as a service');
324+
$this->assertTrue(DefinitionValidator::$called, 'DefinitionValidator is called');
321325

322326
$workflowDefinition = $container->getDefinition('workflow.article.definition');
323327

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/PhpFrameworkExtensionTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/PhpFrameworkExtensionTest.php
+60Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,53 @@ public function testWorkflowValidationStateMachine()
128128
});
129129
}
130130

131+
/**
132+
* @dataProvider provideWorkflowValidationCustomTests
133+
*/
134+
public function testWorkflowValidationCustomBroken(string $class, string $message)
135+
{
136+
$this->expectException(InvalidConfigurationException::class);
137+
$this->expectExceptionMessage($message);
138+
$this->createContainerFromClosure(function ($container) use ($class) {
139+
$container->loadFromExtension('framework', [
140+
'annotations' => false,
141+
'http_method_override' => false,
142+
'handle_all_throwables' => true,
143+
'php_errors' => ['log' => true],
144+
'workflows' => [
145+
'article' => [
146+
'type' => 'state_machine',
147+
'supports' => [
148+
__CLASS__,
149+
],
150+
'places' => [
151+
'a',
152+
'b',
153+
],
154+
'transitions' => [
155+
'a_to_b' => [
156+
'from' => ['a'],
157+
'to' => ['b'],
158+
],
159+
],
160+
'definition_validators' => [
161+
$class,
162+
]
163+
],
164+
],
165+
]);
166+
});
167+
}
168+
169+
public static function provideWorkflowValidationCustomTests()
170+
{
171+
yield ['classDoesNotExist', 'Invalid configuration for path "framework.workflows.workflows.article.definition_validators.0": The validation class "classDoesNotExist" does not exist.'];
172+
173+
yield [\DateTime::class, 'Invalid configuration for path "framework.workflows.workflows.article.definition_validators.0": The validation class "DateTime" is not an instance of Symfony\Component\Workflow\Validator\DefinitionValidatorInterface.'];
174+
175+
yield [WorkflowValidatorWithConstructor::class, 'Invalid configuration for path "framework.workflows.workflows.article.definition_validators.0": The validation class "Symfony\\\\Bundle\\\\FrameworkBundle\\\\Tests\\\\DependencyInjection\\\\WorkflowValidatorWithConstructor" constructor must not have any arguments.'];
176+
}
177+
131178
public function testWorkflowDefaultMarkingStoreDefinition()
132179
{
133180
$container = $this->createContainerFromClosure(function ($container) {
@@ -266,3 +313,16 @@ public function testRateLimiterIsTagged()
266313
$this->assertSame('second', $container->getDefinition('limiter.second')->getTag('rate_limiter')[0]['name']);
267314
}
268315
}
316+
317+
318+
class WorkflowValidatorWithConstructor implements \Symfony\Component\Workflow\Validator\DefinitionValidatorInterface
319+
{
320+
public function __construct(bool $enabled)
321+
{
322+
323+
}
324+
325+
public function validate(\Symfony\Component\Workflow\Definition $definition, string $name): void
326+
{
327+
}
328+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.