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