Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00%
0 / 1
58.33%
7 / 12
CRAP
89.90%
89 / 99
SWPhpWorkflowSource
0.00%
0 / 1
58.33%
7 / 12
42.73
89.90%
89 / 99
 init()
100.00%
1 / 1
5
100.00%
11 / 11
 _load($wfId, $forceReload)
0.00%
0 / 1
8.01
94.44%
17 / 18
 _createWorkflow($wf,$wfId)
0.00%
0 / 1
9.76
78.95%
15 / 19
 _getNode($swNode)
0.00%
0 / 1
3.10
77.78%
7 / 9
 isWorkflowLoaded($workflowId)
100.00%
1 / 1
1
100.00%
1 / 1
 loadWorkflow($workflowId,$forceReload=false)
100.00%
1 / 1
1
100.00%
1 / 1
 addWorkflow($definition, $id)
100.00%
1 / 1
3
100.00%
6 / 6
 getNodeDefinition($node, $defaultWorkflowId=null)
100.00%
1 / 1
1
100.00%
3 / 3
 getNextNodes($sourceNode,$workflowId=null)
0.00%
0 / 1
3.01
90.00%
9 / 10
 isNextNode($sourceNode,$targetNode,$workflowId=null)
0.00%
0 / 1
3.05
81.82%
9 / 11
 getInitialNode($workflowId)
100.00%
1 / 1
1
100.00%
2 / 2
 getAllNodes($workflowId)
100.00%
1 / 1
3
100.00%
8 / 8
<?php
/**
* This class gives access to workflow and statuses stored as PHP files.
* Following attributes can be initialized when the component is configured:
* <ul>
* <li><b>basePath</b> (string) : the base path alias where all workflow are stored.By default, it is set to
* application.models.workflows (folder "protected/models/workflows").
* </li>
* <li><b>definitionType</b> (string) : Defines the type of PHP file to load. A Workflow can be defined in
* a PHP file that contains a simple array definition (definitionType = 'array'), or by a
* class (definitionType = 'class'). By default this attribute is set to 'array'.
* </li>
* </ul>
*/
class SWPhpWorkflowSource extends SWWorkflowSource
{
/**
* @var string the base path alias where all workflow are stored.By default, it is set to
* application.models.workflows (folder "protected/models/workflows").
*/
public $basePath = 'application.models.workflows';
/**
* @var string Definition type for workflow. Allowed values are : class, array. Default is 'array'
*/
public $definitionType = 'array';
private $_workflow; // workflow definition collection
private $_workflowBasePath;
/**
* Initialize the component with configured values. To preload workflows, set configuration
* setting 'preload' to an array containing all workflows to preload. If no preload is set
* workflows are loaded on demand.
*
* @see SWWorkflowSource
*/
public function init()
{
parent::init();
$this->_workflowBasePath = Yii::getPathOfAlias($this->basePath);
if( is_array($this->preload) and count($this->preload)!=0){
foreach ( $this->preload as $wfId ) {
$this->_load($wfId,true);
}
}
if( $this->definitionType == 'class'){
Yii::import($this->basePath.'.*');
}
}
//
///////////////////////////////////////////////////////////////////////////////////
// private methods
/**
* Loads a workflow from a php source file into the $this->_workflow
* associative array. A call to reset() will unload all workflows.
*/
private function _load($wfId, $forceReload)
{
if( !is_string($wfId) or empty($wfId))
{
throw new SWException('failed to load workflow - invalid workflow Id : '.$wfId,SWException::SW_ERR_WORKFLOW_ID);
}
if( !isset($this->_workflow[$wfId]) or $forceReload==true)
{
if($this->definitionType == 'class')
{
$wo = new $wfId;
$this->_workflow[$wfId] = $this->_createWorkflow($wo->getDefinition(),$wfId);
}
elseif( $this->definitionType == 'array')
{
$fname=$this->_workflowBasePath.DIRECTORY_SEPARATOR.$wfId.'.php';
if( file_exists($fname)==false){
throw new SWException('workflow definition file not found : '.$fname,SWException::SW_ERR_WORKFLOW_NOT_FOUND);
}
$this->_workflow[$wfId] = $this->_createWorkflow(require($fname),$wfId);
}
}
return $this->_workflow[$wfId];
}
/**
* @param array $wf workflow definition
* @param string $wfId workflow Id
*/
private function _createWorkflow($wf,$wfId)
{
if(!is_array($wf) || empty($wfId)){
throw new SWException('invalid argument');
}
$wfDefinition=array();
if( !isset($wf['initial'])) {
throw new SWException('missing initial status for workflow : '.$wfId,SWException::SW_ERR_IN_WORKFLOW);
}
// load node list
$nodeIds = array();
foreach($wf['node'] as $rnode)
{
$node=new SWNode($rnode,$wfId);
if(in_array($node->getId(),$nodeIds )){
throw new SWException('duplicate node id : '.$node->getId(),SWException::SW_ERR_IN_WORKFLOW);
}else{
$nodeIds[] = $node->getId();
}
$wfDefinition[$node->getId()]=$node;
if( $node->getId()==$wf['initial'] || $node->toString() == $wf['initial']){
$wfDefinition['swInitialNode']= $node;
}
}
// checks that initialnode is set
if(!isset($wfDefinition['swInitialNode'])){
throw new SWException('missing initial status for workflow : '.$wfId,SWException::SW_ERR_IN_WORKFLOW);
}
return $wfDefinition;
}
/**
* Returns the SWNode object from the workflow collection.
*
* @param SWnode swNode node to search for in the node list
* @return SWNode the SWNode object retrieved from the workflow collection, or NULL if this
* node could not be found in the workflow collection
*/
private function _getNode($swNode)
{
$wfId=$swNode->getWorkflowId();
if($wfId==null)
{
throw new SWException('workflow not found : '.$wfId,SWException::SW_ERR_WORKFLOW_NOT_FOUND);
}
$this->_load($wfId,false);
$nodeId=$swNode->getId();
if(isset($this->_workflow[$wfId][$nodeId])){
return $this->_workflow[$wfId][$nodeId];
}else {
return null;
}
}
//
///////////////////////////////////////////////////////////////////////////////////
// public methods
/**
* Verify if a workflow has been loaded.
*
* @param string $workflowId workflow id
* @return boolean TRUE if the workflow whose id is $workflowId has already been loaded,
* FALSE otherwise
*/
public function isWorkflowLoaded($workflowId)
{
return isset($this->_workflow[$workflowId]);
}
/**
* Loads the workflow whose id is passed as argument.
* By default, if the workflow has already been loaded it is not reloaded unless
* $forceReload is TRUE
* @param string $workflowId the workflow id
* @param boolean $forceReload TRUE to force workflow loading, FALSE otherwise
*/
public function loadWorkflow($workflowId,$forceReload=false)
{
return $this->_load($workflowId,$forceReload) != null;
}
/**
* This method is used to add a new workflow definition to the current workflow collection.
* @param array $definition the workflow definition in its array form
* @param string $id the workflow id
*/
public function addWorkflow($definition, $id)
{
if(!is_array($definition))
throw new SWException('array expected');
if( ! isset($this->_workflow[$id])){
$this->_workflow[$id] = $this->_createWorkflow($definition,$id);
}
}
/**
* (non-PHPdoc)
* @see SWWorkflowSource::getNodeDefinition()
*/
public function getNodeDefinition($node, $defaultWorkflowId=null)
{
return $this->_getNode(
$this->createSWNode($node,$defaultWorkflowId)
);
}
/**
* (non-PHPdoc)
* @see SWWorkflowSource::getNextNodes()
*/
public function getNextNodes($sourceNode,$workflowId=null)
{
$result=array();
// convert startStatus into SWNode
$startNode=$this->getNodeDefinition(
$this->createSWNode($sourceNode,$workflowId)
);
if($startNode==null){
throw new SWException('node could not be found : '.$sourceNode,SWException::SW_ERR_NODE_NOT_FOUND);
}else {
foreach($startNode->getNext() as $nxtNodeId => $tr){
$result[]=$this->_getNode(new SWNode($nxtNodeId,$workflowId));
}
}
return $result;
}
/**
* (non-PHPdoc)
* @see SWWorkflowSource::isNextNode()
*/
public function isNextNode($sourceNode,$targetNode,$workflowId=null)
{
$startNode=$this->createSWNode($sourceNode,$workflowId);
$nextNode=$this->createSWNode(
$targetNode,
( $workflowId!=null
? $workflowId
: $startNode->getWorkflowId()
)
);
$nxt=$this->getNextNodes($startNode);
if( $nxt != null){
return in_array($nextNode->toString(),$nxt);
}else {
return false;
}
}
/**
* (non-PHPdoc)
* @see SWWorkflowSource::getInitialNode()
*/
public function getInitialNode($workflowId)
{
$this->_load($workflowId,false);
return $this->_workflow[$workflowId]['swInitialNode'];
}
/**
* (non-PHPdoc)
* @see SWWorkflowSource::getAllNodes()
*/
public function getAllNodes($workflowId)
{
$result=array();
$wf=$this->_load($workflowId,false);
foreach($wf as $key => $value){
if($key!='swInitialNode'){
$result[]=$value;
}
}
return $result;
}
}
?>