Skip to content

Instantly share code, notes, and snippets.

@raoul2000
Created April 13, 2015 20:38
Show Gist options
  • Save raoul2000/b93e478124e45fd4a58d to your computer and use it in GitHub Desktop.
Save raoul2000/b93e478124e45fd4a58d to your computer and use it in GitHub Desktop.
// the model /////////////////////////////////////////////////////////////////////
class Post extends \yii\db\ActiveRecord
{
/**
* @inheritdoc
*/
public static function tableName()
{
return 'item';
}
/**
* @inheritdoc
*/
public function rules()
{
return [
// The RelatedWorkflowValidator is in charge of validating status_ex transition
// depending on transition occuring on the primary workflow (status attribute)
['status_ex',RelatedWorkflowValidator::className()],
];
}
/**
* (non-PHPdoc)
* @see \yii\base\Component::behaviors()
*/
public function behaviors()
{
return [
// Primary workflow
'w1' =>[
'class' => \raoul2000\workflow\base\SimpleWorkflowBehavior::className(),
'statusAttribute' => 'status',
'defaultWorkflowId' => 'PostWorkflow1'
],
// Secondary workflow
'w2' => [
'class' => \raoul2000\workflow\base\SimpleWorkflowBehavior::className(),
'statusAttribute' => 'status_ex',
'defaultWorkflowId' => 'PostWorkflow2'
]
];
}
}
// PostWorkflow1 definition /////////////////////////////////////////////////////////////////////
class PostWorkflow1 implements IWorkflowDefinitionProvider
{
public function getDefinition() {
return [
'initialStatusId' => 'draft',
'status' => [
'draft' => [
'transition' => ['correction']
],
'correction' => [
'transition' => ['draft','ready']
],
'ready' => [
'transition' => ['draft', 'correction', 'published']
],
'published' => [
'transition' => ['ready', 'archived']
],
'archived' => [
'transition' => ['ready']
]
]
];
}
}
// PostWorkflow2 definition /////////////////////////////////////////////////////////////////////
class PostWorkflow2 implements IWorkflowDefinitionProvider
{
public function getDefinition() {
return [
'initialStatusId' => 'success',
'status' => [
'success' => [
'transition' => ['onHold']
],
'onHold' => [
'transition' => ['success']
],
]
];
}
}
// The Standalone Validator class /////////////////////////////////////////////////////////////////////
use yii\validators\Validator;
use raoul2000\workflow\validation\WorkflowScenario;
class RelatedWorkflowValidator extends Validator
{
private $constraint;
/**
* Set constraint array where keys are scenario for the secondary workflow, and
* values are array of scenario for the primary workflow that allow secondary transition.
* If value is TRUE, the secondary transition is allowed.
*
* @see \yii\validators\Validator::init()
*/
public function init()
{
parent::init();
$this->constraint = [
// model can enter into secondary workflow no matter what is the primary workflow transition
WorkflowScenario::enterWorkflow('Post4Workflow2') => true,
WorkflowScenario::changeStatus('Post4Workflow2/success', 'Post4Workflow2/onHold') => [
WorkflowScenario::changeStatus('Post4Workflow1/draft', 'Post4Workflow1/correction'),
WorkflowScenario::changeStatus('Post4Workflow1/ready', 'Post4Workflow1/draft')
],
WorkflowScenario::changeStatus('Post4Workflow2/onHold', 'Post4Workflow2/success') => [
WorkflowScenario::changeStatus('Post4Workflow1/correction', 'Post4Workflow1/ready')
]
];
}
/**
* Perform validation.
* WARNING : primary and secondary status attribute names are hard coded (to change if needed)
*
* @see \yii\validators\Validator::validateAttribute()
*/
public function validateAttribute($model, $attribute)
{
$w2scenarios=null;
$w1scenarios=null;
try {
list(,$w2scenarios) = $model->getBehavior('w2')->_createTransitionItems($model->status_ex, true, false);
if( $w2scenarios == null) {
return; // no pending transition for w2 : validation succeeds
}
} catch (Exception $e) {
$this->addError($attribute, 'invalid transition on secondary workflow');
return;
}
try {
list(,$w1scenarios) = $model->getBehavior('w1')->_createTransitionItems($model->status, true, false);
} catch (Exception $e) {
$this->addError($attribute, 'invalid transition on primary workflow');
return;
}
foreach ($w2scenarios as $w2sc) {
if (isset( $this->constraint[$w2sc])) {
if( $this->constraint[$w2sc] === true) {
return;
}elseif($w1scenarios === null && in_array($w1scenarios, $this->constraint[$w2sc])) {
return;
}else {
foreach ($w1scenarios as $w1sc) {
if( in_array($w1sc,$this->constraint[$w2sc])) {
return;
}
}
}
}
}
// the constraint array does not contain secondary AND related primary transition
// for the current model.
$msgInfo= implode(', ',$w2scenarios);
$this->addError($attribute, 'constraint failed : '. $msgInfo);
}
}
@abdullah-almesbahi
Copy link

Thank you so much for your help , I'll test it now and see what I can do. I will update you soon

@abdullah-almesbahi
Copy link

Do you know how to get defaultWorkflowId from controller ?

            'w1' =>[
                'class' => \raoul2000\workflow\base\SimpleWorkflowBehavior::className(),
                'statusAttribute' => 'status',
                'defaultWorkflowId' => 'PostWorkflow1'
            ],

@abdullah-almesbahi
Copy link

I already got it , thank you , i'll update you soon

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment