Skip to content

[Workflow] Be able to know why exactly transitions can't be made. #24501

Closed
@d-ph

Description

@d-ph
Q A
Bug report? no
Feature request? yes
BC Break report? no
RFC? no
Symfony version 3.3.10

Hello,

Would it be possible to add a way to know exactly why a transition isn't possible, please?

Motivation: I'd like to show to my Users why exactly a transition couldn't happen. For this I need to know why it can't happen. Currently, the Workflow::can(): bool returns true or false. Ideally, it would instead return a collection of "TransitionViolation[]" (similar to how ValidatorInterface::validate(): ConstraintViolationListInterface returns a collection of ConstraintViolation). This way I can block a transition with a TransitionViolation and then retrieve those violations in the code, that tries to transition objects' statuses, and eventually show a descriptive reason to my Users, what they need to fix in order to move forward.

In other words, in a Guard the following would be possible:

public function onTransition(GuardEvent $event)
{
    if (is_monday()) {
        /*
         * addTransitionViolation() would internally call $event->setBlocked(true);
         */
        $event->addTransitionViolation(new TransitionViolation('Cannot transition on Monday.'));
    }
}

Problems:
2.1. Changing the return type of Workflow::can() is a BC break. Introducing a new method would be better. E.g. Workflow::canTransitionReturnWhyNot(): TransitionViolation[]. Picking up a nice name for the new method will be a challenge.
2.2. TransitionViolation might not be the best name under the Sun. I'm open for suggestions. E.g. TransitionRefusal, GuardRefusal or similar.

TransitionViolation should accept a message, message parameters (optional) and a machine error code (optional):

class TransitionViolation 
{
    public function __construct(string $message, array $messageParameters = [], string $errorCode = 'default') {}
}

/*
 * Example usage
 */
$foo = new TransitionViolation(
    'Cannot transition, when the distance difference is less than 5 kilometres',
    ['minDistance' => 5],
    'com.symfony.www.min_distance'
);

Thank you.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions