xref: /plugin/struct/types/DateTime.php (revision 987ccc7f0328ab5d1bee7848402f7803f7b62014)
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     * @param string $htmlID
37     *
38     * @return string html
39     */
40    public function valueEditor($name, $rawvalue, $htmlID) {
41        if($this->config['prefilltoday'] && !$rawvalue) {
42            $rawvalue = date('Y-m-d H:i:s');
43        }
44
45        $params = array(
46            'name' => $name,
47            'value' => $rawvalue,
48            'class' => 'struct_datetime',
49            'type' => 'datetime-local', // HTML5 datetime picker
50            'id' => $htmlID,
51        );
52        $attributes = buildAttributes($params, true);
53        return "<input $attributes />";
54    }
55
56    /**
57     * Validate a single value
58     *
59     * This function needs to throw a validation exception when validation fails.
60     * The exception message will be prefixed by the appropriate field on output
61     *
62     * @param string|array $rawvalue
63     * @return string
64     * @throws ValidationException
65     */
66    public function validate($rawvalue) {
67        $rawvalue = trim($rawvalue);
68        list($date, $time) = explode(' ', $rawvalue, 2);
69        $date = trim($date);
70        $time = trim($time);
71
72        list($year, $month, $day) = explode('-', $date, 3);
73        if(!checkdate((int) $month, (int) $day, (int) $year)) {
74            throw new ValidationException('invalid datetime format');
75        }
76
77        list($h, $m, $s) = explode(':', $time, 3);
78        $h = (int) $h;
79        $m = (int) $m;
80        $s = (int) $s;
81        if($h < 0 || $h > 23 || $m < 0 || $m > 59 || $s < 0 || $s > 59) {
82            throw new ValidationException('invalid datetime format');
83        }
84
85        return sprintf("%d-%02d-%02d %02d:%02d:%02d", $year, $month, $day, $h, $m, $s);
86    }
87
88    /**
89     * @param QueryBuilder $QB
90     * @param string $tablealias
91     * @param string $colname
92     * @param string $alias
93     */
94    public function select(QueryBuilder $QB, $tablealias, $colname, $alias) {
95        $col = "$tablealias.$colname";
96
97        // when accessing the revision column we need to convert from Unix timestamp
98        if(is_a($this->context,'dokuwiki\plugin\struct\meta\RevisionColumn')) {
99            $rightalias = $QB->generateTableAlias();
100            $QB->addLeftJoin($tablealias, 'titles', $rightalias, "$tablealias.pid = $rightalias.pid");
101            $col = "DATETIME($rightalias.lastrev, 'unixepoch', 'localtime')";
102        }
103
104        $QB->addSelectStatement($col, $alias);
105    }
106
107    /**
108     * @param QueryBuilderWhere $add
109     * @param string $tablealias
110     * @param string $colname
111     * @param string $comp
112     * @param string|\string[] $value
113     * @param string $op
114     */
115    public function filter(QueryBuilderWhere $add, $tablealias, $colname, $comp, $value, $op) {
116        $col = "$tablealias.$colname";
117
118        // when accessing the revision column we need to convert from Unix timestamp
119        if(is_a($this->context,'dokuwiki\plugin\struct\meta\RevisionColumn')) {
120            $QB = $add->getQB();
121            $rightalias = $QB->generateTableAlias();
122            $col = "DATETIME($rightalias.lastrev, 'unixepoch', 'localtime')";
123            $QB->addLeftJoin($tablealias, 'titles', $rightalias, "$tablealias.pid = $rightalias.pid");
124        }
125
126        /** @var QueryBuilderWhere $add Where additionional queries are added to*/
127        if(is_array($value)) {
128            $add = $add->where($op); // sub where group
129            $op = 'OR';
130        }
131        foreach((array) $value as $item) {
132            $pl = $QB->addValue($item);
133            $add->where($op, "$col $comp $pl");
134        }
135    }
136
137    /**
138     * When sorting `%lastupdated%`, then sort the data from the `titles` table instead the `data_` table.
139     *
140     * @param QueryBuilder $QB
141     * @param string $tablealias
142     * @param string $colname
143     * @param string $order
144     */
145    public function sort(QueryBuilder $QB, $tablealias, $colname, $order) {
146        $col = "$tablealias.$colname";
147
148        if(is_a($this->context,'dokuwiki\plugin\struct\meta\RevisionColumn')) {
149            $rightalias = $QB->generateTableAlias();
150            $QB->addLeftJoin($tablealias, 'titles', $rightalias, "$tablealias.pid = $rightalias.pid");
151            $col = "$rightalias.lastrev";
152        }
153
154        $QB->addOrderBy("$col $order");
155    }
156
157}
158