57 if (is_array($config) && isset($config[
'numeratorId']))
59 $this->lastInvocationTime = $config[
'lastInvocationTime'] ??
null;
60 $this->numeratorId = $config[
'numeratorId'];
61 if ($this->isDirectNumeration)
75 $timezonesSettings = static::getTimezoneSettings();
76 foreach ($timezonesSettings as $index => $timezonesSetting)
78 $timezonesSettings[$index][
'settingName'] = $timezonesSetting[
'name'];
79 unset($timezonesSettings[$index][
'name']);
83 'settingName' =>
'length',
'type' =>
'int',
'default' => 0,
84 'title' =>
Loc::getMessage(
'TITLE_BITRIX_MAIN_NUMERATOR_GENERATOR_SEQUENTNUMBERGENERATOR_LENGTH'),
87 'settingName' =>
'padString',
'type' =>
'string',
'default' =>
'0',
88 'title' =>
Loc::getMessage(
'TITLE_BITRIX_MAIN_NUMERATOR_GENERATOR_SEQUENTNUMBERGENERATOR_PAD_STRING'),
91 'settingName' =>
'start',
'type' =>
'int',
'default' => 1,
92 'title' =>
Loc::getMessage(
'TITLE_BITRIX_MAIN_NUMERATOR_GENERATOR_SEQUENTNUMBERGENERATOR_START'),
95 'settingName' =>
'step',
'type' =>
'int',
'default' => 1,
96 'title' =>
Loc::getMessage(
'TITLE_BITRIX_MAIN_NUMERATOR_GENERATOR_SEQUENTNUMBERGENERATOR_STEP'),
99 'settingName' =>
'periodicBy',
'type' =>
'array',
100 'title' =>
Loc::getMessage(
'TITLE_BITRIX_MAIN_NUMERATOR_GENERATOR_SEQUENTNUMBERGENERATOR_PERIODICBY'),
103 'settingName' =>
'default',
'value' =>
'',
104 'title' =>
Loc::getMessage(
'TITLE_BITRIX_MAIN_NUMERATOR_GENERATOR_SEQUENTNUMBERGENERATOR_PERIODICBY_DEFAULT'),
108 'title' =>
Loc::getMessage(
'TITLE_BITRIX_MAIN_NUMERATOR_GENERATOR_SEQUENTNUMBERGENERATOR_PERIODICBY_DAY'),
112 'title' =>
Loc::getMessage(
'TITLE_BITRIX_MAIN_NUMERATOR_GENERATOR_SEQUENTNUMBERGENERATOR_PERIODICBY_MONTH'),
116 'title' =>
Loc::getMessage(
'TITLE_BITRIX_MAIN_NUMERATOR_GENERATOR_SEQUENTNUMBERGENERATOR_PERIODICBY_YEAR'),
121 'settingName' =>
'timezone',
'type' =>
'array',
'values' => $timezonesSettings,
122 'title' =>
Loc::getMessage(
'TITLE_BITRIX_MAIN_NUMERATOR_GENERATOR_SEQUENTNUMBERGENERATOR_TIMEZONE'),
125 'settingName' =>
'isDirectNumeration',
'type' =>
'boolean',
126 'title' =>
Loc::getMessage(
'TITLE_BITRIX_MAIN_NUMERATOR_GENERATOR_SEQUENTNUMBERGENERATOR_ISDIRECTNUMERATION'),
135 static::getPatternFor(static::TEMPLATE_WORD_NUMBER) =>
136 Loc::getMessage(
'BITRIX_MAIN_NUMERATOR_GENERATOR_SEQUENTNUMBERGENERATOR_WORD_NUMBER'),
150 'isDirectNumeration' => (bool)$this->isDirectNumeration,
170 if (!$nextNumberSettings && $createIfEmpty)
174 return $nextNumberSettings;
180 private function getNumberHash()
182 if ($this->numberHash ===
null)
192 for ($tryouts = 0; $tryouts < 50; $tryouts++)
194 $this->nextNumber =
null;
195 $this->currentNumber =
null;
197 if (!$nextNumberSettings)
201 $this->lastInvocationTime = $nextNumberSettings[
'LAST_INVOCATION_TIME'];
202 $this->calculateNextAndCurrentNumber($nextNumberSettings[
'NEXT_NUMBER']);
206 $this->getNumberHash(),
208 'NEXT_NUMBER' => $this->nextNumber,
209 'LAST_INVOCATION_TIME' => $this->lastInvocationTime,
211 $nextNumberSettings[
'NEXT_NUMBER']
213 if ($affectedRows == 1)
219 return $this->replaceNumberInPattern($template);
230 return [static::getPatternFor(static::TEMPLATE_WORD_NUMBER)];
236 $nextNumberSettings = $this->
getSettings($this->numeratorId,
false);
237 $this->lastInvocationTime = $nextNumberSettings[
'LAST_INVOCATION_TIME'] ??
$this->nowTime;
238 $this->calculateNextAndCurrentNumber($nextNumberSettings[
'NEXT_NUMBER'] ?? $this->start);
239 return $this->replaceNumberInPattern($template);
242 private function replaceNumberInPattern($template)
245 if ($this->length > 0)
247 $resultNumber = \Bitrix\Main\Text\UtfSafeString::pad($resultNumber, $this->length, $this->padString, STR_PAD_LEFT);
249 return str_replace(static::getPatternFor(static::TEMPLATE_WORD_NUMBER), $resultNumber, $template);
261 if ($nextNumberSettings)
263 return $nextNumberSettings[
'NEXT_NUMBER'];
282 $this->nextNumber = $newNumber;
290 $this->getNumberHash(),
292 'NEXT_NUMBER' => $this->nextNumber,
296 if ($affectedRows == 1)
306 private function resetCurrentNumberIfNeeded()
308 if ($this->periodicBy)
310 if ($this->periodicBy == static::YEAR && $this->isHasChanged(static::YEAR))
314 if ($this->periodicBy == static::MONTH)
316 if ($this->isHasChanged(static::MONTH) || $this->isSameMonthButDifferentYear())
321 if ($this->periodicBy == static::DAY)
323 if ($this->isHasChanged(static::DAY)
324 || $this->isSameDayButDifferent(static::MONTH)
325 || $this->isSameDayButDifferent(static::YEAR))
336 private function isSameMonthButDifferentYear()
338 return $this->getLastInvocationUserTime()->format(
'm') === $this->getNowUserTime()->format(
'm') && $this->isHasChanged(static::YEAR);
345 private function isSameDayButDifferent($interval)
347 $isSameDay = $this->getLastInvocationUserTime()->format(
'd') === $this->getNowUserTime()->format(
'd');
348 if ($interval == static::MONTH)
350 return $isSameDay && $this->isHasChanged(static::MONTH);
352 if ($interval == static::YEAR)
354 return $isSameDay && $this->isHasChanged(static::YEAR);
363 private function isHasChanged($interval)
365 if ($interval == static::MONTH)
367 return $this->getLastInvocationUserTime()->format(
'm') !== $this->getNowUserTime()->format(
'm');
369 if ($interval == static::DAY)
371 return $this->getLastInvocationUserTime()->format(
'd') !== $this->getNowUserTime()->format(
'd');
373 if ($interval == static::YEAR)
375 return $this->getLastInvocationUserTime()->format(
'Y') !== $this->getNowUserTime()->format(
'Y');
383 private static function getTimezoneSettings()
385 $timezones = \CTimeZone::GetZones();
387 foreach ($timezones as $timezoneValue => $timezoneName)
389 $settings[] = [
'name' => $timezoneName,
'value' => $timezoneValue,];
394 private function getNowUserTime()
396 return $this->createDateTimeInCurrentTimezone($this->nowTime);
399 private function getLastInvocationUserTime()
401 return $this->createDateTimeInCurrentTimezone($this->lastInvocationTime);
404 private function createDateTimeInCurrentTimezone($timestamp)
406 $dateTime = \DateTime::createFromFormat(
'U', $timestamp);
409 $result = $dateTime->setTimezone(
new \DateTimeZone($this->timezone));
410 if ($result ===
false)
412 $dateTime = \DateTime::createFromFormat(
'U', $timestamp);
432 if ($this->numberHash ===
null)
438 private function calculateNextAndCurrentNumber($initNumber)
440 $this->currentNumber = $initNumber;
441 $this->resetCurrentNumberIfNeeded();
442 $this->nextNumber = $this->currentNumber +
$this->step;
static loadMessages($file)
static getMessage($code, $replace=null, $language=null)
setFromArrayOrDefault($value, $config, $default=null, $type=null)
setNextNumber($numeratorId, $newNumber, $whereNumber)
getSettings($numeratorId=null, $createIfEmpty=true)
saveNumeratorSequenceSettings($numeratorId, $numberHash, $fields, $whereNextNumber=null)
static setSettings($numeratorId, $numberHash, $defaultNumber, $lastInvocationTime)
static getSettings($numeratorId, $numberHash)
static updateSettings($numeratorId, $numberHash, $fields, $whereNextNumber=null)