27 private const STEP_INIT_BACKGROUND =
'init_background';
28 private const STEP_START =
'start';
29 private const STEP_MANIFEST =
'manifest';
30 private const STEP_CLEAN =
'clean';
31 private const STEP_LOAD =
'load';
32 private const STEP_FINISH =
'finish';
34 private const STEPS_ORDER = [
36 self::STEP_INIT_BACKGROUND,
43 private const COUNT_ADD_FILES_BY_STEP = 200;
45 private $manifestCode;
55 $this->manifestCode = $code;
66 return $this->manifestCode ??
'';
77 public function run(): bool
82 if ($this->
check($data))
90 'run' => self::STEP_START,
92 'currentSection' => 0,
98 switch ($actionInfo[
'run'])
100 case self::STEP_START:
101 $actionInfo[
'setting'] = $this->
doStart();
102 $actionInfo[
'section'] = $actionInfo[
'setting'][
'section'];
104 case self::STEP_INIT_BACKGROUND:
105 $actionInfo[
'setting'] = $this->doInitBackground($actionInfo, $data);
107 case self::STEP_MANIFEST:
109 $actionInfo[
'setting'][
'next'],
114 case self::STEP_CLEAN:
117 (isset($data[
'MANIFEST'][
'SKIP_CLEARING']) && $data[
'MANIFEST'][
'SKIP_CLEARING'] ===
'Y')
118 || (isset($manifest[
'SKIP_CLEARING']) && $manifest[
'SKIP_CLEARING'] ===
'Y')
121 $actionInfo[
'setting'][
'finish'] =
true;
125 $actionInfo[
'section'][
'next'] = $actionInfo[
'section'][
'next'] ??
null;
126 $actionInfo[
'setting'] = $this->
doClean(
127 $actionInfo[
'section'][$actionInfo[
'currentSection']],
128 $actionInfo[
'section'][
'next'],
129 (
int) $actionInfo[
'step']
133 case self::STEP_LOAD:
134 $actionInfo[
'setting'][
'result'] =
true;
135 $type = $actionInfo[
'section'][$actionInfo[
'currentSection']] ??
false;
136 if ($type && isset($data[self::PROPERTY_STRUCTURE][$type][$actionInfo[
'step']]))
139 $http = DataProvider\Controller::getInstance()->get(DataProvider\Controller::CODE_IO);
140 $content = $http->getContent($path, $actionInfo[
'step']);
141 if (!empty($content[
'ERROR_CODE']))
145 'REST_CONFIGURATION_IMPORT_ERROR_CONTENT',
147 '#STEP#' => $actionInfo[
'step'],
153 $content[
'ERROR_CODE'],
154 $actionInfo[
'section'][$actionInfo[
'currentSection']],
161 if ($content[
'COUNT'] === 0)
163 $content[
'COUNT'] = count($data[self::PROPERTY_STRUCTURE][$type]);
166 if ($content[
'SANITIZE'])
170 'REST_CONFIGURATION_IMPORT_ERROR_SANITIZE_SHORT',
172 '#STEP#' => $actionInfo[
'step']
179 $actionInfo[
'currentSection'],
187 if (!is_null($content[
'DATA']))
189 $actionInfo[
'setting'][
'step'] = $actionInfo[
'setting'][
'step'] ??
null;
190 $actionInfo[
'setting'] = $this->
doLoad(
191 $actionInfo[
'setting'][
'step'],
192 $actionInfo[
'section'][$actionInfo[
'currentSection']],
197 $actionInfo[
'setting'][
'next'] = !$actionInfo[
'setting'][
'result'];
200 case self::STEP_FINISH:
201 $actionInfo[
'setting'] = $this->
doFinish();
214 if (!empty($exception))
221 $actionInfo[
'step']++;
223 !array_key_exists(
'next', $actionInfo[
'setting'])
224 || $actionInfo[
'setting'][
'next'] ===
false
227 $actionInfo[
'currentSection']++;
228 $actionInfo[
'step'] = 0;
232 !array_key_exists(
'finish', $actionInfo[
'setting'])
233 && !isset($actionInfo[
'section'][$actionInfo[
'currentSection']])
236 isset($actionInfo[
'setting'][
'finish'])
237 && $actionInfo[
'setting'][
'finish'] ===
true
241 $actionInfo[
'setting'][
'finish'] =
false;
242 $actionInfo[
'currentSection'] = 0;
243 $actionInfo[
'step'] = 0;
244 $key = array_search($actionInfo[
'run'], self::STEPS_ORDER);
249 $actionInfo[
'run'] = self::STEPS_ORDER[$key] ??
false;
263 protected function check(array $data): bool
266 if (!empty($data[self::PROPERTY_MANIFEST][
'CODE']))
296 'ADDITIONAL_OPTION' => $additionalOption,
299 foreach ($items as $item)
302 if ($item[
'NEXT'] !==
false)
304 $result[
'next'] = $item[
'NEXT'];
305 $result[
'finish'] =
false;
320 public function doClean($code, $step, $next,
bool $clearFull =
false): array
329 $data = Controller::callEventClear(
336 'CLEAR_FULL' => $clearFull,
337 'PREFIX_NAME' =>
Loc::getMessage(
'REST_CONFIGURATION_INSTALL_CLEAR_PREFIX_NAME'),
340 'ADDITIONAL_OPTION' => $additionalOption,
346 if (isset($data[
'NEXT']))
348 $result[
'next'] = $data[
'NEXT'];
362 public function doLoad($step, $code, $content): array
368 if ($content[
'COUNT'] > $step)
370 $result[
'result'] =
false;
373 if (!is_null($content[
'DATA']))
377 $dataList = Controller::callEventImport(
380 'CONTENT' => $content,
386 'ADDITIONAL_OPTION' => $additionalOption,
390 foreach ($dataList as $data)
392 if (is_array($data[
'RATIO']))
394 if (empty($ratio[$code]))
398 foreach ($data[
'RATIO'] as $old => $new)
400 $ratio[$code][$old] = $new;
420 private function doInitBackground($actionInfo, $data): array
423 $next = $actionInfo[
'step'];
424 $structure =
new Structure($this->setting->getContext());
428 $chunkList = array_chunk($data[self::PROPERTY_FILES], self::COUNT_ADD_FILES_BY_STEP);
429 if (!empty($chunkList[$next]))
431 $structure->addFileList(
448 if (!empty($actionInfo[
'next']) && (
int)$actionInfo[
'next'] === 0)
452 foreach ($data[self::PROPERTY_STRUCTURE] as $path)
454 if (is_string($path) && mb_strpos($path, $fileName) !==
false)
458 $content = File::getFileContents($path);
459 $structure->unpackSmallFiles($content);
461 catch (\Exception $e)
468 elseif (!empty($actionInfo[
'next']) && (
int)$actionInfo[
'next'] > 0)
496 $section = Controller::getEntityCodeList();
497 $result[
'section'] = array_values($section);
499 if (!is_array($app) && $app !==
null)
501 $app = \Bitrix\Rest\AppTable::getByClientId($app);
509 if (!empty($option[
'UNINSTALL_APP_ON_FINISH']))
530 'createItemList' => [],
535 if (!empty($app[
'ID']))
540 $updateResult = AppTable::update(
549 $result[
'result'] = $updateResult->isSuccess();
553 $result[
'result'] =
true;
563 if (!empty($uninstallAppCode))
565 $res = AppTable::getList(
568 "=CODE" => $uninstallAppCode,
573 if ($appInfo = $res->fetch())
576 $checkResult = AppTable::checkUninstallAvailability($appInfo[
'ID'], $clean);
577 if ($checkResult->isEmpty())
579 $result[
'result'] =
true;
585 AppTable::update($appInfo[
'ID'], $appFields);
595 $eventResult = Controller::callEventFinish(
603 'APP_ID' => ($app[
'ID'] > 0) ? $app[
'ID'] : 0,
604 'USER_ID' => $userId,
605 'ADDITIONAL_OPTION' => $additionalOption,
609 foreach ($eventResult as $data)
611 if (is_array($data[
'CREATE_DOM_LIST']))
613 $result[
'createItemList'] = array_merge($result[
'createItemList'], $data[
'CREATE_DOM_LIST']);
616 if (is_array($data[
'ADDITIONAL']))
618 $result[
'additional'] = array_merge($result[
'additional'], $data[
'ADDITIONAL']);
621 $result[
'finish'] = $result[
'result'];
631 !isset($data[
'MANIFEST'][
'CODE'])
636 'error' => static::ERROR_MANIFEST_IS_NOT_AVAILABLE,
637 'error_description' =>
'Manifest is not available.',
649 public function get(): array
652 $result = parent::get();
654 if ($status === self::STATUS_PROCESS || $status === self::STATUS_ERROR)
658 $result[
'progress'] = [
659 'action' => $actionInfo[
'run'],
660 'step' => $actionInfo[
'step'],
663 !empty($actionInfo[
'section'][$actionInfo[
'currentSection']])
664 && !empty($actionInfo[
'run'])
665 && $actionInfo[
'run'] !== self::STEP_FINISH
668 $result[
'progress'][
'section'] = $actionInfo[
'section'][$actionInfo[
'currentSection']];
672 elseif ($status === self::STATUS_FINISH)
674 $result[
'additional'] = $actionInfo[
'setting'][
'additional'] ?? [];
675 $result[
'createItemList'] = $actionInfo[
'setting'][
'createItemList'] ?? [];
static getMessage($code, $replace=null, $language=null)
const ACTION_TYPE_UNINSTALL
static log($appId, $action)
const ACTION_TYPE_INSTALL
static uninstall($appId, $clean=0)
static setSkipRemoteUpdate($v)
getNotificationInstance()
setStatus(string $status)
doClean($code, $step, $next, bool $clearFull=false)
doLoad($step, $code, $content)
const ERROR_MANIFEST_IS_NOT_AVAILABLE
doInitManifest(?string $next, int $step, string $type)
doStart($app=null, string $mode=Helper::MODE_IMPORT, array $option=[])
doFinish(string $mode=Helper::MODE_IMPORT)
const STRUCTURE_FILES_NAME
const CONFIGURATION_FILE_EXTENSION
const STRUCTURE_SMALL_FILES_NAME
static callEventInit($code, $params=[])
static isRestImportAvailable(string $entityCode)
const SETTING_ACTION_INFO
const SETTING_ACTION_ADDITIONAL_OPTION
const SETTING_UNINSTALL_APP_CODE