winzou / statemachinebundle Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
Version 0.3.1 claims to be Symfony4 compatible, but when running this version as a part of Symfony 3.4.9, I still get the following deprecation warning:
Auto-registration of the command "winzou\Bundle\StateMachineBundle\Command\winzouStateMachineDebugCommand" is deprecated since Symfony 3.4 and won't be supported in 4.0. Use PSR-4 based service discovery instead.
So was working with Sylius about a year ago really enjoyed your State Machine Bundle's implementation within in. I'm trying to incorporate it into my own project but am running into errors. I'm working with Symfony 4 and have an autowired service that's throwing a '$this not in object context' when I try to use it with the transition callback. But when I use the same service in a controller or command or something, it works fine. Thoughts? Is there a config setting somewhere I need to set?
Hi,
I've found myself in need to test if transitions is possible inside template, which is easily can be solved with twig extension like this.
<?php
namespace Acme\AppBundle\Twig;
use SM\Factory\FactoryInterface;
class StateMachineExtension extends \Twig_Extension
{
/**
* @var FactoryInterface
*/
protected $factory;
/**
* @param FactoryInterface $factory
*/
public function __construct(FactoryInterface $factory) {
$this->factory = $factory;
}
public function getFunctions()
{
return [
new \Twig_SimpleFunction('acme_statemachine_can', [$this, 'can']),
];
}
/**
* @param object $subject
* @param string $graph
* @param string $transition
*
* @return bool
*/
public function can($subject, $graph, $transition)
{
$stateMachine = $this->factory->get($subject, $graph);
return $stateMachine->can($transition);
}
public function getName()
{
return 'acme_statemachine_extension';
}
}
~
{% if acme_statemachine_can(payment, 'sylius_payment', 'complete') %}
{{ buttons.put(path('sylius_backend_payment_update_state', {'id': payment.id, 'transition': 'complete'}), 'Complete') }}
{% endif %}
Is this feature falls into bundles scope? If so, let me know and I would be glad to provide PR.
It would be nice to do so :)
Hello,
I was trying the new sylius 1.0.0@alpha and tried to disable a state and transitions but it seems that the way that configuration is parsed does not respect overrides and merge all together...
I created test and made a PR, tell me if it seems ok for you and i can create the code to respect this spec
I'd like to see a command line command that works a lot like the debug:event-dispatcher
command, where you supply a graph, a transition, and optionally before/after and it lists all of the callbacks, in order, just like the event dispatcher lists the event listeners. Does anyone else have any thoughts about this? IMO this is useful if your state-machines are configured in more that one config file and you want to see everything in one place. Thoughts? Suggestions?
I've always wondered why we need to instantiate a different state machine for each instantiated domain object, can't we just instantiate one state machine per class, per graph? So instead of doing $sm = $factory->get($object, 'graph-name')
for each domain object, you'd just do it once per CLASS and be able to pass instances of that class into the state machine asking it to transition the given object through a transition.
Here's the example of what I'm talking about:
$foos = [new Foo(), new Foo(), new Foo()];
$fooDefaultSM = $factory->get(current($foos), 'default') // First argument can also be a class name maybe?
foreach ($foos as $foo) {
if ($fooDefaultSM->can($foo, 'some-transition'))
$fooDefaultSM->apply($foo, 'some-transition);
}
}
Under the current implementation, you need to instantiate one SM per iteration of the loop (3 of them). Under the proposed interface, you'd only need one SM total.
Thoughts? Am I missing something?
Hi, maybe this is a stupid question. I was wondering if there is any easy way to share a graph.
Say I have 2 entities that follow the same state graph, which is pretty common in cms systems (draft, proposal, confirmed, published, etc).
I'd like to create a common flow that I could attach in configuration to each entity.
Is that possible?
Thx
Hello,
When you list possible transitions or use a can
function the transitions appear valid even if the guard says no. Is there a way to check for the guard without applying changes?
Can't find any doc about how to create multiple graphs for the same entity ? Tried to duplicate the conf from the graph property, but it throws a configuration error
Hello,
I just would like to know if it's possible to execute the same callback on multiple transitions like :
callbacks:
after:
create_invoice:
on: ['confirm', 'cashing_and_collection_of_goods']
do: [ "@app.infrastructure.state_handler.order.invoice", create ]
args: [ 'object' ]
i have tried to use this with https://github.com/Sylius/Sylius/pull/1426/files in view and others i found, however is not very clear
I am getting
) Vendor\UseCases\WorkflowTest::it_goes_through_the_whole_workflow
SM\SMException: Cannot create a state machine because the configuration
for object Vendor\Domain\ACase with graph vendor_transition does not exist.
I think it may be because i copied the state machine from sylius into my project and the configuration gets assigned in a weird way. Do you have any hint? maybe a doc cookbook would come handy to use this more. The specs don't tell us how to do it at the symfony level.
Does the latest version of this bundle 0.3.1 fully support Symfony 4?
I still got some autowiring issues:
Cannot autowire service "***\ProfileController": argument "$statemachine" of method "__construct()" references class "SM\Factory\Factory" but no such service exists. It cannot be auto-registered because it is from a different root namespace.
Maybe I have to include some configuration files?
Not sure what triggered it.. but I have seen it a few times.
Warning: strpos() expects parameter 1 to be string, object given in /Users/kayue/Sites/store/vendor/winzou/state-machine-bundle/Callback/ContainerAwareCallback.php on line 40
Call Stack:
0.0002 228976 1. {main}() /Users/kayue/Sites/store/app/console:0
0.0227 2780728 2. Symfony\Component\Console\Application->run() /Users/kayue/Sites/store/app/console:28
0.0252 2977504 3. Symfony\Bundle\FrameworkBundle\Console\Application->doRun() /Users/kayue/Sites/store/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php:121
0.2312 18938440 4. Symfony\Component\Console\Application->doRun() /Users/kayue/Sites/store/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Application.php:96
0.2338 18939856 5. Symfony\Component\Console\Application->doRunCommand() /Users/kayue/Sites/store/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php:191
0.2348 19019096 6. Symfony\Component\Console\Command\Command->run() /Users/kayue/Sites/store/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php:898
0.2351 19023440 7. Doctrine\Bundle\FixturesBundle\Command\LoadDataFixturesDoctrineCommand->execute() /Users/kayue/Sites/store/vendor/symfony/symfony/src/Symfony/Component/Console/Command/Command.php:244
1.7017 26742648 8. Doctrine\Common\DataFixtures\Executor\ORMExecutor->execute() /Users/kayue/Sites/store/vendor/doctrine/doctrine-fixtures-bundle/Doctrine/Bundle/FixturesBundle/Command/LoadDataFixturesDoctrineCommand.php:106
1.7017 26744080 9. Doctrine\ORM\EntityManager->transactional() /Users/kayue/Sites/store/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/ORMExecutor.php:85
1.7065 26938696 10. call_user_func() /Users/kayue/Sites/store/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:243
1.7065 26938784 11. Doctrine\Common\DataFixtures\Executor\ORMExecutor->Doctrine\Common\DataFixtures\Executor\{closure}() /Users/kayue/Sites/store/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:243
7.9412 62978464 12. Doctrine\Common\DataFixtures\Executor\AbstractExecutor->load() /Users/kayue/Sites/store/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/ORMExecutor.php:83
7.9417 62979544 13. Hypebeast\Bundle\CoreBundle\DataFixtures\ORM\LoadOrdersData->load() /Users/kayue/Sites/store/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/AbstractExecutor.php:121
25.0190 113213056 14. Hypebeast\Bundle\CoreBundle\DataFixtures\ORM\LoadOrdersData->setState() /Users/kayue/Sites/store/src/Hypebeast/Bundle/CoreBundle/DataFixtures/ORM/LoadOrdersData.php:75
25.3522 113775472 15. SM\StateMachine\StateMachine->apply() /Users/kayue/Sites/store/src/Hypebeast/Bundle/CoreBundle/DataFixtures/ORM/LoadOrdersData.php:96
25.3525 113777256 16. SM\StateMachine\StateMachine->callCallbacks() /Users/kayue/Sites/store/vendor/winzou/state-machine/src/SM/StateMachine/StateMachine.php:123
25.3526 113782952 17. SM\Callback\Callback->__invoke() /Users/kayue/Sites/store/vendor/winzou/state-machine/src/SM/StateMachine/StateMachine.php:204
25.3527 113783000 18. winzou\Bundle\StateMachineBundle\Callback\ContainerAwareCallback->call() /Users/kayue/Sites/store/vendor/winzou/state-machine/src/SM/Callback/Callback.php:77
25.3528 113783536 19. SM\Callback\Callback->call() /Users/kayue/Sites/store/vendor/winzou/state-machine-bundle/Callback/ContainerAwareCallback.php:46
25.3534 113812688 20. call_user_func_array() /Users/kayue/Sites/store/vendor/winzou/state-machine/src/SM/Callback/Callback.php:68
25.3535 113813368 21. SM\Callback\CascadeTransitionCallback->apply() /Users/kayue/Sites/store/vendor/winzou/state-machine/src/SM/Callback/Callback.php:68
25.3535 113814120 22. SM\StateMachine\StateMachine->apply() /Users/kayue/Sites/store/vendor/winzou/state-machine/src/SM/Callback/CascadeTransitionCallback.php:61
25.3538 113814488 23. SM\StateMachine\StateMachine->callCallbacks() /Users/kayue/Sites/store/vendor/winzou/state-machine/src/SM/StateMachine/StateMachine.php:123
25.3538 113814488 24. SM\Callback\Callback->__invoke() /Users/kayue/Sites/store/vendor/winzou/state-machine/src/SM/StateMachine/StateMachine.php:204
25.3539 113814536 25. winzou\Bundle\StateMachineBundle\Callback\ContainerAwareCallback->call() /Users/kayue/Sites/store/vendor/winzou/state-machine/src/SM/Callback/Callback.php:77
25.3539 113814632 26. strpos() /Users/kayue/Sites/store/vendor/winzou/state-machine-bundle/Callback/ContainerAwareCallback.php:40
The object is a SM\Callback\CascadeTransitionCallback
.
I will try to reproduce it in Sylius's master when I have time.
I @winzou , Just googling, I found this bundle. I'm surpised by your great job.
I was wondering if there is way to read the graph definition from my DB. I want to be able to create the states, transitions and callbacks from my front web app.
Doy you think there is a workaround ?
I appreciate your help.
would you please give an example?....i think one needs to use a callback but not sure if there is a method for cancelling the on going transition....
In Symfony 4.3, the following deprecation warning is thrown:
The "Symfony\Component\Config\Definition\Builder\TreeBuilder::root()" method called for the "winzou_state_machine" configuration is deprecated since Symfony 4.3, pass the root name to the constructor instead.
A fix for a similar issue can be seen here: FriendsOfSymfony/FOSMessageBundle@e0a0587
Hi there. Not an issue. Hope you don't mind i post the question here. I'm working with sylius and sylius used this bundle. In a sylius yml file you can see something like
winzou_state_machine:
sylius_order_checkout:
class: "%sylius.model.order.class%"
property_path: checkoutState
graph: sylius_order_checkout
state_machine_class: "%sylius.state_machine.class%"
...
callbacks:
after:
sylius_hold_inventory:
on: ["complete"]
do: ["@sylius.inventory.order_inventory_operator", "hold"]
args: ["object"]
My question is if i could add my own do
to that after sylius hold inventory
from my own bundle. I need that sylius still do its job, but i need to do some things... is this possible?
Hello,
Right now we can disable a callback via enabled: false
.
Wouldn't be awesome if we could put Expressions
using the ExpressionEngine instead of a boolean ?
Use case: feature flags
This way we could enable/disable callbacks with business logic instead of adding the logic itself inside the callback code wenever possible.
callbacks:
my_callback:
...
enabled: "object.getSettings().hasFeature('email_enabled')"
One of the last pull requests apparently made the bundle compatible with Symfony 5.
Would it be possible to officially check if the bundle is compatible, and if so tag a version with an amended composer.json to allow Symfony 5?
Thanks!
Hello,
I got this problem : You have requested a non-existent parameter "sylius.state_machine.class".
Using sylius 1.5 and symfony 4.3
Hi there,
It would be nice if the bundle could be compatible with the new php enum:
https://www.php.net/manual/fr/language.enumerations.basics.php
Here's some sample with the current doc:
<?php
namespace App\Enum;
enum ArticleStates: string
{
case NewArticle = 'new';
case PendingReview = 'pending_review';
//...
}
<?php
namespace App\Entity;
use App\Enum\ArticleStates;
class Article
{
/** @var ArticleStates */
private $state;
//...
public function getState() : ArticleStates
{
return $this->state;
}
public function setState(ArticleStates $state) : self
{
$this->state = $state;
return $this;
}
//...
}
Hi
I have next bundle version at my composer.lock
:
{
"name": "winzou/state-machine-bundle",
"version": "v0.3.1",
...
"require": {
...
"winzou/state-machine": "~0.3"
},
}
After doing composer update
- Updating winzou/state-machine (0.3.3 => 0.4.0): Downloading (100%)
I see
In ContainerAwareCallbackFactory.php line 35:
Compile Error: Declaration of winzou\Bundle\StateMachineBundle\Callback\Con
tainerAwareCallbackFactory::get(array $specs) must be compatible with SM\Ca
llback\CallbackFactory::get(array $specs): SM\Callback\CallbackInterface
I guess winzou/state-machine-bundle:v0.3.2
and winzou/state-machine-bundle:v0.4.3
should contain something like this (0.4.0+
excluded):
"require": {
...
"winzou/state-machine": "^0.3"
},
rather than ~0.3
This line:
throws an exception when a callback is set in the configuration. You assume the $callback['on']
is an array, though it can be a scalar string. At least it is a string in any example out there.
I have method "UpdateStateToPaymentProgress" inside controller
public function UpdateStateToPaymentProgress(Cart $cart, $state)
{
$dm = $this->getDocumentManager();
$cart->setState($state);
$dm->persist($cart);
$dm->flush();
}
This is my config file
(...)
transitions:
create:
from: [new]
to: created
payment:
from: [created]
to: progressPayment
(...)
callbacks:
# will be called after applying a transition
after:
progress_pay_cart:
on: 'payment'
do: [@application.cart.checkout, 'UpdateStateToPaymentProgress']
args: ['object', '"progressPayment"']
i define controller as service in service.yml
services:
application.cart.checkout:
class: Application\CartBundle\Controller\CheckoutController
the problem is when i call method $cartSM->apply('payment') , the entity dont change state, and the bundle dnt call method of controller.
FileLoaderLoadException: Cannot import resource "/var/www/app/src/App/MainBundle/DependencyInjection/../Resources/config/maquina-estado-ticket.yml" from "/var/www/app/src/App/MainBundle/DependencyInjection/../Resources/config/services.yml". (There is no extension able to load the configuration for "winzou_state_machine" (in /var/www/app/src/App/MainBundle/DependencyInjection/../Resources/config/maquina-estado-ticket.yml). Looked for namespace "winzou_state_machine", found none)
thx in advance
The "winzou\Bundle\StateMachineBundle\Command\winzouStateMachineDebugCommand" class extends "Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand" that is deprecated since Symfony 4.2, use {@see Command} instead.
I use sylius.
winzou_state_machine:
sylius_order_checkout:
class: "%sylius.model.order.class%"
property_path: checkoutState
graph: sylius_order_checkout
state_machine_class: "%sylius.state_machine.class%"
states:
cart: ~
addressed: ~
shipping_selected: ~
payment_selected: ~
completed: ~
transitions:
address:
from: [cart]
to: addressed
readdress:
from: [payment_selected, shipping_selected, addressed]
to: cart
select_shipping:
from: [addressed]
to: shipping_selected
reselect_shipping:
from: [payment_selected, shipping_selected]
to: addressed
select_payment:
from: [shipping_selected]
to: payment_selected
reselect_payment:
from: [payment_selected]
to: shipping_selected
complete:
from: [payment_selected]
to: completed
callbacks:
after:
sylius_process_cart:
on: ["address", "select_shipping"]
do: ["@sylius.order_processing.order_processor", "process"]
args: ["object"]
sylius_recalculate_cart:
on: ["address", "readdress", "select_shipping", "reselect_shipping", "select_payment", "reselect_payment"]
do: ["@sylius.order_processing.order_recalculator", "recalculate"]
args: ["object"]
sylius_create_order:
on: ["complete"]
do: ["@sm.callback.cascade_transition", "apply"]
args: ["object", "event", "'create'", "'sylius_order'"]
sylius_create_payment:
on: ["complete"]
do: ["@sm.callback.cascade_transition", "apply"]
args: ["object.getPayments()", "event", "'create'", "'sylius_payment'"]
sylius_request_shipping:
on: ["complete"]
do: ["@sm.callback.cascade_transition", "apply"]
args: ["object", "event", "'request_shipping'", "'sylius_order_shipping'"]
what is this @sm.callback.cascade_transition? i can't figure it out and its only one place in code
Is it possible to use integer constants as states?
For example:
<?php
namespace My\Bundle\Entity;
class Article
{
const STATE_NEW = 1;
const STATE_PENDING_REVIEW = 2;
const STATE_AWAITING_CHANGES = 3;
// ...
}
winzou_state_machine:
my_bundle_article:
class: My\Bundle\Entity\Article
property_path: state
graph: simple
states:
- My\Bundle\Entity\Article::STATE_NEW # ?
- My\Bundle\Entity\Article::STATE_PENDING_REVIEW # ?
- My\Bundle\Entity\Article::STATE_AWAITING_CHANGES # ?
# ...
Will be you interested on add tests to the bundle? Phpunit works for you?
Thanks.
Hello,
I'd like to trigger a service on the initial state (aka entity creation),
I know that I can do it without the state machine, with an event listener, but I feel like the whole point of the state machine is to not use classical event listener, so it seems odd to me to have to use them on this first stage.
How should I do in this use case ? use an event, or use this (awesome) tool in a way that I didn't imagined?
Thanks by advance,
Bruno (a huge fan of winzou and his awesome symfony MOOC on openclassroom)
Hello, I don't know if this is possible, but would to know if is possible get the next state before apply the transition.
hi,
i have a question on how to pass extra arguments when using callbacks, like i have the follow configuration:
callbacks:
after:
sylius_process_cart:
on: ["select_shipping", "address", "select_payment", "skip_shipping", "skip_payment"]
do: ["@sylius.order_processing.order_processor", "process"]
args: ["object"]
then, in the args field i want to add another args(is an object), pls tell me how can i finish this operation? thx.
Hello,
one thing i am always missing is something like a visual presentations of the states like this state diagram
As i have some complex machines with 10+ states and therefore lots of transitions, this would help me to better understand and explain the machine to another person. Is there something which you evaluated? It could for example be used for automated document generation.
Here some sources as reference:
Here is an example based on your graph
digraph finite_state_machine {
rankdir=LR;
size="8,5"
node [shape = doublecircle]; new;
node [shape = point ]; qi
node [shape = circle];
qi -> new;
new -> pending_review [ label = "create" ];
pending_rewiew -> awaiting_changes [ label = "ask for changes" ];
pending_review -> accepted [ label = "approve" ];
awaiting_changes -> pending_review [ label = "submit review" ];
rejected -> accepted [ label = "approve" ];
accepted -> published [label = "publish"]
accepted -> awaiting_changes [ label = "ask for changes" ];
}
dot -Tpng gv-file.gv -o myFiniteStateMachine.png
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.