protected function insertSystemItem($item) { if ($finder = fx::data($item['target_type'])) { $_this = $this; $itemIdNew = null; $createNew = true; /** * Заполняем данные */ $data = array(); foreach ($item['data'] as $field => $value) { // todo: можно убрать цикл, если нет дополнительной обработки полей if ($field != 'id') { $data[$field] = $value; } } if ($item['target_type'] == 'site') { if ($this->siteNew) { $itemIdNew = $this->siteNew['id']; $createNew = false; } else { /** * Ищем сайт по домену */ if ($existing = fx::data($item['target_type'])->where('domain', $data['domain'])->one()) { $itemIdNew = $existing['id']; $createNew = false; } } if ($createNew) { /** * index_page_id */ $linkIdOld = $data['index_page_id']; if (false === ($idLinkNew = $this->getIdNewForType($linkIdOld, 'content'))) { $data['index_page_id'] = 0; /** * Добавляем коллбэк на получение ID после импорта всех данных */ $this->addCallbackIdUpdate($item['target_type'], $itemIdNew, 'content', $linkIdOld, 'index_page_id'); } else { $data['index_page_id'] = $idLinkNew; } /** * error_page_id */ $linkIdOld = $data['error_page_id']; if (false === ($idLinkNew = $this->getIdNewForType($linkIdOld, 'content'))) { $data['error_page_id'] = 0; /** * Добавляем коллбэк на получение ID после импорта всех данных */ $this->addCallbackIdUpdate($item['target_type'], $itemIdNew, 'content', $linkIdOld, 'error_page_id'); } else { $data['error_page_id'] = $idLinkNew; } /** * layout_id */ $linkIdOld = $data['layout_id']; if (false === ($idLinkNew = $this->getIdNewForType($linkIdOld, 'layout'))) { $data['layout_id'] = 0; /** * Добавляем коллбэк на получение ID после импорта всех данных */ $this->addCallbackIdUpdate($item['target_type'], $itemIdNew, 'layout', $linkIdOld, 'layout_id'); } else { $data['layout_id'] = $idLinkNew; } } } if ($item['target_type'] == 'layout') { /** * Ищем layout по ключевику */ if ($existing = fx::data($item['target_type'])->where('keyword', $data['keyword'])->one()) { $itemIdNew = $existing['id']; $createNew = false; } } /** * Список линкованных полей полей в зависимости от типа */ if ($item['target_type'] == 'infoblock') { /** * site_id */ $linkIdOld = $data['site_id']; if (false === ($idLinkNew = $this->getIdNewForType($linkIdOld, 'site'))) { $data['site_id'] = 0; /** * Добавляем коллбэк на получение ID после импорта всех данных */ $this->addCallbackIdUpdate($item['target_type'], $itemIdNew, 'site', $linkIdOld, 'site_id'); } else { $data['site_id'] = $idLinkNew; } /** * page_id */ $linkIdOld = $data['page_id']; if (false === ($idLinkNew = $this->getIdNewForType($linkIdOld, 'content'))) { $data['page_id'] = 0; /** * Добавляем коллбэк на получение ID после импорта всех данных */ $this->addCallbackIdUpdate($item['target_type'], $itemIdNew, 'content', $linkIdOld, 'page_id'); } else { $data['page_id'] = $idLinkNew; } /** * parent_infoblock_id */ $linkIdOld = $data['parent_infoblock_id']; if (false === ($idLinkNew = $this->getIdNewForType($linkIdOld, 'infoblock'))) { $data['parent_infoblock_id'] = 0; /** * Добавляем коллбэк на получение ID после импорта всех данных */ $this->addCallbackIdUpdate($item['target_type'], $itemIdNew, 'infoblock', $linkIdOld, 'parent_infoblock_id'); } else { $data['parent_infoblock_id'] = $idLinkNew; } $params = $data['params']; /** * Связи из параметров */ if (isset($params['extra_infoblocks']) and is_array($params['extra_infoblocks'])) { /** * Обновляем параметры через коллбэк */ $this->callbackIdUpdateStack[] = function () use($_this, &$itemIdNew) { if ($itemNew = fx::data('infoblock', $itemIdNew)) { $params = $itemNew['params']; foreach ($params['extra_infoblocks'] as $k => $id) { if (false !== ($idNew = $_this->getIdNewForType($id, 'infoblock'))) { $params['extra_infoblocks'][$k] = $idNew; } else { unset($params['extra_infoblocks'][$k]); } } $itemNew['params'] = $params; $itemNew->save(); } }; } /** * Условия инфоблоков conditions */ if (isset($params['conditions']) and $params['conditions']) { $this->callbackIdUpdateStack[] = function () use($_this, &$itemIdNew, $data) { if ($itemNew = fx::data('infoblock', $itemIdNew)) { $params = $itemNew['params']; $component = fx::controller($data['controller'])->getComponent(); if (isset($_this->metaInfo['component_linked_fields'][$component['keyword']])) { $linkedFields = $_this->metaInfo['component_linked_fields'][$component['keyword']]; /** * Перебираем все поля в условии */ foreach ($params['conditions'] as $k => $fieldCond) { if (isset($linkedFields[$fieldCond['name']]) and $fieldCond['value']) { $linkedField = $linkedFields[$fieldCond['name']]; $valueNew = array(); foreach ($fieldCond['value'] as $id) { if ($linkedField['target_type'] == 'component') { $type = 'content'; } else { $type = $linkedField['target_id']; } if ($idNew = $_this->getIdNewForType($id, $type)) { $valueNew[] = $idNew; } } $params['conditions'][$k]['value'] = $valueNew; } /** * Т.к. инфоблок реализован не через механизм дополнительных полей */ if ($fieldCond['name'] == 'infoblock_id') { $valueNew = array(); foreach ($fieldCond['value'] as $id) { if ($idNew = $_this->getIdNewForType($id, 'infoblock')) { $valueNew[] = $idNew; } } $params['conditions'][$k]['value'] = $valueNew; } } $itemNew['params'] = $params; $itemNew->save(); } } }; } /** * Линкованные параметры */ // они обрабатываются автоматически за счет обычных связей в линкере, по аналогии с типом many-many } if ($item['target_type'] == 'infoblock_visual') { /** * infoblock_id */ $linkIdOld = $data['infoblock_id']; if (false === ($idLinkNew = $this->getIdNewForType($linkIdOld, 'infoblock'))) { $data['infoblock_id'] = 0; /** * Добавляем коллбэк на получение ID после импорта всех данных */ $this->addCallbackIdUpdate($item['target_type'], $itemIdNew, 'infoblock', $linkIdOld, 'infoblock_id'); } else { $data['infoblock_id'] = $idLinkNew; } /** * layout_id */ $linkIdOld = $data['layout_id']; if (false === ($idLinkNew = $this->getIdNewForType($linkIdOld, 'layout'))) { $data['layout_id'] = 0; /** * Добавляем коллбэк на получение ID после импорта всех данных */ $this->addCallbackIdUpdate($item['target_type'], $itemIdNew, 'layout', $linkIdOld, 'layout_id'); } else { $data['layout_id'] = $idLinkNew; } /** * area */ if (preg_match('#^(.+_)(\\d+)$#', $data['area'], $match)) { $this->callbackIdUpdateStack[] = function () use($_this, &$itemIdNew, $match) { if ($itemNew = fx::data('infoblock_visual', $itemIdNew)) { if ($itemNew and false !== ($idNew = $_this->getIdNewForType($match[2], 'infoblock'))) { $itemNew['area'] = $match[1] . $idNew; $itemNew->setNeedRecountFiles(false); $itemNew->save(); } } }; } /** * Получаем ссылки на контент из визуальных параметров */ $visuals = $data['template_visual']; if (is_array($visuals)) { $startCallback = false; foreach ($visuals as $name => $value) { /** * Ищем линки на изображения */ if (preg_match('#^\\/floxim_files\\/#i', $value)) { $visuals[$name] = $_this->importFile($value); } if (!$startCallback and preg_match('#^(.+_)(\\d+)$#', $name, $match)) { /** * Есть ссылочные параметры - запускаем коллбэк обработку */ $this->callbackIdUpdateStack[] = function () use($_this, &$itemIdNew) { if ($itemNew = fx::data('infoblock_visual', $itemIdNew)) { $visuals = $itemNew['template_visual']; foreach ($visuals as $name => $value) { if (preg_match('#^(.+_)(\\d+)$#', $name, $match)) { unset($visuals[$name]); if ($idNew = $_this->getIdNewForType($match[2], 'content')) { $visuals[$match[1] . $idNew] = $value; } } } $itemNew['template_visual'] = $visuals; $itemNew->setNeedRecountFiles(false); $itemNew->save(); } }; $startCallback = true; } } $data['template_visual'] = $visuals; } } if ($createNew) { $itemNew = $finder->create($data); if ($item['target_type'] == 'infoblock_visual') { /** * Отключаем специфичную обработку * Далее она сработает при сохранении из коллбэков */ $itemNew->setNeedRecountFiles(false); } $itemNew->save(); $itemIdNew = $itemNew['id']; } $this->mapIds[$item['target_type']][$item['target_id']] = $itemIdNew; } }
protected function exportSystemItems($type, $ids) { if (!is_array($ids)) { $ids = array($ids); } $ids = array_unique($ids); if (isset($this->systemItemsForExport[$type])) { $ids = array_diff($ids, $this->systemItemsForExport[$type]); } else { $this->systemItemsForExport[$type] = array(); } if (!$ids) { return; } /** * Сразу блокируем повторный экспорт */ $this->systemItemsForExport[$type] = array_merge($this->systemItemsForExport[$type], $ids); $usedSystemItems = array(); $usedContentItems = array(); $_this = $this; $this->readDataTable($type, array(array('id', $ids)), function ($item) use($_this, $type, &$usedSystemItems, &$usedContentItems, $ids) { $needSave = true; /** * Хардкодим для специфичных типов */ if ($type == 'infoblock') { /** * Проверяем принадлежность инфоблока к корневому дереву */ if (!$this->exportSite and !in_array($item['page_id'], $_this->contentsRootTreeForExport)) { //$needSave=false; return; } /** * Формируем список дополнительных элементов по связям */ /** * Экспортируем привязанные к инфоблокам infoblock_visual */ $this->exportSystemItemsByField('infoblock_visual', 'infoblock_id', $item['id']); /** * Парент */ if ($item['parent_infoblock_id'] and (!isset($usedSystemItems['infoblock']) or !in_array($item['parent_infoblock_id'], $usedSystemItems['infoblock']))) { $usedSystemItems['infoblock'][] = $item['parent_infoblock_id']; } /** * Сайт * todo: здесь нужно продумать, т.к. не понятно для чего экспортить сайт, если мы сделать экспорт только ветки дерева */ if ($item['site_id'] and (!isset($usedSystemItems['site']) or !in_array($item['site_id'], $usedSystemItems['site']))) { //$usedSystemItems['site'][] = $item['site_id']; } /** * Страница контента */ if ($item['page_id'] and !in_array($item['page_id'], $usedContentItems)) { $usedContentItems[] = $item['page_id']; } /** * Связи из параметров */ $params = $item['params']; if (isset($params['extra_infoblocks']) and is_array($params['extra_infoblocks'])) { foreach ($params['extra_infoblocks'] as $id) { $usedSystemItems['infoblock'][] = $id; } } /** * Условия инфоблоков conditions */ if (isset($params['conditions']) and $params['conditions']) { /** * Получаем компонент через контроллер инфоблока, он необходим для получения списка линкованных полей */ $component = fx::controller($item['controller'])->getComponent(); $linkedFields = $_this->getLinkedFieldsForComponent($component); /** * Перебираем все поля в условии */ foreach ($params['conditions'] as $fieldCond) { if (isset($linkedFields[$fieldCond['name']]) and $fieldCond['value']) { $linkedField = $linkedFields[$fieldCond['name']]; $_this->processingLinkedField($linkedField, $fieldCond['value'], null, $usedContentItems, $usedSystemItems); } /** * Т.к. инфоблок реализован не через механизм дополнительных полей */ if ($fieldCond['name'] == 'infoblock_id') { $usedSystemItems['infoblock'] = array_merge($usedSystemItems['infoblock'], $fieldCond['value']); } } } /** * Линкованные параметры */ $finder = fx::data('floxim.main.linker'); if ($linkers = $finder->where('infoblock_id', $item['id'])->all()->getValues('linked_id')) { $usedContentItems = array_merge($usedContentItems, $linkers); } } elseif ($type == 'infoblock_visual') { /** * layout_id */ if ($item['layout_id'] and (!isset($usedSystemItems['layout']) or !in_array($item['layout_id'], $usedSystemItems['layout']))) { $usedSystemItems['layout'][] = $item['layout_id']; } /** * todo: решить, что делать с infoblock_id (по идеи все infoblock_visual экспортируются через связь с инфоблоками, которые уже экспортированы) */ /** * Получаем ссылки на контент из визуальных параметров * todo: проблема - ссылки могут быть не только на контент, но и на инфоблоки, в итоге валит ошибку. Нужно рефакторить ядро. */ $visuals = $item['template_visual']; if (is_array($visuals)) { foreach ($visuals as $name => $value) { if (preg_match('#._(\\d+)$#', $name, $match)) { if (!in_array($match[1], $usedContentItems)) { $usedContentItems[] = $match[1]; } } /** * Ищем линки на изображения */ if (preg_match('#^\\/floxim_files\\/#i', $value)) { $_this->exportFile($value); } } } } elseif ($type == 'site') { /** * layout_id */ if ($item['layout_id'] and (!isset($usedSystemItems['layout']) or !in_array($item['layout_id'], $usedSystemItems['layout']))) { $usedSystemItems['layout'][] = $item['layout_id']; } } if ($needSave) { /** * Сохраняем элемент в файл */ $_this->saveTableRowToFile($item, $type); } }); /** * Экспортируем связанные данные */ foreach ($usedSystemItems as $linkType => $linkIds) { $this->exportSystemItems($linkType, $linkIds); } /** * Связанный контент */ $this->exportContentTreeArray($usedContentItems); }