1083afc55SAndreas Gohr<?php 2083afc55SAndreas Gohr 3083afc55SAndreas Gohrnamespace plugin\struct\meta; 4083afc55SAndreas Gohr 57182938bSAndreas Gohr/** 67182938bSAndreas Gohr * Class Schema 77182938bSAndreas Gohr * 87182938bSAndreas Gohr * Represents the schema of a single data table and all its properties. It defines what can be stored in 97182938bSAndreas Gohr * the represented data table and how those contents are formatted. 107182938bSAndreas Gohr * 117182938bSAndreas Gohr * It can be initialized with a timestamp to access the schema as it looked at that particular point in time. 127182938bSAndreas Gohr * 137182938bSAndreas Gohr * @package plugin\struct\meta 147182938bSAndreas Gohr */ 15083afc55SAndreas Gohrclass Schema { 16083afc55SAndreas Gohr 17083afc55SAndreas Gohr /** @var \helper_plugin_sqlite|null */ 18083afc55SAndreas Gohr protected $sqlite; 19083afc55SAndreas Gohr 20083afc55SAndreas Gohr /** @var int The ID of this schema */ 21083afc55SAndreas Gohr protected $id = 0; 22083afc55SAndreas Gohr 23083afc55SAndreas Gohr /** @var string name of the associated table */ 24083afc55SAndreas Gohr protected $table = ''; 25083afc55SAndreas Gohr 26083afc55SAndreas Gohr /** 27083afc55SAndreas Gohr * @var string the current checksum of this schema 28083afc55SAndreas Gohr */ 29083afc55SAndreas Gohr protected $chksum = ''; 30083afc55SAndreas Gohr 311c502704SAndreas Gohr /** @var Column[] all the colums */ 32083afc55SAndreas Gohr protected $columns = array(); 33083afc55SAndreas Gohr 34083afc55SAndreas Gohr /** @var int */ 35083afc55SAndreas Gohr protected $maxsort = 0; 36083afc55SAndreas Gohr 37250c83c2SAndreas Gohr /** @var int */ 38250c83c2SAndreas Gohr protected $ts = 0; 39250c83c2SAndreas Gohr 40083afc55SAndreas Gohr /** 41083afc55SAndreas Gohr * Schema constructor 427182938bSAndreas Gohr * 43083afc55SAndreas Gohr * @param string $table The table this schema is for 44083afc55SAndreas Gohr * @param int $ts The timestamp for when this schema was valid, 0 for current 45083afc55SAndreas Gohr */ 46083afc55SAndreas Gohr public function __construct($table, $ts = 0) { 47083afc55SAndreas Gohr /** @var \helper_plugin_struct_db $helper */ 48083afc55SAndreas Gohr $helper = plugin_load('helper', 'struct_db'); 49083afc55SAndreas Gohr $this->sqlite = $helper->getDB(); 50083afc55SAndreas Gohr if(!$this->sqlite) return; 51083afc55SAndreas Gohr 52083afc55SAndreas Gohr $table = self::cleanTableName($table); 53083afc55SAndreas Gohr $this->table = $table; 54250c83c2SAndreas Gohr $this->ts = $ts; 55083afc55SAndreas Gohr 56083afc55SAndreas Gohr // load info about the schema itself 57083afc55SAndreas Gohr if($ts) { 58083afc55SAndreas Gohr $sql = "SELECT * 59083afc55SAndreas Gohr FROM schemas 60083afc55SAndreas Gohr WHERE tbl = ? 61083afc55SAndreas Gohr AND ts <= ? 62083afc55SAndreas Gohr ORDER BY ts DESC 63083afc55SAndreas Gohr LIMIT 1"; 64083afc55SAndreas Gohr $opt = array($table, $ts); 65083afc55SAndreas Gohr } else { 66083afc55SAndreas Gohr $sql = "SELECT * 67083afc55SAndreas Gohr FROM schemas 68083afc55SAndreas Gohr WHERE tbl = ? 69083afc55SAndreas Gohr ORDER BY ts DESC 70083afc55SAndreas Gohr LIMIT 1"; 71083afc55SAndreas Gohr $opt = array($table); 72083afc55SAndreas Gohr } 73083afc55SAndreas Gohr $res = $this->sqlite->query($sql, $opt); 74083afc55SAndreas Gohr if($this->sqlite->res2count($res)) { 754e2abec0SMichael Große $schema = $this->sqlite->res2arr($res); 764e2abec0SMichael Große $result = array_shift($schema); 77083afc55SAndreas Gohr $this->id = $result['id']; 78083afc55SAndreas Gohr $this->chksum = $result['chksum']; 79083afc55SAndreas Gohr 80083afc55SAndreas Gohr } 81083afc55SAndreas Gohr $this->sqlite->res_close($res); 82083afc55SAndreas Gohr if(!$this->id) return; 83083afc55SAndreas Gohr 84083afc55SAndreas Gohr // load existing columns 85083afc55SAndreas Gohr $sql = "SELECT SC.*, T.* 86083afc55SAndreas Gohr FROM schema_cols SC, 87083afc55SAndreas Gohr types T 881c502704SAndreas Gohr WHERE SC.sid = ? 891c502704SAndreas Gohr AND SC.tid = T.id 90083afc55SAndreas Gohr ORDER BY SC.sort"; 911c502704SAndreas Gohr $res = $this->sqlite->query($sql, $this->id); 92083afc55SAndreas Gohr $rows = $this->sqlite->res2arr($res); 93083afc55SAndreas Gohr $this->sqlite->res_close($res); 94083afc55SAndreas Gohr 95083afc55SAndreas Gohr foreach($rows as $row) { 961c502704SAndreas Gohr $class = 'plugin\\struct\\types\\' . $row['class']; 97*98eaa57dSAndreas Gohr if(!class_exists($class)) { 98*98eaa57dSAndreas Gohr // This usually never happens, except during development 99*98eaa57dSAndreas Gohr msg('Unknown type "'.hsc($row['class']).'" falling back to Text', -1); 100*98eaa57dSAndreas Gohr $class = 'plugin\\struct\\types\\Text'; 101*98eaa57dSAndreas Gohr } 102*98eaa57dSAndreas Gohr 103083afc55SAndreas Gohr $config = json_decode($row['config'], true); 1041c502704SAndreas Gohr $this->columns[$row['colref']] = 1051c502704SAndreas Gohr new Column( 1061c502704SAndreas Gohr $row['sort'], 10704eb61a6SAndreas Gohr new $class($config, $row['label'], $row['ismulti'], $row['tid']), 1081c502704SAndreas Gohr $row['colref'], 10963d51bbfSAndreas Gohr $row['enabled'], 11063d51bbfSAndreas Gohr $table 1111c502704SAndreas Gohr ); 1121c502704SAndreas Gohr 113083afc55SAndreas Gohr if($row['sort'] > $this->maxsort) $this->maxsort = $row['sort']; 114083afc55SAndreas Gohr } 115083afc55SAndreas Gohr } 116083afc55SAndreas Gohr 117083afc55SAndreas Gohr /** 118083afc55SAndreas Gohr * Cleans any unwanted stuff from table names 119083afc55SAndreas Gohr * 120083afc55SAndreas Gohr * @param string $table 121083afc55SAndreas Gohr * @return string 122083afc55SAndreas Gohr */ 123083afc55SAndreas Gohr static public function cleanTableName($table) { 1242af472dcSAndreas Gohr $table = strtolower($table); 125083afc55SAndreas Gohr $table = preg_replace('/[^a-z0-9_]+/', '', $table); 126083afc55SAndreas Gohr $table = preg_replace('/^[0-9_]+/', '', $table); 127083afc55SAndreas Gohr $table = trim($table); 128083afc55SAndreas Gohr return $table; 129083afc55SAndreas Gohr } 130083afc55SAndreas Gohr 131083afc55SAndreas Gohr /** 1321c502704SAndreas Gohr * @return string 1331c502704SAndreas Gohr */ 1341c502704SAndreas Gohr public function getChksum() { 1351c502704SAndreas Gohr return $this->chksum; 1361c502704SAndreas Gohr } 1371c502704SAndreas Gohr 1381c502704SAndreas Gohr /** 1391c502704SAndreas Gohr * @return int 1401c502704SAndreas Gohr */ 1411c502704SAndreas Gohr public function getId() { 1421c502704SAndreas Gohr return $this->id; 1431c502704SAndreas Gohr } 1441c502704SAndreas Gohr 1451c502704SAndreas Gohr /** 146ce206ec7SAndreas Gohr * Returns a list of columns in this schema 147ce206ec7SAndreas Gohr * 148ce206ec7SAndreas Gohr * @param bool $withDisabled if false, disabled columns will not be returned 149ce206ec7SAndreas Gohr * @return Column[] 1501c502704SAndreas Gohr */ 151ce206ec7SAndreas Gohr public function getColumns($withDisabled = true) { 152ce206ec7SAndreas Gohr if(!$withDisabled) { 153ce206ec7SAndreas Gohr return array_filter( 154ce206ec7SAndreas Gohr $this->columns, 155ce206ec7SAndreas Gohr function (Column $col) { 156ce206ec7SAndreas Gohr return $col->isEnabled(); 157ce206ec7SAndreas Gohr } 158ce206ec7SAndreas Gohr ); 159ce206ec7SAndreas Gohr } 160ce206ec7SAndreas Gohr 1611c502704SAndreas Gohr return $this->columns; 1621c502704SAndreas Gohr } 1631c502704SAndreas Gohr 164ae697e1fSAndreas Gohr /** 1655742aea9SAndreas Gohr * Find a column in the schema by its label 1665742aea9SAndreas Gohr * 1675742aea9SAndreas Gohr * Only enabled columns are returned! 1685742aea9SAndreas Gohr * 1695742aea9SAndreas Gohr * @param $name 1705742aea9SAndreas Gohr * @return bool|Column 1715742aea9SAndreas Gohr */ 1725742aea9SAndreas Gohr public function findColumn($name) { 1735742aea9SAndreas Gohr foreach($this->columns as $col) { 1745742aea9SAndreas Gohr if($col->isEnabled() && utf8_strtolower($col->getLabel()) == utf8_strtolower($name)) { 1755742aea9SAndreas Gohr return $col; 1765742aea9SAndreas Gohr } 1775742aea9SAndreas Gohr } 1785742aea9SAndreas Gohr return false; 1795742aea9SAndreas Gohr } 1805742aea9SAndreas Gohr 1815742aea9SAndreas Gohr /** 182ae697e1fSAndreas Gohr * @return string 183ae697e1fSAndreas Gohr */ 184ae697e1fSAndreas Gohr public function getTable() { 185ae697e1fSAndreas Gohr return $this->table; 186ae697e1fSAndreas Gohr } 1871c502704SAndreas Gohr 188ae697e1fSAndreas Gohr /** 189ae697e1fSAndreas Gohr * @return int the highest sort number used in this schema 190ae697e1fSAndreas Gohr */ 191ae697e1fSAndreas Gohr public function getMaxsort() { 192ae697e1fSAndreas Gohr return $this->maxsort; 193ae697e1fSAndreas Gohr } 1941c502704SAndreas Gohr 195083afc55SAndreas Gohr} 196