Created
April 2, 2021 12:51
-
-
Save andronex/09fe88bb36b64337cf94bf245f6eecef to your computer and use it in GitHub Desktop.
Парсер товаров с сайта поставщика portobello.ru для MODX Revolution от 2.6.5-pl + miniShop2 от 2.4.12-pl / можно запускать как из браузера с offset, так из консоли или по cron
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
//настройки для коннекта к portobello.ru | |
$portobelloUrlTree = 'https://portobello.ru/export/new-products.xml'; //весь каталог товаров | |
$portobelloUrlStock = 'https://portobello.ru/export/new-products-quantity.xml'; //наличие товаров | |
//настройки для парсинга и установки шаблонов для создаваемых продуктов | |
$fileProductGroups = dirname(__FILE__).'/portobello_groups.txt'; | |
$fileCatExist = dirname(__FILE__).'/portobello_category_exist.txt'; | |
//настройки для обработки товаров | |
$tplProduct = 6;//номер шаблона для карточки товара | |
$numOffset = 3;//число товаров для загрузки за 1 проход парсера | |
$tplParent = 4;//номер шаблона для категорий | |
$tplChildParent = 4;//номер шаблона для подкатегорий | |
$idParent = 10;//id каталога товаров | |
$categoryArticleTVnumber = 'tv8';//ID TV поля для записи уникального идентификатора категории товаров для последующего сравнения с деревом категорий поставщика | |
$tag = 'pto_'; | |
//МЕТА поля массовые | |
$longtitle = ', цены в Москве, заказать оптом на «Gitwell»'; | |
$description = '. Достойный подарок - Gitwell наносит логотипы и фирменный стиль на любые товары.'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
* первый запуск с параметром ?tree=1 | |
*/ | |
//ini_set('display_errors', 1); | |
//ini_set('error_reporting', -1); | |
//error_reporting(E_ALL); | |
require_once(dirname(__FILE__).'/portobello_config.php'); | |
if(!$xml = simplexml_load_file($portobelloUrlTree)){ | |
die('Не получен каталог товаров'); | |
} | |
if(!$stocks = simplexml_load_file($portobelloUrlStock)){ | |
die('Не получены остатки товаров'); | |
} | |
//функция рекурсивной проверки наличия ключа массива | |
function array_key_exists_recursive($key, $arr) { | |
if (array_key_exists($key, $arr)) { | |
return true; | |
} | |
foreach ($arr as $curval) { | |
if (is_array($curval)) { | |
if (array_key_exists_recursive($key, $curval)) { | |
return true; | |
} | |
} | |
} | |
return false; | |
} | |
//функция рекурсивного парсинга страниц и построения структуры каталога | |
/* | |
$item | |
SimpleXMLElement Object | |
( | |
[@attributes] => Array | |
( | |
[id] => 1353 | |
[parentId] => | |
[title] => Шеврон для пледа | |
) | |
) | |
$tree | |
SimpleXMLElement Object | |
( | |
[category] => Array | |
( | |
[0] => SimpleXMLElement Object | |
( | |
[@attributes] => Array | |
( | |
[id] => 1353 | |
[parentId] => | |
[title] => Шеврон для пледа | |
) | |
) | |
[1] => SimpleXMLElement Object | |
( | |
[@attributes] => Array | |
( | |
[id] => 1136 | |
[parentId] => | |
[title] => Ежедневники | |
) | |
) | |
............... | |
*/ | |
function parseCategory(){ | |
global $xml,$idParent; | |
$counter = ['new' => 0, 'upd' => 0, 'error' => 0]; | |
$tree = $xml->categories; | |
foreach($tree->xpath('//category') as $item){ | |
$counter_category = createCategory($item, $tree, $idParent); | |
foreach($counter_category as $key => $val) { | |
$counter[$key] += $counter_category[$key]; | |
} | |
} | |
return ($counter)?echoStat($counter, 'категорий'):false; | |
} | |
//функция скачивания и сохранения картинок | |
function downloadImg($image, $urlImages){ | |
global $modx; | |
if (!file_exists(dirname(__FILE__).'/thumbs/'.$image)) { | |
$ch = curl_init($urlImages); | |
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}"); | |
return ''; | |
} | |
curl_close($ch); | |
} | |
return dirname(__FILE__).'/thumbs/'.$image; | |
} | |
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; // Обнуляем переменную | |
if (XPDO_CLI_MODE) { | |
$numOffset = 50000; | |
$_GET['tree'] = @$argv[1]; | |
} | |
//функция получения массива сопоставляемых категорий | |
function getCategoryManual(){ | |
global $fileCatExist; | |
$category_manual = array(); | |
if($in = @file_get_contents($fileCatExist)){ | |
$category_manual = unserialize($in); | |
} | |
unset($in); | |
return ($category_manual)?:''; | |
} | |
//функция нахождения категории в дереве категорий сайта | |
function getCatExists($article){ | |
global $categoryArticleTVnumber, $modx; | |
$where = $modx->newQuery('msCategory'); | |
$where->leftJoin('modTemplateVarResource', 'TemplateVarResources'); | |
$where->leftJoin('modTemplateVar', 'tv', "tv.id=TemplateVarResources.tmplvarid"); | |
$where->limit(1); | |
$where->where(array( | |
array( | |
'tv.id' => str_replace('tv', '', $categoryArticleTVnumber), | |
'TemplateVarResources.value' => $article | |
) | |
)); | |
return ($res = $modx->getObject('msCategory', $where))?$res->id:false; | |
} | |
//функция обращения к процессору создания категории | |
function createCatProcess($prop, $i = 1){ | |
global $modx, $categoryArticleTVnumber; | |
$response = $modx->runProcessor('resource/create', $prop); | |
//$modx->log(1, print_r($response->response['object'], true)); | |
if ($response->isError()) { | |
print_r($modx->error->failure($response->getMessage())); | |
if($i == 1){ | |
print_r('Пробуем создать категорию с уникальным URI с учётом артикула категории'); | |
$prop['pagetitle'] = $prop['pagetitle'] . '-' . $prop[$categoryArticleTVnumber]; | |
return createCatProcess($prop, 2); | |
} | |
return false; | |
} | |
$res = $modx->getObject('msCategory', array('id' => $response->response['object']['id'])); | |
$res->set('pagetitle', str_replace('-' . $prop[$categoryArticleTVnumber], '', $res->pagetitle)); | |
$res->save(); | |
return $response->response['object']['id']; | |
} | |
//функция создания категорий | |
function createCategory($massiv, $tree, $parent, $return = false, $template = null) { | |
//return 12;//временно | |
global $tplParent,$tplChildParent; | |
global $modx; | |
global $idParent,$categoryArticleTVnumber; | |
global $tag,$longtitle,$description; | |
$new = $upd = $err = 0; | |
if(!$parent) $parent = $idParent; | |
if(!$template) $template = $tplParent; | |
$create = false; | |
$article_cat = $tag . (int)$massiv['id']; | |
//проверка наличия категории в массиве сопоставления категорий | |
if($category_manual = getCategoryManual()){ | |
if(isset($category_manual[ (int)$massiv['id'] ])){ | |
$article_cat = $category_manual[ (int)$massiv['id'] ]['article']; | |
} | |
} | |
/*if($article_cat == 'pto_1330'){//для проверки | |
$article_cat = 'pto_13300'; | |
}*/ | |
if($parent_tree = getCatExists($article_cat)){ | |
$parent = $parent_tree; | |
$create = false; | |
$upd++; | |
if($return){ | |
return $parent; | |
} | |
} | |
else{ | |
$parentId = (int)$massiv['parentId']; | |
$parentMassive = $tree->xpath("//category[@id='".$parentId."']")[0]; | |
$parent = createCategory($parentMassive, $tree, $parent, true); | |
$create = true; | |
$prop = array( | |
'tvs' => true, | |
$categoryArticleTVnumber => $article_cat, | |
'parent' => $parent, | |
'class_key' => 'msCategory', | |
'pagetitle' => (string)$parentMassive['title'], | |
'template' => $template, | |
'published' => 1, | |
'context_key' => 'web', | |
'longtitle' => (string)$parentMassive['title'] . $longtitle, | |
'description' => (string)$parentMassive['title'] . $description, | |
); | |
} | |
if($create){ | |
$parent = ($tmp = createCatProcess($prop))?$tmp:$parent; | |
if($tmp){ | |
$new++; | |
} | |
else{ | |
$err++; | |
} | |
if($return){ | |
return $parent; | |
} | |
} | |
return (array)['new' => $new, 'upd' => $upd, 'error' => $err]; | |
} | |
//функция вывода результатов | |
function echoStat($data, $text = 'товаров'){ | |
global $modx; | |
global $time; | |
$out = ''; | |
if (!XPDO_CLI_MODE) {$out = '<pre>';} | |
$summ = $data['new'] + $data['upd'] + $data['error']; | |
$out .= "\nИмпорт прошёл за ".number_format(microtime(true) - $modx->startTime, 7) . " сек.\n"; | |
$time = microtime(true); | |
$out .= "Итого обработано {$text}\n за проход: {$summ}\n обновлено из них: {$data['upd']}\n создано новых из них: {$data['new']}\n ошибок, в том числе пропущенных: {$data['error']}\n"; | |
//$out .= "Всего обработано {$text}: <a id='link' href='$URL_GET'><span id='offset'>$off_set</span></a>\n"; | |
return $out; | |
} | |
//функция преобразования SimpleXML Object в массив с поддержкой вложенности и CDATA в описании | |
function SimpleXML2ArrayWithCDATASupport($xml) | |
{ | |
$array = (array)$xml; | |
if (count($array) === 0) { | |
return (string)$xml; | |
} | |
foreach ($array as $key => $value) { | |
if (!is_object($value) || strpos(get_class($value), 'SimpleXML') === false) { | |
if($key == 'personalization'){ | |
$array[$key] = SimpleXML2ArrayWithCDATASupport($value); | |
} | |
else{ | |
continue; | |
} | |
} | |
$array[$key] = SimpleXML2ArrayWithCDATASupport($value); | |
} | |
return $array; | |
} | |
//функция получение перечня товаров | |
function getTreeGoods(){ | |
global $tag,$time,$xml,$stocks; | |
$time = $time?:microtime(true); | |
$result = []; | |
if($result_orig = $xml->products->product) { | |
foreach($result_orig as $item){ | |
//удаляем товар, если кол-во 0 или null | |
if($item->price > 0 && $item->bigImage){ | |
$free = $stocks->productsStocks->xpath("//product[@article='{$item->article}']/stock[@xmlId='000000116']"); | |
$is_cat = $xml->categories->xpath("//category[@id='{$item->categoryId}']"); | |
if($free && $is_cat && $free[0] instanceof SimpleXMLElement){ | |
if((int)$free[0]->free){ | |
$tmp = SimpleXML2ArrayWithCDATASupport($item); | |
$tmp['free'] = (int)$free[0]->free; | |
$tmp['balance'] = (int)$free[0]->balance; | |
$tmp['reserve'] = (int)$free[0]->balance - (int)$free[0]->free; | |
$result[] = $tmp; | |
} | |
} | |
} | |
} | |
unset($result_orig); | |
$file_tree = fopen(dirname(__FILE__)."/{$tag}goods.txt",'w+'); | |
if($file_tree) { | |
fwrite($file_tree, json_encode($result)); | |
fclose($file_tree); | |
} | |
unset($file_tree); | |
} | |
return "\nНайдено товаров в каталоге поставщика: " . count($result) . "\nЗапрос занял: ".number_format(microtime(true) - $time, 7) . " сек.\n"; | |
} | |
//функция получение конкретного товара | |
function getInfoGood($id_product){ | |
global $xml,$stocks; | |
if($result = $xml->products->xpath("//product[./article='".$id_product."']")){ | |
$free = $stocks->productsStocks->xpath("//product[@article='{$id_product}']/stock[@xmlId='000000116']"); | |
$tmp = SimpleXML2ArrayWithCDATASupport($result[0]); | |
$tmp['free'] = (int)$free[0]->free; | |
$tmp['balance'] = (int)$free[0]->balance; | |
$tmp['reserve'] = (int)$free[0]->balance - (int)$free[0]->free; | |
return $tmp; | |
} | |
return false; | |
} | |
//функция получение резерва товара | |
/* | |
$id_product = article | |
Array | |
( | |
[free] => 72 | |
[balance] => 72 | |
[reserve] => 0 | |
) | |
*/ | |
function getReserveGood($id_product){ | |
global $xml,$stocks; | |
if($free = $stocks->productsStocks->xpath("//product[@article='{$id_product}']/stock[@xmlId='000000116']")){ | |
$tmp = []; | |
$tmp['free'] = (int)$free[0]->free; | |
$tmp['balance'] = (int)$free[0]->balance; | |
$tmp['reserve'] = (int)$free[0]->balance - (int)$free[0]->free; | |
return $tmp; | |
} | |
return false; | |
} | |
//функция добавления к товару картинок | |
function addImages($image, $res, $pagetitle){ | |
if ($image) { | |
global $modx; | |
$response_img = $modx->runProcessor('gallery/upload', | |
array('id' => $res->get('id'), 'name' => $pagetitle, 'file' => $image), | |
array('processors_path' => MODX_CORE_PATH.'components/minishop2/processors/mgr/') | |
); | |
if ($response_img->isError()) { | |
$modx->log(modX::LOG_LEVEL_ERROR, "Ошибка привязки картинки \"{$image}\" к товару id = {$res->get('id')}: \n". print_r($response_img->getAllErrors(), 1)); | |
} | |
else { | |
$sql = "UPDATE {$modx->getTableName('msProductFile')} SET `name` = \"{$pagetitle}\" WHERE `product_id` = {$res->get('id')};"; | |
$stmt = $modx->prepare($sql); | |
$stmt->execute(); | |
$stmt->closeCursor(); | |
unset($sql, $stmt); | |
unlink($image); | |
$modx->log(modX::LOG_LEVEL_INFO, "Удачно загружена картинка \"$image\": \n". print_r($response_img->getObject(), 1)); | |
return true; | |
} | |
} | |
return false; | |
} | |
//ф-ия создания новых ресурсов или получения ID уже созданных | |
function createProduct ($prop, $filtersArray = array()) { | |
//return 'upd';//временно | |
global $tplProduct, $tag; | |
global $modx; | |
/*if($prop['article'] == 'oas_18664' || $prop['article'] == 'oas_18666'){ | |
return false; | |
}*/ | |
$prop['pagetitle'] = $prop['pagetitle'] . '-' . $prop['article']; | |
$prop['tvs'] = true; | |
//print_r($prop); | |
$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()); | |
//$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->set('old_price', $prop['old_price']); | |
$res->save(); | |
if(is_array($prop['images']) && !$modx->getObject('msProductFile', array('product_id' => $res->id))){ | |
//привязка картинок addImages | |
foreach ($prop['images'] as $v) { | |
addImages($v, $res, $res->pagetitle); | |
} | |
} | |
//удаление картинок | |
if(isset($prop['images'])){ | |
foreach($prop['images'] as $imgs){ | |
if(file_exists($imgs)) unlink($imgs); | |
} | |
} | |
return 'upd'; | |
} | |
$modx->error->message = null; | |
$response = $modx->runProcessor('resource/create', $prop, | |
array('processors_path' => MODX_CORE_PATH.'model/modx/processors/') | |
); | |
if ($response->isError()) { | |
//пишем в лог | |
$modx->log(1, print_r('Первая ошибка', true)); | |
$modx->log(1, print_r($response->getAllErrors(), true)); | |
//пробуем поменять название и создать повторно | |
$prop['pagetitle'] = $prop['pagetitle'] . '-' . $prop['article'] . '-double'; | |
$modx->error->message = null; | |
$response = $modx->runProcessor('resource/create', $prop, | |
array('processors_path' => MODX_CORE_PATH.'model/modx/processors/') | |
); | |
//если всё же ошибка, то выбрасываем error | |
if ($response->isError()) { | |
$modx->log(1, print_r('Повторная ошибка: выбрасывание error', true)); | |
$modx->log(1, print_r($response->getAllErrors(), true)); | |
return 'error'; | |
} | |
} | |
$resource = $response->getObject(); | |
//удаление из pagetitle артикулов, нужных на стадии создания товара для формирования alias ресурса | |
$res = $modx->getObject('msProduct', array('id' => $resource['id'])); | |
$res->set('pagetitle', str_replace('-' . $prop['article'] . '-double', '', $res->get('pagetitle'))); | |
$res->set('pagetitle', str_replace('-' . $prop['article'], '', $res->get('pagetitle'))); | |
$res->save(); | |
//доп. категории только если их более одной в массиве $prop['parents'] | |
if($prop['parents']){ | |
foreach ($prop['parents'] as $catProduct){ | |
$category = $modx->newObject('msCategoryMember'); | |
$category->set('category_id', $catProduct); | |
$category->set('product_id', $resource['id']); | |
$category->save(); | |
} | |
} | |
//привязка фильтров к товару и к категории товара из массива фильтров товара $filtersArray | |
if($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->set('value', ''); | |
$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); | |
}*/ | |
//привязка картинок addImages | |
if ($prop['images']) { | |
foreach ($prop['images'] as $v) { | |
addImages($v, $res, $res->pagetitle); | |
} | |
unset($res, $prop); | |
} | |
return 'new'; | |
} | |
//построение каталога и получение перечня товаров для дальнейшей загрузки с параметром ?tree=1 | |
if(isset($_GET['tree']) && $_GET['tree'] == 1){ | |
echo parseCategory(); | |
echo getTreeGoods(); | |
$URL_GET = str_replace('?tree=1','?off_set=0',$_SERVER['REQUEST_URI']); | |
echo "Ссылка для продолжения обновления каталога: <a id='link' href='$URL_GET'><span id='offset'>{$URL_GET}</span></a>\n"; | |
echo "</pre>"; | |
echo '<script type="text/javascript"> | |
if(document.readyState||document.body.readyState==\'complete\'){ | |
var url = document.getElementById(\'link\').getAttribute(\'href\'); | |
window.location.href = url; | |
document.getElementById(\'link\').setAttribute("style", "pointer-events: none;cursor: default;"); | |
}; | |
</script>'; | |
exit; | |
} | |
//получение перечня товаров, скачанных на сервер в файл {$tag}goods.txt , параметр ?off_set=INTEGER | |
$catalog = $catalog_origin = json_decode(file_get_contents(dirname(__FILE__)."/{$tag}goods.txt"), true); | |
$info = array('upd' => 0, 'new' => 0, 'error' => 0); | |
$i = $a = 0; | |
if(empty($_GET['off_set'])) { | |
$off_set = 0; | |
} | |
else $off_set = (int)$_GET['off_set']; //определяем смещение парсинга | |
foreach($catalog as $tree){ | |
$data = $filtersArray = array(); | |
$i++; | |
if($i <= $off_set) {continue;} | |
if(isset($tree['article'])){ | |
$product = getInfoGood($tree['article']); | |
$reserve = getReserveGood($tree['article']); | |
//if($product['article'] != '15GIFT-BOX-321-BLUE-L/1'){ continue; } | |
/*print_r($reserve[0]['reserve']);exit;*/ | |
$data = array('parent' => $idParent, 'context_key' => 'web', 'template' => $tplProduct, 'class_key' => 'msProduct', 'published' => 1); | |
//if(!$product['total_stock'] || !is_array($product['images'])){continue;} | |
if(!$product || !is_array($reserve)){continue;} | |
$a++; | |
//снимаем с публикации, если товара нет, допускаем только те, которые в наличии | |
if($reserve['free'] <= 0){ | |
$data['published'] = 0; | |
} | |
//получаем нужную инфу по товару | |
//$data['product_id'] = $product['id']; | |
$data['groups_id'] = ($product['model'])?:$product['collection']; | |
$data['article'] = $data['article_donor'] = $tag.$product['article']; | |
$data['pagetitle'] = $product['title']; | |
$data['longtitle'] = $product['title'] . ' - заказать в «Gitwell»'; | |
$data['description'] = '[[*pagetitle]] - заказать печать и нанесение логотипа в Москве, компания «Gitwell»'; | |
$data['content'] = "<p class=\"pto_description\">{$product['description']}</p>"; | |
$data['price'] = $product['price']; | |
$data['weight'] = $product['weight']; | |
$data['old_price'] = $product['price_old']?:0; | |
$data['made_in'] = $filtersArray['brand'][] = $product['brand']; | |
$data['new'] = $data['popular'] = false; | |
if(isset($product['specials']['value']) && $product['specials']['value'] == 'Новинка'){ | |
$data['new'] = true; | |
$filtersArray['migalki'][] = 'Новинки'; | |
} | |
if(isset($product['specials']['value']) && $product['specials']['value'] == 'Промо'){ | |
$data['popular'] = true; | |
$filtersArray['migalki'][] = 'Выгодные предложения'; | |
$filtersArray['migalki'][] = 'Распродажа'; | |
} | |
//скачиваем картинки товара | |
//$first = true; | |
$images = array( $product['bigImage'] ); | |
if($product['addImages'] && $product['addImages']['image']){ | |
if(is_array($product['addImages']['image'])){ | |
foreach($product['addImages']['image'] as $img){ | |
$images[] = $img; | |
} | |
} | |
else{ | |
$images[] = $product['addImages']['image']; | |
} | |
} | |
foreach($images as $img){ | |
$data['images'][] = downloadImg(end(explode('/', $img)), $img); | |
} | |
//определяем родительскую рубрику | |
$main_category = $tag . $product['categoryId']; | |
//проверка наличия категории в массиве сопоставления категорий | |
if($category_manual = getCategoryManual()){ | |
if(isset($category_manual[ $product['categoryId'] ])){ | |
$main_category = $category_manual[ $product['categoryId'] ]['article']; | |
} | |
} | |
//находим ID рубрики | |
if($parent_tree = getCatExists($main_category)){ | |
$data['parent'] = $parent_tree; | |
} | |
//Кастомные тэвэшки для кол-ва доступного товара и для описания упаковки | |
$data['tv9'] = $reserve['balance']; //на складе | |
$data['tv10'] = $reserve['free']?:0; //доступно | |
$data['tv14'] = $data['groups_id']; | |
if($product['size'] && $product['size'] != '//'){//размеры | |
$tmp = trim(str_replace('/','x',$product['size']), 'x'); | |
$tmp = str_replace('xx', 'x', $tmp); | |
$data['size'][] = $tmp . ' мм'; | |
} | |
$idx_option = 1; | |
while(isset($product['material'.$idx_option])){//подробная информация о материале | |
if($product['material'.$idx_option]){ | |
$data['tv13'][] = $product['material'.$idx_option]; | |
if($idx_option == 1){ | |
$filtersArray['material'] = array_map('trim', explode('/', mb_strtolower(trim($product['material'.$idx_option])) )); | |
} | |
} | |
$idx_option++; | |
} | |
if($data['tv13']){ | |
$data['tv13'] = implode(', ', $data['tv13']); | |
} | |
//цвета | |
$data['color'] = []; | |
if(isset($product['multi_color']['value'])){ | |
if(is_array($product['multi_color']['value'])){ | |
foreach($product['multi_color']['value'] as $color){ | |
if( array_search(mb_strtolower(trim($color)), $data['color']) === true ){continue;} | |
$data['color'][] = mb_strtolower(trim($color)); | |
} | |
} | |
else{ | |
if( array_search(mb_strtolower(trim($product['multi_color']['value'])), $data['color']) === true ){continue;} | |
$data['color'][] = mb_strtolower(trim($product['multi_color']['value'])); | |
} | |
} | |
//нанесения | |
if(isset($product['personalization_list']['personalization'])){ | |
if(is_array($product['personalization_list']['personalization'])){ | |
foreach($product['personalization_list']['personalization'] as $personalization){ | |
preg_match('/уф-печать|уф печать/ui', $personalization['name'], $personal_array); | |
if($personal_array){ | |
$filtersArray['type_of_application'][] = 'УФ печать'; | |
} | |
preg_match('/тиснение/ui', $personalization['name'], $personal_array); | |
if($personal_array){ | |
$filtersArray['type_of_application'][] = 'Тиснение'; | |
} | |
preg_match('/шелкография/ui', $personalization['name'], $personal_array); | |
if($personal_array){ | |
$filtersArray['type_of_application'][] = 'Шелкография'; | |
} | |
preg_match('/термотрансфер/ui', $personalization['name'], $personal_array); | |
if($personal_array){ | |
$filtersArray['type_of_application'][] = 'Термотрансфер'; | |
} | |
preg_match('/шеврон/ui', $personalization['name'], $personal_array); | |
if($personal_array){ | |
$filtersArray['type_of_application'][] = 'Шеврон'; | |
} | |
preg_match('/шильда/ui', $personalization['name'], $personal_array); | |
if($personal_array){ | |
$filtersArray['type_of_application'][] = 'Шильда'; | |
} | |
preg_match('/полимерная наклейка/ui', $personalization['name'], $personal_array); | |
if($personal_array){ | |
$filtersArray['type_of_application'][] = 'Полимерная наклейка'; | |
} | |
preg_match('/гравировка/ui', $personalization['name'], $personal_array); | |
if($personal_array){ | |
$filtersArray['type_of_application'][] = 'Гравировка'; | |
} | |
preg_match('/тампопечать/ui', $personalization['name'], $personal_array); | |
if($personal_array){ | |
$filtersArray['type_of_application'][] = 'Тампопечать'; | |
} | |
if( $filtersArray['print'] && (array_search($personalization['name'], $filtersArray['print']) !== true) ){ | |
$filtersArray['print'][] = $personalization['name']; | |
} | |
elseif(!$filtersArray['print']){ | |
$filtersArray['print'][] = $personalization['name']; | |
} | |
if($filtersArray['type_of_application']){ | |
$filtersArray['type_of_application'] = array_unique($filtersArray['type_of_application']); | |
} | |
} | |
} | |
} | |
if(isset($product['personalization_list']['personalization']) && empty($filtersArray['type_of_application'])){ | |
$filtersArray['type_of_application'][] = 'Прочие нанесения'; | |
} | |
//Доп. характеристики | |
foreach($product as $key => $attr_item){ | |
/*if($attr_item['name'] == 'Плотность'){ | |
$data['tv13'] = ($data['tv13'])?$data['tv13'] . ' ' . $attr_item['value']:''; //подробная информация о плотности | |
} | |
if($attr_item['name'] == 'Диаметр ручки/крандаша'){ | |
$data['content'] .= "<p class=\"dop_options\">Диаметр ручки/карандаша: <span>{$attr_item['value']}</span></p>"; | |
}*/ | |
switch($key){ | |
case 'coating': | |
$data['content'] .= $attr_item?"<p class=\"dop_options\">Покрытие: <span>{$attr_item}</span></p>":''; | |
break; | |
case 'capacity': | |
$data['content'] .= $attr_item?"<p class=\"dop_options\">Ёмкость, мА*ч: <span>{$attr_item}</span></p>":''; | |
break; | |
case 'format': | |
$data['content'] .= $attr_item?"<p class=\"dop_options\">Формат: <span>{$attr_item}</span></p>":''; | |
if($attr_item){ | |
$data['content'] .= $product['dated']?"<p class=\"dop_options\">Датированный: <span>{$product['dated']}</span></p>":''; | |
$filtersArray['dating'][] = mb_strtolower(trim($product['dated'])); | |
} | |
break; | |
case 'flexibility': | |
$data['content'] .= $attr_item?"<p class=\"dop_options\">Обложка: <span>{$attr_item}</span></p>":''; | |
if($attr_item){ | |
$filtersArray['type_cover'][] = mb_strtolower(trim($attr_item)); | |
} | |
break; | |
case 'stitching': | |
$data['content'] .= $attr_item?"<p class=\"dop_options\">Сшит: <span>{$attr_item}</span></p>":''; | |
break; | |
case 'pages': | |
$data['content'] .= $attr_item?"<p class=\"dop_options\">Кол-во страниц: <span>{$attr_item}</span></p>":''; | |
break; | |
case 'volume_ml': | |
if($attr_item && ($attr_item < 1)){ | |
$attr_item = $attr_item * 1000; | |
} | |
$data['content'] .= $attr_item?"<p class=\"dop_options\">Объём, мл: <span>{$attr_item}</span></p>":''; | |
break; | |
/*case 'Вид застежки': | |
case 'Кол-во панелей': | |
case 'Возможность замены стержня/картриджа': | |
case 'Диаметр ручки/карандаша': | |
case 'Тип стержня': | |
case 'Цвет чернил': | |
case 'Вид механизма': | |
case 'Вместимость': | |
case 'Кол-во визиток/карт': | |
case 'Объем': | |
case 'Объём': | |
case 'Комплектность': | |
case 'Температурный режим': | |
case 'Источник питания': | |
case 'Диаметр купола': | |
case 'Кол-во сложений': | |
case 'Наличие чехла/футляра': | |
case 'Кол-во спиц': | |
case 'Изнанка': | |
case 'Емкость элемента': | |
case 'Время воспроизведения': | |
case 'Версия Bluetooth®': | |
case 'Мощность': | |
case 'Соединительный разъем': | |
case 'Источник питания': | |
case 'Частотный диапазон': | |
case 'Чувствительность': | |
case 'Максимальная нагрузка': | |
case 'Герметичность': | |
case 'Состав': | |
case 'Масса нетто': | |
case 'Срок годности': | |
case 'Требуется обрешетка': | |
case 'Объем памяти': | |
case 'Интерфейс': | |
case 'Скорость записи': | |
case 'Скорость чтения': | |
case 'Крепление блока': | |
case 'Формат': | |
case 'Разлиновка': | |
case 'Кол-во листов': | |
case 'Обложка': | |
$dim = ($attr_item['dim'])?' <span class="dop_options_dim">'.$attr_item['dim'].'</span>':''; | |
$data['content'] .= "<p class=\"dop_options\">{$attr_item['name']}: <span class=\"dop_options_val\">{$attr_item['value']}</span>{$dim}</p>"; | |
break;*/ | |
} | |
} | |
//упаковка | |
$data['tv12'] = ''; | |
if($product['numberPackaged'] || $product['volume']){ | |
if($product['packaging']){ | |
$data['tv12'] .= "<p><span class=\"pack_type\">Вид упаковки единицы товара:</span> <span class=\"pack_val\">{$product['packaging']}</span></p>"; | |
} | |
if($product['numberPackaged']){ | |
$data['tv12'] .= "<p><span class=\"pack_type\">Количество в транспортной коробке:</span> <span class=\"pack_val\">{$product['numberPackaged']}</span></p>"; | |
} | |
if($product['numberPackaged'] && $product['volume']){ | |
$volume = $product['numberPackaged'] * $product['volume']; | |
$data['tv12'] .= "<p><span class=\"pack_type\">Объём коробки, м³:</span> <span class=\"pack_val\">{$volume}</span></p>"; | |
} | |
elseif(!$product['numberPackaged'] && $product['volume']){ | |
$data['tv12'] .= "<p><span class=\"pack_type\">Объём коробки, м³:</span> <span class=\"pack_val\">{$product['volume']}</span></p>"; | |
} | |
if($product['weight']){ | |
$weight = $product['weight'] * ($product['numberPackaged']?:1); | |
$data['tv12'] .= "<p><span class=\"pack_type\">Вес коробки, кг:</span> <span class=\"pack_val\">{$weight}</span></p>"; | |
} | |
} | |
$filtersArray = array_diff($filtersArray, array('')); | |
//print_r($filtersArray);exit; | |
//создание или обновление товара | |
$modx->error->message = null; | |
$goods = createProduct($data, $filtersArray); | |
/*print_r($product); | |
print_r($reserve); | |
print_r($data); | |
print_r($filtersArray); | |
print_r($goods); | |
exit;*/ | |
//плюсуем произведённое действие (товар обновлён, создан или ошибка) | |
switch($goods) { | |
case 'upd': | |
$info['upd']++; | |
break; | |
case 'new': | |
$info['new']++; | |
break; | |
default: | |
$info['error']++; | |
} | |
//прерываем цикл, если достигнут лимит по количеству обрабатываемых товаров за один проход | |
if ($a == $numOffset) break; | |
//print_r($data); | |
//print_r($info); | |
//exit; | |
} | |
} | |
$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 = 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 обновлено из них: {$info['upd']}\n создано новых из них: {$info['new']}\n ошибок: {$info['error']}\n"; | |
echo "Всего обработано товаров: <a id='link' href='$URL_GET'><span id='offset'>$off_set</span></a>\n"; | |
if ($a == 0) { | |
$autofset = ''; | |
echo "<span style='color:green'>Загрузка завершена</span>"; | |
$resources = $modx->getCollection('modResource', array('template' => 4, 'class_key' => 'msCategory')); | |
$disabled = 0; | |
$active = 0; | |
foreach($resources as $res){ | |
if(!count($modx->getChildIds($res->id,10,array('context' => 'web')))){ | |
$res->set('published', false); | |
$res->save(); | |
$disabled++; | |
} | |
else{ | |
$res->set('published', true); | |
$res->save(); | |
$active++; | |
} | |
} | |
/*print_r($disabled); | |
echo '/'; | |
print_r($active);*/ | |
$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> | |
';} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment