Last active
August 29, 2015 14:23
-
-
Save raoul2000/37ebdbd89830f827c4a3 to your computer and use it in GitHub Desktop.
The wizflow manager component is used by the controller to handle wizards steps
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace app\components; | |
use Yii; | |
use raoul2000\workflow\base\Status; | |
use yii\base\Exception; | |
use yii\base\InvalidConfigException; | |
/** | |
* Implement the Wizard UI design pattern using yii2-workflow. | |
*/ | |
class WizflowManager extends \yii\base\Object | |
{ | |
/** | |
* @var array SimpleWorkflowBehavior configuration array attached to all wizard steps | |
*/ | |
public $workflowBehavior = [ | |
'class' => '\raoul2000\workflow\base\SimpleWorkflowBehavior', | |
'defaultWorkflowId' => 'Wizflow' | |
]; | |
/** | |
* @var string namle of the workflow behavior that is attached to all wizards steps | |
*/ | |
public $workflowBehaviorName = 'wizflowBehavior'; | |
/** | |
* @var IWorkflowSource the workflow source component to use | |
*/ | |
public $workflowSource; | |
/** | |
* | |
* @var string session key name used to stor | |
*/ | |
public $skeyName = '_wiz'; | |
/** | |
* This array stores the wizards state : | |
* - the current step (key = 'current') | |
* - a list of all steps that have been performed so far (key = 'path') | |
* | |
* Example : | |
* <pre> | |
* [ | |
* 'current' => [ | |
* 'attrib1' => 'value1', | |
* //... | |
* 'status' => 'Wizflow/step', | |
* ], | |
* 'path' => [ | |
* 'Wizflow/step' => [ | |
* 'attrib1' => 'value1', | |
* //... | |
* 'status' => 'Wizflow/step', | |
* ], | |
* //etc ... | |
* ] | |
* ] | |
*</pre> | |
*/ | |
private $_wiz = [ | |
'current' => null, | |
'path' => [] | |
]; | |
/** | |
* Loads existing wizard data if available. | |
* | |
* @see \yii\base\Object::init() | |
*/ | |
public function init() | |
{ | |
if( empty($this->skeyName) || ! is_string($this->skeyName)) { | |
throw new InvalidConfigException('Parameter "skeyName" must be a non-empty string'); | |
} | |
$wiz = Yii::$app->session->get($this->skeyName,null); | |
if($wiz !== null) { | |
$this->_wiz = $wiz; | |
} | |
} | |
/** | |
* Creates and returns the form model instance for the status attribute. | |
* Note that the attribute array passed as argument must include the status value. | |
* | |
* The instance is created using the 'model' metadata value associated with the 'status' | |
* attribute value. The metadata 'model' must be an array suitable to invoke Yii::createObject(). | |
* | |
* Once created, the SimpleWorkflowBehavior is attached to the model. | |
* | |
* @param array $attributes list of attributes | |
* @throws Exception | |
* @return Model | |
*/ | |
private function createInstance($attributes) | |
{ | |
if( isset($attributes['status']) == false ) { | |
throw new Exception('missing attribute "status"'); | |
} | |
$status = $this->workflowSource->getStatus($attributes['status']); | |
$config = array_merge( | |
$status->getMetadata('model'), | |
$attributes | |
); | |
$instance = Yii::createObject($config); | |
$instance->attachBehavior( | |
$this->workflowBehaviorName, | |
$this->workflowBehavior | |
); | |
return $instance; | |
} | |
/** | |
* Save the wizard data into the current session | |
*/ | |
public function save() | |
{ | |
Yii::$app->session->set($this->skeyName,$this->_wiz); | |
} | |
/** | |
* @return boolean TRUE if the wizard process as started (i.e. a current step is available) | |
* FALSE otherwise. | |
*/ | |
public function hasCurrentStep() | |
{ | |
return $this->_wiz['current'] != null; | |
} | |
/** | |
* Updates the current step with the model passed as argument. | |
* | |
* @param Model $model | |
* @throws Exception | |
*/ | |
public function updateCurrentStep($model) | |
{ | |
if( $this->hasCurrentStep() == false ) { | |
throw new Exception('wizard has no current step'); | |
} | |
$this->_wiz['current'] = $model->getAttributes(); | |
} | |
/** | |
* Returns the model associated with the current wizard step. | |
* | |
* @return Model|null the current stemp model instance or NULL if no current step is defined. | |
*/ | |
public function getCurrentStep() | |
{ | |
$currentStep = null; | |
if( $this->hasCurrentStep() ) { | |
$currentStep = $this->createInstance($this->_wiz['current']); | |
} | |
return $currentStep; | |
} | |
/** | |
* Returns an array containing all steps models that have been done until now. | |
* The current step is not included in the returned array. | |
* | |
* @return array list of steps that have been performed until now | |
*/ | |
public function getPath() | |
{ | |
$path = []; | |
foreach ($this->_wiz['path'] as $stepConfig) { | |
$stepModel = $this->createInstance($stepConfig); | |
$path[] = $stepModel; | |
} | |
return $path; | |
} | |
/** | |
* Add the current step to the path and creates the next step form which becomes the new current step. | |
* | |
* @return Model the new current step | |
*/ | |
public function getNextStep() | |
{ | |
$nextStep = null; | |
if ( $this->hasCurrentStep()) { | |
// add current step to the path | |
$currentStep = $this->getCurrentStep(); | |
$this->_wiz['path'][$currentStep->getWorkflowStatus()->getId()] = $this->_wiz['current']; | |
$this->_wiz['current'] = null; | |
// find the next step | |
$nextStatuses = $currentStep->getNextStatuses(true, true); | |
$nextStep = null; | |
if( count($nextStatuses) != 0) { | |
foreach($nextStatuses as $info) { | |
if( $info['isValid']) { | |
// create the next step Form instance | |
$nextStep = $this->createInstance(['status' => $info['status']->getId()]); | |
// save it as the current step | |
$this->_wiz['current'] = $nextStep->getAttributes(); | |
break; | |
} | |
} | |
} | |
} | |
return $nextStep; | |
} | |
/** | |
* Replace the current step, with the last step of the path and returns it. | |
* | |
* @return Model the new current step | |
*/ | |
public function getPreviousStep() | |
{ | |
$prevStep = null; | |
if( count($this->_wiz['path']) != 0) { | |
$config = array_pop($this->_wiz['path']); | |
// replace current step | |
$this->_wiz['current'] = $config; | |
// create instance | |
$prevStep = $this->createInstance($config); | |
} | |
return $prevStep; | |
} | |
/** | |
* Initiate the wizard. | |
* This method reset the existing wizard path and returns the model for the first step. | |
* | |
* @return Model the model for the first step | |
*/ | |
public function start() | |
{ | |
$workflow = $this->workflowSource->getWorkflow('Wizflow'); | |
$status = $workflow->getInitialStatus(); | |
$config = $status->getMetadata('model'); | |
$config['status'] = $status->getId(); | |
$firstStep = $this->createInstance($config); | |
$this->_wiz['current'] = $firstStep->getAttributes(); | |
$this->_wiz['path'] = []; | |
return $firstStep; | |
} | |
/** | |
* Clean up session data that may have been stored by this wizard. | |
*/ | |
public function destroy() | |
{ | |
Yii::$app->session->remove($this->skeyName); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment