xref: /plugin/struct/meta/Schema.php (revision 2987727967455b4335cb8dba900196317113c849)
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        } else {
70            $sql = "SELECT *
71                      FROM schemas
72                     WHERE tbl = ?
73                  ORDER BY ts DESC
74                     LIMIT 1";
75            $opt = array($table);
76        }
77        $res = $this->sqlite->query($sql, $opt);
78        if($this->sqlite->res2count($res)) {
79            $schema = $this->sqlite->res2arr($res);
80            $result = array_shift($schema);
81            $this->id = $result['id'];
82            $this->chksum = $result['chksum'];
83
84        }
85        $this->sqlite->res_close($res);
86        if(!$this->id) return;
87
88        // load existing columns
89        $sql = "SELECT SC.*, T.*
90                  FROM schema_cols SC,
91                       types T
92                 WHERE SC.sid = ?
93                   AND SC.tid = T.id
94              ORDER BY SC.sort";
95        $res = $this->sqlite->query($sql, $this->id);
96        $rows = $this->sqlite->res2arr($res);
97        $this->sqlite->res_close($res);
98
99        foreach($rows as $row) {
100            $class = 'plugin\\struct\\types\\' . $row['class'];
101            $config = json_decode($row['config'], true);
102            $this->columns[$row['colref']] =
103                new Column(
104                    $row['sort'],
105                    new $class($config, $row['label'], $row['ismulti'], $row['tid']),
106                    $row['colref'],
107                    $row['enabled'],
108                    $table
109                );
110
111            if($row['sort'] > $this->maxsort) $this->maxsort = $row['sort'];
112        }
113    }
114
115    /**
116     * Cleans any unwanted stuff from table names
117     *
118     * @param string $table
119     * @return string
120     */
121    static public function cleanTableName($table) {
122        $table = strtolower($table);
123        $table = preg_replace('/[^a-z0-9_]+/', '', $table);
124        $table = preg_replace('/^[0-9_]+/', '', $table);
125        $table = trim($table);
126        return $table;
127    }
128
129    /**
130     * @return string
131     */
132    public function getChksum() {
133        return $this->chksum;
134    }
135
136    /**
137     * @return int
138     */
139    public function getId() {
140        return $this->id;
141    }
142
143    /**
144     * Returns a list of columns in this schema
145     *
146     * @param bool $withDisabled if false, disabled columns will not be returned
147     * @return Column[]
148     */
149    public function getColumns($withDisabled = true) {
150        if(!$withDisabled) {
151            return array_filter(
152                $this->columns,
153                function (Column $col) {
154                    return $col->isEnabled();
155                }
156            );
157        }
158
159        return $this->columns;
160    }
161
162    /**
163     * Find a column in the schema by its label
164     *
165     * Only enabled columns are returned!
166     *
167     * @param $name
168     * @return bool|Column
169     */
170    public function findColumn($name) {
171        foreach($this->columns as $col) {
172            if($col->isEnabled() && utf8_strtolower($col->getLabel()) == utf8_strtolower($name)) {
173                return $col;
174            }
175        }
176        return false;
177    }
178
179    /**
180     * @return string
181     */
182    public function getTable() {
183        return $this->table;
184    }
185
186    /**
187     * @return int the highest sort number used in this schema
188     */
189    public function getMaxsort() {
190        return $this->maxsort;
191    }
192
193}
194