Skip to content

Instantly share code, notes, and snippets.

@Fi1osof Fi1osof/plugin.php Secret
Last active Nov 22, 2017

Embed
What would you like to do?
1c import
<?php
switch($modx->event->name){
case 'OnMODXInit':
$modx->loadClass('msVendor');
$modx->map['msVendor']['fields']['externalKey'] = null;
$modx->map['msVendor']['fieldMeta']['externalKey'] = array(
'dbtype' => 'varchar',
'precision' => 36,
'phptype' => 'string',
'null' => true,
'default' => null,
);
$modx->loadClass('modImporterObject');
$modx->map['modImporterObject']['fields']['vendor'] = null;
$modx->map['modImporterObject']['fieldMeta']['vendor'] = array(
'dbtype' => 'varchar',
'precision' => 36,
'phptype' => 'string',
'null' => true,
'default' => null,
);
break;
}
<?php
require_once dirname(dirname(dirname(dirname(dirname(__FILE__))))) . '/import/xml/1c/console.class.php';
class modModimporterCustomImport1cConsoleProcessor extends modModimporterImportXml1cConsoleProcessor{
public function initialize(){
$this->setDefaultProperties(array(
"category_root_id" => 19, // Корневой раздел каталога
"category_template_id" => 1, // Шаблон категории
"good_template_id" => 5, // Шаблон товара
));
return parent::initialize();
}
protected function processRequest(){
switch($this->getProperty('modimporter_step')){
# Чтение производителей
case 'modimporter_write_tmp_vendors':
return $this->StepWriteTmpVendors();
break;
// Обновление производителей
case 'modimporter_import_update_vendors':
return $this->StepImportUpdateVendors();
break;
// Создание производителей
case 'modimporter_import_create_vendors':
return $this->StepImportCreateVendors();
break;
default: ;
}
return parent::processRequest();
}
protected function StepWriteTmpCategories(){
if(!$reader = & $this->getReader()){
return $this->failure('Не был получен ридер');
}
if(!$filename = $this->getProperty('filename')){
return $this->failure("Не был указан файл");
}
if(!$path = $this->getImportPath()){
return $this->failure("Не была получена директория файлов");
}
$schema = array(
"КоммерческаяИнформация" => array(
"Классификатор" => array(
"Группы" => array(
"Группа" => array(
"parse" => true,
)
),
),
),
);
$depth = 0;
$parents = array();
$categoryId = false;
$objects = array();
$groupProperties = array(
"Наименование" => "title",
);
$result = $reader->read(array(
"file" => $path.$filename,
), function(modImporterXmlReader $reader) use (& $schema, & $depth, & $categoryId, & $objects, & $groupProperties , & $parents){
$xmlReader = & $reader->getReader();
$node = $reader->getNodeName($xmlReader);
if(!$reader->isNodeText($xmlReader) && $reader->getSchemaNodeByKey($schema, $node)){
if($reader->isNode('Группа', $xmlReader))
{
$categoryId = true;
$depth++;
}
if (
$reader->isNode('Ид', $xmlReader)
AND $categoryId
// AND $depth > 1 Это если надо пропустить первый уровень вложенности
)
{
$id = (string)$reader->getXMLNode($xmlReader);
$parents[$depth] = $id;
$categoryId = $id;
$objects[$id] = array(
"id" => $id,
"tmp_parent" => !empty($parents[$depth - 1]) ? $parents[$depth - 1] : null,
);
}
if (
$reader->isNode($xmlReader->name, $xmlReader)
AND array_key_exists($xmlReader->name, $groupProperties)
AND $categoryId
AND isset($objects[$categoryId])
)
{
$objects[$categoryId][$groupProperties[$xmlReader->name]] = (string)$reader->getXMLNode($xmlReader);
}
if($reader->isNodeEnd('Группа', $xmlReader))
{
$categoryId = false;
$depth--;
}
if ($reader->isNodeEnd('Классификатор', $xmlReader))
{
// Завершаем парсинг файла
return false;
}
}
return true;
});
if($objects){
foreach($objects as $category){
$category = array_merge($category, array(
"tmp_title" => $category['title'],
"tmp_raw_data" => $category,
));
$o = $this->createImportObject($category["id"], $category, "category");
$o->save();
}
}
if($result !== true AND $result !== false){
return $this->failure($result);
}
return $this->nextStep("modimporter_write_tmp_goods", "Категории успешно записаны");
}
protected function StepWriteTmpGoods(){
if(!$reader = & $this->getReader()){
return $this->failure('Не был получен ридер');
}
if(!$filename = $this->getProperty('filename')){
return $this->failure("Не был указан файл");
}
if(!$path = $this->getImportPath()){
return $this->failure("Не была получена директория файлов");
}
$schema = array(
"КоммерческаяИнформация" => array(
"Каталог" => array(
"Товары" => array(
"Товар" => array(
"parse" => true,
),
),
),
),
);
$result = $reader->read(array(
"file" => $path.$filename,
), function(modImporterXmlReader $reader) use (& $schema){
$xmlReader = & $reader->getReader();
$node = $reader->getNodeName($xmlReader);
if(!$reader->isNodeText($xmlReader) && $reader->getSchemaNodeByKey($schema, $node) && $reader->isNode($node, $xmlReader)){
if(isset($schema["parse"]) && $schema["parse"]){
$xml = $reader->getXMLNode($xmlReader);
$id = (string)$xml->Ид;
$tmp_data = (array)self::toArray($xml);
$data = array(
"tmp_title" => $tmp_data['Наименование'],
"tmp_parent" => $tmp_data['Группы']['Ид'],
"tmp_raw_data" => $tmp_data,
"vendor" => !empty($tmp_data['Изготовитель']['Ид']) ? $tmp_data['Изготовитель']['Ид'] : null,
);
$object = $this->createImportObject($id, $data, "product");
if(!$object->tmp_external_key){
$this->modx->log(xPDO::LOG_LEVEL_ERROR, "Ошибка разбора данных товара", '', 'modImporter', __FILE__, __LINE__);
$this->modx->log(xPDO::LOG_LEVEL_ERROR, print_r($tmp_data, true), '', 'modImporter', __FILE__, __LINE__);
}
else if(!$object->save()){
$this->modx->log(xPDO::LOG_LEVEL_ERROR, "Ошибка записи данных товара", '', 'modImporter', __FILE__, __LINE__);
$this->modx->log(xPDO::LOG_LEVEL_ERROR, print_r($object->toArray(), true), '', 'modImporter', __FILE__, __LINE__);
}
$xmlReader->next();
return true;
}
}
return true;
});
if($result !== true AND $result !== false){
return $this->failure($result);
}
return $this->nextStep("modimporter_write_tmp_vendors", "Товары успешно записаны");
}
/*
Записываем производителей
*/
protected function StepWriteTmpVendors(){
/*
Производителей получаем просто выборкой уникальных родителей товаров из временной таблицы
*/
$q = $this->modx->newQuery("modImporterObject");
$alias = $q->getAlias();
$q->where(array(
"tmp_object_type" => "product",
"vendor:!=" => '',
));
$q->select(array(
"{$alias}.*",
));
$q->groupby('vendor');
foreach($this->modx->getIterator("modImporterObject", $q) as $tmp_object){
if(
$raw_data = $tmp_object->get('tmp_raw_data')
AND !empty($raw_data['Изготовитель'])
AND $vendor_data = $raw_data['Изготовитель']
){
$object = $this->createImportObject($vendor_data['Ид'], array(
"tmp_title" => $vendor_data['Наименование'], // Артикул
"tmp_parent" => null,
"tmp_raw_data" => $vendor_data,
), "vendor");
if(!$object->save()){
$this->modx->log(xPDO::LOG_LEVEL_ERROR, "Ошибка записи данных производителя", '', 'modImporter', __FILE__, __LINE__);
$this->modx->log(xPDO::LOG_LEVEL_ERROR, print_r($vendor_data, true), '', 'modImporter', __FILE__, __LINE__);
}
}
}
return $this->nextStep("modimporter_write_tmp_prices", "Производители успешно записаны");
}
protected function StepWriteTmpPrices(){
if(!$reader = & $this->getReader()){
return $this->failure('Не был получен ридер');
}
if(!$filename = $this->getProperty('filename')){
return $this->failure("Не был указан файл");
}
if(!$path = $this->getImportPath()){
return $this->failure("Не была получена директория файлов");
}
$schema = array(
"КоммерческаяИнформация" => array(
"ПакетПредложений" => array(
"Предложения" => array(
"Предложение" => array(
"parse" => true,
),
),
),
),
);
$result = $reader->read(array(
"file" => $path.$filename,
), function(modImporterXmlReader $reader) use (& $schema){
$xmlReader = & $reader->getReader();
$node = $reader->getNodeName($xmlReader);
if(!$reader->isNodeText($xmlReader) && $reader->getSchemaNodeByKey($schema, $node) && $reader->isNode($node, $xmlReader)){
if(isset($schema["parse"]) && $schema["parse"]){
$xml = $reader->getXMLNode($xmlReader);
$id = (string)$xml->Ид;
$tmp_data = (array)self::toArray($xml);
$data = array(
"tmp_title" => $tmp_data['Наименование'],
"tmp_raw_data" => $tmp_data,
);
$object = $this->createImportObject($id, $data, "offer");
if(!$object->tmp_external_key){
$this->modx->log(xPDO::LOG_LEVEL_ERROR, "Ошибка разбора данных товара", '', 'modImporter', __FILE__, __LINE__);
$this->modx->log(xPDO::LOG_LEVEL_ERROR, print_r($tmp_data, true), '', 'modImporter', __FILE__, __LINE__);
}
else if(!$object->save()){
$this->modx->log(xPDO::LOG_LEVEL_ERROR, "Ошибка записи данных товара", '', 'modImporter', __FILE__, __LINE__);
$this->modx->log(xPDO::LOG_LEVEL_ERROR, print_r($object->toArray(), true), '', 'modImporter', __FILE__, __LINE__);
}
$xmlReader->next();
return true;
}
}
return true;
});
if($result !== true AND $result !== false){
return $this->failure($result);
}
return $this->nextStep("modimporter_write_tmp_remains", "Цены успешно записаны");
}
public static function toArray( $xml ) {
$arr = array();
if(is_string( $xml )){
$str = $xml;
if(!$xml = new SimpleXMLElement( $str )){
return $str;
}
}
if(is_array($xml)){
foreach($xml as $item => $node){
$arr[$item] = self::toArray( $node );
}
}
if(empty($xml)){
return (string)$xml;
}
if($xml && ($xml instanceof SimpleXMLElement)){
$children = $xml->children();
if ( !count($children)){
return (string) $xml;
}
else{
foreach ( $children as $key => $node ) {
$node = self::toArray( $node );
// support for 'anon' non-associative arrays
if ( $key == 'anon' ) $key = count( $arr );
// if the node is already set, put it into an array
if ( isset( $arr[$key] ) ) {
if ( !is_array( $arr[$key] ) || @$arr[$key][0] == null ) $arr[$key] = array( $arr[$key] );
$arr[$key][] = $node;
} else {
$arr[$key] = $node;
}
}
}
}
return $arr;
}
/*
Обновляем категории
*/
protected function StepImportUpdateCategories(){
/*
Получаем только те временные данные, для которых есть имеющиеся категории
*/
$category_template_id = $this->getProperty("category_template_id");
$q = $this->modx->newQuery("modImporterObject");
$alias = $q->getAlias();
$q->innerJoin("modResource", "category", "category.template = {$category_template_id} AND category.externalKey = {$alias}.tmp_external_key");
$q->where(array(
"tmp_object_type" => "category",
"tmp_processed" => 0,
));
$q->select(array(
"{$alias}.*",
"category.id as category_id",
));
$q->limit(1);
while($tmp_object = $this->modx->getObject("modImporterObject", $q)){
$tmp_object->tmp_resource_id = $tmp_object->category_id;
$tmp_object->tmp_processed = 1;
$tmp_object->save();
}
return $this->nextStep("modimporter_import_create_categories", "Категории успешно обновлены");
}
// Создаем категории
protected function StepImportCreateCategories(){
$category_root_id = $this->getProperty("category_root_id");
$category_template_id = $this->getProperty("category_template_id");
$q = $this->modx->newQuery("modImporterObject");
$alias = $q->getAlias();
$q->leftJoin("modImporterObject", "Parent", "Parent.tmp_external_key = {$alias}.tmp_parent");
$q->leftJoin("modResource", "Category", "Category.template = {$category_template_id} AND Category.externalKey = {$alias}.tmp_external_key");
$q->where(array(
"tmp_object_type" => "category",
"tmp_processed" => 0,
"Category.id" => null,
));
$q->select(array(
"{$alias}.*",
"Parent.tmp_resource_id as parent",
));
$q->sortby("{$alias}.id");
$q->limit(1);
$limit = $this->getProperty("limit", 50);
if(!$processed = (int)$this->getSessionValue("categories_created")){
$processed = 0;
}
while($tmp_object = $this->modx->getObject("modImporterObject", $q)){
$tmp_object->tmp_processed = 1;
$tmp_object->save();
$pagetitle = $tmp_object->tmp_title;
$alias = "{$pagetitle}";
$data = array(
"externalKey" => $tmp_object->tmp_external_key,
"pagetitle" => $pagetitle,
"parent" => $tmp_object->parent ? $tmp_object->parent : $category_root_id,
"alias" => $alias,
"template" => $category_template_id,
"class_key" => 'msCategory',
"published" => 1,
"isfolder" => 1,
);
$response = $this->modx->runProcessor('resource/create', $data);
if($response->isError()){
$tmp_object->tmp_error = 1;
$tmp_object->tmp_error_msg = json_encode($response->getResponse());
$tmp_object->save();
return $response->getResponse();
}
// else
$object = $response->getObject();
$tmp_object->tmp_resource_id = $object['id'];
$tmp_object->save();
$processed++;
if($limit AND $processed%$limit === 0){
$this->setSessionValue("categories_created", $processed);
return $this->progress("Создано {$processed} новых категорий");
}
}
return $this->nextStep("modimporter_import_update_vendors", "Категории успешно созданы");
}
/*
Обновляем категории
*/
protected function StepImportUpdateVendors(){
$q = $this->modx->newQuery("modImporterObject");
$alias = $q->getAlias();
$q->innerJoin("msVendor", "Vendor", "Vendor.externalKey = {$alias}.tmp_external_key");
$q->where(array(
"tmp_object_type" => "vendor",
"tmp_processed" => 0,
));
$q->limit(1);
$limit = $this->getProperty("limit", 100);
if(!$processed = (int)$this->getSessionValue("vendors_updated")){
$processed = 0;
}
while($tmp_object = $this->modx->getObject("modImporterObject", $q)){
$tmp_object->tmp_processed = 1;
$tmp_object->save();
$processed++;
if($limit AND $processed%$limit === 0){
$this->setSessionValue("vendors_updated", $processed);
return $this->progress("Обновлено {$processed} производителей");
}
}
return $this->nextStep("modimporter_import_create_vendors", "Производители успешно обновлены");
}
// Создаем производителей
protected function StepImportCreateVendors(){
$q = $this->modx->newQuery("modImporterObject");
$alias = $q->getAlias();
$q->leftJoin("msVendor", "Vendor", "Vendor.externalKey = {$alias}.tmp_external_key");
$q->where(array(
"tmp_object_type" => "vendor",
"tmp_processed" => 0,
"Vendor.id" => null,
));
$q->select(array(
"{$alias}.*",
));
$q->sortby("{$alias}.id");
$q->limit(1);
$limit = $this->getProperty("limit", 50);
if(!$processed = (int)$this->getSessionValue("vendors_created")){
$processed = 0;
}
while($tmp_object = $this->modx->getObject("modImporterObject", $q)){
$tmp_object->tmp_processed = 1;
$tmp_object->save();
$pagetitle = $tmp_object->tmp_title;
$data = array(
"externalKey" => $tmp_object->tmp_external_key,
"name" => $pagetitle,
);
$namespace = 'minishop2';
$response = $this->modx->runProcessor('mgr/settings/vendor/create', $data,array(
'processors_path' => $this->modx->getObject('modNamespace', $namespace)->getCorePath().'processors/',
));
if($response->isError()){
$tmp_object->tmp_error = 1;
$tmp_object->tmp_error_msg = json_encode($response->getResponse());
$tmp_object->save();
return $response->getResponse();
}
// else
$object = $response->getObject();
$tmp_object->tmp_resource_id = $object['id'];
$tmp_object->save();
$processed++;
if($limit AND $processed%$limit === 0){
$this->setSessionValue("vendors_created", $processed);
return $this->progress("Создано {$processed} новых производителей");
}
}
return $this->nextStep("modimporter_import_goods", "Производители успешно созданы");
}
/*
Обновляем товары
*/
protected function StepImportUpdateGoods(){
/*
Получаем только те временные данные, для которых есть имеющиеся товары
*/
$good_template_id = $this->getProperty("good_template_id");
$q = $this->modx->newQuery("modImporterObject");
$alias = $q->getAlias();
$q->innerJoin("modResource", "resource", "resource.template = {$good_template_id} AND resource.externalKey = {$alias}.tmp_external_key");
$q->where(array(
"tmp_object_type" => "product",
"tmp_processed" => 0,
));
$q->select(array(
"{$alias}.*",
"resource.id as resource_id",
));
$q->limit(1);
$limit = $this->getProperty("limit", 100);
if(!$processed = (int)$this->getSessionValue("products_updated")){
$processed = 0;
}
while($tmp_object = $this->modx->getObject("modImporterObject", $q)){
$tmp_object->tmp_resource_id = $tmp_object->resource_id;
$tmp_object->tmp_processed = 1;
$tmp_object->save();
$processed++;
if($limit AND $processed%$limit === 0){
$this->setSessionValue("products_updated", $processed);
return $this->progress("Обновлено {$processed} товаров");
}
}
return $this->nextStep("modimporter_import_create_goods", "Товары успешно обновлены");
}
// Создаем товары
protected function StepImportCreateGoods(){
$good_template_id = $this->getProperty('good_template_id');
$category_template_id = $this->getProperty("category_template_id");
$q = $this->modx->newQuery("modImporterObject");
$alias = $q->getAlias();
$q->leftJoin("modResource", "Product", "Product.template = {$good_template_id} AND Product.externalKey = {$alias}.tmp_external_key");
$q->innerJoin("modImporterObject", "CategoryTmpObject", "CategoryTmpObject.tmp_external_key = {$alias}.tmp_parent");
$q->innerJoin("modResource", "Category", "Category.id = CategoryTmpObject.tmp_resource_id AND Category.template = {$category_template_id}");
$q->leftJoin("msVendor", "Vendor", "Vendor.externalKey = {$alias}.vendor");
$q->where(array(
"tmp_object_type" => "product",
"tmp_processed" => 0,
"Product.id" => null,
));
$q->select(array(
"{$alias}.*",
"{$alias}.tmp_external_key as pagetitle",
"{$alias}.tmp_title as longtitle",
"Category.id as parent",
"Vendor.id as vendor_id",
));
$q->limit(1);
$limit = $this->getProperty("limit", 20);
if(!$inserted = (int)$this->getSessionValue("goods_inserted")){
$inserted = 0;
}
while($tmp_object = $this->modx->getObject("modImporterObject", $q)){
$tmp_object->tmp_processed = 1;
$tmp_object->save();
$raw_data = $tmp_object->get('tmp_raw_data');
$article = $raw_data['Артикул'];
$pagetitle = $tmp_object->tmp_title;
$alias = "{$pagetitle}";
$data = array(
"class_key" => 'msProduct',
"published" => 1,
"isfolder" => 0,
"template" => $good_template_id,
"parent" => $tmp_object->parent,
"externalKey" => $tmp_object->tmp_external_key,
"article" => $article,
"pagetitle" => $pagetitle,
"alias" => $alias,
"content" => !empty($raw_data['Описание']) ? $raw_data['Описание'] : '',
"vendor" => $tmp_object->vendor_id,
);
$response = $this->modx->runProcessor('resource/create', $data);
if($response->isError()){
$tmp_object->tmp_error = 1;
$tmp_object->tmp_error_msg = json_encode($response->getResponse());
$this->modx->error->reset();
}
else{
$object = $response->getObject();
$tmp_object->tmp_resource_id = $object['id'];
// Обновляем галерею
if(
!empty($raw_data['Картинка'])
AND $images = (array)$raw_data['Картинка']
){
foreach($images as $image){
$image = $this->getImportPath() . $image;
if(!file_exists($image)){
$this->modx->log(xPDO::LOG_LEVEL_ERROR, "Отсутствует картинка '{$image}'", '', 'modImporter', __FILE__, __LINE__);
}
else{
$response = $this->modx->runProcessor('gallery/upload',
array(
'id' => $object['id'],
'file' => $image,
),
array('processors_path' => MODX_CORE_PATH.'components/minishop2/processors/mgr/')
);
if ($response->isError()) {
$this->modx->log(xPDO::LOG_LEVEL_ERROR, print_r($response->getAllErrors(), 1), '', 'modImporter', __FILE__, __LINE__);
$this->modx->error->reset();
}
}
}
}
}
$tmp_object->save();
$inserted++;
if($limit AND $inserted%$limit === 0){
$this->setSessionValue("goods_inserted", $inserted);
return $this->progress("Создано {$inserted} новых товаров");
}
}
return $this->nextStep("modimporter_import_prices", "Товары успешно созданы");
}
protected function StepImportPrices(){
return $this->nextStep("modimporter_import_flush_prices", "Стартуем импорт цен и остатков");
}
// Сбрасываем остатки
protected function StepImportFlushPrices(){
$q = $this->modx->newQuery('msProductData');
$q->command('update');
$q->set(array(
'amount' => 0,
));
$q->prepare()
->execute();
return $this->nextStep("modimporter_import_create_prices", "Остатки успешно сброшены");
}
// Создаем цены и остатки
protected function StepImportCreatePrices(){
$good_template_id = $this->getProperty('good_template_id');
$q = $this->modx->newQuery("modImporterObject");
$alias = $q->getAlias();
$q->innerJoin("modResource", "Product", "Product.template = {$good_template_id} AND Product.externalKey = {$alias}.tmp_external_key");
$q->where(array(
"tmp_object_type" => "offer",
"tmp_processed" => 0,
));
$q->select(array(
"{$alias}.*",
"Product.id as resource_id",
));
$q->limit(1);
$limit = $this->getProperty("limit", 100);
if(!$processed = (int)$this->getSessionValue("prices_processed")){
$processed = 0;
}
while($tmp_object = $this->modx->getObject("modImporterObject", $q)){
$tmp_object->tmp_processed = 1;
$tmp_object->save();
$raw_data = $tmp_object->get('tmp_raw_data');
$data = array(
"price" => !empty($raw_data['Цены']['Цена']['ЦенаЗаЕдиницу']) ? $raw_data['Цены']['Цена']['ЦенаЗаЕдиницу'] : 0,
"amount" => !empty($raw_data['Количество']) ? $raw_data['Количество'] : 0,
);
$q2 = $this->modx->newQuery('msProductData');
$q2->command('update');
$q2->set($data);
$q2->where(array(
"id" => $tmp_object->resource_id,
));
$q2->prepare()
->execute();
$processed++;
if($limit AND $processed%$limit === 0){
$this->setSessionValue("prices_processed", $processed);
return $this->progress("Обновлено {$processed} цен и остатков");
}
}
return $this->nextStep("modimporter_import_remains", "Цены и остатки успешно созданы");
}
}
return 'modModimporterCustomImport1cConsoleProcessor';
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.