xref: /plugin/ireadit/action/migration.php (revision 5f08124fd36655a1e65e4e98a2403a814959c4e4)
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([$this, "migration$to"])) {
40            $event->result = call_user_func([$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 migration2($data)
63    {
64        global $conf;
65
66        /** @var helper_plugin_sqlite $sqlite */
67        $sqlite = $data['sqlite'];
68        $db = $sqlite->getAdapter()->getDb();
69
70        /* @var \helper_plugin_ireadit $helper */
71        $helper = plugin_load('helper', 'ireadit');
72
73
74        $datadir = $conf['datadir'];
75        if (substr($datadir, -1) != '/') {
76            $datadir .= '/';
77        }
78
79        $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($datadir));
80        $pages = [];
81        foreach ($rii as $file) {
82            if ($file->isDir()){
83                continue;
84            }
85
86            //remove start path and extension
87            $page = substr($file->getPathname(), strlen($datadir), -4);
88            $pages[] = str_replace('/', ':', $page);
89        }
90
91        $db->beginTransaction();
92
93        foreach ($pages as $page) {
94            //import historic data
95            $meta = p_get_metadata($page, 'plugin ireadit');
96            if (!$meta) continue;
97
98            $sqlite->storeEntry('meta', [
99                'page' => $page,
100                'meta' => json_encode($meta)
101            ]);
102        }
103        $db->commit();
104
105
106    }
107
108    protected function migration1($data)
109    {
110        global $conf;
111
112        /** @var helper_plugin_sqlite $sqlite */
113        $sqlite = $data['sqlite'];
114        $db = $sqlite->getAdapter()->getDb();
115
116        /* @var \helper_plugin_ireadit $helper */
117        $helper = plugin_load('helper', 'ireadit');
118
119
120        $datadir = $conf['datadir'];
121        if (substr($datadir, -1) != '/') {
122            $datadir .= '/';
123        }
124
125        $rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($datadir));
126        $pages = [];
127        foreach ($rii as $file) {
128            if ($file->isDir()){
129                continue;
130            }
131
132            //remove start path and extension
133            $page = substr($file->getPathname(), strlen($datadir), -4);
134            $pages[] = str_replace('/', ':', $page);
135        }
136        $db->beginTransaction();
137
138        foreach ($pages as $page) {
139            //import historic data
140            $meta = p_get_metadata($page, 'plugin_ireadit');
141            if (!$meta) continue;
142
143            foreach ($meta as $rev => $data) {
144                if ($rev === '' || count($data) == 0) continue;
145                foreach ($data as $user_read) {
146                    $sqlite->storeEntry('ireadit', [
147                        'page' => $page,
148                        'rev' => $rev,
149                        'user' => $user_read['client'],
150                        'timestamp' => date('c', $user_read['time'])
151                    ]);
152                }
153            }
154
155            //import current data
156            $content = file_get_contents($datadir . str_replace(':', '/', $page) . '.txt');
157            $status = preg_match('/~~IREADIT.*~~/', $content, $matches);
158            //no ireadit on page
159            if ($status !== 1) continue;
160
161            $match = trim(substr($matches[0], strlen('~~IREADIT'), -2));
162            $splits = preg_split('/\s+/', $match, -1, PREG_SPLIT_NO_EMPTY);
163
164            $users = [];
165            $groups = [];
166            foreach ($splits as $split) {
167                if ($split[0] == '@') {
168                    $group = substr($split, 1);
169                    $groups[] = $group;
170                } else {
171                    $users[] = $split;
172                }
173            }
174
175            $usersToInsert = $helper->users_set($users, $groups);
176
177            if ($usersToInsert) {
178                $last_change_date = p_get_metadata($page, 'last_change date');
179                foreach ($usersToInsert as $user => $info) {
180                    $this->insertOrIgnore($sqlite,'ireadit', [
181                        'page' => $page,
182                        'rev' => $last_change_date,
183                        'user' => $user
184                    ]);
185                }
186            }
187
188        }
189        $db->commit();
190
191        return true;
192    }
193}
194