FusionDirectory
class_DateAttribute.inc
1 <?php
2 /*
3  This code is part of FusionDirectory (http://www.fusiondirectory.org/)
4 
5  Copyright (C) 2012-2019 FusionDirectory
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21 
27 {
28  protected $format;
29  protected $minDate = NULL;
30  protected $maxDate = NULL;
31 
44  function __construct (string $label, string $description, string $ldapName, bool $required, string $format, $defaultValue = 'today', $min = NULL, $max = NULL, string $acl = '')
45  {
46  parent::__construct($label, $description, $ldapName, $required, $defaultValue, $acl);
47  $this->format = $format;
48  if ($min !== NULL) {
49  try {
50  $this->minDate = new DateTime($min, new DateTimeZone('UTC'));
51  } catch (Exception $e) {
52  // Failed to parse min date, ignore
53  }
54  }
55  if ($max !== NULL) {
56  try {
57  $this->maxDate = new DateTime($max, new DateTimeZone('UTC'));
58  } catch (Exception $e) {
59  // Failed to parse max date, ignore
60  }
61  }
62  }
63 
64  function inputValue ($value)
65  {
66  if (
67  ($value === '') ||
68  ($this->isTemplate() && preg_match('/%/', $value))
69  ) {
70  return $value;
71  } else {
72  return $this->ldapToDate($value);
73  }
74  }
75 
76  function getValue ()
77  {
78  if ($this->value === '') {
79  return $this->value;
80  } else {
81  try {
82  return $this->getDateValue()->format('Y-m-d');
83  } catch (Exception $e) {
84  return $this->value;
85  }
86  }
87  }
88 
89  protected function ldapToDate ($ldapValue)
90  {
91  $date = DateTime::createFromFormat('!'.$this->format, $ldapValue, new DateTimeZone('UTC'));
92  if ($date !== FALSE) {
93  return $date;
94  } else {
95  return $ldapValue;
96  }
97  }
98 
99  protected function dateToLdap (DateTime $dateValue)
100  {
101  return $dateValue->format($this->format);
102  }
103 
104  function getDateValue ()
105  {
106  $value = $this->value;
107  if (!($value instanceof DateTime)) {
108  try {
109  $value = new DateTime($value, new DateTimeZone('UTC'));
110  } catch (Exception $e) {
111  /* Fallback to LdapGeneralizedTime to accept LDAP format */
112  try {
113  $value = LdapGeneralizedTime::fromString($value);
115  throw $e;
116  }
117  }
118  }
119  return $value;
120  }
121 
122  function computeLdapValue ()
123  {
124  if ($this->value === '') {
125  return $this->value;
126  } elseif (!($this->value instanceof DateTime)) {
127  try {
128  $this->setValue($this->getDateValue());
129  } catch (Exception $e) {
130  return $this->value;
131  }
132  }
133  return $this->dateToLdap($this->value);
134  }
135 
136  function check ()
137  {
138  $error = parent::check();
139  if (!empty($error)) {
140  return $error;
141  } else {
142  if (empty($this->value)) {
143  return '';
144  }
145  try {
146  $dateValue = $this->getDateValue();
147  if (($this->minDate !== NULL) && ($dateValue < $this->minDate)) {
148  return new SimplePluginCheckError(
149  $this,
150  SimplePluginCheckError::invalidValue(sprintf(_('%s is older than %s'), $dateValue->format('Y-m-d'), $this->minDate->format('Y-m-d')))
151  );
152  }
153  if (($this->maxDate !== NULL) && ($dateValue > $this->maxDate)) {
154  return new SimplePluginCheckError(
155  $this,
156  SimplePluginCheckError::invalidValue(sprintf(_('%s is newer than %s'), $dateValue->format('Y-m-d'), $this->maxDate->format('Y-m-d')))
157  );
158  }
159  } catch (Exception $e) {
160  if ($this->isTemplate() && preg_match('/%/', $this->value)) {
161  return '';
162  } else {
163  return new SimplePluginCheckError(
164  $this,
165  SimplePluginCheckError::invalidValue(sprintf(_('Incorrect date: %s'), $e->getMessage())),
166  0,
167  $e
168  );
169  }
170  }
171  return '';
172  }
173  }
174 
175  function renderFormInput (): string
176  {
177  $attributes = [
178  'value' => $this->getValue(),
179  'pattern' => '[0-9]{4}-[0-9]{2}-[0-9]{2}',
180  ];
181  if ($this->minDate !== NULL) {
182  $attributes['min'] = $this->minDate->format('Y-m-d');
183  }
184  if ($this->maxDate !== NULL) {
185  $attributes['max'] = $this->maxDate->format('Y-m-d');
186  }
187  $display = $this->renderInputField('date', $this->getHtmlId(), $attributes);
188  return $this->renderAcl($display);
189  }
190 
191  function renderTemplateInput (): string
192  {
193  $id = $this->getHtmlId();
194  $attributes = [
195  'value' => $this->getValue()
196  ];
197  if ($this->isSubAttribute) {
198  $attributes['class'] = 'subattribute';
199  }
200  $display = $this->renderInputField('text', $id, $attributes);
201  return $this->renderAcl($display);
202  }
203 }
204 
209 {
210  function __construct (string $label, string $description, string $ldapName, bool $required, $defaultValue = 'today', $min = NULL, $max = NULL, string $acl = '')
211  {
212  parent::__construct($label, $description, $ldapName, $required, '', $defaultValue, $min, $max, $acl);
213  }
214 
215  protected function ldapToDate ($ldapValue)
216  {
217  try {
218  return LdapGeneralizedTime::fromString($ldapValue);
220  return $ldapValue;
221  }
222  }
223 
224  protected function dateToLdap (DateTime $dateValue)
225  {
226  return LdapGeneralizedTime::toString($dateValue);
227  }
228 }
229 
234 {
235  protected $convert;
236 
237  function __construct ($label, $description, $ldapName, $required, $convert = TRUE, $acl = '')
238  {
239  $this->convert = $convert;
240  $attributes = [
241  new IntAttribute(
242  '', _('Hours'),
243  $ldapName.'_hours', TRUE,
244  0, 23, 1
245  ),
246  new IntAttribute(
247  ':', _('Minutes'),
248  $ldapName.'_minutes', TRUE,
249  0, 59, 0
250  ),
251  new IntAttribute(
252  ':', _('Seconds'),
253  $ldapName.'_seconds', TRUE,
254  0, 59, 0
255  )
256  ];
257  parent::__construct($description, $ldapName, $attributes, '/^(\d\d)(\d\d)(\d\d)$/', '%02d%02d%02d', $acl, $label);
258  $this->setLinearRendering(TRUE);
259  }
260 
261  function readValues (string $value): array
262  {
263  $values = parent::readValues($value);
264  if ($this->convert) {
265  $datetime = new DateTime('T'.implode(':', $values), timezone::utc());
266 
267  $datetime->setTimeZone(timezone::getDefaultTimeZone());
268  if (count($values) < 3) {
269  $values = explode(':', $datetime->format('H:i'));
270  } else {
271  $values = explode(':', $datetime->format('H:i:s'));
272  }
273  }
274  return $values;
275  }
276 
277  function writeValues (array $values)
278  {
279  if ($this->convert) {
280  $datetime = new DateTime('T'.implode(':', $values), timezone::getDefaultTimeZone());
281  $datetime->setTimeZone(timezone::utc());
282  if (count($values) < 3) {
283  $values = explode(':', $datetime->format('H:i'));
284  } else {
285  $values = explode(':', $datetime->format('H:i:s'));
286  }
287  }
288  return parent::writeValues($values);
289  }
290 
291  function displayValue ($value): string
292  {
293  $values = parent::readValues($value);
294  $datetime = new DateTime('T'.implode(':', $values), timezone::utc());
295  if ($this->convert) {
296  $datetime->setTimeZone(timezone::getDefaultTimeZone());
297  }
298  if (count($values) < 3) {
299  return $datetime->format('H:i');
300  } else {
301  return $datetime->format('H:i:s');
302  }
303  }
304 }
305 
310 {
311  function __construct ($label, $description, $ldapName, $required, $convert = TRUE, $acl = '')
312  {
313  $this->convert = $convert;
314  $attributes = [
315  new IntAttribute(
316  '', _('Hours'),
317  $ldapName.'_hours', TRUE,
318  0, 23, 1
319  ),
320  new IntAttribute(
321  ':', _('Minutes'),
322  $ldapName.'_minutes', TRUE,
323  0, 59, 0
324  )
325  ];
326  CompositeAttribute::__construct($description, $ldapName, $attributes, '/^(\d\d)(\d\d)$/', '%02d%02d', $acl, $label);
327  $this->setLinearRendering(TRUE);
328  }
329 }
330 
335 {
336  function __construct ($label, $description, $ldapName, $required, $acl = '')
337  {
338  $attributes = [
339  new DateAttribute(
340  _('Date'), '',
341  $ldapName.'_date', $required,
342  'Ymd'
343  ),
344  /* Disabling conversion as it needs to be done on the date+time level (see argonautAction for an example) */
345  new TimeHisAttribute(
346  _('Time'), '',
347  $ldapName.'_time', $required,
348  FALSE
349  )
350  ];
351  parent::__construct($description, $ldapName, $attributes, '/^(\d{8})(\d{6})$/', '%s%s', $acl, $label);
352  }
353 }
354 
359 {
360  protected $displayFormat;
361 
362  function __construct (string $label, string $description, string $ldapName, bool $required, $defaultValue = '', $format = 'Y-m-d, H:i:s', $min = NULL, $max = NULL, string $acl = '')
363  {
364  parent::__construct($label, $description, $ldapName, $required, $defaultValue, $min, $max, $acl);
365  $this->displayFormat = $format;
366  }
367 
368  function getValue ()
369  {
370  return $this->computeLdapValue();
371  }
372 
373  function renderFormInput (): string
374  {
375  if (empty($this->value)) {
376  return '';
377  }
378  $date = $this->getDateValue();
379  $date->setTimezone(timezone::getDefaultTimeZone());
380  return htmlescape($date->format($this->displayFormat));
381  }
382 }
383 
388 {
389  /* 24 * 60 * 60 = 86400 */
390  public static $secondsPerDay = 86400;
391 
392  function __construct (string $label, string $description, string $ldapName, bool $required, $defaultValue = 'today', $min = NULL, $max = NULL, string $acl = '')
393  {
394  parent::__construct($label, $description, $ldapName, $required, '', $defaultValue, $min, $max, $acl);
395  }
396 
397  protected function ldapToDate ($ldapValue)
398  {
399  $date = DateTime::createFromFormat('U', (string)($ldapValue * static::$secondsPerDay), timezone::utc());
400  if ($date !== FALSE) {
401  return $date;
402  } else {
403  trigger_error('LDAP value for '.$this->getLdapName().' was not in the right date format.');
404  return new DateTime($ldapValue, timezone::utc());
405  }
406  }
407 
408  protected function dateToLdap (DateTime $dateValue)
409  {
410  return floor($dateValue->format('U') / static::$secondsPerDay);
411  }
412 
413  function getEpochDays ()
414  {
415  if (empty($this->value)) {
416  return 0;
417  } else {
418  try {
419  return $this->dateToLdap($this->getDateValue());
420  } catch (Exception $e) {
421  if (is_object($this->plugin) && $this->plugin->is_template) {
422  return $this->value;
423  } else {
424  throw $e;
425  }
426  }
427  }
428  }
429 }
Date attribute storing standard LDAP GeneralizedTime format.
Attribute storing time as Hi format.
htmlescape(string $str)
Escape string for HTML output.
Definition: php_setup.inc:32
Read-only GeneralizedTimeDateAttribute. Used by audit plugin.
__construct(string $label, string $description, string $ldapName, bool $required, string $format, $defaultValue='today', $min=NULL, $max=NULL, string $acl='')
The constructor of DateAttribute.
static toString(DateTime $date, $setToUTC=TRUE)
Convert from DateTime object to LDAP GeneralizedTime formatted string.
This class allow to handle easily a composite attribute.
__construct(string $description, string $ldapName, array $attributes, $readFormat, $writeFormat, string $acl='', string $label=NULL)
The constructor of CompositeAttribute.
Exception class which can be thrown by LdapGeneralizedTime if the format does not match...
static invalidValue(string $error)
Format error message for invalid value.
Error returned by check method of SimplePlugin.
Attribute storing time as His format.
renderAcl(string $display)
Add ACL information around display.
static fromString($string, $useException=TRUE)
Convert from LDAP GeneralizedTime formatted string to DateTime object.
This class allow to handle easily an Integer LDAP attribute.
Attribute storing both Date and Time.
This class allow to handle easily an Date LDAP attribute.
This class allow to handle easily any kind of LDAP attribute.
Date stored as days since Unix epoch. Used by posix plugin.