Exemplo n.º 1
0
 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;
     }
 }
Exemplo n.º 2
0
 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);
 }