1<?php
2
3namespace dokuwiki\plugin\struct\types;
4
5use dokuwiki\plugin\struct\meta\ValidationException;
6
7class Date extends AbstractBaseType
8{
9    protected $config = [
10        'format' => 'Y/m/d',
11        'prefilltoday' => false,
12        'pastonly' => false,
13        'futureonly' => false
14    ];
15
16    /**
17     * Output the stored data
18     *
19     * @param string|int $value the value stored in the database
20     * @param \Doku_Renderer $R the renderer currently used to render the data
21     * @param string $mode The mode the output is rendered in (eg. XHTML)
22     * @return bool true if $mode could be satisfied
23     */
24    public function renderValue($value, \Doku_Renderer $R, $mode)
25    {
26        $date = date_create($value);
27        if ($date !== false) {
28            $out = date_format($date, $this->config['format']);
29        } else {
30            $out = '';
31        }
32
33        $R->cdata($out);
34        return true;
35    }
36
37    /**
38     * Return the editor to edit a single value
39     *
40     * @param string $name the form name where this has to be stored
41     * @param string $rawvalue the current value
42     * @param string $htmlID
43     *
44     * @return string html
45     */
46    public function valueEditor($name, $rawvalue, $htmlID)
47    {
48        if ($this->config['prefilltoday'] && !$rawvalue) {
49            $rawvalue = date('Y-m-d');
50        }
51
52        $params = [
53            'name' => $name,
54            'value' => $rawvalue,
55            'class' => 'struct_date',
56            'type' => 'date', // HTML5 date picker
57            'id' => $htmlID,
58        ];
59        $attributes = buildAttributes($params, true);
60        return "<input $attributes />";
61    }
62
63    /**
64     * Validate a single value
65     *
66     * This function needs to throw a validation exception when validation fails.
67     * The exception message will be prefixed by the appropriate field on output
68     *
69     * @param string|int $rawvalue
70     * @return int|string
71     * @throws ValidationException
72     */
73    public function validate($rawvalue)
74    {
75        $rawvalue = parent::validate($rawvalue);
76        [$rawvalue] = explode(' ', $rawvalue, 2); // strip off time if there is any
77
78        [$year, $month, $day] = explode('-', $rawvalue, 3);
79        if (!checkdate((int)$month, (int)$day, (int)$year)) {
80            throw new ValidationException('invalid date format');
81        }
82        if ($this->config['pastonly'] && strtotime($rawvalue) > time()) {
83            throw new ValidationException('pastonly');
84        }
85        if ($this->config['futureonly'] && strtotime($rawvalue) < time()) {
86            throw new ValidationException('futureonly');
87        }
88        return sprintf('%d-%02d-%02d', $year, $month, $day);
89    }
90}
91