/** * Парсинг XML и импортв БД товаров. * @param $filename - путь к файлу архива с данными. */ public function processImportXml($filename) { $importOnlyNew = false; $sep = DIRECTORY_SEPARATOR; $dirname = dirname(__FILE__); $realDocumentRoot = str_replace($sep . 'mg-core' . $sep . 'controllers', '', $dirname); $lastPositionProduct = $_SESSION['lastCountProduct1cImport']; $lastPositionOffer = $_SESSION['lastCountOffer1cImport']; $xml = $this->getImportXml($filename); if ($xml && $filename == 'import.xml') { foreach ($xml->Каталог->attributes() as $key => $val) { if ($key == 'СодержитТолькоИзменения' && $val == "true") { $importOnlyNew = true; } } if (isset($xml->Каталог->СодержитТолькоИзменения)) { $importOnlyNew = $xml->Каталог->СодержитТолькоИзменения[0] == 'true' ? true : false; } if (empty($lastPositionProduct) && $importOnlyNew == false) { // если установлена директива CLEAR_CATALOG = 1 в config.ini, то удаляем товары перед синхронизацией с 1с if (CLEAR_1С_CATALOG != 'CLEAR_1С_CATALOG' && CLEAR_1С_CATALOG != 0) { DB::query('DELETE FROM `' . PREFIX . 'product` WHERE 1'); DB::query('DELETE FROM `' . PREFIX . 'category` WHERE 1'); DB::query('DELETE FROM `' . PREFIX . 'product_variant` WHERE 1'); } } $category = $this->groupsGreate($xml->Классификатор, $category, 0); $this->propertyСreate($xml->Классификатор->Свойства); $model = new Models_Product(); $currentPosition = 0; $upload = new Upload(false); $widthPreview = MG::getSetting('widthPreview') ? MG::getSetting('widthPreview') : 200; $widthSmallPreview = MG::getSetting('widthSmallPreview') ? MG::getSetting('widthSmallPreview') : 50; $heightPreview = MG::getSetting('heightPreview') ? MG::getSetting('heightPreview') : 100; $heightSmallPreview = MG::getSetting('heightSmallPreview') ? MG::getSetting('heightSmallPreview') : 50; foreach ($xml->Каталог->Товары[0] as $item) { $currentPosition++; if ($currentPosition <= $lastPositionProduct) { continue; } // Добавляем изображение товара в папку uploads $imageUrl = array(); $realImgPath = array(); if (isset($item->Картинка)) { foreach ($item->Картинка as $img) { $path = 'tempcml' . $sep . $img; $realImgPath[] = $path; $image = basename($img); $imageUrl[] = $image; } } $imageUrl = implode($imageUrl, "|"); $id = (string) $item->Группы->Ид[0]; $name = (string) $item->Наименование[0]; $description = ''; $desExist = false; if (isset($item->Описание)) { $description = nl2br((string) $item->Описание[0], true); $desExist = true; } foreach ($item->ЗначенияРеквизитов->ЗначениеРеквизита as $row) { if ($row->Наименование == 'Полное наименование') { // если в файле нет специального тега с описанием, то берем из полного наименования if (!$desExist) { $description = (string) $row->Значение ? (string) $row->Значение : $description; $description = nl2br($description, true); } else { // иначе полное наименование подставляем в title товара $name = (string) $row->Значение ? (string) $row->Значение : $name; } } } $code = !empty($item->Артикул[0]) ? $item->Артикул[0] : $item->ШтрихКод[0]; $id_1c = (string) $item->Ид[0]; $dataProd = array('title' => $name, 'url' => str_replace('\\', '-', URL::prepareUrl(MG::translitIt($name), true)), 'code' => $code, 'price' => 0, 'description' => $description, 'old_price' => '', 'image_url' => $imageUrl, 'count' => 0, 'cat_id' => $category[$id]['category_id'], 'meta_title' => $name, 'meta_keywords' => $name, 'meta_desc' => MG::textMore($description, 157), 'recommend' => 0, 'activity' => 1, 'new' => 0, 'related' => '', 'inside_cat' => '', '1c_id' => $id_1c, 'weight' => '0'); if ($importOnlyNew) { unset($dataProd['description']); unset($dataProd['image_url']); unset($dataProd['meta_title']); unset($dataProd['meta_keywords']); unset($dataProd['recommend']); unset($dataProd['activity']); unset($dataProd['new']); unset($dataProd['related']); unset($dataProd['inside_cat']); unset($dataProd['weight']); } $res = DB::query('SELECT * FROM ' . PREFIX . 'product WHERE `1c_id`=' . DB::quote($id_1c)); if ($row = DB::fetchAssoc($res)) { DB::query(' UPDATE `' . PREFIX . 'product` SET ' . DB::buildPartQuery($dataProd) . ' WHERE `1c_id`=' . DB::quote($id_1c)); $productId = $row['id']; } else { $newProd = $model->addProduct($dataProd); $productId = $newProd['id']; } $arImgPath = explode('/', $realImgPath[0]); array_pop($arImgPath); $path = implode($sep, $arImgPath); $imageUrl = explode('|', $imageUrl); $dir = floor($productId / 100) . '00'; if (!empty($realImgPath)) { foreach ($realImgPath as $cell => $image) { if (!empty($image) && is_file($image)) { $upload->_reSizeImage('70_' . $imageUrl[$cell], $realDocumentRoot . $sep . $image, $widthPreview, $heightPreview, 'PROPORTIONAL', 'uploads' . $sep . $addPath . 'thumbs' . $sep); $upload->_reSizeImage('30_' . $imageUrl[$cell], $realDocumentRoot . $sep . $image, $widthSmallPreview, $heightSmallPreview, 'PROPORTIONAL', 'uploads/' . $addPath . 'thumbs/'); } } $model->movingProductImage($imageUrl, $productId, $path); } // Привязываем свойства. if (isset($item->ЗначенияСвойств)) { foreach ($item->ЗначенияСвойств->ЗначенияСвойства as $prop) { $propVal = ''; $tempProp = '' . $prop->Значение[0]; if (!empty($_SESSION['variant_value'][$tempProp])) { $propVal = $_SESSION['variant_value'][$tempProp]; } if (empty($propVal)) { $propVal = ''; $idVal = '' . $prop->ИдЗначения; if (!empty($_SESSION['variant_value'][$idVal])) { $propVal = $_SESSION['variant_value'][$idVal]; } } $this->propertyConnect($id_1c, $prop->Ид, $propVal, $category[$id]['category_id']); } } $execTime = microtime(true) - $this->startTime; if ($execTime + 1 >= $this->maxExecTime) { header("Content-type: text/xml; charset=utf-8"); echo ""; echo "progress\r\n"; echo "Выгружено товаров: {$currentPosition}"; $_SESSION['lastCountProduct1cImport'] = $currentPosition; exit; } } if ($this->unlinkFile) { unlink($realDocumentRoot . '/tempcml/' . $filename); } $_SESSION['lastCountProduct1cImport'] = 0; } elseif ($xml && $filename == 'offers.xml') { $currentPosition = 0; $model = new Models_Product(); $currencyRate = MG::getSetting('currencyRate'); $currencyShort = MG::getSetting('currencyShort'); foreach ($xml->ПакетПредложений[0]->Предложения[0] as $item) { $currentPosition++; if ($currentPosition <= $lastPositionOffer) { continue; } $id = (string) $item->Ид[0]; $price = (string) $item->Цены->Цена->ЦенаЗаЕдиницу[0]; $iso = $this->getIsoByCode((string) $item->Цены->Цена->Валюта[0]); if ($iso == 'NULL') { $iso = substr(MG::translitIt((string) $item->Цены->Цена->Валюта[0]), 0, 3); } $count = (string) $item->Количество[0]; // если валюта товара не задана ранее в магазине, то добавим ее. (Курс нужно будет установить вручную в настройках) $currency = array(); if (empty($currencyRate[$iso])) { $currency['iso'] = htmlspecialchars($iso); $currency['short'] = $currency['iso']; $currency['rate'] = 1; $currencyRate[$currency['iso']] = $currency['rate']; $currencyShort[$currency['iso']] = $currency['short']; MG::setOption(array('option' => 'currencyRate', 'value' => addslashes(serialize($currencyRate)))); MG::setOption(array('option' => 'currencyShort', 'value' => addslashes(serialize($currencyShort)))); } $partProd = array('price' => $price, 'count' => $count < 0 ? 0 : $count, 'currency_iso' => $iso); // проверяем, вдруг это предложение является вариантом для товара $ids1c = explode('#', (string) $item->Ид[0]); $variantId = ''; // если id варианта не найден if (empty($ids1c[1])) { // просто товар, не вариант DB::query(' UPDATE `' . PREFIX . 'product` SET ' . DB::buildPartQuery($partProd) . ' , `price_course` = ROUND(' . DB::quote($price * $currencyRate[$iso], TRUE) . ',2) WHERE 1c_id = ' . DB::quote($ids1c[0]) . ' '); } else { // если товарное предложение является вариантом для продукта $productId = ''; $variantId = $ids1c[1]; $variant = array(); $dbRes = DB::query(' SELECT id FROM `' . PREFIX . 'product` WHERE 1c_id = ' . DB::quote($ids1c[0]) . ' '); if ($row = DB::fetchArray($dbRes)) { $productId = $row['id']; $name = array(); foreach ($item->ХарактеристикиТовара->ХарактеристикаТовара as $prop) { $name[] = $prop->Значение; } $name = implode(', ', $name); $titleVariant = $name; $variant = array('title_variant' => $titleVariant, 'code' => $item->Артикул[0], 'price' => $price, 'old_price' => '', 'image' => '', 'count' => $count < 0 ? 0 : $count, '1c_id' => $variantId, 'weight' => '0', 'activity' => 1, 'currency_iso' => $iso); // ****** // ищем варианты для этого товара $dbRes = DB::query(' SELECT id FROM `' . PREFIX . 'product_variant` WHERE product_id = ' . DB::quote($productId) . ' '); // если еще ни одного небыло, то создаем и обновляем в таблице product значения по первому варианту if ($row != DB::fetchArray($dbRes)) { DB::query(' UPDATE `' . PREFIX . 'product` SET ' . DB::buildPartQuery($partProd) . ' , `price_course` = ROUND(' . DB::quote($price * $currencyRate[$iso], TRUE) . ',2) WHERE 1c_id = ' . DB::quote($ids1c[0]) . ' '); } // ****** // проверяем, импортирован ли ранее этот вариант $dbRes = DB::query(' SELECT id FROM `' . PREFIX . 'product_variant` WHERE 1c_id = ' . DB::quote($ids1c[1]) . ' '); // если еще нет, то получаем массив всех имеющихся вариантов по этому продукту, // добавляем к нему новый вариант и обновляем массив вариантов стандартными средствами if (!($row = DB::fetchArray($dbRes))) { $arrVariants = array(); $res = DB::query(' SELECT pv.* FROM `' . PREFIX . 'product_variant` pv WHERE pv.product_id = ' . DB::quote($productId) . ' ORDER BY sort '); if (!empty($res)) { while ($var = DB::fetchAssoc($res)) { $arrVariants[$var['id']] = $var; } } $variant['price_course'] = round($price * $currencyRate[$iso], 2); $arrVariants[] = $variant; $model->saveVariants($arrVariants, $productId); } else { // обновить вариант DB::query(' UPDATE `' . PREFIX . 'product_variant` SET ' . DB::buildPartQuery($variant) . ',`price_course` = ROUND(' . DB::quote($price * $currencyRate[$iso], TRUE) . ',2) WHERE 1c_id = ' . DB::quote($ids1c[0]) . ' '); } } } $execTime = microtime(true) - $this->startTime; if ($execTime + 1 >= $this->maxExecTime) { header("Content-type: text/xml; charset=utf-8"); echo ""; echo "progress\r\n"; echo "Выгружено предложений: {$currentPosition}"; $_SESSION['lastCountOffer1cImport'] = $currentPosition; exit; } } if ($this->unlinkFile) { unlink($realDocumentRoot . '/tempcml/' . $filename); } $_SESSION['lastCountOffer1cImport'] = 0; Storage::clear(); } else { echo "Ошибка загрузки XML\n"; foreach (libxml_get_errors() as $error) { echo "\t", $error->message; exit; } } }