xref: /plugin/struct/types/DateTime.php (revision a0b3799e3857209811ed06eddf7c60cec2980a26)
1<?php
2namespace dokuwiki\plugin\struct\types;
3
4use dokuwiki\plugin\struct\meta\DateFormatConverter;
5use dokuwiki\plugin\struct\meta\QueryBuilder;
6use dokuwiki\plugin\struct\meta\QueryBuilderWhere;
7use dokuwiki\plugin\struct\meta\ValidationException;
8
9class DateTime extends Date {
10
11    protected $config = array(
12        'format' => '', // filled by constructor
13        'prefilltoday' => false
14    );
15
16    /**
17     * DateTime constructor.
18     *
19     * @param array|null $config
20     * @param string $label
21     * @param bool $ismulti
22     * @param int $tid
23     */
24    public function __construct($config = null, $label = '', $ismulti = false, $tid = 0) {
25        global $conf;
26        $this->config['format'] = DateFormatConverter::toDate($conf['dformat']);
27
28        parent::__construct($config, $label, $ismulti, $tid);
29    }
30
31    /**
32     * Return the editor to edit a single value
33     *
34     * @param string $name the form name where this has to be stored
35     * @param string $rawvalue the current value
36     * @return string html
37     */
38    public function valueEditor($name, $rawvalue) {
39        $name = hsc($name);
40        $rawvalue = hsc($rawvalue);
41
42        if($this->config['prefilltoday'] && !$rawvalue) {
43            $rawvalue = date('Y-m-d H:i:s');
44        }
45
46        $html = "<input class=\"struct_datetime\" name=\"$name\" value=\"$rawvalue\" />";
47        return "$html";
48    }
49
50    /**
51     * Validate a single value
52     *
53     * This function needs to throw a validation exception when validation fails.
54     * The exception message will be prefixed by the appropriate field on output
55     *
56     * @param string|array $rawvalue
57     * @return string
58     * @throws ValidationException
59     */
60    public function validate($rawvalue) {
61        $rawvalue = trim($rawvalue);
62        list($date, $time) = explode(' ', $rawvalue, 2);
63        $date = trim($date);
64        $time = trim($time);
65
66        list($year, $month, $day) = explode('-', $date, 3);
67        if(!checkdate((int) $month, (int) $day, (int) $year)) {
68            throw new ValidationException('invalid datetime format');
69        }
70
71        list($h, $m, $s) = explode(':', $time, 3);
72        $h = (int) $h;
73        $m = (int) $m;
74        $s = (int) $s;
75        if($h < 0 || $h > 23 || $m < 0 || $m > 59 || $s < 0 || $s > 59) {
76            throw new ValidationException('invalid datetime format');
77        }
78
79        return sprintf("%d-%02d-%02d %02d:%02d:%02d", $year, $month, $day, $h, $m, $s);
80    }
81
82    /**
83     * @param QueryBuilder $QB
84     * @param string $tablealias
85     * @param string $colname
86     * @param string $alias
87     */
88    public function select(QueryBuilder $QB, $tablealias, $colname, $alias) {
89        $col = "$tablealias.$colname";
90
91        // when accessing the revision column we need to convert from Unix timestamp
92        if(is_a($this->context,'dokuwiki\plugin\struct\meta\RevisionColumn')) {
93            $rightalias = $QB->generateTableAlias();
94            $QB->addLeftJoin($tablealias, 'titles', $rightalias, "$tablealias.pid = $rightalias.pid");
95            $col = "DATETIME($rightalias.lastrev, 'unixepoch', 'localtime')";
96        }
97
98        $QB->addSelectStatement($col, $alias);
99    }
100
101    /**
102     * @param QueryBuilder $QB
103     * @param string $tablealias
104     * @param string $colname
105     * @param string $comp
106     * @param string|\string[] $value
107     * @param string $op
108     */
109    public function filter(QueryBuilder $QB, $tablealias, $colname, $comp, $value, $op) {
110        $col = "$tablealias.$colname";
111
112        // when accessing the revision column we need to convert from Unix timestamp
113        if(is_a($this->context,'dokuwiki\plugin\struct\meta\RevisionColumn')) {
114            $rightalias = $QB->generateTableAlias();
115            $col = "DATETIME($rightalias.lastrev, 'unixepoch', 'localtime')";
116            $QB->addLeftJoin($tablealias, 'titles', $rightalias, "$tablealias.pid = $rightalias.pid");
117        }
118
119        /** @var QueryBuilderWhere $add Where additionional queries are added to*/
120        if(is_array($value)) {
121            $add = $QB->filters()->where($op); // sub where group
122            $op = 'OR';
123        } else {
124            $add = $QB->filters(); // main where clause
125        }
126        foreach((array) $value as $item) {
127            $pl = $QB->addValue($item);
128            $add->where($op, "$col $comp $pl");
129        }
130    }
131
132    /**
133     * When sorting `%lastupdated%`, then sort the data from the `titles` table instead the `data_` table.
134     *
135     * @param QueryBuilder $QB
136     * @param string $tablealias
137     * @param string $colname
138     * @param string $order
139     */
140    public function sort(QueryBuilder $QB, $tablealias, $colname, $order) {
141        $col = "$tablealias.$colname";
142
143        if(is_a($this->context,'dokuwiki\plugin\struct\meta\RevisionColumn')) {
144            $rightalias = $QB->generateTableAlias();
145            $QB->addLeftJoin($tablealias, 'titles', $rightalias, "$tablealias.pid = $rightalias.pid");
146            $col = "$rightalias.lastrev";
147        }
148
149        $QB->addOrderBy("$col $order");
150    }
151
152}
153