Core  3.2
PHP API documentation
 All Data Structures Namespaces Files Functions Variables Pages
CheckWorkflow.php
Go to the documentation of this file.
1 <?php
2 /*
3  * @author Anakeen
4  * @package FDL
5 */
6 /**
7  * Verify several point for the integrity of a workflow
8  * @class CheckWorkflow
9  * @brief Check worflow definition when importing definition
10  * @see ErrorCodeWFL
11  */
13 {
14  /**
15  * @var array
16  */
17  private $terr = array();
18  /**
19  * @var Wdoc
20  */
21  private $wdoc;
22  /**
23  * @var string
24  */
25  private $className;
26  /**
27  * @var string
28  */
29  private $familyName;
30  /**
31  * max column for a table in postgresql
32  */
33  const maxSqlColumn = 1600;
34  /**
35  * number of attributes contructed by transition
36  */
38  /**
39  * number of attributes contructed by state
40  */
42  /**
43  * @var array
44  */
45  private $transitionModelProperties = array(
46  'm0',
47  'm1',
48  'm2',
49  'm3',
50  'ask',
51  'nr'
52  );
53  /**
54  * @var array
55  */
56  private $transitionProperties = array(
57  'e1',
58  'e2',
59  't'
60  );
61  /**
62  * @param string $className workflow class name
63  * @param string $famName workflow family name
64  */
65  public function __construct($className, $famName)
66  {
67  $this->className = $className;
68  $this->familyName = $famName;
69  }
70  /**
71  * @param $code
72  * @param $msg
73  * @deprecated use addCoreError instead
74  */
75  private function addError($code, $msg)
76  {
77  if ($msg) {
78  $msg = sprintf("{%s} %s", $code, $msg);
79  if (!in_array($msg, $this->terr)) {
80  $this->terr[] = $msg;
81  }
82  }
83  }
84  /**
85  * short cut to call ErrorCode::getError
86  * @param $code
87  * @param null $args
88  */
89  private function addCodeError($code, $args = null)
90  {
91  if ($code) {
92  $tArgs = array(
93  $code
94  );
95  $nargs = func_num_args();
96  for ($ip = 1; $ip < $nargs; $ip++) {
97  $tArgs[] = func_get_arg($ip);
98  }
99 
100  $msg = call_user_func_array("ErrorCode::getError", $tArgs);
101  if (!in_array($msg, $this->terr)) {
102  $this->terr[] = $msg;
103  }
104  }
105  }
106 
107  public function getErrorMessage()
108  {
109  return implode("\n", $this->terr);
110  }
111 
112  public function getError()
113  {
114  return $this->terr;
115  }
116  /**
117  * verify php workflow class name
118  * @return array
119  */
120  public function verifyWorkflowClass()
121  {
122  $this->checkClassName();
123  if (!$this->getErrorMessage()) {
124  $this->checkIsAWorkflow();
125  if (!$this->getErrorMessage()) {
126  $this->checkPrefix();
127  $this->checkTransitionModels();
128  $this->checkTransitions();
129  $this->checkActivities();
130  }
131  }
132  return $this->getError();
133  }
134  /**
135  * verify validity with attributes
136  * @return string
137  */
138  public function verifyWorkflowComplete()
139  {
140  $this->verifyWorkflowClass();
141 
142  if (!$this->getErrorMessage()) {
143  $this->checkAskAttributes();
144  }
145  return $this->getError();
146  }
147  public function checkActivities()
148  {
149  $activities = $this->wdoc->stateactivity;
150  if (!is_array($activities)) {
151 
152  $this->addCodeError('WFL0051', $this->className);
153  } else {
154  $states = $this->wdoc->getStates();
155 
156  foreach ($activities as $state => $label) {
157  if (!in_array($state, $states)) {
158  $this->addCodeError('WFL0052', $state, $label, $this->className);
159  }
160  }
161  }
162  }
163 
164  public function checkTransitions()
165  {
166 
167  $cycle = $this->wdoc->cycle;
168  if (!is_array($cycle)) {
169 
170  $this->addCodeError('WFL0200', $this->className);
171  } else {
172  foreach ($cycle as $k => $state) {
173  if (!is_array($state)) {
174  $this->addCodeError('WFL0203', $k, $this->className, gettype($state));
175  continue;
176  }
177  $props = array_keys($state);
178  $diff = array_diff($props, $this->transitionProperties);
179  if (count($diff) > 0) {
180 
181  $this->addCodeError('WFL0201', implode(',', $diff) , $k, $this->className, implode(',', $this->transitionProperties));
182  }
183  if (!empty($state["e1"])) $this->checkTransitionStateKey($state["e1"]);
184  if (!empty($state["e2"])) $this->checkTransitionStateKey($state["e2"]);
185  if (!empty($state["t"])) {
186  } else {
187  $this->addCodeError('WFL0202', $k, $this->className);
188  }
189  }
190  }
191  }
192 
193  public function checkTransitionModels()
194  {
195 
196  $transitions = $this->wdoc->transitions;
197  if (!is_array($transitions)) {
198  $this->addCodeError('WFL0100', $this->className);
199  } else {
200  $columnNumber = count($transitions) * self::numberAttributeTransition + count($this->wdoc->getStates()) * self::numberAttributeState + count($this->wdoc->fields) + count($this->wdoc->sup_fields);
201 
202  if ($columnNumber > self::maxSqlColumn) {
203  $this->addCodeError('WFL0102', $this->className, $columnNumber, self::maxSqlColumn);
204  }
205  $index = 0;
206  foreach ($transitions as $tkey => $transition) {
207  if (!is_array($transition)) {
208  $this->addCodeError('WFL0110', $tkey, $index, $this->className, gettype($transition));
209  continue;
210  }
211  $this->checkTransitionStateKey($tkey);
212 
213  $props = array_keys($transition);
214  $diff = array_diff($props, $this->transitionModelProperties);
215  if (count($diff) > 0) {
216  $this->addCodeError('WFL0101', implode(',', $diff) , $tkey, $this->className, implode(',', $this->transitionModelProperties));
217  }
218 
219  if (isset($transition["ask"]) && (!is_array($transition["ask"]))) {
220  $this->addCodeError('WFL0103', $tkey, $this->className);
221  }
222 
223  if (!empty($transition["m0"])) {
224  if (!method_exists($this->wdoc, $transition["m0"])) {
225 
226  $this->addCodeError('WFL0108', $transition["m0"], $tkey, $this->className);
227  }
228  }
229  if (!empty($transition["m1"])) {
230  if (!method_exists($this->wdoc, $transition["m1"])) {
231 
232  $this->addCodeError('WFL0105', $transition["m1"], $tkey, $this->className);
233  }
234  }
235  if (!empty($transition["m2"])) {
236  if (!method_exists($this->wdoc, $transition["m2"])) {
237 
238  $this->addCodeError('WFL0106', $transition["m2"], $tkey, $this->className);
239  }
240  }
241  if (!empty($transition["m3"])) {
242  if (!method_exists($this->wdoc, $transition["m3"])) {
243 
244  $this->addCodeError('WFL0109', $transition["m3"], $tkey, $this->className);
245  }
246  }
247  if (in_array("nr", $props)) {
248  if (!is_bool($transition["nr"])) {
249  $this->addCodeError('WFL0107', $tkey, $this->className);
250  }
251  }
252  $index++;
253  }
254  }
255  }
256 
257  public function checkAskAttributes()
258  {
259  $transitions = $this->wdoc->transitions;
260  if (!is_array($transitions)) {
261  $this->addCodeError('WFL0100', $this->className);
262  } else {
263 
264  foreach ($transitions as $tkey => $transition) {
265  $this->checkTransitionStateKey($tkey);
266  $askes = isset($transition["ask"]) ? $transition["ask"] : null;
267  if ($askes) {
268  if (!is_array($askes)) {
269  $this->addCodeError('WFL0103', $tkey, $this->className);
270  } else {
271 
272  $wi = createTmpDoc($this->wdoc->dbaccess, $this->familyName);
273  $aids = array_keys($wi->getAttributes());
274  foreach ($askes as $aid) {
275  if (!in_array(strtolower($aid) , $aids)) {
276  $this->addCodeError('WFL0104', $aid, $this->className);
277  }
278  }
279  }
280  }
281  }
282  }
283  }
284 
285  private function checkTransitionStateKey($key)
286  {
287  $limit = 49 - strlen($this->wdoc->attrPrefix);
288  if (!preg_match("/^[a-zA-Z_][a-zA-Z0-9_:]{0,$limit}$/", $key)) {
289  $this->addCodeError('WFL0050', $key, $this->className, $limit + 1);
290  }
291  }
292 
293  public function checkIsAWorkflow()
294  {
295  // Sort out the formatting of the filename
296  $fileName = realpath($this->getWorkflowClassFile());
297  if (CheckClass::phpLintFile($fileName, $output) === false) {
298  $this->addCodeError('WFL0003', implode("\n", $output));
299  } else {
300  include_once ($this->getWorkflowClassFile());
301  if (!class_exists($this->className)) {
302  $this->addCodeError('WFL0004', $this->className);
303  } else {
304  $class = $this->className;
305  $this->wdoc = new $class();
306 
307  if (!is_a($this->wdoc, "WDoc")) {
308  $this->addCodeError('WFL0006', $this->className);
309  }
310  }
311  }
312  }
313 
314  public function checkPrefix()
315  {
316  if (!$this->wdoc->attrPrefix) {
317  $this->addCodeError('WFL0007', $this->className);
318  } elseif (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_]{0,14}$/', $this->wdoc->attrPrefix)) {
319  $this->addCodeError('WFL0008', $this->className);
320  }
321  }
322 
323  public function checkClassName()
324  {
325  if (empty($this->className)) {
326  $this->addCodeError('WFL0001');
327  } elseif (!self::checkPhpClass($this->className)) {
328  $this->addCodeError('WFL0002', $this->className);
329  } else {
330  $this->checkFileName();
331  }
332  }
333 
334  public function checkFileName()
335  {
336  $fileName = $this->getWorkflowClassFile();
337  if (!file_exists($fileName)) {
338  $this->addCodeError('WFL0005', $fileName, $this->className);
339  }
340  }
341 
342  public static function checkPhpClass($name)
343  {
344  if (preg_match('/^[a-zA-Z_][a-zA-Z0-9_\\\\]+$/', $name)) {
345  return true;
346  } else {
347  return false;
348  }
349  }
350 
351  public function getWorkflowClassFile()
352  {
353  $classFile = \Dcp\DirectoriesAutoloader::instance(null, null)->getClassFile($this->className);
354 
355  if ($classFile === null) {
356  \Dcp\DirectoriesAutoloader::instance(null, null)->forceRegenerate($this->className);
357  $classFile = \Dcp\DirectoriesAutoloader::instance(null, null)->getClassFile($this->className);
358  }
359 
360  if (!$classFile) {
361  $classFile = sprintf("FDL/Class.%s.php", $this->className);
362  }
363  return $classFile;
364  }
365 }
366 ?>
if(substr($wsh, 0, 1)!= '/') $args
const numberAttributeTransition
static instance($pTmpPath, $pTmpFileName= 'directoriesautoloader.cache.php')
static phpLintFile($fileName, &$output)
Definition: CheckClass.php:86
const numberAttributeState
__construct($className, $famName)
Check worflow definition when importing definition.
createTmpDoc($dbaccess, $fromid, $defaultvalue=true)
$class
Definition: updateclass.php:38
static checkPhpClass($name)
← centre documentaire © anakeen