1<?php 2 3namespace plugin\struct\meta; 4 5use dokuwiki\Form\Form; 6use plugin\struct\types\AbstractBaseType; 7use plugin\struct\types\Text; 8 9/** 10 * Class Schema 11 * 12 * Represents the schema of a single data table and all its properties. It defines what can be stored in 13 * the represented data table and how those contents are formatted. 14 * 15 * It can be initialized with a timestamp to access the schema as it looked at that particular point in time. 16 * 17 * @package plugin\struct\meta 18 */ 19class Schema { 20 21 /** @var \helper_plugin_sqlite|null */ 22 protected $sqlite; 23 24 /** @var int The ID of this schema */ 25 protected $id = 0; 26 27 /** @var string name of the associated table */ 28 protected $table = ''; 29 30 /** 31 * @var string the current checksum of this schema 32 */ 33 protected $chksum = ''; 34 35 /** @var Column[] all the colums */ 36 protected $columns = array(); 37 38 /** @var int */ 39 protected $maxsort = 0; 40 41 /** @var int */ 42 protected $ts = 0; 43 44 /** 45 * Schema constructor 46 * 47 * @param string $table The table this schema is for 48 * @param int $ts The timestamp for when this schema was valid, 0 for current 49 */ 50 public function __construct($table, $ts = 0) { 51 /** @var \helper_plugin_struct_db $helper */ 52 $helper = plugin_load('helper', 'struct_db'); 53 $this->sqlite = $helper->getDB(); 54 if(!$this->sqlite) return; 55 56 $table = self::cleanTableName($table); 57 $this->table = $table; 58 $this->ts = $ts; 59 60 // load info about the schema itself 61 if($ts) { 62 $sql = "SELECT * 63 FROM schemas 64 WHERE tbl = ? 65 AND ts <= ? 66 ORDER BY ts DESC 67 LIMIT 1"; 68 $opt = array($table, $ts); 69 70 } else { 71 $sql = "SELECT * 72 FROM schemas 73 WHERE tbl = ? 74 ORDER BY ts DESC 75 LIMIT 1"; 76 $opt = array($table); 77 } 78 $res = $this->sqlite->query($sql, $opt); 79 if($this->sqlite->res2count($res)) { 80 $schema = $this->sqlite->res2arr($res); 81 $result = array_shift($schema); 82 $this->id = $result['id']; 83 $this->chksum = $result['chksum']; 84 85 } 86 $this->sqlite->res_close($res); 87 if(!$this->id) return; 88 89 // load existing columns 90 $sql = "SELECT SC.*, T.* 91 FROM schema_cols SC, 92 types T 93 WHERE SC.sid = ? 94 AND SC.tid = T.id 95 ORDER BY SC.sort"; 96 $res = $this->sqlite->query($sql, $this->id); 97 $rows = $this->sqlite->res2arr($res); 98 $this->sqlite->res_close($res); 99 100 foreach($rows as $row) { 101 $class = 'plugin\\struct\\types\\' . $row['class']; 102 $config = json_decode($row['config'], true); 103 $this->columns[$row['colref']] = 104 new Column( 105 $row['sort'], 106 new $class($config, $row['label'], $row['ismulti'], $row['tid']), 107 $row['colref'], 108 $row['enabled'], 109 $table 110 ); 111 112 if($row['sort'] > $this->maxsort) $this->maxsort = $row['sort']; 113 } 114 } 115 116 /** 117 * Cleans any unwanted stuff from table names 118 * 119 * @param string $table 120 * @return string 121 */ 122 static public function cleanTableName($table) { 123 $table = strtolower($table); 124 $table = preg_replace('/[^a-z0-9_]+/', '', $table); 125 $table = preg_replace('/^[0-9_]+/', '', $table); 126 $table = trim($table); 127 return $table; 128 } 129 130 /** 131 * @return string 132 */ 133 public function getChksum() { 134 return $this->chksum; 135 } 136 137 /** 138 * @return int 139 */ 140 public function getId() { 141 return $this->id; 142 } 143 144 /** 145 * Returns a list of columns in this schema 146 * 147 * @param bool $withDisabled if false, disabled columns will not be returned 148 * @return Column[] 149 */ 150 public function getColumns($withDisabled = true) { 151 if(!$withDisabled) { 152 return array_filter( 153 $this->columns, 154 function (Column $col) { 155 return $col->isEnabled(); 156 } 157 ); 158 } 159 160 return $this->columns; 161 } 162 163 /** 164 * Find a column in the schema by its label 165 * 166 * Only enabled columns are returned! 167 * 168 * @param $name 169 * @return bool|Column 170 */ 171 public function findColumn($name) { 172 foreach($this->columns as $col) { 173 if($col->isEnabled() && utf8_strtolower($col->getLabel()) == utf8_strtolower($name)) { 174 return $col; 175 } 176 } 177 return false; 178 } 179 180 /** 181 * @return string 182 */ 183 public function getTable() { 184 return $this->table; 185 } 186 187 /** 188 * @return int the highest sort number used in this schema 189 */ 190 public function getMaxsort() { 191 return $this->maxsort; 192 } 193 194} 195