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