source: sandbox/workflow/trunk/inc/class.so_move_instances.inc.php @ 2466

Revision 2466, 12.3 KB checked in by pedroerp, 14 years ago (diff)

Ticket #609 - Merged 2356:2442 /sandbox/workflow/branches/609 em /sandbox/workflow/trunk.

Line 
1<?php
2
3/**************************************************************************\
4* eGroupWare                                                               *
5* http://www.egroupware.org                                                *
6* --------------------------------------------                             *
7*  This program is free software; you can redistribute it and/or modify it *
8*  under the terms of the GNU General Public License as published by the   *
9*  Free Software Foundation; either version 2 of the License, or (at your  *
10*  option) any later version.                                              *
11\**************************************************************************/
12
13
14/**
15 * Camada Model para Mover Instâncias.
16 * @package Workflow
17 * @author Sidnei Augusto Drovetto Jr. - drovetto@gmail.com
18 * @license http://www.gnu.org/copyleft/gpl.html GPL
19 */
20class so_move_instances
21{
22        /**
23         * @var bool True se o usuário for administrador do expresso.
24         * @access private
25         */
26        private $isAdmin;
27
28        /**
29         * @var int ID do usuário logado no Expresso
30         * @access private
31         */
32        private $userID;
33
34        /**
35         * @var object Link para a ACL do Workflow.
36         * @access private
37         */
38        private $acl;
39
40        /**
41         * @var object Link para o Banco de Dados do Expresso.
42         * @access private
43         */
44        private $db;
45
46        /**
47         * Checa se o usuário possui direitos administrativos em um processo.
48         * @param int $processID O ID do processo que se quer checar se o usuário tem direito administrativo.
49         * @return bool True em caso de sucesso. Em caso de falha, a execução é abortada.
50         * @access private
51         */
52        private function _checkAccess($processID = null)
53        {
54                /* the user is an administrator */
55                if ($this->isAdmin)
56                        return true;
57
58                if (!is_null($processID))
59                {
60                        if ($this->acl->checkUserGroupAccessToResource('PRO', $this->userID, $processID))
61                                return true;
62                        else
63                                die(serialize("Você não tem permissão para executar este procedimento!"));
64                }
65                if ($this->acl->checkUserGroupAccessToType('PRO', $this->userID))
66                        return true;
67
68                die(serialize("Você não tem permissão para executar este procedimento!"));
69        }
70
71        /**
72         * Verifica se houve erro em alguma query do Banco de Dados.
73         * @param object $result O resultado de alguma query
74         * @return void
75         * @access private
76         */
77        private function _checkError($result)
78        {
79                if ($result === false)
80                        die(serialize("Ocorreu um erro ao se tentar executar a operação solicitada."));
81        }
82
83        /**
84         * Construtor da classe so_move_instances
85         * @return object
86         */
87        function so_move_instances()
88        {
89                $this->userID = $_SESSION['phpgw_info']['workflow']['account_id'];
90                $this->isAdmin = $_SESSION['phpgw_info']['workflow']['user_is_admin'];
91                $this->acl =& $GLOBALS['ajax']->acl;
92                $this->db =& Factory::getInstance('WorkflowObjects')->getDBGalaxia()->Link_ID;
93        }
94
95        /**
96         * Carrega a lista de processos que o usuário tem acesso.
97         * @return array Lista de processos.
98         * @access public
99         */
100        function loadProcesses()
101        {
102                $this->_checkAccess();
103
104                $where = array();
105                if (!$this->isAdmin)
106                {
107                        $processIDs = $this->acl->get_granted_processes($this->userID);
108                        if (count($processIDs) > 0)
109                                $where[] = 'wf_p_id IN (' . implode(',', $processIDs) . ')';
110                        else
111                                $where[] = 'wf_p_id IS NULL';
112                }
113                $processManager = &Factory::getInstance('ProcessManager');
114
115                /* workaround to sort the result using two columns */
116                $items = $processManager->list_processes(0, -1, 'wf_name__ASC, wf_version ASC', '', implode(' AND ', $where));
117                $output = array();
118                foreach ($items['data'] as $item)
119                        $output[] = array(
120                                'wf_p_id' => $item['wf_p_id'],
121                                'wf_name' => $item['wf_name'],
122                                'wf_version' => $item['wf_version']);
123
124                return $output;
125        }
126
127        /**
128         * Carrega a lista de atividades de um processo (com exceção de atividades do tipo Standalone e View).
129         * @param int $processID O ID do processo do qual se quer a lista de atividades.
130         * @return array Lista de atividades de um processo.
131         * @access public
132         */
133        function loadProcessActivities($processID)
134        {
135                $this->_checkAccess($processID);
136
137                $activityManager = &Factory::newInstance('ActivityManager');
138                $activities = $activityManager->list_activities($processID, 0, -1, 'wf_name__ASC', '', 'wf_type <> \'standalone\' AND wf_type <> \'view\'');
139                $output = array();
140                foreach ($activities['data'] as $activity)
141                        $output[] = array(
142                                'wf_activity_id' => $activity['wf_activity_id'],
143                                'wf_name' => $activity['wf_name'],
144                                'wf_type' => $activity['wf_type']);
145                return $output;
146        }
147
148        /**
149         * Faz um pré-relacionamento das atividades dos dois processos.
150         * @param array $fromActivities Lista de atividades do processo de origem.
151         * @param array $toActivities Lista de atividades do processo de destino.
152         * @param float $threshold Limiar que define a menor porcentagem de semelhança entre o nome de duas atividades para que estas sejam relacionadas.
153         * @return array Lista de atividades relacionadas.
154         * @access public
155         */
156        function matchActivities($fromActivities, $toActivities, $threshold)
157        {
158                $preOutput = array();
159                foreach ($fromActivities as $fromActivity)
160                {
161                        $fromActivityName = $fromActivity['wf_name'];
162                        $fromActivityID = $fromActivity['wf_activity_id'];
163                        foreach ($toActivities as $toActivity)
164                        {
165                                $toActivityName = $toActivity['wf_name'];
166                                $toActivityID = $toActivity['wf_activity_id'];
167                                $currentValue = isset($preOutput[$fromActivityID]) ? $preOutput[$fromActivityID]['value'] : 0;
168
169                                similar_text($fromActivityName, $toActivityName, $matchValue);
170                                if (($matchValue > $threshold) && ($matchValue > $currentValue))
171                                        $preOutput[$fromActivityID] = array(
172                                                'activityID' => $toActivityID,
173                                                'value' => $matchValue);
174                        }
175                }
176                $output = array();
177                foreach ($preOutput as $fromActivityID => $toActivityInfo)
178                        $output[] = array(
179                                'from' => $fromActivityID,
180                                'to' => $toActivityInfo['activityID']);
181
182                return $output;
183        }
184
185        /**
186         * Move as instâncias de um processo para outro.
187         * @param int $from O ID do processo de origem.
188         * @param int $to O ID do processo de destino.
189         * @param bool $active Indica se devem ser movidas as instâncias ativas.
190         * @param bool $completed Indica se devem ser movidas as instâncias finalizadas.
191         * @param array $activityMappings O relacionamento entre as atividades dos dois processos.
192         * @return bool TRUE em caso de sucesso e FALSE caso contrário.
193         * @access public
194         */
195        function moveInstances($from, $to, $activityMappings, $active, $completed)
196        {
197                $this->_checkAccess($from);
198                $this->_checkAccess($to);
199
200                if (($active || $completed) == false)
201                        return array('error' => 'Nenhuma instância foi movida. Selecione pelo menos uma das checkboxes do status das instâncias.');
202
203                $instanceStatus = array();
204                $instanceActivityStatus = array();
205                if ($active)
206                {
207                        $instanceStatus[] = "'active'";
208                        $instanceStatus[] = "'exception'";
209                        $instanceActivityStatus[] = "'running'";
210                }
211
212                if ($completed)
213                {
214                        $instanceStatus[] = "'completed'";
215                        $instanceStatus[] = "'aborted'";
216                        $instanceActivityStatus[] = "'completed'";
217
218                }
219
220                /* create an array for quick conversion between the old and the new activities ID */
221                $activitiesConvert = array();
222                foreach ($activityMappings as $toActivityID => $fromActivities)
223                        foreach ($fromActivities as $fromActivityID)
224                                $activitiesConvert[$fromActivityID] = $toActivityID;
225
226                $this->db->StartTrans();
227                $transactionResult = true;
228
229                /* update the instances table */
230                $resultSet = $this->db->query("SELECT wf_instance_id, wf_next_activity, wf_next_user FROM egw_wf_instances WHERE (wf_status IN (" . implode(', ', $instanceStatus) . ")) AND (wf_p_id = ?)", array($from));
231                $rows = $resultSet->GetArray(-1);
232                $instanceList = array();
233                if (is_array($rows))
234                {
235                        foreach ($rows as $row)
236                        {
237                                /* save the ID of the instances for future use */
238                                $instanceList[] = $row['wf_instance_id'];
239
240                                /* get the data and unserialize them */
241                                $oldInstance = array(
242                                        'wf_instance_id' => $row['wf_instance_id'],
243                                        'wf_next_activity' => unserialize(base64_decode($row['wf_next_activity'])),
244                                        'wf_next_user' => unserialize(base64_decode($row['wf_next_user'])));
245
246                                /* change the next activity */
247                                $newInstance['wf_next_activity'] = array();
248                                if (is_array($oldInstance['wf_next_activity']))
249                                {
250                                        foreach ($oldInstance['wf_next_activity'] as $k => $v)
251                                                $newInstance['wf_next_activity'][$activitiesConvert[$k]] = $activitiesConvert[$v];
252                                }
253
254                                /* change the next user */
255                                $newInstance['wf_next_user'] = array();
256                                if (is_array($oldInstance['wf_next_user']))
257                                {
258                                        foreach ($oldInstance['wf_next_user'] as $k => $v)
259                                                if ($k[0] == '*')
260                                                        $newInstance['wf_next_user']['*' . $activitiesConvert[substr($k, 1)]] = $v;
261                                                else
262                                                        $newInstance['wf_next_user'][$activitiesConvert[$k]] = $v;
263                                }
264
265                                /* serialize and encode the data */
266                                $newInstance['wf_next_activity'] = base64_encode(serialize($newInstance['wf_next_activity']));
267                                $newInstance['wf_next_user'] = base64_encode(serialize($newInstance['wf_next_user']));
268
269                                /* update the egw_wf_instances table */
270                                if (!$this->db->query("UPDATE egw_wf_instances SET wf_next_activity = ?, wf_next_user = ?, wf_p_id = ? WHERE (wf_instance_id = ?)", array($newInstance['wf_next_activity'], $newInstance['wf_next_user'], $to, $oldInstance['wf_instance_id'])))
271                                {
272                                        $this->db->FailTrans();
273                                        return array('error' => 'Erro atualizando a tabela de instâncias. Nenhuma modificação foi salva');
274                                }
275                        }
276                }
277                /* assure at least one element */
278                $instanceList[] = -1;
279
280                /* update the instance_activities table */
281                $instanceActivityList = array();
282                $resultSet = $this->db->query("SELECT wf_instance_id, wf_activity_id FROM egw_wf_instance_activities WHERE (wf_status IN (" . implode(', ', $instanceActivityStatus) . ")) AND (wf_activity_id IN (" . implode(', ', array_keys($activitiesConvert)) . "))");
283                $rows = $resultSet->GetArray(-1);
284                if (is_array($rows))
285                {
286                        foreach ($rows as $row)
287                        {
288                                /* save the instance ID and activity ID pair for future use */
289                                $instanceActivityList[] = array(
290                                        'iid' => $row['wf_instance_id'],
291                                        'aid' => $row['wf_activity_id']);
292
293                                /* update the activity ID */
294                                if (!$this->db->query("UPDATE egw_wf_instance_activities SET wf_activity_id = ? WHERE (wf_instance_id = ?) AND (wf_activity_id = ?)", array($activitiesConvert[$row['wf_activity_id']], $row['wf_instance_id'], $row['wf_activity_id'])))
295                                {
296                                        $this->db->FailTrans();
297                                        return array('error' => 'Erro atualizando a tabela que relaciona instâncias e atividades. Nenhuma modificação foi salva');
298                                }
299                        }
300                }
301                /* assure at least one element */
302                $instanceActivityList[] = array('iid' => -1, 'aid' => -1);
303
304                /* update the workitems of the modified instances */
305                $resultSet = $this->db->query("SELECT wf_item_id, wf_activity_id FROM egw_wf_workitems WHERE (wf_instance_id IN (" . implode(', ', $instanceList) . "))");
306                $rows = $resultSet->GetArray(-1);
307                if (is_array($rows))
308                {
309                        foreach ($rows as $row)
310                        {
311                                /* update the activity ID */
312                                if (!$this->db->query("UPDATE egw_wf_workitems SET wf_activity_id = ? WHERE (wf_item_id = ?)", array($activitiesConvert[$row['wf_activity_id']], $row['wf_item_id'])))
313                                {
314                                        $this->db->FailTrans();
315                                        return array('error' => 'Erro atualizando a tabela de workitems. Nenhuma modificação foi salva');
316                                }
317                        }
318                }
319
320                /* format the array elements for use in a SELECT SQL statement, e.g. [iid => 12, aid = 27] would produce (12, 27) */
321                $instanceActivityList = array_map(create_function('$e', 'return \'(\' . $e[\'iid\'] . \', \' . $e[\'aid\'] . \')\';'), $instanceActivityList);
322
323                /* update the interinstance relations of the modified rows of the instance_activities table */
324                $resultSet = $this->db->query("SELECT wf_parent_instance_id, wf_parent_activity_id FROM egw_wf_interinstance_relations WHERE ((wf_parent_instance_id, wf_parent_activity_id) IN (" . implode(', ', $instanceActivityList) . "))");
325                $rows = $resultSet->GetArray(-1);
326                if (is_array($rows))
327                {
328                        foreach ($rows as $row)
329                        {
330                                /* update the activity ID */
331                                if (!$this->db->query("UPDATE egw_wf_interinstance_relations SET wf_parent_activity_id = ? WHERE (wf_parent_instance_id = ?) AND (wf_parent_activity_id = ?)", array($activitiesConvert[$row['wf_parent_activity_id']], $row['wf_parent_instance_id'], $row['wf_parent_activity_id'])))
332                                {
333                                        $this->db->FailTrans();
334                                        return array('error' => 'Erro atualizando a tabela de relacionamento inter-instância. Nenhuma modificação foi salva');
335                                }
336                        }
337                }
338
339                /* in case of success, commit the modifications */
340                $this->db->CompleteTrans();
341                return true;
342        }
343}
344?>
Note: See TracBrowser for help on using the repository browser.