Description
Description
At the moment the recommended way to initialize a workflow for an object $subject
is to call WorkflowInterface::getMarking($subject)
. Internally this will call the getter for the configured property holding the marking on $subject
. If this returns null the configured initial marking will be set on $subject
.
The problem is that if you use typed properties in $subject::class
the marking property has to be either nullable or has to initialize the marking property with the initial marking. In my opinion both of these options are suboptimal.
Option 1 probably doesn't reflect your model in a good way, most of the times you don't want a marking to be null at any time.
Option 2 conflicts with separation of concerns considerations.
The only other fix I can think of is to implement the getter for your marking like this:
public function getMarking(): string
{
return $this->marking ?? null;
}
But I think this is very unintuitive and even worse than options 1 and 2.
The only good solution I can think of is to add a method WorkflowInterface::initialize($subject)
that will only set the marking property of $subject
to the configured initial marking without trying to get the marking first.
In my opinion this would also be a much more intuitive way of initializing a workflow than calling WorkflowInterface::getMarking($subject)
.
If no one disagrees with my opinion and proposal on this I would gladly implement this feature myself.
Example
// src/Entity/Book
namespace App\Entity;
class Book
{
private string $marking;
public function getMarking(): string
{
return $this->marking;
}
public function setMarking(string $marking): void
{
$this->marking = $marking;
}
}
# config/workflow.yaml
framework:
workflows:
book:
type: 'state_machine'
marking_store:
type: 'method'
property: 'marking'
supports:
- App\Entity\Book
initial_marking: on_shelf
places:
- on_shelf
- ...
// some code initializing the workflow in App\Entity\Book
$book = new Book();
// current way that results in an exception
/** @var WorkflowInterface $bookStateMachine */
$bookStateMachine->getMarking($book); // Typed property must not be accessed before initialization
// current way that works
$initialMarking = new Marking();
foreach ($bookStateMachine>getDefinition()->getInitialPlaces() as $initialPlace) {
$initialMarking->mark($initialPlace);
}
$bookStateMachine->getMarkingStore()->setMarking($book, $initialMarking);
$book->getMarking(); // 'on_shelf'
// proposed way
$bookStateMachine->initialize($book);
$book->getMarking(); // 'on_shelf'