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

Revision 5928, 19.0 KB checked in by marcosw, 12 years ago (diff)

Ticket #2398 - Compatibilizacao com PHP-5.3 em alguns módulos do expresso

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::newInstance('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::newInstance('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        * @deprecated 2.2.000
246        */
247        public function getAll($activities = null)
248        {
249                wf_warn_deprecated_method('wf_instances', 'getAllActive');
250                return $this->getIdle(0, $activities);
251        }
252
253        /**
254        * Search and return all active instances.
255        * @param array $activities A list of activities codes to restrict instances from (may also be a single integer code).
256        * @return array The instaces which match the search criteria.
257        * @access public
258        */
259        public function getAllActive($activities = null)
260        {
261                return $this->getIdle(0, $activities);
262        }
263
264        /**
265        * Retrieve all completed instances.
266        * @return array All completed instances from current process. Be careful this may be a long array.
267        * @access public
268        */
269        public function getAllCompleted()
270        {
271                $output = array();
272
273                // Build the SQL query
274                // Select all instances from the process that has a final date
275                $query = 'SELECT i.wf_instance_id, i.wf_started, i.wf_ended, i.wf_name, i.wf_status, i.wf_priority ';
276                $query .= 'FROM egw_wf_instances i ';
277                $query .= 'WHERE (i.wf_p_id = ?) AND (i.wf_ended > 0)';
278                $resultSet = $this->db->query($query, array($this->processID));
279
280                /* fetch the results */
281                while ($row = $resultSet->fetchRow())
282                {
283                        $output[] = $row;
284                }
285
286                return $output;
287        }
288
289        /**
290        * This method gets all children instances of the given instance.
291        * If there is no parameter, it gets the children instances of the current instance
292        * @param int $instanceID Dad instance's identification.
293        * @return array Array with the children instances, or false
294        * @access public
295        */
296        public function getChildren($instanceID = null)
297        {
298                $output = array();
299                if (is_null($instanceID))
300                        $instanceID = $GLOBALS['workflow']['wf_runtime']->instance_id;
301
302                /* check instanceID */
303                if (!$this->checkInstanceAccess($instanceID))
304                        return $output;
305
306                /* build the SQL query */
307                $query = "
308                        SELECT
309                                i.wf_instance_id AS wf_instance_id,
310                                ia.wf_activity_id AS wf_activity_id,
311                                i.wf_started AS wf_started,
312                                i.wf_name AS wf_name,
313                                i.wf_status AS wf_status,
314                                ia.wf_user AS wf_user,
315                                ir.wf_parent_lock AS wf_parent_lock
316                        FROM
317                            egw_wf_interinstance_relations as ir
318                        LEFT JOIN
319                            egw_wf_instances as i
320                        ON
321                            i.wf_instance_id = ir.wf_child_instance_id
322                        LEFT JOIN
323                            egw_wf_instance_activities as ia
324                        ON
325                            i.wf_instance_id = ia.wf_instance_id
326                        WHERE
327                            ir.wf_parent_instance_id = ?";
328
329                $result = $this->db->query($query, array($instanceID));
330                $output = $result->GetArray(-1);
331
332                return $output;
333        }
334
335        /**
336        * Busca as propriedades de uma instância (do mesmo processo).
337        * @param int $instanceID O ID da instância.
338        * @return mixed Uma array contento as propriedades da instância (no formato "nome_da_propriedade" => "valor"). Ou false em caso de erro.
339        * @access public
340        */
341        public function getProperties($instanceID)
342        {
343                /* check instanceID */
344                if (!$this->checkInstanceAccess($instanceID))
345                        return false;
346
347                /* load the properties of the instance object */
348                return $this->getInstanceObject($instanceID)->properties;
349        }
350
351        /**
352        * Define uma propriedade de uma instância.
353        * @param int $instanceID O ID da instância.
354        * @return bool true caso a propriedade tenha sido alterada com sucesso
355        * @access public
356        */
357        public function setProperty($instanceID, $propertyName, $propertyValue)
358        {
359                /* check instanceID */
360                if (!$this->checkInstanceAccess($instanceID))
361                        return false;
362
363                /* load the instance object */
364                $instance = $this->getInstanceObject($instanceID);
365
366                /* set the property */
367                $output = $instance->set($propertyName, $propertyValue);
368                $output = $output && $instance->sync();
369
370                return $output;
371        }
372
373        /**
374        * Busca as instância de usuários de acordo com alguns critérios
375        * @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)
376        * @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)
377        * @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)
378        * @return array As instâncias que satisfazem o critério de seleção.
379        * @access public
380        */
381        public function getByUser($users, $activities = null, $status = null)
382        {
383                /* check for the supplied users/roles */
384                if (empty($users))
385                        return array();
386                if (!is_array($users))
387                        $users = array($users);
388                foreach ($users as &$user)
389                {
390                        if (!preg_match('/^[p]{0,1}[0-9]+$/i', "$user"))
391                                trigger_error('wf_engine::getUserInstances: O usuário/perfil "' . $user . '" é inválido', E_USER_ERROR);
392                        $user = "'{$user}'";
393                }
394
395                /* check for activity restriction */
396                $restrictToActivities = !is_null($activities);
397                if (!is_array($activities))
398                        $activities = array((int) $activities);
399                array_walk($activities, create_function('&$a', '$a = (int) $a;'));
400
401                /* check for status restriction */
402                $statusPossibleValues = array('completed', 'active', 'aborted', 'exception');
403                $restrictToStatus = !is_null($status);
404                if (is_string($status))
405                        $status = array($status);
406                /* check if the supplied status are valid */
407                if ($restrictToStatus)
408                {
409                        array_walk($status, create_function('&$a', '$a = strtolower($a);'));
410                        foreach ($status as $currentStatus)
411                                if (!in_array($currentStatus, $statusPossibleValues))
412                                        trigger_error('wf_engine::getUserInstances: O status "' . $currentStatus . '" é inválido', E_USER_ERROR);
413                }
414
415                /* build the SQL query */
416                $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 ";
417                $query .= "FROM egw_wf_instance_activities ia, egw_wf_instances i ";
418                $query .= "WHERE (ia.wf_instance_id = i.wf_instance_id) AND (i.wf_p_id = ?) AND (ia.wf_user IN (" . implode(', ', $users) . "))";
419                $values = array($this->processID);
420
421                if ($restrictToActivities)
422                {
423                        $query .= ' AND (ia.wf_activity_id = ANY (?))';
424                        $values[] = '{' . implode(', ', $activities) . '}';
425                }
426
427                if ($restrictToStatus)
428                {
429                        $aux = ' AND (i.wf_status IN (';
430                        foreach($status as $id){
431                                $values[] = $id;
432                                $query .= $aux.' ?';
433                                $aux = ', ';
434                        }
435                        $query .= ' ))';
436                }
437
438                $resultSet = $this->db->query($query, $values);
439
440                /* fetch and return the results */
441                return $resultSet->GetArray(-1);
442        }
443
444        /**
445        * Busca todas as instâncias que possuem esse nome (identificador).
446        * @param string $name O nome da instância que se quer encontrar.
447        * @return array As instâncias que satisfazem o critério de seleção.
448        * @access public
449        */
450        public function getByName($name)
451        {
452                /* build the SQL query */
453                $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 ';
454                $query .= 'FROM egw_wf_instances i LEFT JOIN egw_wf_instance_activities ia ON (ia.wf_instance_id = i.wf_instance_id)';
455                $query .= 'WHERE (i.wf_p_id = ?) AND (UPPER(i.wf_name) = UPPER(?))';
456
457                $resultSet = $this->db->query($query, array($this->processID, $name));
458                return $resultSet->GetArray();
459        }
460
461        /**
462        * Verifica se um dado usuário tem acesso a uma instância
463        * @param int $userID O ID do usuário que se quer verificar
464        * @param int $instanceID O ID da instância
465        * @param int $activityID O ID da atividade onde a instância está
466        * @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
467        * @return bool true se o usuário tiver acesso à instância (levando em consideração $writeAccess) ou false caso contrário
468        * @access public
469        */
470        public function checkUserAccess($userID, $instanceID, $activityID, $writeAccess = true)
471        {
472                /* only integers are allowed */
473                $userID = (int) $userID;
474                $instanceID = (int) $instanceID;
475                $activityID = (int) $activityID;
476
477                /* load the required instance (for the required user) */
478                $GUI = &Factory::newInstance('GUI');
479                $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);
480                $userInstance = $userInstance['data'];
481
482                /* if no instance is found, the user does not have access to it */
483                if (empty($userInstance))
484                        return false;
485
486                /* if no write access is required, then the user have access to the instance */
487                if (!$writeAccess)
488                        return true;
489
490                /* write access is required, check for it */
491                return ($userInstance['wf_readonly'] == 0);
492        }
493
494        /**
495        * Define o usuário de uma instância (em uma atividade)
496        * @param int $instanceID O ID da instância.
497        * @param int $activityID O ID da atividade.
498        * @param int $userID O ID do usuário.
499        * @return boolean true se foi possível definir o usuário da instância ou false caso contrário.
500        * @access public
501        */
502        public function setUser($instanceID, $activityID, $userID)
503        {
504                /* check instanceID and activityID */
505                if (!$this->checkInstanceAccess($instanceID, $activityID))
506                        return false;
507
508                if ($userID !== '*')
509                {
510                        $wfRole = Factory::getInstance('wf_role');
511                        $engine = Factory::getInstance('wf_engine');
512                        /* get information about the activity */
513                        if (($activityInfo = $engine->getActivityInformationByID($activityID)) === false)
514                                return false;
515
516                        /* load the possible roles of the activity */
517                        $possibleRoles = $wfRole->getActivityRoles($activityInfo['name']);
518                        if (substr($userID, 0, 1) == 'p')
519                        {
520                                /* the instance is being set to a role */
521                                /* check if the role is valid */
522                                $roleID = (int) substr($userID, 1);
523                                $userID = 'p' . $roleID;
524                                $validRole = false;
525                                foreach ($possibleRoles as $possibleRole)
526                                {
527                                        if ($roleID == $possibleRole['id'])
528                                        {
529                                                $validRole = true;
530                                                break;
531                                        }
532                                }
533                                if (!$validRole)
534                                        return false;
535                        }
536                        else
537                        {
538                                /* the instance is being set to a user */
539                                /* check if the $userID is a number */
540                                if (!is_numeric($userID))
541                                        return false;
542
543                                /* check if the user is valid */
544                                $userID = (int) $userID;
545                                $validUser = false;
546                                foreach ($possibleRoles as $possibleRole)
547                                {
548                                        if ($wfRole->checkUserInRole($userID, $possibleRole['name']))
549                                        {
550                                                $validUser = true;
551                                                break;
552                                        }
553                                }
554                                if (!$validUser)
555                                        return false;
556                        }
557                }
558
559                $query = 'UPDATE egw_wf_instance_activities SET wf_user = ? WHERE (wf_instance_id = ?) AND (wf_activity_id = ?)';
560                $this->db->execute($query, array($userID, $instanceID, $activityID));
561
562                return true;
563        }
564
565        /**
566        * Define o perfil que poderá acessar uma instância (em uma atividade)
567        * @param int $instanceID O ID da instância.
568        * @param int $activityID O ID da atividade.
569        * @param string $roleName O nome do perfil.
570        * @return boolean true se foi possível definir o perfil da instância ou false caso contrário.
571        * @access public
572        */
573        public function setRole($instanceID, $activityID, $roleName)
574        {
575                /* check instanceID and activityID */
576                if (!$this->checkInstanceAccess($instanceID, $activityID))
577                        return false;
578
579                /* try to get the role id */
580                $wfRole = Factory::getInstance('wf_role');
581                if (($roleID = $wfRole->getRoleIdByName($roleName)) === false)
582                        return false;
583
584                return $this->setUser($instanceID, $activityID, 'p' . $roleID);
585        }
586}
587?>
Note: See TracBrowser for help on using the repository browser.