source: trunk/workflow/inc/local/classes/class.wf_instance.php @ 2832

Revision 2832, 18.0 KB checked in by asaikawa, 14 years ago (diff)

Ticket #1082 - Alterado o método getChildren da classe wf_instance de acordo com a descricao do ticket

Line 
1<?php
2/**************************************************************************\
3* eGroupWare                                                               *
4* http://www.egroupware.org                                                *
5* --------------------------------------------                             *
6*  This program is free software; you can redistribute it and/or modify it *
7*  under the terms of the GNU General Public License as published by the   *
8*  Free Software Foundation; either version 2 of the License, or (at your  *
9*  option) any later version.                                              *
10\**************************************************************************/
11
12/**
13* Provê métodos que acessam informações relacionadas às instâncias.
14* @author Sidnei Augusto Drovetto Junior - drovetto@gmail.com
15* @version 1.0
16* @license http://www.gnu.org/copyleft/gpl.html GPL
17* @package Workflow
18* @subpackage local
19*/
20class wf_instance
21{
22        /**
23        * @var object $db objeto do banco de dados
24        * @access private
25        */
26        private $db;
27
28        /**
29        * @var int $processID o ID do processo onde a classe está sendo utilizada
30        * @access private
31        */
32        private $processID;
33
34        /**
35        * Verifica se um dado processo equivale àquele que está sendo executado.
36        * @param int $processID O ID do processo.
37        * @return bool true caso sejam o mesmo processo ou, false caso contrário.
38        * @access public
39        */
40        private function checkProcessAccess($processID)
41        {
42                $processID = (int) $processID;
43                return ($processID === $this->processID);
44        }
45
46        /**
47        * Verifica se uma instância pertence ao processo que está sendo executado.
48        * @param int instanceID O ID da instância.
49        * @return bool true caso a instância pertença ao processo que está sendo executado ou, false caso contrário.
50        * @access public
51        */
52        private function checkInstanceAccess($instanceID, $activityID = null)
53        {
54                $instance = $this->getInstanceObject($instanceID);
55                if ($instance === false)
56                        return false;
57                if (!is_null($activityID))
58                {
59                        $activityFound = false;
60                        foreach ($instance->activities as $activity)
61                                if (($activityFound = ($activityID == $activity['wf_activity_id'])))
62                                        break;
63
64                        if ($activityFound == false)
65                                return false;
66                }
67                return $this->checkProcessAccess($instance->pId);
68        }
69
70        /**
71        * Pega o objeto de uma instância.
72        * @param int instanceID O ID da instância.
73        * @return mixed object caso a instância seja encontrada ou false caso contrário.
74        * @access public
75        */
76        private function getInstanceObject($instanceID)
77        {
78                $instanceID = (int) $instanceID;
79                $instance = Factory::getInstance('workflow_instance');
80                if (!$instance->getInstance($instanceID))
81                        return false;
82                else
83                        return $instance;
84        }
85
86        /**
87        * Construtor do wf_instances.
88        * @return object
89        * @access public
90        */
91        public function wf_instance()
92        {
93                /* load the DB */
94                $this->db = &Factory::getInstance('WorkflowObjects')->getDBGalaxia()->Link_ID;
95
96                /* load the process ID from the runtime */
97                if (!is_null($GLOBALS['workflow']['wf_runtime']->activity))
98                        $this->processID = (int) $GLOBALS['workflow']['wf_runtime']->activity->getProcessId();
99                /* if a job is running the process, then load the processID specified by the job */
100                if (isset($GLOBALS['workflow']['job']))
101                        $this->processID = (int) $GLOBALS['workflow']['job']['processID'];
102        }
103
104        /**
105        * Dá seqüência no fluxo de uma instância (simula ação do usuário).
106        * @param int $activityID O ID da atividade da instância.
107        * @param int $instanceID O ID da instância.
108        * @return bool true caso a instância tenha sido continuada e false caso contrário.
109        * @access public
110        */
111        public function continueInstance($activityID, $instanceID)
112        {
113                /* check instanceID */
114                if (!$this->checkInstanceAccess($instanceID, $activityID))
115                        return false;
116
117                /* load the instance object */
118                $instance = $this->getInstanceObject($instanceID);
119
120                $runActivity = Factory::getInstance('run_activity');
121
122                ob_start();
123                $output = $runActivity->go($activityID, $instanceID, true);
124                ob_end_clean();
125
126                return ($output !== false);
127        }
128
129        /**
130        * Aborta uma instância
131        * @param int $instanceID O ID da instância.
132        * @return boolean true se foi possível abortar a instância e false caso contrário.
133        * @access public
134        */
135        public function abort($instanceID)
136        {
137                /* check instanceID */
138                if (!$this->checkInstanceAccess($instanceID))
139                        return false;
140
141                /* load the instance object */
142                $instance = $this->getInstanceObject($instanceID);
143
144                /* abort the instance */
145                return $instance->abort();
146        }
147
148        /**
149        * Define o nome (identificador) de uma instância
150        * @param int $instanceID O ID da instância.
151        * @param string $name O novo nome da instância.
152        * @return boolean true se foi possível mudar o nome da instância e false caso contrário.
153        * @access public
154        */
155        public function setName($instanceID, $name)
156        {
157                /* check instanceID */
158                if (!$this->checkInstanceAccess($instanceID))
159                        return false;
160
161                /* load the instance object */
162                $instance = $this->getInstanceObject($instanceID);
163
164                /* set the name */
165                $output = $instance->setName($name);
166                $output = $output && $instance->sync();
167
168                return $output;
169        }
170
171        /**
172        * Define a prioridade de uma instância
173        * @param int $instanceID O ID da instância.
174        * @param int $priority A nova prioridade da instância
175        * @return boolean true se foi possível mudar a prioridade da instância e false caso contrário.
176        * @access public
177        */
178        public function setPriority($instanceID, $priority)
179        {
180                /* check instanceID */
181                if (!$this->checkInstanceAccess($instanceID))
182                        return false;
183
184                /* load the instance object */
185                $instance = $this->getInstanceObject($instanceID);
186
187                /* ensure the instance priority range */
188                $priority = max(min((int) $priority, 4), 0);
189
190                /* set the new priority */
191                $output = $instance->setPriority($priority);
192                $output = $output && $instance->sync();
193                return $output;
194        }
195
196        /**
197        * Busca instâncias ativas que estão "abandonadas".
198        * @param int $numberOfDays O tempo (em dias) em que a instância está abandonada.
199        * @param array $activities Uma lista de atividades das quais se quer as instâncias abandonadas (também pode ser um valor inteiro).
200        * @return array As instâncias que satisfazem o critério de seleção.
201        * @access public
202        */
203        public function getIdle($numberOfDays, $activities = null)
204        {
205                /* prepare some variables */
206                $output = array();
207                $restrictToActivities = !is_null($activities);
208                if (is_numeric($activities))
209                        $activities = array((int) $activities);
210
211                if (is_numeric($numberOfDays))
212                        $numberOfDays = (int) $numberOfDays;
213                else
214                        return $output;
215
216                /* restrict the range and get the threshold date (in UNIX ERA format) */
217                $numberOfDays = max(0, $numberOfDays);
218                $threshold = time() - ($numberOfDays * 24 * 60 * 60);
219
220                /* build the SQL query */
221                $query = 'SELECT ia.wf_instance_id AS wf_instance_id, ia.wf_activity_id AS wf_activity_id, ia.wf_started AS wf_started, i.wf_name AS wf_name, i.wf_status AS wf_status, ia.wf_user AS wf_user, i.wf_priority AS wf_priority ';
222                $query .= 'FROM egw_wf_instance_activities ia, egw_wf_instances i ';
223                $query .= 'WHERE (ia.wf_instance_id = i.wf_instance_id) AND (i.wf_p_id = ?) AND (ia.wf_started < ?)';
224                $resultSet = $this->db->query($query, array($this->processID, $threshold));
225
226                /* fetch the results */
227                while ($row = $resultSet->fetchRow())
228                {
229                        /* if required, restrict to specific activities */
230                        if ($restrictToActivities)
231                                if (!in_array($row['wf_activity_id'], $activities))
232                                        continue;
233
234                        $output[] = $row;
235                }
236
237                return $output;
238        }
239
240        /**
241        * Busca todas as instâncias ativas.
242        * @param array $activities Uma lista de atividades das quais se quer as instâncias (também pode ser um valor inteiro).
243        * @return array As instâncias que satisfazem o critério de seleção.
244        * @access public
245        */
246        public function getAll($activities = null)
247        {
248                return $this->getIdle(0, $activities);
249        }
250
251        /**
252        * This method gets all children instances of the given instance.
253        * If there is no parameter, it gets the children instances of the current instance
254        * @param int $instanceID Dad instance's identification.
255        * @return array Array with the children instances, or false
256        * @access public
257        */
258        public function getChildren($instanceID = null)
259        {
260                $output = array();
261                if (is_null($instanceID))
262                        $instanceID = $GLOBALS['workflow']['wf_runtime']->instance_id;
263
264                /* check instanceID */
265                if (!$this->checkInstanceAccess($instanceID))
266                        return $output;
267
268                /* build the SQL query */
269                $query = 'SELECT i.wf_instance_id AS wf_instance_id, ' .
270                                 '       ia.wf_activity_id AS wf_activity_id, ' .
271                                 '       i.wf_started AS wf_started, ' .
272                                 '       i.wf_name AS wf_name, ' .
273                                 '       i.wf_status AS wf_status, ' .
274                                 '       ia.wf_user AS wf_user, ' .
275                                 '       ir.wf_parent_lock AS wf_parent_lock ' .
276                                 ' FROM egw_wf_interinstance_relations ir, egw_wf_instances i ' .
277                                 '  LEFT JOIN egw_wf_instance_activities ia ' .
278                                 '  ON (ia.wf_instance_id = i.wf_instance_id) ' .
279                                 ' WHERE ' .
280                                 '  (ir.wf_child_instance_id = i.wf_instance_id) AND (ir.wf_parent_instance_id = ?) ';
281
282                $result = $this->db->query($query, array($instanceID));
283                $output = $result->GetArray(-1);
284
285                return $output;
286        }
287
288        /**
289        * Busca as propriedades de uma instância (do mesmo processo).
290        * @param int $instanceID O ID da instância.
291        * @return mixed Uma array contento as propriedades da instância (no formato "nome_da_propriedade" => "valor"). Ou false em caso de erro.
292        * @access public
293        */
294        public function getProperties($instanceID)
295        {
296                /* check instanceID */
297                if (!$this->checkInstanceAccess($instanceID))
298                        return false;
299
300                /* load the properties of the instance object */
301                return $this->getInstanceObject($instanceID)->properties;
302        }
303
304        /**
305        * Define uma propriedade de uma instância.
306        * @param int $instanceID O ID da instância.
307        * @return bool true caso a propriedade tenha sido alterada com sucesso
308        * @access public
309        */
310        public function setProperty($instanceID, $propertyName, $propertyValue)
311        {
312                /* check instanceID */
313                if (!$this->checkInstanceAccess($instanceID))
314                        return false;
315
316                /* load the instance object */
317                $instance = $this->getInstanceObject($instanceID);
318
319                /* set the property */
320                $output = $instance->set($propertyName, $propertyValue);
321                $output = $output && $instance->sync();
322
323                return $output;
324        }
325
326        /**
327        * Busca as instância de usuários de acordo com alguns critérios
328        * @param mixed $users Um array com IDs de usuários ou perfis (no caso de perfis, deve-se prefixar seu ID com o caractere 'p'). Também pode possuir um único ID (seja de usuário ou de perfil)
329        * @param mixed $activities Um array com IDs de atividades das se quer as instâncias. Também pode ser um inteiro, representando um único ID. Caso possua valor null, o resultado não é filtrado de acordo com as atividades (parâmetro opcional)
330        * @param mixed $status Um array com os status requeridos (para filtrar as instâncias). Também pode ser uma string, representando um único status. Caso possua valor null, o resultado não é filtrado de acordo com o status. Os status podem ser: completed, active, aborted e exception (parâmetro opcional)
331        * @return array As instâncias que satisfazem o critério de seleção.
332        * @access public
333        */
334        public function getByUser($users, $activities = null, $status = null)
335        {
336                /* check for the supplied users/roles */
337                if (empty($users))
338                        return array();
339                if (!is_array($users))
340                        $users = array($users);
341                foreach ($users as &$user)
342                {
343                        if (!eregi('^[p]{0,1}[0-9]+$', "$user"))
344                                trigger_error('wf_engine::getUserInstances: O usuário/perfil "' . $user . '" é inválido', E_USER_ERROR);
345                        $user = "'{$user}'";
346                }
347
348                /* check for activity restriction */
349                $restrictToActivities = !is_null($activities);
350                if (!is_array($activities))
351                        $activities = array((int) $activities);
352                array_walk($activities, create_function('&$a', '$a = (int) $a;'));
353
354                /* check for status restriction */
355                $statusPossibleValues = array('completed', 'active', 'aborted', 'exception');
356                $restrictToStatus = !is_null($status);
357                if (is_string($status))
358                        $status = array($status);
359                /* check if the supplied status are valid */
360                if ($restrictToStatus)
361                {
362                        array_walk($status, create_function('&$a', '$a = strtolower($a);'));
363                        foreach ($status as $currentStatus)
364                                if (!in_array($currentStatus, $statusPossibleValues))
365                                        trigger_error('wf_engine::getUserInstances: O status "' . $currentStatus . '" é inválido', E_USER_ERROR);
366                }
367
368                /* build the SQL query */
369                $query = "SELECT ia.wf_instance_id AS wf_instance_id, ia.wf_activity_id AS wf_activity_id, ia.wf_started AS wf_started, i.wf_name AS wf_name, i.wf_status AS wf_status, ia.wf_user AS wf_user, i.wf_priority AS wf_priority ";
370                $query .= "FROM egw_wf_instance_activities ia, egw_wf_instances i ";
371                $query .= "WHERE (ia.wf_instance_id = i.wf_instance_id) AND (i.wf_p_id = ?) AND (ia.wf_user IN (" . implode(', ', $users) . "))";
372                $values = array($this->processID);
373
374                if ($restrictToActivities)
375                {
376                        $query .= ' AND (ia.wf_activity_id = ANY (?))';
377                        $values[] = '{' . implode(', ', $activities) . '}';
378                }
379
380                if ($restrictToStatus)
381                {
382                        $aux = ' AND (i.wf_status IN (';
383                        foreach($status as $id){
384                                $values[] = $id;
385                                $query .= $aux.' ?';
386                                $aux = ', ';
387                        }
388                        $query .= ' ))';
389                }
390
391                $resultSet = $this->db->query($query, $values);
392
393                /* fetch and return the results */
394                return $resultSet->GetArray(-1);
395        }
396
397        /**
398        * Busca todas as instâncias que possuem esse nome (identificador).
399        * @param string $name O nome da instância que se quer encontrar.
400        * @return array As instâncias que satisfazem o critério de seleção.
401        * @access public
402        */
403        public function getByName($name)
404        {
405                /* build the SQL query */
406                $query = 'SELECT i.wf_instance_id AS wf_instance_id, ia.wf_activity_id AS wf_activity_id, ia.wf_started AS wf_started, i.wf_name AS wf_name, i.wf_status AS wf_status, ia.wf_user AS wf_user, i.wf_priority AS wf_priority ';
407                $query .= 'FROM egw_wf_instances i LEFT JOIN egw_wf_instance_activities ia ON (ia.wf_instance_id = i.wf_instance_id)';
408                $query .= 'WHERE (i.wf_p_id = ?) AND (UPPER(i.wf_name) = UPPER(?))';
409
410                $resultSet = $this->db->query($query, array($this->processID, $name));
411                return $resultSet->GetArray();
412        }
413
414        /**
415        * Verifica se um dado usuário tem acesso a uma instância
416        * @param int $userID O ID do usuário que se quer verificar
417        * @param int $instanceID O ID da instância
418        * @param int $activityID O ID da atividade onde a instância está
419        * @param bool $writeAccess Se true, indica que é necessário que o usuário tenha acesso para modificar a instância (dar seqüência ao fluxo). Se false, não será verificado se o usuário tem permissão de escrita na instância
420        * @return bool true se o usuário tiver acesso à instância (levando em consideração $writeAccess) ou false caso contrário
421        * @access public
422        */
423        public function checkUserAccess($userID, $instanceID, $activityID, $writeAccess = true)
424        {
425                /* only integers are allowed */
426                $userID = (int) $userID;
427                $instanceID = (int) $instanceID;
428                $activityID = (int) $activityID;
429
430                /* load the required instance (for the required user) */
431                $GUI = &Factory::newInstance('GUI');
432                $userInstance = $GUI->gui_list_user_instances($userID, 0, -1, '', '', "(ga.wf_is_interactive = 'y') AND (gia.wf_activity_id = {$activityID}) AND (gia.wf_instance_id = {$instanceID})", false, $this->processID, true, false, true, false, false, false);
433                $userInstance = $userInstance['data'];
434
435                /* if no instance is found, the user does not have access to it */
436                if (empty($userInstance))
437                        return false;
438
439                /* if no write access is required, then the user have access to the instance */
440                if (!$writeAccess)
441                        return true;
442
443                /* write access is required, check for it */
444                return ($userInstance['wf_readonly'] == 0);
445        }
446
447        /**
448        * Define o usuário de uma instância (em uma atividade)
449        * @param int $instanceID O ID da instância.
450        * @param int $activityID O ID da atividade.
451        * @param int $userID O ID do usuário.
452        * @return boolean true se foi possível definir o usuário da instância ou false caso contrário.
453        * @access public
454        */
455        public function setUser($instanceID, $activityID, $userID)
456        {
457                /* check instanceID and activityID */
458                if (!$this->checkInstanceAccess($instanceID, $activityID))
459                        return false;
460
461                if ($userID !== '*')
462                {
463                        $wfRole = Factory::getInstance('wf_role');
464                        $engine = Factory::getInstance('wf_engine');
465                        /* get information about the activity */
466                        if (($activityInfo = $engine->getActivityInformationByID($activityID)) === false)
467                                return false;
468
469                        /* load the possible roles of the activity */
470                        $possibleRoles = $wfRole->getActivityRoles($activityInfo['name']);
471                        if (substr($userID, 0, 1) == 'p')
472                        {
473                                /* the instance is being set to a role */
474                                /* check if the role is valid */
475                                $roleID = (int) substr($userID, 1);
476                                $userID = 'p' . $roleID;
477                                $validRole = false;
478                                foreach ($possibleRoles as $possibleRole)
479                                {
480                                        if ($roleID == $possibleRole['id'])
481                                        {
482                                                $validRole = true;
483                                                break;
484                                        }
485                                }
486                                if (!$validRole)
487                                        return false;
488                        }
489                        else
490                        {
491                                /* the instance is being set to a user */
492                                /* check if the $userID is a number */
493                                if (!is_numeric($userID))
494                                        return false;
495
496                                /* check if the user is valid */
497                                $userID = (int) $userID;
498                                $validUser = false;
499                                foreach ($possibleRoles as $possibleRole)
500                                {
501                                        if ($wfRole->checkUserInRole($userID, $possibleRole['name']))
502                                        {
503                                                $validUser = true;
504                                                break;
505                                        }
506                                }
507                                if (!$validUser)
508                                        return false;
509                        }
510                }
511
512                $query = 'UPDATE egw_wf_instance_activities SET wf_user = ? WHERE (wf_instance_id = ?) AND (wf_activity_id = ?)';
513                $this->db->execute($query, array($userID, $instanceID, $activityID));
514
515                return true;
516        }
517
518        /**
519        * Define o perfil que poderá acessar uma instância (em uma atividade)
520        * @param int $instanceID O ID da instância.
521        * @param int $activityID O ID da atividade.
522        * @param string $roleName O nome do perfil.
523        * @return boolean true se foi possível definir o perfil da instância ou false caso contrário.
524        * @access public
525        */
526        public function setRole($instanceID, $activityID, $roleName)
527        {
528                /* check instanceID and activityID */
529                if (!$this->checkInstanceAccess($instanceID, $activityID))
530                        return false;
531
532                /* try to get the role id */
533                $wfRole = Factory::getInstance('wf_role');
534                if (($roleID = $wfRole->getRoleIdByName($roleName)) === false)
535                        return false;
536
537                return $this->setUser($instanceID, $activityID, 'p' . $roleID);
538        }
539}
540?>
Note: See TracBrowser for help on using the repository browser.