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; 115a1a3bb1SAndreas Gohruse dokuwiki\plugin\struct\meta\Column; 12ba766201SAndreas Gohruse dokuwiki\plugin\struct\meta\Schema; 135a1a3bb1SAndreas Gohruse dokuwiki\plugin\struct\types\Lookup; 145a1a3bb1SAndreas 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 205a1a3bb1SAndreas Gohr /** @var helper_plugin_sqlite */ 215a1a3bb1SAndreas Gohr protected $db = null; 225a1a3bb1SAndreas 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'); 445a1a3bb1SAndreas Gohr $this->db = $hlp->getDB(false); 455a1a3bb1SAndreas Gohr if(!$this->db) return false; 460173e75dSAndreas Gohr $old = $event->data['src_id']; 470173e75dSAndreas Gohr $new = $event->data['dst_id']; 480173e75dSAndreas Gohr 49*2cbf8951SAndreas Gohr // prepare work 50*2cbf8951SAndreas Gohr $this->db->query('BEGIN TRANSACTION'); 51*2cbf8951SAndreas Gohr 525a1a3bb1SAndreas Gohr // general update of our meta tables 535a1a3bb1SAndreas Gohr $this->updateDataTablePIDs($old, $new); 545a1a3bb1SAndreas Gohr $this->updateAssignments($old, $new); 555a1a3bb1SAndreas Gohr $this->updateTitles($old, $new); 5607e48105SAndreas Gohr 575a1a3bb1SAndreas Gohr // apply updates to all columns in all schemas depending on type 585a1a3bb1SAndreas Gohr $schemas = Schema::getAll(); 595a1a3bb1SAndreas Gohr foreach($schemas as $table) { 605a1a3bb1SAndreas Gohr $schema = new Schema($table); 615a1a3bb1SAndreas Gohr foreach($schema->getColumns() as $col) { 625a1a3bb1SAndreas Gohr switch(get_class($col->getType())) { 635a1a3bb1SAndreas Gohr case Page::class: 645a1a3bb1SAndreas Gohr $this->updateColumnPage($schema, $col, $old, $new); 655a1a3bb1SAndreas Gohr break; 665a1a3bb1SAndreas Gohr case Lookup::class: 675a1a3bb1SAndreas Gohr $this->updateColumnLookup($schema, $col, $old, $new); 685a1a3bb1SAndreas Gohr break; 690173e75dSAndreas Gohr } 705a1a3bb1SAndreas Gohr } 715a1a3bb1SAndreas Gohr } 720173e75dSAndreas Gohr 735a1a3bb1SAndreas Gohr // FIXME we need to update Media Type fields on media move 74*2cbf8951SAndreas Gohr 75*2cbf8951SAndreas Gohr // execute everything 76*2cbf8951SAndreas Gohr $ok = $this->db->query('COMMIT TRANSACTION'); 77*2cbf8951SAndreas Gohr if(!$ok) { 78*2cbf8951SAndreas Gohr $this->db->query('ROLLBACK TRANSACTION'); 79*2cbf8951SAndreas Gohr return false; 80*2cbf8951SAndreas Gohr } 8107e48105SAndreas Gohr 820173e75dSAndreas Gohr return true; 830173e75dSAndreas Gohr } 8407e48105SAndreas Gohr 8507e48105SAndreas Gohr /** 865a1a3bb1SAndreas Gohr * Update the pid column of ALL data tables 8707e48105SAndreas Gohr * 885a1a3bb1SAndreas Gohr * (we don't trust the assigments are still there) 895a1a3bb1SAndreas Gohr * 905a1a3bb1SAndreas Gohr * @param string $old old page id 915a1a3bb1SAndreas Gohr * @param string $new new page id 9207e48105SAndreas Gohr */ 935a1a3bb1SAndreas Gohr protected function updateDataTablePIDs($old, $new) { 945a1a3bb1SAndreas Gohr foreach(Schema::getAll('page') as $tbl) { 955a1a3bb1SAndreas Gohr /** @noinspection SqlResolve */ 965a1a3bb1SAndreas Gohr $sql = "UPDATE data_$tbl SET pid = ? WHERE pid = ?"; 975a1a3bb1SAndreas Gohr $this->db->query($sql, array($new, $old)); 9807e48105SAndreas Gohr 995a1a3bb1SAndreas Gohr /** @noinspection SqlResolve */ 1005a1a3bb1SAndreas Gohr $sql = "UPDATE multi_$tbl SET pid = ? WHERE pid = ?"; 1015a1a3bb1SAndreas Gohr $this->db->query($sql, array($new, $old)); 1025a1a3bb1SAndreas Gohr } 1035a1a3bb1SAndreas Gohr } 10407e48105SAndreas Gohr 1055a1a3bb1SAndreas Gohr /** 1065a1a3bb1SAndreas Gohr * Update the page-schema assignments 1075a1a3bb1SAndreas Gohr * 1085a1a3bb1SAndreas Gohr * @param string $old old page id 1095a1a3bb1SAndreas Gohr * @param string $new new page id 1105a1a3bb1SAndreas Gohr */ 1115a1a3bb1SAndreas Gohr protected function updateAssignments($old, $new) { 1125a1a3bb1SAndreas Gohr // assignments 1135a1a3bb1SAndreas Gohr $sql = "UPDATE schema_assignments SET pid = ? WHERE pid = ?"; 1145a1a3bb1SAndreas Gohr $this->db->query($sql, array($new, $old)); 1155a1a3bb1SAndreas Gohr // make sure assignments still match patterns; 1165a1a3bb1SAndreas Gohr $assignments = Assignments::getInstance(); 1175a1a3bb1SAndreas Gohr $assignments->reevaluatePageAssignments($new); 1185a1a3bb1SAndreas Gohr } 1195a1a3bb1SAndreas Gohr 1205a1a3bb1SAndreas Gohr /** 1215a1a3bb1SAndreas Gohr * Update the Title information for the moved page 1225a1a3bb1SAndreas Gohr * 1235a1a3bb1SAndreas Gohr * @param string $old old page id 1245a1a3bb1SAndreas Gohr * @param string $new new page id 1255a1a3bb1SAndreas Gohr */ 1265a1a3bb1SAndreas Gohr protected function updateTitles($old, $new) { 1275a1a3bb1SAndreas Gohr $sql = "UPDATE titles SET pid = ? WHERE pid = ?"; 1285a1a3bb1SAndreas Gohr $this->db->query($sql, array($new, $old)); 1295a1a3bb1SAndreas Gohr } 1305a1a3bb1SAndreas Gohr 1315a1a3bb1SAndreas Gohr /** 1325a1a3bb1SAndreas Gohr * Update a Page type column 1335a1a3bb1SAndreas Gohr * 1345a1a3bb1SAndreas Gohr * @param Schema $schema 1355a1a3bb1SAndreas Gohr * @param Column $col 1365a1a3bb1SAndreas Gohr * @param string $old old page id 1375a1a3bb1SAndreas Gohr * @param string $new new page id 1385a1a3bb1SAndreas Gohr */ 1395a1a3bb1SAndreas Gohr protected function updateColumnPage(Schema $schema, Column $col, $old, $new) { 14007e48105SAndreas Gohr $colref = $col->getColref(); 1415a1a3bb1SAndreas Gohr $table = $schema->getTable(); 1425a1a3bb1SAndreas Gohr 14307e48105SAndreas Gohr if($col->isMulti()) { 14407e48105SAndreas Gohr /** @noinspection SqlResolve */ 14507e48105SAndreas Gohr $sql = "UPDATE multi_$table 14607e48105SAndreas Gohr SET value = REPLACE(value, ?, ?) 14707e48105SAndreas Gohr WHERE value LIKE ? 14807e48105SAndreas Gohr AND colref = $colref 14907e48105SAndreas Gohr AND latest = 1"; 15007e48105SAndreas Gohr 15107e48105SAndreas Gohr } else { 15207e48105SAndreas Gohr /** @noinspection SqlResolve */ 15307e48105SAndreas Gohr $sql = "UPDATE data_$table 15407e48105SAndreas Gohr SET col$colref = REPLACE(col$colref, ?, ?) 15507e48105SAndreas Gohr WHERE col$colref LIKE ? 15607e48105SAndreas Gohr AND latest = 1"; 15707e48105SAndreas Gohr } 1585a1a3bb1SAndreas Gohr $this->db->query($sql, $old, $new, $old); // exact match 1595a1a3bb1SAndreas Gohr $this->db->query($sql, $old, $new, "$old#%"); // match with hashes 16007e48105SAndreas Gohr } 1615a1a3bb1SAndreas Gohr 1625a1a3bb1SAndreas Gohr /** 1635a1a3bb1SAndreas Gohr * Update a Lookup type column 1645a1a3bb1SAndreas Gohr * 1655a1a3bb1SAndreas Gohr * Lookups contain a page id when the referenced schema is a data schema 1665a1a3bb1SAndreas Gohr * 1675a1a3bb1SAndreas Gohr * @param Schema $schema 1685a1a3bb1SAndreas Gohr * @param Column $col 1695a1a3bb1SAndreas Gohr * @param string $old old page id 1705a1a3bb1SAndreas Gohr * @param string $new new page id 1715a1a3bb1SAndreas Gohr */ 1725a1a3bb1SAndreas Gohr protected function updateColumnLookup(Schema $schema, Column $col, $old, $new) { 1735a1a3bb1SAndreas Gohr $tconf = $col->getType()->getConfig(); 1745a1a3bb1SAndreas Gohr $ref = new Schema($tconf['schema']); 1755a1a3bb1SAndreas Gohr if(!$ref->getId()) return; // this schema does not exist 1765a1a3bb1SAndreas Gohr if($ref->isLookup()) return; // a lookup is referenced, nothing to do 1775a1a3bb1SAndreas Gohr 1785a1a3bb1SAndreas Gohr // after the checks it's basically the same as a Page type column 1795a1a3bb1SAndreas Gohr $this->updateColumnPage($schema, $col, $old, $new); 18007e48105SAndreas Gohr } 1810173e75dSAndreas Gohr} 182