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