xref: /plugin/bez/action/migration.php (revision 9fa666385d9e587824d1393ce3c427a2eaa60a79)
1<?php
2/**
3 * DokuWiki Plugin bez (Action Component)
4 *
5 */
6
7// must be run within Dokuwiki
8
9if(!defined('DOKU_INC')) die();
10
11/**
12 * Class action_plugin_bez_migration
13 *
14 * Handle migrations that need more than just SQL
15 */
16class action_plugin_bez_migration extends DokuWiki_Action_Plugin {
17    /**
18     * @inheritDoc
19     */
20    public function register(Doku_Event_Handler $controller) {
21        $controller->register_hook('PLUGIN_SQLITE_DATABASE_UPGRADE', 'BEFORE', $this, 'handle_migrations');
22    }
23
24    /**
25     * Call our custom migrations when defined
26     *
27     * @param Doku_Event $event
28     * @param $param
29     */
30    public function handle_migrations(Doku_Event $event, $param) {
31        if ($event->data['sqlite']->getAdapter()->getDbname() !== 'b3p') {
32            return;
33        }
34        $to = $event->data['to'];
35
36        if(is_callable(array($this, "migration$to"))) {
37            $event->preventDefault();
38            $event->result = call_user_func(array($this, "migration$to"), $event->data);
39        }
40    }
41
42    /**
43     * Executes Migration 1
44     *
45     * Add a latest column to all existing multi tables
46     *
47     * @param helper_plugin_sqlite $sqlite
48     * @return bool
49     */
50    protected function migration1($data) {
51        global $INFO;
52
53        $file = $data['file'];
54        /** @var helper_plugin_sqlite $sqlite */
55        $sqlite = $data['sqlite'];
56
57        $sql = file_get_contents($file);
58        if ($sql === false) {
59            throw new Exception('cannot open file '.$file);
60        }
61
62        $matches = array();
63        preg_match_all('/.*?(?(?=BEGIN)BEGIN.*?END)\s*;/is', $sql, $matches);
64        $queries = $matches[0];
65
66        $db = $sqlite->getAdapter()->getDb();
67
68        $db->beginTransaction();
69        foreach ($queries as $query) {
70            $res = $db->query($query);
71            if($res === false) {
72                $err = $db->errorInfo();
73                msg($err[0].' '.$err[1].' '.$err[2].':<br /><pre>'.hsc($query).'</pre>', -1);
74                $db->rollBack();
75                return false;
76            }
77        }
78
79        $bez_file = DOKU_INC . 'data/meta/bez.sqlite3';
80        if (!file_exists($bez_file)) {
81            $db->commit();
82            return true;
83        }
84
85        //import from bez
86        $bez = new \PDO('sqlite:' . $bez_file);
87
88        $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
89
90        $stmt = $bez->query('SELECT * FROM issuetypes');
91        while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
92            $sqlite->storeEntry('label', array('id' => $row['id'],
93                                                            'name' => $row['pl'],
94                                                            'added_by' => $INFO['client'],
95                                                            'added_date' => date('c')));
96        }
97
98        $stmt = $bez->query('SELECT * FROM tasktypes');
99        while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
100            $sqlite->storeEntry('task_program', array('id' => $row['id'],
101                                                             'name' => $row['pl'],
102                                                             'added_by' => $INFO['client'],
103                                                             'added_date' => date('c')));
104        }
105
106        $stmt = $bez->query('SELECT *, (SELECT COUNT(*) FROM tasks
107								WHERE tasks.cause = commcauses.id) AS task_count FROM commcauses');
108        while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
109            if ($row['type'] == '0') {
110                $type = 'comment';
111            } elseif ($row['type'] == '1') {
112                $type = 'cause_real';
113            } elseif ($row['type'] == '2') {
114                $type = 'cause_potential';
115            }
116            $sqlite->storeEntry('thread_comment',
117                                       array('id' => $row['id'],
118                                             'thread_id' => $row['issue'],
119                                             'type' => $type,
120                                             'author' => $row['reporter'],
121                                             'create_date' => date('c', strtotime($row['datetime'])),
122                                             'last_modification_date' => date('c', strtotime($row['datetime'])),
123                                             'content' => $row['content'],
124                                             'content_html' => $row['content_cache'],
125                                             'task_count' => $row['task_count']));
126        }
127
128        $stmt = $bez->query('SELECT tasks.*, commcauses.type AS cause_type
129                                          FROM tasks
130                                          LEFT JOIN commcauses ON tasks.cause = commcauses.id');
131        //thread_id => array('user_id' => 'user_id')
132        $task_assignee = array();
133        while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
134            if ($row['close_date'] != '') {
135                $last_mod = date('c', (int) $row['close_date']);
136            } else {
137                $last_mod = date('c', (int) $row['date']);
138            }
139
140            $data =  array('id' => $row['id'],
141                           'original_poster' => $row['reporter'],
142                           'assignee' => $row['executor'],
143                           'create_date' => date('c', (int) $row['date']),
144                           'last_activity_date' => $last_mod,
145                           'last_modification_date' => $last_mod,
146                           'plan_date' => $row['plan_date'],
147                           'all_day_event' => $row['all_day_event'],
148                           'start_time' => $row['start_time'],
149                           'finish_time' => $row['finish_time'],
150                           'content' => $row['task'],
151                           'content_html' => $row['task_cache'],
152                           'thread_id' => $row['issue'],
153                           'thread_comment_id' => $row['cause'],
154                           'task_program_id' => $row['tasktype']
155            );
156
157            if ($data['thread_id'] != '') {
158                if (!is_array($task_assignee[$data['thread_id']])) {
159                    $task_assignee[$data['thread_id']] = array();
160                }
161                $task_assignee[$data['thread_id']][$row['executor']] = $row['executor'];
162            }
163
164            if ($row['cost'] != '0') {
165                $data['cost'] = $row['cost'];
166            }
167
168            if ($row['issue'] == '') {
169                $data['type'] = 'program';
170            } elseif ($row['cause'] == '') {
171                $data['type'] = 'correction';
172            } elseif ($row['cause_type'] == '1') {
173                $data['type'] = 'corrective';
174            } else {
175                $data['type'] = 'preventive';
176            }
177
178            if ($row['state'] == '0') {
179                $data['state'] = 'opened';
180            } elseif ($row['state'] == '1' || $row['state'] == '2') {
181                $data['state'] = 'done';
182                $data['closed_by'] = $row['executor'];
183                $data['close_date'] = date('c', (int) $row['close_date']);
184
185                if ($row['reason'] != '') {
186                    $sqlite->storeEntry('task_comment',
187                                               array('task_id' => $row['id'],
188                                                     'author' => $row['executor'],
189                                                     'create_date' => $data['close_date'],
190                                                     'last_modification_date' => $data['close_date'],
191                                                     'content' => $row['reason'],
192                                                     'content_html' => $row['reason_cache']));
193                }
194            }
195
196            //user_id => array()
197            $participants = array();
198            $subscribents = explode(',', $row['subscribents']);
199            foreach ($subscribents as $user_id) {
200                $participants[$user_id] = array('user_id' => $user_id, 'subscribent' => '1');
201            }
202
203            $op = $data['original_poster'];
204            if (!isset($participants[$op])) {
205                $participants[$op] = array('user_id' => $op, 'original_poster' => '1');
206            } else {
207                $participants[$op]['original_poster'] = '1';
208            }
209
210            $as = $data['assignee'];
211            if (!isset($participants[$as])) {
212                $participants[$as] = array('user_id' => $as, 'assignee' => '1');
213            } else {
214                $participants[$as]['assignee'] = '1';
215            }
216
217            foreach($participants as $part) {
218                $part['task_id'] = $row['id'];
219                $part['added_by'] = $INFO['client'];
220                $part['added_date'] = date('c');
221
222                $res = $sqlite->storeEntry('task_participant', $part);
223                if ($res === false) {
224                    throw new Exception($db->errorInfo());
225                }
226            }
227
228            $sqlite->storeEntry('task', $data);
229        }
230
231
232
233        $stmt = $bez->query('SELECT *,
234                                (SELECT COUNT(*) FROM tasks
235								WHERE tasks.issue = issues.id) AS task_count,
236								(SELECT COUNT(*) FROM tasks
237								WHERE tasks.issue = issues.id AND tasks.state != 0) AS task_closed_count,
238								(SELECT SUM(cost) FROM tasks
239								WHERE tasks.issue = issues.id) AS task_sum_cost
240								FROM issues');
241
242        while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
243
244            $data =  array('id' => $row['id'],
245                           'original_poster' => $row['reporter'],
246                           'coordinator' => $row['coordinator'],
247                           'create_date' => date('c', (int) $row['date']),
248                           'last_activity_date' => date('c', strtotime($row['last_activity'])),
249                           'last_modification_date' => date('c', (int) $row['last_mod']),
250                           'title' => $row['title'],
251                           'content' => $row['description'],
252                           'content_html' => $row['description_cache'],
253                           'task_count' => $row['task_count'],
254                           'task_count_closed' => $row['task_closed_count']
255            );
256
257            if ($row['task_sum_cost'] != '0') {
258                $data['task_sum_cost'] = $row['task_sum_cost'];
259            }
260
261            if ($row['coordinator'] == '') {
262                $data['state'] = 'proposal';
263            } elseif ($row['state'] == '1') {
264                $data['closed_by'] = $row['coordinator'];
265                $data['state'] = 'closed';
266                $data['close_date'] = $data['last_modification_date'];
267
268                $sqlite->storeEntry('thread_comment',
269                                           array('thread_id' => $row['id'],
270                                                 'type' => 'comment',
271                                                 'author' => $row['coordinator'],
272                                                 'create_date' => $data['close_date'],
273                                                 'last_modification_date' => $data['close_date'],
274                                                 'content' => $row['opinion'],
275                                                 'content_html' => $row['opinion_cache']));
276
277
278            } elseif ($row['state'] == '2') {
279                $data['closed_by'] = $row['coordinator'];
280                $data['state'] = 'rejected';
281                $data['close_date'] = $data['last_modification_date'];
282
283                if ($row['opinion'] != '') {
284                    $res = $sqlite->storeEntry('thread_comment',
285                                               array('thread_id' => $row['id'],
286                                                     'type' => 'comment',
287                                                     'author' => $row['coordinator'],
288                                                     'create_date' => $data['close_date'],
289                                                     'last_modification_date' => $data['close_date'],
290                                                     'content' => $row['opinion'],
291                                                     'content_html' => $row['opinion_cache']));
292                    if ($res === false) {
293                        throw new Exception($db->errorInfo());
294                    }
295                }
296
297            } elseif ($row['task_count'] != '0' && $row['task_count'] == $row['task_closed_count']) {
298                $data['state'] = 'done';
299            } else {
300                $data['state'] = 'opened';
301            }
302
303            $sqlite->storeEntry('thread', $data);
304
305            $sqlite->storeEntry('thread_label',
306                                       array('thread_id' => $row['id'],
307                                             'label_id' => $row['type']));
308
309            //participants
310            //user_id => array()
311            $participants = array();
312            $org_participants = array_filter(explode(',', $row['participants']));
313            foreach ($org_participants as $user_id) {
314                $participants[$user_id] = array('user_id' => $user_id);
315            }
316
317            $subscribents = array_filter(explode(',', $row['subscribents']));
318            foreach ($subscribents as $user_id) {
319                if (!isset($participants[$user_id])) {
320                    $participants[$user_id] = array('user_id' => $user_id);
321                }
322                $participants[$user_id]['subscribent'] = '1';
323            }
324
325            $stmt_i = $bez->query('SELECT reporter FROM commcauses WHERE issue=' . $row['id']);
326            while ($commcause = $stmt_i->fetch(\PDO::FETCH_ASSOC)) {
327                $user_id = $commcause['reporter'];
328                if (!isset($participants[$user_id])) {
329                    $participants[$user_id] = array('user_id' => $user_id);
330                }
331                $participants[$user_id]['commentator'] = '1';
332            }
333
334            if (is_array($task_assignee[$row['id']])) foreach ($task_assignee[$row['id']] as $user_id) {
335                if (!isset($participants[$user_id])) {
336                    $participants[$user_id] = array('user_id' => $user_id);
337                }
338                $participants[$user_id]['task_assignee'] = '1';
339            }
340
341            $op = $data['original_poster'];
342            if (!isset($participants[$op])) {
343                $participants[$op] = array('user_id' => $op, 'original_poster' => '1');
344            } else {
345                $participants[$op]['original_poster'] = '1';
346            }
347
348            $cor = $data['coordinator'];
349            if (!isset($participants[$cor])) {
350                $participants[$cor] = array('user_id' => $cor, 'coordinator' => '1');
351            } else {
352                $participants[$cor]['coordinator'] = '1';
353            }
354
355            foreach($participants as $part) {
356                $part['thread_id'] = $row['id'];
357                $part['added_by'] = $INFO['client'];
358                $part['added_date'] = date('c');
359
360                $sqlite->storeEntry('thread_participant', $part);
361            }
362
363        }
364
365        $db->commit();
366
367        return true;
368    }
369
370}
371