diff --git a/src/Symfony/Component/Workflow/Event/AnnounceEvent.php b/src/Symfony/Component/Workflow/Event/AnnounceEvent.php index 0c675a4854dcd..56bf306776a0e 100644 --- a/src/Symfony/Component/Workflow/Event/AnnounceEvent.php +++ b/src/Symfony/Component/Workflow/Event/AnnounceEvent.php @@ -17,6 +17,9 @@ final class AnnounceEvent extends Event { + use EventNameTrait { + getNameForTransition as public get; + } use HasContextTrait; public function __construct(object $subject, Marking $marking, ?Transition $transition = null, ?WorkflowInterface $workflow = null, array $context = []) diff --git a/src/Symfony/Component/Workflow/Event/CompletedEvent.php b/src/Symfony/Component/Workflow/Event/CompletedEvent.php index 63a5e44836b2c..38e1bdd9ba6d7 100644 --- a/src/Symfony/Component/Workflow/Event/CompletedEvent.php +++ b/src/Symfony/Component/Workflow/Event/CompletedEvent.php @@ -17,6 +17,9 @@ final class CompletedEvent extends Event { + use EventNameTrait { + getNameForTransition as public get; + } use HasContextTrait; public function __construct(object $subject, Marking $marking, ?Transition $transition = null, ?WorkflowInterface $workflow = null, array $context = []) diff --git a/src/Symfony/Component/Workflow/Event/EnterEvent.php b/src/Symfony/Component/Workflow/Event/EnterEvent.php index 46213d48ff466..84a7050171f10 100644 --- a/src/Symfony/Component/Workflow/Event/EnterEvent.php +++ b/src/Symfony/Component/Workflow/Event/EnterEvent.php @@ -17,6 +17,9 @@ final class EnterEvent extends Event { + use EventNameTrait { + getNameForPlace as public get; + } use HasContextTrait; public function __construct(object $subject, Marking $marking, ?Transition $transition = null, ?WorkflowInterface $workflow = null, array $context = []) diff --git a/src/Symfony/Component/Workflow/Event/EnteredEvent.php b/src/Symfony/Component/Workflow/Event/EnteredEvent.php index 17529b8a4d801..c379065185e14 100644 --- a/src/Symfony/Component/Workflow/Event/EnteredEvent.php +++ b/src/Symfony/Component/Workflow/Event/EnteredEvent.php @@ -17,6 +17,9 @@ final class EnteredEvent extends Event { + use EventNameTrait { + getNameForPlace as public get; + } use HasContextTrait; public function __construct(object $subject, Marking $marking, ?Transition $transition = null, ?WorkflowInterface $workflow = null, array $context = []) diff --git a/src/Symfony/Component/Workflow/Event/EventNameTrait.php b/src/Symfony/Component/Workflow/Event/EventNameTrait.php new file mode 100644 index 0000000000000..141a357a4e563 --- /dev/null +++ b/src/Symfony/Component/Workflow/Event/EventNameTrait.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Workflow\Event; + +use Symfony\Component\Workflow\Exception\InvalidArgumentException; + +/** + * @author Nicolas Rigaud + */ +trait EventNameTrait +{ + /** + * Get the event name as lowercase string. + * + * Example: EnterEvent => enter + */ + public static function getName(): string + { + return strtolower(substr(substr(static::class, strrpos(static::class, '\\') + 1), 0, -5)); + } + + /** + * Get event name for workflow and transition. + * + * @throws InvalidArgumentException If $transitionName is provided without $workflowName + */ + private static function getNameForTransition(?string $workflowName, ?string $transitionName): string + { + return self::computeName($workflowName, $transitionName); + } + + /** + * Get event name for workflow and place. + * + * @throws InvalidArgumentException If $placeName is provided without $workflowName + */ + private static function getNameForPlace(?string $workflowName, ?string $placeName): string + { + return self::computeName($workflowName, $placeName); + } + + private static function computeName(?string $workflowName, ?string $transitionOrPlaceName): string + { + if (null !== $transitionOrPlaceName && null === $workflowName) { + throw new \InvalidArgumentException('Missing workflow name.'); + } + + return implode('.', array_filter(['workflow', $workflowName, self::getName(), $transitionOrPlaceName], \is_string(...))); + } +} diff --git a/src/Symfony/Component/Workflow/Event/GuardEvent.php b/src/Symfony/Component/Workflow/Event/GuardEvent.php index 68a57a979b503..e4b6a38ac1e79 100644 --- a/src/Symfony/Component/Workflow/Event/GuardEvent.php +++ b/src/Symfony/Component/Workflow/Event/GuardEvent.php @@ -23,6 +23,10 @@ */ final class GuardEvent extends Event { + use EventNameTrait { + getNameForTransition as public get; + } + private TransitionBlockerList $transitionBlockerList; public function __construct(object $subject, Marking $marking, Transition $transition, ?WorkflowInterface $workflow = null) diff --git a/src/Symfony/Component/Workflow/Event/LeaveEvent.php b/src/Symfony/Component/Workflow/Event/LeaveEvent.php index ca7ff1aa1af0a..8246fd98e532e 100644 --- a/src/Symfony/Component/Workflow/Event/LeaveEvent.php +++ b/src/Symfony/Component/Workflow/Event/LeaveEvent.php @@ -17,6 +17,9 @@ final class LeaveEvent extends Event { + use EventNameTrait { + getNameForPlace as public get; + } use HasContextTrait; public function __construct(object $subject, Marking $marking, ?Transition $transition = null, ?WorkflowInterface $workflow = null, array $context = []) diff --git a/src/Symfony/Component/Workflow/Event/TransitionEvent.php b/src/Symfony/Component/Workflow/Event/TransitionEvent.php index 6bae1595c86f3..ec994005ea514 100644 --- a/src/Symfony/Component/Workflow/Event/TransitionEvent.php +++ b/src/Symfony/Component/Workflow/Event/TransitionEvent.php @@ -17,6 +17,9 @@ final class TransitionEvent extends Event { + use EventNameTrait { + getNameForTransition as public get; + } use HasContextTrait; public function __construct(object $subject, Marking $marking, ?Transition $transition = null, ?WorkflowInterface $workflow = null, array $context = []) diff --git a/src/Symfony/Component/Workflow/Tests/Event/EventNameTraitTest.php b/src/Symfony/Component/Workflow/Tests/Event/EventNameTraitTest.php new file mode 100644 index 0000000000000..2535c13e6ca7c --- /dev/null +++ b/src/Symfony/Component/Workflow/Tests/Event/EventNameTraitTest.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Workflow\Tests\Event; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Workflow\Event\AnnounceEvent; +use Symfony\Component\Workflow\Event\CompletedEvent; +use Symfony\Component\Workflow\Event\EnteredEvent; +use Symfony\Component\Workflow\Event\EnterEvent; +use Symfony\Component\Workflow\Event\GuardEvent; +use Symfony\Component\Workflow\Event\LeaveEvent; +use Symfony\Component\Workflow\Event\TransitionEvent; + +class EventNameTraitTest extends TestCase +{ + /** + * @dataProvider getEvents + * + * @param class-string $class + */ + public function testEventNames(string $class, ?string $workflowName, ?string $transitionOrPlaceName, string $expected) + { + $name = $class::get($workflowName, $transitionOrPlaceName); + $this->assertEquals($expected, $name); + } + + public static function getEvents(): iterable + { + yield [AnnounceEvent::class, null, null, 'workflow.announce']; + yield [AnnounceEvent::class, 'post', null, 'workflow.post.announce']; + yield [AnnounceEvent::class, 'post', 'publish', 'workflow.post.announce.publish']; + + yield [CompletedEvent::class, null, null, 'workflow.completed']; + yield [CompletedEvent::class, 'post', null, 'workflow.post.completed']; + yield [CompletedEvent::class, 'post', 'publish', 'workflow.post.completed.publish']; + + yield [EnteredEvent::class, null, null, 'workflow.entered']; + yield [EnteredEvent::class, 'post', null, 'workflow.post.entered']; + yield [EnteredEvent::class, 'post', 'published', 'workflow.post.entered.published']; + + yield [EnterEvent::class, null, null, 'workflow.enter']; + yield [EnterEvent::class, 'post', null, 'workflow.post.enter']; + yield [EnterEvent::class, 'post', 'published', 'workflow.post.enter.published']; + + yield [GuardEvent::class, null, null, 'workflow.guard']; + yield [GuardEvent::class, 'post', null, 'workflow.post.guard']; + yield [GuardEvent::class, 'post', 'publish', 'workflow.post.guard.publish']; + + yield [LeaveEvent::class, null, null, 'workflow.leave']; + yield [LeaveEvent::class, 'post', null, 'workflow.post.leave']; + yield [LeaveEvent::class, 'post', 'published', 'workflow.post.leave.published']; + + yield [TransitionEvent::class, null, null, 'workflow.transition']; + yield [TransitionEvent::class, 'post', null, 'workflow.post.transition']; + yield [TransitionEvent::class, 'post', 'publish', 'workflow.post.transition.publish']; + } + + public function testInvalidArgumentExceptionIsThrownIfWorkflowNameIsMissing() + { + $this->expectException(\InvalidArgumentException::class); + + EnterEvent::get(null, 'place'); + } +}