Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
iblockmoneyproperty.php
1<?php
2
4
11
12class IblockMoneyProperty
13{
14 public const USER_TYPE = 'Money';
15 public const SEPARATOR = '|';
16
22 public static function getUserTypeDescription()
23 {
24 $className = get_called_class();
25 return [
26 'PROPERTY_TYPE' => 'S',
27 'USER_TYPE' => self::USER_TYPE,
28 'DESCRIPTION' => Loc::getMessage('CIMP_INPUT_DESCRIPTION'),
29 'GetPublicEditHTML' => [$className, 'getPublicEditHTML'],
30 'GetPublicViewHTML' => [$className, 'getPublicViewHTML'],
31 'GetPropertyFieldHtml' => [$className, 'getPropertyFieldHtml'],
32 'GetAdminListViewHTML' => [$className, 'getAdminListViewHTML'],
33 'GetUIEntityEditorProperty' => [$className, 'GetUIEntityEditorProperty'],
34 'getFormattedValue' => [$className, 'getSeparatedValues'],
35 'CheckFields' => [$className, 'checkFields'],
36 'GetLength' => [$className, 'getLength'],
37 'ConvertToDB' => [$className, 'convertToDB'],
38 'ConvertFromDB' => [$className, 'convertFromDB'],
39 'AddFilterFields' => [$className, 'addFilterFields'],
40 ];
41 }
42
51 public static function getPublicEditHTML($property, $value, $controlSettings)
52 {
53 return self::getPropertyFieldHtml($property, $value, $controlSettings);
54 }
55
64 public static function getPublicViewHTML($property, $value, $controlSettings)
65 {
66 return self::getAdminListViewHTML($property, $value, $controlSettings);
67 }
68
77 public static function getPropertyFieldHtml($property, $value, $controlSettings)
78 {
79 $randString = mb_strtolower(\Bitrix\Main\Security\Random::getString(6));
80
81 $explode = (is_string($value['VALUE']) ? explode(self::SEPARATOR, $value['VALUE']) : []);
82 $currentValue = (isset($explode[0]) && $explode[0] !== '' ? $explode[0] : '');
83 $currentCurrency = ($explode[1] ?? '');
84
85 $html = '<input type="text" style="width: auto;" value="'.htmlspecialcharsbx($currentValue).
86 '" id="input-'.$randString.'">';
87 $html .= '<input type="hidden" id="hidden-'.$randString.'" name="'.
88 htmlspecialcharsbx($controlSettings['VALUE']).'" value="'.htmlspecialcharsbx($value["VALUE"]).'">';
89 $listCurrency = self::getListCurrency();
90 if($listCurrency)
91 {
92 if($property['MULTIPLE'] == 'Y')
93 $html .= '<input type="hidden" data-id="'.$randString.'">';
94 $html .= '<select id="selector-'.$randString.'" style="width: auto; margin: 0 5px;">';
95 foreach($listCurrency as $currency)
96 {
97 $selected = ($currentCurrency == $currency['CURRENCY'] ||
98 (!$currentCurrency && $currency['BASE'] == 'Y')) ? 'selected' : '';
99 $html .= '<option '.$selected.' value="'.$currency['CURRENCY'].'">'.
100 htmlspecialcharsbx($currency['NAME']).'</option>';
101 }
102 $html .= '</select>';
103 $html .= '<span id="error-'.$randString.'" style="color: red;"></span>';
104 $html .= self::getJsHandlerSelector($randString, $listCurrency);
105 }
106
107 return $html;
108 }
109
118 public static function getAdminListViewHTML($property, $value, $controlSettings)
119 {
120 $explode = is_string($value['VALUE']) ? explode(self::SEPARATOR, $value['VALUE']) : [];
121 $currentValue = (isset($explode[0]) && $explode[0] !== '' ? $explode[0] : '');
122 $currentCurrency = $explode[1] ?? '';
123
124 if (!$currentCurrency)
125 return is_numeric($currentValue) ? $currentValue : '';
126
127 if (CurrencyManager::isCurrencyExist($currentCurrency))
128 {
129 if(!empty($controlSettings['MODE']))
130 {
131 switch($controlSettings['MODE'])
132 {
133 case 'CSV_EXPORT':
134 return $value['VALUE'];
135 case 'ELEMENT_TEMPLATE':
136 case 'SIMPLE_TEXT':
137 return $currentValue;
138 }
139 }
140
141 list($currentValue, $currentCurrency, $decimalsValue) = array_values(self::getSeparatedValues($value['VALUE']));
142 $currentValue = $currentValue.'.'.$decimalsValue;
143
144 return \CCurrencyLang::CurrencyFormat($currentValue, $currentCurrency, true);
145 }
146
147 return '';
148 }
149
157 public static function checkFields($property, $value)
158 {
159 $result = [];
160 if(empty($value['VALUE'])) return $result;
161 $explode = (is_string($value['VALUE']) ? explode(self::SEPARATOR, $value['VALUE']) : []);
162 $currentValue = (isset($explode[0]) && $explode[0] !== '' ? $explode[0] : '');
163 $currentCurrency = ($explode[1] ?? '');
164
165 if(!$currentCurrency)
166 return is_numeric($currentValue) ? $result : array(Loc::getMessage('CIMP_FORMAT_ERROR'));
167
168 if(CurrencyManager::isCurrencyExist($currentCurrency))
169 {
170 $format = \CCurrencyLang::GetFormatDescription($currentCurrency);
171 $decPoint = $format['DEC_POINT'];
172 $thousandsSep = $format['THOUSANDS_SEP'];
173 $decimals = $format['DECIMALS'];
174 $regExp = '/^\d{1,3}(('.$thousandsSep.'){0,1}\d{3})*(\\'.$decPoint.'\d{1,'.$decimals.'})?$/';
175 if($thousandsSep && $decPoint)
176 {
177 if ($decimals > 0)
178 {
179 $regExp = '/^\d{1,3}(('.$thousandsSep.'){0,1}\d{3})*(\\'.$decPoint.'\d{1,'.$decimals.'})?$/';
180 }
181 else
182 {
183 $regExp = '/^\d{1,3}(('.$thousandsSep.'){0,1}\d{3})*$/';
184 }
185 }
186 elseif($thousandsSep && !$decPoint)
187 {
188 $regExp = '/^\d{1,3}(('.$thousandsSep.'){0,1}\d{3})*$/';
189 }
190 elseif(!$thousandsSep && $decPoint)
191 {
192 if ($decimals > 0)
193 {
194 $regExp = '/^[0-9]*(\\'.$decPoint.'\d{1,'.$decimals.'})?$/';
195 }
196 else
197 {
198 $regExp = '/^[0-9]*$/';
199 }
200 }
201 elseif(!$thousandsSep && !$decPoint)
202 {
203 $regExp = '/^[0-9]*$/';
204 }
205 if(!preg_match($regExp, $currentValue))
206 {
207 $result[] = Loc::getMessage('CIMP_FORMAT_ERROR');
208 }
209 }
210 else
211 {
212 $result[] = Loc::getMessage('CIMP_FORMAT_ERROR');
213 }
214
215 return $result;
216 }
217
225 public static function getLength($property, $value)
226 {
227 return mb_strlen(trim($value['VALUE'], "\n\r\t"));
228 }
229
237 public static function convertToDB($property, $value)
238 {
239 return $value;
240 }
241
249 public static function convertFromDB($property, $value)
250 {
251 return $value;
252 }
253
254 public static function getSeparatedValues($value)
255 {
256 $explode = is_string($value) ? explode(self::SEPARATOR, $value) : [];
257 $currentValue = (isset($explode[0]) && $explode[0] !== '' ? $explode[0] : '');
258 $currentCurrency = $explode[1] ?? '';
259 $format = \CCurrencyLang::GetFormatDescription($currentCurrency);
260 $explode = explode($format['DEC_POINT'], $currentValue);
261 $currentValue = ($explode[0] !== '' ? $explode[0] : '');
262 $decimalsValue = $explode[1] ?? '';
263 return array(
264 'AMOUNT' => $currentValue,
265 'CURRENCY' => $currentCurrency,
266 'DECIMALS' => $decimalsValue
267 );
268 }
269
270 public static function getUnitedValue($amount, string $currency): string
271 {
272 return
273 ($amount === '')
274 ? ''
275 : $amount.self::SEPARATOR.$currency
276 ;
277 }
278
288 public static function addFilterFields($property, $controlSettings, &$filter, &$filtered)
289 {
290 $filtered = false;
291
292 if(isset($_REQUEST[$controlSettings['VALUE']]))
293 {
294 $value = $_REQUEST[$controlSettings['VALUE']];
295 }
296 elseif(isset($controlSettings["FILTER_ID"]))
297 {
298 $filterOption = new \Bitrix\Main\UI\Filter\Options($controlSettings["FILTER_ID"]);
299 $filterData = $filterOption->getFilter();
300 if(!empty($filterData[$controlSettings['VALUE']]))
301 $value = $filterData[$controlSettings['VALUE']];
302 }
303
304 if(!empty($value))
305 {
306 $explode = explode(self::SEPARATOR, $value);
307 if(empty($explode[1]))
308 {
309 $listCurrency = self::getListCurrency();
310 if($listCurrency)
311 {
312 $filter[$controlSettings['VALUE']] = array();
313 foreach($listCurrency as $currencyType => $currency)
314 {
315 $filter[$controlSettings['VALUE']][] = $value.self::SEPARATOR.$currencyType;
316 }
317 }
318 }
319 $filtered = true;
320 }
321 }
322
323 protected static function getListCurrency(): array
324 {
325 return Editor::getListCurrency();
326 }
327
328 protected static function getJsHandlerSelector($randString, array $listCurrency)
329 {
330 ob_start();
331 ?>
332 <script>
333 if (!window.BX && top.BX)
334 window.BX = top.BX;
335 BX.ready(function() {
336 'use strict';
337 if(!BX.HandlerMoneyField) {
338 BX.HandlerMoneyField = function(params) {
339 this.randomString = params.randomString;
340 this.listCurrency = params.listCurrency;
341 this.defaultSeparator = params.defaultSeparator;
342 setTimeout(BX.proxy(this.setDefaultParams, this), 300);
343 };
344 BX.HandlerMoneyField.prototype.setDefaultParams = function() {
345 this.input = BX('input-' + this.randomString);
346 this.hidden = BX('hidden-' + this.randomString);
347 this.selector = BX('selector-' + this.randomString);
348 this.error = BX('error-' + this.randomString);
349 this.init();
350 };
351 BX.HandlerMoneyField.prototype.init = function() {
352 if (!this.input || !this.selector || !this.hidden) return;
353 this.currentCurrency = this.selector.value;
354 this.currentFormat = null;
355 this.oldFormat = {
356 'currentCurrency': this.currentCurrency,
357 'decPoint': this.listCurrency[this.currentCurrency].DEC_POINT,
358 'thousandsSep': this.listCurrency[this.currentCurrency].SEPARATOR
359 };
360 this.availableKey = [8,9,13,36,37,39,38,40,46,18,17,16,188,190,86,65,112,113,114,115,116,117,118,
361 119,120,121,122,123,67,45,34,33,35];
362 this.availableSymbol = [];
363 this.changeCurrency();
364 BX.bind(this.selector, 'change', BX.proxy(this.changeCurrency, this));
365 BX.bind(this.input, 'keydown', BX.proxy(function(event) {this.onkeydown(event)}, this));
366 BX.bind(this.input, 'keyup', BX.proxy(this.onkeyup, this));
367 BX.bind(this.input, 'blur', BX.proxy(this.onblur, this));
368 BX.bind(this.input, 'focus', BX.proxy(this.onfocus, this));
369 BX.addCustomEvent(window, 'onAddNewRowBeforeInner', BX.proxy(function(htmlObject) {
370 var regExp = new RegExp('data-id=".+?"', 'g'), oldId;
371 var match = htmlObject.html.match(regExp);
372 if(match) match = match[0].match(/"([^"]*)"/i);
373 if(match) oldId = match[1];
374 if(this.randomString == oldId)
375 {
376 var newId = BX.util.getRandomString(6).toLowerCase();
377 htmlObject.html = htmlObject.html.replace(new RegExp(oldId, 'g'), newId);
378 }
379 }, this));
380 };
381 BX.HandlerMoneyField.prototype.changeCurrency = function() {
382 this.currentCurrency = (BX.proxy_context && BX.proxy_context.value) ?
383 BX.proxy_context.value : this.selector.value;
384 this.currentFormat = this.listCurrency[this.currentCurrency].FORMAT;
385 this.decPoint = this.listCurrency[this.currentCurrency].DEC_POINT;
386 this.thousandsSep = this.listCurrency[this.currentCurrency].SEPARATOR;
387 this.decimals = this.listCurrency[this.currentCurrency].DECIMALS;
388 if(this.realValue)
389 {
390 var regExp = this.oldFormat.thousandsSep ? '\\'+this.oldFormat.thousandsSep : '';
391 this.realValue = this.realValue.replace(new RegExp(regExp, 'g'),'');
392 this.input.value = this.oldFormat.decPoint ?
393 this.realValue.replace(this.oldFormat.decPoint,this.decPoint) : this.realValue;
394 }
395 this.oldFormat = {
396 'currentCurrency': this.currentCurrency,
397 'decPoint': this.decPoint,
398 'thousandsSep': this.thousandsSep
399 };
400 this.setRealValue();
401 this.setVisibleValue(true);
402 this.setHiddenValue();
403 var decimals = '';
404 for(var i = 1; i <= this.decimals; i++)
405 decimals += i;
406 this.availableSymbol.push(this.thousandsSep);
407 this.availableSymbol.push(this.decPoint);
408 this.regExp = '';
409 this.isDecimalsNull = (!parseInt(this.decimals));
410 if(this.thousandsSep && this.decPoint)
411 {
412 if (this.isDecimalsNull)
413 {
414 this.regExp = '^\\d{1,3}('+this.thousandsSep+'?\\d{3})*$';
415 this.exampleValue = '6'+this.thousandsSep+'456';
416 }
417 else
418 {
419 this.regExp = '^\\d{1,3}('+this.thousandsSep+
420 '?\\d{3})*(\\'+this.decPoint+'\\d{1,'+this.decimals+'})?$';
421 this.exampleValue = '6'+this.thousandsSep+'456'+this.decPoint+decimals;
422 }
423 }
424 else if(this.thousandsSep && !this.decPoint)
425 {
426 this.regExp = '^\\d{1,3}('+this.thousandsSep+'?\\d{3})*$';
427 this.exampleValue = '6'+this.thousandsSep+'456';
428 }
429 else if(!this.thousandsSep && this.decPoint)
430 {
431 if (this.isDecimalsNull)
432 {
433 this.regExp = '^[0-9]*$';
434 this.exampleValue = '6456';
435 }
436 else
437 {
438 this.regExp = '^[0-9]*(\\'+this.decPoint+'\\d{1,'+this.decimals+'})?$';
439 this.exampleValue = '6456'+this.decPoint+decimals;
440 }
441 }
442 else if(!this.thousandsSep && !this.decPoint)
443 {
444 this.regExp = '^[0-9]*$';
445 this.exampleValue = '6456';
446 }
447 this.checkFormatValue();
448 };
449 BX.HandlerMoneyField.prototype.onkeydown = function(event) {
450 this.setTextError();
451 if (!BX.util.in_array(event.key, this.availableSymbol)
452 && !BX.util.in_array(event.keyCode,this.availableKey)) {
453 if (isNaN(parseInt(event.key))) {
454 this.setTextError(BX.message('CIMP_INPUT_FORMAT_ERROR')
455 .replace('#example#', this.exampleValue));
456 return BX.PreventDefault(event);
457 }
458 }
459 };
460 BX.HandlerMoneyField.prototype.onkeyup = function() {
461 this.setRealValue();
462 this.setHiddenValue();
463 this.setVisibleValue(true);
464 };
465 BX.HandlerMoneyField.prototype.onblur = function() {
466 this.setRealValue();
467 this.setHiddenValue();
468 this.setVisibleValue(true);
469 this.setTextError();
470 this.checkFormatValue();
471 };
472 BX.HandlerMoneyField.prototype.onfocus = function() {
473 this.input.value = this.realValue;
474 };
475 BX.HandlerMoneyField.prototype.getTemplateValue = function() {
476 return this.currentFormat.replace(new RegExp('(^|[^&])#'), '$1' + this.realValue);
477 };
478 BX.HandlerMoneyField.prototype.checkFormatValue = function() {
479 if(!this.realValue) return;
480 var regExp = new RegExp(this.regExp);
481 if(!this.realValue.match(regExp))
482 {
483 this.setTextError(BX.message('CIMP_INPUT_FORMAT_ERROR')
484 .replace('#example#', this.exampleValue));
485 }
486 else
487 {
488 this.setTextError();
489 }
490 };
491 BX.HandlerMoneyField.prototype.setTextError = function(text) {
492 this.error.innerHTML = text ? text : '';
493 };
494 BX.HandlerMoneyField.prototype.setRealValue = function() {
495 this.realValue = this.getFormatValue();
496 };
497 BX.HandlerMoneyField.prototype.setVisibleValue = function(useTemplate) {
498 this.input.value = this.input.value ? !useTemplate ?
499 this.getTemplateValue() : this.getFormatValue(): '';
500 };
501 BX.HandlerMoneyField.prototype.setHiddenValue = function() {
502 if (this.input.value)
503 {
504 var regExp = this.thousandsSep ? '\\'+this.thousandsSep : '';
505 this.hidden.value = this.realValue.replace(new RegExp(regExp, 'g'), '') +
506 this.defaultSeparator + this.currentCurrency;
507 }
508 else
509 {
510 this.hidden.value = '';
511 }
512 };
513 BX.HandlerMoneyField.prototype.getFormatValue = function() {
514 var baseValue = this.input.value;
515 var valueLength = baseValue.length;
516 var formatValue = "";
517 var regExp;
518 if(this.thousandsSep == ',' || this.thousandsSep == '.')
519 regExp = new RegExp('['+this.decPoint+']');
520 else
521 regExp = new RegExp('['+this.decPoint+',.]');
522 var decPointPosition = baseValue.match(regExp);
523 decPointPosition = decPointPosition == null ? baseValue.length : decPointPosition.index;
524 var countDigit = 0;
525 for(var i = 0; i < baseValue.length; i++)
526 {
527 var symbolPosition = baseValue.length-1-i;
528 var symbol = baseValue.charAt(symbolPosition);
529 var isDigit = ('0123456789'.indexOf(symbol) >= 0);
530 if(isDigit) countDigit++;
531 if(symbolPosition == decPointPosition) countDigit = 0;
532 if(symbolPosition >= decPointPosition)
533 {
534 if(this.decPoint == '.' && symbol == ',')
535 symbol = this.decPoint;
536 if(this.decPoint == ',' && symbol == '.')
537 symbol = this.decPoint;
538 if(isDigit || (symbolPosition == decPointPosition && symbol == this.decPoint))
539 formatValue = symbol + formatValue;
540 else
541 if(valueLength > symbolPosition) valueLength--;
542 }
543 if(symbolPosition < decPointPosition)
544 {
545 if(isDigit)
546 formatValue = symbol+formatValue;
547 else
548 if(valueLength > symbolPosition) valueLength--;
549 if(isDigit && countDigit % 3 == 0 && countDigit !== 0 && symbolPosition !== 0)
550 {
551 formatValue = this.thousandsSep + formatValue;
552 if(valueLength >= symbolPosition) valueLength++;
553 }
554 }
555 }
556 if(this.decimals > 0)
557 {
558 decPointPosition = formatValue.match(new RegExp('['+this.decPoint+']'));
559 decPointPosition = decPointPosition == null ? formatValue.length : decPointPosition.index;
560 while(formatValue.length-1-decPointPosition > this.decimals)
561 {
562 if(valueLength >= formatValue.length-1) valueLength--;
563 formatValue = formatValue.substr(0, formatValue.length - 1);
564 }
565 }
566
567 return formatValue;
568 };
569 }
570 var handlerMoneyField = new BX.HandlerMoneyField({
571 randomString: '<?=$randString?>',
572 defaultSeparator: '<?=self::SEPARATOR?>',
573 listCurrency: <?=Json::encode($listCurrency)?>
574 });
575 BX.message({
576 CIMP_INPUT_FORMAT_ERROR: '<?=GetMessageJS('CIMP_INPUT_FORMAT_ERROR')?>'
577 });
578 });
579 </script>
580 <?
581 $script = ob_get_contents();
582 ob_end_clean();
583 return $script;
584 }
585
586 public static function GetUIEntityEditorProperty($settings, $value)
587 {
588 if (method_exists(BaseForm::class, 'getAdditionalMoneyValues'))
589 {
590 return [
591 'type' => $settings['MULTIPLE'] === 'Y' ? 'multimoney' : 'money',
592 ];
593 }
594
595 return [
596 'type' => 'money',
597 ];
598 }
599}
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29