Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ab9b40d

Browse files
committed
Merge branch '3.4' into 4.1
* 3.4: Update symfony links to https [FrameworkBundle] fixed guard event names for transitions [FrameworkBundle] fixed guard event names for transitions
2 parents 913781b + 8dcefc9 commit ab9b40d

File tree

11 files changed

+343
-35
lines changed

11 files changed

+343
-35
lines changed

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

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,7 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $
485485

486486
foreach ($config['workflows'] as $name => $workflow) {
487487
$type = $workflow['type'];
488+
$workflowId = sprintf('%s.%s', $type, $name);
488489

489490
// Process Metadata (workflow + places (transition is done in the "create transition" block))
490491
$metadataStoreDefinition = new Definition(Workflow\Metadata\InMemoryMetadataStore::class, array(array(), array(), null));
@@ -503,11 +504,25 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $
503504

504505
// Create transitions
505506
$transitions = array();
507+
$guardsConfiguration = array();
506508
$transitionsMetadataDefinition = new Definition(\SplObjectStorage::class);
509+
// Global transition counter per workflow
510+
$transitionCounter = 0;
507511
foreach ($workflow['transitions'] as $transition) {
508512
if ('workflow' === $type) {
509513
$transitionDefinition = new Definition(Workflow\Transition::class, array($transition['name'], $transition['from'], $transition['to']));
510-
$transitions[] = $transitionDefinition;
514+
$transitionDefinition->setPublic(false);
515+
$transitionId = sprintf('%s.transition.%s', $workflowId, $transitionCounter++);
516+
$container->setDefinition($transitionId, $transitionDefinition);
517+
$transitions[] = new Reference($transitionId);
518+
if (isset($transition['guard'])) {
519+
$configuration = new Definition(Workflow\EventListener\GuardExpression::class);
520+
$configuration->addArgument(new Reference($transitionId));
521+
$configuration->addArgument($transition['guard']);
522+
$configuration->setPublic(false);
523+
$eventName = sprintf('workflow.%s.guard.%s', $name, $transition['name']);
524+
$guardsConfiguration[$eventName][] = $configuration;
525+
}
511526
if ($transition['metadata']) {
512527
$transitionsMetadataDefinition->addMethodCall('attach', array(
513528
$transitionDefinition,
@@ -518,7 +533,18 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $
518533
foreach ($transition['from'] as $from) {
519534
foreach ($transition['to'] as $to) {
520535
$transitionDefinition = new Definition(Workflow\Transition::class, array($transition['name'], $from, $to));
521-
$transitions[] = $transitionDefinition;
536+
$transitionDefinition->setPublic(false);
537+
$transitionId = sprintf('%s.transition.%s', $workflowId, $transitionCounter++);
538+
$container->setDefinition($transitionId, $transitionDefinition);
539+
$transitions[] = new Reference($transitionId);
540+
if (isset($transition['guard'])) {
541+
$configuration = new Definition(Workflow\EventListener\GuardExpression::class);
542+
$configuration->addArgument(new Reference($transitionId));
543+
$configuration->addArgument($transition['guard']);
544+
$configuration->setPublic(false);
545+
$eventName = sprintf('workflow.%s.guard.%s', $name, $transition['name']);
546+
$guardsConfiguration[$eventName][] = $configuration;
547+
}
522548
if ($transition['metadata']) {
523549
$transitionsMetadataDefinition->addMethodCall('attach', array(
524550
$transitionDefinition,
@@ -560,7 +586,6 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $
560586
}
561587

562588
// Create Workflow
563-
$workflowId = sprintf('%s.%s', $type, $name);
564589
$workflowDefinition = new ChildDefinition(sprintf('%s.abstract', $type));
565590
$workflowDefinition->replaceArgument(0, new Reference(sprintf('%s.definition', $workflowId)));
566591
if (isset($markingStoreDefinition)) {
@@ -596,16 +621,7 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $
596621
}
597622

598623
// Add Guard Listener
599-
$guard = new Definition(Workflow\EventListener\GuardListener::class);
600-
$guard->setPrivate(true);
601-
$configuration = array();
602-
foreach ($workflow['transitions'] as $config) {
603-
$transitionName = $config['name'];
604-
605-
if (!isset($config['guard'])) {
606-
continue;
607-
}
608-
624+
if ($guardsConfiguration) {
609625
if (!class_exists(ExpressionLanguage::class)) {
610626
throw new LogicException('Cannot guard workflows as the ExpressionLanguage component is not installed. Try running "composer require symfony/expression-language".');
611627
}
@@ -614,20 +630,21 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $
614630
throw new LogicException('Cannot guard workflows as the Security component is not installed. Try running "composer require symfony/security".');
615631
}
616632

617-
$eventName = sprintf('workflow.%s.guard.%s', $name, $transitionName);
618-
$guard->addTag('kernel.event_listener', array('event' => $eventName, 'method' => 'onTransition'));
619-
$configuration[$eventName] = $config['guard'];
620-
}
621-
if ($configuration) {
633+
$guard = new Definition(Workflow\EventListener\GuardListener::class);
634+
$guard->setPrivate(true);
635+
622636
$guard->setArguments(array(
623-
$configuration,
637+
$guardsConfiguration,
624638
new Reference('workflow.security.expression_language'),
625639
new Reference('security.token_storage'),
626640
new Reference('security.authorization_checker'),
627641
new Reference('security.authentication.trust_resolver'),
628642
new Reference('security.role_hierarchy'),
629643
new Reference('validator', ContainerInterface::NULL_ON_INVALID_REFERENCE),
630644
));
645+
foreach ($guardsConfiguration as $eventName => $config) {
646+
$guard->addTag('kernel.event_listener', array('event' => $eventName, 'method' => 'onTransition'));
647+
}
631648

632649
$container->setDefinition(sprintf('%s.listener.guard', $workflowId), $guard);
633650
$container->setParameter('workflow.has_guard_listeners', true);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@
313313
<xsd:element name="from" type="xsd:string" minOccurs="1" maxOccurs="unbounded" />
314314
<xsd:element name="to" type="xsd:string" minOccurs="1" maxOccurs="unbounded" />
315315
<xsd:element name="metadata" type="metadata" minOccurs="0" maxOccurs="unbounded" />
316+
<xsd:element name="guard" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
316317
</xsd:sequence>
317318
<xsd:attribute name="name" type="xsd:string" use="required" />
318319
</xsd:complexType>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
use Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest;
4+
5+
$container->loadFromExtension('framework', array(
6+
'workflows' => array(
7+
'article' => array(
8+
'type' => 'workflow',
9+
'marking_store' => array(
10+
'type' => 'multiple_state',
11+
),
12+
'supports' => array(
13+
FrameworkExtensionTest::class,
14+
),
15+
'initial_place' => 'draft',
16+
'places' => array(
17+
'draft',
18+
'wait_for_journalist',
19+
'approved_by_journalist',
20+
'wait_for_spellchecker',
21+
'approved_by_spellchecker',
22+
'published',
23+
),
24+
'transitions' => array(
25+
'request_review' => array(
26+
'from' => 'draft',
27+
'to' => array('wait_for_journalist', 'wait_for_spellchecker'),
28+
),
29+
'journalist_approval' => array(
30+
'from' => 'wait_for_journalist',
31+
'to' => 'approved_by_journalist',
32+
),
33+
'spellchecker_approval' => array(
34+
'from' => 'wait_for_spellchecker',
35+
'to' => 'approved_by_spellchecker',
36+
),
37+
'publish' => array(
38+
'from' => array('approved_by_journalist', 'approved_by_spellchecker'),
39+
'to' => 'published',
40+
'guard' => '!!true',
41+
),
42+
'publish_editor_in_chief' => array(
43+
'name' => 'publish',
44+
'from' => 'draft',
45+
'to' => 'published',
46+
'guard' => '!!false',
47+
),
48+
),
49+
),
50+
),
51+
));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?xml version="1.0" ?>
2+
3+
<container xmlns="http://symfony.com/schema/dic/services"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xmlns:framework="http://symfony.com/schema/dic/symfony"
6+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
7+
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
8+
9+
<framework:config>
10+
<framework:workflow name="article" type="workflow" initial-place="draft">
11+
<framework:marking-store type="multiple_state">
12+
<framework:argument>a</framework:argument>
13+
<framework:argument>a</framework:argument>
14+
</framework:marking-store>
15+
<framework:support>Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest</framework:support>
16+
<framework:place>draft</framework:place>
17+
<framework:place>wait_for_journalist</framework:place>
18+
<framework:place>approved_by_journalist</framework:place>
19+
<framework:place>wait_for_spellchecker</framework:place>
20+
<framework:place>approved_by_spellchecker</framework:place>
21+
<framework:place>published</framework:place>
22+
<framework:transition name="request_review">
23+
<framework:from>draft</framework:from>
24+
<framework:to>wait_for_journalist</framework:to>
25+
<framework:to>wait_for_spellchecker</framework:to>
26+
</framework:transition>
27+
<framework:transition name="journalist_approval">
28+
<framework:from>wait_for_journalist</framework:from>
29+
<framework:to>approved_by_journalist</framework:to>
30+
</framework:transition>
31+
<framework:transition name="spellchecker_approval">
32+
<framework:from>wait_for_spellchecker</framework:from>
33+
<framework:to>approved_by_spellchecker</framework:to>
34+
</framework:transition>
35+
<framework:transition name="publish">
36+
<framework:from>approved_by_journalist</framework:from>
37+
<framework:from>approved_by_spellchecker</framework:from>
38+
<framework:to>published</framework:to>
39+
<framework:guard>!!true</framework:guard>
40+
</framework:transition>
41+
<framework:transition name="publish">
42+
<framework:from>draft</framework:from>
43+
<framework:to>published</framework:to>
44+
<framework:guard>!!false</framework:guard>
45+
</framework:transition>
46+
</framework:workflow>
47+
</framework:config>
48+
</container>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
framework:
2+
workflows:
3+
article:
4+
type: workflow
5+
marking_store:
6+
type: multiple_state
7+
supports:
8+
- Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest
9+
initial_place: draft
10+
places:
11+
- draft
12+
- wait_for_journalist
13+
- approved_by_journalist
14+
- wait_for_spellchecker
15+
- approved_by_spellchecker
16+
- published
17+
transitions:
18+
request_review:
19+
from: [draft]
20+
to: [wait_for_journalist, wait_for_spellchecker]
21+
journalist_approval:
22+
from: [wait_for_journalist]
23+
to: [approved_by_journalist]
24+
spellchecker_approval:
25+
from: [wait_for_spellchecker]
26+
to: [approved_by_spellchecker]
27+
publish:
28+
from: [approved_by_journalist, approved_by_spellchecker]
29+
to: [published]
30+
guard: "!!true"
31+
publish_editor_in_chief:
32+
name: publish
33+
from: [draft]
34+
to: [published]
35+
guard: "!!false"

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

Lines changed: 78 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -321,14 +321,84 @@ public function testWorkflowMultipleTransitionsWithSameName()
321321

322322
$this->assertCount(5, $transitions);
323323

324-
$this->assertSame('request_review', $transitions[0]->getArgument(0));
325-
$this->assertSame('journalist_approval', $transitions[1]->getArgument(0));
326-
$this->assertSame('spellchecker_approval', $transitions[2]->getArgument(0));
327-
$this->assertSame('publish', $transitions[3]->getArgument(0));
328-
$this->assertSame('publish', $transitions[4]->getArgument(0));
329-
330-
$this->assertSame(array('approved_by_journalist', 'approved_by_spellchecker'), $transitions[3]->getArgument(1));
331-
$this->assertSame(array('draft'), $transitions[4]->getArgument(1));
324+
$this->assertSame('workflow.article.transition.0', (string) $transitions[0]);
325+
$this->assertSame(array(
326+
'request_review',
327+
array(
328+
'draft',
329+
),
330+
array(
331+
'wait_for_journalist', 'wait_for_spellchecker',
332+
),
333+
), $container->getDefinition($transitions[0])->getArguments());
334+
335+
$this->assertSame('workflow.article.transition.1', (string) $transitions[1]);
336+
$this->assertSame(array(
337+
'journalist_approval',
338+
array(
339+
'wait_for_journalist',
340+
),
341+
array(
342+
'approved_by_journalist',
343+
),
344+
), $container->getDefinition($transitions[1])->getArguments());
345+
346+
$this->assertSame('workflow.article.transition.2', (string) $transitions[2]);
347+
$this->assertSame(array(
348+
'spellchecker_approval',
349+
array(
350+
'wait_for_spellchecker',
351+
),
352+
array(
353+
'approved_by_spellchecker',
354+
),
355+
), $container->getDefinition($transitions[2])->getArguments());
356+
357+
$this->assertSame('workflow.article.transition.3', (string) $transitions[3]);
358+
$this->assertSame(array(
359+
'publish',
360+
array(
361+
'approved_by_journalist',
362+
'approved_by_spellchecker',
363+
),
364+
array(
365+
'published',
366+
),
367+
), $container->getDefinition($transitions[3])->getArguments());
368+
369+
$this->assertSame('workflow.article.transition.4', (string) $transitions[4]);
370+
$this->assertSame(array(
371+
'publish',
372+
array(
373+
'draft',
374+
),
375+
array(
376+
'published',
377+
),
378+
), $container->getDefinition($transitions[4])->getArguments());
379+
}
380+
381+
public function testGuardExpressions()
382+
{
383+
$container = $this->createContainerFromFile('workflow_with_guard_expression');
384+
385+
$this->assertTrue($container->hasDefinition('workflow.article.listener.guard'), 'Workflow guard listener is registered as a service');
386+
$this->assertTrue($container->hasParameter('workflow.has_guard_listeners'), 'Workflow guard listeners parameter exists');
387+
$this->assertTrue(true === $container->getParameter('workflow.has_guard_listeners'), 'Workflow guard listeners parameter is enabled');
388+
$guardDefinition = $container->getDefinition('workflow.article.listener.guard');
389+
$this->assertSame(array(
390+
array(
391+
'event' => 'workflow.article.guard.publish',
392+
'method' => 'onTransition',
393+
),
394+
), $guardDefinition->getTag('kernel.event_listener'));
395+
$guardsConfiguration = $guardDefinition->getArgument(0);
396+
$this->assertTrue(1 === \count($guardsConfiguration), 'Workflow guard configuration contains one element per transition name');
397+
$transitionGuardExpressions = $guardsConfiguration['workflow.article.guard.publish'];
398+
$this->assertSame('workflow.article.transition.3', (string) $transitionGuardExpressions[0]->getArgument(0));
399+
$this->assertSame('!!true', $transitionGuardExpressions[0]->getArgument(1));
400+
$this->assertSame('workflow.article.transition.4', (string) $transitionGuardExpressions[1]->getArgument(0));
401+
$this->assertSame('!!false', $transitionGuardExpressions[1]->getArgument(1));
332402
}
333403

334404
public function testWorkflowServicesCanBeEnabled()

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/config.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@
113113
<div class="sf-toolbar-info-piece">
114114
<b>Help</b>
115115
<span>
116-
<a href="http://symfony.com/support">
116+
<a href="https://symfony.com/support">
117117
Symfony Support Channels
118118
</a>
119119
</span>
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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\EventListener;
13+
14+
use Symfony\Component\Workflow\Transition;
15+
16+
class GuardExpression
17+
{
18+
private $transition;
19+
20+
private $expression;
21+
22+
/**
23+
* @param string $expression
24+
*/
25+
public function __construct(Transition $transition, $expression)
26+
{
27+
$this->transition = $transition;
28+
$this->expression = $expression;
29+
}
30+
31+
public function getTransition()
32+
{
33+
return $this->transition;
34+
}
35+
36+
public function getExpression()
37+
{
38+
return $this->expression;
39+
}
40+
}

0 commit comments

Comments
 (0)