Yii 1.1: simpleworkflow

A simple workflow engine for active records
48 followers

simpleWorkflow

The simpleWorkflow extension is a set of Yii components that is dedicated to provide an easy way to manage the life cycle of CActiveRecord objects inside a workflow. It provides features to control the behavior of the active record in its associated workflow : transition tasks, status constraints, event model.

Workflows are defined as associative arrays or as classes. They can be created manually, but for your convenience, since version 1.1, a Gii command is provided to automatically convert any workflow created by the yEd Graphical Editor into a simpleWorkflow : check out the video to learn more about it.

Please note that the simpleWorkflow command for Gii is still experimental

Resources

Documentation

Requirements

  • Yii 1.1.4 or above
  • the Gii command requires domxml PHP extension and since version 1.1.0.8, the DOM extension is also supported

Installation

  • Extract the release file under protected/extensions
  • add the SWPhpWorkflowSource component to your configuration
'components'=>array(    
    // adding the simple Workflow source component
    'swSource'=> array(
        'class'=>'application.extensions.simpleWorkflow.SWPhpWorkflowSource',
    ), ...
  • add simpleWorkflow extension base folder to your imports
'import'=>array(
    ...
        // Import simpleWorkflow components : validator, helper ...      
    'application.extensions.simpleWorkflow.*',  
),

For more information on how to use the simpleWorkflow extension, please refer to the documentation

Usage

Once installed and correctly configured, the simpleWorkflow extension will handle the workflow for any model. This happens automatically when the model is read/saved from/to database, or programatically by the developer. For instance :

$m=MyModel::model()->findByPk('1');
if( $m->swHasStatus() ){
     echo 'status : '.$m->swGetStatus()->toString();        
}else {
     $m->swInsertToWorkflow();
     $m->save();
}

Change Log

May 26, 2013

  • version 1.1.0.8
    • gii command : add SWyEdConverterDOM that uses DOM extension. If domxml extension is available, use it in priority otherwise use DOM
    • add swSetStatus() to replace swNextStatus() which is still supported, but deprecated

September 19, 2012

  • version 1.1
    • change swNextStatus() : it is not permitted anymore to call 'swNextStatus()' with no argument. To insert a model into a workflow, swNextStatus() must be replaced by a call to 'swInsertToWorkflow()'.
    • enh : add method 'swRemoveFromWorkflow()'. This method is only successful when the owner model is in a final status (i.e a status with no outgoing transition).
    • enh : add swGetWorkflowSource() as public method to return the workflow source component used by the behavior
    • Gii command to convert yEd Graph Editor workflows into sW workflows (experimental)
    • enh : when loading a workflow, raise exception on duplicate node id

August 15, 2012

  • Version 1.0
    • fix : autoinsert into workflow (jmariani)
    • enh : replace function is_a() by instanceof (kjharni)
    • enh : metadata. It is now possible to add any value to node definition by using the metadata attribute.
    • enh : workflow class definition. A workflow can be defined as a class that must implement method getDefinition() which returns the workflow definition in its array format.
    • enh : add 'leaveWorkflow' event. This event is fired whenever a component in a workflow reset its status. This must be done from a final status only.

November 27, 2010

  • (RC2)
    • fix : replace 'split' with 'explode' (got 2 doodle)
    • enh : SWActiveRecordBehavior->swValidate now returns boolean
    • enh : Workflow Driven Model Validation. It is now possible to define validators which are only executed upon specific transitions (this is done by defining specific scenario names).

October 3, 2010

  • Initial release (RC1).

Total 20 comments

#17766 report it
Raoul at 2014/07/21 03:12am
@myrazel

Hi myrazel,

if you don't provide a label for node, then the node ID is used as label.

ciao

#17733 report it
myrazel at 2014/07/18 12:53am
get specific label

can we get specific label from an id/status?

something like

$id = 'Archived'
SWNode::getLabelFromId($id)

I found nothing about that

#17703 report it
lutek at 2014/07/16 05:42am
re: Spacing in ID

@myrazel id should be consistent (without space), for displaying you should use labels (SWNode -> getLabel( ))

#17702 report it
myrazel at 2014/07/16 05:26am
Spacing in ID

in ID we cannot put space or something separating the words. for example:

return array(
    'initial' => "Waiting Approval", //absolutely will raise error, edit to "WaitingApproval"
    'node'    => array(
        array(
            'id' => "Waiting Approval", //absolutely will raise error, edit to "WaitingApproval"
            'label' => Yii::t('workflow','Waiting Approval'), //But this make it works
            'transition' => array(
                'Booking',
                'Rejected',
            ),
            'metadata' => array(
                'background-color' => '#FFCC00',
                'color' => '#000000',
            ),
        ),
        array(
            'id' => 'Rejected',
            'label' => Yii::t('workflow','Rejected'),
            //'constraint' => '',
            'metadata' => array(
                'background-color' => '#FFCC00',
                'color' => '#000000',
            ),
        ),
#17589 report it
Raoul at 2014/07/05 07:08am
@seng

hi seng, I'm not sure to understand what your problem is. For sure the simpleWorkflow extension being provided as a behavior it can only be used for (attached to) aa AR class... but you can attach it to different AR classes.

ciao

#17588 report it
seng at 2014/07/04 11:27pm
Does it suit when the workflow spans over several rows?

Looks like the extension is perfect suit when managing the state transitions of a single object. But in my case, my workflow spans across multiple rows, sometimes multiple rows from different active records ojects and I need to inspect all those object to validate it. Does it work across multiple active record objects?

#16991 report it
wwwwww at 2014/04/19 08:42am
WEB Gui

Hi Raoul, I tested the URL again, it works fine! http://lms.irc.ac.ir/extras/hwts/odg/workflow/update/id/1

#16962 report it
Raoul at 2014/04/16 02:39pm
Web GUI

Hi wwwww,

I can't acces to the demo url but yes, creating a simpleWorkflow visual builder is an option I had in mind. Sometimes ago I created such a tool based on a Flash component but I was not satisfied with it so I never released it.

Maybe for the next version ...

#16950 report it
wwwwww at 2014/04/16 03:18am
Web GUI to generate sw in browser (tested in FF)

I have used a d3.js svg (http://bl.ocks.org/rkirsling/5001347) to develop a web based app in order to create Simple Workflow as simple as possible. Workflow definition and extra simple workflow model required rules are generated automatically. Here is the link: http://lms.irc.ac.ir/extras/hwts/odg/workflow/update/id/1

#16799 report it
Raoul at 2014/03/29 10:46am
logging

Hi wwwwww,

and thanks for your comment.

The extension doesn't include some built-in logging feature, and actually I removed sometimes ago most of the TRACE that remained for debug purpose.

However, if you want to add status transition logging, what you could do is to write a LoggableStatusBehavior that would handle events triggered by the SWActiveRecordBehavior behavior and in particular the afterTransition event. The SWEvent fired contains the source and destination status, applied to the sender model (check out the SWEvent class).

Hope it helps...

bye

#16798 report it
wwwwww at 2014/03/29 08:11am
Question About Logging

Although it is mentioned before, but: "Great Extension!"

The Question:
Does your extension supports status transition logging?

#15314 report it
Raoul at 2013/10/28 04:14am
@williamquitian

hi williamquitian,

I'm not sure to understand your problem (if you wnat to describe more in detail, I advice you use the forum thread)

Workflows are not saved in DB, they are just stored as associative array (or class) into a file. That being said, storage is not related to how you assign a workflow to a model instance. This can be done automatically (autoInsert = true) or programatically. In this last case you can assign whatever workflow you want dynamically. Then, when the model instance is assigned a workflow it lives its own life among this workflow.

Again, I'm not sure I understand your question/problem so feel free to elaborate on the forum thread.

ciao

#15297 report it
williamquitian at 2013/10/24 03:25pm
Save workflow in database

Hello, another question, what workflows can be saved in a database, that is, I have to create different flows for the same model, but different filters I have to choose one among many, please if you can guide me how to do it.

#13806 report it
williamquitian at 2013/06/27 12:08pm
thanks

thanks Raoul for your reply, congratulations for your good work on this extension

#13799 report it
Raoul at 2013/06/26 09:29pm
one node at a time

hi williamquitian, sorry but what you are asking is not possible with this extension : at a certain moment a model is in one and only one node (or status).

#13797 report it
williamquitian at 2013/06/26 05:59pm
Question

as you can go from one node to two or more nodes at the same time? to run more than one node at the time, and to save time. thanks for your help

#6920 report it
Raoul at 2012/02/13 02:43pm
reply to aleksdj

Hi aleksdj, and thanks for your kind comments. I appreciate !

Regarding your question I don't really have production data on performance impact. The only thing I can say is that as workflow definition is stored in a file, it will require disk access each time it is used so unless the server provides some sort of cashing, you'll have to count with that.

Cheers

#6904 report it
aleksdj at 2012/02/12 09:39am
Incredible extension and moreover documentation

Wow Raoul! I reached your page looking for some kind of "visual guide" for interfaces (eguider) and I ended reading ALL the workflow extension documentation, let me give you my congratulations not only for the really difficult extension code, but for the great documentation that let me understand practicaly all the functionality mostly because of the continous comparation with an example!! We will think to implement it in our cloud service, just a question: do we decrease our overall performance using it for a simple pair of models with status? What is the drawback if any? thanks again

#4379 report it
Raoul at 2011/07/02 11:24am
reply : Status not saved on action/update

hi philippfrenzel, thanks for your comment.

Regarding your problem, it may be more convient to discuss on the forum

bye

#4366 report it
PinkBrainPlan at 2011/06/29 06:23am
Status not saved on action/update

Hi,

first i love your component, the problem i have, is that i use the following JUIButton to save the form:

<?php echo CHtml::ajaxButton($model->isNewRecord ? 'Create' : 'Save',
            $model->isNewRecord ? Yii::app()->createUrl('customer/create') : Yii::app()->createUrl('customer/update',array('id'=>$model->customer_id)),
            array(
                'type'=>'POST',
                'success'=>'function(responseText,statusText) {
                                $("#customer_save_button").val("saved");
                                $.fn.yiiGridView.update("ledger-grid");
                            }',
            ),
            array('class'=>'ui-button ui-state-default ui-corner-all','id'=>'customer_save_button'));
?>

and here the update from the controller:

public function actionUpdate($id)
    {
        $model=$this->loadModel($id);
 
        // Uncomment the following line if AJAX validation is needed
        $this->performAjaxValidation($model);
 
        if(isset($_POST['Customer']))
        {
            $model->attributes=$_POST['Customer'];
            if($model->save()){
                                //here comes the logging part
                                $EventLog = new Event();
                                $EventLog->user_id =  Yii::app()->user->id;
                                $EventLog->eve_creationdate = date('Y-m-d H:i:s');
                                $EventLog->customer_id = $model->customer_id;
                                $EventLog->action_id = 4; //pls take a look into the wiki, to set the correct event id!
                                $EventLog->save();
 
                $this->redirect(array('view','id'=>$model->customer_id));
                        }
        }
 
        $this->render('update',array(
            'model'=>$model,
        ));
    }

But the status is not changed:( Pls. help!

Cheers Phil

Leave a comment

Please to leave your comment.

Create extension