1*083afc55SAndreas Gohr<?php 2*083afc55SAndreas Gohr 3*083afc55SAndreas Gohrnamespace plugin\struct\meta; 4*083afc55SAndreas Gohr 5*083afc55SAndreas Gohruse plugin\struct\types\AbstractBaseType; 6*083afc55SAndreas Gohruse plugin\struct\types\Text; 7*083afc55SAndreas Gohr 8*083afc55SAndreas Gohrclass Schema { 9*083afc55SAndreas Gohr 10*083afc55SAndreas Gohr /** @var \helper_plugin_sqlite|null */ 11*083afc55SAndreas Gohr protected $sqlite; 12*083afc55SAndreas Gohr 13*083afc55SAndreas Gohr /** @var int The ID of this schema */ 14*083afc55SAndreas Gohr protected $id = 0; 15*083afc55SAndreas Gohr 16*083afc55SAndreas Gohr /** @var string name of the associated table */ 17*083afc55SAndreas Gohr protected $table = ''; 18*083afc55SAndreas Gohr 19*083afc55SAndreas Gohr /** 20*083afc55SAndreas Gohr * @var string the current checksum of this schema 21*083afc55SAndreas Gohr */ 22*083afc55SAndreas Gohr protected $chksum = ''; 23*083afc55SAndreas Gohr 24*083afc55SAndreas Gohr /** @var AbstractBaseType[] all the colums */ 25*083afc55SAndreas Gohr protected $columns = array(); 26*083afc55SAndreas Gohr 27*083afc55SAndreas Gohr /** @var int */ 28*083afc55SAndreas Gohr protected $maxsort = 0; 29*083afc55SAndreas Gohr 30*083afc55SAndreas Gohr /** 31*083afc55SAndreas Gohr * Schema constructor 32*083afc55SAndreas Gohr * @param string $table The table this schema is for 33*083afc55SAndreas Gohr * @param int $ts The timestamp for when this schema was valid, 0 for current 34*083afc55SAndreas Gohr */ 35*083afc55SAndreas Gohr public function __construct($table, $ts = 0) { 36*083afc55SAndreas Gohr /** @var \helper_plugin_struct_db $helper */ 37*083afc55SAndreas Gohr $helper = plugin_load('helper', 'struct_db'); 38*083afc55SAndreas Gohr $this->sqlite = $helper->getDB(); 39*083afc55SAndreas Gohr if(!$this->sqlite) return; 40*083afc55SAndreas Gohr 41*083afc55SAndreas Gohr $table = self::cleanTableName($table); 42*083afc55SAndreas Gohr $this->table = $table; 43*083afc55SAndreas Gohr 44*083afc55SAndreas Gohr // load info about the schema itself 45*083afc55SAndreas Gohr if($ts) { 46*083afc55SAndreas Gohr $sql = "SELECT * 47*083afc55SAndreas Gohr FROM schemas 48*083afc55SAndreas Gohr WHERE tbl = ? 49*083afc55SAndreas Gohr AND ts <= ? 50*083afc55SAndreas Gohr ORDER BY ts DESC 51*083afc55SAndreas Gohr LIMIT 1"; 52*083afc55SAndreas Gohr $opt = array($table, $ts); 53*083afc55SAndreas Gohr 54*083afc55SAndreas Gohr } else { 55*083afc55SAndreas Gohr $sql = "SELECT * 56*083afc55SAndreas Gohr FROM schemas 57*083afc55SAndreas Gohr WHERE tbl = ? 58*083afc55SAndreas Gohr ORDER BY ts DESC 59*083afc55SAndreas Gohr LIMIT 1"; 60*083afc55SAndreas Gohr $opt = array($table); 61*083afc55SAndreas Gohr } 62*083afc55SAndreas Gohr $res = $this->sqlite->query($sql, $opt); 63*083afc55SAndreas Gohr if($this->sqlite->res2count($res)) { 64*083afc55SAndreas Gohr $result = $this->sqlite->res2arr($res); 65*083afc55SAndreas Gohr $this->id = $result['id']; 66*083afc55SAndreas Gohr $this->chksum = $result['chksum']; 67*083afc55SAndreas Gohr 68*083afc55SAndreas Gohr } 69*083afc55SAndreas Gohr $this->sqlite->res_close($res); 70*083afc55SAndreas Gohr if(!$this->id) return; 71*083afc55SAndreas Gohr 72*083afc55SAndreas Gohr // load existing columns 73*083afc55SAndreas Gohr $sql = "SELECT SC.*, T.* 74*083afc55SAndreas Gohr FROM schema_cols SC, 75*083afc55SAndreas Gohr types T 76*083afc55SAndreas Gohr WHERE SC.schema_id = ? 77*083afc55SAndreas Gohr AND SC.type_id = T.id 78*083afc55SAndreas Gohr ORDER BY SC.sort"; 79*083afc55SAndreas Gohr $res = $this->sqlite->query($sql, $opt); 80*083afc55SAndreas Gohr $rows = $this->sqlite->res2arr($res); 81*083afc55SAndreas Gohr $this->sqlite->res_close($res); 82*083afc55SAndreas Gohr 83*083afc55SAndreas Gohr foreach($rows as $row) { 84*083afc55SAndreas Gohr $class = 'plugin\\struct\\type\\' . $row['class']; 85*083afc55SAndreas Gohr $config = json_decode($row['config'], true); 86*083afc55SAndreas Gohr $this->columns[$row['col']] = new $class($config, $row['label'], $row['ismulti']); 87*083afc55SAndreas Gohr if($row['sort'] > $this->maxsort) $this->maxsort = $row['sort']; 88*083afc55SAndreas Gohr } 89*083afc55SAndreas Gohr } 90*083afc55SAndreas Gohr 91*083afc55SAndreas Gohr /** 92*083afc55SAndreas Gohr * Cleans any unwanted stuff from table names 93*083afc55SAndreas Gohr * 94*083afc55SAndreas Gohr * @param string $table 95*083afc55SAndreas Gohr * @return string 96*083afc55SAndreas Gohr */ 97*083afc55SAndreas Gohr static public function cleanTableName($table) { 98*083afc55SAndreas Gohr $table = preg_replace('/[^a-z0-9_]+/', '', $table); 99*083afc55SAndreas Gohr $table = preg_replace('/^[0-9_]+/', '', $table); 100*083afc55SAndreas Gohr $table = trim($table); 101*083afc55SAndreas Gohr return $table; 102*083afc55SAndreas Gohr } 103*083afc55SAndreas Gohr 104*083afc55SAndreas Gohr /** 105*083afc55SAndreas Gohr * Returns a table to edit the schema 106*083afc55SAndreas Gohr * 107*083afc55SAndreas Gohr * @todo should this include the form? 108*083afc55SAndreas Gohr * 109*083afc55SAndreas Gohr * @return string 110*083afc55SAndreas Gohr */ 111*083afc55SAndreas Gohr public function adminEditor() { 112*083afc55SAndreas Gohr $html = ''; 113*083afc55SAndreas Gohr 114*083afc55SAndreas Gohr $html .= '<input type="hidden" name="table" value="' . hsc($this->table) . '">'; 115*083afc55SAndreas Gohr 116*083afc55SAndreas Gohr $html .= '<table class="inline">'; 117*083afc55SAndreas Gohr $html .= '<tr><th>Sort</th><th>Label</th><th>Multi-Input?</th><th>Configuration</th><th>Type</th></tr>'; // FIXME localize 118*083afc55SAndreas Gohr foreach($this->columns as $key => $obj) { 119*083afc55SAndreas Gohr $html .= $this->adminColumn($key, $obj); 120*083afc55SAndreas Gohr } 121*083afc55SAndreas Gohr 122*083afc55SAndreas Gohr // FIXME new one needs to be added dynamically, this is just for testing 123*083afc55SAndreas Gohr $html .= $this->adminColumn('new1', new Text($this->maxsort+10)); 124*083afc55SAndreas Gohr 125*083afc55SAndreas Gohr $html .= '</table>'; 126*083afc55SAndreas Gohr return $html; 127*083afc55SAndreas Gohr } 128*083afc55SAndreas Gohr 129*083afc55SAndreas Gohr /** 130*083afc55SAndreas Gohr * Returns the HTML to edit a single column definition of the schema 131*083afc55SAndreas Gohr * 132*083afc55SAndreas Gohr * @param string $column_id 133*083afc55SAndreas Gohr * @param AbstractBaseType $type 134*083afc55SAndreas Gohr * @return string 135*083afc55SAndreas Gohr * @todo this should probably be reused for adding new columns via AJAX later? 136*083afc55SAndreas Gohr */ 137*083afc55SAndreas Gohr protected function adminColumn($column_id, AbstractBaseType $type) { 138*083afc55SAndreas Gohr $base = 'schema[' . $column_id . ']'; // base name for all fields 139*083afc55SAndreas Gohr 140*083afc55SAndreas Gohr $html = '<tr>'; 141*083afc55SAndreas Gohr 142*083afc55SAndreas Gohr $html .= '<td>'; 143*083afc55SAndreas Gohr $html .= '<input type="text" name="' . $base . '[sort]" value="' . hsc($type->getSort()) . '" size="3">'; 144*083afc55SAndreas Gohr $html .= '</td>'; 145*083afc55SAndreas Gohr 146*083afc55SAndreas Gohr $html .= '<td>'; 147*083afc55SAndreas Gohr $html .= '<input type="text" name="' . $base . '[label]" value="' . hsc($type->getLabel()) . '">'; 148*083afc55SAndreas Gohr $html .= '</td>'; 149*083afc55SAndreas Gohr 150*083afc55SAndreas Gohr $html .= '<td>'; 151*083afc55SAndreas Gohr $checked = $type->isMulti() ? 'checked="checked"' : ''; 152*083afc55SAndreas Gohr $html .= '<input type="checkbox" name="' . $base . '[ismulti]" value="1" ' . $checked . '>'; 153*083afc55SAndreas Gohr $html .= '</td>'; 154*083afc55SAndreas Gohr 155*083afc55SAndreas Gohr $html .= '<td>'; 156*083afc55SAndreas Gohr $config = json_encode($type->getConfig(), JSON_PRETTY_PRINT); 157*083afc55SAndreas Gohr $html .= '<textarea name="' . $base . '[config]" cols="45" rows="10">' . hsc($config) . '</textarea>'; 158*083afc55SAndreas Gohr $html .= '</td>'; 159*083afc55SAndreas Gohr 160*083afc55SAndreas Gohr $html .= '<td>'; 161*083afc55SAndreas Gohr $html .= substr(get_class($type), 20); //FIXME this needs to be a dropdown 162*083afc55SAndreas Gohr $html .= '</td>'; 163*083afc55SAndreas Gohr 164*083afc55SAndreas Gohr $html .= '</tr>'; 165*083afc55SAndreas Gohr 166*083afc55SAndreas Gohr return $html; 167*083afc55SAndreas Gohr } 168*083afc55SAndreas Gohr 169*083afc55SAndreas Gohr} 170