<p dir="auto"><strong>Symfony version(s) affected</strong>: 4.1. symfony/workflow: 4.2</p>
<p dir="auto"><strong>Description</strong><br>
Hello. I've faced an issue when I placing two or more values in <code class="notranslate">from</code> section at transitions description in config. As far as I know, this is allowed, right?</p>
<p dir="auto">So I'm getting false negative results when trying to apply for state transfer with allowed <code class="notranslate">from</code> values.</p>
<p dir="auto"><strong>How to reproduce</strong><br>
After some research, I believe that the problem is in the following <code class="notranslate">buildTransitionBlockerListForTransition</code> method. The method just iterates all over places and creates <code class="notranslate">TransitionBlockerList</code> on first false condition. But as far as I get - method have to iterate over all forms and only then create <code class="notranslate">TransitionBlockerList</code> if needed.</p>
<p dir="auto">Here is the reference on code that I've described above.<br>
<a href="https://github.com/symfony/workflow/blob/master/Workflow.php#L247">https://github.com/symfony/workflow/blob/master/Workflow.php#L247</a></p>
<p dir="auto"><strong>Possible Solution</strong><br>
Iterate over all places and create <code class="notranslate">TransitionBlockerList</code> only if <code class="notranslate">$marking-&gt;has($place)</code> have returned false for every <code class="notranslate">$place</code></p>
<p dir="auto"><strong>Additional context</strong><br>
My workflow config</p>
<div class="highlight highlight-source-yaml notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="framework:
    workflows:
        payment:
            type: 'workflow'
            supports:
                - App\Entity\Payment
                - App\Entity\RecurringPayment
            initial_place: new
            marking_store:
                type: 'single_state'
                arguments:
                    - 'status'
            places:
                - new
                - accepted
                - error
                - declined
                - pending
                - refunded
                - cancelled
            transitions:
                pending:
                    from: new
                    to: pending
                accepted:
                    from: [new, pending, accepted]
                    to: accepted
                refunded:
                    from: accepted
                    to: refunded
                cancelled:
                    from: [new, pending, accepted]
                    to: cancelled
                error:
                    from: [new, pending]
                    to: error
                declined:
                    from: [new, pending]
                    to: declined"><pre class="notranslate"><span class="pl-ent">framework</span>:
    <span class="pl-ent">workflows</span>:
        <span class="pl-ent">payment</span>:
            <span class="pl-ent">type</span>: <span class="pl-s"><span class="pl-pds">'</span>workflow<span class="pl-pds">'</span></span>
            <span class="pl-ent">supports</span>:
                - <span class="pl-s">App\Entity\Payment</span>
                - <span class="pl-s">App\Entity\RecurringPayment</span>
            <span class="pl-ent">initial_place</span>: <span class="pl-s">new</span>
            <span class="pl-ent">marking_store</span>:
                <span class="pl-ent">type</span>: <span class="pl-s"><span class="pl-pds">'</span>single_state<span class="pl-pds">'</span></span>
                <span class="pl-ent">arguments</span>:
                    - <span class="pl-s"><span class="pl-pds">'</span>status<span class="pl-pds">'</span></span>
            <span class="pl-ent">places</span>:
                - <span class="pl-s">new</span>
                - <span class="pl-s">accepted</span>
                - <span class="pl-s">error</span>
                - <span class="pl-s">declined</span>
                - <span class="pl-s">pending</span>
                - <span class="pl-s">refunded</span>
                - <span class="pl-s">cancelled</span>
            <span class="pl-ent">transitions</span>:
                <span class="pl-ent">pending</span>:
                    <span class="pl-ent">from</span>: <span class="pl-s">new</span>
                    <span class="pl-ent">to</span>: <span class="pl-s">pending</span>
                <span class="pl-ent">accepted</span>:
                    <span class="pl-ent">from</span>: <span class="pl-s">[new, pending, accepted]</span>
                    <span class="pl-ent">to</span>: <span class="pl-s">accepted</span>
                <span class="pl-ent">refunded</span>:
                    <span class="pl-ent">from</span>: <span class="pl-s">accepted</span>
                    <span class="pl-ent">to</span>: <span class="pl-s">refunded</span>
                <span class="pl-ent">cancelled</span>:
                    <span class="pl-ent">from</span>: <span class="pl-s">[new, pending, accepted]</span>
                    <span class="pl-ent">to</span>: <span class="pl-s">cancelled</span>
                <span class="pl-ent">error</span>:
                    <span class="pl-ent">from</span>: <span class="pl-s">[new, pending]</span>
                    <span class="pl-ent">to</span>: <span class="pl-s">error</span>
                <span class="pl-ent">declined</span>:
                    <span class="pl-ent">from</span>: <span class="pl-s">[new, pending]</span>
                    <span class="pl-ent">to</span>: <span class="pl-s">declined</span></pre></div>
<p dir="auto">Hi all,</p>
<p dir="auto">I'm posting this RFC to submit a new validator constraint idea. I don't know if it's worth it or not and that's why I would like to get some feedbacks.</p>
<p dir="auto">Something that annoys me with validation constraints is repeating the validation groups everytime in all constraints when dealing with multiple validation contexts. Below is a very simple example:</p>
<div class="highlight highlight-text-html-php notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="
class User
{
    /**
     * @Assert\NotBlank(groups = { &quot;Signup&quot; })
     * @Assert\Length(min = 6, max = 15, groups = { &quot;Signup&quot; })
     * @Assert\Regex(pattern = &quot;^/[a-z0-9]+$/&quot;, groups = { &quot;Signup&quot; })
     */
    private $username;

    /**
     * @Assert\NotBlank(groups = { &quot;Signup&quot; })
     * @Assert\Length(min = 8, groups = { &quot;Signup&quot;, &quot;Profile&quot; })
     *
     */
    private $password;
}"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-v">User</span>
{
    <span class="pl-c">/**</span>
<span class="pl-c">     * @Assert\NotBlank(groups = { "Signup" })</span>
<span class="pl-c">     * @Assert\Length(min = 6, max = 15, groups = { "Signup" })</span>
<span class="pl-c">     * @Assert\Regex(pattern = "^/[a-z0-9]+$/", groups = { "Signup" })</span>
<span class="pl-c">     */</span>
    <span class="pl-k">private</span> <span class="pl-c1"><span class="pl-c1">$</span>username</span>;

    <span class="pl-c">/**</span>
<span class="pl-c">     * @Assert\NotBlank(groups = { "Signup" })</span>
<span class="pl-c">     * @Assert\Length(min = 8, groups = { "Signup", "Profile" })</span>
<span class="pl-c">     *</span>
<span class="pl-c">     */</span>
    <span class="pl-k">private</span> <span class="pl-c1"><span class="pl-c1">$</span>password</span>;
}</pre></div>
<p dir="auto">As you can see in the above code, for the <code class="notranslate">$username</code> property, we have to repeat the <code class="notranslate">groups</code> option to indicate for which context we want to validate that property. I think this is annonying to duplicate that <code class="notranslate">group</code> option.</p>
<p dir="auto">That's why I suggest to introduce a new <code class="notranslate">Group</code> constraint that is a collection of constraints to be triggered only for a particular (set of) group(s).</p>
<div class="highlight highlight-text-html-php notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class User
{
    /**
     * @Assert\Group(groups = { &quot;Signup&quot; }, constraints = {
     *     @Assert\NotBlank(),
     *     @Assert\Length(min = 6, max = 15),
     *     @Assert\Regex(pattern = &quot;^/[a-z0-9]+$/&quot;)
     * })
     */
    private $username;

    /**
     * @Assert\NotBlank(groups = { &quot;Signup&quot; })
     * @Assert\Length(min = 8, groups = { &quot;Signup&quot;, &quot;Profile&quot; })
     *
     */
    private $password;
}"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-v">User</span>
{
    <span class="pl-c">/**</span>
<span class="pl-c">     * @Assert\Group(groups = { "Signup" }, constraints = {</span>
<span class="pl-c">     *     @Assert\NotBlank(),</span>
<span class="pl-c">     *     @Assert\Length(min = 6, max = 15),</span>
<span class="pl-c">     *     @Assert\Regex(pattern = "^/[a-z0-9]+$/")</span>
<span class="pl-c">     * })</span>
<span class="pl-c">     */</span>
    <span class="pl-k">private</span> <span class="pl-c1"><span class="pl-c1">$</span>username</span>;

    <span class="pl-c">/**</span>
<span class="pl-c">     * @Assert\NotBlank(groups = { "Signup" })</span>
<span class="pl-c">     * @Assert\Length(min = 8, groups = { "Signup", "Profile" })</span>
<span class="pl-c">     *</span>
<span class="pl-c">     */</span>
    <span class="pl-k">private</span> <span class="pl-c1"><span class="pl-c1">$</span>password</span>;
}</pre></div>
<p dir="auto">As you can see, I can embed my three constraints into one single <code class="notranslate">Group</code> constraint that tells for which context we want to execute that set of annotations. I find it a bit more readable and it also avoids to duplicate the goup name everywhere in the other constraints.</p>
<p dir="auto">What do you think of such feature?<br>
Is it something that you would need or help improve your efficiency?</p>
<p dir="auto">Regards.</p>