Bitrix-D7 22.2
Загрузка...
Поиск...
Не найдено
input.php
См. документацию.
1<?php
2
4
12
13Loc::loadMessages(__FILE__);
14
15// TODO integrate with input.js on adding multiple item
17{
18 static function initJs()
19 {
20 static $done = false;
21
22 if (! $done)
23 {
24 $done = true;
25
26 if (Loader::includeModule('location'))
27 {
28 \Bitrix\Main\UI\Extension::load('sale.address');
29 }
30
31 \CJSCore::RegisterExt('input', array(
32 'js' => [
33 '/bitrix/js/sale/input.js'
34 ],
35 'lang' => '/bitrix/modules/sale/lang/'.LANGUAGE_ID.'/lib/internals/input.php',
36 ));
37 \CJSCore::Init(array('input'));
38
39 print('<div style="display:none">');
40 $GLOBALS['APPLICATION']->IncludeComponent("bitrix:sale.location.selector.".\Bitrix\Sale\Location\Admin\LocationHelper::getWidgetAppearance(), "", array(
41 "ID" => '',
42 "CODE" => '',
43 "INPUT_NAME" => 'SALE_LOCATION_SELECTOR_RESOURCES',
44 "PROVIDE_LINK_BY" => 'code',
45
46 "FILTER_BY_SITE" => 'Y',
47
48 "SHOW_DEFAULT_LOCATIONS" => 'Y',
49 "SEARCH_BY_PRIMARY" => 'Y',
50
51 "JS_CONTROL_GLOBAL_ID" => 'SALE_LOCATION_SELECTOR_RESOURCES',
52 //"INITIALIZE_BY_GLOBAL_EVENT" => 'sale-event-never-happen',
53 "USE_JS_SPAWN" => 'Y'
54 ),
55 false,
56 array('HIDE_ICONS' => 'Y')
57 );
58 print('</div>');
59 }
60 }
61
62 protected static $types = array();
63
70 static function getViewHtml(array $input, $value = null)
71 {
72 if (! static::$initialized)
73 static::initialize();
74
75 if ($type = static::$types[$input['TYPE']])
76 return call_user_func(array($type['CLASS'], __FUNCTION__), $input, $value);
77 else
78 throw new SystemException('invalid input type in '.print_r($input, true), 0, __FILE__, __LINE__);
79 }
80
88 static function getEditHtml($name, array $input, $value = null)
89 {
90 if (! static::$initialized)
91 static::initialize();
92
93 if ($type = static::$types[$input['TYPE']])
94 return call_user_func(array($type['CLASS'], __FUNCTION__), $name, $input, $value);
95 else
96 throw new SystemException('invalid input type in '.print_r($input, true), 0, __FILE__, __LINE__);
97 }
98
106 static function getFilterEditHtml($name, array $input, $value = null)
107 {
108 if (! static::$initialized)
109 static::initialize();
110
111 if ($type = static::$types[$input['TYPE']])
112 return call_user_func(array($type['CLASS'], __FUNCTION__), $name, $input, $value);
113 else
114 throw new SystemException('invalid input type in '.print_r($input, true), 0, __FILE__, __LINE__);
115 }
116
123 static function getError(array $input, $value)
124 {
125 if (! static::$initialized)
126 static::initialize();
127
128 if ($type = static::$types[$input['TYPE']])
129 return call_user_func(array($type['CLASS'], __FUNCTION__), $input, $value);
130 else
131 throw new SystemException('invalid input type in '.print_r($input, true), 0, __FILE__, __LINE__);
132 }
133
141 static function getRequiredError(array $input, $value)
142 {
143 if (! static::$initialized)
144 static::initialize();
145
146 if ($type = static::$types[$input['TYPE']])
147 {
148 return call_user_func(array($type['CLASS'], __FUNCTION__), $input, $value);
149 }
150 else
151 {
152 throw new SystemException('invalid input type in '.print_r($input, true), 0, __FILE__, __LINE__);
153 }
154 }
155
163 static function getValue(array $input, $value)
164 {
165 if (! static::$initialized)
166 static::initialize();
167
168 if ($type = static::$types[$input['TYPE']])
169 return call_user_func(array($type['CLASS'], __FUNCTION__), $input, $value);
170 else
171 throw new SystemException('invalid input type in '.print_r($input, true), 0, __FILE__, __LINE__);
172 }
173
180 static function asMultiple(array $input, $value)
181 {
182 if (! static::$initialized)
183 static::initialize();
184
185 if ($type = static::$types[$input['TYPE']])
186 return call_user_func(array($type['CLASS'], __FUNCTION__), $value);
187 else
188 throw new SystemException('invalid input type in '.print_r($input, true), 0, __FILE__, __LINE__);
189 }
190
197 static function getSettings(array $input, $reload = null)
198 {
199 if (! static::$initialized)
200 static::initialize();
201
202 if ($type = static::$types[$input['TYPE']])
203 return call_user_func(array($type['CLASS'], __FUNCTION__), $input, $reload);
204 else
205 throw new SystemException('invalid input type in '.print_r($input, true), 0, __FILE__, __LINE__);
206 }
207
213 static function getCommonSettings(array $input, $reload = null)
214 {
215 if (! static::$initialized)
216 static::initialize();
217
218 $typeOptions = array();
219
220 foreach (static::$types as $k => $v)
221 {
222 if (in_array($k, ['PRODUCT_CATEGORIES', 'CONCRETE_PRODUCT']))
223 {
224 continue;
225 }
226
227 $typeOptions[$k] = $v['NAME']." [$k]";
228 }
229
230 $hasMultipleSupport = true;
231 if (isset(static::$types[$input['TYPE']]))
232 {
234 $typeClass = static::$types[$input['TYPE']]['CLASS'];
235
236 if (!$typeClass::hasMultipleValuesSupport())
237 {
238 $hasMultipleSupport = false;
239 }
240 }
241
242 $multiple = array('TYPE' => 'Y/N' , 'LABEL' => Loc::getMessage('INPUT_MULTIPLE'));
243
244 if (!$hasMultipleSupport)
245 {
246 $multiple['DISABLED_YN'] = 'N';
247 }
248 else
249 {
250 $multiple['ONCLICK'] = $reload;
251 }
252
253 $result = [
254 'TYPE' => array('TYPE' => 'ENUM', 'LABEL' => Loc::getMessage('INPUT_TYPE'), 'OPTIONS' => $typeOptions, 'REQUIRED' => 'Y', 'ONCHANGE' => $reload),
255 'REQUIRED' => array('TYPE' => 'Y/N' , 'LABEL' => Loc::getMessage('INPUT_REQUIRED')),
256 'MULTIPLE' => $multiple,
257 'VALUE' => array('LABEL' => Loc::getMessage('INPUT_VALUE'), 'REQUIRED' => 'N') + $input,
258 ];
259
260 return $result;
261 }
262
266 static function getTypes()
267 {
268 if (! static::$initialized)
269 static::initialize();
270
271 return static::$types;
272 }
273
282 static function register($name, array $type)
283 {
284 if (isset(static::$types[$name]))
285 {
286 throw new SystemException('duplicate type '.$name, 0, __FILE__, __LINE__);
287 }
288
289 if (! class_exists($type['CLASS']))
290 {
291 throw new SystemException('undefined CLASS in '.print_r($type, true), 0, __FILE__, __LINE__);
292 }
293
294 if (! is_subclass_of($type['CLASS'], __NAMESPACE__.'\Base'))
295 {
296 throw new SystemException($type['CLASS'].' does not implement Input\Base', 0, __FILE__, __LINE__);
297 }
298
299 static::$types[$name] = $type;
300 }
301
302 protected static $initialized;
303
304 protected static function initialize()
305 {
306 static::$initialized = true;
307
309 $event = new Event('sale', 'registerInputTypes', static::$types);
310 $event->send();
311
312 if ($event->getResults())
313 {
314 foreach($event->getResults() as $eventResult)
315 {
316 if ($eventResult->getType() != EventResult::SUCCESS)
317 continue;
318
319 if ($params = $eventResult->getParameters())
320 {
321 if(!empty($params) && is_array($params))
322 {
323 static::$types = array_merge(static::$types, $params);
324 }
325 }
326 }
327 }
328 }
329}
330
331abstract class Base
332{
333 const MULTITAG = 'div';
334
339 static function isMultiple($value)
340 {
341 return is_array($value);
342 }
343
348 static function asSingle($value)
349 {
350 if (static::isMultiple($value))
351 {
352 $v = null;
353
354 foreach ($value as $v)
355 if ($v) // !== null) TODO maybe??
356 break;
357
358 return $v;
359 }
360 else
361 {
362 return $value;
363 }
364 }
365
366 static function asMultiple($value)
367 {
368 if (static::isMultiple($value))
369 {
370 return array_diff($value, array("", NULL, false));
371 }
372 else
373 {
374 return $value === null ? array() : array($value);
375 }
376 }
377
378 public static function getViewHtml(array $input, $value = null)
379 {
380 if ($value === null)
381 $value = $input['VALUE'];
382
383 if ($input['MULTIPLE'] == 'Y')
384 {
385 $tag = isset($input['MULTITAG']) ? htmlspecialcharsbx($input['MULTITAG']) : static::MULTITAG;
386 [$startTag, $endTag] = $tag ? array("<$tag>", "</$tag>") : array('', '');
387
388 $html = '';
389
390 foreach (static::asMultiple($value) as $value)
391 $html .= $startTag.static::getViewHtmlSingle($input, $value).$endTag;
392
393 return $html;
394 }
395 else
396 {
397 return static::getViewHtmlSingle($input, static::asSingle($value));
398 }
399 }
400
401 public static function getViewHtmlSingle(array $input, $value)
402 {
403 $output = $valueText = htmlspecialcharsbx($value);
404 if ($input['IS_EMAIL'] == 'Y')
405 {
406 $output = '<a href="mailto:'.$valueText.'">'.$valueText.'</a>';
407 }
408
409 return $output;
410 }
411
412 public static function getEditHtml($name, array $input, $value = null)
413 {
414 $name = htmlspecialcharsbx($name);
415
416 if ($value === null)
417 $value = $input['VALUE'];
418
419 $html = '';
420
421 if ($input['HIDDEN'] == 'Y')
422 {
423 $html .= static::getHiddenRecursive($name
424 , $input['MULTIPLE'] == 'Y' ? static::asMultiple($value) : static::asSingle($value)
425 , static::extractAttributes($input, array('DISABLED'=>''), array('FORM'=>''), false));
426 }
427 else
428 {
429 if ($input['MULTIPLE'] == 'Y')
430 {
431 $tag = isset($input['MULTITAG']) ? htmlspecialcharsbx($input['MULTITAG']) : static::MULTITAG;
432 [$startTag, $endTag] = $tag ? array("<$tag>", "</$tag>") : array('', '');
433
434 $index = -1;
435
436 foreach (static::asMultiple($value) as $value)
437 {
438 $namix = $name.'['.(++$index).']';
439 $html .= $startTag
440 .static::getEditHtmlSingle($namix, $input, $value)
441 .static::getEditHtmlSingleDelete($namix, $input)
442 .$endTag;
443 }
444
445 $replace = '##INPUT##NAME##';
446
447 if ($input['DISABLED'] !== 'Y') // TODO
448 $html .= static::getEditHtmlInsert($tag, $replace, $name
449 , static::getEditHtmlSingle($replace, $input, null).static::getEditHtmlSingleDelete($replace, $input)
450 , static::getEditHtmlSingleAfterInsert());
451 }
452 else
453 {
454 $html .= static::getEditHtmlSingle($name, $input, static::asSingle($value));
455 }
456 }
457
458 if ($input['ADDITIONAL_HIDDEN'] === 'Y')
459 {
460 $html .= static::getHiddenRecursive($name
461 , $input['MULTIPLE'] == 'Y' ? static::asMultiple($value) : static::asSingle($value)
462 , static::extractAttributes($input, array(), array('FORM'=>''), false));
463 }
464
465 return $html;
466 }
467
469 public static function getEditHtmlSingle($name, array $input, $value)
470 {
471 throw new SystemException("you must implement [getEditHtmlSingle] or override [getEditHtml] in yor class", 0, __FILE__, __LINE__);
472 }
473
474 public static function getEditHtmlSingleDelete($name, array $input)
475 {
476 return '<label> '.Loc::getMessage('INPUT_DELETE').' <input type="checkbox" onclick="'
477
478 ."this.parentNode.previousSibling.disabled = this.checked;"
479
480 .'"> </label>';
481 }
482
483 public static function getEditHtmlInsert($tag, $replace, $name, $sample, $after)
484 {
485 $name = \CUtil::JSEscape($name);
486 $sample = \CUtil::JSEscape(htmlspecialcharsbx($sample));
487
488 return '<input type="button" value="'.Loc::getMessage('INPUT_ADD').'" onclick="'
489
490 ."var parent = this.parentNode;"
491 ."var container = document.createElement('$tag');"
492 ."container.innerHTML = '$sample'.replace(/$replace/g, '{$name}['+parent.childNodes.length+']');"
493 ."parent.insertBefore(container, this);"
494
495 .$after.'">';
496 }
497
498 public static function getEditHtmlSingleAfterInsert()
499 {
500 return "container.firstChild.focus();";
501 }
502
503 public static function getError(array $input, $value)
504 {
505 $errors = array();
506 if ($value === null)
507 $value = $input['VALUE'];
508
509 if ($input['MULTIPLE'] == 'Y')
510 {
511
512 $index = -1;
513
514 foreach (static::asMultiple($value) as $value)
515 {
516 if (($value !== '' && $value !== null) && ($error = static::getErrorSingle($input, $value)))
517 {
518 $errors[++$index] = $error;
519 }
520 }
521 }
522 else
523 {
524 $value = static::asSingle($value);
525
526 if ($value !== '' && $value !== null)
527 {
528 return static::getErrorSingle($input, $value);
529 }
530 }
531
532 return $errors;
533 }
534
541 public static function getRequiredError(array $input, $value)
542 {
543 $errors = array();
544
545 if ($value === null)
546 $value = $input['VALUE'];
547
548 if ($input['MULTIPLE'] == 'Y')
549 {
550 $index = -1;
551 foreach (static::asMultiple($value) as $value)
552 {
553 if ($value === '' || $value === null)
554 {
555 if ($input['REQUIRED'] == 'Y')
556 $errors[++$index] = array('REQUIRED' => Loc::getMessage('INPUT_REQUIRED_ERROR'));
557 }
558 }
559 }
560 else
561 {
562 $value = static::asSingle($value);
563
564 if ($value === '' || $value === null)
565 {
566 return ($input['REQUIRED'] == 'Y')
567 ? array('REQUIRED' => Loc::getMessage('INPUT_REQUIRED_ERROR'))
568 : array();
569 }
570 }
571
572 return $errors;
573 }
574
581 public static function getErrorSingle(array $input, $value)
582 {
583 throw new SystemException("you must implement [getErrorSingle] or override [getError] in yor class", 0, __FILE__, __LINE__);
584 }
585
586 public static function getValue(array $input, $value)
587 {
588 if ($input['DISABLED'] == 'Y')
589 return null; // TODO maybe??
590
591 if ($value === null)
592 $value = $input['VALUE'];
593
594 if ($input['MULTIPLE'] == 'Y')
595 {
596 $values = array();
597
598 foreach (static::asMultiple($value) as $value)
599 {
600 $value = static::getValueSingle($input, $value);
601 if ($value !== null)
602 $values []= $value;
603 }
604
605 return $values ? $values : null;
606 }
607 else
608 {
609 return static::getValueSingle($input, static::asSingle($value));
610 }
611 }
612
613 public static function getValueSingle(array $input, $value)
614 {
615 return $value;
616 }
617
618 public static function getSettings(array $input, $reload)
619 {
620 return array(); // no settings
621 }
622
623 // utils
624
625 protected static function getHiddenRecursive($name, $value, $attributes)
626 {
627 if (is_array($value))
628 {
629 $html = '';
630
631 foreach ($value as $k => $v)
632 $html .= self::getHiddenRecursive($name.'['.htmlspecialcharsbx($k).']', $v, $attributes);
633
634 return $html;
635 }
636 else
637 {
638 return '<input type="hidden" name="'.$name.'" value="'.htmlspecialcharsbx($value).'"'.$attributes.'>';
639 }
640 }
641
643 protected static function extractAttributes(array $input, array $boolean, array $other, $withGlobal = true)
644 {
645 $string = '';
646
647 // add boolean attributes with predefined values or no value
648
649 unset($boolean['REQUIRED']); // TODO remove with HTML5
650
651 static $globalBoolean = array('CONTENTEDITABLE'=>'', 'DRAGGABLE'=>'true', 'SPELLCHECK'=>'', 'TRANSLATE'=>'yes');
652
653 if ($withGlobal)
654 $boolean = $globalBoolean + $boolean;
655
656 foreach (array_intersect_key($input, $boolean) as $k => $v)
657 if ($v === 'Y' || $v === true)
658 $string .= ' '.mb_strtolower($k).($boolean[$k] ? '="'.$boolean[$k].'"' : '');
659
660 // add event attributes with values
661 if ($withGlobal)
662 {
663 static $globalEvents = array(
664 'ONABORT'=>1, 'ONBLUR'=>1, 'ONCANPLAY'=>1, 'ONCANPLAYTHROUGH'=>1, 'ONCHANGE'=>1, 'ONCLICK'=>1,
665 'ONCONTEXTMENU'=>1, 'ONDBLCLICK'=>1, 'ONDRAG'=>1, 'ONDRAGEND'=>1, 'ONDRAGENTER'=>1, 'ONDRAGLEAVE'=>1,
666 'ONDRAGOVER'=>1, 'ONDRAGSTART'=>1, 'ONDROP'=>1, 'ONDURATIONCHANGE'=>1, 'ONEMPTIED'=>1, 'ONENDED'=>1,
667 'ONERROR'=>1, 'ONFOCUS'=>1, 'ONINPUT'=>1, 'ONINVALID'=>1, 'ONKEYDOWN'=>1, 'ONKEYPRESS'=>1, 'ONKEYUP'=>1,
668 'ONLOAD'=>1, 'ONLOADEDDATA'=>1, 'ONLOADEDMETADATA'=>1, 'ONLOADSTART'=>1, 'ONMOUSEDOWN'=>1, 'ONMOUSEMOVE'=>1,
669 'ONMOUSEOUT'=>1, 'ONMOUSEOVER'=>1, 'ONMOUSEUP'=>1, 'ONMOUSEWHEEL'=>1, 'ONPAUSE'=>1, 'ONPLAY'=>1,
670 'ONPLAYING'=>1, 'ONPROGRESS'=>1, 'ONRATECHANGE'=>1, 'ONREADYSTATECHANGE'=>1, 'ONRESET'=>1, 'ONSCROLL'=>1,
671 'ONSEEKED'=>1, 'ONSEEKING'=>1, 'ONSELECT'=>1, 'ONSHOW'=>1, 'ONSTALLED'=>1, 'ONSUBMIT'=>1, 'ONSUSPEND'=>1,
672 'ONTIMEUPDATE'=>1, 'ONVOLUMECHANGE'=>1, 'ONWAITING'=>1,
673 );
674
675 $events = array_intersect_key($input, $globalEvents);
676 $other = array_diff_key($other, $events);
677
678 foreach ($events as $k => $v)
679 if ($v)
680 $string .= ' '.mb_strtolower($k).'="'.$v.'"';
681 }
682
683 // add other attributes with values
684
685 static $globalOther = array(
686 'ACCESSKEY'=>1, 'CLASS'=>1, 'CONTEXTMENU'=>1, 'DIR'=>1, 'DROPZONE'=>1, 'LANG'=>1, 'STYLE'=>1, 'TABINDEX'=>1,
687 'TITLE'=>1, 'ID' => 1,
688 'XML:LANG'=>1, 'XML:SPACE'=>1, 'XML:BASE'=>1
689 );
690
691 if ($withGlobal)
692 $other += $globalOther;
693
694 foreach (array_intersect_key($input, $other) as $k => $v)
695 if ($v)
696 $string .= ' '.mb_strtolower($k).'="'.htmlspecialcharsbx($v).'"';
697
698 // add data attributes
699 if ($withGlobal && is_array($input['DATA']))
700 {
701 foreach ($input['DATA'] as $k => $v)
702 $string .= ' data-'.htmlspecialcharsbx($k).'="'.htmlspecialcharsbx($v).'"';
703 }
704
705 return $string;
706 }
707
711 public static function hasMultipleValuesSupport()
712 {
713 return true;
714 }
715}
716
720class StringInput extends Base // String reserved in php 7
721{
722 protected static $patternDelimiters = array('/', '#', '~');
723
724 public static function getEditHtmlSingle($name, array $input, $value)
725 {
726 $input = self::prepareIntFields($input);
727 if ($input['MULTILINE'] == 'Y')
728 {
729 $attributes = static::extractAttributes($input,
730 array('DISABLED'=>'', 'READONLY'=>'', 'AUTOFOCUS'=>'', 'REQUIRED'=>''),
731 array('FORM'=>1, 'MAXLENGTH'=>1, 'PLACEHOLDER'=>1, 'DIRNAME'=>1, 'ROWS'=>1, 'COLS'=>1, 'WRAP'=>1));
732
733 return '<textarea name="'.$name.'"'.$attributes.'>'.htmlspecialcharsbx($value).'</textarea>';
734 }
735 else
736 {
737 $attributes = static::extractAttributes($input,
738 array('DISABLED'=>'', 'READONLY'=>'', 'AUTOFOCUS'=>'', 'REQUIRED'=>'', 'AUTOCOMPLETE'=>'on'),
739 array('FORM'=>1, 'MAXLENGTH'=>1, 'PLACEHOLDER'=>1, 'DIRNAME'=>1, 'SIZE'=>1, 'LIST'=>1));
740
741 return '<input type="text" name="'.$name.'" value="'.htmlspecialcharsbx($value).'"'.$attributes.'>';
742 }
743 }
744
745 private static function prepareIntFields(array $input): array
746 {
747 $intFields = ['SIZE', 'ROWS', 'COLS'];
748 foreach ($intFields as $intField)
749 {
750 $input[$intField] = (int)($input['$intField'] ?? 0);
751 if ($input[$intField] <= 0)
752 {
753 unset($input[$intField]);
754 }
755 }
756
757 return $input;
758 }
759
766 public static function getFilterEditHtml($name, array $input, $value)
767 {
768 return static::getEditHtmlSingle($name, $input, $value);
769 }
770
771 public static function getErrorSingle(array $input, $value)
772 {
773 $errors = array();
774
775 $value = trim($value);
776
777 $minLength = isset($input['MINLENGTH']) && is_numeric($input['MINLENGTH']) ? (int)$input['MINLENGTH'] : 0;
778 if ($minLength > 0 && mb_strlen($value) < $minLength)
779 {
780 $errors['MINLENGTH'] = Loc::getMessage('INPUT_STRING_MINLENGTH_ERROR', ['#NUM#' => $minLength]);
781 }
782
783 $maxLength = isset($input['MAXLENGTH']) && is_numeric($input['MAXLENGTH']) ? (int)$input['MAXLENGTH'] : 0;
784 if ($maxLength > 0 && mb_strlen($value) > $maxLength)
785 {
786 $errors['MAXLENGTH'] = Loc::getMessage('INPUT_STRING_MAXLENGTH_ERROR', ['#NUM#' => $maxLength]);
787 }
788
789 if (strval(trim($input['PATTERN'])) != "")
790 {
791 $issetDelimiter = false;
792 $pattern = trim($input['PATTERN']);
793
794 if (isset($pattern[0]) && in_array($pattern[0], static::$patternDelimiters) && mb_strrpos($pattern, $pattern[0]) !== false)
795 {
796 $issetDelimiter = true;
797 }
798
799 $matchPattern = $pattern;
800 if (!$issetDelimiter)
801 {
802 $matchPattern = "/".$pattern."/";
803 }
804
805 $pregMatchResult = null;
806 try
807 {
808 $pregMatchResult = preg_match($matchPattern, $value);
809 }
810 catch (\Exception $e)
811 {
812 }
813 finally
814 {
815 if (!$pregMatchResult)
816 {
817 $errors['PATTERN'] = Loc::getMessage('INPUT_STRING_PATTERN_ERROR');
818 }
819 }
820 }
821
822 return $errors;
823 }
824
825 static function getSettings(array $input, $reload)
826 {
827 $settings = array(
828 'MINLENGTH' => array('TYPE' => 'NUMBER', 'LABEL' => Loc::getMessage('INPUT_STRING_MINLENGTH'), 'MIN' => 0, 'STEP' => 1),
829 'MAXLENGTH' => array('TYPE' => 'NUMBER', 'LABEL' => Loc::getMessage('INPUT_STRING_MAXLENGTH'), 'MIN' => 0, 'STEP' => 1),
830 'PATTERN' => array('TYPE' => 'STRING', 'LABEL' => Loc::getMessage('INPUT_STRING_PATTERN' )),
831 'MULTILINE' => array('TYPE' => 'Y/N' , 'LABEL' => Loc::getMessage('INPUT_STRING_MULTILINE'), 'ONCLICK' => $reload),
832 );
833
834 if ($input['MULTILINE'] == 'Y')
835 {
836 $settings['COLS'] = array('TYPE' => 'NUMBER', 'LABEL' => Loc::getMessage('INPUT_STRING_SIZE'), 'MIN' => 0, 'STEP' => 1);
837 $settings['ROWS'] = array('TYPE' => 'NUMBER', 'LABEL' => Loc::getMessage('INPUT_STRING_ROWS'), 'MIN' => 0, 'STEP' => 1);
838 }
839 else
840 {
841 $settings['SIZE'] = array('TYPE' => 'NUMBER', 'LABEL' => Loc::getMessage('INPUT_STRING_SIZE'), 'MIN' => 0, 'STEP' => 1);
842 }
843
844 return $settings;
845 }
846
852 public static function isDeletedSingle($value)
853 {
854 return is_array($value) && $value['DELETE'];
855 }
856
857}
858
859Manager::register('STRING', array(
860 'CLASS' => __NAMESPACE__.'\StringInput',
861 'NAME' => Loc::getMessage('INPUT_STRING'),
862));
863
867class Number extends Base
868{
869 public static function getEditHtmlSingle($name, array $input, $value)
870 {
871 // TODO HTML5 from IE10: remove SIZE; Add MIN, MAX, STEP; Change type="number"
872
873 $size = 5;
874
875 if (($s = mb_strlen(strval($input['MIN']))) && $s > $size)
876 $size = $s;
877
878 if (($s = mb_strlen(strval($input['MAX']))) && $s > $size)
879 $size = $s;
880
881 if (($s = mb_strlen(strval($input['STEP']))) && $s > $size)
882 $size = $s;
883
884 $input['SIZE'] = $size;
885
886 $attributes = static::extractAttributes($input,
887 array('DISABLED'=>'', 'READONLY'=>'', 'AUTOFOCUS'=>'', 'REQUIRED'=>'', 'AUTOCOMPLETE'=>'on'),
888 array('FORM'=>1, 'LIST'=>1, 'PLACEHOLDER'=>1, 'SIZE'=>1));
889
890 return '<input type="text" name="'.$name.'" value="'.htmlspecialcharsbx($value).'"'.$attributes.'>';
891 }
892
899 public static function getFilterEditHtml($name, array $input, $value)
900 {
901 return static::getEditHtmlSingle($name, $input, $value);
902 }
903
904 public static function getErrorSingle(array $input, $value)
905 {
906 $errors = array();
907
908 if (is_numeric($value))
909 {
910 $value = (double) $value;
911
912 if (!empty($input['MIN']) && $value < $input['MIN'])
913 $errors['MIN'] = Loc::getMessage('INPUT_NUMBER_MIN_ERROR', array("#NUM#" => $input['MIN']));
914
915 if (!empty($input['MAX']) && $value > $input['MAX'])
916 $errors['MAX'] = Loc::getMessage('INPUT_NUMBER_MAX_ERROR', array("#NUM#" => $input['MAX']));
917
918 if ($input['STEP'])
919 {
920 $step = (double) $input['STEP'];
921
922 $value = (double) abs($value - ($input['MIN'] ? $input['MIN'] : 0.0));
923
924 if (! ($value / pow(2.0, 53) > $step))
925 {
926 $remainder = (double) abs($value - $step * round($value / $step));
927 $acceptableError = (double) ($step / pow(2.0, 24));
928
929 if ($acceptableError < $remainder && ($step - $acceptableError) > $remainder)
930 $errors['STEP'] = Loc::getMessage('INPUT_NUMBER_STEP_ERROR', array("#NUM#" => $input['STEP']));
931 }
932 }
933 }
934 else
935 {
936 $errors['NUMERIC'] = Loc::getMessage('INPUT_NUMBER_NUMERIC_ERROR');
937 }
938
939 return $errors;
940 }
941
942 public static function getSettings(array $input, $reload)
943 {
944 return array(
945 'MIN' => array('TYPE' => 'NUMBER', 'LABEL' => Loc::getMessage('INPUT_NUMBER_MIN' )),
946 'MAX' => array('TYPE' => 'NUMBER', 'LABEL' => Loc::getMessage('INPUT_NUMBER_MAX' )),
947 'STEP' => array('TYPE' => 'NUMBER', 'LABEL' => Loc::getMessage('INPUT_NUMBER_STEP')),
948 );
949 }
950}
951
952Manager::register('NUMBER', array(
953 'CLASS' => __NAMESPACE__.'\Number',
954 'NAME' => Loc::getMessage('INPUT_NUMBER'),
955));
956
960class EitherYN extends Base
961{
962 public static function getViewHtmlSingle(array $input, $value)
963 {
964 return $value == 'Y' ? Loc::getMessage('INPUT_EITHERYN_Y') : Loc::getMessage('INPUT_EITHERYN_N');
965 }
966
967 public static function getEditHtmlSingle($name, array $input, $value)
968 {
969 $hiddenAttributes = static::extractAttributes($input, array('DISABLED'=>''), array('FORM'=>1), false);
970 $checkboxAttributes = static::extractAttributes($input, array('DISABLED'=>'', 'AUTOFOCUS'=>'', 'REQUIRED'=>''), array('FORM'=>1));
971
972 if (isset($input['DISABLED_YN']))
973 {
974 return '<input type="hidden" name="'.$name.'" value="' . (($input['DISABLED_YN'] == 'Y') ? 'Y' : 'N') . '">'
975 .'<input type="checkbox" '.($input['DISABLED_YN'] == 'Y' ? ' checked' : '').'disabled'.'>';
976 }
977 else
978 {
979 return '<input type="hidden" name="'.$name.'" value="N"'.$hiddenAttributes.'>'
980 .'<input type="checkbox" name="'.$name.'" value="Y"'.($value == 'Y' ? ' checked' : '').$checkboxAttributes.'>';
981 }
982
983 }
984
991 public static function getFilterEditHtml($name, array $input, $value)
992 {
993 $hiddenAttributes = static::extractAttributes($input, array('DISABLED'=>''), array('FORM'=>1), false);
994
995 $checkboxAttributes = static::extractAttributes($input, array('DISABLED'=>'', 'AUTOFOCUS'=>'', 'REQUIRED'=>''), array('FORM'=>1));
996
997 return '<select name="'.$name.'" '.$hiddenAttributes.'>
998 <option value="">'.Loc::getMessage('INPUT_EITHERYN_ALL').'</option>
999 <option value="Y"'.($value=="Y" ? " selected" : '').' '.$checkboxAttributes.'>'.Loc::getMessage('INPUT_EITHERYN_Y').'</option>
1000 <option value="N"'.($value=="N" ? " selected" : '').' '.$checkboxAttributes.'>'.Loc::getMessage('INPUT_EITHERYN_N').'</option>
1001 </select>';
1002 }
1003
1004 public static function getErrorSingle(array $input, $value)
1005 {
1006 if ($input['REQUIRED'] == 'Y' && ($value === '' || $value === null))
1007 return array('REQUIRED' => Loc::getMessage('INPUT_REQUIRED_ERROR'));
1008
1009 return ($value == 'N' || $value == 'Y')
1010 ? array()
1011 : array('INVALID' => Loc::getMessage('INPUT_INVALID_ERROR'));
1012 }
1013
1014 public static function getValueSingle(array $input, $value)
1015 {
1016 return $value == 'Y' ? 'Y' : 'N';
1017 }
1018}
1019
1020Manager::register('Y/N', array(
1021 'CLASS' => __NAMESPACE__.'\EitherYN',
1022 'NAME' => Loc::getMessage('INPUT_EITHERYN'),
1023));
1024
1028class Enum extends Base
1029{
1030 private static function flatten(array $array)
1031 {
1032 $result = array();
1033
1034 foreach ($array as $key => $value)
1035 {
1036 if (is_array($value))
1037 {
1038 $result = $result + $value;
1039 }
1040 else
1041 {
1042 $result[$key] = $value;
1043 }
1044 }
1045
1046 return $result;
1047 }
1048
1049 public static function getViewHtmlSingle(array $input, $value) // TODO optimize to getViewHtml
1050 {
1051 $options = $input['OPTIONS'];
1052
1053 if (is_array($options))
1054 {
1055 $options = self::flatten($options);
1056
1057 if ($v = $options[$value])
1058 $value = $v;
1059 }
1060
1061 return htmlspecialcharsbx($value);
1062 }
1063
1070 public static function getFilterEditHtml($name, array $input, $value)
1071 {
1072 return static::getEditHtml($name, $input, $value);
1073 }
1074
1075 public static function getEditHtml($name, array $input, $value = null)
1076 {
1077 $options = $input['OPTIONS'];
1078
1079 if (! is_array($options))
1080 return Loc::getMessage('INPUT_ENUM_OPTIONS_ERROR');
1081
1082 $multiple = $input['MULTIPLE'] == 'Y';
1083
1084 $name = htmlspecialcharsbx($name);
1085
1086 if ($value === null && isset($input['VALUE']))
1087 $value = $input['VALUE'];
1088
1089 $originalValue = $value;
1090 $html = '';
1091
1092 if ($input['HIDDEN'] == 'Y')
1093 {
1094 $html .= static::getHiddenRecursive($name
1095 , $multiple ? static::asMultiple($value) : static::asSingle($value)
1096 , static::extractAttributes($input, array('DISABLED'=>''), array('FORM'=>1), false));
1097 }
1098 else
1099 {
1100 if ($value === null)
1101 $value = array();
1102 else
1103 $value = $multiple ? array_flip(static::asMultiple($value)) : array(static::asSingle($value) => true);
1104
1105 if ($input['MULTIELEMENT'] == 'Y')
1106 {
1107 $tag = isset($input['MULTITAG']) ? htmlspecialcharsbx($input['MULTITAG']) : static::MULTITAG;
1108 [$startTag, $endTag] = $tag ? array("<$tag>", "</$tag>") : array('', '');
1109
1110 $attributes = static::extractAttributes($input, array('DISABLED'=>''), array('FORM'=>1), false);
1111
1112 $type = 'radio';
1113
1114 if ($multiple)
1115 {
1116 $type = 'checkbox';
1117 $name .= '[]';
1118 }
1119
1120 $html .= self::getEditOptionsHtml($options, $value, ' checked',
1121 '<fieldset><legend>{GROUP}</legend>{OPTIONS}</fieldset>',
1122 $startTag.'<label><input type="'.$type.'" name="'.$name.'" value="{VALUE}"{SELECTED}'.$attributes.'> {TEXT} </label>'.$endTag
1123 );
1124 }
1125 else // select
1126 {
1127 $attributes = static::extractAttributes($input, array('DISABLED'=>'', 'AUTOFOCUS'=>'', 'REQUIRED'=>''), array('FORM'=>1, 'SIZE'=>1));
1128
1129 $html .= '<select'.$attributes.' name="'.$name.($multiple ? '[]" multiple>' : '">');
1130
1131 $html .= self::getEditOptionsHtml($options, $value, ' selected',
1132 '<optgroup label="{GROUP}">{OPTIONS}</optgroup>',
1133 '<option value="{VALUE}"{SELECTED}>{TEXT}</option>'
1134 );
1135
1136 $html .= '</select>';
1137 }
1138 }
1139
1140 if ($input['ADDITIONAL_HIDDEN'] === 'Y')
1141 {
1142 $html .= static::getHiddenRecursive($name
1143 , $multiple ? static::asMultiple($originalValue) : static::asSingle($originalValue)
1144 , static::extractAttributes($input, array(), array('FORM'=>1), false));
1145 }
1146
1147 return $html;
1148 }
1149
1150 private static function getEditOptionsHtml(array $options, array $selected, $selector, $group, $option)
1151 {
1152 $result = '';
1153
1154 foreach ($options as $key => $value)
1155 {
1156 $result .= is_array($value)
1157 ? str_replace(
1158 array('{GROUP}', '{OPTIONS}'),
1159 array(
1160 htmlspecialcharsEx($key),
1161 self::getEditOptionsHtml($value, $selected, $selector, $group, $option),
1162 ),
1163 $group
1164 )
1165 : str_replace(
1166 array('{VALUE}', '{SELECTED}', '{TEXT}'),
1167 array(
1168 htmlspecialcharsEx($key),
1169 isset($selected[$key]) ? $selector : '',
1170 htmlspecialcharsEx($value) ?: htmlspecialcharsEx($key),
1171 ),
1172 $option
1173 );
1174 }
1175
1176 return $result;
1177 }
1178
1179 public static function getErrorSingle(array $input, $value) // TODO optimize to getError
1180 {
1181 $options = $input['OPTIONS'];
1182
1183 if (is_array($options))
1184 {
1185 $options = self::flatten($options);
1186
1187 return isset($options[$value])
1188 ? array()
1189 : array('INVALID' => Loc::getMessage('INPUT_INVALID_ERROR'));
1190 }
1191 else
1192 {
1193 return array('OPTIONS' => Loc::getMessage('INPUT_ENUM_OPTIONS_ERROR'));
1194 }
1195 }
1196
1197 static function getSettings(array $input, $reload)
1198 {
1199 $settings = array(
1200 // TODO maybe??? 'OPTIONS' => array('TYPE' => 'TUPLE'),
1201 'MULTIELEMENT' => array('TYPE' => 'Y/N', 'LABEL' => Loc::getMessage('INPUT_ENUM_MULTIELEMENT'), 'ONCLICK' => $reload),
1202 );
1203
1204 if ($input['MULTIELEMENT'] != 'Y')
1205 $settings['SIZE'] = array('TYPE' => 'NUMBER', 'LABEL' => Loc::getMessage('INPUT_ENUM_SIZE'), 'MIN' => 0, 'STEP' => 1);
1206
1207 return $settings;
1208 }
1209}
1210
1211Manager::register('ENUM', array(
1212 'CLASS' => __NAMESPACE__.'\Enum',
1213 'NAME' => Loc::getMessage('INPUT_ENUM'),
1214));
1215
1220class File extends Base
1221{
1258 static function getPostWithFiles(array $post, array $files)
1259 {
1260 foreach ($files as $key => $file)
1261 {
1262 if (! is_array($post[$key]))
1263 $post[$key] = array();
1264
1265 foreach ($file as $property => $value)
1266 {
1267 if (is_array($value))
1268 self::getPostWithFilesRecursive($post[$key], $value, $property);
1269 else
1270 $post[$key][$property] = $value;
1271 }
1272 }
1273
1274 return $post;
1275 }
1276
1277 private static function getPostWithFilesRecursive(array &$root, array $values, $property)
1278 {
1279 foreach ($values as $key => $value)
1280 {
1281 if (! is_array($root[$key]))
1282 $root[$key] = array();
1283
1284 if (is_array($value))
1285 self::getPostWithFilesRecursive($root[$key], $value, $property);
1286 else
1287 $root[$key][$property] = $value;
1288 }
1289 }
1290
1296 static function loadInfo($value)
1297 {
1298 if (! $multiple = static::isMultiple($value))
1299 $value = array($value);
1300
1301 foreach ($value as &$file)
1302 $file = self::loadInfoSingle($file);
1303
1304 return $multiple ? $value : reset($value);
1305 }
1306
1308 static function loadInfoSingle($file)
1309 {
1310 if (is_array($file))
1311 {
1312 if ($file['SRC'])
1313 return $file; // already loaded
1314
1315 $fileId = $file['ID'];
1316 }
1317 else
1318 {
1319 $fileId = $file;
1320 }
1321
1322 if ($fileId && is_numeric($fileId) && ($row = \CFile::GetFileArray($fileId)))
1323 {
1324 $file = (is_array($file) ? $file : array('ID' => $fileId)) + $row;
1325 }
1326
1327 return $file;
1328 }
1329
1334 static function isDeletedSingle($value)
1335 {
1336 return is_array($value) && $value['DELETE'];
1337 }
1338
1343 static function isUploadedSingle($value)
1344 {
1345 return is_array($value) && $value['error'] == UPLOAD_ERR_OK && is_uploaded_file($value['tmp_name']);
1346 }
1347
1348 // input methods ///////////////////////////////////////////////////////////////////////////////////////////////////
1349
1350 static function isMultiple($value)
1351 {
1352 $isMultiple = false;
1353
1354 if (isset($value['ID']))
1355 {
1356 return $isMultiple;
1357 }
1358
1359 if (\is_array($value))
1360 {
1361 $file = current($value);
1362 if (\is_array($file) || ((int)$file > 0))
1363 {
1364 $isMultiple = true;
1365 }
1366 }
1367
1368 return $isMultiple;
1369 }
1370
1371 public static function getViewHtmlSingle(array $input, $value)
1372 {
1373 if (! is_array($value))
1374 $value = array('ID' => $value);
1375
1376 if ($src = $value['SRC'])
1377 {
1378 $attributes = ' href="'.htmlspecialcharsbx($src).'" title="'.htmlspecialcharsbx(Loc::getMessage('INPUT_FILE_DOWNLOAD')).'"';
1379
1380 if (\CFile::IsImage($src, $value['CONTENT_TYPE']) && $value['FILE_SIZE'] > 100000)
1381 {
1382 $previewImage = \CFile::ResizeImageGet($value['ID'], array(200,200), BX_RESIZE_IMAGE_PROPORTIONAL);
1383 if (is_array($previewImage))
1384 $src = $previewImage['src'];
1385 }
1386
1387 $content = \CFile::IsImage($value['SRC'], $value['CONTENT_TYPE'])
1388 ? '<img src="'.$src.'" border="0" alt="" style="max-height:100px; max-width:100px">'
1389 : htmlspecialcharsbx($value['ORIGINAL_NAME']);
1390 }
1391 else
1392 {
1393 $attributes = '';
1394 $content = htmlspecialcharsbx($value['ORIGINAL_NAME']);
1395 }
1396
1397 if (! $content)
1398 $content = $value['FILE_NAME'];
1399
1400 if (! $content)
1401 $content = $value['ID'];
1402
1403 return "<a$attributes>$content</a>";
1404 }
1405
1412 public static function getFilterEditHtml($name, array $input, $value)
1413 {
1414 return static::getEditHtmlSingle($name, $input, $value);
1415 }
1416
1417 public static function getEditHtmlSingle($name, array $input, $value)
1418 {
1419 if (! is_array($value))
1420 {
1421 $value = array('ID' => $value);
1422 }
1423
1424 if ($value['DELETE'])
1425 {
1426 unset($value['ID']);
1427 }
1428
1429 $input['ONCHANGE'] =
1430 "var anchor = this.previousSibling.previousSibling;".
1431 "if (anchor.firstChild) anchor.removeChild(anchor.firstChild);".
1432 "anchor.appendChild(document.createTextNode(this.value.split(/(\\\\|\\/)/g).pop()));".
1433 $input['ONCHANGE'];
1434
1435 // TODO HTML5 add MULTIPLE
1436 $fileAttributes = static::extractAttributes($input,
1437 array('DISABLED'=>'', 'AUTOFOCUS'=>'', 'REQUIRED'=>''),
1438 array('FORM'=>1, 'ACCEPT'=>1));
1439
1440 $otherAttributes = static::extractAttributes($input, array('DISABLED'=>''), array('FORM'=>1), false);
1441
1442 return static::getViewHtmlSingle($input, $value)
1443 .'<input type="hidden" name="'.$name.'[ID]" value="'.htmlspecialcharsbx($value['ID']).'"'.$otherAttributes.'>'
1444 .'<input type="file" name="'.$name.'" style="position:absolute; visibility:hidden"'.$fileAttributes.'>'
1445 .'<input type="button" value="'.Loc::getMessage('INPUT_FILE_BROWSE').'" onclick="this.previousSibling.click()">'
1446 .(
1447 $input['NO_DELETE']
1448 ? ''
1449 : '<label> '.Loc::getMessage('INPUT_DELETE').' <input type="checkbox" name="'.$name.'[DELETE]" onclick="'
1450
1451 ."var button = this.parentNode.previousSibling, file = button.previousSibling;"
1452 ."button.disabled = file.disabled = this.checked;"
1453
1454 .'"'.$otherAttributes.'> </label>'
1455 );
1456 }
1457
1458 public static function getEditHtmlSingleDelete($name, array $input)
1459 {
1460 return '';
1461 }
1462
1463 public static function getErrorSingle(array $input, $value)
1464 {
1465 if (is_array($value))
1466 {
1467 if ($value['DELETE'])
1468 {
1469 return $input['REQUIRED'] == 'Y'
1470 ? array('REQUIRED' => Loc::getMessage('INPUT_REQUIRED_ERROR'))
1471 : array();
1472 }
1473 elseif (is_uploaded_file($value['tmp_name']))
1474 {
1475 $errors = array();
1476
1477 if ($input['MAXSIZE'] && $value['size'] > $input['MAXSIZE'])
1478 $errors['MAXSIZE'] = Loc::getMessage('INPUT_FILE_MAXSIZE_ERROR');
1479
1480 // TODO check: file name, mime type, extension
1481 //$info = pathinfo($value['name']);
1482
1483 if ($error = \CFile::CheckFile($value, 0, false, $input['ACCEPT']))
1484 $errors['CFILE'] = $error;
1485
1486 return $errors;
1487 }
1488 else
1489 {
1490 switch ($value['error'])
1491 {
1492 case UPLOAD_ERR_OK: return array(); //file uploaded successfully
1493
1494 case UPLOAD_ERR_INI_SIZE:
1495 case UPLOAD_ERR_FORM_SIZE: return array('MAXSIZE' => Loc::getMessage('INPUT_FILE_MAXSIZE_ERROR'));
1496
1497 case UPLOAD_ERR_PARTIAL: return array('PARTIAL' => Loc::getMessage('INPUT_FILE_PARTIAL_ERROR'));
1498
1499 case UPLOAD_ERR_NO_FILE:
1500
1501 return $input['REQUIRED'] == 'Y' && (! is_numeric($value['ID']) || $value['DELETE'])
1502 ? array('REQUIRED' => Loc::getMessage('INPUT_REQUIRED_ERROR'))
1503 : array();
1504
1505 // TODO case UPLOAD_ERR_NO_TMP_DIR UPLOAD_ERR_CANT_WRITE UPLOAD_ERR_EXTENSION
1506 default: return array('INVALID' => Loc::getMessage('INPUT_INVALID_ERROR'));
1507 }
1508 }
1509 }
1510 elseif (is_numeric($value))
1511 {
1512 // TODO check if file id exists maybe ???
1513 return array();
1514 }
1515 else
1516 {
1517 return array('INVALID' => Loc::getMessage('INPUT_INVALID_ERROR'));
1518 }
1519 }
1520
1521 public static function getValueSingle(array $input, $value)
1522 {
1523 if (is_array($value))
1524 {
1525 if ($value['DELETE'])
1526 return null;
1527
1528 $value = $value['ID'];
1529 }
1530
1531 return is_numeric($value) ? $value : null;
1532 }
1533
1534 public static function getSettings(array $input, $reload)
1535 {
1536 return array(
1537 'MAXSIZE' => array('TYPE' => 'NUMBER', 'LABEL' => Loc::getMessage('INPUT_FILE_MAXSIZE'), 'MIN' => 0, 'STEP' => 1),
1538 'ACCEPT' => array('TYPE' => 'STRING', 'LABEL' => Loc::getMessage('INPUT_FILE_ACCEPT' ), 'PLACEHOLDER' => 'png, doc, zip'),
1539 );
1540 }
1541}
1542
1543Manager::register('FILE', array(
1544 'CLASS' => __NAMESPACE__.'\File',
1545 'NAME' => Loc::getMessage('INPUT_FILE'),
1546));
1547
1551class Date extends Base
1552{
1553 public static function getEditHtmlSingle($name, array $input, $value)
1554 {
1555 $showTime = $input['TIME'] == 'Y';
1556
1557 // TODO HTML5 input="date|datetime|datetime-local" & min & max & step(date:integer|datetime..:float)
1558
1559 $textAttributes = static::extractAttributes($input,
1560 array('DISABLED'=>'', 'AUTOCOMPLETE'=>'on', 'AUTOFOCUS'=>'', 'READONLY'=>'', 'REQUIRED'=>''),
1561 array('FORM'=>1, 'LIST'=>1));
1562
1563 $buttonAttributes = static::extractAttributes($input, array('DISABLED'=>''), array(), false);
1564
1565 return '<input type="text" name="'.$name.'" size="'.($showTime ? 20 : 10).'" value="'.htmlspecialcharsbx($value).'"'.$textAttributes.'>'
1566 .'<input type="button" value="'.Loc::getMessage('INPUT_DATE_SELECT').'"'.$buttonAttributes.' onclick="'
1567 ."BX.calendar({node:this, field:'$name', form:'', bTime:".($showTime ? 'true' : 'false').", bHideTime:false});"
1568 .'">';
1569 }
1570
1577 public static function getFilterEditHtml($name, array $input, $value)
1578 {
1579 return static::getEditHtmlSingle($name, $input, $value);
1580 }
1581
1582 public static function getEditHtmlSingleDelete($name, array $input)
1583 {
1584 return '<label> '.Loc::getMessage('INPUT_DELETE').' <input type="checkbox" onclick="'
1585
1586 ."var disabled = this.checked;"
1587 ."var button = this.parentNode.previousSibling;"
1588 ."button.disabled = disabled;"
1589 ."button.previousSibling.disabled = disabled;"
1590
1591 .'"> </label>';
1592 }
1593
1594 public static function getErrorSingle(array $input, $value)
1595 {
1596 return CheckDateTime($value, FORMAT_DATE)
1597 ? array()
1598 : array('INVALID' => Loc::getMessage('INPUT_INVALID_ERROR'));
1599 }
1600
1601 static function getSettings(array $input, $reload)
1602 {
1603 return array(
1604 'TIME' => array('TYPE' => 'Y/N', 'LABEL' => Loc::getMessage('INPUT_DATE_TIME'), 'ONCLICK' => $reload),
1605 // TODO min, max, step
1606 );
1607 }
1608}
1609
1610Manager::register('DATE', array(
1611 'CLASS' => __NAMESPACE__.'\Date',
1612 'NAME' => Loc::getMessage('INPUT_DATE'),
1613));
1614
1618class Location extends Base
1619{
1620 public static function getViewHtmlSingle(array $input, $value)
1621 {
1622 if((string) $value == '')
1623 return '';
1624
1625 try
1626 {
1627 $result = \Bitrix\Sale\Location\LocationTable::getPathToNodeByCode($value, array(
1628 'select' => array('CHAIN' => 'NAME.NAME'),
1629 'filter' => array('NAME.LANGUAGE_ID' => LANGUAGE_ID),
1630 ));
1631
1632 $path = array();
1633
1634 while($row = $result->fetch())
1635 $path[] = $row['CHAIN'];
1636
1637 return htmlspecialcharsbx(implode(', ', $path));
1638 }
1639 catch(\Bitrix\Main\SystemException $e)
1640 {
1641 return '';
1642 }
1643 }
1644
1651 public static function getFilterEditHtml($name, array $input, $value)
1652 {
1653 return static::getEditHtml($name, $input, $value);
1654 }
1655
1656 public static function getEditHtml($name, array $input, $value = null)
1657 {
1658 $name = htmlspecialcharsbx($name);
1659
1660 if ($value === null)
1661 $value = $input['VALUE'];
1662
1663 $html = '';
1664
1665 if ($input['HIDDEN'] == 'Y')
1666 {
1667 $html .= static::getHiddenRecursive($name
1668 , $input['MULTIPLE'] == 'Y' ? static::asMultiple($value) : static::asSingle($value)
1669 , static::extractAttributes($input, array('DISABLED'=>''), array('FORM'=>1), false));
1670 }
1671 else
1672 {
1673 $selector = md5("location input selector $name");
1674 $input["LOCATION_SELECTOR"] = $selector;
1675
1676 if ($onChange = $input['ONCHANGE'])
1677 {
1678 $functionName = 'OnLocationChange'.$selector;
1679 $html .= "<script>function $functionName (){ $onChange }; BX.proxy($functionName, this);</script>";
1680 $input['JS_CALLBACK'] = $functionName;
1681 }
1682 else
1683 {
1684 $input['JS_CALLBACK'] = null;
1685 }
1686
1687 if ($input['MULTIPLE'] == 'Y')
1688 {
1689 $tag = isset($input['MULTITAG']) ? htmlspecialcharsbx($input['MULTITAG']) : static::MULTITAG;
1690 [$startTag, $endTag] = $tag ? array("<$tag>", "</$tag>") : array('', '');
1691
1692 $index = -1;
1693
1694 $values = static::asMultiple($value);
1695 if (empty($value))
1696 {
1697 $values = array(null);
1698 }
1699 foreach ($values as $value)
1700 $html .= $startTag
1701 .static::getEditHtmlSingle($name.'['.(++$index).']', $input, $value)
1702 .$endTag;
1703
1704 $replace = '##INPUT##NAME##';
1705
1706 if ($input['DISABLED'] !== 'Y') // TODO
1707 $html .= static::getEditHtmlInsert($tag, $replace, $name
1708 , static::getEditHtmlSingle($replace, $input, null)
1709 , "var location = BX.locationSelectors['$selector'].spawn(container, {selectedItem: false, useSpawn: false});"
1710 ."location.clearSelected();"
1711 //."location.focus();" // TODO
1712 );
1713 }
1714 else
1715 {
1716 $html .= static::getEditHtmlSingle($name, $input, static::asSingle($value));
1717 }
1718 }
1719
1720 if ($input['ADDITIONAL_HIDDEN'] === 'Y')
1721 {
1722 $html .= static::getHiddenRecursive($name
1723 , $input['MULTIPLE'] == 'Y' ? static::asMultiple($value) : static::asSingle($value)
1724 , static::extractAttributes($input, array(), array('FORM'=>1), false));
1725 }
1726
1727 return $html;
1728 }
1729
1730 public static function getEditHtmlSingle($name, array $input, $value)
1731 {
1732 $filterMode = isset($input['IS_FILTER_FIELD']) && $input['IS_FILTER_FIELD'] === true;
1733 $isSearchLine = isset($input['IS_SEARCH_LINE']) && $input['IS_SEARCH_LINE'] === true;
1734 $parameters = array(
1735 'CODE' => $value,
1736 'INPUT_NAME' => $name,
1737 'PROVIDE_LINK_BY' => 'code',
1738 'SELECT_WHEN_SINGLE' => 'N',
1739 'FILTER_BY_SITE' => 'N',
1740 'SHOW_DEFAULT_LOCATIONS' => 'N',
1741 'SEARCH_BY_PRIMARY' => 'N',
1742 'JS_CONTROL_GLOBAL_ID' => $input["LOCATION_SELECTOR"],
1743 'JS_CALLBACK' => $input['JS_CALLBACK']
1744 );
1745
1746 ob_start();
1747
1748 if($filterMode)
1749 {
1750 print('<div style="width: 100%; margin-left: 12px">');
1751 $parameters['INITIALIZE_BY_GLOBAL_EVENT'] = 'onAdminFilterInited'; // this allows js logic to be initialized after admin filter
1752 $parameters['GLOBAL_EVENT_SCOPE'] = 'window';
1753 }
1754
1755 $GLOBALS['APPLICATION']->IncludeComponent(
1756 'bitrix:sale.location.selector.'.($filterMode || $isSearchLine ? 'search' : \Bitrix\Sale\Location\Admin\Helper::getWidgetAppearance()),
1757 '',
1758 $parameters,
1759 false
1760 );
1761
1762 if($filterMode)
1763 {
1764 print('</div>');
1765 }
1766
1767 $html = ob_get_contents();
1768 ob_end_clean();
1769
1770 return $html;
1771 }
1772
1773 public static function getErrorSingle(array $input, $value)
1774 {
1775 return \Bitrix\Sale\Location\LocationTable::getByCode($value)->fetch()
1776 ? array()
1777 : array('INVALID' => Loc::getMessage('INPUT_INVALID_ERROR'));
1778 }
1779}
1780
1781Manager::register('LOCATION', array(
1782 'CLASS' => __NAMESPACE__.'\Location',
1783 'NAME' => Loc::getMessage('INPUT_LOCATION'),
1784));
1785
1790class Address extends Base
1791{
1795 static function isMultiple($value)
1796 {
1797 return false;
1798 }
1799
1803 public static function hasMultipleValuesSupport()
1804 {
1805 return false;
1806 }
1807
1813 public static function getViewHtml(array $input, $value = null)
1814 {
1815 if (!is_array($value) || !Loader::includeModule('location'))
1816 {
1817 return '';
1818 }
1819
1820 $address = \Bitrix\Location\Entity\Address::fromArray($value);
1821
1822 return $address->toString(
1823 FormatService::getInstance()->findDefault(LANGUAGE_ID)
1824 );
1825 }
1826
1830 public static function getFilterEditHtml($name, array $input, $value)
1831 {
1832 //not implemented
1833 return '';
1834 }
1835
1841 public static function getErrorSingle(array $input, $value)
1842 {
1843 if ($input['REQUIRED'] == 'Y')
1844 {
1845 if (!(is_array($value) && !empty($value)))
1846 {
1847 return ['REQUIRED' => Loc::getMessage('INPUT_REQUIRED_ERROR')];
1848 }
1849 }
1850
1851 return [];
1852 }
1853
1859 public static function getRequiredError(array $input, $value)
1860 {
1861 return static::getErrorSingle($input, $value);
1862 }
1863
1867 public static function getEditHtmlSingle($name, array $input, $value)
1868 {
1869 if (!Loader::includeModule('location'))
1870 {
1871 return '';
1872 }
1873
1874 \Bitrix\Main\UI\Extension::load('sale.address');
1875
1876 ob_start();
1877 ?>
1878 <script>
1879 if (BX.Sale.AddressControlConstructor)
1880 {
1881 new BX.Sale.AddressControlConstructor(
1882 {
1883 propsData: {
1884 name: '<?=$name?>',
1885 initValue: <?=(is_array($value)) ? ("'" . \Bitrix\Location\Entity\Address::fromArray($value)->toJson() . "'") : Json::encode(null)?>,
1886 isLocked: <?=($input['DISABLED'] === 'Y') ? Json::encode(true) : Json::encode(false)?>,
1887 onChangeCallback: function () {
1888 <?if (isset($input['ONCHANGE'])):?>
1889 <?=$input['ONCHANGE']?>
1890 <?endif;?>
1891 }
1892 }
1893 }
1894 ).$mount('#<?=$name?>');
1895 }
1896 </script>
1897 <?
1898 $script = ob_get_clean();
1899
1900 return '
1901 <div id="' . $name . '"></div>
1902 ' . $script . '
1903 ';
1904 }
1905}
1906
1907if (Loader::includeModule('location'))
1908{
1909 Manager::register('ADDRESS', array(
1910 'CLASS' => __NAMESPACE__.'\Address',
1911 'NAME' => Loc::getMessage('INPUT_ADDRESS'),
1912 ));
1913}
1914
1916{
1917
1924 public static function getViewHtml(array $input, $values = null) : string
1925 {
1926 if (!is_array($values))
1927 {
1928 return '';
1929 }
1930
1931 $result = '<br><br>';
1932 $catList = self::getCategoriesList($values);
1933
1934 foreach ($catList as $catName)
1935 {
1936 $result .= "<div> - {$catName}</div>";
1937 }
1938
1939 return $result;
1940 }
1941
1949 public static function getEditHtml($name, array $input, $values = null) : string
1950 {
1951 if (!is_array($values))
1952 {
1953 $values = [];
1954 }
1955
1956 $addInputTranslate = Loc::getMessage('SALE_PRODUCT_CATEGORY_INP_ADD');
1957 $deleteInputTranslate = Loc::getMessage('SALE_PRODUCT_CATEGORY_INP_DELETE');
1958
1959 $openFilterButtonId = $input['ID'];
1960
1961 $deprecatedSupport = isset($input['SCRIPT']) && isset($input['URL']);
1962 if ($deprecatedSupport)
1963 {
1964 $url = $input['URL'];
1965 $addCategoryScript = $input['SCRIPT'];
1966 $input['ID'] = 'sale-admin-delivery-restriction-cat';
1967 }
1968 else
1969 {
1970 $addCategoryScript = "window.InS".md5('SECTIONS_IDS')."=function(id, name){{$input['JS_HANDLER']}.addRestrictionProductSection(id, name, '{$input['ID']}', this);};";
1971 $url = 'cat_section_search.php?lang=ru&m=y&n=SECTIONS_IDS';
1972 }
1973
1974 $editSection = "
1975 <br>
1976 <a
1977 class='adm-s-restriction-open-dialog-link'
1978 href='javascript:void(0);'
1979 id='{$openFilterButtonId}'
1980 onclick=\"window.open('{$url}','choose category', 'width=850, height=600');\"
1981 >
1982 {$addInputTranslate}
1983 </a>
1984 <br><br>
1985 <script type='text/javascript'>
1986 {$addCategoryScript}
1987 BX.message({SALE_PRODUCT_CATEGORY_INP_DELETE: '{$deleteInputTranslate}'});
1988 </script>
1989 ";
1990
1991 $catList = self::getCategoriesList($values);
1992 $existCatHtml = "<table id='{$input['ID']}-content' width='100%'>";
1993
1994 foreach ($catList as $catId => $catName)
1995 {
1996 if ($deprecatedSupport)
1997 {
1998 $deleteNodeScript = "BX.Sale.Delivery.deleteRestrictionProductSection('{$catId}');";
1999 }
2000 else
2001 {
2002 $deleteNodeScript = "{$input['JS_HANDLER']}.deleteRestrictionProductSection('{$catId}', '{$input['ID']}');";
2003 }
2004
2005 $existCatHtml .= "
2006 <tr class='adm-s-product-category-restriction-delcat' id='{$input['ID']}-{$catId}'>
2007 <td>
2008 <span> - {$catName}</span>
2009 <input type='hidden' name='RESTRICTION[CATEGORIES][]' value='{$catId}'>
2010 </td>
2011 <td align='right'>
2012 &nbsp;
2013 <a
2014 class='adm-s-bus-morelinkqhsw'
2015 href='javascript:void(0);'
2016 onclick=\"{$deleteNodeScript}\"
2017 >
2018 {$deleteInputTranslate}
2019 </a>
2020 </td>
2021 </tr>
2022 ";
2023 }
2024
2025 $existCatHtml .= '</table>';
2026
2027 return $existCatHtml.$editSection;
2028 }
2029
2035 protected static function getCategoriesList($ids) : array
2036 {
2037 if(!\Bitrix\Main\Loader::includeModule('iblock'))
2038 return [];
2039
2040 $result = [];
2041
2042 $res = \Bitrix\Iblock\SectionTable::getList([
2043 'filter' => [
2044 'ID' => $ids,
2045 ],
2046 'select' => ['ID', 'NAME'],
2047 ]);
2048
2049 while($section = $res->fetch())
2050 $result[$section['ID']] = htmlspecialcharsbx($section['NAME']);
2051
2052 return $result;
2053 }
2054
2055 public static function getValueSingle(array $input, $userValue)
2056 {
2057 return $userValue;
2058 }
2059
2060 public static function getError(array $input, $values)
2061 {
2062 return self::getErrorSingle($input, $values);
2063 }
2064
2065 public static function getErrorSingle(array $input, $values)
2066 {
2067 return [];
2068 }
2069
2070 public static function getSettings(array $input, $reload)
2071 {
2072 return [];
2073 }
2074}
2075
2076 Manager::register('PRODUCT_CATEGORIES', [
2077 'CLASS' => __NAMESPACE__.'\ProductCategories',
2078 'NAME' => Loc::getMessage('SALE_PRODUCT_CATEGORY_INP'),
2079]);
2080
2082{
2088 public static function getViewHtml(array $input, $values = null) : string
2089 {
2090 if (!is_array($values))
2091 {
2092 return '';
2093 }
2094
2095 $result = '<br><br>';
2096
2097 $productList = self::getProductsList($values);
2098
2099 foreach ($productList as $productName)
2100 {
2101 $result .= "<div> - {$productName}</div>";
2102 }
2103
2104 return $result;
2105 }
2106
2114 public static function getEditHtml($name, array $input, $values = null) : string
2115 {
2116 if (!is_array($values))
2117 {
2118 $values = [];
2119 }
2120
2121 $nodeId = &$input['ID'];
2122
2123 $input['FORM_NAME'] = md5($input['FORM_NAME']);
2124 $url = "cat_product_search.php?func_name={$input['FORM_NAME']}&new_value=Y";
2125 $addProductScript = "window.".$input['FORM_NAME']."=function(id, name, url){".$input["JS_HANDLER"].".addRestrictionByConcreteProduct('".$nodeId."', id, name, this);};";
2126
2127 $addInputTranslate = Loc::getMessage('SALE_CONCRETE_PRODUCT_INP_ADD');
2128 $deleteInputTranslate = Loc::getMessage('SALE_CONCRETE_PRODUCT_INP_DELETE');
2129
2130 $editSection = "
2131 <br>
2132 <a
2133 class='adm-s-restriction-open-dialog-link'
2134 href='javascript:void(0);'
2135 id='{$input["ID"]}'
2136 onclick=\"window.open('{$url}', 'choose product', 'width=850,height=600');\"
2137 >
2138 {$addInputTranslate}
2139 </a>
2140 <br><br>
2141 <script type='text/javascript'>
2142 {$addProductScript}
2143 BX.message({SALE_CONCRETE_PRODUCT_INP_DELETE: '$deleteInputTranslate'});
2144 </script>";
2145
2146 $productsList = self::getProductsList($values);
2147 $existProductsHtml = "<table id='{$nodeId}-content' width='100%'>";
2148
2149 foreach ($productsList as $productId => $productName)
2150 {
2151 $existProductsHtml .= "
2152 <tr class='adm-s-concrete-product-restriction-delprod' id='{$nodeId}-{$productId}'>
2153 <td>
2154 <span> - {$productName}</span>
2155 <input type='hidden' name='RESTRICTION[PRODUCTS][]' value='{$productId}'>
2156 </td>
2157 <td align='right'>
2158 &nbsp;
2159 <a
2160 class='adm-s-bus-morelinkqhsw' href='javascript:void(0);'
2161 onclick=\"{$input["JS_HANDLER"]}.deleteRestrictionByConcreteProduct('{$nodeId}', '{$productId}');\"
2162 >
2163 {$deleteInputTranslate}
2164 </a>
2165 </td>
2166 </tr>
2167 ";
2168 }
2169
2170 $existProductsHtml .= "</table>";
2171
2172 return $existProductsHtml.$editSection;
2173 }
2174
2175 protected static function getProductsList($elementIds)
2176 {
2177 if (!\Bitrix\Main\Loader::includeModule('iblock'))
2178 {
2179 return [];
2180 }
2181
2182 $productsList = [];
2183
2184 $productsListSource = \Bitrix\Iblock\ElementTable::getList([
2185 'filter' => [
2186 'ID' => $elementIds,
2187 ],
2188 'select' => ['ID', 'NAME'],
2189 ]);
2190
2191 while ($productRow = $productsListSource->fetch())
2192 {
2193 $productsList[$productRow['ID']] = htmlspecialcharsbx($productRow['NAME']);
2194 }
2195
2196 return $productsList;
2197 }
2198
2199 public static function getValueSingle(array $input, $userValue)
2200 {
2201 return $userValue;
2202 }
2203
2204 public static function getError(array $input, $value)
2205 {
2206 return self::getErrorSingle($input, $value);
2207 }
2208
2209 public static function getErrorSingle(array $input, $value)
2210 {
2211 return [];
2212 }
2213
2214 public static function getSettings(array $input, $reload)
2215 {
2216 return [];
2217 }
2218}
2219
2221 'CONCRETE_PRODUCT',
2222 [
2223 'CLASS' => __NAMESPACE__.'\\ConcreteProduct',
2224 'NAME' => Loc::getMessage('SALE_CONCRETE_PRODUCT_INP')
2225 ]
2226);
static fromArray(array $arrayData)
Definition: address.php:298
static loadMessages($file)
Definition: loc.php:64
static getMessage($code, $replace=null, $language=null)
Definition: loc.php:29
static getRequiredError(array $input, $value)
Definition: input.php:1859
static getEditHtmlSingle($name, array $input, $value)
Definition: input.php:1867
static getFilterEditHtml($name, array $input, $value)
Definition: input.php:1830
static getErrorSingle(array $input, $value)
Definition: input.php:1841
static getViewHtml(array $input, $value=null)
Definition: input.php:1813
static getValue(array $input, $value)
Definition: input.php:586
static getSettings(array $input, $reload)
Definition: input.php:618
static getViewHtmlSingle(array $input, $value)
Definition: input.php:401
static getEditHtml($name, array $input, $value=null)
Definition: input.php:412
static extractAttributes(array $input, array $boolean, array $other, $withGlobal=true)
Definition: input.php:643
static getHiddenRecursive($name, $value, $attributes)
Definition: input.php:625
static getRequiredError(array $input, $value)
Definition: input.php:541
static getEditHtmlSingle($name, array $input, $value)
Definition: input.php:469
static getEditHtmlSingleDelete($name, array $input)
Definition: input.php:474
static getValueSingle(array $input, $value)
Definition: input.php:613
static getErrorSingle(array $input, $value)
Definition: input.php:581
static getError(array $input, $value)
Definition: input.php:503
static getEditHtmlInsert($tag, $replace, $name, $sample, $after)
Definition: input.php:483
static getViewHtml(array $input, $value=null)
Definition: input.php:378
static getSettings(array $input, $reload)
Definition: input.php:2214
static getViewHtml(array $input, $values=null)
Definition: input.php:2088
static getValueSingle(array $input, $userValue)
Definition: input.php:2199
static getEditHtml($name, array $input, $values=null)
Definition: input.php:2114
static getErrorSingle(array $input, $value)
Definition: input.php:2209
static getError(array $input, $value)
Definition: input.php:2204
static getSettings(array $input, $reload)
Definition: input.php:1601
static getEditHtmlSingle($name, array $input, $value)
Definition: input.php:1553
static getEditHtmlSingleDelete($name, array $input)
Definition: input.php:1582
static getFilterEditHtml($name, array $input, $value)
Definition: input.php:1577
static getErrorSingle(array $input, $value)
Definition: input.php:1594
static getViewHtmlSingle(array $input, $value)
Definition: input.php:962
static getEditHtmlSingle($name, array $input, $value)
Definition: input.php:967
static getValueSingle(array $input, $value)
Definition: input.php:1014
static getFilterEditHtml($name, array $input, $value)
Definition: input.php:991
static getErrorSingle(array $input, $value)
Definition: input.php:1004
static getSettings(array $input, $reload)
Definition: input.php:1197
static getViewHtmlSingle(array $input, $value)
Definition: input.php:1049
static getEditHtml($name, array $input, $value=null)
Definition: input.php:1075
static getFilterEditHtml($name, array $input, $value)
Definition: input.php:1070
static getErrorSingle(array $input, $value)
Definition: input.php:1179
static getSettings(array $input, $reload)
Definition: input.php:1534
static isUploadedSingle($value)
Definition: input.php:1343
static getViewHtmlSingle(array $input, $value)
Definition: input.php:1371
static isDeletedSingle($value)
Definition: input.php:1334
static getEditHtmlSingle($name, array $input, $value)
Definition: input.php:1417
static getPostWithFiles(array $post, array $files)
Definition: input.php:1258
static getEditHtmlSingleDelete($name, array $input)
Definition: input.php:1458
static getValueSingle(array $input, $value)
Definition: input.php:1521
static getFilterEditHtml($name, array $input, $value)
Definition: input.php:1412
static getErrorSingle(array $input, $value)
Definition: input.php:1463
static getViewHtmlSingle(array $input, $value)
Definition: input.php:1620
static getEditHtml($name, array $input, $value=null)
Definition: input.php:1656
static getEditHtmlSingle($name, array $input, $value)
Definition: input.php:1730
static getFilterEditHtml($name, array $input, $value)
Definition: input.php:1651
static getErrorSingle(array $input, $value)
Definition: input.php:1773
static getValue(array $input, $value)
Definition: input.php:163
static getSettings(array $input, $reload=null)
Definition: input.php:197
static getEditHtml($name, array $input, $value=null)
Definition: input.php:88
static asMultiple(array $input, $value)
Definition: input.php:180
static register($name, array $type)
Definition: input.php:282
static getRequiredError(array $input, $value)
Definition: input.php:141
static getFilterEditHtml($name, array $input, $value=null)
Definition: input.php:106
static getError(array $input, $value)
Definition: input.php:123
static getViewHtml(array $input, $value=null)
Definition: input.php:70
static getSettings(array $input, $reload)
Definition: input.php:942
static getEditHtmlSingle($name, array $input, $value)
Definition: input.php:869
static getFilterEditHtml($name, array $input, $value)
Definition: input.php:899
static getErrorSingle(array $input, $value)
Definition: input.php:904
static getSettings(array $input, $reload)
Definition: input.php:2070
static getErrorSingle(array $input, $values)
Definition: input.php:2065
static getViewHtml(array $input, $values=null)
Definition: input.php:1924
static getValueSingle(array $input, $userValue)
Definition: input.php:2055
static getEditHtml($name, array $input, $values=null)
Definition: input.php:1949
static getError(array $input, $values)
Definition: input.php:2060
static getSettings(array $input, $reload)
Definition: input.php:825
static getEditHtmlSingle($name, array $input, $value)
Definition: input.php:724
static getFilterEditHtml($name, array $input, $value)
Definition: input.php:766
static getErrorSingle(array $input, $value)
Definition: input.php:771