Workflow
[ ]
[ ]
[ ]
[ ]
[ ]
Source for file node.php
Documentation is available at node.php
1. <?php
2. /**
3. * File containing the ezcWorkflowNode class.
4. *
5. * This class provides basic facilities for workflow nodes
6. * such as constraints for in and output nodes and methods
7. * for identifying and execution of the node.
8. *
9. * @package Workflow
10. * @version //autogen//
11. * @copyright Copyright (C) 2005-2009 eZ Systems AS. All rights reserved.
12. * @license http://ez.no/licenses/new_bsd New BSD License
13. */
14.
15. /**
16. * Abstract base class for workflow nodes.
17. *
18. * All workflow nodes must extend this class.
19. *
20. * @package Workflow
21. * @version //autogen//
22. * @mainclass
23. */
24. abstract class ezcWorkflowNode implements ezcWorkflowVisitable
25. {
26. /**
27. * The node is waiting to be activated.
28. */
29. const WAITING_FOR_ACTIVATION = 0;
30.
31. /**
32. * The node is activated and waiting to be executed.
33. */
34. const WAITING_FOR_EXECUTION = 1;
35.
36. /**
37. * Unique ID of this node.
38. *
39. * Only available when the workflow this node belongs to has been loaded
40. * from or saved to the data storage.
41. *
42. * @var integer
43. */
44. protected $id = false;
45.
46. /**
47. * The incoming nodes of this node.
48. *
49. * @var array( int => ezcWorkflowNode )
50. */
51. protected $inNodes = array();
52.
53. /**
54. * The outgoing nodes of this node.
55. *
56. * @var array( int => ezcWorkflowNode )
57. */
58. protected $outNodes = array();
59.
60. /**
61. * Constraint: The minimum number of incoming nodes this node has to have
62. * to be valid. Set to false to disable this constraint.
63. *
64. * @var integer
65. */
66. protected $minInNodes = 1;
67.
68. /**
69. * Constraint: The maximum number of incoming nodes this node has to have
70. * to be valid. Set to false to disable this constraint.
71. *
72. * @var integer
73. */
74. protected $maxInNodes = 1;
75.
76. /**
77. * Constraint: The minimum number of outgoing nodes this node has to have
78. * to be valid. Set to false to disable this constraint.
79. *
80. * @var integer
81. */
82. protected $minOutNodes = 1;
83.
84. /**
85. * Constraint: The maximum number of outgoing nodes this node has to have
86. * to be valid. Set to false to disable this constraint.
87. *
88. * @var integer
89. */
90. protected $maxOutNodes = 1;
91.
92. /**
93. * The number of incoming nodes.
94. *
95. * @var integer
96. */
97. protected $numInNodes = 0;
98.
99. /**
100. * The number of outgoing nodes.
101. *
102. * @var integer
103. */
104. protected $numOutNodes = 0;
105.
106. /**
107. * The configuration of this node.
108. *
109. * The configuration is a structured (hash) array with the
110. * various options of the implemented node.
111. *
112. * This functionality is implemented as an array to make it possible
113. * to have the storage engines unaware of the node classes.
114. *
115. * @var array( config key => config value )
116. */
117. protected $configuration;
118.
119. /**
120. * The state of this node.
121. *
122. * @var integer
123. */
124. protected $activationState;
125.
126. /**
127. * The node(s) that activated this node.
128. *
129. * @var ezcWorkflowNode[]
130. */
131. protected $activatedFrom = array();
132.
133. /**
134. * The state of this node.
135. *
136. * @var mixed
137. */
138. protected $state = null;
139.
140. /**
141. * The id of the thread this node is executing in.
142. *
143. * @var integer
144. */
145. protected $threadId = null;
146.
147. /**
148. * Flag that indicates whether an add*Node() or remove*Node()
149. * call is internal. This is necessary to avoid unlimited loops.
150. *
151. * @var boolean
152. */
153. protected static $internalCall = false;
154.
155. /**
156. * Constructs a new node with the configuration $configuration.
157. *
158. * The configuration is a structured (hash) array. Implementations
159. * must pass their complete configuration on to this object. We have
160. * chosen to use structured arrays for the configuration since it
161. * simplifies the process of creating new node types and storing workflows.
162. *
163. * @param mixed $configuration
164. */
165. public function __construct( $configuration = null )
166. {
167. if ( $configuration !== null )
168. {
169. $this->configuration = $configuration;
170. }
171.
172. $this->initState();
173. }
174.
175. /**
176. * Adds a node to the incoming nodes of this node.
177. *
178. * Automatically adds $node to the workflow and adds
179. * this node as an out node of $node.
180. *
181. * @param ezcWorkflowNode $node The node that is to be added as incoming node.
182. * @throws ezcWorkflowInvalidWorkflowException if the operation violates the constraints of the nodes involved.
183. * @return ezcWorkflowNode
184. */
185. public function addInNode( ezcWorkflowNode $node )
186. {
187. // Check whether the node is already an incoming node of this node.
188. if ( ezcWorkflowUtil::findObject( $this->inNodes, $node ) === false )
189. {
190. // Add this node as an outgoing node to the other node.
191. if ( !self::$internalCall )
192. {
193. self::$internalCall = true;
194. $node->addOutNode( $this );
195. }
196. else
197. {
198. self::$internalCall = false;
199. }
200.
201. // Add the other node as an incoming node to this node.
202. $this->inNodes[] = $node;
203. $this->numInNodes++;
204. }
205.
206. return $this;
207. }
208.
209. /**
210. * Removes a node from the incoming nodes of this node.
211. *
212. * Automatically removes $this as an out node of $node.
213. *
214. * @param ezcWorkflowNode $node The node that is to be removed as incoming node.
215. * @throws ezcWorkflowInvalidWorkflowException if the operation violates the constraints of the nodes involved.
216. * @return boolean
217. */
218. public function removeInNode( ezcWorkflowNode $node )
219. {
220. $index = ezcWorkflowUtil::findObject( $this->inNodes, $node );
221.
222. if ( $index !== false )
223. {
224. // Remove this node as an outgoing node from the other node.
225. if ( !self::$internalCall )
226. {
227. self::$internalCall = true;
228. $node->removeOutNode( $this );
229. }
230. else
231. {
232. self::$internalCall = false;
233. }
234.
235. unset( $this->inNodes[$index] );
236. $this->numInNodes--;
237.
238. return true;
239. }
240.
241. return false;
242. }
243.
244. /**
245. * Adds a node to the outgoing nodes of this node.
246. *
247. * Automatically adds $node to the workflow and adds
248. * this node as an in node of $node.
249. *
250. * @param ezcWorkflowNode $node The node that is to be added as outgoing node.
251. * @throws ezcWorkflowInvalidWorkflowException if the operation violates the constraints of the nodes involved.
252. * @return ezcWorkflowNode
253. */
254. public function addOutNode( ezcWorkflowNode $node )
255. {
256. // Check whether the other node is already an outgoing node of this node.
257. if ( ezcWorkflowUtil::findObject( $this->outNodes, $node ) === false )
258. {
259. // Add this node as an incoming node to the other node.
260. if ( !self::$internalCall )
261. {
262. self::$internalCall = true;
263. $node->addInNode( $this );
264. }
265. else
266. {
267. self::$internalCall = false;
268. }
269.
270. // Add the other node as an outgoing node to this node.
271. $this->outNodes[] = $node;
272. $this->numOutNodes++;
273. }
274.
275. return $this;
276. }
277.
278. /**
279. * Removes a node from the outgoing nodes of this node.
280. *
281. * Automatically removes $this as an in node of $node.
282. *
283. * @param ezcWorkflowNode $node The node that is to be removed as outgoing node.
284. * @throws ezcWorkflowInvalidWorkflowException if the operation violates the constraints of the nodes involved.
285. * @return boolean
286. */
287. public function removeOutNode( ezcWorkflowNode $node )
288. {
289. $index = ezcWorkflowUtil::findObject( $this->outNodes, $node );
290.
291. if ( $index !== false )
292. {
293. // Remove this node as an incoming node from the other node.
294. if ( !self::$internalCall )
295. {
296. self::$internalCall = true;
297. $node->removeInNode( $this );
298. }
299. else
300. {
301. self::$internalCall = false;
302. }
303.
304. unset( $this->outNodes[$index] );
305. $this->numOutNodes--;
306.
307. return true;
308. }
309.
310. return false;
311. }
312.
313. /**
314. * Returns the Id of this node.
315. *
316. * @return integer
317. * @ignore
318. */
319. public function getId()
320. {
321. return $this->id;
322. }
323.
324. /**
325. * Sets the Id of this node.
326. *
327. * @param int $id
328. * @ignore
329. */
330. public function setId( $id )
331. {
332. $this->id = $id;
333. }
334.
335. /**
336. * Sets the activation state for this node.
337. *
338. * One of ezcWorkflowNode::WAITING_FOR_ACTIVATION or
339. * ezcWorkflowNode::WAITING_FOR_EXECUTION.
340. *
341. * @param int $activationState
342. * @ignore
343. */
344. public function setActivationState( $activationState )
345. {
346. if ( $activationState == self::WAITING_FOR_ACTIVATION ||
347. $activationState == self::WAITING_FOR_EXECUTION )
348. {
349. $this->activationState = $activationState;
350. }
351. }
352.
353. /**
354. * Returns the incoming nodes of this node.
355. *
356. * @return ezcWorkflowNode[]
357. */
358. public function getInNodes()
359. {
360. return $this->inNodes;
361. }
362.
363. /**
364. * Returns the outgoing nodes of this node.
365. *
366. * @return ezcWorkflowNode[]
367. */
368. public function getOutNodes()
369. {
370. return $this->outNodes;
371. }
372.
373. /**
374. * Returns the configuration of this node.
375. *
376. * @return mixed
377. */
378. public function getConfiguration()
379. {
380. return $this->configuration;
381. }
382.
383. /**
384. * Returns the state of this node.
385. *
386. * @return mixed
387. * @ignore
388. */
389. public function getState()
390. {
391. return $this->state;
392. }
393.
394. /**
395. * Sets the state of this node.
396. *
397. * @param mixed $state
398. * @ignore
399. */
400. public function setState( $state )
401. {
402. $this->state = $state;
403. }
404.
405. /**
406. * Returns the node(s) that activated this node.
407. *
408. * @return array
409. * @ignore
410. */
411. public function getActivatedFrom()
412. {
413. return $this->activatedFrom;
414. }
415.
416. /**
417. * Sets the node(s) that activated this node.
418. *
419. * @param array $activatedFrom
420. * @ignore
421. */
422. public function setActivatedFrom( array $activatedFrom )
423. {
424. $this->activatedFrom = $activatedFrom;
425. }
426.
427. /**
416. /**
417. * Returns the id of the thread this node is executing in.
418. *
419. * @return integer
420. * @ignore
432. */
433. public function getThreadId()
434. {
435. return $this->threadId;
436. }
437.
438. /**
439. * Sets the id of the thread this node is executing in.
440. *
441. * @param int $threadId
442. * @ignore
443. */
444. public function setThreadId( $threadId )
445. {
446. $this->threadId = $threadId;
447. }
448.
449. /**
450. * Checks this node's constraints.
451. *
452. * The constraints checked are the minimum in nodes
453. * maximum in nodes, minimum out nodes and maximum
454. * out nodes.
455. *
456. * @throws ezcWorkflowInvalidWorkflowException if the constraints of this node are not met.
457. */
458. public function verify()
459. {
460. $type = str_replace( 'ezcWorkflowNode', '', get_class( $this ) );
461.
462. if ( $this->minInNodes !== false && $this->numInNodes < $this->minInNodes )
463. {
464. throw new ezcWorkflowInvalidWorkflowException(
465. sprintf(
466. 'Node of type "%s" has less incoming nodes than required.',
467. $type
468. )
469. );
470. }
471.
472. if ( $this->maxInNodes !== false && $this->numInNodes > $this->maxInNodes )
473. {
474. throw new ezcWorkflowInvalidWorkflowException(
475. sprintf(
476. 'Node of type "%s" has more incoming nodes than allowed.',
477. $type
478. )
479. );
480. }
481.
482. if ( $this->minOutNodes !== false && $this->numOutNodes < $this->minOutNodes )
483. {
484. throw new ezcWorkflowInvalidWorkflowException(
485. sprintf(
486. 'Node of type "%s" has less outgoing nodes than required.',
487. $type
488. )
489. );
490. }
491.
492. if ( $this->maxOutNodes !== false && $this->numOutNodes > $this->maxOutNodes )
493. {
494. throw new ezcWorkflowInvalidWorkflowException(
495. sprintf(
496. 'Node of type "%s" has more outgoing nodes than allowed.',
497. $type
498. )
499. );
500. }
501. }
502.
503. /**
504. * Reimplementation of accept() calls accept on all out nodes.
505. *
506. * @param ezcWorkflowVisitor $visitor
507. */
508. public function accept( ezcWorkflowVisitor $visitor )
509. {
510. if ( $visitor->visit( $this ) )
511. {
512. foreach ( $this->outNodes as $outNode )
513. {
514. $outNode->accept( $visitor );
515. }
516. }
517. }
518.
519. /**
520. * Activate this node in the execution environment $execution.
521. *
522. * $activatedFrom is the node that activated this node and $threadId is
523. * threadId of the thread the node should be activated in.
524. *
525. * This method is called by other nodes and/or the execution environment
526. * depending on the workflow.
527. *
528. * @param ezcWorkflowExecution $execution
529. * @param ezcWorkflowNode $activatedFrom
530. * @param int $threadId
531. * @ignore
532. */
533. public function activate( ezcWorkflowExecution $execution, ezcWorkflowNode $activatedFrom = null, $threadId = 0 )
534. {
535. if ( $this->activationState === self::WAITING_FOR_ACTIVATION )
536. {
537. $this->activationState = self::WAITING_FOR_EXECUTION;
538. $this->setThreadId( $threadId );
539.
540. if ( $activatedFrom !== null )
541. {
542. $this->activatedFrom[] = get_class( $activatedFrom );
543. }
544.
545. $execution->activate( $this );
546. }
547. }
548.
549. /**
550. * Convenience method for activating an (outgoing) node.
551. *
552. * @param ezcWorkflowExecution $execution
553. * @param ezcWorkflowNode $node
554. */
555. protected function activateNode( ezcWorkflowExecution $execution, ezcWorkflowNode $node )
556. {
557. $node->activate( $execution, $this, $this->getThreadId() );
558. }
559.
560. /**
561. * Returns true if this node is ready for execution
562. * and false if it is not.
563. *
564. * @return boolean
565. * @ignore
566. */
567. public function isExecutable()
568. {
569. return $this->activationState === self::WAITING_FOR_EXECUTION;
570. }
571.
572. /**
573. * Executes and performs the workflow duties of this node
574. * and returns true if the node completed execution.
575. *
576. * Implementations of ezcWorkflowNode should reimplement this method.
577. *
578. * This method is called automatically by the workflow execution
579. * environment and should not be called directly.
580. *
581. * The default implementation resets the activation state of the
582. * node.
583. *
584. * @param ezcWorkflowExecution $execution
585. * @return boolean true when the node finished execution,
586. * and false otherwise
587. * @ignore
588. */
589. public function execute( ezcWorkflowExecution $execution )
590. {
591. $this->activationState = self::WAITING_FOR_ACTIVATION;
592. $this->activatedFrom = array();
593. $this->threadId = null;
594.
595. return true;
596. }
597.
598. /**
599. * Generate node configuration from XML representation.
600. *
601. * @param DOMElement $element
602. * @ignore
603. */
604. public static function configurationFromXML( DOMElement $element )
605. {
606. }
607.
608. /**
609. * Generate XML representation of this node's configuration.
610. *
611. * @param DOMElement $element
612. * @ignore
613. */
614. public function configurationToXML( DOMElement $element )
615. {
616. }
617.
618. /**
619. * Returns a textual representation of this node.
620. *
621. * @return string
622. * @ignore
623. */
624. public function __toString()
625. {
626. $type = str_replace( 'ezcWorkflowNode', '', get_class( $this ) );
627. $max = strlen( $type );
628. $string = '';
629.
630. for ( $i = 0; $i < $max; $i++ )
631. {
632. if ( $i > 0 && ord( $type[$i] ) >= 65 && ord( $type[$i] ) <= 90 )
633. {
634. $string .= ' ';
635. }
636.
637. $string .= $type[$i];
638. }
639.
640. return $string;
641. }
642.
643. /**
644. * Initializes the state of this node.
645. *
646. * @ignore
647. */
648. public function initState()
649. {
650. $this->activatedFrom = array();
651. $this->state = null;
652. $this->threadId = null;
653.
654. $this->setActivationState( self::WAITING_FOR_ACTIVATION );
655. }
656. }
657. ?>
Last updated: Mon, 21 Dec 2009