source: sandbox/workflow/branches/609/inc/class.bo_monitors.inc.php @ 2323

Revision 2323, 54.5 KB checked in by pedroerp, 14 years ago (diff)

Ticket #609 - Removendo 'require_once's desnecessários.

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