Skip to content

Instantly share code, notes, and snippets.

@andronex
Last active October 12, 2019 08:20
Show Gist options
  • Save andronex/34a028afa56b9697019b to your computer and use it in GitHub Desktop.
Save andronex/34a028afa56b9697019b to your computer and use it in GitHub Desktop.
Парсер товаров для импорта с gifts.ru для MODX Revolution v.2.6+ и miniShop2 v.2.4.10+ (обновлённая, рабочая версия на 02.02.2018 г.) !!!ВНИМАНИЕ!!! Просьба обратить внимание на комментарий @dumbuzz ниже. Если будете использовать, то внесите изменения в код. Если будет время, доработаю сам и выложу.
/*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*/
/*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*/
В связи с участившимися случаями обращения ко мне с вопросами по работе данного скрипта импорта товаров с gifts.ru на сайты, работающие на MODX Revolution в связке с miniShop2 или без таковой, сообщаю расценки на услуги разработки любых парсеров данных, в том числе на доработку/интеграцию данного скрипта парсера под ваши нужды и под ваш проект. Подробности и минимальная цена здесь https://vk.com/modxrevo?w=product-77410673_1198119
/*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*/
/*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*//*/*/
<?php
//настройки для коннекта к gifts
$giftsLogin = '****_xmlexport';
$giftsPass = '****';
$giftsUrlProduct = "http://{$giftsLogin}:{$giftsPass}@api2.gifts.ru/export/v2/catalogue/product.xml";
$giftsUrlTree = "http://{$giftsLogin}:{$giftsPass}@api2.gifts.ru/export/v2/catalogue/tree.xml";
$giftsUrlStock = "http://{$giftsLogin}:{$giftsPass}@api2.gifts.ru/export/v2/catalogue/stock.xml";
$giftsUrlFilters = "http://{$giftsLogin}:{$giftsPass}@api2.gifts.ru/export/v2/catalogue/filters.xml";
$urlImages = 'http://files.gifts.ru/reviewer/';
//настройки для входа в админку MODX (уже не используются)
$username = 'admin';
$userpass = '****';
//настройки для парсинга XML файла и установки шаблонов для создаваемых продуктов
$fileProduct = dirname(__FILE__).'/product.xml';
$fileParentCat = dirname(__FILE__).'/product.txt';
$fileProductStock = dirname(__FILE__).'/stock.txt';
$fileProductFilters = dirname(__FILE__).'/filters.txt';
$fileProductGroups = dirname(__FILE__).'/groups.txt';
$fileTree = dirname(__FILE__).'/tree.xml';
$fileStock = dirname(__FILE__).'/stock.xml';
$fileFilters = dirname(__FILE__).'/filters.xml';
$xpath_expression['product'] = '//doct/product'; //DOM структура до продукта
$xpath_expression['page'] = '//doct/page/page'; //DOM структура до страницы
$xpath_expression['stock'] = '//doct/stock'; //DOM структура до наличия на складе
$xpath_expression['filters'] = '//root/filtertypes/filtertype'; //DOM структура до фильтров товара
//настройки для обработки товаров
$tplProduct = 6;//номер шаблона для карточки товара
$numOffset = 50;//число товаров для загрузки за 1 проход парсера
$tplParent = 4;//номер шаблона для категорий
$tplChildParent = 4;//номер шаблона для подкатегорий
$idParent = 10;//id каталога товаров
$categoryArticleTVnumber = 'tv8';//ID TV поля для записи уникального идентификатора категории товаров для последующего сравнения с деревом категорий поставщика
//API ключ для Яндекс переводчика, получить здесь https://tech.yandex.ru/translate/
$apiYaTranslate = 'trnsl.1.1.20180130T1***************043c53e0c440bb752c8df1f90829410aed9fd';
<?php
/**
* запускать отдельно после первого запуска парсера, когда все товары добавлены на сайт
* связывает товары по цветам в группы
* */
require_once(dirname(__FILE__).'/config.php');
define('MODX_API_MODE', true);
require_once(dirname(dirname(__FILE__)).'/index.php');
// Включаем обработку ошибок
$modx->getService('error','error.modError');
$modx->setLogLevel(modX::LOG_LEVEL_ERROR);
$modx->setLogTarget(XPDO_CLI_MODE ? 'ECHO' : 'HTML');
$modx->error->message = null; // Обнуляем переменную
// Логинимся в админку
$response = $modx->runProcessor('security/login', array('username' => $username, 'password' => $userpass));
if ($response->isError()) {
$modx->log(modX::LOG_LEVEL_ERROR, $response->getMessage());
return;
}
$modx->initialize('mgr');
/****************************************************************/
$groupsArray = @file_get_contents(dirname(__FILE__).'/groups.txt');
$groupsArray = unserialize($groupsArray);
foreach($groupsArray as $groups){
if(is_array($groups)) {
if(count($groups) < 2) continue;
for($a = 0;$a < count($groups);$a++){
if($a == 0) continue;
if(!$modx->getObject('msProduct', $groups[$a])) continue;
$master = $groups[0];
$slave = $groups[$a];
$linkid = 1;
//print_r($master.$slave.$linkid);exit;
$response = $modx->runProcessor('product/productlink/create',
array('master' => $master, 'slave' => $slave, 'link' => $linkid),
array('processors_path' => MODX_CORE_PATH.'components/minishop2/processors/mgr/'));
if ($response->isError()) {
$modx->log(modX::LOG_LEVEL_ERROR, "Ошибка установки связи товара-мастера {$master} к товару {$slave}: \n". print_r($response->getAllErrors(), 1));
}
}
}
}
<?php
/**
* в скрипте есть TV поля, не представленные в config.php по причине уникальности каждого магазина
* см. строки 160 и 425
*/
//ini_set('display_errors', 1);
//ini_set('error_reporting', -1);
/***************************************/
require_once(dirname(__FILE__).'/config.php');
require_once(dirname(__FILE__).'/tree.parser.php');
if(empty($_GET['off_set'])) {
$off_set = 0;
if (!treeParser($giftsLogin, $giftsPass, $giftsUrlTree, $giftsUrlStock, $username, $userpass, $fileTree, $fileStock, $xpath_expression['page'], $xpath_expression['stock'], $tplParent, $tplChildParent, $giftsUrlFilters, $fileFilters, $xpath_expression['filters'], $apiYaTranslate)) {
die("ошибка парсинга структуры каталога");
}
}
else $off_set = (int)$_GET['off_set']; //определяем смещение парсинга
$i = $ii = $iii = $a = $aa = $all = 0;
$treeTxt = '';
$tree = array();
/***************************************/
if (!file_exists($fileProduct) || (time() - filemtime($fileProduct)) > 43200 || file_get_contents($fileProduct) === '') { //12 часов
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $giftsUrlProduct);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
curl_close($ch);
if ($result) {
$file_tree = fopen ($fileProduct,'w+');
if ($file_tree) {
fwrite($file_tree, $result);
fclose ($file_tree);
}
}
}
unset ($file_tree,$result,$file_filters);
define('MODX_API_MODE', true);
require_once(dirname(dirname(__FILE__)).'/index.php');
// Включаем обработку ошибок
$modx->getService('error','error.modError');
$modx->setLogLevel(modX::LOG_LEVEL_ERROR);
$modx->setLogTarget(XPDO_CLI_MODE ? 'ECHO' : 'HTML');
$modx->error->message = null; // Обнуляем переменную
// Логинимся в админку
/*$response = $modx->runProcessor('security/login', array('username' => $username, 'password' => $userpass));
if ($response->isError()) {
$modx->log(modX::LOG_LEVEL_ERROR, $response->getMessage());
return;
}
$modx->initialize('mgr');*/
/***************************************/
$xml = new DOMDocument();
$xml->load($fileProduct);
$xpath = new DOMXPath($xml);
$nodes = $xpath->query($xpath_expression['product']);
$productTree = @file_get_contents($fileParentCat);
if(!$productTree) die('Дерево каталога ещё не построено.');
$productTree = (array) unserialize($productTree);
$productStock = @file_get_contents($fileProductStock);
if(!$productStock) die('Нет .txt файла с наличием товара на складе поставщика.');
$productStock = (array) unserialize($productStock);
$productFilters = @file_get_contents($fileProductFilters);
if(!$productFilters) die('Нет .txt файла с фильтрами для товаров.');
$productFilters = (array) unserialize($productFilters);
//проверка на существование или создание отсутствующих фильтров
foreach($productFilters as $keyFilters => $productFilter){
$temp = $modx->getObject('msOption', array('key' => $productFilter['filtertypenameEng']));
if(!$temp && $productFilter['filtertypenameEng'] != 'color') {
$newFilters = $modx->newObject('msOption',array(
'key' => $productFilter['filtertypenameEng'],
'caption' => $productFilter['filtertypename'],
'type' => 'combo-options'//тип опции
));
$newFilters->save();
unset($newFilters);
}
$productFilters[$keyFilters]['filteridMODX'] = $temp->id ? $temp->id : null;
unset($temp);
}
//ф-ия создания новых ресурсов или получения ID уже созданных
function createProduct ($prop, $filtersArray = array(), $gallery = array(), $artForAlias = '') {
//return 'upd';//временно
global $tplProduct;
global $modx;
global $productTree;
global $fileProductGroups;
global $urlImages;
$prop['template'] = $tplProduct;
$prop['context_key'] = 'web';
$prop['class_key'] = 'msProduct';
$q = $modx->newQuery('msProduct');
$q->select($modx->getSelectColumns('msProduct','msProduct').','.$modx->getSelectColumns('msProductData','Data').','.$modx->getSelectColumns('msProductOption','Option'));
$q->innerJoin('msProductData', 'Data', 'msProduct.id = Data.id');
$q->rightJoin('msProductOption', 'Option', 'msProduct.id = Option.product_id');
$q->where(array('Data.article' => $prop['article']));
$q->prepare();
if($res = $modx->getObject('msProduct', $q)) {
//print_r($res->toArray());exit;
//$prop['id'] = $artProd->contentid;
//$prop['pagetitle'] = $res->pagetitle;
//$prop['introtext'] = $res->introtext;
//$prop['content'] = $res->content;
//$prop['alias'] = $res->alias;
//$prop['parent'] = $res->parent;
//$prop['tv3'] = $prop['tv3'];
//$prop['tv4'] = $res->getTVValue('image');
//$prop['tv6'] = $prop['tv6'];
//$prop['published'] = $prop['published'];
$prop['editedon'] = date("Y-m-d H:i:s");
//print_r($res->toArray());exit;
//корректное пересохранение опций товара
$resdata = $res->getOne('Data');
$optionKeys = $resdata->getOptionKeys();
//$optionKeys = $res->getOptionKeys();
$productData = $res->toArray();
if(count($optionKeys) > 0) {
$productOption = array();
foreach ($optionKeys as $key) {
if(is_array($productData[$key])) {
foreach ($productData[$key] as $dataOption) {
$productOption[] = '('.$res->get('id').',"'.$key.'","'.$dataOption.'")';
}
}
else if(!empty($productData[$key])) $productOption[] = '('.$res->get('id').',"'.$key.'","'.$productData[$key].'")';
}
}
if (!empty($productOption)) {
$productOption = array_unique($productOption);
$sql = 'DELETE FROM '.$modx->getTableName('msProductOption').' WHERE product_id = ' . $res->get('id').';';
$stmt = $modx->prepare($sql);
$stmt->execute();
$stmt->closeCursor();
$sql = 'INSERT INTO '.$modx->getTableName('msProductOption').' (`product_id`,`key`,`value`) VALUES ' . implode(',', $productOption).';';
$stmt = $modx->prepare($sql);
$stmt->execute();
$stmt->closeCursor();
}
//$res->set('content',$prop['content']);
$res->setTVValue(9,$prop['tv9']);
$res->setTVValue(10,$prop['tv10']);
$res->setTVValue(12,$prop['tv12']);
$res->setTVValue(14,$prop['tv14']);
$res->set('new',$prop['new']);
$res->set('popular',$prop['popular']);
$res->set('favorite',$prop['favorite']);
$res->set('editedon',$prop['editedon']);
$res->set('published',$prop['published']);
$res->set('price', $prop['price']);
$res->save();
return 'upd';
}
$modx->error->message = null;
$response = $modx->runProcessor('resource/create', $prop,
array('processors_path' => MODX_CORE_PATH.'model/modx/processors/')
);
if ($response->isError()) {
return $response->getAllErrors();
}
$resource = $response->getObject();
//удаление из pagetitle артикулов, нужных на стадии создания товара для формирования alias ресурса
$res = $modx->getObject('msProduct', array('id' => $resource['id']));
$res->set('pagetitle', str_replace($artForAlias, '', $res->get('pagetitle')));
$res->save();
//доп. категории только если их более одной в массиве $productTree[$prop['product_id']], начиная со второй, первая основная (parent)
if(count($productTree[$prop['product_id']]) > 1){
$aCat = 0;
foreach ($productTree[$prop['product_id']] as $catProduct){
$aCat++;
if($aCat == 1) continue;
$category = $modx->newObject('msCategoryMember');
$category->set('category_id', $catProduct);
$category->set('product_id', $resource['id']);
$category->save();
}
}
//привязка фильтров к товару и к категории товара из массива фильтров $productFilters и массива фильтров товара $filtersArray
if(is_array($filtersArray)){
foreach($filtersArray as $keyF => $valsF){
foreach($valsF as $valF){
$optionProduct = $modx->newObject('msProductOption');
$optionProduct->set('product_id', $resource['id']);
$optionProduct->set('key', $keyF);
$optionProduct->set('value', $valF);
$optionProduct->save();
}
if($temp = $modx->getObject('msOption', array('key' => $keyF))){
$optionId = $temp->get('id');
$categoryId = $res->get('parent');
if( !$modx->getObject('msCategoryOption', array('option_id' => $optionId, 'category_id' => $categoryId)) ){
$optionCat = $modx->newObject('msCategoryOption');
$optionCat->set('option_id', $optionId);
$optionCat->set('category_id', $categoryId);
$optionCat->set('active', 1);
$optionCat->save();
}
unset($optionId, $categoryId);
}
unset($temp);
}
}
//удаление пустых значений фильтров из таблицы фильтров в БД
$sql = "DELETE FROM {$modx->getTableName('msProductOption')} WHERE `product_id` IN ({$resource['id']}) AND (`value`='' OR `value` IS NULL);";
$stmt = $modx->prepare($sql);
$stmt->execute();
$stmt->closeCursor();
unset($sql, $stmt);
//построение массива групп товаров
if(isset($prop['groups_id'])) {
if (!function_exists('createGroups')) {
function createGroups ($id, $gid, $fileProductGroups) {
$productGroups = @file_get_contents($fileProductGroups);
if($productGroups) {
$productGroups = (array) unserialize($productGroups);
} else $productGroups = array();
$productGroups[$gid][] = $id;
$productGroups = serialize($productGroups);
$file = fopen($fileProductGroups, 'w+');
if($file) {
fwrite($file, $productGroups);
fclose ($file);
} else return false;
return true;
}
}
createGroups($resource['id'], $prop['groups_id'], $fileProductGroups);
}
//привязка картинок
if (is_array($gallery)) {
foreach ($gallery as $v) {
if (empty($v)) {continue;}
$image = $v;
$image = explode('/', $image);
$image = $image[count($image)-1];
$image = str_replace('_', '-', $image);
if (!file_exists(dirname(__FILE__).'/thumbs/'.$image)) {
$ch = curl_init($urlImages.$v);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
if(!file_put_contents(dirname(__FILE__).'/thumbs/'.$image, curl_exec($ch))){
$modx->log(modX::LOG_LEVEL_ERROR, "Неудача при скачивании картинки товара {$urlImages}{$v}");
$noimg = true;
}
curl_close($ch);
}
if(!$noimg) {
$response_img = $modx->runProcessor('gallery/upload',
array('id' => $res->get('id'), 'name' => $image, 'file' => dirname(__FILE__).'/thumbs/'.$image),
array('processors_path' => MODX_CORE_PATH.'components/minishop2/processors/mgr/')
);
if ($response_img->isError()) {
$modx->log(modX::LOG_LEVEL_ERROR, "Ошибка привязки картинки \"$image\" к товару id = {$resource['id']}: \n". print_r($response_img->getAllErrors(), 1));
}
else {
$sql = "UPDATE {$modx->getTableName('msProductFile')} SET `name` = \"{$res->get('pagetitle')}\" WHERE `product_id` IN ({$resource['id']});";
$stmt = $modx->prepare($sql);
$stmt->execute();
$stmt->closeCursor();
unset($sql, $stmt);
$modx->log(modX::LOG_LEVEL_INFO, "Удачно загружена картинка \"$image\": \n". print_r($response_img->getObject(), 1));
}
}
}
unset($response_img, $res, $image, $resource);
}
return 'new';
}
/***************************************/
foreach($nodes as $node){$all++;}
foreach($nodes as $node){
$i++;
if($i <= $off_set) {continue;}
$massiv_data = $gallery = $filtersArray = array();
$a++;
$massiv_data['product_id'] = $node->getElementsByTagName('product_id')->item(0)->nodeValue;
if(isset($node->getElementsByTagName('group')->item(0)->nodeValue))
{$massiv_data['groups_id'] = $node->getElementsByTagName('group')->item(0)->nodeValue;}
$massiv_data['pagetitle'] = $node->getElementsByTagName('name')->item(0)->nodeValue;
$massiv_data['article'] = $node->getElementsByTagName('code')->item(0)->nodeValue;
$massiv_data['price'] = $node->getElementsByTagName('price')->item(1)->nodeValue;
$gallery[] = $node->getElementsByTagName('super_big_image')->item(0)->getAttribute('src');
$attachCount = $node->getElementsByTagName('product_attachment')->length;
for($aa = 0; $aa < $attachCount; $aa++) {
switch($node->getElementsByTagName('product_attachment')->item($aa)->getElementsByTagName('meaning')->item(0)->nodeValue){
case 0:
$gallery[] = $node->getElementsByTagName('product_attachment')->item($aa)->getElementsByTagName('file')->item(0)->nodeValue;
break;
default:
$gallery[] = $node->getElementsByTagName('product_attachment')->item($aa)->getElementsByTagName('image')->item(0)->nodeValue;
}
$gallery = array_unique($gallery);
}
if(isset($productTree[$massiv_data['product_id']])){
foreach ($productTree[$massiv_data['product_id']] as $catProduct){
$massiv_data['parent'] = $catProduct;
break;
}
}
else $massiv_data['parent'] = $idParent;
$massiv_data['published'] = ($node->getElementsByTagName('status')->item(0)->getAttribute('id') == '3') ? 0 : 1;
$massiv_data['new'] = ($node->getElementsByTagName('status')->item(0)->getAttribute('id') == '0') ? 1 : 0;
$massiv_data['popular'] = 0; //не распродажа
$massiv_data['favorite'] = 0;//не эко-товар
//далее по коду переопределяются, если найдены соответствующие фильтры
$massiv_data['matherial'] = $node->getElementsByTagName('matherial')->item(0)->nodeValue;
if(isset($node->getElementsByTagName('brand')->item(0)->nodeValue))
{$massiv_data['made_in'] = $node->getElementsByTagName('brand')->item(0)->nodeValue;}
$massiv_data['size'] = array($node->getElementsByTagName('product_size')->item(0)->nodeValue);
$sizeCount = $node->getElementsByTagName('product')->length;
for($aa = 0; $aa < $sizeCount; $aa++) {
if($node->getElementsByTagName('product')->item($aa)->getElementsByTagName('main_product')->item(0)->nodeValue == $massiv_data['product_id']){
$massiv_data['size'][$aa] = $node->getElementsByTagName('product')->item($aa)->getElementsByTagName('size_code')->item(0)->nodeValue;
}
}
$massiv_data['weight'] = $node->getElementsByTagName('weight')->item(0)->nodeValue;
if($productStock[$massiv_data['product_id']]['amount'] != 0){
if($productStock[$massiv_data['product_id']]['inwayamount']) $massiv_data['inwayamount'] = " <small>+{$productStock[$massiv_data['product_id']]['inwayamount']} в поставке</small>";
$massiv_data['amount'] = "На складе: {$productStock[$massiv_data['product_id']]['amount']}{$massiv_data['inwayamount']}<br>Можно зарезервировать: {$productStock[$massiv_data['product_id']]['free']}";
}
else $massiv_data['amount'] = 'под заказ';
if($node->getElementsByTagName('pack')->length) {
$massiv_data['pack_amount'] = $node->getElementsByTagName('pack')->item(0)->getElementsByTagName('amount')->item(0)->nodeValue;
$massiv_data['pack_weight'] = (int)round($node->getElementsByTagName('pack')->item(0)->getElementsByTagName('weight')->item(0)->nodeValue)/1000;
$massiv_data['pack_volume'] = (float)round($node->getElementsByTagName('pack')->item(0)->getElementsByTagName('volume')->item(0)->nodeValue/1000000,3);
$massiv_data['pack_sizex'] = $node->getElementsByTagName('pack')->item(0)->getElementsByTagName('sizex')->item(0)->nodeValue;
$massiv_data['pack_sizey'] = $node->getElementsByTagName('pack')->item(0)->getElementsByTagName('sizey')->item(0)->nodeValue;
$massiv_data['pack_sizez'] = $node->getElementsByTagName('pack')->item(0)->getElementsByTagName('sizez')->item(0)->nodeValue;
}
$massiv_data['print'] = $node->getElementsByTagName('print');
$massiv_data['prints'] = "<p><label>Возможные виды нанесения:</label>";
$printCount = $massiv_data['print']->length;
for($aa = 0;$aa < $printCount;$aa++) {
$massiv_data['print_name'] = $massiv_data['print']->item($aa)->getElementsByTagName('name')->item(0)->nodeValue;
$massiv_data['print_description'] = $massiv_data['print']->item($aa)->getElementsByTagName('description')->item(0)->nodeValue;
$massiv_data['prints'] .= "<br>{$massiv_data['print_name']}: {$massiv_data['print_description']}";
$filtersArray['print'][] = $massiv_data['print_name'].': '.$massiv_data['print_description']; //фильтры: возможная печать
}
unset($massiv_data['print'], $massiv_data['print_name'], $massiv_data['print_description'], $printCount, $aa);
$massiv_data['filters'] = $node->getElementsByTagName('filters')->item(0)->getElementsByTagName('filter');
$filtersCount = $massiv_data['filters']->length;
for($aa = 0;$aa < $filtersCount;$aa++) {
if($productFilters[$massiv_data['filters']->item($aa)->getElementsByTagName('filtertypeid')->item(0)->nodeValue]['filtertypenameEng'] == 'color'){
$massiv_data['color'][] = $productFilters[$massiv_data['filters']->item($aa)->getElementsByTagName('filtertypeid')->item(0)->nodeValue][$massiv_data['filters']->item($aa)->getElementsByTagName('filterid')->item(0)->nodeValue]; //присвоение цветов товара
}
if($massiv_data['filters']->item($aa)->getElementsByTagName('filtertypeid')->item(0)->nodeValue == 8){
switch($massiv_data['filters']->item($aa)->getElementsByTagName('filterid')->item(0)->nodeValue){
case 230:
$massiv_data['popular'] = 1;
break;
case 229:
$massiv_data['new'] = 1;
break;
case 220:
$massiv_data['favorite'] = 1;
break;
}
}
$filtersArray[ $productFilters[$massiv_data['filters']->item($aa)->getElementsByTagName('filtertypeid')->item(0)->nodeValue]['filtertypenameEng'] ][] = $productFilters[$massiv_data['filters']->item($aa)->getElementsByTagName('filtertypeid')->item(0)->nodeValue][$massiv_data['filters']->item($aa)->getElementsByTagName('filterid')->item(0)->nodeValue]; //фильтры: все остальные
}
$massiv_data['prints'] .= "</p>";
$massiv_data['content'] = '[+content]';
//Кастомные тэвэшки для кол-ва доступного товара и для описания упаковки
$massiv_data['tv9'] = $productStock[$massiv_data['product_id']]['amount']; //на складе
$massiv_data['tv10'] = $productStock[$massiv_data['product_id']]['free']; //доступно
$massiv_data['tv12'] = (!$massiv_data['pack_amount']) ? '' : "<p>Количество в упаковке: {$massiv_data['pack_amount']} шт.<br>Вес в упаковке: {$massiv_data['pack_weight']} кг.<br>Объём упаковки: {$massiv_data['pack_volume']} м<sup>3</sup><br>ШxВxГ: {$massiv_data['pack_sizex']}x{$massiv_data['pack_sizey']}x{$massiv_data['pack_sizez']} см.</p>";
$massiv_data['tv13'] = $massiv_data['matherial']; //подробная информация о материале
$massiv_data['tv14'] = ($massiv_data['groups_id']) ? $massiv_data['groups_id'] : $massiv_data['article']; //группа товаров для дополнительной привязки через TV поля
//$info = "<p><label>Материал:</label> {$massiv_data['matherial']}</p><p><label>Упаковка:</label><br>количество в упаковке: {$massiv_data['pack_amount']} шт.<br>вес в упаковке: {$massiv_data['pack_weight']} кг.<br>объём упаковки: {$massiv_data['pack_volume']} м<sup>3</sup><br>ШxВxГ: {$massiv_data['pack_sizex']}x{$massiv_data['pack_sizey']}x{$massiv_data['pack_sizez']} см.</p>{$massiv_data['prints']}";
$content = $node->getElementsByTagName('content')->item(0)->nodeValue;
//if(!empty($content)) $content = "<p><label>Описание</label><br>{$content}</p>";
//$amount = "<p><label>Сведения о наличии:</label><br>{$massiv_data['amount']}</p>";
$massiv_data['content'] = str_replace(array('[+info]','[+amount]','[+content]'),array($info, $amount, $content),$massiv_data['content']);
unset($info,$content,$amount,$massiv_data['filters'],$massiv_data['prints'],$filtersArray['color'],$massiv_data['urltoimg'],$massiv_data['matherial'],$massiv_data['inwayamount'],$massiv_data['amount'],$massiv_data['pack_amount'],$massiv_data['pack_weight'],$massiv_data['pack_volume'],$massiv_data['pack_sizex'],$massiv_data['pack_sizey'],$massiv_data['pack_sizez']);
$massiv_data['pagetitle'] .= $artForAlias = " арт.{$massiv_data['article']}";
//для проверки нужного товара if($massiv_data['product_id'] != 75424) continue;
//print_r($massiv_data); print_r($filtersArray);exit;
$Product = createProduct($massiv_data, $filtersArray, $gallery, $artForAlias);
//print_r($Product);
switch($Product) {
case 'upd':
$ii++;
break;
default:
$iii++;
}
if ($a == $numOffset) break;
}
$off_set = $off_set + $numOffset;
if (!strpos($_SERVER['REQUEST_URI'],'off_set'))
$_SERVER['REQUEST_URI'] = $_SERVER['REQUEST_URI'].'&off_set='.($off_set-$numOffset);
$URL_GET = 'http://'.$_SERVER['SERVER_NAME'].str_replace('off_set='.($off_set-$numOffset), 'off_set='.$off_set, $_SERVER['REQUEST_URI']);
if (!XPDO_CLI_MODE) {echo '<pre>';}
echo "\nИмпорт прошёл за ".number_format(microtime(true) - $modx->startTime, 7) . " сек.\n";
echo "Итого обработано\n товаров за проход: {$a}\n обновлено из них: {$ii}\n создано новых из них: {$iii}\n";
echo "Всего обработано товаров: <a id='link' href='$URL_GET'><span id='offset'>$off_set</span></a>\n";
echo "Всего основных товаров в XML файле: $all\n";
if ($off_set >= $all) {
$autofset = '';
$paths = array('context_settings/');
$options = array('objects' => null, 'extensions' => array('.php'));
$modx->cacheManager->clearCache($paths, $options);
} else $autofset = 'window.location = url;';
if (!XPDO_CLI_MODE) {
echo '</pre>
<script type="text/javascript">
if(document.readyState||document.body.readyState==\'complete\'){
var url = document.getElementById(\'link\').getAttribute(\'href\');
'.$autofset.'
};
</script>
';}
<?php
function treeParser ($giftsLogin, $giftsPass, $giftsUrlTree, $giftsUrlStock, $username, $userpass, $file, $file_stock, $xpath_expression, $xpath_expression_stock, $tplParent, $tplChildParent, $giftsUrlFilters, $fileFilters, $xpath_expression_filters, $apiYaTranslate) {
global $modx;
global $idParent;
global $categoryArticleTVnumber;
$globalIdParent = $idParent;
$i = $ii = $iiii = 0;
$treeTxt = $productTxt = '';
$massiv_data = $tree = array();
/***************************************/
if (!file_exists($file) || (time() - filemtime($file)) > 43200 || file_get_contents($file) === '') { //12 часов
function update_xml ($giftsUrlTree, $file) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $giftsUrlTree);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
curl_close($ch);
if ($result) {
$file_tree = fopen ($file,'w+');
if ($file_tree) {
fwrite($file_tree, $result);
fclose ($file_tree);
return true;
}
}
return false;
}
update_xml ($giftsUrlTree, $file);
update_xml ($giftsUrlStock, $file_stock);
update_xml ($giftsUrlFilters, $fileFilters);
}
unset ($file_tree,$result);
define('MODX_API_MODE', true);
require dirname(dirname(__FILE__)).'/index.php';
// Включаем обработку ошибок
$modx->getService('error','error.modError');
$modx->setLogLevel(modX::LOG_LEVEL_ERROR);
$modx->setLogTarget(XPDO_CLI_MODE ? 'ECHO' : 'HTML');
$modx->error->message = null; // Обнуляем переменную
// Логинимся в админку
/*$response = $modx->runProcessor('security/login', array('username' => $username, 'password' => $userpass));
if ($response->isError()) {
$modx->log(modX::LOG_LEVEL_ERROR, $response->getMessage());
return;
}
$modx->initialize('mgr');*/
/***************************************/
function newDomXml ($file, $xpath_expression) {
$xml = new DOMDocument();
$xml->load($file);
$xpath = new DOMXPath($xml);
$nodes = $xpath->query($xpath_expression);
return $nodes;
}
$nodes = newDomXml ($file, $xpath_expression);
//ф-ия создания новых ресурсов или получения ID уже созданных
function createCategory ($parent = 2, $pagetitle, $art, $template = null) {
//return 12;//временно
global $tplParent;
global $modx;
global $categoryArticleTVnumber;
$prop = array(
'parent' => $parent,
'class_key' => 'msCategory',
'pagetitle' => $pagetitle,
'template' => (empty($template)) ? $tplParent : $template,
'published' => 1,
$categoryArticleTVnumber => $art
);
//print_r($prop);exit;
if($artCat = $modx->getObject('modTemplateVarResource', array('value' => $art))) return $artCat->contentid;
$response = $modx->runProcessor('resource/create', $prop);
if ($response->isError()) {
return $modx->error->failure($response->getMessage());
}
$newResource = $response->response['object'];
return $newResource['id'];
}
/***************************************/
foreach($nodes as $node){
$i++;
$massiv_data['parent'] = ($node->getAttribute('parent_page_id') == 1) ? $globalIdParent : $node->getAttribute('parent_page_id');
$massiv_data['pagetitle'] = $node->getElementsByTagName('name')->item(0)->nodeValue;
$massiv_data[ $categoryArticleTVnumber ] = 'cat_'.$node->getElementsByTagName('page_id')->item(0)->nodeValue;
$idParent = createCategory($massiv_data['parent'], $massiv_data['pagetitle'], $massiv_data[ $categoryArticleTVnumber ]);
if(is_array($idParent)) {
die('Ошибка создания категории или подкатегории товаров: ' . $idParent['message']);
}
//$tree[$idParent] = array();
if($nodesClild = $node->childNodes) {
foreach($nodesClild as $nodeClild) {
if($nodeClild->nodeName == 'page') {
$ii++;
$massiv_data['parent'] = $idParent;
$massiv_data['pagetitle'] = $nodeClild->getElementsByTagName('name')->item(0)->nodeValue;
$artId = $nodeClild->getElementsByTagName('page_id')->item(0)->nodeValue;
$massiv_data[ $categoryArticleTVnumber ] = 'cat_'.$artId;
$idChildParent = createCategory($massiv_data['parent'], $massiv_data['pagetitle'], $massiv_data[ $categoryArticleTVnumber ], $tplChildParent);
//$tree[$idParent+$i][] = $idChildParent;
$treeTxt .= $artId.':'.$idChildParent.',';
if($nodesClildProduct = $nodeClild->childNodes) {
foreach($nodesClildProduct as $nodeClildProduct) {
if($nodeClildProduct->nodeName == 'product') {
$massiv_data['parent'] = $idChildParent;
$massiv_data[ $categoryArticleTVnumber ] = $nodeClildProduct->getElementsByTagName('product')->item(0)->nodeValue;
$tree[$massiv_data[ $categoryArticleTVnumber ]][$iiii] = $idChildParent;
$productTxt .= $massiv_data[ $categoryArticleTVnumber ].':'.$idChildParent.',';
$iiii++;
}
}
}
}
}
}
}
$iii = count($tree);
$tree = serialize($tree);
if ($tree) {
$file_tree = fopen (dirname(__FILE__).'/product.txt','w+');
if ($file_tree) {
fwrite($file_tree, $tree);
fclose ($file_tree);
}
unset ($file_tree,$tree);
}
//наличие
unset($nodes, $artId);
$nodes = newDomXml ($file_stock, $xpath_expression_stock);
foreach($nodes as $node){
$artId = $node->getElementsByTagName('product_id')->item(0)->nodeValue;
$tree[$artId]['amount'] = $node->getElementsByTagName('amount')->item(0)->nodeValue;
$tree[$artId]['free'] = $node->getElementsByTagName('free')->item(0)->nodeValue;
$tree[$artId]['inwayamount'] = $node->getElementsByTagName('inwayamount')->item(0)->nodeValue;
}
if ($tree) {
$tree = serialize($tree);
$file_tree = fopen (dirname(__FILE__).'/stock.txt','w+');
if ($file_tree) {
fwrite($file_tree, $tree);
fclose ($file_tree);
}
unset ($file_tree,$tree);
}
//фильтры
unset($nodes, $artId);
$nodes = newDomXml ($fileFilters, $xpath_expression_filters);
foreach($nodes as $node){
$artId = $node->getElementsByTagName('filtertypeid')->item(0)->nodeValue;
foreach ($node->getElementsByTagName('filters')->item(0)->getElementsByTagName('filter') as $artFilters) {
$tree[$artId][$artFilters->getElementsByTagName('filterid')->item(0)->nodeValue] = $artFilters->getElementsByTagName('filtername')->item(0)->nodeValue;
}
$tree[$artId]['filtertypename'] = $node->getElementsByTagName('filtertypename')->item(0)->nodeValue;
$POST = array(
'key'=>$apiYaTranslate
,'text'=>$tree[$artId]['filtertypename']
,'lang'=>'ru-en'
);
$curl = curl_init();
curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
curl_setopt($curl,CURLOPT_SSL_VERIFYPEER,0);
curl_setopt($curl,CURLOPT_URL,'https://translate.yandex.net/api/v1.5/tr.json/translate');
curl_setopt($curl,CURLOPT_USERAGENT,'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13');
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($POST));
curl_setopt($curl,CURLOPT_FOLLOWLOCATION,1);
$translate = curl_exec($curl);
curl_close($curl);
switch($tree[$artId]['filtertypename']){
case 'Пол':
$tree[$artId]['filtertypenameEng'] = 'sex';
break;
case 'Материал':
$tree[$artId]['filtertypenameEng'] = 'material';
break;
default:
$tree[$artId]['filtertypenameEng'] = str_replace(' ', '_', mb_strtolower(json_decode($translate)->text[0]));
}
}
if ($tree) {
$tree = serialize($tree);
$file_tree = fopen (dirname(__FILE__).'/filters.txt','w+');
if ($file_tree) {
fwrite($file_tree, $tree);
fclose ($file_tree);
}
unset ($file_tree,$tree,$nodes,$artId,$POST);
}
$paths = array('context_settings/');
$options = array('objects' => null, 'extensions' => array('.php'));
$modx->cacheManager->clearCache($paths, $options);
if (!XPDO_CLI_MODE) {echo '<pre>';}
echo "\nИтого в каталоге\n категорий: {$i}\n подкатегорий: {$ii}";//\n товаров: {$iii}";
if (!XPDO_CLI_MODE) {echo '</pre>';}
return true;
}
@dumbuzz
Copy link

dumbuzz commented May 17, 2018

Настоятельно просим изменить конфигурационный параметр $urlImages = 'http://files.gifts.ru/reviewer/'
Это недокументированная возможность, которая создаёт избыточную нагрузку на сервер files.gifts.ru
Картинки нужно скачивать с базового адреса: "http://login:password@api2.gifts.ru/export/v2/catalogue/" и с частотой - не более 5 запросов в секунду.

Разработчики gifts.ru

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment