xref: /plugin/ireadit/action/migration.php (revision 85300102eeb4c8e415de0f1ac21287aaee10e4bc)
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_ireadit_migration extends DokuWiki_Action_Plugin
17{
18    /**
19     * @inheritDoc
20     */
21    public function register(Doku_Event_Handler $controller)
22    {
23        $controller->register_hook('PLUGIN_SQLITE_DATABASE_UPGRADE', 'AFTER', $this, 'handle_migrations');
24    }
25
26    /**
27     * Call our custom migrations when defined
28     *
29     * @param Doku_Event $event
30     * @param $param
31     */
32    public function handle_migrations(Doku_Event $event, $param)
33    {
34        if ($event->data['sqlite']->getAdapter()->getDbname() !== 'ireadit') {
35            return;
36        }
37        $to = $event->data['to'];
38
39        if (is_callable(array($this, "migration$to"))) {
40            $event->result = call_user_func(array($this, "migration$to"), $event->data);
41        }
42    }
43
44    /**
45     * Convenience function to run an INSERT ... ON CONFLICT IGNORE operation
46     *
47     * The function takes a key-value array with the column names in the key and the actual value in the value,
48     * build the appropriate query and executes it.
49     *
50     * @param string $table the table the entry should be saved to (will not be escaped)
51     * @param array $entry A simple key-value pair array (only values will be escaped)
52     * @return bool|SQLiteResult
53     */
54    protected function insertOrIgnore(helper_plugin_sqlite $sqlite, $table, $entry) {
55        $keys = join(',', array_keys($entry));
56        $vals = join(',', array_fill(0,count($entry),'?'));
57
58        $sql = "INSERT OR IGNORE INTO $table ($keys) VALUES ($vals)";
59        return $sqlite->query($sql, array_values($entry));
60    }
61
62    protected function migration1($data)
63    {
64        global $conf;
65        /** @var $auth DokuWiki_Auth_Plugin */
66        global $auth;
67
68        /** @var helper_plugin_sqlite $sqlite */
69        $sqlite = $data['sqlite'];
70        $db = $sqlite->getAdapter()->getDb();
71
72
73        $datadir = $conf['datadir'];
74        if (substr($datadir, -1) != '/') {
75            $datadir .= '/';
76        }
77
78        $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($datadir));
79        $pages = array();
80        foreach ($rii as $file) {
81            if ($file->isDir()){
82                continue;
83            }
84
85            //remove start path and extension
86            $page = substr($file->getPathname(), strlen($datadir), -4);
87            $pages[] = str_replace('/', ':', $page);
88        }
89        $db->beginTransaction();
90
91        foreach ($pages as $page) {
92            //import historic data
93            $meta = p_get_metadata($page, 'plugin_ireadit');
94            if (!$meta) continue;
95            $date = p_get_metadata($page, 'date modified');
96
97            if (isset($meta[$date])) {
98                $meta[0] = $meta[$date];
99                unset($meta[$date]);
100            }
101
102            $current = null;
103            foreach ($meta as $rev => $data) {
104                if ($rev === '' || count($data) == 0) continue;
105                $sqlite->storeEntry('ireadit', array(
106                    'page' => $page,
107                    'rev' => $rev
108                ));
109                $id = $db->lastInsertId();
110                if ($rev === 0) {
111                    $current = $id;
112                }
113                foreach ($data as $user_read) {
114                    $sqlite->storeEntry('ireadit_user', array(
115                        'ireadit_id' => $id,
116                        'user' => $user_read['client'],
117                        'timestamp' => date('c', $user_read['time'])
118                    ));
119                }
120            }
121
122            //import current data
123            $content = file_get_contents($datadir . str_replace(':', '/', $page) . '.txt');
124            $status = preg_match('/~~IREADIT.*~~/', $content, $matches);
125            //no ireadit on page
126            if ($status !== 1) continue;
127
128            $match = trim(substr($matches[0], strlen('~~IREADIT'), -2));
129            $splits = preg_split('/\s+/', $match, -1, PREG_SPLIT_NO_EMPTY);
130
131            $users = array();
132            $groups = array();
133            foreach ($splits as $split) {
134                if ($split[0] == '@') {
135                    $group = substr($match, 1);
136                    $groups[] = $group;
137                } else {
138                    $users[] = $split;
139                }
140            }
141
142            $usersToInsert = array();
143            if (empty($users) && empty($groups)) {
144                $usersToInsert = $auth->retrieveUsers();
145            } else {
146                $all_users = $auth->retrieveUsers();
147                foreach ($all_users as $user => $info) {
148                    if (in_array($user, $users)) {
149                        $usersToInsert[$user] = $info;
150                    } elseif (array_intersect($groups, $info['grps'])) {
151                        $usersToInsert[$user] = $info;
152                    }
153                }
154            }
155
156            if ($usersToInsert) {
157                if ($current === NULL) {
158                    $sqlite->storeEntry('ireadit', array(
159                        'page' => $page,
160                        'rev' => 0
161                    ));
162                    $current = $db->lastInsertId();
163                }
164                foreach ($usersToInsert as $user => $info) {
165                    $this->insertOrIgnore($sqlite,'ireadit_user', array(
166                        'ireadit_id' => $current,
167                        'user' => $user
168                    ));
169                }
170            }
171
172        }
173        $db->commit();
174
175        return true;
176    }
177}
178