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( 79 $data, 80 static fn($isempty, $cell) => $isempty && ($cell === '' || $cell === [] || $cell === null), 81 true 82 ); 83 84 return !$isempty; 85 } 86 87 /** 88 * @inheritDoc 89 */ 90 protected function getSingleNoninputCols() 91 { 92 return ['pid', 'rev', 'latest']; 93 } 94 95 /** 96 * @inheritDoc 97 */ 98 protected function getSingleNoninputValues() 99 { 100 return [$this->pid, AccessTable::DEFAULT_REV, AccessTable::DEFAULT_LATEST]; 101 } 102 103 /** 104 * @inheritDoc 105 */ 106 protected function getMultiNoninputValues() 107 { 108 return [$this->pid, $this->rid, AccessTable::DEFAULT_REV, AccessTable::DEFAULT_LATEST]; 109 } 110 111 /** 112 * Set new rid if this is a new insert 113 * @return bool 114 */ 115 protected function afterSingleSave() 116 { 117 $ok = true; 118 if (!$this->rid) { 119 $this->rid = $this->sqlite->queryValue("SELECT rid FROM $this->stable WHERE ROWID = last_insert_rowid()"); 120 if (!$this->rid) { 121 $ok = false; 122 } 123 } 124 125 // FIXME this might replace handleEmptyMulti() but would it always be safe? in remote API context? 126 if (!empty($this->multiValues)) { 127 $ok = $ok && $this->clearMulti(); 128 } 129 130 return $ok; 131 } 132 133 /** 134 * Add an optional query to clear any previous multi values if the first one is empty. 135 * Allows for deleting multi values from the inline editor. 136 * 137 * @param string $pid 138 * @param int $rid 139 * @param int $colref 140 */ 141 protected function handleEmptyMulti($pid, $rid, $colref) 142 { 143 $table = 'multi_' . $this->schema->getTable(); 144 $this->optQueries[] = [ 145 "DELETE FROM $table WHERE pid = ? AND rid = ? AND colref = ?", 146 $pid, $rid, $colref 147 ]; 148 } 149} 150