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 = implode(',', $cols); 56 57 $vals = array_merge($this->getSingleNoninputValues(), $this->singleValues); 58 $rid = $this->getRid() ?: "(SELECT (COALESCE(MAX(rid), 0 ) + 1) FROM $this->stable)"; 59 60 return "REPLACE INTO $this->stable (rid, $cols) 61 VALUES ($rid," . trim(str_repeat('?,', count($vals)), ',') . ');'; 62 } 63 64 /** 65 * @inheritDoc 66 */ 67 protected function getMultiSql() 68 { 69 return "REPLACE INTO $this->mtable (pid, rid, rev, latest, colref, row, value) VALUES (?,?,?,?,?,?,?)"; 70 } 71 72 /** 73 * @inheritDoc 74 */ 75 protected function validateTypeData($data) 76 { 77 // we do not store completely empty rows 78 $isempty = array_reduce($data, static fn($isempty, $cell) => $isempty && ($cell === '' || $cell === [] || $cell === null), true); 79 80 return !$isempty; 81 } 82 83 /** 84 * @inheritDoc 85 */ 86 protected function getSingleNoninputCols() 87 { 88 return ['pid', 'rev', 'latest']; 89 } 90 91 /** 92 * @inheritDoc 93 */ 94 protected function getSingleNoninputValues() 95 { 96 return [$this->pid, AccessTable::DEFAULT_REV, AccessTable::DEFAULT_LATEST]; 97 } 98 99 /** 100 * @inheritDoc 101 */ 102 protected function getMultiNoninputValues() 103 { 104 return [$this->pid, $this->rid, AccessTable::DEFAULT_REV, AccessTable::DEFAULT_LATEST]; 105 } 106 107 /** 108 * Set new rid if this is a new insert 109 * @return bool 110 */ 111 protected function afterSingleSave() 112 { 113 $ok = true; 114 if (!$this->rid) { 115 $this->rid = $this->sqlite->queryValue("SELECT rid FROM $this->stable WHERE ROWID = last_insert_rowid()"); 116 if (!$this->rid) { 117 $ok = false; 118 } 119 } 120 121 // FIXME this might replace handleEmptyMulti() but would it always be safe? in remote API context? 122 if (!empty($this->multiValues)) { 123 $ok = $ok && $this->clearMulti(); 124 } 125 126 return $ok; 127 } 128 129 /** 130 * Add an optional query to clear any previous multi values if the first one is empty. 131 * Allows for deleting multi values from the inline editor. 132 * 133 * @param string $pid 134 * @param int $rid 135 * @param int $colref 136 */ 137 protected function handleEmptyMulti($pid, $rid, $colref) 138 { 139 $table = 'multi_' . $this->schema->getTable(); 140 $this->optQueries[] = [ 141 "DELETE FROM $table WHERE pid = ? AND rid = ? AND colref = ?", 142 $pid, $rid, $colref 143 ]; 144 } 145} 146