source: branches/2.2/workflow/inc/class.bo_monitors.inc.php @ 3167

Revision 3167, 54.6 KB checked in by viani, 14 years ago (diff)

Ticket #1135 - Merged r1990:3166 from /trunk/workflow into /branches/2.2/workflow

  • Property svn:executable set to *
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
12require_once('class.bo_ajaxinterface.inc.php');
13
14
15/**
16 * DO NOT remove this line. Ever. Somehow, monitors interface will stop working..
17 */
18require_once(PHPGW_API_INC . SEP . 'common_functions.inc.php');
19
20
21/**
22 * @package Workflow
23 * @license http://www.gnu.org/copyleft/gpl.html GPL
24 * @author Sidnei Augusto Drovetto Jr. - drovetto@gmail.com
25 */
26class bo_monitors extends bo_ajaxinterface
27{
28        /* permissions index */
29
30        /**
31         * @var integer $IP_CHANGE_PRIORITY
32         * @access public
33         */
34        var $IP_CHANGE_PRIORITY = 0;
35        /**
36         * @var integer $IP_CHANGE_USER
37         * @access public
38         */
39        var $IP_CHANGE_USER = 1;
40        /**
41         * @var integer $IP_CHANGE_STATUS
42         * @access public
43         */
44        var $IP_CHANGE_STATUS = 2;
45        /**
46         * @var integer $IP_CHANGE_NAME
47         * @access public
48         */
49        var $IP_CHANGE_NAME = 3;
50        /**
51         * @var integer $IP_CHANGE_ACTIVITY
52         * @access public
53         */
54        var $IP_CHANGE_ACTIVITY = 4;
55        /**
56         * @var integer $IP_VIEW_PROPERTIES
57         * @access public
58         */
59        var $IP_VIEW_PROPERTIES = 5;
60        /**
61         * @var integer $IP_CHANGE_PROPERTIES
62         * @access public
63         */
64        var $IP_CHANGE_PROPERTIES = 6;
65        /**
66         * @var integer $IP_VIEW_STATISTICS
67         * @access public
68         */
69        var $IP_VIEW_STATISTICS = 7;
70        /**
71         * @var integer $IP_REMOVE_COMPLETED_INSTANCES
72         * @access public
73         */
74        var $IP_REMOVE_COMPLETED_INSTANCES = 8;
75        /**
76         * @var integer $IP_REPLACE_USER
77         * @access public
78         */
79        var $IP_REPLACE_USER = 9;
80        /**
81         * @var integer $IP_SEND_EMAILS
82         * @access public
83         */
84        var $IP_SEND_EMAILS = 10;
85        /**
86         * @var object $processManager
87         * @access public
88         */
89        var $processManager;
90        /**
91         * @var object $activityManager
92         * @access public
93         */
94        var $activityManager;
95        /**
96         * @var object $instanceManager
97         * @access public
98         */
99        var $instanceManager;
100        /**
101         * @var object $roleManager
102         * @access public
103         */
104        var $roleManager;
105        /**
106         * @var integer $userID
107         * @access public
108         */
109        var $userID;
110
111        /**
112         * @var bool $isWorkflowAdmin
113         * @access public
114         */
115        var $isWorkflowAdmin;
116
117        /**
118         * @var object $processMonitor
119         * @access public
120         */
121        var $processMonitor;
122
123        /**
124         * Construtor da classe bo_monitors
125         *
126         * @access public
127         * @return object
128         */
129        function bo_monitors()
130        {
131                parent::bo_ajaxinterface();
132                $GLOBALS['ajax']->gui   = &Factory::newInstance('GUI');
133                $this->userID                   = $_SESSION['phpgw_info']['workflow']['account_id'];
134                $this->isWorkflowAdmin  = $GLOBALS['ajax']->acl->checkWorkflowAdmin($this->userID);
135                $this->processManager   = &Factory::newInstance('ProcessManager');
136                $this->activityManager  = &Factory::newInstance('ActivityManager');
137                $this->instanceManager  = &Factory::newInstance('InstanceManager');
138                $this->roleManager              = &Factory::newInstance('RoleManager');
139                $this->processMonitor   = &Factory::newInstance('ProcessMonitor');
140        }
141
142        /**
143         * Verifica se o usuário logado possui acesso ao Monitoramento
144         *
145         * @param int $processID O ID do processo que se está tentando monitorar
146         * @param array $requiredLevel Permissões necessárias
147         * @return bool true se o usuário tiver permissão ou false caso contrário
148         * @access private
149         */
150        private function checkAccess($processID, $requiredLevel = null)
151        {
152                if ($this->isWorkflowAdmin)
153                        return true;
154
155                return $GLOBALS['ajax']->acl->checkUserGroupAccessToResource('MON', $this->userID, (int) $processID, $requiredLevel);
156        }
157
158        /**
159         * Converte os filtros utilizados na interface de monitoramento para código SQL
160         *
161         * @param string $filters Uma string contendo dados, serializados, sobre os filtros selecionados
162         * @return array Uma array onde cada elemento corresponde a um condicional de um filtro
163         * @access private
164         */
165        private function convertFiltersToSQL($filters)
166        {
167
168                /* desserializa os dados */
169                $JSON = &Factory::newInstance('Services_JSON');
170                /* desserializa a array principal, depois desserializa cada elemento desta array e, por fim, converte os elementos (que estão em forma de objeto) para array associativa */
171                $filters = array_map('get_object_vars', array_map(array($JSON, 'decode'), $JSON->decode($filters)));
172                $sqlFilters = array();
173
174                /* gera o SQL de acordo com o filtro selecionado */
175                foreach ($filters as $filter)
176                {
177                        /* verifica se existe o ID do filtro */
178                        if (!isset($filter['id']))
179                                continue;
180
181                        switch ($filter['id'])
182                        {
183                                case 'activityDate':
184                                        $sqlFilters[] = '(DATE_TRUNC(\'DAY\', \'EPOCH\'::TIMESTAMP + (gia.wf_started || \' SECONDS\')::INTERVAL) ' . (($filter['operator'] == 'EQ') ? '=' : (($filter['operator'] == 'LT') ? '<' : '>')) . ' TO_DATE(\'' . addslashes($filter['date']) . '\', \'DD/MM/YYYY\'))';
185                                        break;
186
187                                case 'instanceName':
188                                        $sqlFilters[] = '(gi.wf_name ILIKE \'%' . addslashes($filter['name']) . '%\')';
189                                        break;
190
191                                case 'instanceID':
192                                        $sqlFilters[] = '(gi.wf_instance_id ' . (($filter['operator'] == 'EQ') ? '=' : (($filter['operator'] == 'LT') ? '<' : '>')) . ' ' . addslashes($filter['number']) . ')';
193                                        break;
194
195                                case 'instancePriority':
196                                        $sqlFilters[] = '(gi.wf_priority ' . (($filter['operator'] == 'EQ') ? '=' : (($filter['operator'] == 'LT') ? '<' : '>')) . ' ' . addslashes($filter['priority']) . ')';
197                                        break;
198
199                                case 'instanceDate':
200                                        $sqlFilters[] = '(DATE_TRUNC(\'DAY\', \'EPOCH\'::TIMESTAMP + (gi.wf_started || \' SECONDS\')::INTERVAL) ' . (($filter['operator'] == 'EQ') ? '=' : (($filter['operator'] == 'LT') ? '<' : '>')) . ' TO_DATE(\'' . addslashes($filter['date']) . '\', \'DD/MM/YYYY\'))';
201                                        break;
202
203                                case 'instanceEndDate':
204                                        $sqlFilters[] = '(DATE_TRUNC(\'DAY\', \'EPOCH\'::TIMESTAMP + (gi.wf_ended || \' SECONDS\')::INTERVAL) ' . (($filter['operator'] == 'EQ') ? '=' : (($filter['operator'] == 'LT') ? '<' : '>')) . ' TO_DATE(\'' . addslashes($filter['date']) . '\', \'DD/MM/YYYY\'))';
205                                        break;
206
207                                case 'instanceStatus':
208                                        $sqlFilters[] = '(gi.wf_status = \'' . addslashes($filter['status']) . '\')';
209                                        break;
210
211                                case 'instanceActivity':
212                                        $sqlFilters[] = '(gia.wf_activity_id = \'' . addslashes($filter['activity']) . '\')';
213                                        break;
214
215                                case 'instanceUser':
216                                        $sqlFilters[] = '(gia.wf_user = \'' . addslashes($filter['user']) . '\')';
217                                        break;
218
219                                case 'instanceOwner':
220                                        $sqlFilters[] = '(gi.wf_owner = \'' . addslashes($filter['owner']) . '\')';
221                                        break;
222                        }
223                }
224
225                return $sqlFilters;
226        }
227
228        /**
229         * Lista os processos do usuario
230         *
231         * @access public
232         * @return array lista de processos
233         */
234        function listProcesses()
235        {
236                if ($this->isWorkflowAdmin)
237                {
238                        $permissions = $this->processManager->list_processes(0, -1, 'wf_p_id__ASC');
239                        $permissions = array_map(create_function('$a', 'return $a[\'wf_p_id\'];'), $permissions['data']);
240                }
241                else
242                {
243                        $permissions = $GLOBALS['ajax']->acl->getUserGroupPermissions('MON', $this->userID);
244                }
245                $processes = array();
246                foreach ($permissions as $pid)
247                {
248                        $process = $this->processManager->get_process($pid);
249                        if ($process)
250                        {
251                                $processes['data'][] = $process;
252                                if ($this->isWorkflowAdmin)
253                                        $processes['permissions'][$pid] = array(
254                                                'number' => 4294967295,
255                                                'bits' => array_fill(0, 32, true)
256                                        );
257                                else
258                                        $processes['permissions'][$pid] = $GLOBALS['ajax']->acl->getUserGroupAdminLevel('MON', $this->userID, $pid);
259                        }
260                }
261
262                usort($processes['data'], create_function('$a,$b', 'return strnatcasecmp($a[\'wf_name\'],$b[\'wf_name\']);'));
263                return $processes;
264        }
265        /**
266         * Lista as instancias ativas de um processo
267         *
268         * @param array $params Parâmetros advindos da chamada Ajax
269         * @param bool $completeData Informa se devem ser retornados todos os dados ou somente aqueles necessários para a construção da listagem de instâncias ativas da interface de monitoramento. false por padrão
270         * @access public
271         * @return array lista de instancias
272         */
273        function listInstances($params, $completeData = false)
274        {
275                $output = array();
276
277                /* check if the user has the proper right to list the instances of this process */
278                if (!$this->checkAccess($params['pid']))
279                        return "Você não tem permissão para executar este procedimento!";
280
281                /* check for filters */
282                if ($params['filters'])
283                        $filters = $this->convertFiltersToSQL($params['filters']);
284                else
285                        $filters = array();
286
287                if(empty($params['srt']))
288                        $params['srt'] = 2;
289                if(empty($params['ord']))
290                {
291                        $params['ord'] = "__ASC";
292                }
293                else
294                {
295
296                        // being sure that the prefix "__DESC" or "__ASC" exists, preventing SQL injections
297                        $isOrdOK = false;
298                        if($params['ord'] == "__DESC") $isOrdOK = true;
299                        if($params['ord'] == "__ASC") $isOrdOK = true;
300
301                        if(!$isOrdOK) $params['ord'] = "__ASC";
302                }
303
304                switch($params['srt'])
305                {
306                        case 1:
307                                $order = "wf_instance_id".$params['ord'];
308                                break;
309                        case 2:
310                                $order = "wf_activity_name".$params['ord'];
311                                break;
312                        case 3:
313                                $order = "wf_instance_name".$params['ord'];
314                                break;
315                        case 4:
316                                $order = "wf_priority".$params['ord'];
317                                break;
318                        case 5:
319                                $order = "wf_user".$params['ord'];
320                                break;
321                        case 6:
322                                $order = "wf_status".$params['ord'];
323                                break;
324                        default:
325                                $order = "wf_activity_name".$params['ord'];
326                                break;
327                }
328
329                $filters[] = '(gp.wf_p_id = ' . $params['pid'] . ')';
330                $filters[] = '(gia.wf_user IS NOT NULL)';
331
332                $ldap = &Factory::getInstance('WorkflowLDAP');
333                if (!$completeData)
334                {
335                        $paging = Factory::newInstance('Paging', 500, $_POST);
336                        $tmp = $this->processMonitor->monitor_list_instances($paging->nextItem, $paging->itemsPerPage, $order, '', implode(' AND ', $filters));
337                        $output['data'] = $paging->restrictItems(array_values($tmp['data']), $tmp['cant']);
338                        $output['instanceCount'] = $tmp['cant'];
339                        $output['pagingData'] = $paging->commonLinks();
340                }
341                else
342                {
343                        $tmp = $this->processMonitor->monitor_list_instances(0, -1, $order, '', implode(' AND ', $filters));
344                        $output['data'] = array_values($tmp['data']);
345                }
346
347                $userMapping = array('*' => '*');
348                $activityMapping = array();
349                $instanceCount = count($output['data']);
350                $cachedLDAP = &Factory::getInstance('CachedLDAP');
351                for ($i = 0; $i < $instanceCount; $i++)
352                {
353                        /* get the user name */
354                        $currentInstanceUser = $output['data'][$i]['wf_user'];
355                        if (!isset($userMapping[$currentInstanceUser]))
356                        {
357                                if (substr($currentInstanceUser, 0, 1) == 'p')
358                                {
359                                        $role = $this->roleManager->get_role($output['data'][$i]['wf_p_id'], substr($currentInstanceUser, 1));
360                                        $userMapping[$currentInstanceUser] = 'Perfil: ' . $role['wf_name'];
361                                }
362                                else
363                                {
364                                        $name = $ldap->getName($currentInstanceUser);
365                                        if (empty($name))
366                                        {
367                                                $userInfo = $cachedLDAP->getEntryByID($currentInstanceUser);
368                                                if ($userInfo)
369                                                        $name = "ID: {$currentInstanceUser} - {$userInfo['cn']} (excluído)";
370                                                else
371                                                        $name = "ID: {$currentInstanceUser}";
372                                        }
373
374                                        $userMapping[$currentInstanceUser] = $name;
375                                }
376                        }
377
378                        if ($completeData)
379                        {
380                                $currentInstanceOwner = $output['data'][$i]['wf_owner'];
381                                if (!isset($userMapping[$currentInstanceOwner]))
382                                        $userMapping[$currentInstanceOwner] = $ldap->getName($currentInstanceOwner);
383                        }
384
385                        /* get the activity names */
386                        if (!isset($activityMapping[$output['data'][$i]['wf_activity_id']]))
387                                $activityMapping[$output['data'][$i]['wf_activity_id']] = $output['data'][$i]['wf_activity_name'];
388
389                        /* remove unused elements */
390                        if (!$completeData)
391                                unset(
392                                        $output['data'][$i]['wf_is_interactive'],
393                                        $output['data'][$i]['wf_proc_normalized_name'],
394                                        $output['data'][$i]['wf_owner'],
395                                        $output['data'][$i]['wf_procname'],
396                                        $output['data'][$i]['wf_version'],
397                                        $output['data'][$i]['wf_activity_name'],
398                                        $output['data'][$i]['wf_type'],
399                                        $output['data'][$i]['wf_started'],
400                                        $output['data'][$i]['wf_ended'],
401                                        $output['data'][$i]['wf_act_status'],
402                                        $output['data'][$i]['wf_act_started']
403                                );
404                }
405                $output['userMapping'] = $userMapping;
406                $output['activityMapping'] = $activityMapping;
407
408                $output['params'] = $params;
409                return $output;
410        }
411
412        /**
413         * Lista as instancias finalizadas de um processo
414         *
415         * @param array $params Parâmetros advindos da chamada Ajax
416         * @param bool $completeData Informa se devem ser retornados todos os dados ou somente aqueles necessários para a construção da listagem de instâncias finalizadas da interface de monitoramento. false por padrão
417         * @access public
418         * @return array lista de instancias
419         */
420        function listCompletedInstances($params, $completeData = false)
421        {
422                $params['pid'] = (int) $params['pid'];
423                $output = array();
424
425                /* check if the user has the proper right to list the instances of this process */
426                if (!$this->checkAccess($params['pid']))
427                        return "Você não tem permissão para executar este procedimento!";
428
429                /* check for filters */
430                if ($params['filters'])
431                        $filters = $this->convertFiltersToSQL($params['filters']);
432                else
433                        $filters = array();
434
435                if(empty($params['sort']))
436                        $params['sort'] = 1;
437
438                if(empty($params['ord']) || ($params['ord'] != '__DESC'))
439                        $params['ord'] = '__ASC';
440
441                /* define the sorting criteria */
442                switch($params['sort'])
443                {
444                        case 1:
445                                $order = 'wf_instance_id';
446                                break;
447                        case 2:
448                                $order = 'wf_instance_name';
449                                break;
450                        case 3:
451                                $order = 'wf_owner';
452                                break;
453                        case 4:
454                                $order = 'wf_priority';
455                                break;
456                        case 5:
457                                $order = 'wf_started';
458                                break;
459                        case 6:
460                                $order = 'wf_ended';
461                                break;
462                        case 7:
463                                $order = 'wf_status';
464                                break;
465                        default:
466                                $order = 'wf_instance_id';
467                                break;
468                }
469                $order .= $params['ord'];
470
471                /* load the data */
472                $filters[] = '(gp.wf_p_id = ' . $params['pid'] . ')';
473                $ldap = &Factory::getInstance('WorkflowLDAP');
474                if (!$completeData)
475                {
476                        $paging = Factory::newInstance('Paging', 500, $_POST);
477                        $tmp = $this->processMonitor->monitor_list_completed_instances($paging->nextItem, $paging->itemsPerPage, $order, '', implode(' AND ', $filters));
478                        $output['data'] = $paging->restrictItems(array_values($tmp['data']), $tmp['cant']);
479                        $output['instanceCount'] = $tmp['cant'];
480                        $output['pagingData'] = $paging->commonLinks();
481                }
482                else
483                {
484                        $tmp = $this->processMonitor->monitor_list_completed_instances(0, -1, $order, '', implode(' AND ', $filters));
485                        $output['data'] = array_values($tmp['data']);
486                }
487
488                $cachedLDAP = &Factory::getInstance('CachedLDAP');
489                $userMapping = array();
490                $instanceCount = count($output['data']);
491                for ($i = 0; $i < $instanceCount; $i++)
492                {
493                        /* get the user name */
494                        $currentInstanceOwner = $output['data'][$i]['wf_owner'];
495                        {
496                                $name = $ldap->getName($currentInstanceOwner);
497                                if (empty($name))
498                                {
499                                        $userInfo = $cachedLDAP->getEntryByID($currentInstanceOwner);
500                                        if ($userInfo)
501                                                $name = "ID: {$currentInstanceOwner} - {$userInfo['cn']} (excluído)";
502                                        else
503                                                $name = "ID: {$currentInstanceOwner}";
504                                }
505
506                                $userMapping[$currentInstanceOwner] = $name;
507                        }
508
509                        /* format the data */
510                        $output['data'][$i]['wf_started'] = date('d/m/Y H:i', $output['data'][$i]['wf_started']);
511                        $output['data'][$i]['wf_ended'] = date('d/m/Y H:i', $output['data'][$i]['wf_ended']);
512
513                        /* remove unused elements */
514                        if (!$completeData)
515                                unset(
516                                        $output['data'][$i]['wf_proc_normalized_name'],
517                                        $output['data'][$i]['wf_procname'],
518                                        $output['data'][$i]['wf_version']
519                                );
520                }
521                $output['userMapping'] = $userMapping;
522
523                $output['params'] = $params;
524                return $output;
525        }
526
527        /**
528         * Lista as atividades da instancia
529         * @param array $params Parâmetros advindos da chamada Ajax
530         * @access public
531         * @return array
532         */
533        function listActivities($params)
534        {
535                $pid = (int) $params['pid'];
536                /* check if the user has the proper right to list the activities of this process */
537                if (!$this->checkAccess($pid))
538                        return "Você não tem permissão para executar este procedimento!";
539
540                /* retrieve all the activities */
541                $activities = $this->activityManager->list_activities($pid, 0, -1, 'wf_name__asc', '', '');
542
543                /* format the output */
544                $output['params'] = $params;
545                $output['data'] = array();
546                foreach ($activities['data'] as $activity)
547                        if (($activity['wf_type'] != 'view') && ($activity['wf_type'] != 'standalone') && ($activity['wf_type'] != 'start') && ($activity['wf_is_interactive'] == 'y'))
548                                $output['data'][] = array('id' => $activity['wf_activity_id'], 'name' => $activity['wf_name']);
549
550                return $output;
551        }
552        /**
553         * Lista os usuarios da instancia
554         * @param array $params Parâmetros advindos da chamada Ajax
555         * @access public
556         * @return array lista de usuarios
557         */
558        function listUsers($params)
559        {
560                /* check if the user has the right to view all users from this instance */
561                $instance = $this->instanceManager->get_instance($params['iid']);
562                if ((!$this->checkAccess($params['pid'])) || ($instance['wf_p_id'] != $params['pid']))
563                        return 'Você não tem permissão para executar este procedimento!';
564
565                /* retrieve all the users from the activity */
566                $users = $this->roleManager->list_mapped_users($params['pid'], true, array('wf_activity_id' => $params['aid']));
567                asort($users);
568
569                $roles = $this->activityManager->get_activity_roles($params['aid']);
570                usort($roles, create_function('$a,$b', 'return strcasecmp($a[\'wf_name\'],$b[\'wf_name\']);'));
571                $usersOutput['data'] = array();
572                $usersOutput['data'][] = array('id' => '-1', 'name' => 'TODOS');
573                foreach ($roles as $role)
574                        $usersOutput['data'][] = array('id' => 'p' . $role['wf_role_id'], 'name' => 'Perfil: ' . $role['wf_name']);
575
576                /* format the output */
577                $usersOutput['params'] = $params;
578                foreach ($users as $id => $name)
579                        $usersOutput['data'][] = array('id' => $id, 'name' => $name);
580
581                return $usersOutput;
582        }
583        /**
584         * Realiza o Update da prioridade de uma instancia
585         * @param array $params Parâmetros advindos da chamada Ajax
586         * @access public
587         * @return array parametros?
588         */
589        function updatePriority($params)
590        {
591                /* check if the user has the right to update the priority of the instance */
592                $instance = $this->instanceManager->get_instance($params['iid']);
593                if ((!$this->checkAccess($params['pid'], array($this->IP_CHANGE_PRIORITY))) || ($instance['wf_p_id'] != $params['pid']))
594                        return "Você não tem permissão para executar este procedimento!";
595
596                $this->instanceManager->set_instance_priority($params['iid'], $params['np']);
597                return $params;
598        }
599
600        /**
601         * Realiza o update do usuario atual da instancia
602         * @param array $params Parâmetros advindos da chamada Ajax
603         * @return array
604         * @access public
605         */
606        function updateUser($params)
607        {
608                /* check if the user has the right to update the current user of this instance */
609                $instance = $this->instanceManager->get_instance($params['iid']);
610                if ((!$this->checkAccess($params['pid'], array($this->IP_CHANGE_USER))) || ($instance['wf_p_id'] != $params['pid']))
611                        return "Você não tem permissão para executar este procedimento!";
612
613                $output = $params;
614                $user = ($params['user'] == -1) ? '*' : $params['user'];
615                if ($user == '*')
616                        $output['fullname'] = '*';
617                else
618                        if (substr($user, 0, 1) == 'p')
619                        {
620                                $role = $this->roleManager->get_role($instance['wf_p_id'], substr($user, 1));
621                                $output['fullname'] = 'Perfil: ' . $role['wf_name'];
622                        }
623                        else
624                                $output['fullname'] = Factory::getInstance('WorkflowLDAP')->getName($user);
625
626                $this->instanceManager->set_instance_user($params['iid'], $params['aid'], $user);
627
628                return $output;
629        }
630        /**
631         * Realiza o update do status da instancia
632         * @param array $params Parâmetros advindos da chamada Ajax
633         * @return array
634         * @access public
635         */
636        function updateStatus($params)
637        {
638                /* check if the user has the right to update the status of the instance */
639                $instance = $this->instanceManager->get_instance($params['iid']);
640                if ((!$this->checkAccess($params['pid'], array($this->IP_CHANGE_STATUS))) || ($instance['wf_p_id'] != $params['pid']))
641                        return "Você não tem permissão para executar este procedimento!";
642
643                if ($params['ns'] == 'aborted')
644                {
645                        $realInstance = &Factory::newInstance('Instance');
646                        $realInstance->getInstance($params['iid']);
647                        if (!empty($realInstance->instanceId))
648                        {
649                                if (!$realInstance->abort())
650                                {
651                                        unset($realInstance);
652                                        return 'Ocorreu um erro ao abortar a instância selecionada';
653                                }
654                        }
655                        else
656                        {
657                                unset($realInstance);
658                                return 'Não foi possível abortar a instância selecionada';
659                        }
660                }
661                else
662                        $this->instanceManager->set_instance_status($params['iid'], $params['ns']);
663
664                return $params;
665        }
666
667        /**
668         * Realiza o update de uma atividade da instancia
669         * @param array $params Parâmetros advindos da chamada Ajax
670         * @return array
671         * @access public
672         */
673        function updateActivity($params)
674        {
675                /* check if the user has the right to update change the activity of the instance */
676                $instance = $this->instanceManager->get_instance($params['iid']);
677                if ((!$this->checkAccess($params['pid'], array($this->IP_CHANGE_ACTIVITY))) || ($instance['wf_p_id'] != $params['pid']))
678                        return "Você não tem permissão para executar este procedimento!";
679
680                /* use next user or * for the new instance */
681                $realInstance = &Factory::newInstance('Instance');
682                $realInstance->getInstance($params['iid'], false, false);
683                $user = $realInstance->getNextUser($params['aid']);
684                $user = ($user == '') ? '*' : $user;
685                $this->instanceManager->set_instance_destination($params['iid'], $params['aid'], $user);
686                $result = $this->activityManager->get_activity($params['aid']);
687                $output = $params;
688                $output['name'] = $result['wf_name'];
689                return $output;
690        }
691
692        /**
693         * Realiza o update do nome da instancia
694         * @param array $params Parâmetros advindos da chamada Ajax
695         * @return array
696         * @access public
697         */
698        function updateName($params)
699        {
700                /* check if the user has the right to update the status of the instance */
701                $instance = $this->instanceManager->get_instance($params['iid']);
702                if ((!$this->checkAccess($params['pid'], array($this->IP_CHANGE_NAME))) || ($instance['wf_p_id'] != $params['pid']))
703                        return "Você não tem permissão para executar este procedimento!";
704
705                $this->instanceManager->set_instance_name($params['iid'], $params['nn']);
706                return $params;
707        }
708
709        /**
710         * Remove instâncias finalizadas
711         * @param array $params Parâmetros advindos da chamada Ajax
712         * @return int O número de instâncias removidas
713         * @access public
714         */
715        function removeCompletedInstances($params)
716        {
717                /* check if the user has the proper right to remove the completed instances of this process */
718                if (!$this->checkAccess($params['pid'], array($this->IP_REMOVE_COMPLETED_INSTANCES)))
719                        return array('error' => 'Você não tem permissão para executar este procedimento!');
720
721                /* load the instances */
722                $rawData = $this->listCompletedInstances($params, true);
723
724                /* remove the instances */
725                $instanceCount = 0;
726                if (!empty($rawData['data']))
727                        foreach ($rawData['data'] as $instance)
728                                if ($this->processMonitor->remove_instance($instance['wf_instance_id']))
729                                        $instanceCount++;
730                return $instanceCount;
731        }
732
733
734        /**
735         * Lista as propriedades de uma instancia
736         * @param array $params Parâmetros advindos da chamada Ajax
737         * @return array
738         * @access public
739         */
740        function listInstanceProperties($params)
741        {
742                /* check if the user has the right to view the  instance properties */
743                $instanceInfo = $this->instanceManager->get_instance($params['iid']);
744                if (((!$this->checkAccess($params['pid'], array($this->IP_VIEW_PROPERTIES))) && (!$this->checkAccess($params['pid'], array($this->IP_CHANGE_PROPERTIES)))) || ($instanceInfo['wf_p_id'] != $params['pid']))
745                        return "Você não tem permissão para executar este procedimento!";
746
747                $maximumDisplaySize = 100;
748                $instance = &Factory::newInstance('Instance');
749                $instance->getInstance($params['iid']);
750
751                $output = array();
752                $output['params'] = $params;
753                foreach ($instance->properties as $name => $value)
754                {
755                        $complete = 1;
756                        if (strlen($value) > $maximumDisplaySize)
757                        {
758                                $value = substr($value, 0, $maximumDisplaySize-3) . "...";
759                                $complete = 0;
760                        }
761                        $output[] = array ("name" => $name, "value" => htmlentities($value), "complete" => $complete);
762                }
763                return $output;
764        }
765
766        /**
767         * Retorna o valor de uma propriedade
768         *
769         * @param array $params Parâmetros advindos da chamada Ajax
770         * @return array
771         * @access public
772         */
773        function getCompletePropertyValue($params)
774        {
775                /* check if the user has the right to edit the instance properties */
776                $instanceInfo = $this->instanceManager->get_instance($params['iid']);
777                if ((!$this->checkAccess($params['pid'], array($this->IP_CHANGE_PROPERTIES))) || ($instanceInfo['wf_p_id'] != $params['pid']))
778                        return "Você não tem permissão para executar este procedimento!";
779
780                $instance = &Factory::newInstance('Instance');
781                $instance->getInstance($params['iid']);
782                $output = $params;
783                $output['value'] = $instance->properties[$params['name']];
784                return $output;
785        }
786
787        /**
788         * Realiza o update de uma propriedade de uma instancia
789         * @param array $params Parâmetros advindos da chamada Ajax
790         * @access public
791         */
792        function updateProperty($params)
793        {
794                /* check if the user has the right to edit the instance properties */
795                $instanceInfo = $this->instanceManager->get_instance($params['iid']);
796                if ((!$this->checkAccess($params['pid'], array($this->IP_CHANGE_PROPERTIES))) || ($instanceInfo['wf_p_id'] != $params['pid']))
797                        return "Você não tem permissão para executar este procedimento!";
798
799                $maximumDisplaySize = 100;
800
801                $instance = &Factory::newInstance('Instance');
802                $instance->getInstance($params['iid']);
803                $instance->set($params['name'], $params['value']);
804                $instance->sync();
805
806                $output = array();
807                if (strlen($params['value']) > $maximumDisplaySize)
808                {
809                        $params['value'] = substr($params['value'], 0, $maximumDisplaySize-3) . "...";
810                        $output['complete'] = 0;
811                }
812                else
813                $output['complete'] = 1;
814                $output['value'] = htmlentities($params['value']);
815
816                return $output;
817        }
818
819        /**
820         * Remove uma propriedade da instancia
821         * @param array $params Parâmetros advindos da chamada Ajax
822         * @return array
823         * @access public
824         */
825        function removeProperty($params)
826        {
827                /* check if the user has the right to remove a property of the instance */
828                $instanceInfo = $this->instanceManager->get_instance($params['iid']);
829                if ((!$this->checkAccess($params['pid'], array($this->IP_CHANGE_PROPERTIES))) || ($instanceInfo['wf_p_id'] != $params['pid']))
830                        return "Você não tem permissão para executar este procedimento!";
831
832                $instance = &Factory::newInstance('Instance');
833                $instance->getInstance($params['iid']);
834                $instance->clear($params['name']);
835                $instance->sync();
836
837                $output = $params;
838                return $output;
839        }
840
841        /**
842         * Mostra as estatisticas
843         * @param array $params Parâmetros advindos da chamada Ajax
844         * @return array
845         * @access public
846         */
847        function showStatistics($params)
848        {
849                if (!$this->checkAccess($params['pid'], array($this->IP_VIEW_STATISTICS)))
850                        return "Você não tem permissão para executar este procedimento!";
851
852                /* common configuration */
853                $output = array();
854                $urlPrefix = 'workflow/inc/class.powergraphic.inc.php?';
855                $powergraphic = &Factory::getInstance('powergraphic');
856                $powergraphic->graphic_1 = $params['pid'];
857                $powergraphic->skin = 1;
858                $powergraphic->credits = 0;
859
860                /* number of instances per month */
861                $powergraphic->type = 4;
862                $powergraphic->title = 'Quantidade de Instancias x Mes';
863                $powergraphic->axis_x = 'Mes';
864                $powergraphic->axis_y = 'No. de Instancias';
865                $aux = $this->processMonitor->stats_instances_per_month($params['pid']);
866                $index = 0;
867                foreach ($aux as $date => $count)
868                {
869                        list($year, $month) = explode('-', $date);
870                        $powergraphic->x[$index] = $month . '/' . substr($year, -2);
871                        $powergraphic->y[$index++] = $count;
872                }
873                if (count($aux) > 0)
874                        $output[] = $powergraphic->create_query_string();
875
876                /* number of instances per activity */
877                $powergraphic->x = $powergraphic->y = array();
878                $powergraphic->type = 5;
879                $powergraphic->title = 'Instancias x Atividade';
880                $powergraphic->axis_x = 'Atividade';
881                $powergraphic->axis_y = 'No. de Instancias';
882                $aux = $this->processMonitor->stats_instances_activities($params['pid']);
883                $index = 0;
884                foreach ($aux as $info)
885                {
886                        $powergraphic->x[$index] = $info['wf_name'] . " ({$info['count']})";
887                        $powergraphic->y[$index++] = $info['count'];
888                }
889                if (count($aux) > 0)
890                        $output[] = $powergraphic->create_query_string();
891
892                /* number of instances per user */
893                $powergraphic->x = $powergraphic->y = array();
894                $powergraphic->type = 5;
895                $powergraphic->title = 'Instancias x Usuario';
896                $powergraphic->axis_x = 'Usuario';
897                $powergraphic->axis_y = 'No. de Instancias';
898                $aux = $this->processMonitor->stats_instances_per_user($params['pid']);
899                /* prepare the data */
900                $aux2 = array();
901                $ldap = &Factory::getInstance('WorkflowLDAP');
902                foreach ($aux as $user => $count)
903                        $aux2[] = array(
904                                'user' => $ldap->getName($user) . " ({$count})",
905                                'count' => $count
906                        );
907                usort($aux2, create_function('$a,$b', 'return strcasecmp($a[\'user\'],$b[\'user\']);'));
908                $index = 0;
909                foreach ($aux2 as $info)
910                {
911                        $powergraphic->x[$index] = $info['user'];
912                        $powergraphic->y[$index++] = $info['count'];
913                }
914                if (count($aux) > 0)
915                        $output[] = $powergraphic->create_query_string();
916
917                /* number of instances per status */
918                $translateStatus = array(
919                        'completed' => 'Completada',
920                        'active' => 'Ativa',
921                        'aborted' => 'Abortada',
922                        'exception' => 'Em exceção');
923                $powergraphic->x = $powergraphic->y = array();
924                $powergraphic->type = 5;
925                $powergraphic->title = 'Instancias x Status';
926                $powergraphic->axis_x = 'Status';
927                $powergraphic->axis_y = 'No. de Instancias';
928                $aux = $this->processMonitor->stats_instances_per_status($params['pid']);
929                $index = 0;
930                foreach ($aux as $status => $count)
931                {
932                        $powergraphic->x[$index] = $translateStatus[$status] . " ({$count})";
933                        $powergraphic->y[$index++] = $count;
934                }
935                if (count($aux) > 0)
936                        $output[] = $powergraphic->create_query_string();
937
938                foreach ($output as $key => $value)
939                        $output[$key] = $urlPrefix . $value;
940                return $output;
941        }
942
943        /**
944         * Pega os usuários de instâncias ativas de um determinado processo
945         * @param array $params Parâmetros advindos da chamada Ajax
946         * @return array Contendo o nome/id dos usuários
947         * @access public
948         */
949        function getUsersInInstances($params)
950        {
951                $pid = (int) $params['pid'];
952                /* check if the user has the proper right to list the users of this process */
953                if (!$this->checkAccess($pid))
954                        return "Você não tem permissão para executar este procedimento!";
955
956                /* initialize some variables */
957                $users = array();
958                $roles = array();
959                $specialUsers = array();
960
961                /* load the users */
962                $activities = $this->activityManager->get_process_activities($pid);
963                if (!empty($activities))
964                        $users = $this->processMonitor->monitor_list_users('wf_activity_id IN (' . implode(',', array_map(create_function('$a', 'return $a[\'wf_activity_id\'];'), $activities)) . ')');
965
966                /* remove the '*' user */
967                if (($asteriskPosition = array_search('*', $users)) !== false)
968                        unset($users[$asteriskPosition]);
969
970                /* separate roles from users */
971                foreach ($users as $key => $user)
972                {
973                        if (substr($user, 0, 1) == 'p')
974                        {
975                                $roles[] = $user;
976                                unset($users[$key]);
977                        }
978                }
979
980                /* load LDAP info and sort the result */
981                $foundUsers = Factory::getInstance('WorkflowLDAP')->getNames($users);
982                usort($foundUsers, create_function('$a,$b', 'return strcasecmp($a[\'name\'],$b[\'name\']);'));
983
984
985                /* special treatment for  users not found in LDAP */
986                if (count($users) > count($foundUsers))
987                {
988                        $cachedLDAP = &Factory::getInstance('CachedLDAP');
989                        $foundUsersID = array_map(create_function('$a', 'return $a[\'id\'];'), $foundUsers);
990                        $missingUsers = array_diff($users, $foundUsersID);
991                        foreach ($missingUsers as $missingUser)
992                        {
993                                $userInfo = $cachedLDAP->getEntryByID($missingUser);
994                                if ($userInfo)
995                                        $name = "ID: {$missingUser} - {$userInfo['cn']} (excluído)";
996                                else
997                                        $name = "ID: {$missingUser}";
998                                $specialUsers[] = array('id' => $missingUser, 'name' => $name);
999                        }
1000                }
1001
1002                /* load roles info */
1003                foreach ($roles as $role)
1004                {
1005                        $roleInfo = $this->roleManager->get_role($pid, substr($role, 1));
1006                        $specialUsers[] = array('id' => $role, 'name' => 'Perfil: ' . $roleInfo['wf_name']);
1007                }
1008
1009                /* sort the special users */
1010                usort($specialUsers, create_function('$a,$b', 'return strnatcasecmp($a[\'name\'],$b[\'name\']);'));
1011
1012                /* define the output (merging the ordinary users with the "special" ones) */
1013                $output = $params;
1014                $output['users'] = array_merge($specialUsers, $foundUsers);
1015
1016                return $output;
1017        }
1018
1019        /**
1020         * Pega os proprietários de instâncias ativas ou inativas de um determinado processo
1021         * @param array $params Parâmetros advindos da chamada Ajax
1022         * @return array Contendo o nome/id dos proprietários
1023         * @access public
1024         */
1025        function getInstancesOwners($params)
1026        {
1027                $pid = (int) $params['pid'];
1028
1029                /* check if the user has the proper right to list the owners of this process */
1030                if (!$this->checkAccess($pid))
1031                        return 'Você não tem permissão para executar este procedimento!';
1032
1033                $output = $params;
1034                $output['owners'] = array();
1035
1036                /* load the instances (active ou completed ones) */
1037                if ($params['currentList'] == 'active')
1038                        $instances = $this->listInstances($params, true);
1039                else
1040                        $instances = $this->listCompletedInstances($params, true);
1041
1042                /* get the owners */
1043                if (count($instances['userMapping']) > 0)
1044                {
1045                        if ($params['currentList'] == 'completed')
1046                        {
1047                                foreach ($instances['userMapping'] as $id => $name)
1048                                        $output['owners'][] = array('id' => $id, 'name' => $name);
1049                        }
1050                        else
1051                        {
1052                                foreach ($instances['data'] as $instance)
1053                                        if (!isset($output['owners'][$instance['wf_owner']]))
1054                                                $output['owners'][$instance['wf_owner']] = array('id' => $instance['wf_owner'], 'name' => $instances['userMapping'][$instance['wf_owner']]);
1055                                $output['owners'] = array_values($output['owners']);
1056                        }
1057                }
1058
1059                /* sort the owners */
1060                usort($output['owners'], create_function('$a,$b', 'return strcasecmp($a[\'name\'],$b[\'name\']);'));
1061
1062                return $output;
1063        }
1064
1065        /**
1066         * Pega as atividades das instâncias de um determinado usuário
1067         * @param array $params Parâmetros advindos da chamada Ajax
1068         * @return array Contendo o nome/id das atividades
1069         * @access public
1070         */
1071        function getUserActivities($params)
1072        {
1073                $pid = (int) $params['pid'];
1074                $user = (int) $params['user'];
1075                /* check if the user has the proper right to list the instances of this process */
1076                if (!$this->checkAccess($pid, array($this->IP_REPLACE_USER)))
1077                        return "Você não tem permissão para executar este procedimento!";
1078
1079                $instances = $this->processMonitor->monitor_list_instances(0, -1, 'wf_activity_name__ASC', null, "gia.wf_user = '{$user}' AND gp.wf_p_id = {$pid}");
1080                $activities = array_map('unserialize', array_unique(array_map(create_function('$a', 'return serialize(array(\'id\' => $a[\'wf_activity_id\'], \'name\' => $a[\'wf_activity_name\']));'), $instances['data'])));
1081                usort($activities, create_function('$a,$b', 'return strcasecmp($a[\'name\'],$b[\'name\']);'));
1082
1083                $output = $params;
1084                $output['activities'] = $activities;
1085
1086                return $output;
1087        }
1088
1089        /**
1090         * Verifica se o novo dono das instâncias já está em todos os perfis necessários. Caso não esteja, envia uma lista com sugestões de perfis
1091         * @param array $params Parâmetros advindos da chamada Ajax
1092         * @return array Contendo informações e sugestões de perfis para adicionar o novo dono das instâncias
1093         * @access public
1094         */
1095        function checkUserRoles($params)
1096        {
1097                $pid = (int) $params['pid'];
1098                $oldUser = (int) $params['oldUser'];
1099                $newUser = (int) $params['newUser'];
1100                $activity = (int) $params['activity'];
1101
1102                /* check if the user has the proper right to list the instances of this process */
1103                if (!$this->checkAccess($pid, array($this->IP_REPLACE_USER)))
1104                        return "Você não tem permissão para executar este procedimento!";
1105
1106                $activities = array();
1107                if ($activity == 0)
1108                {
1109                        $instances = $this->processMonitor->monitor_list_instances(0, -1, 'wf_activity_name__ASC', null, "gia.wf_user = '{$oldUser}' AND gp.wf_p_id = {$pid}");
1110                        $activities = array_values(array_map('unserialize', array_unique(array_map(create_function('$a', 'return serialize(array(\'id\' => $a[\'wf_activity_id\'], \'name\' => $a[\'wf_activity_name\']));'), $instances['data']))));
1111                }
1112                else
1113                {
1114                        $activityInfo = $this->activityManager->get_activity($activity);
1115                        $activities[] = array('id' => $activity, 'name' => $activityInfo['wf_name']);
1116                }
1117
1118                $userRoles = $this->roleManager->getUserRoles($newUser, $pid);
1119                foreach ($activities as $key => $value)
1120                {
1121                        $roles = $this->activityManager->get_activity_roles($value['id']);
1122                        $userExistsInRoles = false;
1123                        foreach ($roles as $role)
1124                        {
1125                                if (in_array($role['wf_role_id'], $userRoles))
1126                                {
1127                                        $userExistsInRoles = true;
1128                                        break;
1129                                }
1130                                else
1131                                        $activities[$key]['possibleRoles'][] = array('id' => $role['wf_role_id'], 'name' => $role['wf_name']);
1132                        }
1133                        if ($userExistsInRoles)
1134                        {
1135                                unset($activities[$key]);
1136                                continue;
1137                        }
1138                }
1139                $output = $params;
1140                $output['roles'] = array_values($activities);
1141
1142                return $output;
1143        }
1144
1145        /**
1146         * Adiciona um usuário ao perfil indicado
1147         * @param array $params Parâmetros advindos da chamada Ajax
1148         * @return array Contém a saída do método 'checkUserRoles'
1149         * @access public
1150         */
1151        function addUserToRole($params)
1152        {
1153                $pid = (int) $params['pid'];
1154                $newUser = (int) $params['newUser'];
1155                $role = (int) $params['role'];
1156
1157                /* check if the user has the proper right to list the instances of this process */
1158                if (!$this->checkAccess($pid, array($this->IP_REPLACE_USER)))
1159                        return "Você não tem permissão para executar este procedimento!";
1160
1161                /* get the process roles */
1162                $processRoles = $this->roleManager->list_roles($pid, 0, -1, 'wf_p_id__ASC', null);
1163                $processRoles = array_map(create_function('$a', 'return $a[\'wf_role_id\'];'), $processRoles['data']);
1164
1165                /* check if the role belongs to the process */
1166                if (!in_array($role, $processRoles))
1167                        return 'Os dados fornecidos estão incorretos.';
1168                $this->roleManager->map_user_to_role($pid, $newUser, $role, 'u');
1169
1170                return $this->checkUserRoles($params);
1171        }
1172
1173        /**
1174         * Troca os usuários das instâncias (de acordo com filtro de atividade e usuário original)
1175         * @param array $params Parâmetros advindos da chamada Ajax
1176         * @return array Contém estatísticas sobre as instâncias alteradas
1177         * @access public
1178         */
1179        function replaceUser($params)
1180        {
1181                $pid = (int) $params['pid'];
1182                $oldUser = (int) $params['oldUser'];
1183                $newUser = (int) $params['newUser'];
1184                $activity = (int) $params['activity'];
1185
1186                /* check if the user has the proper right to list the instances of this process */
1187                if (!$this->checkAccess($pid, array($this->IP_REPLACE_USER)))
1188                        return "Você não tem permissão para executar este procedimento!";
1189
1190                $instances = $this->processMonitor->monitor_list_instances(0, -1, 'wf_activity_name__ASC', null, "gia.wf_user = '{$oldUser}' AND gp.wf_p_id = {$pid}");
1191                $activities = array();
1192                if ($activity == 0)
1193                        $activities = array_unique(array_map(create_function('$a', 'return $a[\'wf_activity_id\'];'), $instances['data']));
1194                else
1195                        $activities[] = $activity;
1196
1197                $OKCount = 0;
1198                $errorCount = 0;
1199                foreach ($instances['data'] as $instance)
1200                {
1201                        if (in_array($instance['wf_activity_id'], $activities))
1202                        {
1203                                if ($this->instanceManager->set_instance_user($instance['wf_instance_id'], $instance['wf_activity_id'], $newUser))
1204                                        $OKCount++;
1205                                else
1206                                        $errorCount++;
1207                        }
1208                }
1209                $output = $params;
1210                $output['OKCount'] = $OKCount;
1211                $output['errorCount'] = $errorCount;
1212
1213                return $output;
1214        }
1215
1216        /**
1217         * Gera os e-mails enviados para alertar sobre determinadas instâncias
1218         * @param array $params Parâmetros repassados por outros métodos e que são advindos de uma chamada Ajax
1219         * @return array Uma array seqüencial onde cada elemento corresponde a uma array contendo as informações de: nome do destinatário, e-mail do destinatário, ID do destinatário, corpo do e-mail e assunto do e-mail
1220         * @access public
1221         */
1222        function generateEmails($params)
1223        {
1224                /* define the type */
1225                $type = ($params['emailType'] == 'user') ? 'user' : 'instance';
1226
1227                /* load the instances and add the username */
1228                $rawData = $this->listInstances($params, true);
1229                $list = array();
1230                foreach ($rawData['data'] as $element)
1231                        if (($element['wf_user'] != '*') && (substr($element['wf_user'], 0, 1) != 'p'))
1232                                $list[] = array_merge($element, array('wf_user_name' => $rawData['userMapping'][$element['wf_user']]));
1233
1234                /* check if there is at least one instance */
1235                $output = array();
1236                if (count($list) === 0)
1237                        return $output;
1238
1239                $BOUserInterface = &Factory::getInstance('bo_userinterface');
1240
1241                /* initialize some variables */
1242                $translationArray = array();
1243                $emailBody = $params['emailBody'];
1244                $emailSubject = $params['emailSubject'];
1245
1246                /* if the developer decided to send only one e-mail per user */
1247                if ($type === 'user')
1248                {
1249                        /* split the e-mail according to definition */
1250                        ereg('(.*)%inicio_loop%(.*)%fim_loop%(.*)', $emailBody, $records);
1251                        if (($records == null) || (count($records) != 4))
1252                                return array('error' => 'Formato de e-mail inválido');
1253
1254                        /* prepare the list */
1255                        $userList = array();
1256                        foreach ($list as $element)
1257                                $userList[$element['wf_user']][] = $element;
1258
1259                        /* construct the e-mails */
1260                        foreach ($userList as $user => $instances)
1261                        {
1262                                /* add the e-mail header */
1263                                $email = $records[1];
1264                                $totalInstances = count($instances);
1265                                $currentInstance = 1;
1266                                foreach ($instances as $instance)
1267                                {
1268                                        /* prepare the translation array */
1269                                        $url = sprintf('%s/index.php?menuaction=workflow.run_activity.go&activity_id=%d&iid=%d', $_SESSION['phpgw_info']['workflow']['server']['webserver_url'], $instance['wf_activity_id'], $instance['wf_instance_id']);
1270                                        $translationArray = array(
1271                                                '%atividade%' => $instance['wf_activity_name'],
1272                                                '%usuario%' => $instance['wf_user_name'],
1273                                                '%processo%' => $instance['wf_procname'],
1274                                                '%identificador%' => $instance['wf_instance_name'],
1275                                                '%tempo_atividade%' => $BOUserInterface->time_diff(mktime() - $instance['wf_act_started']),
1276                                                '%tempo_instancia%' => $BOUserInterface->time_diff(mktime() - $instance['wf_started']),
1277                                                '%prioridade%' => $instance['wf_priority'],
1278                                                '%quantidade_instancia%' => $totalInstances,
1279                                                '%atual_instancia%' => $currentInstance++,
1280                                                '%inicio_atividade%' => date('d/m/Y H\hi', $instance['wf_act_started']),
1281                                                '%inicio_instancia%' => date('d/m/Y H\hi', $instance['wf_started']),
1282                                                '%url%' => $url,
1283                                                '%link%' => sprintf('<a href="%s" target="_blank">%s</a>', $url, $url)
1284                                        );
1285
1286                                        $email .= str_replace(array_keys($translationArray), array_values($translationArray), $records[2]);
1287                                }
1288
1289                                /* add the e-mail footer */
1290                                $email .= $records[3];
1291
1292                                /* replace, once again, any %variable% (also for the subject) */
1293                                $email = str_replace(array_keys($translationArray), array_values($translationArray), $email);
1294                                $subject = str_replace(array_keys($translationArray), array_values($translationArray), $emailSubject);
1295
1296                                /* construct the final e-mail array */
1297                                $output[] = array(
1298                                        'emailBody' => $email,
1299                                        'emailSubject' => $subject,
1300                                        'user' => $user
1301                                );
1302                        }
1303                }
1304
1305                if ($type === 'instance')
1306                {
1307                        /* construct the e-mails */
1308                        foreach ($list as $instance)
1309                        {
1310                                $url = sprintf('%s/index.php?menuaction=workflow.run_activity.go&activity_id=%d&iid=%d', $_SESSION['phpgw_info']['workflow']['server']['webserver_url'], $instance['wf_activity_id'], $instance['wf_instance_id']);
1311                                $translationArray = array(
1312                                        '%atividade%' => $instance['wf_activity_name'],
1313                                        '%usuario%' => $instance['wf_user_name'],
1314                                        '%processo%' => $instance['wf_procname'],
1315                                        '%identificador%' => $instance['wf_instance_name'],
1316                                        '%tempo_atividade%' => $BOUserInterface->time_diff(mktime() - $instance['wf_act_started']),
1317                                        '%tempo_instancia%' => $BOUserInterface->time_diff(mktime() - $instance['wf_started']),
1318                                        '%prioridade%' => $instance['wf_priority'],
1319                                        '%quantidade_instancia%' => 1,
1320                                        '%atual_instancia%' => 1,
1321                                        '%inicio_atividade%' => date('d/m/Y H\hi', $instance['wf_act_started']),
1322                                        '%inicio_instancia%' => date('d/m/Y H\hi', $instance['wf_started']),
1323                                        '%url%' => $url,
1324                                        '%link%' => sprintf('<a href="%s" target="_blank">%s</a>', $url, $url)
1325                                );
1326
1327                                /* replace any %variable% for its correspondence (also for the subject) */
1328                                $email = str_replace(array_keys($translationArray), array_values($translationArray), $emailBody);
1329                                $subject = str_replace(array_keys($translationArray), array_values($translationArray), $emailSubject);
1330
1331                                /* construct the final e-mail array */
1332                                $output[] = array(
1333                                        'emailBody' => $email,
1334                                        'emailSubject' => $subject,
1335                                        'user' => $instance['wf_user']
1336                                );
1337                        }
1338                }
1339
1340                /* load the recipient e-mail */
1341                $ldap = &Factory::getInstance('WorkflowLDAP');
1342                foreach ($output as $key => $value)
1343                {
1344                        $userData = $ldap->getUserInfo($value['user']);
1345                        $output[$key]['to'] = $userData['mail'];
1346                        $output[$key]['username'] = $userData['cn'];
1347                }
1348
1349                return $output;
1350        }
1351
1352        /**
1353         * Gera um preview do e-mail que será enviado
1354         * @param array $params Parâmetros advindos da chamada Ajax
1355         * @return string O corpo do primeiro e-mail que seria enviado caso a ação "Enviar" fosse disparada
1356         * @access public
1357         */
1358        function previewEmail($params)
1359        {
1360                /* check if the user has the proper right to send e-mails related to this process */
1361                $pid = (int) $params['pid'];
1362                if (!$this->checkAccess($pid, array($this->IP_SEND_EMAILS)))
1363                        return array('error' => 'Você não tem permissão para executar este procedimento!');
1364
1365                $output = $this->generateEmails($params);
1366                if (!isset($output['error']))
1367                        return array('emailBody' => $output[0]['emailBody'], 'emailCount' => count($output));
1368                else
1369                        return $output;
1370        }
1371
1372        /**
1373         * Envia e-mails para os usuários das instâncias selecionadas
1374         * @param array $params Parâmetros advindos da chamada Ajax
1375         * @return int O número de e-mails enviados
1376         * @access public
1377         */
1378        function sendMail($params)
1379        {
1380                /* check if the user has the proper right to send e-mails related to this process */
1381                $pid = (int) $params['pid'];
1382                if (!$this->checkAccess($pid, array($this->IP_SEND_EMAILS)))
1383                        return array('error' => 'Você não tem permissão para executar este procedimento!');
1384
1385                /* generate the e-mails */
1386                $emails = $this->generateEmails($params);
1387
1388                /* check for errors */
1389                if (isset($emails['error']) || (count($emails) == 0))
1390                        return $emails;
1391
1392                /* prepare the environment to load some configuration values from other module */
1393                $GLOBALS['phpgw']->db =& Factory::getInstance('WorkflowObjects')->getDBExpresso();
1394                $GLOBALS['phpgw']->common = Factory::getInstance('common');
1395                $GLOBALS['phpgw']->session = Factory::getInstance('sessions');
1396                function lang($a){return $a;};
1397
1398                /* get the required configuration */
1399                $BOEmailAdmin = Factory::getInstance('bo');
1400                $profileList = $BOEmailAdmin->getProfileList();
1401                $profile = $BOEmailAdmin->getProfile($profileList[0]['profileID']);
1402
1403                /**
1404                 * XXX - XXX
1405                 * It's weird.. There are two almost identical PHPMailer classes.
1406                 * The class registered in our factory is under 'EGW_INC_ROOT'.
1407                 * The class used here has the same name and it's under another
1408                 * directory. For now, let's just include it in the old-fashion
1409                 * way, but if someone, someday try to use both classes in the
1410                 * same access, it could cause us troubles.
1411                 */
1412
1413                /* configure the PHPMailer class to send the e-mails */
1414                require_once '../expressoMail1_2/inc/class.phpmailer.php';
1415                $phpMailer = new PHPMailer();
1416                $phpMailer->SMTPDebug = false;
1417                $phpMailer->IsSMTP();
1418                $phpMailer->Host = $profile['smtpServer'];
1419                $phpMailer->Port = $profile['smtpPort'];
1420                $phpMailer->From = 'no-reply@' . $profile['defaultDomain'];
1421                $phpMailer->FromName = 'Workflow Expresso';
1422
1423                /* send the e-mails */
1424                $count = 0;
1425                foreach ($emails as $email)
1426                {
1427                        $phpMailer->ClearAllRecipients();
1428                        $phpMailer->IsHTML(true);
1429                        $phpMailer->Subject = $email['emailSubject'];
1430                        $phpMailer->Body = $email['emailBody'];
1431                        $phpMailer->AddAddress($email['to'], $email['username']);
1432                        if ($phpMailer->Send())
1433                                $count++;
1434                }
1435                return $count;
1436        }
1437
1438        /**
1439         * Lista instâncias inconsistentes.
1440         * @param array $params Parâmetros advindos da chamada Ajax
1441         * @return array Uma array contendo as instâncias de acordo com suas inconsistências
1442         * @access public
1443         */
1444        function loadInconsistentInstances($params)
1445        {
1446                $processID = (int) $params['pid'];
1447                /* check if the user has the proper right to send e-mails related to this process */
1448                if (!$this->checkAccess($processID))
1449                        return "Você não tem permissão para executar este procedimento!";
1450
1451                $output = array(
1452                        'instances' => array(),
1453                        'names' => array(),
1454                        'params' => $params
1455                );
1456
1457                $output['instances'][] = array(
1458                        'name' => 'Usuários Removidos',
1459                        'description' => 'Quando uma instância está atribuída a um usuário que não está mais no LDAP.',
1460                        'items' => $this->inconsistentInstancesRemovedUser($processID)
1461                );
1462
1463                $output['instances'][] = array(
1464                        'name' => 'Usuários sem Autorização',
1465                        'description' => 'Quando o usuário que está com a instância não pertence a nenhum dos perfis da atividade desta instância.',
1466                        'items' => $this->inconsistentInstancesUnauthorizedUsers($processID)
1467                );
1468
1469                $output['instances'][] = array(
1470                        'name' => 'Instâncias Falhas',
1471                        'description' => 'Quando uma instância encontra-se em uma atividade não-interativa.',
1472                        'items' => $this->inconsistentInstancesFailedInstances($processID)
1473                );
1474
1475                $output['instances'][] = array(
1476                        'name' => 'Instâncias Finalizadas Vinculadas a uma Atividade',
1477                        'description' => 'Quando uma instância finalizada ou abortada ainda está vinculada a uma atividade.',
1478                        'items' => $this->inconsistentInstancesUnfinishedActivity($processID)
1479                );
1480
1481                $userIDs = array();
1482                foreach ($output['instances'] as $inconsistencyTypes)
1483                        foreach ($inconsistencyTypes['items'] as $instance)
1484                                $userIDs[$instance['wf_user']] = '';
1485
1486                $output['names'] = $this->getNames(array_keys($userIDs), $processID);
1487
1488                return $output;
1489        }
1490
1491        /**
1492         * Carrega os nomes de usuários/perfis
1493         * @param array $userIDs Uma array contendo os IDs dos usuários/perfis.
1494         * @param int $processID O ID do processo de onde os nomes dos perfis serão extraídos
1495         * @return array Uma array associativa no formato ID => Nome
1496         * @access public
1497         */
1498        private function getNames($userIDs, $processID)
1499        {
1500                $output = array();
1501                $cachedLDAP = &Factory::getInstance('CachedLDAP');
1502                $ldap = &Factory::getInstance('WorkflowLDAP');
1503                foreach ($userIDs as $userID)
1504                {
1505                        if (!isset($output[$userID]))
1506                        {
1507                                if ($userID == '*')
1508                                {
1509                                        $output['*'] = '*';
1510                                        continue;
1511                                }
1512
1513                                if (substr($userID, 0, 1) == 'p')
1514                                {
1515                                        $role = $this->roleManager->get_role($processID, substr($userID, 1));
1516                                        $output[$userID] = 'Perfil: ' . $role['wf_name'];
1517                                }
1518                                else
1519                                {
1520                                        $name = $ldap->getName($userID);
1521                                        if (empty($name))
1522                                        {
1523                                                $userInfo = $cachedLDAP->getEntryByID($userID);
1524                                                if ($userInfo)
1525                                                        $name = "ID: {$userID} - {$userInfo['cn']} (excluído)";
1526                                                else
1527                                                        $name = "ID: {$userID}";
1528                                        }
1529
1530                                        $output[$userID] = $name;
1531                                }
1532                        }
1533                }
1534                return $output;
1535        }
1536
1537        /**
1538         * Lista as instâncias inconsistentes: instâncias que estão com usuários que foram removidos do LDAP
1539         * @param int $processID O ID do processo
1540         * @return array Lista das instâncias que satisfazem o critério de inconsistência
1541         * @access public
1542         */
1543        private function inconsistentInstancesRemovedUser($processID)
1544        {
1545                $filters = array();
1546                $filters[] = "(gp.wf_p_id = {$processID})";
1547                $filters[] = '(gia.wf_user IS NOT NULL)';
1548
1549                $cachedLDAP = &Factory::newInstance('CachedLDAP');
1550                $cachedLDAP->setOperationMode($cachedLDAP->OPERATION_MODE_LDAP);
1551                $output = array();
1552                $instanceList = $this->processMonitor->monitor_list_instances(0, -1, 'wf_instance_id__ASC', '', implode(' AND ', $filters));
1553
1554                $userIDs = array();
1555                foreach ($instanceList['data'] as $instance)
1556                {
1557                        if (substr($instance['wf_user'], 0, 1) == 'p')
1558                                continue;
1559
1560                        if ($instance['wf_user'] == '*')
1561                                continue;
1562
1563                        $userIDs[$instance['wf_user']] = true;
1564                }
1565
1566                $validUsers = Factory::getInstance('WorkflowLDAP')->getNames(array_keys($userIDs));
1567                array_walk($validUsers, create_function('&$a', '$a = $a[\'id\'];'));
1568
1569                foreach ($instanceList['data'] as $instance)
1570                {
1571                        if (substr($instance['wf_user'], 0, 1) == 'p')
1572                                continue;
1573
1574                        if ($instance['wf_user'] == '*')
1575                                continue;
1576
1577                        if (!in_array($instance['wf_user'], $validUsers))
1578                                $output[] = $instance;
1579                }
1580
1581                return $output;
1582        }
1583
1584        /**
1585         * Lista as instâncias inconsistentes: instâncias que estão com usuários que não estão em nenhum dos perfis da atividade em que a instância se encontra
1586         * @param int $processID O ID do processo
1587         * @return array Lista das instâncias que satisfazem o critério de inconsistência
1588         * @access public
1589         */
1590        private function inconsistentInstancesUnauthorizedUsers($processID)
1591        {
1592                $output = array();
1593                $roleIDs = array();
1594                $roles = $this->roleManager->list_roles($processID, 0, -1, 'wf_role_id__ASC', '');
1595                foreach ($roles['data'] as $role)
1596                        $roleIDs[] = $role['wf_role_id'];
1597                $activities = $this->activityManager->list_activities($processID, 0, -1, 'wf_name__asc', '', '');
1598                $activityUsers = array();
1599                foreach ($activities['data'] as $activity)
1600                {
1601                        if ($activity['wf_is_interactive'] == 'y')
1602                        {
1603                                $userList = $this->roleManager->list_mapped_users($processID, true, array('wf_activity_id' => $activity['wf_activity_id']));
1604                                if (!isset($activityUsers[$activity['wf_activity_id']]))
1605                                        $activityUsers[$activity['wf_activity_id']] = array();
1606                                $activityUsers[$activity['wf_activity_id']] += array_keys($userList);
1607                        }
1608                }
1609
1610                $filters = array();
1611                $filters[] = "(gp.wf_p_id = {$processID})";
1612                $filters[] = "(ga.wf_is_interactive = 'y')";
1613                $filters[] = '(gia.wf_user IS NOT NULL)';
1614                $instanceList = $this->processMonitor->monitor_list_instances(0, -1, 'wf_instance_id__ASC', '', implode(' AND ', $filters));
1615                foreach ($instanceList['data'] as $instance)
1616                {
1617                        if ($instance['wf_user'] == '*')
1618                                continue;
1619
1620                        if (substr($instance['wf_user'], 0, 1) == 'p')
1621                                if (in_array(substr($instance['wf_user'], 1), $roleIDs))
1622                                        continue;
1623
1624                        if (in_array($instance['wf_user'], $activityUsers[$instance['wf_activity_id']]))
1625                                continue;
1626
1627                        $output[] = $instance;
1628                }
1629
1630                return $output;
1631        }
1632
1633        private function inconsistentInstancesFailedInstances($processID)
1634        {
1635                $filters = array();
1636                $filters[] = "(gp.wf_p_id = {$processID})";
1637                $filters[] = "(ga.wf_is_interactive = 'n')";
1638                $filters[] = '(gia.wf_started < ' . (date('U') - 60). ')';
1639                $instanceList = $this->processMonitor->monitor_list_instances(0, -1, 'wf_instance_id__ASC', '', implode(' AND ', $filters));
1640
1641                return $instanceList['data'];
1642        }
1643
1644        /**
1645         * Lista as instâncias inconsistentes: instâncias que estão paradas em atividades não-interativas há mais de um minuto
1646         * @param int $processID O ID do processo
1647         * @return array Lista das instâncias que satisfazem o critério de inconsistência
1648         * @access public
1649         */
1650        private function inconsistentInstancesUnfinishedActivity($processID)
1651        {
1652                $filters = array();
1653                $filters[] = "(gp.wf_p_id = {$processID})";
1654                $filters[] = "(gi.wf_status IN ('aborted', 'completed'))";
1655                $filters[] = '(gia.wf_activity_id IS NOT NULL)';
1656                $instanceList = $this->processMonitor->monitor_list_instances(0, -1, 'wf_instance_id__ASC', '', implode(' AND ', $filters));
1657
1658                return $instanceList['data'];
1659        }
1660}
1661?>
Note: See TracBrowser for help on using the repository browser.