Path

ez components / documentation / api reference / trunk / workflow


eZ Components trunk

Workflow

[ Tutorial ] [ Class tree ] [ Element index ] [ ChangeLog ] [ Credits ]

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 addInNodeezcWorkflowNode $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 removeInNodeezcWorkflowNode $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 addOutNodeezcWorkflowNode $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 removeOutNodeezcWorkflowNode $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 setActivatedFromarray $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 acceptezcWorkflowVisitor $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 activateezcWorkflowExecution $executionezcWorkflowNode $activatedFrom null$threadId )
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 activateNodeezcWorkflowExecution $executionezcWorkflowNode $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 executeezcWorkflowExecution $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 configurationFromXMLDOMElement $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 configurationToXMLDOMElement $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 && 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->setActivationStateself::WAITING_FOR_ACTIVATION );
655.     }
656. }
657. ?>
Last updated: Mon, 21 Dec 2009