Файл: mg-core/lib/import.php
Строк: 260
<?php
/**
* Класс Import - предназначен для импорта товаров в каталог магазина.
*
* @author Авдеев Марк <mark-avdeev@mail.ru>
* @package moguta.cms
* @subpackage Libraries
*/
class Import {
public function __construct() {
}
/**
* Запускает загрузку товаров с заданной строки
* @param type $rowId - id строки для старта
* @return type
*/
public function startUpload($rowId = false) {
if (!$rowId) {
$rowId = 1;
}
if (empty($_SESSION['stopProcessImportCsv'])) {
$data = $this->importFromCsv($rowId);
return
array(
'percent' => $data['percent'],
'status' => 'run',
'rowId' => $data['rowId']
// 'rowId' => 100
);
} else {
unset($_SESSION['stopProcessImportCsv']);
return
array(
'percent' => 0,
'status' => 'canseled',
'rowId' => $rowId
);
}
}
/**
* Останавливает процесс импорта.
* @return type
*/
public function stopProcess() {
$_SESSION['stopProcessImportCsv'] = true;
}
/**
* Вычисляет разделитель в CSV файле.
* @return type
*/
public function getDelimetr() {
$delimert = ';';
return $delimert;
}
public function importFromCsv($rowId) {
$this->maxExecTime = min(30, @ini_get("max_execution_time"));
if (empty($this->maxExecTime)) {
$this->maxExecTime = 30;
}
$startTimeSql = microtime(true);
$delimert = $this->getDelimetr();
$infile = false;
$file = new SplFileObject("uploads/importCatalog.csv");
if ($rowId === 1 || empty($rowId)) {
$rowId = 0;
}
$file->seek($rowId);
while (!$file->eof()) {
$infile = true;
$data = $file->fgetcsv(";");
if ($rowId === 0) {
$rowId = 1;
continue;
}
if ((microtime(true) - $startTimeSql) > $this->maxExecTime - 1) {
break;
}
/* if (empty($_SESSION['break'])) {
$_SESSION['break'] = true;
break;
} */
foreach ($data as $k => $v) {
$v = trim($v);
if (!empty($v)) {
$data[$k] = iconv("WINDOWS-1251", "UTF-8", $v);
}
}
$itemsIn = array(
'cat_id' => $data[0],
'title' => $data[1],
'variant' => $data[2],
'description' => $data[3],
'price' => trim($data[4]),
'url' => trim($data[5]),
'image_url' => trim($data[6]),
'code' => $data[7],
'count' => trim($data[8]),
'activity' => trim($data[9]),
'meta_title' => $data[10],
'meta_keywords' => $data[11],
'meta_desc' => $data[12],
'old_price' => trim($data[13]),
'recommend' => trim($data[14]),
'new' => trim($data[15]),
'sort' => trim($data[16]),
'weight' => trim($data[17]),
'related' => trim($data[18]),
'link_electro' => trim($data[19]),
'currency_iso' => trim($data[20]),
'property' => trim($data[21]),
);
$this->prepareLineCsv($itemsIn);
$rowId++;
}
$file = null;
$percent100 = count(file("uploads/importCatalog.csv"));
$percent = $rowId;
$percent = ($percent * 100) / $percent100;
if (!$infile) {
$percent = 100;
}
// viewData($percent);
$data = array(
'rowId' => $rowId,
'percent' => floor($percent),
);
/*
if($data['percent']==100){
$this->recoveryTableCatProp();
}
*/
return $data;
}
/**
* Парсит категории, создает их и продлукт.
* @param type $itemsIn
*/
public function prepareLineCsv($itemsIn) {
$categories = $this->parseCategoryPath($itemsIn['cat_id']);
$catId = $this->createCategory($categories);
$this->createProduct($itemsIn);
// вычисляем ID категории если она есть
}
/**
* Создает продукт в БД если их небыло
* @param type $product - массив с данными о продукту
*/
public function createProduct($product) {
$variant = $product['variant'];
$property = $product['property'];
unset($product['variant']);
unset($product['property']);
// 1 находим ID категории по заданному пути
$product['cat_id'] = MG::translitIt($product['cat_id'], 1);
$product['cat_id'] = URL::prepareUrl($product['cat_id']);
if ($product['cat_id']) {
$url = URL::parsePageUrl($product['cat_id']);
$parentUrl = URL::parseParentUrl($product['cat_id']);
$parentUrl = $parentUrl != '/' ? $parentUrl : '';
$cat = MG::get('category')->getCategoryByUrl(
$url, $parentUrl
);
$product['cat_id'] = $cat['id'];
}
$product['cat_id'] = !empty($product['cat_id']) ? $product['cat_id'] : 0;
// 2 если URL не задан в файле, то транслитирируем его из названия товара
$product['url'] = !empty($product['url']) ? $product['url'] : MG::translitIt($product['title'], 1);
$product['url'] = URL::prepareUrl($product['url']);
$model = new Models_Product();
if ($product['cat_id'] == 0) {
$alreadyProduct = $model->getProductByUrl($product['url']);
} else {
$alreadyProduct = $model->getProductByUrl($product['url'], $product['cat_id']);
}
// если в базе найден этот продукт, то при обновлении будет сохранен ID и URL
if (!empty($alreadyProduct['id'])) {
$product['id'] = $alreadyProduct['id'];
$product['url'] = $alreadyProduct['url'];
}
// обновляем товар, если его не было то метод вернет массив с параметрами вновь созданного товара, в том числе и ID. Иначе вернет true
$arrProd = $model->updateProduct($product);
$product_id = $product['id'] ? $product['id'] : $arrProd['id'];
/** Процес записи характеристик
$model->saveUserProperty(json_decode(stripslashes($product['thisUserFields'])),$product_id);
*/
$categoryId = $product['cat_id'];
$productId = $product_id;
$listProperty = $property;
$arrProperty = $this->parseListProperty($listProperty);
foreach ($arrProperty as $key => $value) {
$this->createProperty($key, $value, $categoryId, $productId);
}
if (!$variant) {
return true;
}
// $variant = iconv( 'UTF-8','WINDOWS-1251', $variant);
$var = $model->getVariants($product['id'], $variant);
// viewData($var);
$varUpdate = null;
if(!empty($var)){
foreach ($var as $k => $v) {
if ($v['title_variant'] == $variant && $v['product_id'] == $product_id) {
$varUpdate = $v['id'];
}
}
}
// иначе обновляем существующую запись в таблице вариантов
$newVariant = array(
'product_id' => $product_id,
'title_variant' => $variant,
'sort' => $product['sort'],
'price' => $product['price'],
'old_price' => $product['old_price'],
'count' => $product['count'],
'code' => $product['code'],
'activity' => $product['activity'],
'currency_iso' => $product['currency_iso']
);
$model->importUpdateProductVariant($varUpdate, $newVariant, $product_id);
// обновляем продукт по первому варианту
$res = DB::query('
SELECT pv.*
FROM `'.PREFIX.'product_variant` pv
WHERE pv.product_id = '.DB::quote($product_id).'
ORDER BY sort
');
if($row = DB::fetchAssoc($res)){
if(!empty($row)){
$row['title']=$product['title'];
$row['id']=$row['product_id'];
unset($row['image']);
unset($row['title_variant']);
unset($row['product_id']);
// MG::loger(print_r($row,true));
$model->updateProduct($row);
}
}
// }
}
/**
* Создает категории в БД если их небыло.
* @param type $categories - массив категорий полученый из записи вида категория/субкатегория/субкатегория2
*/
public function createCategory($categories) {
foreach ($categories as $category) {
$category['parent_url'] = $category['parent_url'] != '/' ? $category['parent_url'] : '';
if ($category['parent_url']) {
$pUrl = URL::parsePageUrl($category['parent_url']);
$parentUrl = URL::parseParentUrl($category['parent_url']);
$parentUrl = $parentUrl != '/' ? $parentUrl : '';
} else {
$pUrl = $category['url'];
$parentUrl = $category['parent_url'];
}
// вычисляем ID родительской категории если она есть
$alreadyParentCat = MG::get('category')->getCategoryByUrl(
$pUrl, $parentUrl
);
// если нашлась ID родительская категория назначаем parentID для новой
if (!empty($alreadyParentCat)) {
$category['parent'] = $alreadyParentCat['id'];
}
// проверяем, вдруг такая категория уже существует
$alreadyExist = MG::get('category')->getCategoryByUrl(
$category['url'], $category['parent_url']
);
if (!empty($alreadyExist)) {
$category = $alreadyExist;
}
MG::get('category')->updateCategory($category);
}
}
/**
* Восстанавливает привязки характеристик для новых категорий из таблицы import_cat_prop
*/
public function recoveryTableCatProp() {
DB::query("
INSERT INTO ".PREFIX."category_user_property( category_id, property_id )
SELECT c.id as 'category_id', ip.property_id
FROM ".PREFIX."import_cat_prop AS ip
RIGHT JOIN ".PREFIX."category AS c ON ip.url = c.url AND ip.parent_url = c.parent_url
");
}
/**
* Парсит путь категории возвращает набор категорий.
* @param type $itemsIn
*/
public function parseCategoryPath($path) {
$i = 1;
$categories = array();
if (!$path) {
return $categories;
}
$parent = $path;
$parentTranslit = MG::translitIt($parent, 1);
$parentTranslit = URL::prepareUrl($parentTranslit);
$categories[$parent]['title'] = URL::parsePageUrl($parent);
$categories[$parent]['url'] = URL::parsePageUrl($parentTranslit);
$categories[$parent]['parent_url'] = URL::parseParentUrl($parentTranslit);
$categories[$parent]['parent'] = 0;
while ($parent != '/') {
$parent = URL::parseParentUrl($parent);
$parentTranslit = MG::translitIt($parent, 1);
$parentTranslit = URL::prepareUrl($parentTranslit);
if ($parent != '/') {
$categories[$parent]['title'] = URL::parsePageUrl($parent);
$categories[$parent]['url'] = URL::parsePageUrl($parentTranslit);
$categories[$parent]['parent_url'] = URL::parseParentUrl($parentTranslit);
$categories[$parent]['parent_url'] = $categories[$parent]['parent_url'] != '/' ? $categories[$parent]['parent_url'] : '';
$categories[$parent]['parent'] = 0;
}
}
$categories = array_reverse($categories);
return $categories;
}
/**
* Сравнивает создаваемую категорию, с имеющимися ранее.
* Если обнаруживает, что аналогичная категория раньше существовала,
* то возвращает ее старый ID.
*/
public function getCategoryId($title, $path) {
$path = trim($path, '/');
$sql = '
SELECT cat_id
FROM `'.PREFIX.'import_cat`
WHERE `title` ='.DB::quote($title)." AND `parent` = ".DB::quote($path);
$res = DB::query($sql);
if ($row = DB::fetchAssoc($res)) {
return $row['cat_id'];
}
return null;
}
/**
* Возвращает старый ID для товара
* то возвращает ее старый ID.
*/
public function getProductId($title, $cat_id) {
$path = trim($path, '/');
$sql = '
SELECT product_id
FROM `'.PREFIX.'import_prod`
WHERE `title` ='.DB::quote($title)." AND `category_id` = ".DB::quote($cat_id);
$res = DB::query($sql);
if ($row = DB::fetchAssoc($res)) {
return $row['product_id'];
}
return null;
}
/**
* Создает временную таблицу import_cat_prop, для сохранения связей характеристик и категорий
*/
public function greateTempTableImport() {
DB::query("DROP TABLE IF EXISTS ".PREFIX."import_prod");
DB::query("DROP TABLE IF EXISTS ".PREFIX."import_cat");
DB::query("
CREATE TABLE IF NOT EXISTS ".PREFIX."import_cat (
`cat_id` int(11) NOT NULL,
`title` varchar(2048) NOT NULL,
`parent` varchar(2048) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;");
DB::query("
CREATE TABLE IF NOT EXISTS ".PREFIX."import_prod (
`product_id` int(11) NOT NULL,
`title` varchar(2048) NOT NULL,
`url_cpu_cat` varchar(2048) NOT NULL,
`category_id` int(11) NOT NULL,
`variant` int(1) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;");
$sql = '
SELECT
c.id as category_id,
c.title as category_title,
CONCAT(c.parent_url,c.url) as category_url,
p.url as product_url,
p.*
FROM `'.PREFIX.'product` p
LEFT JOIN `'.PREFIX.'category` c
ON c.id = p.cat_id';
$res = DB::query($sql);
$product = new Models_Product();
while ($row = DB::fetchAssoc($res)) {
$parent = $row['category_url'];
// Подставляем всесто URL названия разделов.
$resultPath = '';
//viewData($parent);
while ($parent) {
// echo "<br>--".$resultPath;
$url = URL::parsePageUrl($parent);
$parent = URL::parseParentUrl($parent);
$parent = $parent != '/' ? $parent : '';
$alreadyParentCat = MG::get('category')->getCategoryByUrl(
$url, $parent
);
$resultPath = $alreadyParentCat['title'].'/'.$resultPath;
}
$resultPath = trim($resultPath, '/');
$variants = $product->getVariants($row['id']);
$variant = 0;
DB::query("
INSERT INTO `".PREFIX."import_prod`
(`product_id`, `title`, `url_cpu_cat`, `category_id`, `variant`)
VALUES (".DB::quote($row['id']).", ".DB::quote($row['title']).", ".DB::quote($row['category_url']).", ".DB::quote($row['category_id']).", ".$variant.")");
}
//---------------------наполняем таблицу для категорий-----------------------------
$sql = '
SELECT `id`, `title`, `parent_url`, url,
CONCAT(parent_url,url) as category_url
FROM `'.PREFIX.'category` c';
$res = DB::query($sql);
while ($row = DB::fetchAssoc($res)) {
$parent = $row['parent_url'];
// Подставляем вместо URL названия разделов.
$resultPath = '';
//viewData($parent);
while ($parent) {
// echo "<br>--".$resultPath;
$url = URL::parsePageUrl($parent);
$parent = URL::parseParentUrl($parent);
$parent = $parent != '/' ? $parent : '';
$alreadyParentCat = MG::get('category')->getCategoryByUrl(
$url, $parent
);
$resultPath = $alreadyParentCat['title'].'/'.$resultPath;
}
$resultPath = trim($resultPath, '/');
//echo $row['id'].';'.$row['title'].';'.$row['category_url'].';'.$variant.'<br>';
DB::query("
INSERT INTO `".PREFIX."import_cat`
(`cat_id`, `title`, `parent`)
VALUES (".DB::quote($row['id']).", ".DB::quote($row['title']).", ".DB::quote($resultPath).")");
}
}
/**
* Возвращает массив из входящей строки с характеристиками
* @param type $listProperty пример $listProperty = 'Производитель=Индия&Цвет=красный&высота=1024';
* @return type
*/
function parseListProperty($listProperty) {
$params = explode('&', $listProperty);
$paramsarr = array();
foreach ($params as $value) {
$tmp = explode('=', $value);
$paramsarr[$tmp[0]] = $tmp[1];
}
return $paramsarr;
}
/**
* Возвращает массив из входящей строки с характеристиками
* @param type $key = Название характеристики
* @param type $value = Значание
* @param type $categoryId = Категория
* @param type $productId = Продукт
* @return type
*/
function createProperty($key, $value, $categoryId, $productId) {
if(empty($key)){
return false;
}
// 0. Очистим продукт от всех ранее имеющихся свойств
$propertyId = '';
// 1. Проверяем, существует такая характеристика у данной категории?
$res = DB::query('
SELECT *
FROM `'.PREFIX.'property`
WHERE `name` = '.DB::quote($key)
);
$row = DB::fetchAssoc($res);
if (empty($row)) {
// если нет характеристики до создадим ее
DB::query('
INSERT INTO `'.PREFIX.'property`
(`name`, `type`, `activity`)
VALUES ('.DB::quote($key).',"string",1)'
);
$propertyId = DB::insertId();
} else {
// если найдена уже характеристика, получаем ее id
$propertyId = $row['id'];
}
// 2. Привязываем к продукту
$res = DB::query('
SELECT *
FROM `'.PREFIX.'product_user_property`
WHERE `property_id` = '.DB::quote($propertyId).'
AND `product_id` = '.DB::quote($productId)
);
$row = DB::fetchAssoc($res);
if (empty($row)) {
DB::query('
INSERT INTO `'.PREFIX.'product_user_property`
(`product_id`, `property_id`, `value`)
VALUES ('.DB::quote($productId).','.DB::quote($propertyId).','.DB::quote($value).')'
);
} else {
DB::query('
UPDATE `'.PREFIX.'product_user_property`
SET `value` = '.DB::quote($value).'
WHERE `product_id` = '.DB::quote($productId).'
AND `property_id` = '.DB::quote($propertyId)
);
}
// 3. Привязываем к категории
$res = DB::query('
SELECT *
FROM `'.PREFIX.'category_user_property`
WHERE `property_id` = '.DB::quote($propertyId)
);
$row = DB::fetchAssoc($res);
if (empty($row)) {
// если нет характеристики до создадим ее
DB::query('
INSERT INTO `'.PREFIX.'category_user_property`
(`category_id`, `property_id`)
VALUES ('.DB::quote($categoryId).','.DB::quote($propertyId).')'
);
}
}
}