xref: /plugin/struct/action/move.php (revision 5a1a3bb10c5ddfec65721ddafcfedbfd8f4cee00)
10173e75dSAndreas Gohr<?php
20173e75dSAndreas Gohr/**
30173e75dSAndreas Gohr * DokuWiki Plugin struct (Action Component)
40173e75dSAndreas Gohr *
50173e75dSAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
60173e75dSAndreas Gohr * @author  Andreas Gohr, Michael Große <dokuwiki@cosmocode.de>
70173e75dSAndreas Gohr */
80173e75dSAndreas Gohr
90173e75dSAndreas Gohr// must be run within Dokuwiki
10ba766201SAndreas Gohruse dokuwiki\plugin\struct\meta\Assignments;
11*5a1a3bb1SAndreas Gohruse dokuwiki\plugin\struct\meta\Column;
12ba766201SAndreas Gohruse dokuwiki\plugin\struct\meta\Schema;
13*5a1a3bb1SAndreas Gohruse dokuwiki\plugin\struct\types\Lookup;
14*5a1a3bb1SAndreas Gohruse dokuwiki\plugin\struct\types\Page;
150173e75dSAndreas Gohr
160173e75dSAndreas Gohrif(!defined('DOKU_INC')) die();
170173e75dSAndreas Gohr
180173e75dSAndreas Gohrclass action_plugin_struct_move extends DokuWiki_Action_Plugin {
190173e75dSAndreas Gohr
20*5a1a3bb1SAndreas Gohr    /** @var helper_plugin_sqlite */
21*5a1a3bb1SAndreas Gohr    protected $db = null;
22*5a1a3bb1SAndreas Gohr
230173e75dSAndreas Gohr    /**
240173e75dSAndreas Gohr     * Registers a callback function for a given event
250173e75dSAndreas Gohr     *
260173e75dSAndreas Gohr     * @param Doku_Event_Handler $controller DokuWiki's event controller object
270173e75dSAndreas Gohr     * @return void
280173e75dSAndreas Gohr     */
290173e75dSAndreas Gohr    public function register(Doku_Event_Handler $controller) {
300173e75dSAndreas Gohr        $controller->register_hook('PLUGIN_MOVE_PAGE_RENAME', 'AFTER', $this, 'handle_move');
310173e75dSAndreas Gohr    }
320173e75dSAndreas Gohr
330173e75dSAndreas Gohr    /**
340173e75dSAndreas Gohr     * Renames all occurances of a page ID in the database
350173e75dSAndreas Gohr     *
360173e75dSAndreas Gohr     * @param Doku_Event $event event object by reference
370173e75dSAndreas Gohr     * @param mixed $param [the parameters passed as fifth argument to register_hook() when this
380173e75dSAndreas Gohr     *                           handler was registered]
390173e75dSAndreas Gohr     * @return bool
400173e75dSAndreas Gohr     */
410173e75dSAndreas Gohr    public function handle_move(Doku_Event $event, $param) {
420173e75dSAndreas Gohr        /** @var helper_plugin_struct_db $hlp */
430173e75dSAndreas Gohr        $hlp = plugin_load('helper', 'struct_db');
44*5a1a3bb1SAndreas Gohr        $this->db = $hlp->getDB(false);
45*5a1a3bb1SAndreas Gohr        if(!$this->db) return false;
460173e75dSAndreas Gohr        $old = $event->data['src_id'];
470173e75dSAndreas Gohr        $new = $event->data['dst_id'];
480173e75dSAndreas Gohr
49*5a1a3bb1SAndreas Gohr        // general update of our meta tables
50*5a1a3bb1SAndreas Gohr        $this->updateDataTablePIDs($old, $new);
51*5a1a3bb1SAndreas Gohr        $this->updateAssignments($old, $new);
52*5a1a3bb1SAndreas Gohr        $this->updateTitles($old, $new);
5307e48105SAndreas Gohr
54*5a1a3bb1SAndreas Gohr        // apply updates to all columns in all schemas depending on type
55*5a1a3bb1SAndreas Gohr        $schemas = Schema::getAll();
56*5a1a3bb1SAndreas Gohr        foreach($schemas as $table) {
57*5a1a3bb1SAndreas Gohr            $schema = new Schema($table);
58*5a1a3bb1SAndreas Gohr            foreach($schema->getColumns() as $col) {
59*5a1a3bb1SAndreas Gohr                switch(get_class($col->getType())) {
60*5a1a3bb1SAndreas Gohr                    case Page::class:
61*5a1a3bb1SAndreas Gohr                        $this->updateColumnPage($schema, $col, $old, $new);
62*5a1a3bb1SAndreas Gohr                        break;
63*5a1a3bb1SAndreas Gohr                    case Lookup::class:
64*5a1a3bb1SAndreas Gohr                        $this->updateColumnLookup($schema, $col, $old, $new);
65*5a1a3bb1SAndreas Gohr                        break;
660173e75dSAndreas Gohr                }
67*5a1a3bb1SAndreas Gohr            }
68*5a1a3bb1SAndreas Gohr        }
690173e75dSAndreas Gohr
70*5a1a3bb1SAndreas Gohr        // FIXME we need to update Media Type fields on media move
71*5a1a3bb1SAndreas Gohr        // FIXME we should wrap all this in a transaction
7207e48105SAndreas Gohr
730173e75dSAndreas Gohr        return true;
740173e75dSAndreas Gohr    }
7507e48105SAndreas Gohr
7607e48105SAndreas Gohr    /**
77*5a1a3bb1SAndreas Gohr     * Update the pid column of ALL data tables
7807e48105SAndreas Gohr     *
79*5a1a3bb1SAndreas Gohr     * (we don't trust the assigments are still there)
80*5a1a3bb1SAndreas Gohr     *
81*5a1a3bb1SAndreas Gohr     * @param string $old old page id
82*5a1a3bb1SAndreas Gohr     * @param string $new new page id
8307e48105SAndreas Gohr     */
84*5a1a3bb1SAndreas Gohr    protected function updateDataTablePIDs($old, $new) {
85*5a1a3bb1SAndreas Gohr        foreach(Schema::getAll('page') as $tbl) {
86*5a1a3bb1SAndreas Gohr            /** @noinspection SqlResolve */
87*5a1a3bb1SAndreas Gohr            $sql = "UPDATE data_$tbl SET pid = ? WHERE pid = ?";
88*5a1a3bb1SAndreas Gohr            $this->db->query($sql, array($new, $old));
8907e48105SAndreas Gohr
90*5a1a3bb1SAndreas Gohr            /** @noinspection SqlResolve */
91*5a1a3bb1SAndreas Gohr            $sql = "UPDATE multi_$tbl SET pid = ? WHERE pid = ?";
92*5a1a3bb1SAndreas Gohr            $this->db->query($sql, array($new, $old));
93*5a1a3bb1SAndreas Gohr        }
94*5a1a3bb1SAndreas Gohr    }
9507e48105SAndreas Gohr
96*5a1a3bb1SAndreas Gohr    /**
97*5a1a3bb1SAndreas Gohr     * Update the page-schema assignments
98*5a1a3bb1SAndreas Gohr     *
99*5a1a3bb1SAndreas Gohr     * @param string $old old page id
100*5a1a3bb1SAndreas Gohr     * @param string $new new page id
101*5a1a3bb1SAndreas Gohr     */
102*5a1a3bb1SAndreas Gohr    protected function updateAssignments($old, $new) {
103*5a1a3bb1SAndreas Gohr        // assignments
104*5a1a3bb1SAndreas Gohr        $sql = "UPDATE schema_assignments SET pid = ? WHERE pid = ?";
105*5a1a3bb1SAndreas Gohr        $this->db->query($sql, array($new, $old));
106*5a1a3bb1SAndreas Gohr        // make sure assignments still match patterns;
107*5a1a3bb1SAndreas Gohr        $assignments = Assignments::getInstance();
108*5a1a3bb1SAndreas Gohr        $assignments->reevaluatePageAssignments($new);
109*5a1a3bb1SAndreas Gohr    }
110*5a1a3bb1SAndreas Gohr
111*5a1a3bb1SAndreas Gohr    /**
112*5a1a3bb1SAndreas Gohr     * Update the Title information for the moved page
113*5a1a3bb1SAndreas Gohr     *
114*5a1a3bb1SAndreas Gohr     * @param string $old old page id
115*5a1a3bb1SAndreas Gohr     * @param string $new new page id
116*5a1a3bb1SAndreas Gohr     */
117*5a1a3bb1SAndreas Gohr    protected function updateTitles($old, $new) {
118*5a1a3bb1SAndreas Gohr        $sql = "UPDATE titles SET pid = ? WHERE pid = ?";
119*5a1a3bb1SAndreas Gohr        $this->db->query($sql, array($new, $old));
120*5a1a3bb1SAndreas Gohr    }
121*5a1a3bb1SAndreas Gohr
122*5a1a3bb1SAndreas Gohr    /**
123*5a1a3bb1SAndreas Gohr     * Update a Page type column
124*5a1a3bb1SAndreas Gohr     *
125*5a1a3bb1SAndreas Gohr     * @param Schema $schema
126*5a1a3bb1SAndreas Gohr     * @param Column $col
127*5a1a3bb1SAndreas Gohr     * @param string $old old page id
128*5a1a3bb1SAndreas Gohr     * @param string $new new page id
129*5a1a3bb1SAndreas Gohr     */
130*5a1a3bb1SAndreas Gohr    protected function updateColumnPage(Schema $schema, Column $col, $old, $new) {
13107e48105SAndreas Gohr        $colref = $col->getColref();
132*5a1a3bb1SAndreas Gohr        $table = $schema->getTable();
133*5a1a3bb1SAndreas Gohr
13407e48105SAndreas Gohr        if($col->isMulti()) {
13507e48105SAndreas Gohr            /** @noinspection SqlResolve */
13607e48105SAndreas Gohr            $sql = "UPDATE multi_$table
13707e48105SAndreas Gohr                               SET value = REPLACE(value, ?, ?)
13807e48105SAndreas Gohr                             WHERE value LIKE ?
13907e48105SAndreas Gohr                               AND colref = $colref
14007e48105SAndreas Gohr                               AND latest = 1";
14107e48105SAndreas Gohr
14207e48105SAndreas Gohr        } else {
14307e48105SAndreas Gohr            /** @noinspection SqlResolve */
14407e48105SAndreas Gohr            $sql = "UPDATE data_$table
14507e48105SAndreas Gohr                               SET col$colref = REPLACE(col$colref, ?, ?)
14607e48105SAndreas Gohr                             WHERE col$colref LIKE ?
14707e48105SAndreas Gohr                               AND latest = 1";
14807e48105SAndreas Gohr        }
149*5a1a3bb1SAndreas Gohr        $this->db->query($sql, $old, $new, $old); // exact match
150*5a1a3bb1SAndreas Gohr        $this->db->query($sql, $old, $new, "$old#%"); // match with hashes
15107e48105SAndreas Gohr    }
152*5a1a3bb1SAndreas Gohr
153*5a1a3bb1SAndreas Gohr    /**
154*5a1a3bb1SAndreas Gohr     * Update a Lookup type column
155*5a1a3bb1SAndreas Gohr     *
156*5a1a3bb1SAndreas Gohr     * Lookups contain a page id when the referenced schema is a data schema
157*5a1a3bb1SAndreas Gohr     *
158*5a1a3bb1SAndreas Gohr     * @param Schema $schema
159*5a1a3bb1SAndreas Gohr     * @param Column $col
160*5a1a3bb1SAndreas Gohr     * @param string $old old page id
161*5a1a3bb1SAndreas Gohr     * @param string $new new page id
162*5a1a3bb1SAndreas Gohr     */
163*5a1a3bb1SAndreas Gohr    protected function updateColumnLookup(Schema $schema, Column $col, $old, $new) {
164*5a1a3bb1SAndreas Gohr        $tconf = $col->getType()->getConfig();
165*5a1a3bb1SAndreas Gohr        $ref = new Schema($tconf['schema']);
166*5a1a3bb1SAndreas Gohr        if(!$ref->getId()) return; // this schema does not exist
167*5a1a3bb1SAndreas Gohr        if($ref->isLookup()) return; // a lookup is referenced, nothing to do
168*5a1a3bb1SAndreas Gohr
169*5a1a3bb1SAndreas Gohr        // after the checks it's basically the same as a Page type column
170*5a1a3bb1SAndreas Gohr        $this->updateColumnPage($schema, $col, $old, $new);
17107e48105SAndreas Gohr    }
1720173e75dSAndreas Gohr}
173