Git Product home page Git Product logo

laravel-workflow's People

Contributors

brexis avatar dependabot[bot] avatar dshafik avatar eudj1n avatar github-actions[bot] avatar j2l4e avatar juliangums avatar laravel-shift avatar laurenkt avatar lguima avatar makroxyz avatar nasrulhazim avatar psmeets-devnl avatar rachediabdenacer avatar riley19280 avatar soap avatar squarezhou avatar symplworks avatar uniconstructor avatar zerodahero avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

laravel-workflow's Issues

Incorrect announce events

Hi,

please review this issue with Symfony. Problem details are already explained there.

In review - they have inspected my bug report and could not reproduce it in vanilla Symfony install so their best guess is that the problem is in our event dispatcher. Could you please check?

Use in tracking mode

I tried to use the tracking mode but it still read from the config files , please what is the correct way to use it
Screen Shot 2020-06-01 at 11 56 38 PM
Screen Shot 2020-06-02 at 12 00 42 AM

"The method "App\Models\BlogPost::getMarking()" does not exist."

Hello,

I use your workflow config file example (be careful, 2 comma are missing). and other fields example.
I have the message :

"The method "App\Models\BlogPost::getMarking()" does not exist." when I do that :

   $post = BlogPost::find(1);
    $workflow = $post->workflow_get();
    $marking = $workflow->getMarking($post);

The property is 'currentPlace' in the config file but in the workflow, I show it is "marking"

    $post = BlogPost::find(1);
    $workflow = $post->workflow_get();
    dd($workflow);

-markingStore: Symfony\Component\Workflow\MarkingStore\MethodMarkingStore {#364
-singleState: false
-property: "marking"
}
-dispatcher: Symfony\Component\EventDispatcher\EventDispatcher {#331 …3}
-name: "straight"
}

I have a field 'currentPlace in my database, I added another field ('marking') but I have always the same error message .

What is the full path of "use Workflow ;" ? I think my app don't find the good way.

I use Laravel 7. It use symfony workflow 5.0.,

Applying a workflow that features a place in multiple transitions - all guards related to place execute

I am wondering whether this behaviour is intentional. I have been debugging an issue in my project and I noticed that when applying a workflow like so:

$this->workflow_apply('prepare', 'order_shipping_states_graph');

Whereby the workflow has defined:

'prepare' => [
'from' => [ 'ready', 'being_prepared'] 
'to' => ['being_prepared']
],
'pick' => [
from => ['being_prepared']
 to => ['ready_to_ship']
]

Then both guardPrepare and guardPick are being executed in the respective workflow subscriber.

I would expect that since there is the transition specified, then only that guard would execute.

Marking store with MorphToMany

Hi,

That's perhaps a little linked with #12 ...

In my application, Post objects are associated to some statuses thanks to a MorphToMany relationship (since not only Post can have statuses, but many other objects).

So I was thinking it is a little redondant to define a "marking" field on my Post model whereas the information already exists in a pivot table (morphToMany) ...
That's when the marking_store like a method could be interesting

'marking_store' => [
                'type' => 'method'
                'property' => 'status'
            ],

and on the Post model I would imagine the two getter and setter (à la Symfony)

public function getStatus(){
    return $this->statusable()->first();
}

public function setStatus($status){
    return $this->statusable()->sync($status)
}

But if I write this ticket, it is above all to see if you had other ideas to suggest to me for this problem?

Thanks

Announce events not fired

Hi,

I have the following test model:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use ZeroDaHero\LaravelWorkflow\Traits\WorkflowTrait;

class Test extends Model
{
    use HasFactory;
    use WorkflowTrait;

    protected $table = 'test';

    protected $casts = [
        'marking' => 'array',
    ];


}

Workflow:

'test' => [
        'type' => 'workflow',
        // 'marking_store' => [
        //     'type' => 'multiple_state',
        // ],
        'supports' => [
            Test::class,
        ],

        'events_to_dispatch' => [
            'workflow.announce',
        ],

        'places' => [
            'a', 'b', 'c',
        ],

        'initial_places' => [
            'a',
        ],

        'transitions' => [
            't1' => [
                'from' => 'a',
                'to' => 'b'
            ],
            't2' => [
                'from' => 'b',
                'to' => 'c'
            ],

        ],
    ];

Event subscriber:

<?php

namespace App\Listeners;

use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;
use Symfony\Component\Workflow\Event\AnnounceEvent;
use ZeroDaHero\LaravelWorkflow\Events\GuardEvent;

class TestSubscriber implements ShouldQueue
{

    public function handleAnnounce($type, $event)
    {
        Log::debug('* Received Event: ' . $type);

        Log::debug(gettype($event));
    }


    public function subscribe($events)
    {
        $events->listen(
            'workflow.test.*',
            [TestSubscriber::class, 'handleAnnounce']
        );
    }
}

And the following testing code:

        Log::debug('---');
        $test = new Test();

        Log::debug('Checking transition t1: ' . $test->workflow_can('t1'));
        Log::debug('Current marking: ' . $test->marking);

        foreach ($test->workflow_transitions() as $transition) {
            Log::debug('Enabled Transition: ' . $transition->getName());
        }

        Log::debug('Applying transition t1:');
        $marking = $test->workflow_apply('t1');

        return 0;

What I expect is to receive the event somehow so I can process it.

All of the above was discovered when I am trying to receive Announce events, in order to make automatic transitions when possible. So far I have discovered that they are not fired at all. This is issue 1.

According to current documentation, the handler in subscriber should receive Event as first argument.
Actually it receives Event only in the case when subscriber is subscribed to ZeroDaHero Events.
If subscribed to Symfony dot-style events (as in the example above), function receives string containing the event name and second parameter of type array, that contains dump of the ZeroDaHero Event. This is issue 2.

I believe this is related to latest changes in Symfony/Workflow 5.2.

here is the debug information from above code:

[2021-01-21 16:22:57] local.DEBUG: ---  
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.entered  
[2021-01-21 16:22:57] local.DEBUG: array  
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.guard  
[2021-01-21 16:22:57] local.DEBUG: array  
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.guard.t1  
[2021-01-21 16:22:57] local.DEBUG: array  
[2021-01-21 16:22:57] local.DEBUG: Checking transition t1: 1  
[2021-01-21 16:22:57] local.DEBUG: Current marking: a  
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.guard  
[2021-01-21 16:22:57] local.DEBUG: array  
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.guard.t1  
[2021-01-21 16:22:57] local.DEBUG: array  
[2021-01-21 16:22:57] local.DEBUG: Enabled Transition: t1  
[2021-01-21 16:22:57] local.DEBUG: Applying transition t1:  
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.guard  
[2021-01-21 16:22:57] local.DEBUG: array  
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.guard.t1  
[2021-01-21 16:22:57] local.DEBUG: array  
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.leave  
[2021-01-21 16:22:57] local.DEBUG: array  
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.leave.a  
[2021-01-21 16:22:57] local.DEBUG: array  
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.transition  
[2021-01-21 16:22:57] local.DEBUG: array  
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.transition.t1  
[2021-01-21 16:22:57] local.DEBUG: array  
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.enter  
[2021-01-21 16:22:57] local.DEBUG: array  
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.enter.b  
[2021-01-21 16:22:57] local.DEBUG: array  
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.entered  
[2021-01-21 16:22:57] local.DEBUG: array  
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.entered.b  
[2021-01-21 16:22:57] local.DEBUG: array  
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.completed  
[2021-01-21 16:22:57] local.DEBUG: array  
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.completed.t1  
[2021-01-21 16:22:57] local.DEBUG: array  
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.guard  
[2021-01-21 16:22:57] local.DEBUG: array  
[2021-01-21 16:22:57] local.DEBUG: * Received Event: workflow.test.guard.t2  
[2021-01-21 16:22:57] local.DEBUG: array  
    "symfony/workflow": "^5.2",
    "zerodahero/laravel-workflow": "^3.2"

Event issuance triples

Hello I am testing the library to make an integration, in which I intend to save all the transactions performed in the flow. But I got an unexpected behavior, and it is that when I listen to the onCompleted event, it is called three times.

This would be problematic because it would duplicate the records by three.

I have checked the code to see if I can contribute, but I don't see the problem.

workflow.php

<?php

use App\Models\Document;

return [
    'document_management' => [
        'type' => 'state_machine',
        'marking_store' => [
            'type' => 'single_state',
            'property' => 'workflow',
        ],
        'supports' => [
            Document::class
        ],
        'places' => [
            'draft',
            'review',
            'rejected',
            'published'
        ],
        'transitions' => [
            'to_review' => [
                'from' => 'draft',
                'to' => 'review',
                'metadata' => [
                    'priority' => 0.5,
                ]
            ],
            'publish' => [
                'from' => 'review',
                'to' => 'published'
            ],
            'reject' => [
                'from' => 'review',
                'to' => 'rejected'
            ]
        ],
        'events_to_dispatch' => [
           Symfony\Component\Workflow\WorkflowEvents::LEAVE,
        ],
    ],
];

DocumentWorkflowSubscribe.php

<?php

namespace App\Listeners;

use ZeroDaHero\LaravelWorkflow\Events\LeaveEvent;

class DocumentWorkflowSubscriber
{
    /**
     * Handle workflow entered event.
     */
    public function onLeave(LeaveEvent $event) {

        $subject = $event->getSubject();

        var_dump($subject->workflow);
    }

    /**
     * Register the listeners for the subscriber.
     *
     * @param  Illuminate\Events\Dispatcher  $events
     */
    public function subscribe(\Illuminate\Events\Dispatcher $events)
    {
        $events->listen(LeaveEvent::class, [DocumentWorkflowSubscriber::class, 'onLeave']);
    }
}

Tinker shell

>>> $document->workflow_apply('to_review');
/var/www/html/app/Listeners/DocumentWorkflowSubscriber.php:16:
string(5) "draft"
/var/www/html/app/Listeners/DocumentWorkflowSubscriber.php:16:
string(5) "draft"
/var/www/html/app/Listeners/DocumentWorkflowSubscriber.php:16:
string(5) "draft"
=> Symfony\Component\Workflow\Marking {#4443}
>>>

Argument 1 passed to Symfony\Component\Workflow\Marking::__construct() must be of the type array, string given

Trying to get model transitions:

$transitions = $model->workflow_transitions();

But it's throwing an error. Here is my setup

config/workflow.php

return [
    'requisitions' => [
        'type' => 'workflow',
        'metadata' => [
            'title' => 'Requisition Workflow',
        ],
        'marking_store' => [
            'type'      => 'multiple_state',
            'arguments' => ['status'],
        ],
        'supports' => ['App\Models\WorkOrder'],
        'initial_marking' => 'draft',
        'places' => ['draft', 'pending', 'quotation', 'procurement', 'lpo', 'declined'],
        'transitions' => [
            'submit' => [
                'from' => 'draft',
                'to' => 'pending',
            ],
            'approve-work-orders-quotation' => [
                'from' => 'pending',
                'to' => 'quotation',
            ],
            'approve-work-orders-procurement' => [
                'from' => 'quotation',
                'to' => 'procurement',
            ],
            'generate-work-orders-lpo' => [
                'from' => 'procurement',
                'to' => 'lpo',
            ],
            'reject-work-order' => [
                'from' => 'procurement',
                'to' => 'declined',
            ],
        ],
    ]
];

What am I doing wrong?

define workflow inside model class

Is it possible to define the workflow inside the model?

I'm currently executing

Workflow::get($post, $workflowName);

Is it possible to do something like this

$post->workflow_get($workflowName)
$post->refresh();

This way I don't have to load Workflow into the controller, and just the model itself.

Multiple dispatching (3 times exactly) of a same event

I am facing multiple dispatching (3 times exactly) of a same event when using workflow_apply() method.

I'm using version 3.3.3 and here is the config of my workflow.

use App\Constants\UserTypes;
use App\Models\Factor;

'factor_wf'  => [
        'type'           => 'state_machine',
        'marking_store'  => [
            'type'     => 'single_state',
            'property' => 'status',
        ],
        'supports'       => [Factor::class],
        'places'         => ['open', 'submit'],
        'initial_places' => ['open'],
        'transitions'    => [
            'to_submit_by_State'   => [
                'from'     => 'open',
                'to'       => 'submit',
                'metadata' => [
                    'permission' => UserTypes::getWorkflowPermission(UserTypes::State),
                ],
            ],
    ]
]

Here is the subscriber.

use ZeroDaHero\LaravelWorkflow\Events\CompletedEvent;

class FactorWorkflowSubscriber
{
    public function onCompleted(CompletedEvent $event)
    {
        if ($event->getWorkflowName() == 'factor_wf') {
            (new HandleFactorWorkflow($event->getOriginalEvent()))->handle();
        }
    }

    public function subscribe($events)
    {
        return [
            CompletedEvent::class => 'onCompleted',
        ];
    }
}

Note that when I use workflow.completed instead of CompleteEvent namespace, it resolves and I don't get repetitive dispatching.

This issue is a continuation of this.

Dependency injection in listeners

Hello,

I have tried to define a listener with second parameter of arbitrary type, using dependency injection.
Attempt to call it fails because the listener function is called with one parameter only (the type of Event).

is it possible to add support for dependency injection?

How subscribe to event

Hello,

I know event and listener with laravel, but I don't understand how use BlogPostWorkflowSubscriber.
How to subscribe to call onleave function for example.
Could someone give a full example, please ?

Fabien

A understandable Example

Hi,

Is there Example project for creating workflow engine in laravel via this package Like This for symfony ?

Symfony project Demo

I don't understand how to use state machine and events .

Thanks For great Supports.

laravel 6 issue

composer require zerodahero/laravel-workflow:2.1.0
gives me this for Laravel 6

Package manifest generated successfully.

@php artisan ide-helper:generate

Symfony\Component\Debug\Exception\FatalThrowableError : Argument 1 passed to ZeroDaHero\LaravelWorkflow\WorkflowRegistry::__construct() must be of the type array, null given, called in \laravel_test\vendor\zerodahero\laravel-workflow\src\WorkflowServiceProvider.php on line 48

at \laravel_test\vendor\zerodahero\laravel-workflow\src\WorkflowRegistry.php:59
55| * @param array $config
56| * @param array $registryConfig
57| * @throws \ReflectionException
58| */

59| public function __construct(array $config, array $registryConfig = null)
60| {
61| $this->registry = new Registry();
62| $this->config = $config;
63| $this->registryConfig = $registryConfig ?? $this->getDefaultRegistryConfig();

Exception trace:

1 ZeroDaHero\LaravelWorkflow\WorkflowRegistry::__construct([])
\laravel_test\vendor\zerodahero\laravel-workflow\src\WorkflowServiceProvider.php:48

2 ZeroDaHero\LaravelWorkflow\WorkflowServiceProvider::ZeroDaHero\LaravelWorkflow{closure}(Object(Illuminate\Foundation\Application), [])
\laravel_test\vendor\laravel\framework\src\Illuminate\Container\Container.php:799

Please use the argument -v to see more details.
Script @php artisan ide-helper:generate handling the post-autoload-dump event returned with error code 1

Installation failed, reverting ./composer.json to its original content.

getMarking

Hi, can you help me?

$workflow = Workflow::get($order, 'order'); //works
$m = $workflow->getMarking($order); //raises an error

"message": "Argument 1 passed to Symfony\Component\Workflow\Marking::__construct() must be of the type array, string given, called in /app/vendor/zerodahero/laravel-workflow/src/MarkingStores/EloquentMarkingStore.php on line 44",
"exception": "TypeError",
"file": "/app/vendor/symfony/workflow/Marking.php",
"line": 26,
"trace": [
{
"file": "/app/vendor/zerodahero/laravel-workflow/src/MarkingStores/EloquentMarkingStore.php",
"line": 44,
"function": "__construct",
"class": "Symfony\Component\Workflow\Marking",
"type": "->"
},
{

Unserialize error

Hi again,

I have stumbled upon this error:

[2021-02-06 17:02:46] local.ERROR: unserialize(): Error at offset 3683 of 3922 bytes {"exception":"[object] (ErrorException(code: 0): unserialize(): Error at offset 3683 of 3922 bytes at /Users/sag/Dropbox/code/api_v3/vendor/zerodahero/laravel-workflow/src/Events/BaseEvent.php:56)
[stacktrace]
#0 [internal function]: Illuminate\\Foundation\\Bootstrap\\HandleExceptions->handleError(8, 'unserialize(): ...', '/Users/sag/Drop...', 56, Array)
#1 /Users/sag/Dropbox/code/api_v3/vendor/zerodahero/laravel-workflow/src/Events/BaseEvent.php(56): unserialize('O:37:\"Modules\\\\B...')
#2 [internal function]: ZeroDaHero\\LaravelWorkflow\\Events\\BaseEvent->unserialize('a:5:{s:16:\"base...')
#3 /Users/sag/Dropbox/code/api_v3/vendor/cloudcreativity/laravel-json-api/src/Queue/UpdateClientProcess.php(64): unserialize('O:36:\"Illuminat...')
#4 /Users/sag/Dropbox/code/api_v3/vendor/cloudcreativity/laravel-json-api/src/Queue/UpdateClientProcess.php(37): CloudCreativity\\LaravelJsonApi\\Queue\\UpdateClientProcess->deserialize(Object(Illuminate\\Queue\\Jobs\\RedisJob))
#5 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(412): CloudCreativity\\LaravelJsonApi\\Queue\\UpdateClientProcess->handle(Object(Illuminate\\Queue\\Events\\JobFailed))
#6 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(237): Illuminate\\Events\\Dispatcher->Illuminate\\Events\\{closure}('Illuminate\\\\Queu...', Array)
#7 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Jobs/Job.php(195): Illuminate\\Events\\Dispatcher->dispatch('Illuminate\\\\Queu...')
#8 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(544): Illuminate\\Queue\\Jobs\\Job->fail(Object(ErrorException))
#9 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(505): Illuminate\\Queue\\Worker->failJob(Object(Illuminate\\Queue\\Jobs\\RedisJob), Object(ErrorException))
#10 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(433): Illuminate\\Queue\\Worker->markJobAsFailedIfWillExceedMaxAttempts('redis', Object(Illuminate\\Queue\\Jobs\\RedisJob), 1, Object(ErrorException))
#11 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(410): Illuminate\\Queue\\Worker->handleJobException('redis', Object(Illuminate\\Queue\\Jobs\\RedisJob), Object(Illuminate\\Queue\\WorkerOptions), Object(ErrorException))
#12 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(356): Illuminate\\Queue\\Worker->process('redis', Object(Illuminate\\Queue\\Jobs\\RedisJob), Object(Illuminate\\Queue\\WorkerOptions))
#13 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(307): Illuminate\\Queue\\Worker->runJob(Object(Illuminate\\Queue\\Jobs\\RedisJob), 'redis', Object(Illuminate\\Queue\\WorkerOptions))
#14 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(116): Illuminate\\Queue\\Worker->runNextJob('redis', 'bsms', Object(Illuminate\\Queue\\WorkerOptions))
#15 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(100): Illuminate\\Queue\\Console\\WorkCommand->runWorker('redis', 'bsms')
#16 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(36): Illuminate\\Queue\\Console\\WorkCommand->handle()
#17 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Container/Util.php(40): Illuminate\\Container\\BoundMethod::Illuminate\\Container\\{closure}()
#18 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(93): Illuminate\\Container\\Util::unwrapIfClosure(Object(Closure))
#19 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(37): Illuminate\\Container\\BoundMethod::callBoundMethod(Object(Illuminate\\Foundation\\Application), Array, Object(Closure))
#20 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Container/Container.php(610): Illuminate\\Container\\BoundMethod::call(Object(Illuminate\\Foundation\\Application), Array, Array, NULL)
#21 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Console/Command.php(136): Illuminate\\Container\\Container->call(Array)
#22 /Users/sag/Dropbox/code/api_v3/vendor/symfony/console/Command/Command.php(256): Illuminate\\Console\\Command->execute(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Illuminate\\Console\\OutputStyle))
#23 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Console/Command.php(121): Symfony\\Component\\Console\\Command\\Command->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Illuminate\\Console\\OutputStyle))
#24 /Users/sag/Dropbox/code/api_v3/vendor/symfony/console/Application.php(971): Illuminate\\Console\\Command->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#25 /Users/sag/Dropbox/code/api_v3/vendor/symfony/console/Application.php(290): Symfony\\Component\\Console\\Application->doRunCommand(Object(Illuminate\\Queue\\Console\\WorkCommand), Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#26 /Users/sag/Dropbox/code/api_v3/vendor/symfony/console/Application.php(166): Symfony\\Component\\Console\\Application->doRun(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#27 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Console/Application.php(93): Symfony\\Component\\Console\\Application->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#28 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(129): Illuminate\\Console\\Application->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#29 /Users/sag/Dropbox/code/api_v3/artisan(37): Illuminate\\Foundation\\Console\\Kernel->handle(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#30 {main}

[previous exception] [object] (ErrorException(code: 0): unserialize(): Error at offset 3683 of 3922 bytes at /Users/sag/Dropbox/code/api_v3/vendor/zerodahero/laravel-workflow/src/Events/BaseEvent.php:56)
[stacktrace]
#0 [internal function]: Illuminate\\Foundation\\Bootstrap\\HandleExceptions->handleError(8, 'unserialize(): ...', '/Users/sag/Drop...', 56, Array)
#1 /Users/sag/Dropbox/code/api_v3/vendor/zerodahero/laravel-workflow/src/Events/BaseEvent.php(56): unserialize('O:37:\"Modules\\\\B...')
#2 [internal function]: ZeroDaHero\\LaravelWorkflow\\Events\\BaseEvent->unserialize('a:5:{s:16:\"base...')
#3 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php(95): unserialize('O:36:\"Illuminat...')
#4 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php(251): Illuminate\\Queue\\CallQueuedHandler->getCommand(Array)
#5 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Jobs/Job.php(213): Illuminate\\Queue\\CallQueuedHandler->failed(Array, Object(ErrorException), '7dada2bb-c2f3-4...')
#6 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Jobs/Job.php(192): Illuminate\\Queue\\Jobs\\Job->failed(Object(ErrorException))
#7 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(544): Illuminate\\Queue\\Jobs\\Job->fail(Object(ErrorException))
#8 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(505): Illuminate\\Queue\\Worker->failJob(Object(Illuminate\\Queue\\Jobs\\RedisJob), Object(ErrorException))
#9 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(433): Illuminate\\Queue\\Worker->markJobAsFailedIfWillExceedMaxAttempts('redis', Object(Illuminate\\Queue\\Jobs\\RedisJob), 1, Object(ErrorException))
#10 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(410): Illuminate\\Queue\\Worker->handleJobException('redis', Object(Illuminate\\Queue\\Jobs\\RedisJob), Object(Illuminate\\Queue\\WorkerOptions), Object(ErrorException))
#11 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(356): Illuminate\\Queue\\Worker->process('redis', Object(Illuminate\\Queue\\Jobs\\RedisJob), Object(Illuminate\\Queue\\WorkerOptions))
#12 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(307): Illuminate\\Queue\\Worker->runJob(Object(Illuminate\\Queue\\Jobs\\RedisJob), 'redis', Object(Illuminate\\Queue\\WorkerOptions))
#13 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(116): Illuminate\\Queue\\Worker->runNextJob('redis', 'bsms', Object(Illuminate\\Queue\\WorkerOptions))
#14 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(100): Illuminate\\Queue\\Console\\WorkCommand->runWorker('redis', 'bsms')
#15 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(36): Illuminate\\Queue\\Console\\WorkCommand->handle()
#16 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Container/Util.php(40): Illuminate\\Container\\BoundMethod::Illuminate\\Container\\{closure}()
#17 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(93): Illuminate\\Container\\Util::unwrapIfClosure(Object(Closure))
#18 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(37): Illuminate\\Container\\BoundMethod::callBoundMethod(Object(Illuminate\\Foundation\\Application), Array, Object(Closure))
#19 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Container/Container.php(610): Illuminate\\Container\\BoundMethod::call(Object(Illuminate\\Foundation\\Application), Array, Array, NULL)
#20 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Console/Command.php(136): Illuminate\\Container\\Container->call(Array)
#21 /Users/sag/Dropbox/code/api_v3/vendor/symfony/console/Command/Command.php(256): Illuminate\\Console\\Command->execute(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Illuminate\\Console\\OutputStyle))
#22 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Console/Command.php(121): Symfony\\Component\\Console\\Command\\Command->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Illuminate\\Console\\OutputStyle))
#23 /Users/sag/Dropbox/code/api_v3/vendor/symfony/console/Application.php(971): Illuminate\\Console\\Command->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#24 /Users/sag/Dropbox/code/api_v3/vendor/symfony/console/Application.php(290): Symfony\\Component\\Console\\Application->doRunCommand(Object(Illuminate\\Queue\\Console\\WorkCommand), Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#25 /Users/sag/Dropbox/code/api_v3/vendor/symfony/console/Application.php(166): Symfony\\Component\\Console\\Application->doRun(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#26 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Console/Application.php(93): Symfony\\Component\\Console\\Application->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#27 /Users/sag/Dropbox/code/api_v3/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(129): Illuminate\\Console\\Application->run(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#28 /Users/sag/Dropbox/code/api_v3/artisan(37): Illuminate\\Foundation\\Console\\Kernel->handle(Object(Symfony\\Component\\Console\\Input\\ArgvInput), Object(Symfony\\Component\\Console\\Output\\ConsoleOutput))
#29 {main}
"} 

I am trying to process Queued subscriber the same way as I have already did with many others. But for some reason only this subscriber is failing. There is nothing different in model, workflow definition, nor subscriber. I have recorded the serialized data in BaseEvent and then manually unserialized it without problem.

Processing the events in synchronous manner does not reproduce the problem (removing implements ShouldQueue from subscriber definition) but I want to process it in queue.

Can you help? I am sure something is different and I am overlooking it, but I can't find the problem by myself.

workflow definition:

    'bsmsDlrOutgoing' => [
        'supports' => [
            OutgoingDlr::class,
        ],
        'places' => [
            'new',
            'processing',
        ],
        'initial_places' => [
            'new'
        ],
        'transitions' => [
            'toProcessing' => [
                'from' => 'new',
                'to' => 'processing',
            ],
        ],
    ],

model definition:

<?php

namespace Modules\BSMS\Entities\Cdr;

use Illuminate\Database\Eloquent\Model;
use Modules\BSMS\Entities\Route\Provider\Provider;
use ZeroDaHero\LaravelWorkflow\Traits\WorkflowTrait;

class OutgoingDlr extends Model
{
    use WorkflowTrait;

    protected $table = 'api_v3_bsms.cdr_out_dlr';

    protected $fillable = [
        'data',
    ];

    protected $casts = [
        'marking' => 'array',
        'data' => 'array',
    ];

    public function message()
    {
        return $this->belongsTo(Outgoing::class, 'cdr_out_id');
    }

    public function provider()
    {
        return $this->belongsTo(Provider::class, 'provider_id');
    }
}

subscriber:

<?php

namespace Modules\BSMS\Listeners;

use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Events\Dispatcher;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;
use ZeroDaHero\LaravelWorkflow\Events\EnteredEvent;

class OutgoingDlrAsyncSubscriber implements ShouldQueue
{
    use InteractsWithQueue;

    public $queue = 'bsms';
    public $tries = 1;
    public $maxExceptions = 1;
    public $timeout = 20;

    public function anyAny($name, array $payload)
    {
        Log::debug('Received event: ' . $name);

        // $event = $payload[0];
        // $subject = $event->getSubject();
    }

    public function enteredProcessing(EnteredEvent $event)
    {
        $subject = $event->getSubject();
        $subject->save();
    }

    public function subscribe(Dispatcher $events)
    {
        $events->listen('workflow.bsmsDlrOutgoing.*.*', [self::class, 'anyAny']);
        // $events->listen('workflow.bsmsDlrOutgoing.entered.processing', [self::class, 'enteredProcessing']);

    }
}

Laravel 6 not working

Your requirements could not be resolved to an installable set of packages.

Problem 1
- Conclusion: remove laravel/framework v6.18.3
- Conclusion: don't install laravel/framework v6.18.3
- litepie/workflow 1.0.0 requires illuminate/console 5.6.* -> satisfiable by laravel/framework[5.6.x-dev], illuminate/console[5.6.x-dev, v5.6.0, v5.6.1, v5.6.10, v5.6.11, v5.6.12, v5.6.13, v5.6.14, v5.6.15, v5.6.16, v5.6.17, v5.6.19, v5.6.2, v5.6.20, v5.6.21, v5.6.22, v5.6.23, v5.6.24, v5.6.26, v5.6.27, v5.6.28, v5.6.29, v5.6.3, v5.6.30, v5.6.31, v5.6.32, v5.6.33, v5.6.34, v5.6.35, v5.6.36, v5.6.37, v5.6.38, v5.6.39, v5.6.4, v5.6.5, v5.6.6, v5.6.7, v5.6.8, v5.6.9].
- litepie/workflow 1.0.x-dev requires illuminate/console 5.6.* -> satisfiable by laravel/framework[5.6.x-dev], illuminate/console[5.6.x-dev, v5.6.0, v5.6.1, v5.6.10, v5.6.11, v5.6.12, v5.6.13, v5.6.14, v5.6.15, v5.6.16, v5.6.17, v5.6.19, v5.6.2, v5.6.20, v5.6.21, v5.6.22, v5.6.23, v5.6.24, v5.6.26, v5.6.27, v5.6.28, v5.6.29, v5.6.3, v5.6.30, v5.6.31, v5.6.32, v5.6.33, v5.6.34, v5.6.35, v5.6.36, v5.6.37, v5.6.38, v5.6.39, v5.6.4, v5.6.5, v5.6.6, v5.6.7, v5.6.8, v5.6.9].
- Can only install one of: laravel/framework[5.6.x-dev, v6.18.3].
- don't install illuminate/console 5.6.x-dev|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.0|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.1|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.10|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.11|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.12|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.13|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.14|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.15|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.16|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.17|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.19|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.2|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.20|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.21|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.22|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.23|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.24|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.26|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.27|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.28|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.29|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.3|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.30|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.31|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.32|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.33|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.34|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.35|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.36|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.37|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.38|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.39|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.4|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.5|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.6|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.7|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.8|don't install laravel/framework v6.18.3
- don't install illuminate/console v5.6.9|don't install laravel/framework v6.18.3
- Installation request for laravel/framework (locked at v6.18.3, required as ^6.3) -> satisfiable by laravel/framework[v6.18.3].
- Installation request for litepie/workflow ^1.0 -> satisfiable by litepie/workflow[1.0.0, 1.0.x-dev].

Installation failed, reverting ./composer.json to its original content.

Laravel: 6.18.3
PHP: 7.4.2

Errors attempting to serialise a Closure if the event name cannot be mapped

If DispatcherAdapter::translateEvent(...) is unable to determine the event to map to, it just simply returns the Symfony event instead of an event which extends ZeroDaHero\LaravelWorkflow\Events\BaseEvent.

This causes the application to fail with the error Serialization of 'Closure' is not allowed. if a registered event listener implements the Illuminate\Contracts\Queue\ShouldQueue interface as the Symfony event contains Clousures and Laravel's queuing mechanism will always attempt to serialise the job.

One way to trigger this issue is to use a dot . character in the configured workflow name, such as straight.test.

There are a few potential solutions for this, but possibly parsing out the workflow name from the event name might be the best option (assuming that's feasible). Alternatively, disabling support for workflows with dot characters in their name is another viable option, although would be a breaking change.

Regardless of which solution is implemented, calls to DispatcherAdapter::translateEvent(...) should also ensure that they don't return Symfony events.

workflow_transitions missing $workflow param

WorkflowTrait:workflow_transitions should be

  public function workflow_transitions($workflow = null)
    {
        return Workflow::get($this, $workflow)->getEnabledTransitions($this);
    }

Argument 1 passed to ZeroDaHero\LaravelWorkflow\WorkflowRegistry::__construct() must be of the type array, null given, called in /var/www/html/vendor/zerodahero/laravel-workflow/src/WorkflowServiceProvider.php

Error when I use workflow_get();

I'm in a team that we are using your software to manage a workflow. A partner created the workflow and tested in a call and all it works!! But when I pulled the branch where there the code that works and then typed in console composer install to download the lib, in my side didn't work, Laravel shows

Argument 1 passed to ZeroDaHero\LaravelWorkflow\WorkflowRegistry::__construct() must be of the type array, null given, called in /var/www/html/vendor/zerodahero/laravel-workflow/src/WorkflowServiceProvider.php

The different here is the error say ...null given...

Notes:

  • We are using a docker container, so I think that the env is not the problem.
  • the marking_store type is multiple_state.
  • We are using Laravel 6.2 and your lib in 2.0 version

Workflow workflow_name is not configured

php artisan workflow:dump workflow_name --format=jpg

Exception : Workflow workflow_name is not configured.

at /var/www/html/laravel/zerodahero/vendor/zerodahero/laravel-workflow/src/Commands/WorkflowDumpCommand.php:49
45| $class = $this->option('class');
46| $config = Config::get('workflow');
47|
48| if (!isset($config[$workflowName])) {

49| throw new Exception("Workflow $workflowName is not configured.");
50| }
51|
52| if (false === array_search($class, $config[$workflowName]['supports'])) {
53| throw new Exception("Workflow $workflowName has no support for class $class.".

Exception trace:

1 ZeroDaHero\LaravelWorkflow\Commands\WorkflowDumpCommand::handle()
/var/www/html/laravel/zerodahero/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:32

2 call_user_func_array([])
/var/www/html/laravel/zerodahero/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:32

Please use the argument -v to see more details.

haw can i change workflow:dump output folder ?

hey !
i'm using this command php artisan workflow:dump workflow_name --class App\\BlogPost to generate a workflow image,
the output folder is alwayse the root folder of my project, but i want to put it inside storage/app/public folder

how can i do it ? what changes i should make in WorkflowDumpCommand.php file to be able to store the output image into storage/app/public ?

workflow_apply second parameter

Hi,

In case I want to use the trait and send context to transition, i have to use all three parameters to workflow_apply.
However second parameter is irrelevant, because the trait is directly applied to given model.
I propose to remove the second parameter and leave context to be second optional argument.

Wrong behavior when having multiple "from" places in transaction

While trying to recreate this example I run into a weird behavior:

Workflow definition

    'test' => [
        'type' => 'workflow', // or 'state_machine'
        'marking_store' => [
            'type' => 'multiple_state', // or 'single_state'
            'property' => 'delivery_workflow', // this is the property on the model
        ],
        'supports' => ['App\Booking\Trip'],
        'places' => ['draft', 'waiting for journalist', 'approved by journalist', 'wait for spellchecker', 'approved by spellchecker', 'published'],
        'transitions' => [
            'request review' => [
                'from' => 'draft',
                'to' => ['waiting for journalist', 'wait for spellchecker']
            ],
            'journalist approval' => [
                'from' => 'waiting for journalist',
                'to' => 'approved by journalist'
            ],
            'spellchecker approval' => [
                'from' => 'wait for spellchecker',
                'to' => 'approved by spellchecker'
            ],
            'publish' => [
                'from' => ['approved by journalist', 'approved by spellchecker'],
                'to' => 'published'
            ],
        ],
    ],

Expected

Screenshot from 2020-08-12 21-58-31

Fact (publish transition rendered twice)

Screenshot from 2020-08-12 21-58-24

After quick digging I found that it happens in WorkflowRegistry

Instead of simple

            $transitionObj = new Transition($transitionName, $transition['from'], $transition['to']);
            $builder->addTransition($transitionObj);

we can see this:

            foreach ((array)$transition['from'] as $form) {  // 
                $transitionObj = new Transition($transitionName, $form, $transition['to']);
                $builder->addTransition($transitionObj);

                if (isset($transition['metadata'])) {
                    $metadata['transitions']->attach($transitionObj, $transition['metadata']);
                }
            }

I believe this was done on purpose, but it doesn't look right. What's the back thinking behind this?

May be require symfony event-dispatcher-contracts instead of event-dispatcher?

I know laravel depends on symfony http-kernel which in turn depends on event-dispatcher... even still, you might want to swap out the event-dispatcher package with the event-dispatcher-contracts package instead.

Just a thought.

diff --git a/composer.json b/composer.json
index f01d06d..777bcf5 100644
--- a/composer.json
+++ b/composer.json
@@ -5,9 +5,9 @@
     "license": "MIT",
     "require": {
         "php": ">=7.2",
         "symfony/workflow": "^5.0",
         "symfony/process": "^5.0",
+        "symfony/event-dispatcher-contracts": "^2.4",
-        "symfony/event-dispatcher": "^5.0",
         "illuminate/console": "^7.1|^8.0",
         "illuminate/support": "^7.1|^8.0",
         "illuminate/contracts": "^7.1|^8.0"
diff --git a/src/WorkflowRegistry.php b/src/WorkflowRegistry.php
index b1894e3..c9337d8 100644
--- a/src/WorkflowRegistry.php
+++ b/src/WorkflowRegistry.php
@@ -3,7 +3,7 @@
 namespace ZeroDaHero\LaravelWorkflow;
 
 use Illuminate\Contracts\Events\Dispatcher as EventsDispatcher;
-use Symfony\Component\EventDispatcher\EventDispatcher;
+use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
 use Symfony\Component\Workflow\Definition;
 use Symfony\Component\Workflow\DefinitionBuilder;
 use Symfony\Component\Workflow\Exception\InvalidArgumentException;
@@ -37,7 +37,7 @@ class WorkflowRegistry
     protected $registryConfig;
 
     /**
-     * @var EventDispatcher
+     * @var EventDispatcherInterface
      */
     protected $dispatcher;

Doesn't work with Laravel 6

Your requirements could not be resolved to an installable set of packages.

Problem 1
- Conclusion: remove laravel/framework v6.18.3
- Conclusion: don't install laravel/framework v6.18.3
- zerodahero/laravel-workflow 3.x-dev requires illuminate/contracts ^7.0 -> satisfiable by laravel/framework[7.x-dev], illuminate/contracts[7.x-dev, v7.0.0, v7.0.1, v7.0.2, v7.0.3, v7.0.4, v7.0.5, v7.0.6, v7.0.7, v7.0.8, v7.1.0, v7.1.1, v7.1.2, v7.1.3, v7.2.0, v7.2.1, v7.2.2, v7.3.0].
- zerodahero/laravel-workflow v3.0.0 requires illuminate/contracts ^7.0 -> satisfiable by laravel/framework[7.x-dev], illuminate/contracts[7.x-dev, v7.0.0, v7.0.1, v7.0.2, v7.0.3, v7.0.4, v7.0.5, v7.0.6, v7.0.7, v7.0.8, v7.1.0, v7.1.1, v7.1.2, v7.1.3, v7.2.0, v7.2.1, v7.2.2, v7.3.0].
- Can only install one of: laravel/framework[7.x-dev, v6.18.3].
- don't install illuminate/contracts 7.x-dev|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.0.0|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.0.1|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.0.2|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.0.3|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.0.4|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.0.5|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.0.6|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.0.7|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.0.8|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.1.0|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.1.1|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.1.2|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.1.3|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.2.0|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.2.1|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.2.2|don't install laravel/framework v6.18.3
- don't install illuminate/contracts v7.3.0|don't install laravel/framework v6.18.3
- Installation request for laravel/framework (locked at v6.18.3, required as ^6.3) -> satisfiable by laravel/framework[v6.18.3].
- Installation request for zerodahero/laravel-workflow ^3.0 -> satisfiable by zerodahero/laravel-workflow[3.x-dev, v3.0.0].

Laravel: 6.18.3 PHP: 7.4.2

Workflow marking store type

UPDATE: My questions are:

  1. How do we use state_machine and do we need it at all?
  2. Should we stick to Symfony recommendation to avoid setting marking store type?
    -- please read below full text

According to the documentation of Symfony https://symfony.com/doc/current/workflow.html#storing-metadata default Workflow marking store type is inferred based on workflow type. If it is workflow, marking store should be "multiple_state". Their recommendation is to not configure the type manually:

The marking store type could be “multiple_state” or “single_state”. A single state marking store does not support a model being on multiple places at the same time. This means a “workflow” must use a “multiple_state” marking store and a “state_machine” must use a “single_state” marking store. Symfony configures the marking store according to the “type” by default, so it’s preferable to not configure it.

A single state marking store uses a string to store the data. A multiple state marking store uses an array to store the data.

The marking_store.type (the default value depends on the type value) and property (default value ['marking']) attributes of the marking_store option are optional. If omitted, their default values will be used. It’s highly recommended to use the default value.

However based on my testing I have found out that default type is "single_state" even when using type workflow (btw. state_machine dumps the workflow with transitions in squares, not with labels above the arrow which makes me believe it is workflow, not state_machine). I have to explicitly set marking: multiple_state if I need to support multiple places and avoid errors. At the same time type: state_machine|workflow appears to be ignored at all.

    'test' => [
        'type' => 'workflow',

        'supports' => [
            Test::class,
        ],

        'places' => [
            'a', 'b',  'c',
            'a1', 'b1', 'b2',
            'a2', 'c1', 'c2',
        ],

        'initial_places' => [
            'a', 'a1', 'a2'
        ],

        'transitions' => [
            't1' => [
                'from' => 'a',
                'to' => 'b',
                'metadata' => [
                    'priority' => 0.5,
                ],
            ],
            't2' => [
                'from' => 'b',
                'to' => 'c'
            ],

            't11' => [
                'from' => 'a1',
                'to' => 'b1'
            ],
            't21' => [
                'from' => 'b1',
                'to' => 'c1'
            ],

            't12' => [
                'from' => 'a2',
                'to' => 'b2'
            ],
            't22' => [
                'from' => 'b2',
                'to' => 'c2'
            ],

        ],

Results:

   Symfony\Component\Workflow\Exception\NotEnabledTransitionException 

  Transition "t11" is not enabled for workflow "test".

And this configuration:

    'test' => [
        'type' => 'state_machine', /// NOTE THIS ?
        'marking_store' => [
            'type' => 'multiple_state',
        ],

        'supports' => [
            Test::class,
        ],

        'places' => [
            'a', 'b',  'c',
            'a1', 'b1', 'b2',
            'a2', 'c1', 'c2',
        ],

        'initial_places' => [
            'a', 'a1', 'a2'
        ],
        'transitions' => [
            't1' => [
                'from' => 'a',
                'to' => 'b',
                'metadata' => [
                    'priority' => 0.5,
                ],
            ],
            't2' => [
                'from' => 'b',
                'to' => 'c'
            ],

            't11' => [
                'from' => 'a1',
                'to' => 'b1'
            ],
            't21' => [
                'from' => 'b1',
                'to' => 'c1'
            ],

            't12' => [
                'from' => 'a2',
                'to' => 'b2'
            ],
            't22' => [
                'from' => 'b2',
                'to' => 'c2'
            ],

        ],

works fine and moves the workflow into expected places.

how to initial workflow when i create new database record? ("Call to a member function getTos() on null" Error)

Hi
when I try to use a workflow, I get an error like this:
Call to a member function getTos() on null

my config/workflow.php file :

<?php

return [
    'straight'   => [
        'type'          => 'workflow',
        'marking_store' => [
            'type'      => 'multiple_state',
            'arguments' => ['state']
        ],
        'supports'      => ["App\Task"],
        'places'        => ['draft', 'review', 'publish'],
        'transitions'   => [
            'drafting' => [
                'from' => 'draft',
                'to'   => 'review',
            ],
            'reviewing' => [
                'from' => 'review',
                'to'   => 'publish',
            ]
        ],
    ]
];

my Controller :

public function store(Request $request)
    {
        // validate the given request
        $data = $this->validate($request, [
            'title' => 'required|string|max:255',
        ]);



        // create a new incomplete task with the given title
        $task = Auth::user()->tasks()->create([
            'title' => $data['title'],
        ]);

        $task->workflow_apply('drafting');

        // flash a success message to the session
        session()->flash('status', 'Task Created!');

        // redirect to tasks index
        return redirect('/tasks');
    }

how i can initialize state of my task when i create new task?

Wrong argument type when calling GuardEvent

Hi,

I have event subscriber - guard function, that is defined using Symfony style. However the guard function is called with parameter that is of type ZeroDaHero\GuardEvent, instead of type Symfony\GuardEvent.

My believe is that if I subscribe using Symfony naming style of events, then I should receive Symfony events.

event subscriber:

use Symfony\Component\Workflow\Event\GuardEvent;

class WorkflowTestSubscriber
{
    public function guard_t1(GuardEvent $event)
    {
        // $originalEvent = $event->getOriginalEvent();

        print "\tGuard T1";

        $subject = $event->getSubject();
        $event->setBlocked(true, 'test blocking reason');
    }

    public function subscribe($events)
    {
        return [
            // 'workflow.*' => 'test',
            'workflow.straight.guard.t1' => 'guard_t1',
        ];
    }
}

Error message:

   TypeError

  App\Listeners\WorkflowTestSubscriber::guard_t1(): Argument #1 ($event) must be of type Symfony\Component\Workflow\Event\GuardEvent, ZeroDaHero\LaravelWorkflow\Events\GuardEvent given, called in /Users/sag/Documents/code/zz_api/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php on line 424

WorkflowRegistry

Hi, I started:
composer require zerodahero/laravel-workflow

I get this error:
Argument 1 passed to ZeroDaHero\LaravelWorkflow\WorkflowRegistry::__construct() must be of the type array, null given, called in /app/vendor/zerodahero/laravel-workflow/src/WorkflowServiceProvider.php on line 49

Wrong events fired when using transition from two places to one

For this workflow
straight

we have a listener that dumps the events fired. There is extra entered.c event emitted.

Transitions:

        $this->info ('Apply T1');
        $workflow->apply($model, 't1');
        
        $this->warn(print_r ($model->marking, true));
        
        $this->info ('Apply T4');
        $workflow->apply($model, 't4');
        $this->warn(print_r ($model->marking, true));

Output:

Apply T1
string(26) "workflow.straight.guard.t1"
string(25) "workflow.straight.leave.a"
string(31) "workflow.straight.transition.t1"
string(25) "workflow.straight.enter.b"
string(25) "workflow.straight.enter.c"
string(27) "workflow.straight.entered.b"
string(27) "workflow.straight.entered.c"
string(30) "workflow.straight.completed.t1"
string(26) "workflow.straight.guard.t4"
string(26) "workflow.straight.guard.t4"
string(29) "workflow.straight.announce.t4"
string(29) "workflow.straight.announce.t4"
Array
(
    [b] => 1
    [c] => 1
)

Apply T4
string(26) "workflow.straight.guard.t4"
string(26) "workflow.straight.guard.t4"
string(25) "workflow.straight.leave.b"
string(31) "workflow.straight.transition.t4"
string(25) "workflow.straight.enter.d"
string(27) "workflow.straight.entered.c"
string(27) "workflow.straight.entered.d"
string(30) "workflow.straight.completed.t4"
string(26) "workflow.straight.guard.t4"
string(29) "workflow.straight.announce.t4"
string(25) "workflow.straight.leave.c"
string(31) "workflow.straight.transition.t4"
string(25) "workflow.straight.enter.d"
string(27) "workflow.straight.entered.d"
string(30) "workflow.straight.completed.t4"
Array
(
    [d] => 1
)

Event listeners defined in EventServiceProvider failing

I have the following in EventServiceProvider:

class EventServiceProvider extends ServiceProvider { protected $listen = [ 'workflow.smsNotificationIncoming.transition.toAccepted' => [IncomingListener::class], ];

When transition is applied, fails with:

{
"message": "Serialization of 'Closure' is not allowed",
"exception": "Exception",

helper as symfony (i.e.: workflow_transition_blockers)

Hi all,
I'm really grateful for this package.
I am trying to recreate some twig/blade helpers from Symfony described here https://symfony.com/doc/current/workflow.html

I.e.:

function workflow_metadata($object, $meta, $place_or_transition)
{
    $workflow = $object->workflow_get();
    return $workflow->getMetadataStore()->getMetadata($meta,$place_or_transition);
}
...

but I need some help to create workflow_transition_blockers
to display current blocking message that prevent to apply "next" transition on a simple state_machine workflow.

Has someone already done it? or may help with some suggestion?

get_class() expects parameter 1 to be object, null given

Captura de pantalla de 2019-05-23 11-26-43

MY ROUTE
Route::get('/workflow', 'BlogPostController@index');

my composer.json

{
"name": "laravel/laravel",
"type": "project",
"description": "The Laravel Framework.",
"keywords": [
"framework",
"laravel"
],
"license": "MIT",
"require": {
"php": "^7.1.3",
"fideloper/proxy": "^4.0",
"laravel/framework": "5.8.*",
"laravel/tinker": "^1.0",
"zerodahero/laravel-workflow": "^2.0"
},
"require-dev": {
"beyondcode/laravel-dump-server": "^1.0",
"filp/whoops": "^2.0",
"fzaninotto/faker": "^1.4",
"mockery/mockery": "^1.0",
"nunomaduro/collision": "^3.0",
"phpunit/phpunit": "^7.5"
},
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true
},
"extra": {
"laravel": {
"dont-discover": []
}
},
"autoload": {
"psr-4": {
"App\": "app/"
},
"classmap": [
"database/seeds",
"database/factories"
]
},
"autoload-dev": {
"psr-4": {
"Tests\": "tests/"
}
},
"minimum-stability": "dev",
"prefer-stable": true,
"scripts": {
"post-autoload-dump": [
"Illuminate\Foundation\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi"
],
"post-root-package-install": [
"@php -r "file_exists('.env') || copy('.env.example', '.env');""
],
"post-create-project-cmd": [
"@php artisan key:generate --ansi"
]
}
}

MY MIGRATION BLOGPOST
`<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateTableBlogPost extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('blogpost', function (Blueprint $table) {
$table->bigIncrements('id');
$table->timestamps();
$table->string('description');
$table->dateTime('currentPlace');
});
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
    Schema::dropIfExists('blogpost');
}

}
`
INSERT INTO BLOGPOST
insert into blogpost(id,description,created_at,updated_at)values(1,'descripcion',now(),now());

MY CONTROLLER BLOGPOST

< ? php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Workflow;
use App\BlogPost;

class BlogPostController extends Controller
{

public function index()
{
        $post = BlogPost::find(1);
        $workflow = Workflow::get($post);
        // if more than one workflow is defined for the BlogPost class
        // $workflow = Workflow::get($post, $workflowName);

        //$workflow->can($post, 'publish'); // False
        $workflow->can($post, 'to_review'); // True
        $transitions = $workflow->getEnabledTransitions($post);

        // Apply a transition
        $workflow->apply($post, 'to_review');
        $post->save(); // Don't forget to persist the state

        // Using the WorkflowTrait
        $post->workflow_can('publish'); // True
        //$post->workflow_can('to_review'); // False

        // Get the post transitions
        foreach ($post->workflow_transitions() as $transition) {
            echo $transition->getName();
        }

        // Apply a transition
        $post->workflow_apply('publish');
        $post->save();        
}

}

Marking_store method not implemented

Hi,

From the Symfony documentation (https://symfony.com/doc/4.4/workflow.html#creating-a-workflow)
and from the Symfony blog (https://symfony.com/blog/new-in-symfony-4-3-workflow-improvements#simpler-configuration) you can see that they modify a little the marking_store property in the config file.

framework:
    workflows:
        article:
            type: workflow
            marking_store:
                type: method # This will be the default value in Symfony 5.0
                property: marking # This is the default value, it could be omitted
        task:
            type: state_machine
            marking_store:
                type: method # This will be the default value in Symfony 5.0
                property: state

And they add a new MethodMarkingStore class that implements the MarkingStoreInterface.

Unfortunately in your WorkflowRegistry you set the marking_store with the getMarkingStoreInstance() method which doesn't take into account those Symfony modifications.

protected function getMarkingStoreInstance(array $workflowData)
    {
        $markingStoreData = isset($workflowData['marking_store']) ? $workflowData['marking_store'] : [];
        $arguments = isset($markingStoreData['arguments']) ? $markingStoreData['arguments'] : [];

        if (isset($markingStoreData['class'])) {
            $className = $markingStoreData['class'];
        } elseif (isset($markingStoreData['type']) && $markingStoreData['type'] === 'multiple_state') {
            $className = MultipleStateMarkingStore::class;
        } else {
            $className = SingleStateMarkingStore::class;
        }

        $class = new \ReflectionClass($className);

        return $class->newInstanceArgs($arguments);
    }

which means we can't use the new marking_store formalism.

Do you think you can have a look on this ?

Thank !

Simple sample for work with Workflow events

Hi,
does Anyone use this package in their project?
How to use symfony-workflow-events in project?

if anyone create project with this package, is it possible to publish example/project (open-source form) to understand how can we use events in the projects ?

v 3.3 downgrades symfony/workflow to 5.4.3

Using version ^3.3 for zerodahero/laravel-workflow
./composer.json has been updated
Running composer update zerodahero/laravel-workflow
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - zerodahero/laravel-workflow[v3.3.0, ..., 3.x-dev] require symfony/event-dispatcher ^5.0 -> found symfony/event-dispatcher[v5.0.0-BETA1, ..., 5.4.x-dev] but the package is fixed to v6.0.3 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
    - zerodahero/laravel-workflow[v3.3.2, ..., v3.3.3] require symfony/event-dispatcher-contracts ^2.4 -> found symfony/event-dispatcher-contracts[v2.4.0, ..., 2.5.x-dev] but the package is fixed to v3.0.0 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
    - Root composer.json requires zerodahero/laravel-workflow ^3.3 -> satisfiable by zerodahero/laravel-workflow[v3.3.0, ..., 3.x-dev].

Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.
You can also try re-running composer require with an explicit version constraint, e.g. "composer require zerodahero/laravel-workflow:*" to figure out if any version is installable, or "composer require zerodahero/laravel-workflow:^2.1" if you know which you need.

Installation failed, reverting ./composer.json and ./composer.lock to their original content.
sag@Sag-MacBook-Pro-15 zz_api % composer require zerodahero/laravel-workflow -W
Using version ^3.3 for zerodahero/laravel-workflow
./composer.json has been updated
Running composer update zerodahero/laravel-workflow --with-all-dependencies
Loading composer repositories with package information
Updating dependencies
Lock file operations: 2 installs, 2 updates, 0 removals
  - Upgrading klimenttoshkov/laravel-currency (dev-master 7a55352 => dev-master fd7c21c)
  - Downgrading symfony/event-dispatcher-contracts (v3.0.0 => v2.5.0)
  - Locking symfony/workflow (v5.4.3)
  - Locking zerodahero/laravel-workflow (v3.3.3)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 2 installs, 2 updates, 0 removals
  - Downloading symfony/event-dispatcher-contracts (v2.5.0)
  - Downloading symfony/workflow (v5.4.3)
  - Downloading zerodahero/laravel-workflow (v3.3.3)
  - Downgrading symfony/event-dispatcher-contracts (v3.0.0 => v2.5.0): Extracting archive
  - Upgrading klimenttoshkov/laravel-currency (dev-master 7a55352 => dev-master fd7c21c): Source already present
  - Installing symfony/workflow (v5.4.3): Extracting archive
  - Installing zerodahero/laravel-workflow (v3.3.3): Extracting archive
Package swiftmailer/swiftmailer is abandoned, you should avoid using it. Use symfony/mailer instead.
Generating optimized autoload files

Column not found. Unknown column 'marking'

First of all, thank you for your work!
When I'm trying to persist the state, I'm getting the above error.

$workflow->apply($post, 'to_review');
$post->save();
//Result: Illuminate\Database\QueryException: SQLSTATE[42S22]: Column not found: 1054Unknown column 'marking' in 'field list'

It seems that I should add some new columns to the DB tables.
Are there any other columns (beside marking) that should be added?
Also, I think that it would be useful to specify this in the documentation.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.