1 <?php
2 3 4 5 6 7 8 9 10 11 12 13 14
15 class SWPhpWorkflowSource extends SWWorkflowSource
16 {
17 18 19 20
21 public $basePath = 'application.models.workflows';
22 23 24
25 public $definitionType = 'array';
26
27 private $_workflow;
28 private $_workflowBasePath;
29 30 31 32 33 34 35
36 public function init()
37 {
38 parent::init();
39 $this->_workflowBasePath = Yii::getPathOfAlias($this->basePath);
40 if( is_array($this->preload) and count($this->preload)!=0){
41 foreach ( $this->preload as $wfId ) {
42 $this->_load($wfId,true);
43 }
44 }
45 if( $this->definitionType == 'class'){
46 Yii::import($this->basePath.'.*');
47 }
48 }
49
50
51
52
53
54 55 56 57
58 private function _load($wfId, $forceReload)
59 {
60 if( !is_string($wfId) or empty($wfId))
61 {
62 throw new SWException('failed to load workflow - invalid workflow Id : '.$wfId,SWException::SW_ERR_WORKFLOW_ID);
63 }
64
65 if( !isset($this->_workflow[$wfId]) or $forceReload==true)
66 {
67
68 if($this->definitionType == 'class')
69 {
70 $wo = new $wfId;
71 $this->_workflow[$wfId] = $this->_createWorkflow($wo->getDefinition(),$wfId);
72 }
73 elseif( $this->definitionType == 'array')
74 {
75 $fname=$this->_workflowBasePath.DIRECTORY_SEPARATOR.$wfId.'.php';
76 if( file_exists($fname)==false){
77 throw new SWException('workflow definition file not found : '.$fname,SWException::SW_ERR_WORKFLOW_NOT_FOUND);
78 }
79
80 $this->_workflow[$wfId] = $this->_createWorkflow(require($fname),$wfId);
81 }
82 }
83 return $this->_workflow[$wfId];
84 }
85 86 87 88
89 private function _createWorkflow($wf,$wfId)
90 {
91 if(!is_array($wf) || empty($wfId)){
92 throw new SWException('invalid argument');
93 }
94 $wfDefinition=array();
95
96 if( !isset($wf['initial'])) {
97 throw new SWException('missing initial status for workflow : '.$wfId,SWException::SW_ERR_IN_WORKFLOW);
98 }
99
100
101 $nodeIds = array();
102 foreach($wf['node'] as $rnode)
103 {
104 $node=new SWNode($rnode,$wfId);
105
106 if(in_array($node->getId(),$nodeIds )){
107 throw new SWException('duplicate node id : '.$node->getId(),SWException::SW_ERR_IN_WORKFLOW);
108 }else{
109 $nodeIds[] = $node->getId();
110 }
111
112 $wfDefinition[$node->getId()]=$node;
113 if( $node->getId()==$wf['initial'] || $node->toString() == $wf['initial']){
114 $wfDefinition['swInitialNode']= $node;
115 }
116 }
117
118
119 if(!isset($wfDefinition['swInitialNode'])){
120 throw new SWException('missing initial status for workflow : '.$wfId,SWException::SW_ERR_IN_WORKFLOW);
121 }
122
123 return $wfDefinition;
124 }
125 126 127 128 129 130 131
132 private function _getNode($swNode)
133 {
134 $wfId=$swNode->getWorkflowId();
135 if($wfId==null)
136 {
137 throw new SWException('workflow not found : '.$wfId,SWException::SW_ERR_WORKFLOW_NOT_FOUND);
138 }
139
140 $this->_load($wfId,false);
141 $nodeId=$swNode->getId();
142 if(isset($this->_workflow[$wfId][$nodeId])){
143 return $this->_workflow[$wfId][$nodeId];
144 }else {
145 return null;
146 }
147 }
148
149
150
151
152 153 154 155 156 157 158
159 public function isWorkflowLoaded($workflowId)
160 {
161 return isset($this->_workflow[$workflowId]);
162 }
163 164 165 166 167 168 169
170 public function loadWorkflow($workflowId,$forceReload=false)
171 {
172 return $this->_load($workflowId,$forceReload) != null;
173 }
174 175 176 177 178
179 public function addWorkflow($definition, $id)
180 {
181 if(!is_array($definition))
182 throw new SWException('array expected');
183
184 if( ! isset($this->_workflow[$id])){
185 $this->_workflow[$id] = $this->_createWorkflow($definition,$id);
186 }
187 }
188 189 190 191
192 public function getNodeDefinition($node, $defaultWorkflowId=null)
193 {
194 return $this->_getNode(
195 $this->createSWNode($node,$defaultWorkflowId)
196 );
197 }
198 199 200 201
202 public function getNextNodes($sourceNode,$workflowId=null)
203 {
204 $result=array();
205
206
207
208 $startNode=$this->getNodeDefinition(
209 $this->createSWNode($sourceNode,$workflowId)
210 );
211
212 if($startNode==null){
213 throw new SWException('node could not be found : '.$sourceNode,SWException::SW_ERR_NODE_NOT_FOUND);
214 }else {
215 foreach($startNode->getNext() as $nxtNodeId => $tr){
216 $result[]=$this->_getNode(new SWNode($nxtNodeId,$workflowId));
217 }
218 }
219 return $result;
220 }
221 222 223 224
225 public function isNextNode($sourceNode,$targetNode,$workflowId=null)
226 {
227 $startNode=$this->createSWNode($sourceNode,$workflowId);
228 $nextNode=$this->createSWNode(
229 $targetNode,
230 ( $workflowId!=null
231 ? $workflowId
232 : $startNode->getWorkflowId()
233 )
234 );
235
236 $nxt=$this->getNextNodes($startNode);
237 if( $nxt != null){
238 return in_array($nextNode->toString(),$nxt);
239 }else {
240 return false;
241 }
242 }
243 244 245 246
247 public function getInitialNode($workflowId)
248 {
249 $this->_load($workflowId,false);
250 return $this->_workflow[$workflowId]['swInitialNode'];
251 }
252 253 254 255
256 public function getAllNodes($workflowId)
257 {
258 $result=array();
259 $wf=$this->_load($workflowId,false);
260 foreach($wf as $key => $value){
261 if($key!='swInitialNode'){
262 $result[]=$value;
263 }
264 }
265 return $result;
266 }
267 }
268 ?>
269