Description
Symfony version(s) affected
4.4.44
Description
Today we noticed some weird behaviour with one of our workflows: Suddenly it started complaining about the marking store method not existing, which was true, since we use the getStatus
method for that workflow and it was complaining that the getState
method did not exist. We just introduced a new workflow that actually does use the getState
method, so that probably had something to do with it.
After some digging it seems that a workflow without a marking store definition will use a previously defined marking store, because the $markingStoreDefinition
variable is used inside a loop in the FrameworkExtension
in the FrameworkBundle and is never unset.
I haven't tested this with any other versions besides 4.4.44, but from looking at the latest version of the FrameworkExtension
, it looks like this is still an issue.
How to reproduce
-
Create two empty classes
App\Entity\ObjectA
andApp\Entity\ObjectB
-
Define the following two workflows:
framework:
workflows:
workflow_a:
type: 'state_machine'
marking_store:
type: 'method'
property: 'status'
supports:
- App\Entity\ObjectA
initial_marking: start
places:
- start
- finish
transitions:
finish:
from: start
to: finish
workflow_b:
type: 'state_machine'
supports:
- App\Entity\ObjectB
initial_marking: start
places:
- start
- finish
transitions:
finish:
from: start
to: finish
- Request the marking store for both of them
- You will notice that workflow_b will use the same marking store as workflow_a (not same instance, but same definition)
Possible Solution
Either set $markingStoreDefinition
to null
initially or unset it after it won't be used anymore.
The piece of code in question:
// Create MarkingStore
if (isset($workflow['marking_store']['type'])) {
$markingStoreDefinition = new ChildDefinition('workflow.marking_store.'.$workflow['marking_store']['type']);
if ('method' === $workflow['marking_store']['type']) {
$markingStoreDefinition->setArguments([
'state_machine' === $type, // single state
$workflow['marking_store']['property'] ?? 'marking',
]);
} else {
foreach ($workflow['marking_store']['arguments'] as $argument) {
$markingStoreDefinition->addArgument($argument);
}
}
} elseif (isset($workflow['marking_store']['service'])) {
$markingStoreDefinition = new Reference($workflow['marking_store']['service']);
}
// Create Workflow
$workflowDefinition = new ChildDefinition(sprintf('%s.abstract', $type));
$workflowDefinition->replaceArgument(0, new Reference(sprintf('%s.definition', $workflowId)));
if (isset($markingStoreDefinition)) {
$workflowDefinition->replaceArgument(1, $markingStoreDefinition);
}
Additional Context
First dump is workflow_a, second dump is workflow_b