xref: /plugin/structpublish/action/migration.php (revision 2b546eccbf453fa6e7a7b042659a4ecc69ad11e9)
1<?php
2
3class action_plugin_structpublish_migration extends DokuWiki_Action_Plugin
4{
5    /**
6     * @inheritDoc
7     */
8    public function register(Doku_Event_Handler $controller)
9    {
10        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handleMigrations');
11    }
12
13    /**
14     * Call our custom migrations when defined
15     *
16     * @param Doku_Event $event
17     * @return bool
18     */
19    public function handleMigrations(Doku_Event $event)
20    {
21        /** @var \helper_plugin_struct_db $helper */
22        $helper = plugin_load('helper', 'struct_db');
23        $sqlite = $helper->getDB();
24
25        $ok = true;
26
27        // check whether we are already up-to-date
28        list($dbVersionStruct, $dbVersionStructpublish) = $this->getDbVersions($sqlite);
29        if (isset($dbVersionStructpublish) && (string)$dbVersionStructpublish == (string)$dbVersionStruct) {
30            return $ok;
31        }
32
33        // check whether we have any pending migrations for the current version of struct db
34        $pending = array_filter(array_map(function ($version) use ($dbVersionStruct) {
35            return $version >= $dbVersionStruct &&
36            is_callable([$this, "migration$version"]) ? $version : null;
37        }, $this->diffVersions($dbVersionStruct, $dbVersionStructpublish)));
38        if (empty($pending)) {
39            return $ok;
40        }
41
42        // execute the migrations
43        foreach ($pending as $version) {
44            $call = 'migration' . $version;
45            $ok = $ok && $this->$call($sqlite);
46        }
47
48        return $ok;
49    }
50
51    /**
52     * Detect which migrations should be executed. Start conservatively with version 1.
53     *
54     * @param int $dbVersionStruct Current version of struct DB as found in 'opts' table
55     * @param int|null $dbVersionStructpublish Current version in 'opts', may not exist yet
56     * @return int[]
57     */
58    protected function diffVersions($dbVersionStruct, $dbVersionStructpublish)
59    {
60        $pluginDbVersion = $dbVersionStructpublish ?: 1;
61        return range($pluginDbVersion, $dbVersionStruct);
62    }
63
64    /**
65     * @param $sqlite
66     * @return array
67     */
68    protected function getDbVersions($sqlite)
69    {
70        $dbVersionStruct = null;
71        $dbVersionStructpublish = null;
72
73        $sql = 'SELECT opt, val FROM opts WHERE opt=? OR opt=?';
74        $res = $sqlite->query($sql, 'dbversion', 'dbversion_structpublish');
75        $vals = $sqlite->res2arr($res);
76
77        foreach ($vals as $val) {
78            if ($val['opt'] === 'dbversion') {
79                $dbVersionStruct = $val['val'];
80            }
81            if ($val['opt'] === 'dbversion_structpublish') {
82                $dbVersionStructpublish = $val['val'];
83            }
84        }
85        return [$dbVersionStruct, $dbVersionStructpublish];
86    }
87
88    /**
89     * Database setup, required struct db version is 19
90     *
91     * @param helper_plugin_sqlite $sqlite
92     * @return bool
93     */
94    protected function migration19($sqlite)
95    {
96        $sql = io_readFile(DOKU_PLUGIN . 'structpublish/db/struct/update0019.sql', false);
97
98        $sql = $sqlite->SQLstring2array($sql);
99        array_unshift($sql, 'BEGIN TRANSACTION');
100        array_push($sql, "INSERT OR REPLACE INTO opts (val,opt) VALUES (19,'dbversion_structpublish')");
101        array_push($sql, "COMMIT TRANSACTION");
102        $ok =  $sqlite->doTransaction($sql);
103
104        if ($ok) {
105            $file = __DIR__ . "/../db/json/structpublish_19.struct.json";
106            $schemaJson = file_get_contents($file);
107            $importer = new \dokuwiki\plugin\struct\meta\SchemaImporter('structpublish', $schemaJson);
108            $ok = (bool)$importer->build();
109        }
110
111        return $ok;
112    }
113}
114