-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[POC] [Workflow] Made StateMachine supports only single state marking #20491
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
This prevents using any other custom implementation of the MarkingStore return astate with a single place, so -1 for that. |
Maybe we could think about introducing dedicated marker interfaces for marking stores that support or do not support multiple states at the same time. |
Ok I think I've got an idea. Status: needs work |
Ok I've updated the PR and the description, I'm finishing some tests, but this is ready to review as POC. Maybe it will inspire someone for something better :) |
* @param object $subject A subject | ||
* @param SingleStateMarking $marking | ||
* | ||
* @return SingleStateMarking The marking |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setters have no reason to return the marking (the return value is ignored anyway)
return; | ||
} | ||
|
||
$this->places[$place] = $this->places[$place] + 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+= 1
or ++
@@ -30,6 +30,14 @@ public function add(Workflow $workflow, $className) | |||
$this->workflows[] = array($workflow, $className); | |||
} | |||
|
|||
/** | |||
* @param $subject | |||
* @param null $workflowName |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wrong phpdoc
if ($place) { | ||
$this->mark($place); | ||
} else { | ||
$this->place = array(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
useless as the property is already initialized
@lyrixx could you have a look at this one ? |
@stof thank you for your comments, they're now addressed, This can be very powerful to handle votes, or deal with weighted places in events. I'm gonna add an event by default for workflow to guard if more than 1. Wdyt? |
Reviewing my code on GH, I think it might be worth having |
39ae224
to
08dbffb
Compare
08dbffb
to
7c47114
Compare
I've updated this PR so it has only one clean commit and a better description. Status: needs review |
Failures unrelated. |
class SingleStateMarking extends Marking | ||
{ | ||
/** | ||
* @param mixed $place A scalar as only place or null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be string|null
public function __construct($place = null) | ||
{ | ||
if (null !== $place && !is_scalar($place)) { | ||
throw new InvalidArgumentException(sprintf('"%s" instances only accept scalar or null as single place, but got "%s".', __CLASS__, is_object($place) ? get_class($place) : gettype($place))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure this safeguard is actually needed.
throw new InvalidArgumentException(sprintf('"%s" instances only accept scalar or null as single place, but got "%s".', __CLASS__, is_object($place) ? get_class($place) : gettype($place))); | ||
} | ||
|
||
if ($place) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be if(null !== $place) {
} elseif (isset($workflow['marking_store']['service'])) { | ||
$markingStoreDefinition = new Reference($workflow['marking_store']['service']); | ||
|
||
$markingStrategy = 'state_machine' === $type ? 'single_state' : $workflow['marking_store']['type']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$markingStrategy = 'state_machine' === $type ? Marking::STRATEGY_SINGLE_STATE : Marking::STRATEGY_MULTIPLE_STATE;
?
*/ | ||
public function __construct($expectedClass, $marking) | ||
{ | ||
$this->message = sprintf('Marking must be an instance of "%", but got "%"', $expectedClass, is_object($marking) ? get_class($marking) : gettype($marking)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
parent::__construct(...)
{ | ||
private $places = array(); | ||
const STRATEGY_SINGLE_STATE = 'single_state'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These constants belong to the MarkingStore
class imo.
*/ | ||
class Marking | ||
abstract class Marking |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure this class is really needed.. why not a pointer interface and 2 final implementations instead?
Hello @HeahDude I understand why you made this PR and I agree a pitfall may exist for newcomers. But I don't like your current implementation: 1/ There are too many code added, it adds too many complexity It could be solved in the full stack framework in a simpler way: just check the framework type with the type marking store type. I don't implemented what I said, because it's not perfect and because the default configuration is error proof. If you can find a much simpler solution to implement this kind of validation in the composant, I will be glad to merge it. but for now I'm -1 |
@lyrixx I understand. Thank you for your feedback, I'll try to look at it again with this in mind :) |
I'll come with something else :) Status: needs work |
I'm sorry, but I have to close this PR as the current implementation is too complex |
Since StateMachine cannot be in one place at the time it does not make sense to allow multiple marking. Actually we default to the right SingleStateMarkingStore, but we can't prevent it with any interface.
This PR makes
Marking
andMarkingStore
abstract so any implementation can use the component mechanisms by defining a marking strategy usingMarking
constants in theMarkingStore
constructor.Hence we need two marking classes
SingleStateMarking
andMultipleStateMarking
so every internal piece of the workflow knows how to behave regarding marking.Also we only need one
PropertyAccessMarkingStore
which use the same decency for its logic but can handle both strategies.Most of the abstract class are public and can easily be overridden.
Wdyt?