simpleWorkflow
  • Class
  • Tree

Classes

  • SWActiveRecord
  • SWActiveRecordBehavior
  • SWComponent
  • SWEvent
  • SWException
  • SWHelper
  • SWNode
  • SWPhpWorkflowSource
  • SWValidator
  • SWWorkflowSource
  • SWyEdConverter
  • SWyEdConverterDOM
  1 <?php
  2 /**
  3  * <p>
  4  * This validator should be used to validate the 'status' attribute for an active record
  5  * object before it is saved. It tests if the transition that is about to occur is valid.<br/>
  6  * Moreover, if <strong>$enableSwValidation</strong> is set to <b>true</b>, this validator applies all
  7  * validators that may have been defined by the model for the scenario associated to the transition
  8  * being done.<br/>
  9  * Scenario names associated with a transition, have the following format :
 10  * <pre>
 11  *  sw:[currentStatus]-[nextStatus]
 12  *  </pre>
 13  * For instance, if the model being validated is currently in status 'A' and it is sent in status 'B', the
 14  * corresponding scenario name is 'sw:A-B'. Note that if the destination status doesn't belong to the same
 15  * workflow as the current status, [nextStatus] must be in the form 'workflowId/statusId' (e.g 'sw:A-workflow/B').
 16  * Eventually, when the model enters in a workflow, the scenario name is '-[nextStatus]' where 'nextStatus'
 17  * includes the workflow Id (e.g 'sw:-workflowIs/statusId').
 18  * </p>
 19  * <p>
 20  *  If this validator is initialized with parameter <b>match</b> set to TRUE, then transitions scenario defined
 21  * for validators are assumed to be regular expressions. If the current transition matches, then the associated
 22  * validator is executed.<br/>
 23  * For instance, if validator 'required' for attribute A applies to scenarion 'sw:/S1_.?/' then each time the
 24  * model leaves status S1, then the <em>required</em> validator will be applied.
 25  * </p>
 26  */
 27 class SWValidator extends CValidator
 28 {
 29     /**
 30      * @var boolean (default FALSE) Enables simpleWorkflow Validation. When TRUE, the SWValidator not only
 31      * validates status change for the model, but also applies all validators that may have been created and
 32      * which are associated with the scenario for the transition being done. Such scenario names are based on
 33      * both the current and the next status name.
 34      */
 35     public $enableSwValidation=false;
 36     /**
 37      * @var boolean (default FALSE) When true, the scenario name is evaluated as a regular expression that must
 38      * match the transition name being done.
 39      */
 40     public $match=false;
 41     
 42     const SW_SCENARIO_STATUS_SEPARATOR='-';
 43     const SW_SCENARIO_PREFIX='sw:';
 44     private $_lenPrefix=null;
 45     /**
 46      * Validate status change and applies all validators defined by the model for the current transition scenario if
 47      * enableSwValidation is TRUE. If validator parameter 'match' is true, the transition scenario is matched
 48      * against validator scenario (which are assumed to be regular expressions).
 49      *
 50      * @see validators/CValidator::validateAttribute()
 51      * @param CModel $model the model to validate
 52      * @param string $attribute the model attribute to validate
 53      */
 54     protected function validateAttribute($model,$attribute)
 55     {
 56         $value=$model->$attribute;
 57         
 58         if($model->swValidate($attribute,$value)==true and $this->enableSwValidation ===true){
 59 
 60             $swScenario=$this->_getSWScenarioName($model, $value);
 61             
 62             if(!empty($swScenario))
 63             {
 64                 if($this->match === true){
 65                     
 66                     // validator scenario are Regular Expression that must match the transition scenarion
 67                     // for the validator to be executed.
 68                     
 69                     $validators=$model->getValidatorList();
 70                     foreach($validators as $validator)
 71                     {
 72                         if($this->_validatorMatches($validator,$swScenario)){
 73                             $validator->validate($model);
 74                         }
 75                     }
 76                 }else {
 77                     $swScenario=SWValidator::SW_SCENARIO_PREFIX.$swScenario;
 78                     // execute only validator defined for the current transition scenario ($swScenario)
 79                     
 80                     // getValidators returns validators with no scenario, and the ones
 81                     // that apply to the current scenario (swScenario).
 82                     
 83                     $saveScenario=$model->getScenario();
 84                     $model->setScenario($swScenario);
 85                     
 86                     $validators=$model->getValidators();
 87                     
 88                     foreach($model->getValidators() as $validator)
 89                     {
 90                         // only run validators that applies to the current (swScenario) scenario
 91                         
 92                         if(isset($validator->on[$swScenario])){
 93                             $validator->validate($model);
 94                         }
 95                     }
 96                     // restore original scenario so validation can continue.
 97                     $model->setScenario($saveScenario);
 98                 }
 99             }
100         }
101     }
102     /**
103      * Create the scenario name for the current transition. Scenario name has following format : <br/>
104      * <pre> [currentStatus]-[nextStatus]</pre>
105      *
106      * @param CModel $model  the model being validated
107      * @param string $nxtStatus  the next status name (destination status for the model)
108      * @return string SW scenario name for this transition
109      *
110      */
111     private function _getSWScenarioName($model,$nxtStatus)
112     {
113         $swScenario=null;
114         $nextNode=$model->swCreateNode($nxtStatus);
115         $curNode=$model->swGetStatus();
116         if( $curNode != null )
117         {
118             $swScenario=$curNode->getId().SWValidator::SW_SCENARIO_STATUS_SEPARATOR;
119             if($curNode->getWorkflowId()!=$nextNode->getWorkflowId()){
120                 $swScenario.=$nextNode->toString();
121             }else {
122                 $swScenario.=$nextNode->getId();
123             }
124         }else {
125             $swScenario=SWValidator::SW_SCENARIO_STATUS_SEPARATOR.$nextNode->toString();
126         }
127         return $swScenario;
128     }
129     /**
130      * Check that a CValidator based object is defined for a scenario that matches
131      * the simple workflow scenario passed as argument.
132      *
133      * @param $validator CValidator validator to test
134      * @param $swScenario string simple workflow scenario defined as a regular expression
135      */
136     private function _validatorMatches($validator,$swScenario)
137     {
138         $bResult=false;
139         if(isset($validator->on)){
140             $validatorScenarios=(is_array($validator->on)?$validator->on:array($validator->on));
141             foreach ($validatorScenarios as $valScenario)
142             {
143                 // SW Scenario validator must begin with a non-empty prefix (default 'sw:')
144                 // and then define a valide regular expression
145                 
146                 $re=$this->_extractSwScenarioPattern($valScenario);
147                 
148                 if( $re != null )
149                 {
150                     if(preg_match($re, $swScenario)){
151                         $bResult=true;
152                         break;
153                     }
154                 }
155             }
156         }
157         return $bResult;
158     }
159     /**
160      * Extract a regular expression pattern out of a simepleWorkflow scenario name
161      *
162      * @param $valScenario String validator scenario name (example : 'sw:/^status1-.*$/')
163      * @return String regular expression (example : '/^status1-.*$/')
164      */
165     private function _extractSwScenarioPattern($valScenario)
166     {
167         $pattern=null;
168         
169         if($this->_lenPrefix==null){
170             $this->_lenPrefix=strlen(SWValidator::SW_SCENARIO_PREFIX);
171         }
172         
173         if( $this->_lenPrefix != 0 &&
174             strpos($valScenario, SWValidator::SW_SCENARIO_PREFIX) === 0)
175         {
176             $pattern=substr($valScenario, $this->_lenPrefix);
177         }
178         return $pattern;
179     }
180 }
181 ?>
182 
simpleWorkflow API documentation generated by ApiGen 2.8.0