Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
date.php
1<?php
3
8
9Loc::loadMessages(__FILE__);
10
15class Date extends Base
16{
20 public static function getType()
21 {
22 return FieldType::DATE;
23 }
24
32 public static function toSingleValue(FieldType $fieldType, $value)
33 {
34 if (is_array($value))
35 {
36 reset($value);
37 $value = current($value);
38 }
39 return $value;
40 }
41
48 public static function convertTo(FieldType $fieldType, $value, $toTypeClass)
49 {
51 $type = $toTypeClass::getType();
52 switch ($type)
53 {
55 case FieldType::INT:
56 $value = $value? (int)strtotime($value) : 0;
57 break;
58 case FieldType::DATE:
61 case FieldType::TEXT:
62 $value = (string) $value;
63 if ($value)
64 {
65 if ($type == FieldType::DATE)
66 $format = \FORMAT_DATE;
67 elseif ($type == FieldType::DATETIME)
68 $format = \FORMAT_DATETIME;
69 else
70 $format = static::getType() == FieldType::DATE ? \FORMAT_DATE : \FORMAT_DATETIME;
71
72 if (\CheckDateTime($value, $format))
73 {
74 $value = date(Type\Date::convertFormatToPhp($format), \MakeTimeStamp($value, $format));
75 }
76 else
77 {
78 $value = date(Type\Date::convertFormatToPhp($format), strtotime($value));
79 }
80 }
81 break;
82 default:
83 $value = null;
84 }
85
86 return $value;
87 }
88
93 public static function getConversionMap()
94 {
95 return array(
96 array(
103 )
104 );
105 }
106
115 protected static function renderControl(FieldType $fieldType, array $field, $value, $allowSelection, $renderMode)
116 {
117 $name = static::generateControlName($field);
118 $value = static::internalizeValue($fieldType, 'Renderer', $value);
119 $offset = ($value instanceof Value\Date) ? $value->getOffset() : 0;
120
121 $className = static::generateControlClassName($fieldType, $field);
122 $renderResult = '';
123 $isPublicControl = $renderMode & FieldType::RENDER_MODE_PUBLIC;
124
125 if ($isPublicControl && $allowSelection)
126 {
127 $selectorAttributes = sprintf(
128 'data-role="inline-selector-target" data-selector-type="%s" data-property="%s" ',
129 htmlspecialcharsbx($fieldType->getType()),
130 htmlspecialcharsbx(Main\Web\Json::encode($fieldType->getProperty()))
131 );
132
133 $renderResult = sprintf(
134 '<input name="%s" type="text" class="%s" value="%s" placeholder="%s" %s/>',
135 htmlspecialcharsbx($name),
136 htmlspecialcharsbx($className),
137 htmlspecialcharsbx($value),
138 htmlspecialcharsbx($fieldType->getDescription()),
139 $selectorAttributes
140 );
141 }
142 elseif ($renderMode & FieldType::RENDER_MODE_MOBILE)
143 {
144 $renderResult = '<div><input type="hidden" value="'
145 .htmlspecialcharsbx($value).'" data-type="'
146 .htmlspecialcharsbx(static::getType()).'" name="'.htmlspecialcharsbx($name).'"/>'
147 .'<a href="#" onclick="return BX.BizProcMobile.showDatePicker(this, event);">'
148 .($value? htmlspecialcharsbx($value) : Loc::getMessage('BPDT_DATE_MOBILE_SELECT')).'</a></div>';
149 }
150 else
151 {
152 \CJSCore::Init(['popup', 'date']);
153 $renderResult = sprintf(
154 '<input type="text" name="%s" value="%s" class="%s"/>'
155 . '<img src="/bitrix/js/main/core/images/calendar-icon.gif" alt="calendar" class="calendar-icon" '
156 . 'onclick="BX.calendar({node:this, field: this.previousSibling, bTime: %s, bHideTime: %s});" '
157 . 'onmouseover="BX.addClass(this, \'calendar-icon-hover\');" '
158 . 'onmouseout="BX.removeClass(this, \'calendar-icon-hover\');" border="0"/>',
159 htmlspecialcharsbx($name),
160 htmlspecialcharsbx($value),
161 $isPublicControl ? htmlspecialcharsbx($className) : '',
162 static::getType() == FieldType::DATETIME ? 'true' : 'false',
163 static::getType() == FieldType::DATETIME ? 'false' : 'true'
164 );
165
166 $tzName = 'tz_'.$name;
167 $zones = self::getZones();
168
169 if (!$offset && $renderMode & FieldType::RENDER_MODE_PUBLIC)
170 {
171 $offset = 'current';
172 }
173
174 $tzClassName = 'bizproc-type-control-date-lc';
175 if ($fieldType->isMultiple())
176 {
177 $tzClassName .= ' bizproc-type-control-date-lc-multiple';
178 }
179 if (!$isPublicControl)
180 {
181 $tzClassName = '';
182 }
183
184 $renderResult .= '<select name="'.htmlspecialcharsbx($tzName).'" class="'.$tzClassName.'">';
185 foreach ($zones as $zone)
186 {
187 $selected = ($offset && $offset === $zone['offset']) ? 'selected' : '';
188 $renderResult .= '<option value="'.htmlspecialcharsbx($zone['value']).'" '.$selected.'>'
189 .htmlspecialcharsbx($zone['text']).'</option>';
190 }
191 $renderResult .= '</select>';
192
193 if ($fieldType->isMultiple())
194 {
195 $settings = $fieldType->getSettings();
196 $settings['timezones'] = $zones;
197 $fieldType->setSettings($settings);
198 }
199 }
200
201 return $renderResult;
202 }
203
212 public static function renderControlSingle(FieldType $fieldType, array $field, $value, $allowSelection, $renderMode)
213 {
214 $allowSelectionOrig = $allowSelection;
215 if ($renderMode & FieldType::RENDER_MODE_PUBLIC)
216 {
217 $allowSelection = false;
218 }
219
220 $value = static::toSingleValue($fieldType, $value);
221 $selectorValue = null;
222
223 if ($allowSelection && \CBPActivity::isExpression($value))
224 {
225 $selectorValue = $value;
226 $value = null;
227 }
228
229 $renderResult = static::renderControl($fieldType, $field, $value, $allowSelectionOrig, $renderMode);
230
231 if ($allowSelection)
232 {
233 $renderResult .= static::renderControlSelector($field, $selectorValue, true, '', $fieldType);
234 }
235
236 return $renderResult;
237 }
238
239 public static function renderControlMultiple(FieldType $fieldType, array $field, $value, $allowSelection, $renderMode)
240 {
241 $allowSelectionOrig = $allowSelection;
242 if ($renderMode & FieldType::RENDER_MODE_PUBLIC)
243 {
244 $allowSelection = false;
245 }
246
247 if (!is_array($value) || is_array($value) && \CBPHelper::isAssociativeArray($value))
248 {
249 $value = array($value);
250 }
251
252 $selectorValue = null;
253 if ($allowSelection)
254 {
255 foreach ($value as $k => $v)
256 {
257 if (\CBPActivity::isExpression($v))
258 {
259 $selectorValue = $v;
260 unset($value[$k]);
261 }
262 }
263 $value = array_values($value);
264 }
265
266 if (empty($value))
267 {
268 $value[] = null;
269 }
270
271 $controls = [];
272
273 foreach ($value as $k => $v)
274 {
275 $singleField = $field;
276 $singleField['Index'] = $k;
277 $controls[] = static::renderControl(
278 $fieldType,
279 $singleField,
280 $v,
281 $allowSelectionOrig,
282 $renderMode
283 );
284 }
285
286 if ($renderMode & FieldType::RENDER_MODE_PUBLIC)
287 {
288 $renderResult = static::renderPublicMultipleWrapper($fieldType, $field, $controls);
289 }
290 else
291 {
292 $renderResult = static::wrapCloneableControls($controls, static::generateControlName($field));
293 }
294
295 if ($allowSelection)
296 {
297 $renderResult .= static::renderControlSelector($field, $selectorValue, true, '', $fieldType);
298 }
299
300 return $renderResult;
301 }
302
303
308 public static function canRenderControl($renderMode)
309 {
310 return true;
311 }
312
319 protected static function extractValue(FieldType $fieldType, array $field, array $request)
320 {
321 $value = parent::extractValue($fieldType, $field, $request);
322
323 if ($value !== null && is_string($value) && $value <> '')
324 {
325 if (\CBPActivity::isExpression($value))
326 return $value;
327
328 $format = static::getType() == FieldType::DATETIME ? \FORMAT_DATETIME : \FORMAT_DATE;
329 if(!\CheckDateTime($value, $format))
330 {
331 $value = null;
332 static::addError(array(
333 'code' => 'ErrorValue',
334 'message' => Loc::getMessage('BPDT_DATE_INVALID'),
335 'parameter' => static::generateControlName($field),
336 ));
337 }
338 else
339 {
340 $tzOffset = self::extractOffset($field, $request);
341 $value = (static::getType() == FieldType::DATETIME) ?
342 new Value\DateTime($value, $tzOffset) : new Value\Date($value, $tzOffset);
343
344 //have to serialize in design time.
345 $value = $value->serialize();
346 }
347 }
348 else
349 {
350 $value = null;
351 }
352
353 return $value;
354 }
355
356 private static function extractOffset(array $field, array $request)
357 {
358 $tzName = 'tz_'.$field['Field'];
359 $tz = isset($request[$tzName]) ? $request[$tzName] : null;
360 if (is_array($tz))
361 {
362 $tz = isset($field['Index']) ? $tz[$field['Index']] : $tz[0];
363 }
364
365 if ($tz === 'current')
366 {
367 return \CTimeZone::GetOffset();
368 }
369 elseif ($tz)
370 {
371 $localTime = new \DateTime();
372 $localOffset = $localTime->getOffset();
373
374 $userTime = new \DateTime(null, new \DateTimeZone($tz));
375 $userOffset = $userTime->getOffset();
376
377 return $userOffset - $localOffset;
378 }
379
380 return 0;
381 }
382
387 public static function getFormats()
388 {
389 $formats = parent::getFormats();
390 $formats['server'] = [
391 'callable' => 'formatValueServer',
392 'separator' => ', ',
393 ];
394
395 $formats['author'] = $formats['responsible'] = [
396 'callable' => 'formatValueAuthor',
397 'separator' => ', ',
398 ];
399
400 return $formats;
401 }
402
408 protected static function formatValueServer(FieldType $fieldType, $value)
409 {
410 if ($value instanceof Value\Date)
411 {
412 return date($value->getFormat(), $value->getTimestamp());
413 }
414
415 return $value;
416 }
417
423 protected static function formatValueAuthor(FieldType $fieldType, $value)
424 {
425 if ($value instanceof Value\Date)
426 {
427 $documentId = $fieldType->getDocumentId();
428
429 if ($documentId)
430 {
431 $userId = \CBPHelper::ExtractUsers(['author', 'responsible'], $documentId, true);
432 $offset = $userId ? \CTimeZone::GetOffset($userId, true) : 0;
433
434 $value = new Value\DateTime($value->getTimestamp(), $offset);
435 }
436
437 return (string) $value;
438 }
439
440 return $value;
441 }
442
443 public static function internalizeValue(FieldType $fieldType, $context, $value)
444 {
445 if ($value && is_string($value))
446 {
447 $offset = \CTimeZone::GetOffset();
448 try
449 {
450 $obj = (static::getType() === FieldType::DATE)
451 ? new Value\Date($value, $offset)
452 : new Value\DateTime($value, $offset);
453 //set value if everything is ok
454 if ($obj->getTimestamp() !== null)
455 {
456 $value = $obj;
457 }
458 }
459 catch(Main\ObjectException $e)
460 {
461 }
462 }
463 else if ($value instanceof Type\Date)
464 {
465 return (static::getType() === FieldType::DATE)
466 ? Value\Date::fromSystemObject($value)
467 : Value\DateTime::fromSystemObject($value);
468 }
469
470 return $value;
471 }
472
473 public static function externalizeValue(FieldType $fieldType, $context, $value)
474 {
475 if ($context === FieldType::VALUE_CONTEXT_JN_MOBILE)
476 {
477 return \CBPHelper::makeTimestamp($value) ?: null;
478 }
479
480 //serialized date string
481 if (is_string($value) && preg_match('#(.+)\s\[([0-9\-]+)\]#', $value))
482 {
483 $value = static::internalizeValue($fieldType, $context, $value);
484 }
485
486 if ($value instanceof Value\Date)
487 {
488 return $context === FieldType::VALUE_CONTEXT_REST ? $value->toSystemObject()->format('c') : (string) $value->toSystemObject();
489 }
490
491 if (is_string($value) && $context === FieldType::VALUE_CONTEXT_REST)
492 {
493 return date('c', strtotime($value));
494 }
495
496 return $value;
497 }
498
499 private static function getZones()
500 {
501 $serverOffset = (new \DateTime())->getOffset();
502
503 $timezones = [];
504 $exclude = ["Etc/", "GMT", "UTC", "UCT", "HST", "PST", "MST", "CST", "EST", "CET", "MET", "WET", "EET", "PRC", "ROC", "ROK", "W-SU"];
505 foreach (\DateTimeZone::listIdentifiers() as $tz)
506 {
507 foreach ($exclude as $ex)
508 if (mb_strpos($tz, $ex) === 0)
509 continue 2;
510 try
511 {
512 $dateTimeZone = new \DateTimeZone($tz);
513 $timezones[$tz] = ['timezone_id' => $tz, 'offset' => $dateTimeZone->getOffset(new \DateTime("now", $dateTimeZone))];
514 } catch (\Exception $e)
515 {
516 }
517 }
518
519 uasort($timezones, function ($a, $b)
520 {
521 if ($a['offset'] == $b['offset'])
522 return strcmp($a['timezone_id'], $b['timezone_id']);
523
524 return ($a['offset'] < $b['offset'] ? -1 : 1);
525 });
526
527 $result = [
528 ['value' => '', 'text' => Loc::getMessage('BPDT_DATE_SERVER_TZ'), 'offset' => 0],
529 ['value' => 'current', 'text' => Loc::getMessage('BPDT_DATE_CURRENT_TZ'), 'offset' => 'current']
530 ];
531 foreach ($timezones as $z)
532 {
533 $result[] = [
534 'value' => $z['timezone_id'],
535 'text' => '(UTC'.($z['offset'] <> 0 ? ' '.($z['offset'] < 0 ? '-' : '+').sprintf("%02d", ($h = floor(abs($z['offset']) / 3600))).':'.sprintf("%02d", abs($z['offset']) / 60 - $h * 60) : '').') '.$z['timezone_id'],
536 'offset' => $z['offset'] - $serverOffset
537 ];
538 }
539
540 return $result;
541 }
542
543 public static function compareValues($valueA, $valueB)
544 {
545 $valueA = \CBPHelper::makeTimestamp($valueA);
546 $valueB = \CBPHelper::makeTimestamp($valueB);
547
548 return parent::compareValues($valueA, $valueB);
549 }
550}
static convertTo(FieldType $fieldType, $value, $toTypeClass)
Definition base.php:209
static formatValueAuthor(FieldType $fieldType, $value)
Definition date.php:423
static renderControl(FieldType $fieldType, array $field, $value, $allowSelection, $renderMode)
Definition date.php:115
static extractValue(FieldType $fieldType, array $field, array $request)
Definition date.php:319
static externalizeValue(FieldType $fieldType, $context, $value)
Definition date.php:473
static renderControlSingle(FieldType $fieldType, array $field, $value, $allowSelection, $renderMode)
Definition date.php:212
static internalizeValue(FieldType $fieldType, $context, $value)
Definition date.php:443
static toSingleValue(FieldType $fieldType, $value)
Definition date.php:32
static renderControlMultiple(FieldType $fieldType, array $field, $value, $allowSelection, $renderMode)
Definition date.php:239
static compareValues($valueA, $valueB)
Definition date.php:543
static canRenderControl($renderMode)
Definition date.php:308
static formatValueServer(FieldType $fieldType, $value)
Definition date.php:408
setSettings(array $settings)
static loadMessages($file)
Definition loc.php:64
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29