Skip to content

Instantly share code, notes, and snippets.

@andronex
Last active September 11, 2023 17:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andronex/9ca517f6f96fb61b15987238be5fb037 to your computer and use it in GitHub Desktop.
Save andronex/9ca517f6f96fb61b15987238be5fb037 to your computer and use it in GitHub Desktop.
Парсер товаров с сайта поставщика artegifts.by (с группировкой по цветам и размерам) для MODX Revolution от 2.6.5-pl + miniShop2 от 2.4.12-pl / можно запускать как из браузера с offset, так из консоли или по cron
<?php
//настройки для коннекта к artegifts.by
$portobelloUrlTree = 'products_description_xml_cdata001.xml'; //весь каталог товаров (логин/пароль выдаются)
$portobelloUrlStock = 'minskstocks.xml'; //наличие товаров (логин/пароль выдаются)
//настройки для парсинга и установки шаблонов для создаваемых продуктов
$fileCatExist = dirname(__FILE__).'/arte_category_exist.txt'; //сопоставление категорий на сайте (родителей для товаров) с выгрузкой (индивидуально для сайтов)
//настройки для обработки товаров
$tplProduct = 6;//номер шаблона для карточки товара
$numOffset = 3;//число товаров для загрузки за 1 проход парсера
$tplParent = 4;//номер шаблона для категорий
$tplChildParent = 4;//номер шаблона для подкатегорий
$idParent = 10;//id каталога товаров
$categoryArticleTVnumber = 'tv8';//ID TV поля для записи уникального идентификатора категории товаров для последующего сравнения с деревом категорий поставщика
$tag = 'arte_';
//МЕТА поля массовые
$longtitle = ', цены в Москве, заказать оптом на <НАЗВАНИЕ КОМПАНИИ>';
$description = '. Достойный подарок - <НАЗВАНИЕ КОМПАНИИ> наносит логотипы и фирменный стиль на любые товары.';
<?php
require_once(dirname(__FILE__).'/artegifts_config.php');
if(!$xml = simplexml_load_file($portobelloUrlTree)){
die('Не получен каталог товаров');
}
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;
$modx->error->reset(); // Обнуляем переменную
$tree = $xml;
$parents = [];
$groups = []; //помежуточный массив со всеми товарами
$exclude_color = []; //товары без цвета
$sizes = []; //размеры товаров одного цвета
if(!$xml_stock = simplexml_load_file($portobelloUrlStock)){
die('Не получены остатки товаров');
}
foreach($tree->xpath('//item') as $item){
$cat = (string)$item->category;
if(!in_array($cat, $parents)){
$parents[] = $cat;
}
$group_sku = trim((string)$item->parent_sku);
$sku = trim((string)$item->sku);
$properties = $item->addChild('properties');
$color = '';
$sizes_tmp = '';
foreach($item->product_attributes as $attrs){
foreach($attrs as $attr){
// $item['properties'][(string)$attr->attributes()->name] = (string)$attr;
$properties->addChild((string)$attr->attributes()->name);
$properties->{(string)$attr->attributes()->name} = (string)$attr;
if((string)$attr->attributes()->name =='Цвет'){
$color = (string)$attr;
}
if((string)$attr->attributes()->name =='Size'){
$sizes_tmp = (string)$attr;
}
}
}
if($sizes_tmp){
if( count($xml_stock->xpath('//data/item[sku[text()="'.$sku.'"]]')) ){
if( $size_instock = (int)$xml_stock->xpath('//data/item[sku[text()="'.$sku.'"]]')[0]->stock ){
$sizes[$group_sku][$color?'color::'.$color:$sku][] = $sizes_tmp;
}
}
}
$groups[$group_sku][$color?'color::'.$color:$sku][] = $item;
if(!$color){
$exclude_color[] = $item;
}
}
$parents_sopostavlenie = []; // родительские категории товаров
foreach($parents as $parent){
$parent_tmp = trim(end(explode('|', $parent)));
if($in = @file_get_contents($fileCatExist)){
$sopostavlenie = unserialize($in);
}
unset($in);
if(!$parentId = ($sopostavlenie[$parent_tmp]?$sopostavlenie[$parent_tmp]['id']:0)){
if(!$parentId = getCatExists($parent_tmp)){
if($res = $modx->getObject('msCategory', array('pagetitle:LIKE' => "%$parent_tmp%"))){
$parentId = $res->id;
}
else{
$parentId = $idParent;
}
}
}
$parents_sopostavlenie[$parent_tmp] = [
'donor_name' => $parent_tmp,
'id' => $parentId,
];
}
$groups_complete = []; //готовый к загрузке перечень товаров
foreach($groups as $group_id => $color_prod){
foreach($color_prod as $color_ident => $prods){
if( count($prods) > 1 ){
$skus = [];
foreach($prods as $prod){
$skus[] = (string)$prod->sku;
}
$prod[0]->addChild('skus');
$prod[0]->skus = implode('|', $skus);
$groups_complete[$group_id][$color_ident][] = $prod[0];
}
else{
$groups_complete[$group_id][$color_ident] = $prods;
}
}
}
// print_r($parents_sopostavlenie); // родительские категории товаров
// echo count($groups);
// echo count($groups_complete);
// print_r($groups);
// print_r($groups_complete);
// print_r($exclude_color);
// print_r($sizes);
/*$file = fopen(dirname(__FILE__).'/arte_category_exist.txt', 'w+');
if($file) {
fwrite($file, serialize($parents_sopostavlenie));
fclose ($file);
}*/
/*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;
}
// приведение к нижнему регистру первого символа
function mb_lcfirst($str) {
return mb_strtolower(mb_substr($str, 0, 1)) . mb_substr($str, 1);
}
//функция нахождения категории в дереве категорий сайта
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 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 '';
}
$code = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if($code != 200){
return '';
}
curl_close($ch);
}
return dirname(__FILE__).'/thumbs/'.$image;
}
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 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 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['skus']){
$prop['skus'] = array_map(function($val) {global $tag; return $tag.$val;} , $prop['skus']);
$prop['skus'][] = $prop['article'];
}
else{
$prop['skus'] = [];
$prop['skus'][] = $prop['article'];
}
$prop['skus'] = array_unique($prop['skus']);
// print_r($prop['skus']);
// exit;
/*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:IN' => $prop['skus']));
$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('size', json_encode($prop['size']));
$res->set('color', json_encode($prop['color']));
$res->set('tags', json_encode($prop['tags']));
//$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->reset();
$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->reset();
$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';
}
//получение перечня товаров, скачанных на сервер в файл {$tag}goods.txt , параметр ?off_set=INTEGER
$catalog = $catalog_origin = $groups_complete;
$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 $group_id => $color_prod){
// if($group_id != '11380.280/M') continue;
foreach($color_prod as $color_ident => $tree){
if(!preg_match('/^color::/', $color_ident)) continue; //исключения в массиве $exclude_color
$data = $filtersArray = $tags = array();
$i++;
if($i <= $off_set) {continue;}
// распродажа вроде
$salecopy = false;
if( (string)$tree[0]->product->attributes()->salecopy == 'yes' ){
$salecopy = true;
}
$tree = SimpleXML2ArrayWithCDATASupport($tree[0]);
$parent_tmp = trim(end(explode('|', $tree['category'])));
$tree['category'] = $parents_sopostavlenie[$parent_tmp]['id'];
$tree['parent'] = $tree['category'];
$tree['imgs'] = array_map('trim', explode(',', $tree['images_urls']));
$article = $tree['sku'];
$tree['article'] = $tag . $article;
if($tree['skus']){
$tree['skus'] = array_map('trim', explode('|', $tree['skus']));
}
// включая обработку нескольких skus на наличие
if( count($xml_stock->xpath('//data/item[sku[text()="'.$article.'"]]')) ){
$size_instock = (int)$xml_stock->xpath('//data/item[sku[text()="'.$article.'"]]')[0]->stock;
$price = (float)$xml_stock->xpath('//data/item[sku[text()="'.$article.'"]]')[0]->price_ru;
$balance = (int)$xml_stock->xpath('//data/item[sku[text()="'.$article.'"]]')[0]->full_stock;
}
// в выгрузке есть артикулы с пробелом на конце
elseif( count($xml_stock->xpath('//data/item[sku[text()="'.$article.' "]]')) ){
$size_instock = (int)$xml_stock->xpath('//data/item[sku[text()="'.$article.' "]]')[0]->stock;
$price = (float)$xml_stock->xpath('//data/item[sku[text()="'.$article.' "]]')[0]->price_ru;
$balance = (int)$xml_stock->xpath('//data/item[sku[text()="'.$article.' "]]')[0]->full_stock;
}
else{
$balance = 0;
$size_instock = 0;
$price = $tree['price_ru']?:0;
}
if( $tree['skus'] ){
foreach($tree['skus'] as $sku_exist){
if( count($xml_stock->xpath('//data/item[sku[text()="'.$sku_exist.'"]]')) && (int)$xml_stock->xpath('//data/item[sku[text()="'.$sku_exist.'"]]')[0]->stock ){
$size_instock = (int)$xml_stock->xpath('//data/item[sku[text()="'.$sku_exist.'"]]')[0]->stock;
$price = (float)$xml_stock->xpath('//data/item[sku[text()="'.$sku_exist.'"]]')[0]->price_ru;
$balance = (int)$xml_stock->xpath('//data/item[sku[text()="'.$sku_exist.'"]]')[0]->full_stock;
$szs_name = $xml->xpath('//data/item[sku[text()="'.$sku_exist.'"]]/product_attributes/*[@name="Size"]');
$szs_name = $szs_name?$szs_name[0]:$sku_exist;
$tags[] = "{$szs_name} (На складе: {$balance} / Доступно: {$size_instock})";
}
}
}
$tree['price'] = $price;
$tree['price_ru'] = $price;
$tree['free'] = $size_instock;
$tree['stock'] = $size_instock;
$data = array_merge(array('context_key' => 'web', 'template' => $tplProduct, 'class_key' => 'msProduct', 'published' => 1), $tree);
unset($data['id']);
if($data['free'] <= 0){
$data['published'] = 0;
}
$data['groups_id'] = $tag . $group_id;
$data['product'] = trim(str_replace(['распродажа, ', 'распродажа,', 'распродажа', ' , '], ['', '', '', ', '], $data['product']));
$data['product'] = preg_replace('/\s+/', ' ', $data['product']);
$data['pagetitle'] = $data['product'];
$data['longtitle'] = $data['product'] . ' - заказать в <НАЗВАНИЕ КОМПАНИИ>';
$material = '';
if(isset($data['properties']['Материал товара'])){
$material = $data['properties']['Материал товара'];
}
$data['description'] = '[[*pagetitle]]'.($material?(', '. mb_lcfirst($material)):'').' - заказать печать и нанесение логотипа в Москве, компания <НАЗВАНИЕ КОМПАНИИ>';
$data['content'] = "<p class=\"".$tag."description\">{$data['general_description']}</p>";
if(isset($data['properties']['Вес'])){
$data['weight'] = $data['properties']['Вес'];
}
if($data['content'] == '<p class="arte_description"></p>'){
$data['content'] = '';
}
$data['old_price'] = 0;
// $data['made_in'] = $filtersArray['brand'][] = $product['brand'];
$data['new'] = $data['popular'] = false;
if($balance > $size_instock || $salecopy){
$data['popular'] = true;
}
//скачиваем картинки товара
//$first = true;
$images = $data['imgs'];
foreach($images as $img){
$data['images'][] = downloadImg(end(explode('/', $img)), $img);
}
if($data['images']){
$data['images'] = array_diff($data['images'], array(''));
}
if(!$data['images']) continue; //если нет картинок
$a++;
$data['tv9'] = $balance; //на складе
$data['tv10'] = $data['free']?:0; //доступно
$data['tv14'] = $data['groups_id'];
//размеры
if(isset($data['properties']['Размер товара']) && $data['properties']['Размер товара']){
$tmp = trim(str_replace('/','x',$data['properties']['Размер товара']), 'x');
$tmp = str_replace('xx', 'x', $tmp);
$tmp = mb_strtolower($tmp);
$tmp_szs = preg_replace('/(\d)(,)(\d)/ui', '$1.$3', $tmp);
$tmp_szs = array_map('trim', explode(',', $tmp_szs));
if($tmp_szs[1]){
foreach($tmp_szs as $tmp_s){
$data['size'][] = $tmp_s;
}
}
else{
$data['size'][] = $tmp_szs[0];
}
}
if( isset($sizes[$group_id][$color_ident]) ){
$data['size'] = $sizes[$group_id][$color_ident];
}
$data['tags'] = $tags;
//цвета
$data['color'] = [];
if(isset($data['vcolor'])){
$data['color'][] = mb_strtolower(trim(str_replace('color::', '', $color_ident)));
}
//материалы
if($material){
$data['tv13'] = $material;
$material = array_map('trim', explode(',', $material));
$filtersArray['material'][] = mb_lcfirst($material[0]);
foreach($material as $mat_idx => $mat_tmp){
if(!$mat_idx) continue;
if($mat_tmp && !preg_match('/\d/iu', $mat_tmp)){
$filtersArray['material'][] = $mat_tmp;
}
}
}
// пол
if(preg_match('/мужс/iu', $data['pagetitle'])){
$filtersArray['sex'][] = 'мужские';
}
if(preg_match('/женс/iu', $data['pagetitle'])){
$filtersArray['sex'][] = 'женские';
}
//упаковка
$data['tv12'] = '';
$pack = '<p>';
if($data['properties']['Упаковка товара']){
$pack .= "<span class=\"pack_type\">Вид упаковки:</span> <span class=\"pack_val\">{$data['properties']['Упаковка товара']}</span><br>";
}
if($data['properties']['Размер транспортной упаковки']){
$pack .= "<span class=\"pack_type\">Размер транспортной упаковки:</span> <span class=\"pack_val\">{$data['properties']['Размер транспортной упаковки']}</span><br>";
}
if($data['properties']['Вес брутто транспортной упаковки']){
$pack .= "<span class=\"pack_type\">Вес в упаковке:</span> <span class=\"pack_val\">{$data['properties']['Вес брутто транспортной упаковки']}</span><br>";
}
if($data['properties']['Количество в транспортной упаковке']){
$pack .= "<span class=\"pack_type\">Количество в упаковке:</span> <span class=\"pack_val\">{$data['properties']['Количество в транспортной упаковке']}</span><br>";
}
$pack .= '</p>';
if($pack && $pack != '<p></p>'){
$data['tv12'] = $pack;
}
// методы нанесения
if(isset($data['properties']['Виды нанесений'])){
$prints = array_map('trim', explode(',', $data['properties']['Виды нанесений']));
if(is_array($prints)){
foreach($prints as $personalization){
preg_match('/уф-печать|уф печать/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['type_of_application'][] = 'УФ печать';
}
preg_match('/тиснение/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['type_of_application'][] = 'Тиснение';
}
preg_match('/шелкография/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['type_of_application'][] = 'Шелкография';
}
preg_match('/термотрансфер/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['type_of_application'][] = 'Термотрансфер';
}
preg_match('/шильд/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['type_of_application'][] = 'Шильд';
}
preg_match('/гравировка/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['type_of_application'][] = 'Гравировка';
}
preg_match('/тампопечать/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['type_of_application'][] = 'Тампопечать';
}
preg_match('/шубер/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['type_of_application'][] = 'Шубер';
}
preg_match('/вышивка/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['type_of_application'][] = 'Вышивка';
}
preg_match('/трансфер/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['type_of_application'][] = 'Трансфер';
}
preg_match('/деколь/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['type_of_application'][] = 'Надглазурная деколь';
}
$filtersArray['print'][] = $personalization;
}
}
if($filtersArray['print']){
$filtersArray['print'] = array_unique($filtersArray['print']);
}
if($filtersArray['type_of_application']){
$filtersArray['type_of_application'] = array_unique($filtersArray['type_of_application']);
}
}
// моргалки
if($salecopy){
$filtersArray['migalki'][] = 'Распродажа';
}
unset($data['properties']['Материал товара'], $data['properties']['Вес'], $data['properties']['Размер товара'], $data['properties']['Упаковка товара'], $data['properties']['Размер транспортной упаковки'], $data['properties']['Вес брутто транспортной упаковки'], $data['properties']['Количество в транспортной упаковке'], $data['properties']['Виды нанесений'], $data['properties']['Size'], $data['properties']['Цвет'], $data['properties']['Цвет']);
if(count($data['properties'])){
$data['content'] .= '<div class="'.$tag.'description '.$tag.'block_description_variation"><ul>';
foreach($data['properties'] as $prop_name => $prop_val){
$data['content'] .= "<li>{$prop_name}: {$prop_val}</li>";
}
$data['content'] .= '</ul></div>';
}
unset($data['properties'], $data['product'], $data['url']);
$filtersArray = array_diff($filtersArray, array(''));
$modx->error->reset();
$goods = createProduct($data, $filtersArray);
//плюсуем произведённое действие (товар обновлён, создан или ошибка)
switch($goods) {
case 'upd':
$info['upd']++;
break;
case 'new':
$info['new']++;
break;
default:
$info['error']++;
}
//прерываем цикл, если достигнут лимит по количеству обрабатываемых товаров за один проход
if ($a == $numOffset) break 2;
// print_r($group_id);
// print_r($color_ident);
// print_r($data);
// print_r($filtersArray);
// break 2; //принудительное завершение циклов для теста
}
}
// 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>
';}
<?php
/* версия с созданием категорий */
require_once(dirname(__FILE__).'/artegifts_config.php');
if(!$xml = simplexml_load_file($portobelloUrlTree)){
die('Не получен каталог товаров');
}
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;
$modx->error->reset();
$tree = $xml;
$parents = [];
$groups = [];
$exclude_color = [];
$sizes = [];
if(!$xml_stock = simplexml_load_file($portobelloUrlStock)){
die('Не получены остатки товаров');
}
foreach($tree->xpath('//item') as $item){
$cat = (string)$item->category;
if(!in_array($cat, $parents)){
$parents[] = $cat;
}
$group_sku = trim((string)$item->parent_sku);
$sku = trim((string)$item->sku);
$properties = $item->addChild('properties');
$color = '';
$sizes_tmp = trim((string)$item->size_range);
$is_size_attr = false;
foreach($item->product_attributes as $attrs){
foreach($attrs as $attr){
// $item['properties'][(string)$attr->attributes()->name] = (string)$attr;
$properties->addChild((string)$attr->attributes()->name);
$properties->{(string)$attr->attributes()->name} = (string)$attr;
if((string)$attr->attributes()->name == 'Цвет'){
$color = (string)$attr;
}
if((string)$attr->attributes()->name == 'Размер товара'){
$is_size_attr = true;
$sizes_tmp = (string)$attr;
}
}
}
if($sizes_tmp){
if(!$is_size_attr){
$properties->addChild('Размер товара');
$properties->{'Размер товара'} = $sizes_tmp;
$properties->addChild('Это одежда');
$properties->{'Это одежда'} = 1;
}
if( count($xml_stock->xpath('//data/item[sku[text()="'.$sku.'"]]')) ){
if( $size_instock = (int)$xml_stock->xpath('//data/item[sku[text()="'.$sku.'"]]')[0]->stock ){
$sizes[$group_sku][$color?'color::'.$color:$sku][] = $sizes_tmp;
}
}
}
$groups[$group_sku][$color?'color::'.$color:$sku][] = $item;
if(!$color){
$exclude_color[] = $item;
}
}
$parents_sopostavlenie = [];
foreach($parents as $parent){
if(trim($parent) == 'Новый год|Упаковка'){
$parent .= '2';
}
$parent_tmp = trim(end(explode('|', $parent)));
if($in = @file_get_contents($fileCatExist)){
$sopostavlenie = unserialize($in);
}
unset($in);
if(!$parentId = ($sopostavlenie[$parent_tmp]?$sopostavlenie[$parent_tmp]['id']:0)){
if(!$parentId = getCatExists($parent_tmp)){
$parentId = createCategory($parent_tmp, $parent, $idParent);
}
}
//проверка на существование категории
if(!$modx->getObject('modResource', $parentId)){
if(!$parentId = getCatExists($parent_tmp)){
$parentId = createCategory($parent_tmp, $parent, $idParent);
}
}
$parents_sopostavlenie[$parent_tmp] = [
'donor_name' => $parent_tmp,
'id' => $parentId,
];
}
// print_r($parents_sopostavlenie);
// print_r($sizes);
// exit;
$groups_complete = [];
foreach($groups as $group_id => $color_prod){
foreach($color_prod as $color_ident => $prods){
if( count($prods) > 1 ){
$skus = [];
foreach($prods as $prod){
$skus[] = (string)$prod->sku;
}
$prod[0]->addChild('skus');
$prod[0]->skus = implode('|', $skus);
$groups_complete[$group_id][$color_ident][] = $prod[0];
}
else{
$groups_complete[$group_id][$color_ident] = $prods;
}
}
}
// print_r($parents_sopostavlenie); // родительские категории товаров
// echo count($groups);
// echo count($groups_complete);
// print_r($groups);
// print_r($groups_complete);
// print_r(count($groups_complete) . "\n");
// $idx_inner_goods = 0;
// foreach($groups_complete as $group_inner){
// $idx_inner_goods = $idx_inner_goods + count($group_inner);
// }
// print_r($idx_inner_goods);
// print_r($exclude_color);
// print_r($sizes);
// exit;
function mb_lcfirst($str) {
return mb_strtolower(mb_substr($str, 0, 1)) . mb_substr($str, 1);
}
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 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 '';
}
$code = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if($code != 200){
return '';
}
curl_close($ch);
}
return dirname(__FILE__).'/thumbs/'.$image;
}
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 createCatProcess($name, $parent, $i = 1){
global $modx, $categoryArticleTVnumber, $idParent, $tplChildParent, $tplParent, $longtitle, $description, $tag;
$article_cat = $tag . $name;
if($category_manual = getCategoryManual()){
if(isset($category_manual[ $name ])){
//проверка на существование категории
if($modx->getObject('modResource', $category_manual[ $name ]['id'])){
return $category_manual[ $name ]['id'];
}
}
}
if($parent_tree = getCatExists($name)){
$parent = $parent_tree;
return $parent;
}
$alias_cat = $name . $tag . '-merch';
if($modx->findResource($alias_cat)){
$alias_cat = $name . $tag . '-arte-merch';
}
$prop = array(
'tvs' => true,
$categoryArticleTVnumber => $tag . $name,
'parent' => $parent?:$idParent,
'class_key' => 'msCategory',
'pagetitle' => (string)$name,
'template' => $tplChildParent?:$tplParent,
'published' => 1,
'context_key' => 'web',
'longtitle' => (string)$name . $longtitle,
'description' => (string)$name . $description,
'alias' => modResource::filterPathSegment($modx, $alias_cat)
);
$response = $modx->runProcessor('resource/create', $prop);
if ($response->isError()) {
print_r($modx->error->failure($response->getMessage()));
if($i == 1){
print_r('Пробуем создать категорию с уникальным URI с учётом артикула категории');
$prop['pagetitle'] = $prop['pagetitle'] . '-' . $prop[$categoryArticleTVnumber];
return createCatProcess($name, $parent, 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(string $name, string $tree, $parent = 0) {
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 . $name;
if($category_manual = getCategoryManual()){
if(isset($category_manual[ $name ])){
//проверка на существование категории
if($modx->getObject('modResource', $category_manual[ $name ]['id'])){
return $category_manual[ $name ]['id'];
}
}
}
if($parent_tree = getCatExists($name)){
$parent = $parent_tree;
$create = false;
$upd++;
return $parent;
}
else{
if(preg_match('/\|/iu', $tree)){
$trees = array_map('trim', explode('|', $tree));
foreach($trees as $tree_item){
$parent = createCatProcess($tree_item, $parent);
}
}
$create = true;
}
return $parent;
}
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;
}
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) {
continue;
}
$array[$key] = SimpleXML2ArrayWithCDATASupport($value);
}
return $array;
}
function addImages($image, $res, $pagetitle){
global $modx;
if ($image && !is_dir($image)) {
$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;
}
function createProduct ($prop, $filtersArray = array()) {
global $tplProduct, $tag, $idParent;
global $modx;
if($prop['skus']){
$prop['skus'] = array_map(function($val) {global $tag; return $tag.$val;} , $prop['skus']);
$prop['skus'][] = $prop['article'];
}
else{
$prop['skus'] = [];
$prop['skus'][] = $prop['article'];
}
$prop['skus'] = array_unique($prop['skus']);
$ids_inner = $modx->getChildIds($idParent, 10, array('context' => 'web'));
$prop['alias'] = modResource::filterPathSegment($modx, $prop['pagetitle'] . '-' . $prop['article']);
$prop['tvs'] = true;
$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:IN' => $prop['skus'], 'msProduct.id:IN' => $ids_inner));
$q->prepare();
if($res = $modx->getObject('msProduct', $q)) {
$res_id = $rid = $res->id;
$prop['editedon'] = date("Y-m-d H:i:s");
if($res->get('parent') == $idParent){
$res->set('parent', $prop['parent']);
}
if($filtersArray){
$sql = 'DELETE FROM '.$modx->getTableName('msProductOption').' WHERE product_id = ' . $res_id.';';
$stmt = $modx->prepare($sql);
$stmt->execute();
$stmt->closeCursor();
foreach($filtersArray as $keyF => $valsF){
if(is_array($valsF)){
foreach($valsF as $valF){
$optionProduct = $modx->newObject('msProductOption');
$optionProduct->set('product_id', $res_id);
$optionProduct->set('key', $keyF);
$optionProduct->set('value', $valF);
$optionProduct->save();
}
}
else{
$optionProduct = $modx->newObject('msProductOption');
$optionProduct->set('product_id', $res_id);
$optionProduct->set('key', $keyF);
$optionProduct->set('value', $valsF);
$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 ({$res_id}) AND (`value`='' OR `value` IS NULL);";
$stmt = $modx->prepare($sql);
$stmt->execute();
$stmt->closeCursor();
unset($sql, $stmt);
$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_id.',"'.$key.'","'.$dataOption.'")';
}
}
else if(!empty($productData[$key])) $productOption[] = '('.$res_id.',"'.$key.'","'.$productData[$key].'")';
}
}
//Проверка на уникальность значений опций
// print_r('Опции:');
// print_r($productOption);
// 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();
// }
$msoptionsprice = $modx->getService('msoptionsprice');
$msoptionsprice->initialize('web');
$modifications = array(
array(
'name' => $prop['article'],
'price' => $prop['price'],
'old_price' => $prop['old_price'],
'article' => $prop['article'],
'count' => $prop['stock'],
'weight' => $prop['weight'],
'options' => array(
'color' => $prop['color'][0],
'size' => $prop['size_this_goods']?:''
)
),
);
if($prop['tags']){
foreach($prop['tags'] as $szs_dop){
$szs_dop_vals = array_map('trim', explode('::', $szs_dop));
array_push($modifications, array(
'name' => $szs_dop_vals[1],
'price' => $szs_dop_vals[3]?:$prop['price'],
'article' => $szs_dop_vals[0],
'count' => $szs_dop_vals[2],
'weight' => $prop['weight'],
'options' => array(
'color' => $prop['color'][0],
'size' => $szs_dop_vals[1]
)
));
}
}
$modifications = $modx->call('msopModification', 'saveProductModification', [&$modx, $rid, $modifications]);
$res->set('size', json_encode($prop['size']));
$res->set('color', json_encode($prop['color']));
$res->set('tags', json_encode($prop['tags']));
$options = $res->loadData()->get('options');
$options['instock'] = $prop['stock'];
$res->set('options', $options);
//$res->setTVValue(10,$prop['tv10']);
//$res->setTVValue(12,$prop['tv12']);
$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))){
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->reset();
$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['alias'] = modResource::filterPathSegment($modx, $prop['pagetitle'] . '-double');
$modx->error->reset();
$response = $modx->runProcessor('resource/create', $prop,
array('processors_path' => MODX_CORE_PATH.'model/modx/processors/')
);
if ($response->isError()) {
$modx->log(1, print_r('Повторная ошибка: выбрасывание error, товар: ' . $prop['pagetitle'] . ', ' . $prop['article'], true));
$modx->log(1, print_r($response->getAllErrors(), true));
return 'error';
}
}
$resource = $response->getObject();
$msoptionsprice = $modx->getService('msoptionsprice');
$msoptionsprice->initialize('web');
$modifications = array(
array(
'name' => $prop['article'],
'price' => $prop['price'],
'old_price' => $prop['old_price'],
'article' => $prop['article'],
'count' => $prop['stock'],
'weight' => $prop['weight'],
'options' => array(
'color' => $prop['color'][0],
'size' => $prop['size_this_goods']?:''
)
),
);
if($prop['tags']){
foreach($prop['tags'] as $szs_dop){
$szs_dop_vals = array_map('trim', explode('::', $szs_dop));
array_push($modifications, array(
'name' => $szs_dop_vals[1],
'price' => $szs_dop_vals[3]?:$prop['price'],
'article' => $szs_dop_vals[0],
'count' => $szs_dop_vals[2],
'weight' => $prop['weight'],
'options' => array(
'color' => $prop['color'][0],
'size' => $szs_dop_vals[1]
)
));
}
}
$modifications = $modx->call('msopModification', 'saveProductModification', [&$modx, $resource['id'], $modifications]);
$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();
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();
}
}
if($filtersArray){
foreach($filtersArray as $keyF => $valsF){
if(is_array($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();
}
}
elseif($valsF){
$optionProduct = $modx->newObject('msProductOption');
$optionProduct->set('product_id', $resource['id']);
$optionProduct->set('key', $keyF);
$optionProduct->set('value', $valsF);
$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 ($prop['images']) {
foreach ($prop['images'] as $v) {
addImages($v, $res, $res->pagetitle);
}
unset($res, $prop);
}
return 'new';
}
$catalog = $catalog_origin = $groups_complete;
$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'];
// print_r(count($catalog));
// print_r($catalog);
// exit;
foreach($catalog as $group_id => $color_prod){
// if($group_id != '4001.03') continue; //для тестирования группы товаров
foreach($color_prod as $color_ident => $tree){
// if(!preg_match('/^color::/', $color_ident)) continue; // закомментировано, чтобы добавлялись товары без указанных цветов
$data = $filtersArray = $tags = array();
$i++;
if($i <= $off_set) {continue;}
$salecopy = false;
if( (string)$tree[0]->product->attributes()->salecopy == 'yes' ){
$salecopy = true;
}
$tree = SimpleXML2ArrayWithCDATASupport($tree[0]);
if(trim($tree['category']) == 'Новый год|Упаковка'){
$tree['category'] .= '2';
}
$parent_tmp = trim(end(explode('|', $tree['category'])));
$tree['category'] = $parents_sopostavlenie[$parent_tmp]['id'];
$tree['parent'] = $tree['category'];
$tree['imgs'] = array_map('trim', explode(',', $tree['images_urls']));
$article = $tree['sku'];
$tree['article'] = $tag . $article;
if($tree['skus']){
$tree['skus'] = array_map('trim', explode('|', $tree['skus']));
}
if( count($xml_stock->xpath('//data/item[sku[text()="'.$article.'"]]')) ){
$size_instock = (int)$xml_stock->xpath('//data/item[sku[text()="'.$article.'"]]')[0]->stock;
$price = (float)$xml_stock->xpath('//data/item[sku[text()="'.$article.'"]]')[0]->price_ru;
$balance = (int)$xml_stock->xpath('//data/item[sku[text()="'.$article.'"]]')[0]->full_stock;
}
elseif( count($xml_stock->xpath('//data/item[sku[text()="'.$article.' "]]')) ){
$size_instock = (int)$xml_stock->xpath('//data/item[sku[text()="'.$article.' "]]')[0]->stock;
$price = (float)$xml_stock->xpath('//data/item[sku[text()="'.$article.' "]]')[0]->price_ru;
$balance = (int)$xml_stock->xpath('//data/item[sku[text()="'.$article.' "]]')[0]->full_stock;
}
else{
$balance = 0;
$size_instock = 0;
$price = $tree['price_ru']?:0;
}
$tree['price'] = $price;
$tree['price_ru'] = $price;
$tree['free'] = $size_instock;
$tree['stock'] = $size_instock;
$is_published = false;
if($tree['free'] > 0){
$is_published = true;
}
if( $tree['skus'] ){
foreach($tree['skus'] as $sku_exist){
if( count($xml_stock->xpath('//data/item[sku[text()="'.$sku_exist.'"]]')) && (int)$xml_stock->xpath('//data/item[sku[text()="'.$sku_exist.'"]]')[0]->stock ){
$size_instock = (int)$xml_stock->xpath('//data/item[sku[text()="'.$sku_exist.'"]]')[0]->stock;
$price = (float)$xml_stock->xpath('//data/item[sku[text()="'.$sku_exist.'"]]')[0]->price_ru;
$balance = (int)$xml_stock->xpath('//data/item[sku[text()="'.$sku_exist.'"]]')[0]->full_stock;
$szs_name = $xml->xpath('//data/item[sku[text()="'.$sku_exist.'"]]/product_attributes/*[@name="Размер товара"]');
$szs_name = $szs_name?:$xml->xpath('//data/item[sku[text()="'.$sku_exist.'"]]')[0]->size_range;
$szs_name = $szs_name?$szs_name[0]:$sku_exist;
$tags[] = "{$sku_exist}::{$szs_name}::{$size_instock}::{$price}";
if($size_instock > 0){
$is_published = true;
}
}
}
}
$data = array_merge(array('context_key' => 'web', 'template' => $tplProduct, 'class_key' => 'msProduct', 'published' => 1), $tree);
unset($data['id']);
if(!$is_published){
$data['published'] = 0;
}
$data['groups_id'] = $tag . $group_id;
$data['product'] = trim(str_replace(['распродажа, ', 'распродажа,', 'распродажа', ' , '], ['', '', '', ', '], $data['product']));
$data['product'] = preg_replace('/\s+/', ' ', $data['product']);
$data['pagetitle'] = $data['product'];
$data['longtitle'] = $data['product'];
$material = '';
if(isset($data['properties']['Материал товара'])){
$material = $data['properties']['Материал товара'];
}
if(isset($data['properties']['Вес'])){
$data['weight'] = $data['properties']['Вес'];
}
$data['old_price'] = 0;
$data['new'] = $data['popular'] = false;
if($balance > $size_instock || $salecopy){
$data['popular'] = true;
}
$images = $data['imgs'];
foreach($images as $img){
$data['images'][] = downloadImg(end(explode('/', $img)), $img);
}
if($data['images']){
$data['images'] = array_diff($data['images'], array(''));
}
if(!$data['images']) continue; //если нет картинок
$a++;
// $res = $modx->getObject('msProduct', $data['id']);
$data['options-instock'] = $data['stock'];
$data['options-group'] = $data['groups_id'];
$filtersArray['instock'] = $data['stock'];
$filtersArray['group'] = $data['groups_id'];
//$options = $res->loadData()->get('options');
//$options['instock'] = $prop['stock'];
//$res->set('options', $options);
if(isset($data['properties']['Размер товара']) && $data['properties']['Размер товара']){
$tmp = trim(str_replace('/','x',$data['properties']['Размер товара']), 'x');
$tmp = str_replace('xx', 'x', $tmp);
$tmp = mb_strtolower($tmp);
$tmp_szs = preg_replace('/(\d)(,)(\d)/ui', '$1.$3', $tmp);
$tmp_szs = array_map('trim', explode(',', $tmp_szs));
if($tmp_szs[1]){
foreach($tmp_szs as $tmp_s){
//$data['size'][] = $tmp_s;
}
}
else{
//$data['size'][] = $tmp_szs[0];
}
}
if( isset($sizes[$group_id][$color_ident]) ){
$data['size'] = $sizes[$group_id][$color_ident];
}
$data['tags'] = $tags;
$data['color'] = [];
if( isset($data['vcolor']) && preg_match('/^color::/', $color_ident) ){
$data['color'][] = mb_strtolower(trim(str_replace('color::', '', $color_ident)));
}
if($material){
// $data['tv13'] = $material;
$material = array_map('trim', explode(',', $material));
$filtersArray['material'][] = mb_lcfirst($material[0]);
foreach($material as $mat_idx => $mat_tmp){
if(!$mat_idx) continue;
if($mat_tmp && !preg_match('/\d/iu', $mat_tmp)){
$filtersArray['material'][] = $mat_tmp;
}
}
}
if(preg_match('/мужс/iu', $data['pagetitle'])){
$filtersArray['sex'][] = 'мужские';
}
if(preg_match('/женс/iu', $data['pagetitle'])){
$filtersArray['sex'][] = 'женские';
}
//$upakov = $data['properties']['Упаковка товара'];
//$upakov = str_replace(',','',$upakov);
if($data['properties']['Упаковка товара']){
$filtersArray['packing'][] = $data['properties']['Упаковка товара'];
}
if($data['properties']['Размер транспортной упаковки']){
$filtersArray['pack'][] = $data['properties']['Размер транспортной упаковки'];
}
if($data['properties']['Вес брутто транспортной упаковки']){
$filtersArray['packves'][] = $data['properties']['Вес брутто транспортной упаковки'];
}
if($data['properties']['Количество в транспортной упаковке']){
$filtersArray['packcol'][] = $data['properties']['Количество в транспортной упаковке'];
}
if($data['properties']['Объем']){
$filtersArray['obem'][] = $data['properties']['Объем'];
}
if($data['properties']['Цвет чернил']){
$filtersArray['colorhernil'][] = $data['properties']['Цвет чернил'];
}
if($data['properties']['Тип механизма']){
$filtersArray['typemehanizm'][] = $data['properties']['Тип механизма'];
}
if($data['properties']['Тип покрытия']){
$filtersArray['typepok'][] = $data['properties']['Тип покрытия'];
}
if($data['properties']['Тип батареи']){
$filtersArray['typebatarei'][] = $data['properties']['Тип батареи'];
}
if($data['properties']['Входы']){
$filtersArray['vhod'][] = $data['properties']['Входы'];
}
if($data['properties']['Выходы']){
$filtersArray['vihodi'][] = $data['properties']['Выходы'];
}
if($data['properties']['Мощность']){
$filtersArray['mohnost'][] = $data['properties']['Мощность'];
}
if($data['properties']['Дополнительные функции']){
$filtersArray['dopfun'][] = $data['properties']['Дополнительные функции'];
}
if($data['properties']['Тип крышки']){
$filtersArray['typekrihka'][] = $data['properties']['Тип крышки'];
}
if($data['properties']['Размер товара']){
if($data['size']){
$filtersArray['product_size'] = $data['size'];
}
$filtersArray['product_size'][] = $data['properties']['Размер товара'];
$data['size_this_goods'] = $data['properties']['Размер товара'];
$filtersArray['product_size'] = array_unique($filtersArray['product_size']);
if(!$data['properties']['Это одежда']){
$data['size'] = [];
}
}
if($data['properties']['КодНабора']){
$filtersArray['codenabor'][] = $data['properties']['КодНабора'];
}
if($data['general_description']){
$result = str_replace('&lt;', '<', $data['general_description']);
$result = str_replace('&gt;', '>', $result);
$result = str_replace('&quot;', '"', $result);
$result = str_replace('&quot;', '"', $result);
$filtersArray['contens'][] = $result;
}
if(!isset($data['properties']['Виды нанесений'])){
foreach($catalog[$group_id] as $tmp_inner){
if((string)$tmp_inner[0]->properties->{'Виды нанесений'}){
$data['properties']['Виды нанесений'] = (string)$tmp_inner[0]->properties->{'Виды нанесений'};
break;
}
}
}
if(isset($data['properties']['Виды нанесений'])){
$prints = array_map('trim', explode(',', $data['properties']['Виды нанесений']));
if(is_array($prints)){
foreach($prints as $personalization){
preg_match('/уф-печать|уф печать/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['branding'][] = 'УФ печать';
}
preg_match('/Круговая УФ-печать/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['branding'][] = 'Круговая УФ-печать';
}
preg_match('/тиснение/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['branding'][] = 'Тиснение';
}
preg_match('/шелкография/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['branding'][] = 'Шелкография';
}
preg_match('/термотрансфер/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['branding'][] = 'Термотрансфер';
}
preg_match('/термотрансфер полноцвет dtf/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['branding'][] = 'Термотрансфер полноцвет DTF';
}
preg_match('/шильд/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['branding'][] = 'Шильд';
}
preg_match('/гравировка/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['branding'][] = 'Гравировка';
}
preg_match('/3D гравировка/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['branding'][] = '3D гравировка';
}
preg_match('/тампопечать/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['branding'][] = 'Тампопечать';
}
preg_match('/тампопечать большая/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['branding'][] = 'Тампопечать большая';
}
preg_match('/шубер/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['branding'][] = 'Шубер';
}
preg_match('/вышивка/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['branding'][] = 'Вышивка';
}
preg_match('/флекс/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['branding'][] = 'Флекс';
}
preg_match('/деколь/ui', $personalization, $personal_array);
if($personal_array){
$filtersArray['branding'][] = 'Деколь';
}
$filtersArray['print'][] = $personalization;
}
}
if($filtersArray['print']){
$filtersArray['print'] = array_unique($filtersArray['print']);
}
if($filtersArray['branding']){
$filtersArray['branding'] = array_unique($filtersArray['branding']);
}
}
if($salecopy){
$filtersArray['migalki'][] = 'Распродажа';
}
// print_r($data);
// print_r($filtersArray);
unset($data['properties']['Материал товара'], $data['properties']['Вес'], $data['properties']['Размер товара'], $data['properties']['Упаковка товара'], $data['properties']['Размер транспортной упаковки'], $data['properties']['Вес брутто транспортной упаковки'], $data['properties']['Количество в транспортной упаковке'], $data['properties']['Виды нанесений'], $data['properties']['Size'], $data['properties']['Цвет'], $data['properties']['Цвет']);
unset($data['properties'], $data['product'], $data['url']);
$filtersArray = array_diff($filtersArray, array(''));
$modx->error->reset();
$goods = createProduct($data, $filtersArray);
switch($goods) {
case 'upd':
$info['upd']++;
break;
case 'new':
$info['new']++;
break;
default:
$info['error']++;
}
if ($a == $numOffset) break 2;
}
}
$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(XPDO_CLI_MODE){
foreach (glob(dirname(__FILE__) . '/thumbs/*') as $file) {
unlink($file);
}
$paths = array('context_settings/');
$options = array('objects' => null, 'extensions' => array('.php'));
$modx->cacheManager->clearCache($paths, $options);
$ress = $modx->getChildIds($idParent, 10, array('context' => 'web'));
foreach($ress as $resId){
$resObj = $modx->getObject('modResource', ['id' => $resId, 'class_key' => 'msProduct']);
if($resObj){
if($resObj->Data->size && $resObj->Data->size != '[]'){
continue;
}
else{
echo $resId . "\n";
$sql = 'DELETE FROM '.$modx->getTableName('msProductOption').' WHERE `key` = \'size\' AND `product_id` = ' . $resId . ';';
$stmt = $modx->prepare($sql);
$stmt->execute();
$stmt->closeCursor();
}
}
}
}
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++;
// }
// }
$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