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