31 private $generators = [];
48 private function __construct()
57 if (static::$numberGeneratorFactory ===
null)
61 return static::$numberGeneratorFactory;
72 public static function getSettingsFields($numeratorType)
74 $numeratorsAmount = static::getNextNumeratorNumber($numeratorType);
75 $settings = [
'settingsFields' => [],
'settingsWords' => [],];
76 $settings[
'settingsFields'][static::getType()] = [
78 'title' => Loc::getMessage(
'TITLE_BITRIX_MAIN_NUMERATOR_NUMERATOR_NAME_TITLE'),
79 'settingName' =>
'name',
81 'default' => Loc::getMessage(
'NUMERATOR_DEFAULT_NUMERATOR_NAME', [
'#NUMBER#' => $numeratorsAmount]),
84 'settingName' =>
'template',
86 'title' => Loc::getMessage(
'TITLE_BITRIX_MAIN_NUMERATOR_NUMERATOR_TEMPLATE_TITLE'),
89 $allGeneratorsClasses = static::getNumberGeneratorFactory()->getClasses();
90 foreach ($allGeneratorsClasses as $class)
93 $isAvailableForAll = $class::getAvailableForType() == static::NUMERATOR_DEFAULT_TYPE;
94 if ($isAvailableForAll || $class::getAvailableForType() == $numeratorType)
96 if (in_array(UserConfigurable::class, class_implements($class)))
98 $settings[
'settingsFields'][$class::getType()] = $class::getSettingsFields();
100 $settings[
'settingsWords'][$class::getType()] = $class::getTemplateWordsSettings();
103 $settings[
'settingsWords'] = array_merge_recursive(
$settings[
'settingsWords'], static::getUserDefinedTemplateWords($numeratorType));
115 $event =
new Event(
'main',
'onBuildNumeratorTemplateWordsList', [
'numeratorType' => $numeratorType]);
121 foreach (
$event->getResults() as $eventResult)
123 $eventParameters = $eventResult->getParameters();
124 if (isset($eventParameters[
'CODE']) && isset($eventParameters[
'NAME']))
126 $settingsWords[
"UserDefinedVirtualGenerator" .
$count++] = [
128 => $eventParameters[
'NAME'],
133 foreach ($eventParameters as $parameters)
135 if (isset($parameters[
'CODE']) && isset($parameters[
'NAME']))
137 $settingsWords[
"UserDefinedVirtualGenerator" .
$count++] = [
139 => $parameters[
'NAME'],
146 return $settingsWords;
161 $type = static::NUMERATOR_DEFAULT_TYPE;
178 $type = static::NUMERATOR_DEFAULT_TYPE;
180 $numeratorSettings = static::getListByType($type);
181 if ($numeratorSettings && isset($numeratorSettings[0]))
183 return $numeratorSettings[0];
193 public static function getTemplateWordsForType($isAvailableByType =
null)
195 if (is_null($isAvailableByType))
197 $isAvailableByType = static::NUMERATOR_DEFAULT_TYPE;
200 $allGeneratorsClasses = static::getNumberGeneratorFactory()->getClasses();
201 foreach ($allGeneratorsClasses as $class)
204 $isAllTypesNeeded = $isAvailableByType === static::NUMERATOR_ALL_GENERATORS_TYPE;
205 $isAvailableByDefault = $class::getAvailableForType() == static::NUMERATOR_DEFAULT_TYPE;
206 if ($isAllTypesNeeded || $isAvailableByDefault || $class::getAvailableForType() == $isAvailableByType)
208 $settings = array_merge(
$settings, [$class::getType() => $class::getTemplateWordsForParse()]);
217 private function setNumberHashForGenerators(
$hash)
219 foreach ($this->generators as $index => $generator)
221 if ($generator instanceof Sequenceable)
223 $generator->setNumberHash(
$hash);
238 public function getNext(
$hash =
null)
240 $this->setNumberHashForGenerators(
$hash);
242 foreach ($this->generators as $index => $generator)
245 $nextNumber = $generator->parseTemplate($nextNumber);
254 private function setDynamicConfigForGenerators($dynamicConfig)
256 if ($dynamicConfig !==
null)
258 foreach ($this->generators as $generator)
260 if ($generator instanceof DynamicConfigurable)
262 $generator->setDynamicConfig($dynamicConfig);
280 $numerator = static::create();
281 $config[static::getType()][
'idFromDb'] = $numId;
288 return $numerator->save();
304 $this->setNumberHashForGenerators($hashable->getHash());
314 $this->setDynamicConfigForGenerators($dynamicConfig);
326 $settingsToStore = $this->getSettings();
328 'CODE' => $this->code,
329 'NAME' => $this->name,
330 'TEMPLATE' => $this->
template,
331 'TYPE' => $this->type ? $this->type : static::NUMERATOR_DEFAULT_TYPE,
332 'SETTINGS' => $settingsToStore,
345 private function getSettings()
347 $settingsToStore = [];
348 foreach ($this->generators as $numberGenerator)
353 $settingsToStore = array_merge($settingsToStore, [$this->getTypeOfGenerator($numberGenerator) => $numberGenerator->getConfig(),]);
356 return $settingsToStore;
369 public static function load($numeratorId, $source =
null)
373 $numerator =
new static();
377 $numerator->setDynamicConfig($source);
378 $numerator->setHash($source);
406 public static function delete($id)
410 return (
new Result())->addError(
new Error(
'Numerator id is required'));
415 NumeratorSequenceTable::deleteByNumeratorId($id);
424 public function previewNextNumber(
$hash =
null)
426 $this->setNumberHashForGenerators(
$hash);
428 foreach ($this->generators as $index => $generator)
431 $nextNumber = $generator->parseTemplateForPreview($nextNumber);
446 $this->setNumberHashForGenerators(
$hash);
447 foreach ($this->generators as $generator)
451 return $generator->getNextNumber($this->
id);
462 foreach ($this->generators as $generator)
482 $this->setNumberHashForGenerators(
$hash);
483 foreach ($this->generators as $generator)
487 return $generator->setNextNumber($this->
id, $nextNumber, $whereNumber);
490 return (
new Result())->addError(
new Error(Loc::getMessage(
'NUMERATOR_SET_SEQUENTIAL_IS_IMPOSSIBLE')));
499 static::getType() => [
507 $generatorConfigs = [];
508 foreach ($this->generators as $generator)
512 $generatorConfigs[$this->getTypeOfGenerator($generator)] = $generator->getConfig();
515 return $selfConfig + $generatorConfigs;
531 return $this->setGeneratorsConfig(
$config);
538 private function setNumeratorConfig(
$config)
545 $this->type = trim(
$config[static::getType()][
'type']);
547 $this->name = trim(
$config[static::getType()][
'name']);
548 if (isset(
$config[static::getType()][
'idFromDb']))
550 $this->
id =
$config[static::getType()][
'idFromDb'];
552 if (array_key_exists(
'code',
$config[static::getType()]))
555 if (is_string(
$code))
565 private function createGenerators()
567 $generatorTypesToCreate = $this->getGeneratorTypesByTemplate();
568 if ($this->type === static::NUMERATOR_ALL_GENERATORS_TYPE)
570 return $this->createGeneratorsOfTypes($generatorTypesToCreate);
573 $factory = static::getNumberGeneratorFactory();
574 $typesForCurrentNumerator = [];
575 foreach ($generatorTypesToCreate as $index => $generatorType)
577 $generatorClass = $factory->getClassByType($generatorType);
578 if ($generatorClass::getAvailableForType() === $this->type
579 || $generatorClass::getAvailableForType() === static::NUMERATOR_DEFAULT_TYPE
582 $typesForCurrentNumerator[] = $generatorType;
586 return $this->createGeneratorsOfTypes($typesForCurrentNumerator);
594 private function setGeneratorsConfig(
$config)
596 $generators = $this->createGenerators();
597 foreach ($generators as $index => $generator)
599 $this->addGenerator($generator);
605 foreach ($this->generators as $generator)
607 if ($generator instanceof UserConfigurable)
610 $generator->setConfig(
$config[$this->getTypeOfGenerator($generator)] ??
null);
623 return str_replace(
'\\',
'_', static::class);
631 $this->
template = str_replace([
"\r\n",
"\n"],
'', trim($template));
638 private function getTypeToTemplateWords()
641 $typesToClasses = static::getNumberGeneratorFactory()->getTypeToClassMap();
642 foreach ($typesToClasses as
$type => $class)
654 private function getGeneratorTypesByTemplate()
656 $generatorTypes = [];
657 foreach ($this->getTypeToTemplateWords() as
$type => $words)
659 foreach ($words as $word)
661 if (mb_stripos($this->
template, $word) !==
false)
663 $generatorTypes[
$type] = 1;
668 return array_keys($generatorTypes);
675 private function createGeneratorsOfTypes($generatorTypesToCreate)
678 foreach ($generatorTypesToCreate as
$key => $type)
680 if ($generator = static::getNumberGeneratorFactory()->createGeneratorByType($type))
682 $generators[] = $generator;
693 private function validate($numeratorConfig)
696 if (!isset($numeratorConfig[static::getType()]))
698 $result->addError(
new Error(
'Numerator config is required'));
700 $numeratorBaseConfig = $numeratorConfig[static::getType()];
702 if (isset($numeratorBaseConfig[
'code']))
704 if (is_string($numeratorBaseConfig[
'code']) && !empty($numeratorBaseConfig[
'code']))
707 if ($idWithSameCode !==
null)
709 $id = (int)($numeratorBaseConfig[
'idFromDb'] ??
null);
710 if ($id <= 0 || $idWithSameCode !== $id)
712 $result->addError(
new Error(
'Another numerator with same code already exists'));
716 elseif (is_string($numeratorBaseConfig[
'code']))
718 $result->addError(
new Error(
'Numerator code should be a non-empty string, if it is provided'));
722 $result->addError(
new Error(
'Numerator code should be a string'));
725 if (!(isset($numeratorBaseConfig[
'name']) && $numeratorBaseConfig[
'name']))
727 $result->addError(
new Error(Loc::getMessage(
'NUMERATOR_VALIDATE_NAME_IS_REQUIRED')));
729 $resultTemplate = $this->validateTemplate($numeratorBaseConfig[
'template']);
730 if ($resultTemplate->getErrors())
732 $result->addErrors($resultTemplate->getErrors());
742 private function validateTemplate($template)
744 if (!($template && $template !=
''))
746 return (
new Result())->addError(
new Error(Loc::getMessage(
'NUMERATOR_VALIDATE_TEMPLATE_IS_REQUIRED')));
758 private static function getNextNumeratorNumber($isAvailableForType)
761 $query->addSelect(
new ExpressionField(
'COUNT',
'COUNT(*)'));
762 $query->where(
'TYPE', $isAvailableForType);
771 private function validateGeneratorsConfig(
$config)
774 foreach ($this->generators as $generator)
776 if ($generator instanceof UserConfigurable)
778 $generatorResult = ($generator->validateConfig(
$config));
779 if ($generatorResult->getErrors())
781 $result->addErrors($generatorResult->getErrors());
792 private function addGenerator($generator)
794 $this->generators[] = $generator;
801 private function getTypeOfGenerator($generator)
804 $generatorClass = get_class($generator);
805 return $generatorClass::getType();
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)