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

Revision 2311, 54.2 KB checked in by pedroerp, 14 years ago (diff)

Ticket #609 - Migrando instanciação das classes da engine para a factory.

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