1<?php 2 3namespace dokuwiki\plugin\struct\meta; 4 5/** 6 * Class AccessTableGlobal 7 * 8 * Load and (more importantly) save data for Global Schemas 9 * 10 * @package dokuwiki\plugin\struct\meta 11 */ 12class AccessTableGlobal extends AccessTable 13{ 14 public function __construct($table, $pid, $ts = 0, $rid = 0) 15 { 16 parent::__construct($table, $pid, $ts, $rid); 17 } 18 19 /** 20 * Remove the current data 21 */ 22 public function clearData() 23 { 24 if (!$this->rid) return; // no data 25 26 /** @noinspection SqlResolve */ 27 $sql = 'DELETE FROM data_' . $this->schema->getTable() . ' WHERE rid = ?'; 28 $this->sqlite->query($sql, $this->rid); 29 $sql = 'DELETE FROM multi_' . $this->schema->getTable() . ' WHERE rid = ?'; 30 $this->sqlite->query($sql, $this->rid); 31 } 32 33 /** 34 * @inheritDoc 35 */ 36 protected function getLastRevisionTimestamp() 37 { 38 return 0; 39 } 40 41 /** 42 * @inheritDoc 43 */ 44 protected function buildGetDataSQL($idColumn = 'rid') 45 { 46 return parent::buildGetDataSQL($idColumn); 47 } 48 49 /** 50 * @inheritDoc 51 */ 52 protected function getSingleSql() 53 { 54 $cols = array_merge($this->getSingleNoninputCols(), $this->singleCols); 55 $cols = join(',', $cols); 56 $vals = array_merge($this->getSingleNoninputValues(), $this->singleValues); 57 $rid = $this->getRid() ?: "(SELECT (COALESCE(MAX(rid), 0 ) + 1) FROM $this->stable)"; 58 59 return "REPLACE INTO $this->stable (rid, $cols) 60 VALUES ($rid," . trim(str_repeat('?,', count($vals)), ',') . ');'; 61 } 62 63 /** 64 * @inheritDoc 65 */ 66 protected function getMultiSql() 67 { 68 return "REPLACE INTO $this->mtable (pid, rid, rev, latest, colref, row, value) VALUES (?,?,?,?,?,?,?)"; 69 } 70 71 /** 72 * @inheritDoc 73 */ 74 protected function validateTypeData($data) 75 { 76 // we do not store completely empty rows 77 $isempty = array_reduce($data, function ($isempty, $cell) { 78 return $isempty && ($cell === '' || $cell === [] || $cell === null); 79 }, true); 80 81 return !$isempty; 82 } 83 84 /** 85 * @inheritDoc 86 */ 87 protected function getSingleNoninputCols() 88 { 89 return ['pid', 'rev', 'latest']; 90 } 91 92 /** 93 * @inheritDoc 94 */ 95 protected function getSingleNoninputValues() 96 { 97 return [$this->pid, AccessTable::DEFAULT_REV, AccessTable::DEFAULT_LATEST]; 98 } 99 100 /** 101 * @inheritDoc 102 */ 103 protected function getMultiNoninputValues() 104 { 105 return [$this->pid, $this->rid, AccessTable::DEFAULT_REV, AccessTable::DEFAULT_LATEST]; 106 } 107 108 /** 109 * Set new rid if this is a new insert 110 * @return bool 111 */ 112 protected function afterSingleSave() 113 { 114 $ok = true; 115 if (!$this->rid) { 116 $this->rid = $this->sqlite->queryValue("SELECT rid FROM $this->stable WHERE ROWID = last_insert_rowid()"); 117 if (!$this->rid) { 118 $ok = false; 119 } 120 } 121 122 // FIXME this might replace handleEmptyMulti() but would it always be safe? in remote API context? 123 if (!empty($this->multiValues)) { 124 $ok = $ok && $this->clearMulti(); 125 } 126 127 return $ok; 128 } 129 130 /** 131 * Add an optional query to clear any previous multi values if the first one is empty. 132 * Allows for deleting multi values from the inline editor. 133 * 134 * @param string $pid 135 * @param int $rid 136 * @param int $colref 137 */ 138 protected function handleEmptyMulti($pid, $rid, $colref) 139 { 140 $table = 'multi_' . $this->schema->getTable(); 141 $this->optQueries[] = [ 142 "DELETE FROM $table WHERE pid = ? AND rid = ? AND colref = ?", 143 $pid, $rid, $colref 144 ]; 145 } 146} 147