Skip to content

Commit

Permalink
[Workflow] Add support for executing custom workflow definition valid…
Browse files Browse the repository at this point in the history
…ators during the container compilation
  • Loading branch information
lyrixx committed Mar 13, 2024
1 parent a0721fd commit 86c1568
Show file tree
Hide file tree
Showing 9 changed files with 53 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
Expand Up @@ -13,6 +13,8 @@ CHANGELOG
* Add `secrets:reveal` command
* Add `rate_limiter` option to `http_client.default_options` and `http_client.scoped_clients`
* Attach the workflow's configuration to the `workflow` tag
* Add support for executing custom workflow definition validators during the
container compilation

7.0
---
Expand Down
Expand Up @@ -49,6 +49,7 @@
use Symfony\Component\Validator\Validation;
use Symfony\Component\Webhook\Controller\WebhookController;
use Symfony\Component\WebLink\HttpHeaderSerializer;
use Symfony\Component\Workflow\Validator\DefinitionValidatorInterface;
use Symfony\Component\Workflow\WorkflowEvents;

/**
Expand Down Expand Up @@ -381,6 +382,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void
->useAttributeAsKey('name')
->prototype('array')
->fixXmlConfig('support')
->fixXmlConfig('definition_validator')
->fixXmlConfig('place')
->fixXmlConfig('transition')
->fixXmlConfig('event_to_dispatch', 'events_to_dispatch')
Expand Down Expand Up @@ -418,6 +420,23 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode): void
->end()
->end()
->end()
->arrayNode('definition_validators')
->beforeNormalization()
->ifString()
->then(fn ($v) => [$v])
->end()
->prototype('scalar')
->cannotBeEmpty()
->validate()
->ifTrue(fn ($v) => !class_exists($v) && !interface_exists($v, false))
->thenInvalid('The validation class %s does not exist.')
->end()
->validate()
->ifTrue(fn ($v) => !is_a($v, DefinitionValidatorInterface::class, true))
->thenInvalid(sprintf('The validation class %%s is not an instance of %s.', DefinitionValidatorInterface::class))
->end()
->end()
->end()
->scalarNode('support_strategy')
->cannotBeEmpty()
->end()
Expand Down
Expand Up @@ -1053,6 +1053,10 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $
$realDefinition = new Workflow\Definition($places, $trs, $initialMarking);
$validator->validate($realDefinition, $name);

foreach ($workflow['definition_validators'] as $validatorClass) {
(new $validatorClass())->validate($realDefinition, $name);
}

// Add workflow to Registry
if ($workflow['supports']) {
foreach ($workflow['supports'] as $supportedClassName) {
Expand Down
Expand Up @@ -386,6 +386,7 @@
<xsd:element name="initial-marking" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="marking-store" type="marking_store" minOccurs="0" maxOccurs="1" />
<xsd:element name="support" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="definition-validator" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="event-to-dispatch" type="event_to_dispatch" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="place" type="place" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="transition" type="transition" minOccurs="0" maxOccurs="unbounded" />
Expand Down
@@ -0,0 +1,17 @@
<?php

namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Fixtures\Workflow\Validator;

use Symfony\Component\Workflow\Definition;
use Symfony\Component\Workflow\Validator\DefinitionValidatorInterface;

class DefinitionValidator implements DefinitionValidatorInterface
{
public static bool $called = false;

public function validate(Definition $definition, string $name): void
{
self::$called = true;
}
}

Expand Up @@ -13,6 +13,9 @@
'supports' => [
FrameworkExtensionTestCase::class,
],
'definition_validators' => [
Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Fixtures\Workflow\Validator\DefinitionValidator::class,
],
'initial_marking' => ['draft'],
'metadata' => [
'title' => 'article workflow',
Expand Down
Expand Up @@ -13,6 +13,7 @@
<framework:audit-trail enabled="true"/>
<framework:initial-marking>draft</framework:initial-marking>
<framework:support>Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTestCase</framework:support>
<framework:definition-validator>Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Fixtures\Workflow\Validator\DefinitionValidator</framework:definition-validator>
<framework:place name="draft" />
<framework:place name="wait_for_journalist" />
<framework:place name="approved_by_journalist" />
Expand Down
Expand Up @@ -9,6 +9,8 @@ framework:
type: workflow
supports:
- Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTestCase
definition_validators:
- Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Fixtures\Workflow\Validator\DefinitionValidator
initial_marking: [draft]
metadata:
title: article workflow
Expand Down
Expand Up @@ -15,6 +15,7 @@
use Psr\Log\LoggerAwareInterface;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\FrameworkExtension;
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
use Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Fixtures\Workflow\Validator\DefinitionValidator;
use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\DummyMessage;
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
use Symfony\Bundle\FullStack;
Expand Down Expand Up @@ -289,6 +290,8 @@ public function testProfilerCollectSerializerDataDefaultDisabled()

public function testWorkflows()
{
DefinitionValidator::$called = false;

$container = $this->createContainerFromFile('workflows');

$this->assertTrue($container->hasDefinition('workflow.article'), 'Workflow is registered as a service');
Expand All @@ -312,6 +315,7 @@ public function testWorkflows()
], $tags['workflow'][0]['metadata'] ?? null);

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

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

Expand Down

0 comments on commit 86c1568

Please sign in to comment.