1083afc55SAndreas Gohr<?php 2083afc55SAndreas Gohr 3083afc55SAndreas Gohrnamespace plugin\struct\meta; 4*bbf3d6aaSAndreas Gohruse plugin\struct\types\AbstractBaseType; 5083afc55SAndreas Gohr 67182938bSAndreas Gohr/** 77182938bSAndreas Gohr * Class Schema 87182938bSAndreas Gohr * 97182938bSAndreas Gohr * Represents the schema of a single data table and all its properties. It defines what can be stored in 107182938bSAndreas Gohr * the represented data table and how those contents are formatted. 117182938bSAndreas Gohr * 127182938bSAndreas Gohr * It can be initialized with a timestamp to access the schema as it looked at that particular point in time. 137182938bSAndreas Gohr * 147182938bSAndreas Gohr * @package plugin\struct\meta 157182938bSAndreas Gohr */ 16083afc55SAndreas Gohrclass Schema { 17083afc55SAndreas Gohr 18083afc55SAndreas Gohr /** @var \helper_plugin_sqlite|null */ 19083afc55SAndreas Gohr protected $sqlite; 20083afc55SAndreas Gohr 21083afc55SAndreas Gohr /** @var int The ID of this schema */ 22083afc55SAndreas Gohr protected $id = 0; 23083afc55SAndreas Gohr 24083afc55SAndreas Gohr /** @var string name of the associated table */ 25083afc55SAndreas Gohr protected $table = ''; 26083afc55SAndreas Gohr 27083afc55SAndreas Gohr /** 28083afc55SAndreas Gohr * @var string the current checksum of this schema 29083afc55SAndreas Gohr */ 30083afc55SAndreas Gohr protected $chksum = ''; 31083afc55SAndreas Gohr 321c502704SAndreas Gohr /** @var Column[] all the colums */ 33083afc55SAndreas Gohr protected $columns = array(); 34083afc55SAndreas Gohr 35083afc55SAndreas Gohr /** @var int */ 36083afc55SAndreas Gohr protected $maxsort = 0; 37083afc55SAndreas Gohr 38250c83c2SAndreas Gohr /** @var int */ 39250c83c2SAndreas Gohr protected $ts = 0; 40250c83c2SAndreas Gohr 41083afc55SAndreas Gohr /** 42083afc55SAndreas Gohr * Schema constructor 437182938bSAndreas Gohr * 44083afc55SAndreas Gohr * @param string $table The table this schema is for 45083afc55SAndreas Gohr * @param int $ts The timestamp for when this schema was valid, 0 for current 46083afc55SAndreas Gohr */ 47083afc55SAndreas Gohr public function __construct($table, $ts = 0) { 48083afc55SAndreas Gohr /** @var \helper_plugin_struct_db $helper */ 49083afc55SAndreas Gohr $helper = plugin_load('helper', 'struct_db'); 50083afc55SAndreas Gohr $this->sqlite = $helper->getDB(); 51083afc55SAndreas Gohr if(!$this->sqlite) return; 52083afc55SAndreas Gohr 53083afc55SAndreas Gohr $table = self::cleanTableName($table); 54083afc55SAndreas Gohr $this->table = $table; 55250c83c2SAndreas Gohr $this->ts = $ts; 56083afc55SAndreas Gohr 57083afc55SAndreas Gohr // load info about the schema itself 58083afc55SAndreas Gohr if($ts) { 59083afc55SAndreas Gohr $sql = "SELECT * 60083afc55SAndreas Gohr FROM schemas 61083afc55SAndreas Gohr WHERE tbl = ? 62083afc55SAndreas Gohr AND ts <= ? 63083afc55SAndreas Gohr ORDER BY ts DESC 64083afc55SAndreas Gohr LIMIT 1"; 65083afc55SAndreas Gohr $opt = array($table, $ts); 66083afc55SAndreas Gohr } else { 67083afc55SAndreas Gohr $sql = "SELECT * 68083afc55SAndreas Gohr FROM schemas 69083afc55SAndreas Gohr WHERE tbl = ? 70083afc55SAndreas Gohr ORDER BY ts DESC 71083afc55SAndreas Gohr LIMIT 1"; 72083afc55SAndreas Gohr $opt = array($table); 73083afc55SAndreas Gohr } 74083afc55SAndreas Gohr $res = $this->sqlite->query($sql, $opt); 75083afc55SAndreas Gohr if($this->sqlite->res2count($res)) { 764e2abec0SMichael Große $schema = $this->sqlite->res2arr($res); 774e2abec0SMichael Große $result = array_shift($schema); 78083afc55SAndreas Gohr $this->id = $result['id']; 79083afc55SAndreas Gohr $this->chksum = $result['chksum']; 80083afc55SAndreas Gohr 81083afc55SAndreas Gohr } 82083afc55SAndreas Gohr $this->sqlite->res_close($res); 83083afc55SAndreas Gohr if(!$this->id) return; 84083afc55SAndreas Gohr 85083afc55SAndreas Gohr // load existing columns 86083afc55SAndreas Gohr $sql = "SELECT SC.*, T.* 87083afc55SAndreas Gohr FROM schema_cols SC, 88083afc55SAndreas Gohr types T 891c502704SAndreas Gohr WHERE SC.sid = ? 901c502704SAndreas Gohr AND SC.tid = T.id 91083afc55SAndreas Gohr ORDER BY SC.sort"; 921c502704SAndreas Gohr $res = $this->sqlite->query($sql, $this->id); 93083afc55SAndreas Gohr $rows = $this->sqlite->res2arr($res); 94083afc55SAndreas Gohr $this->sqlite->res_close($res); 95083afc55SAndreas Gohr 96083afc55SAndreas Gohr foreach($rows as $row) { 971c502704SAndreas Gohr $class = 'plugin\\struct\\types\\' . $row['class']; 9898eaa57dSAndreas Gohr if(!class_exists($class)) { 9998eaa57dSAndreas Gohr // This usually never happens, except during development 10098eaa57dSAndreas Gohr msg('Unknown type "'.hsc($row['class']).'" falling back to Text', -1); 10198eaa57dSAndreas Gohr $class = 'plugin\\struct\\types\\Text'; 10298eaa57dSAndreas Gohr } 10398eaa57dSAndreas Gohr 104083afc55SAndreas Gohr $config = json_decode($row['config'], true); 105*bbf3d6aaSAndreas Gohr /** @var AbstractBaseType $type */ 106*bbf3d6aaSAndreas Gohr $type = new $class($config, $row['label'], $row['ismulti'], $row['tid']); 107*bbf3d6aaSAndreas Gohr $column = new Column( 1081c502704SAndreas Gohr $row['sort'], 109*bbf3d6aaSAndreas Gohr $type, 1101c502704SAndreas Gohr $row['colref'], 11163d51bbfSAndreas Gohr $row['enabled'], 11263d51bbfSAndreas Gohr $table 1131c502704SAndreas Gohr ); 114*bbf3d6aaSAndreas Gohr $type->setContext($column); 1151c502704SAndreas Gohr 116*bbf3d6aaSAndreas Gohr $this->columns[$row['colref']] = $column; 117083afc55SAndreas Gohr if($row['sort'] > $this->maxsort) $this->maxsort = $row['sort']; 118083afc55SAndreas Gohr } 119083afc55SAndreas Gohr } 120083afc55SAndreas Gohr 121083afc55SAndreas Gohr /** 122083afc55SAndreas Gohr * Cleans any unwanted stuff from table names 123083afc55SAndreas Gohr * 124083afc55SAndreas Gohr * @param string $table 125083afc55SAndreas Gohr * @return string 126083afc55SAndreas Gohr */ 127083afc55SAndreas Gohr static public function cleanTableName($table) { 1282af472dcSAndreas Gohr $table = strtolower($table); 129083afc55SAndreas Gohr $table = preg_replace('/[^a-z0-9_]+/', '', $table); 130083afc55SAndreas Gohr $table = preg_replace('/^[0-9_]+/', '', $table); 131083afc55SAndreas Gohr $table = trim($table); 132083afc55SAndreas Gohr return $table; 133083afc55SAndreas Gohr } 134083afc55SAndreas Gohr 135083afc55SAndreas Gohr /** 1361c502704SAndreas Gohr * @return string 1371c502704SAndreas Gohr */ 1381c502704SAndreas Gohr public function getChksum() { 1391c502704SAndreas Gohr return $this->chksum; 1401c502704SAndreas Gohr } 1411c502704SAndreas Gohr 1421c502704SAndreas Gohr /** 1431c502704SAndreas Gohr * @return int 1441c502704SAndreas Gohr */ 1451c502704SAndreas Gohr public function getId() { 1461c502704SAndreas Gohr return $this->id; 1471c502704SAndreas Gohr } 1481c502704SAndreas Gohr 1491c502704SAndreas Gohr /** 150ce206ec7SAndreas Gohr * Returns a list of columns in this schema 151ce206ec7SAndreas Gohr * 152ce206ec7SAndreas Gohr * @param bool $withDisabled if false, disabled columns will not be returned 153ce206ec7SAndreas Gohr * @return Column[] 1541c502704SAndreas Gohr */ 155ce206ec7SAndreas Gohr public function getColumns($withDisabled = true) { 156ce206ec7SAndreas Gohr if(!$withDisabled) { 157ce206ec7SAndreas Gohr return array_filter( 158ce206ec7SAndreas Gohr $this->columns, 159ce206ec7SAndreas Gohr function (Column $col) { 160ce206ec7SAndreas Gohr return $col->isEnabled(); 161ce206ec7SAndreas Gohr } 162ce206ec7SAndreas Gohr ); 163ce206ec7SAndreas Gohr } 164ce206ec7SAndreas Gohr 1651c502704SAndreas Gohr return $this->columns; 1661c502704SAndreas Gohr } 1671c502704SAndreas Gohr 168ae697e1fSAndreas Gohr /** 1695742aea9SAndreas Gohr * Find a column in the schema by its label 1705742aea9SAndreas Gohr * 1715742aea9SAndreas Gohr * Only enabled columns are returned! 1725742aea9SAndreas Gohr * 1735742aea9SAndreas Gohr * @param $name 1745742aea9SAndreas Gohr * @return bool|Column 1755742aea9SAndreas Gohr */ 1765742aea9SAndreas Gohr public function findColumn($name) { 1775742aea9SAndreas Gohr foreach($this->columns as $col) { 1785742aea9SAndreas Gohr if($col->isEnabled() && utf8_strtolower($col->getLabel()) == utf8_strtolower($name)) { 1795742aea9SAndreas Gohr return $col; 1805742aea9SAndreas Gohr } 1815742aea9SAndreas Gohr } 1825742aea9SAndreas Gohr return false; 1835742aea9SAndreas Gohr } 1845742aea9SAndreas Gohr 1855742aea9SAndreas Gohr /** 186ae697e1fSAndreas Gohr * @return string 187ae697e1fSAndreas Gohr */ 188ae697e1fSAndreas Gohr public function getTable() { 189ae697e1fSAndreas Gohr return $this->table; 190ae697e1fSAndreas Gohr } 1911c502704SAndreas Gohr 192ae697e1fSAndreas Gohr /** 193ae697e1fSAndreas Gohr * @return int the highest sort number used in this schema 194ae697e1fSAndreas Gohr */ 195ae697e1fSAndreas Gohr public function getMaxsort() { 196ae697e1fSAndreas Gohr return $this->maxsort; 197ae697e1fSAndreas Gohr } 1981c502704SAndreas Gohr 199083afc55SAndreas Gohr} 200