xref: /plugin/struct/meta/Schema.php (revision 1c502704592431c9b605eb91ad8b3f133892d618)
1083afc55SAndreas Gohr<?php
2083afc55SAndreas Gohr
3083afc55SAndreas Gohrnamespace plugin\struct\meta;
4083afc55SAndreas Gohr
5*1c502704SAndreas Gohruse dokuwiki\Form\Form;
6083afc55SAndreas Gohruse plugin\struct\types\AbstractBaseType;
7083afc55SAndreas Gohruse plugin\struct\types\Text;
8083afc55SAndreas Gohr
9083afc55SAndreas Gohrclass Schema {
10083afc55SAndreas Gohr
11083afc55SAndreas Gohr    /** @var \helper_plugin_sqlite|null */
12083afc55SAndreas Gohr    protected $sqlite;
13083afc55SAndreas Gohr
14083afc55SAndreas Gohr    /** @var int The ID of this schema */
15083afc55SAndreas Gohr    protected $id = 0;
16083afc55SAndreas Gohr
17083afc55SAndreas Gohr    /** @var string name of the associated table */
18083afc55SAndreas Gohr    protected $table = '';
19083afc55SAndreas Gohr
20083afc55SAndreas Gohr    /**
21083afc55SAndreas Gohr     * @var string the current checksum of this schema
22083afc55SAndreas Gohr     */
23083afc55SAndreas Gohr    protected $chksum = '';
24083afc55SAndreas Gohr
25*1c502704SAndreas Gohr    /** @var Column[] all the colums */
26083afc55SAndreas Gohr    protected $columns = array();
27083afc55SAndreas Gohr
28083afc55SAndreas Gohr    /** @var int */
29083afc55SAndreas Gohr    protected $maxsort = 0;
30083afc55SAndreas Gohr
31083afc55SAndreas Gohr    /**
32083afc55SAndreas Gohr     * Schema constructor
33083afc55SAndreas Gohr     * @param string $table The table this schema is for
34083afc55SAndreas Gohr     * @param int $ts The timestamp for when this schema was valid, 0 for current
35083afc55SAndreas Gohr     */
36083afc55SAndreas Gohr    public function __construct($table, $ts = 0) {
37083afc55SAndreas Gohr        /** @var \helper_plugin_struct_db $helper */
38083afc55SAndreas Gohr        $helper = plugin_load('helper', 'struct_db');
39083afc55SAndreas Gohr        $this->sqlite = $helper->getDB();
40083afc55SAndreas Gohr        if(!$this->sqlite) return;
41083afc55SAndreas Gohr
42083afc55SAndreas Gohr        $table = self::cleanTableName($table);
43083afc55SAndreas Gohr        $this->table = $table;
44083afc55SAndreas Gohr
45083afc55SAndreas Gohr        // load info about the schema itself
46083afc55SAndreas Gohr        if($ts) {
47083afc55SAndreas Gohr            $sql = "SELECT *
48083afc55SAndreas Gohr                      FROM schemas
49083afc55SAndreas Gohr                     WHERE tbl = ?
50083afc55SAndreas Gohr                       AND ts <= ?
51083afc55SAndreas Gohr                  ORDER BY ts DESC
52083afc55SAndreas Gohr                     LIMIT 1";
53083afc55SAndreas Gohr            $opt = array($table, $ts);
54083afc55SAndreas Gohr
55083afc55SAndreas Gohr        } else {
56083afc55SAndreas Gohr            $sql = "SELECT *
57083afc55SAndreas Gohr                      FROM schemas
58083afc55SAndreas Gohr                     WHERE tbl = ?
59083afc55SAndreas Gohr                  ORDER BY ts DESC
60083afc55SAndreas Gohr                     LIMIT 1";
61083afc55SAndreas Gohr            $opt = array($table);
62083afc55SAndreas Gohr        }
63083afc55SAndreas Gohr        $res = $this->sqlite->query($sql, $opt);
64083afc55SAndreas Gohr        if($this->sqlite->res2count($res)) {
65*1c502704SAndreas Gohr            $result = array_shift($this->sqlite->res2arr($res));
66083afc55SAndreas Gohr            $this->id = $result['id'];
67083afc55SAndreas Gohr            $this->chksum = $result['chksum'];
68083afc55SAndreas Gohr
69083afc55SAndreas Gohr        }
70083afc55SAndreas Gohr        $this->sqlite->res_close($res);
71083afc55SAndreas Gohr        if(!$this->id) return;
72083afc55SAndreas Gohr
73083afc55SAndreas Gohr        // load existing columns
74083afc55SAndreas Gohr        $sql = "SELECT SC.*, T.*
75083afc55SAndreas Gohr                  FROM schema_cols SC,
76083afc55SAndreas Gohr                       types T
77*1c502704SAndreas Gohr                 WHERE SC.sid = ?
78*1c502704SAndreas Gohr                   AND SC.tid = T.id
79083afc55SAndreas Gohr              ORDER BY SC.sort";
80*1c502704SAndreas Gohr        $res = $this->sqlite->query($sql, $this->id);
81083afc55SAndreas Gohr        $rows = $this->sqlite->res2arr($res);
82083afc55SAndreas Gohr        $this->sqlite->res_close($res);
83083afc55SAndreas Gohr
84083afc55SAndreas Gohr        foreach($rows as $row) {
85*1c502704SAndreas Gohr            $class = 'plugin\\struct\\types\\' . $row['class'];
86083afc55SAndreas Gohr            $config = json_decode($row['config'], true);
87*1c502704SAndreas Gohr            $this->columns[$row['colref']] =
88*1c502704SAndreas Gohr                new Column(
89*1c502704SAndreas Gohr                    $row['sort'],
90*1c502704SAndreas Gohr                    new $class($config, $row['label'], $row['ismulti']),
91*1c502704SAndreas Gohr                    $row['tid'],
92*1c502704SAndreas Gohr                    $row['colref'],
93*1c502704SAndreas Gohr                    $row['enabled']
94*1c502704SAndreas Gohr                );
95*1c502704SAndreas Gohr
96083afc55SAndreas Gohr            if($row['sort'] > $this->maxsort) $this->maxsort = $row['sort'];
97083afc55SAndreas Gohr        }
98083afc55SAndreas Gohr    }
99083afc55SAndreas Gohr
100083afc55SAndreas Gohr    /**
101083afc55SAndreas Gohr     * Cleans any unwanted stuff from table names
102083afc55SAndreas Gohr     *
103083afc55SAndreas Gohr     * @param string $table
104083afc55SAndreas Gohr     * @return string
105083afc55SAndreas Gohr     */
106083afc55SAndreas Gohr    static public function cleanTableName($table) {
107083afc55SAndreas Gohr        $table = preg_replace('/[^a-z0-9_]+/', '', $table);
108083afc55SAndreas Gohr        $table = preg_replace('/^[0-9_]+/', '', $table);
109083afc55SAndreas Gohr        $table = trim($table);
110083afc55SAndreas Gohr        return $table;
111083afc55SAndreas Gohr    }
112083afc55SAndreas Gohr
113083afc55SAndreas Gohr    /**
114*1c502704SAndreas Gohr     * Returns the Admin Form to edit the schema
115083afc55SAndreas Gohr     *
116083afc55SAndreas Gohr     * @return string
117083afc55SAndreas Gohr     */
118083afc55SAndreas Gohr    public function adminEditor() {
119*1c502704SAndreas Gohr        $form = new Form(array('method' => 'POST'));
120*1c502704SAndreas Gohr        $form->setHiddenField('do', 'admin');
121*1c502704SAndreas Gohr        $form->setHiddenField('page', 'struct');
122*1c502704SAndreas Gohr        $form->setHiddenField('table', $this->table);
123*1c502704SAndreas Gohr        $form->setHiddenField('schema[id]', $this->id);
124083afc55SAndreas Gohr
125*1c502704SAndreas Gohr        $form->addHTML('<table class="inline">');
126*1c502704SAndreas Gohr        $form->addHTML('<tr><th>Sort</th><th>Label</th><th>Multi-Input?</th><th>Configuration</th><th>Type</th></tr>'); // FIXME localize
127083afc55SAndreas Gohr
128083afc55SAndreas Gohr        foreach($this->columns as $key => $obj) {
129*1c502704SAndreas Gohr            $form->addHTML($this->adminColumn($key, $obj));
130083afc55SAndreas Gohr        }
131083afc55SAndreas Gohr
132083afc55SAndreas Gohr        // FIXME new one needs to be added dynamically, this is just for testing
133*1c502704SAndreas Gohr        $form->addHTML($this->adminColumn('new1', new Column($this->maxsort+10, new Text()), 'new'));
134083afc55SAndreas Gohr
135*1c502704SAndreas Gohr        $form->addHTML('</table>');
136*1c502704SAndreas Gohr        $form->addButton('save', 'Save')->attr('type','submit');
137*1c502704SAndreas Gohr        return $form->toHTML();
138083afc55SAndreas Gohr    }
139083afc55SAndreas Gohr
140083afc55SAndreas Gohr    /**
141083afc55SAndreas Gohr     * Returns the HTML to edit a single column definition of the schema
142083afc55SAndreas Gohr     *
143083afc55SAndreas Gohr     * @param string $column_id
144*1c502704SAndreas Gohr     * @param Column $col
145*1c502704SAndreas Gohr     * @param string $key The key to use in the form
146083afc55SAndreas Gohr     * @return string
147083afc55SAndreas Gohr     * @todo this should probably be reused for adding new columns via AJAX later?
148083afc55SAndreas Gohr     */
149*1c502704SAndreas Gohr    protected function adminColumn($column_id, Column $col, $key='cols') {
150*1c502704SAndreas Gohr        $base = 'schema['.$key.'][' . $column_id . ']'; // base name for all fields
151083afc55SAndreas Gohr
152083afc55SAndreas Gohr        $html = '<tr>';
153083afc55SAndreas Gohr
154083afc55SAndreas Gohr        $html .= '<td>';
155*1c502704SAndreas Gohr        $html .= '<input type="text" name="' . $base . '[sort]" value="' . hsc($col->getSort()) . '" size="3">';
156083afc55SAndreas Gohr        $html .= '</td>';
157083afc55SAndreas Gohr
158083afc55SAndreas Gohr        $html .= '<td>';
159*1c502704SAndreas Gohr        $html .= '<input type="text" name="' . $base . '[label]" value="' . hsc($col->getType()->getLabel()) . '">';
160083afc55SAndreas Gohr        $html .= '</td>';
161083afc55SAndreas Gohr
162083afc55SAndreas Gohr        $html .= '<td>';
163*1c502704SAndreas Gohr        $checked = $col->getType()->isMulti() ? 'checked="checked"' : '';
164083afc55SAndreas Gohr        $html .= '<input type="checkbox" name="' . $base . '[ismulti]" value="1" ' . $checked . '>';
165083afc55SAndreas Gohr        $html .= '</td>';
166083afc55SAndreas Gohr
167083afc55SAndreas Gohr        $html .= '<td>';
168*1c502704SAndreas Gohr        $config = json_encode($col->getType()->getConfig(), JSON_PRETTY_PRINT);
169083afc55SAndreas Gohr        $html .= '<textarea name="' . $base . '[config]" cols="45" rows="10">' . hsc($config) . '</textarea>';
170083afc55SAndreas Gohr        $html .= '</td>';
171083afc55SAndreas Gohr
172083afc55SAndreas Gohr        $html .= '<td>';
173*1c502704SAndreas Gohr        $html .= '<input type="text" name="' . $base . '[class]" value="' . hsc($col->getType()->getClass()) . '">'; //FIXME this needs to be a dropdown
174083afc55SAndreas Gohr        $html .= '</td>';
175083afc55SAndreas Gohr
176083afc55SAndreas Gohr        $html .= '</tr>';
177083afc55SAndreas Gohr
178083afc55SAndreas Gohr        return $html;
179083afc55SAndreas Gohr    }
180083afc55SAndreas Gohr
181*1c502704SAndreas Gohr    /**
182*1c502704SAndreas Gohr     * @return string
183*1c502704SAndreas Gohr     */
184*1c502704SAndreas Gohr    public function getChksum() {
185*1c502704SAndreas Gohr        return $this->chksum;
186*1c502704SAndreas Gohr    }
187*1c502704SAndreas Gohr
188*1c502704SAndreas Gohr    /**
189*1c502704SAndreas Gohr     * @return int
190*1c502704SAndreas Gohr     */
191*1c502704SAndreas Gohr    public function getId() {
192*1c502704SAndreas Gohr        return $this->id;
193*1c502704SAndreas Gohr    }
194*1c502704SAndreas Gohr
195*1c502704SAndreas Gohr    /**
196*1c502704SAndreas Gohr     * @return \plugin\struct\meta\Column[]
197*1c502704SAndreas Gohr     */
198*1c502704SAndreas Gohr    public function getColumns() {
199*1c502704SAndreas Gohr        return $this->columns;
200*1c502704SAndreas Gohr    }
201*1c502704SAndreas Gohr
202*1c502704SAndreas Gohr
203*1c502704SAndreas Gohr
204*1c502704SAndreas Gohr
205083afc55SAndreas Gohr}
206