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]);
118 if ($event->getResults())
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);
241 $nextNumber = $this->template;
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);
278 public static function update($numId, $config)
280 $numerator = static::create();
281 $config[static::getType()][
'idFromDb'] = $numId;
282 $result = $numerator->setNumeratorConfig($config);
283 if ($result->isSuccess())
285 $result = $numerator->setGeneratorsConfig($config);
286 if ($result->isSuccess())
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,
334 if ($result->isSuccess())
336 $this->
id = $result->getId();
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();
374 $result = $numerator->setConfig($config);
375 if (($result->isSuccess()))
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'));
412 $result = NumeratorTable::delete((
int)$id);
413 if ($result->isSuccess())
415 NumeratorSequenceTable::deleteByNumeratorId($id);
424 public function previewNextNumber($hash =
null)
426 $this->setNumberHashForGenerators($hash);
427 $nextNumber = $this->template;
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);
499 static::getType() => [
500 'name' => $this->name,
501 'template' => $this->template,
503 'code' => $this->code,
504 'type' => $this->type,
507 $generatorConfigs = [];
508 foreach ($this->generators as $generator)
512 $generatorConfigs[$this->getTypeOfGenerator($generator)] = $generator->getConfig();
515 return $selfConfig + $generatorConfigs;
525 $result = $this->setNumeratorConfig($config);
526 if (!$result->isSuccess())
531 return $this->setGeneratorsConfig($config);
538 private function setNumeratorConfig($config)
540 $result = $this->validate($config);
541 if (!$result->isSuccess())
545 $this->type = trim($config[static::getType()][
'type']);
546 $this->
setTemplate($config[static::getType()][
'template']);
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()]))
554 $code = $config[static::getType()][
'code'];
555 if (is_string($code))
560 $this->code = (is_string($code) && !empty($code)) ? $code : null;
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);
601 $result = $this->validateGeneratorsConfig($config);
603 if ($result->isSuccess())
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)
645 $result[$type] = $class::getTemplateWordsForParse();
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)
695 $result =
new Result();
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']))
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)
760 $query =
new Query(NumeratorTable::getEntity());
761 $query->addSelect(
new ExpressionField(
'COUNT',
'COUNT(*)'));
762 $query->where(
'TYPE', $isAvailableForType);
763 $result = $query->exec()->fetch();
764 return $result ? $result[
'COUNT'] + 1 : 1;
771 private function validateGeneratorsConfig($config)
773 $result =
new Result();
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();