Advertisement
Guest User

Untitled

a guest
Mar 13th, 2012
283
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 15.17 KB | None | 0 0
  1. <?php
  2.  
  3. chdir('../..');
  4. require_once('api/Simpla.php');
  5.  
  6. class ImportAjax extends Simpla
  7. {  
  8.     // Соответствие полей в базе и имён колонок в файле
  9.     private $columns_names = array(
  10.             'name'=>             array('product', 'name', 'товар', 'название', 'наименование'),
  11.             'url'=>              array('url', 'адрес'),
  12.             'visible'=>          array('visible', 'видим'),
  13.             'featured'=>         array('featured', 'hit', 'хит', 'рекомендуемый'),
  14.             'category'=>         array('category', 'категория'),
  15.             'brand'=>            array('brand', 'бренд'),
  16.             'variant'=>          array('variant', 'вариант'),
  17.             'price'=>            array('price', 'цена'),
  18.             'compare_price'=>    array('compare_price', 'старая цена'),
  19.             'sku'=>              array('sku', 'артикул'),
  20.             'stock'=>            array('stock', 'склад', 'на складе'),
  21.             'meta_title'=>       array('meta_title', 'заголовок страницы'),
  22.             'meta_keywords'=>    array('meta_keywords', 'ключевые слова'),
  23.             'meta_description'=> array('meta_description', 'описание страницы'),
  24.             'annotation'=>       array('annotation', 'аннотация', 'краткое описание'),
  25.             'description'=>      array('description', 'описание'),
  26.             'images'=>           array('images', 'изображения')
  27.             );
  28.    
  29.     // Соответствие имени колонки и поля в базе
  30.     private $internal_columns_names = array();
  31.  
  32.     private $import_files_dir      = 'simpla/files/import/'; // Временная папка      
  33.     private $import_file           = 'import.csv';           // Временный файл
  34.     private $category_delimiter = ',';                       // Разделитель каегорий в файле
  35.     private $subcategory_delimiter = '/';                    // Разделитель подкаегорий в файле
  36.     private $column_delimiter      = ';';
  37.     private $products_count        = 10;
  38.     private $columns               = array();
  39.  
  40.     public function import()
  41.     {
  42.         // Для корректной работы установим локаль UTF-8
  43.         setlocale(LC_ALL, 'ru_RU.UTF-8');
  44.        
  45.         // Определяем колонки из первой строки файла
  46.         $f = fopen($this->import_files_dir.$this->import_file, 'r');
  47.         $this->columns = fgetcsv($f, null, $this->column_delimiter);
  48.  
  49.         // Заменяем имена колонок из файла на внутренние имена колонок
  50.         foreach($this->columns as &$column)
  51.         {
  52.             if($internal_name = $this->internal_column_name($column))
  53.             {
  54.                 $this->internal_columns_names[$column] = $internal_name;
  55.                 $column = $internal_name;
  56.             }
  57.         }
  58.  
  59.         // Если нет названия товара - не будем импортировать
  60.         if(!in_array('name', $this->columns) && !in_array('sku', $this->columns))
  61.             return false;
  62.        
  63.         // Переходим на заданную позицию, если импортируем не сначала
  64.         if($from = $this->request->get('from'))
  65.             fseek($f, $from);
  66.        
  67.         // Массив импортированных товаров
  68.         $imported_items = array(); 
  69.        
  70.         // Проходимся по строкам, пока не конец файла
  71.         // или пока не импортировано достаточно строк для одного запроса
  72.         for($k=0; !feof($f) && $k<$this->products_count; $k++)
  73.         {
  74.             // Читаем строку
  75.             $line = fgetcsv($f, 0, $this->column_delimiter);
  76.  
  77.             $product = null;           
  78.  
  79.             if(is_array($line))        
  80.             // Проходимся по колонкам строки
  81.             foreach($this->columns as $i=>$col)
  82.             {
  83.                 // Создаем массив item[название_колонки]=значение
  84.                 if(isset($line[$i]) && !empty($line) && !empty($col))
  85.                     $product[$col] = $line[$i];
  86.             }
  87.            
  88.             // Импортируем этот товар
  89.             if($imported_item = $this->import_item($product))
  90.                 $imported_items[] = $imported_item;
  91.         }
  92.  
  93.         /*
  94.         if(count($variants_ids)>0)
  95.         {
  96.             // Для отчета выбираем импортированные товары
  97.             $variants = (array)$this->variants->get_variants(array('id'=>$variants_ids));
  98.             $products_ids = array();
  99.  
  100.             foreach($variants as $v)
  101.                 $products_ids[] = $v->product_id;
  102.            
  103.             $products = array();   
  104.             foreach($this->products->get_products(array('id'=>$products_ids)) as $p)
  105.                 $products[$p->id] = $p;
  106.            
  107.  
  108.             foreach($variants as $v)
  109.             {
  110.                 $imported_items[$v->id]->variant_id = $v->id;
  111.                 $imported_items[$v->id]->product_id = $v->product_id;
  112.                 $imported_items[$v->id]->variant_name = $v->name;
  113.                 $imported_items[$v->id]->product_name = $products[$v->product_id]->name;
  114.             }
  115.         }
  116.         else
  117.         {
  118.             $imported_items = null;
  119.         }
  120.         */
  121.        
  122.         // Запоминаем на каком месте закончили импорт
  123.         $from = ftell($f);
  124.        
  125.         // И закончили ли полностью весь файл
  126.         $result->end = feof($f);
  127.  
  128.         fclose($f);
  129.         $size = filesize($this->import_files_dir.$this->import_file);
  130.        
  131.         // Создаем объект результата
  132.         $result->from = $from;          // На каком месте остановились
  133.         $result->totalsize = $size;     // Размер всего файла
  134.         $result->items = $imported_items;   // Импортированные товары
  135.    
  136.         return $result;
  137.     }
  138.    
  139.     // Импорт одного товара $item[column_name] = value;
  140.     private function import_item($item)
  141.     {
  142.         // Проверим не пустое ли название и артинкул (должно быть хоть что-то из них)
  143.         if(empty($item['name']) && empty($item['sku']))
  144.             return false;
  145.  
  146.         // Подготовим товар для добавления в базу
  147.         if(isset($item['name']))
  148.             $product['name'] = trim($item['name']);
  149.  
  150.         if(isset($item['meta_title']))
  151.             $product['meta_title'] = trim($item['meta_title']);
  152.  
  153.         if(isset($item['meta_keywords']))
  154.             $product['meta_keywords'] = trim($item['meta_keywords']);
  155.  
  156.         if(isset($item['meta_description']))
  157.             $product['meta_description'] = trim($item['meta_description']);
  158.  
  159.         if(isset($item['annotation']))
  160.             $product['annotation'] = trim($item['annotation']);
  161.  
  162.         if(isset($item['description']))
  163.             $product['body'] = trim($item['description']);
  164.    
  165.         if(isset($item['visible']))
  166.             $product['visible'] = intval($item['visible']);
  167.  
  168.         if(isset($item['featured']))
  169.             $product['featured'] = intval($item['featured']);
  170.    
  171.         if(isset($item['url']))
  172.             $product['url'] = trim($item['url']);
  173.         else
  174.             $product['url'] = $this->translit($item['name']);
  175.    
  176.         // Если задан бренд
  177.         $item['brand'] = trim($item['brand']); 
  178.         if(!empty($item['brand']))
  179.         {
  180.             // Найдем его по имени
  181.             $this->db->query('SELECT id FROM __brands WHERE name=?', $item['brand']);
  182.             if(!$product['brand_id'] = $this->db->result('id'))
  183.                 // Создадим, если не найден
  184.                 $product['brand_id'] = $this->brands->add_brand(array('name'=>$item['brand'], 'meta_title'=>$item['brand'], 'meta_keywords'=>$item['brand'], 'meta_description'=>$item['brand']));
  185.         }
  186.        
  187.         // Если задана категория
  188.         $category_id = null;
  189.         $categories_ids = array();
  190.         if(isset($item['category']))
  191.         {
  192.             foreach(explode($this->category_delimiter, $item['category']) as $c)
  193.                 $categories_ids[] = $this->import_category($c);
  194.             $category_id = reset($categories_ids);
  195.         }
  196.    
  197.         // Подготовим вариант товара
  198.         if(isset($item['variant']))
  199.             $variant['name'] = trim($item['variant']);
  200.         else
  201.             $variant['name'] = '';
  202.            
  203.         if(isset($item['price']))
  204.             $variant['price'] = trim($item['price']);
  205.            
  206.         if(isset($item['compare_price']))
  207.             $variant['compare_price'] = trim($item['compare_price']);
  208.            
  209.         if(isset($item['stock']))
  210.             if($item['stock'] == '')
  211.                 $variant['stock'] = null;
  212.             else
  213.                 $variant['stock'] = trim($item['stock']);
  214.            
  215.         if(isset($item['sku']))
  216.             $variant['sku'] = trim($item['sku']);
  217.        
  218.         // Если задан артикул варианта, найдем этот вариант и соответствующий товар
  219.         if(!empty($variant['sku']))
  220.         {
  221.             $this->db->query('SELECT id as variant_id, product_id FROM __variants WHERE sku=? LIMIT 1', $variant['sku']);
  222.             $result = $this->db->result();
  223.             if($result)
  224.             {
  225.                 // и обновим товар
  226.                 $product_id = $this->products->update_product($result->product_id, $product);
  227.                 // и вариант
  228.                 $variant_id = $this->variants->update_variant($result->variant_id, $variant);
  229.                
  230.                 // Обновлен
  231.                 $imported_item->status = 'updated';
  232.             }
  233.         }
  234.        
  235.         // Если на прошлом шаге товар не нашелся,
  236.         if(empty($product_id) || empty($variant_id))
  237.         {
  238.             // Ищем его по названию и категории
  239.             //if(!empty($category_id))
  240.             //  $this->db->query('SELECT v.id as variant_id, p.id as product_id FROM __products p LEFT JOIN __variants v ON v.product_id=p.id AND v.name=? LEFT JOIN __products_categories pc ON pc.product_id=p.id WHERE (pc.category_id=? OR pc.category_id is NULL) AND p.name=? LIMIT 1', $item['variant'], $category_id, $item['name']);
  241.             // Или только по названию, если категория не задана
  242.             //else 
  243.                 $this->db->query('SELECT v.id as variant_id, p.id as product_id FROM __products p LEFT JOIN __variants v ON v.product_id=p.id AND v.name=? WHERE p.name=? LIMIT 1', $variant['name'], $item['name']);
  244.            
  245.             $r =  $this->db->result();
  246.             $product_id = $r->product_id;
  247.             $variant_id = $r->variant_id;
  248.             // Если товар найден - обноаляем,
  249.             if($variant_id)
  250.             {
  251.                 $this->variants->update_variant($variant_id, $variant);
  252.                 $this->products->update_product($product_id, $product);            
  253.                 $imported_item->status = 'updated';    
  254.             }
  255.             // Иначе - добавляем
  256.             elseif(empty($variant_id))
  257.             {
  258.                 if(empty($product_id))
  259.                     $product_id = $this->products->add_product($product);
  260.                 $variant['product_id'] = $product_id;
  261.                 $variant_id = $this->variants->add_variant($variant);
  262.                 $imported_item->status = 'added';      
  263.             }
  264.         }
  265.        
  266.         // Нужно вернуть обновленный товар
  267.         $imported_item->variant = $this->variants->get_variant(intval($variant_id));           
  268.         $imported_item->product = $this->products->get_product(intval($product_id));                       
  269.  
  270.         // Добавляем категории к товару
  271.         if(!empty($categories_ids))
  272.             foreach($categories_ids as $c_id)
  273.                 $this->categories->add_product_category($product_id, $c_id);
  274.  
  275.         // Изображения товаров
  276.         if(isset($item['images']))
  277.         {
  278.             // Изображений может быть несколько, через запятую
  279.             $images = explode(',', $item['images']);
  280.             foreach($images as $image)
  281.             {
  282.                 $image = trim($image);
  283.                 if(!empty($image))
  284.                 {
  285.                     // Имя файла
  286.                     $image_filename = pathinfo($image, PATHINFO_BASENAME);
  287.                    
  288.                     // Добавляем изображение только если такого еще нет в этом товаре
  289.                     $this->db->query('SELECT filename FROM __images WHERE product_id=? AND (filename=? OR filename=?) LIMIT 1', $product_id, $image_filename, $image);
  290.                     if(!$this->db->result('filename'))
  291.                     {
  292.                         $this->products->add_image($product_id, $image);
  293.                     }
  294.                 }
  295.             }
  296.         }
  297.         // Характеристики товаров
  298.         foreach($item as $feature_name=>$feature_value)
  299.         {
  300.             // Если нет такого названия колонки, значит это название свойства
  301.             if(!in_array($feature_name, $this->internal_columns_names))
  302.             {
  303.                 // Свойство добавляем только если для товара указана категория
  304.                 if($category_id)
  305.                 {
  306.                     $this->db->query('SELECT f.id FROM __features f WHERE f.name=? LIMIT 1', $feature_name);
  307.                     if(!$feature_id = $this->db->result('id'))
  308.                         $feature_id = $this->features->add_feature(array('name'=>$feature_name));
  309.                        
  310.                     $this->features->add_feature_category($feature_id, $category_id);              
  311.                     $this->features->update_option($product_id, $feature_id, $feature_value);
  312.                 }
  313.                
  314.             }
  315.         }      
  316.         return $imported_item;
  317.     }
  318.    
  319.    
  320.     // Отдельная функция для импорта категории
  321.     private function import_category($category)
  322.     {          
  323.         // Поле "категория" может состоять из нескольких имен, разделенных subcategory_delimiter-ом
  324.         // Только неэкранированный subcategory_delimiter может разделять категории
  325.         $delimiter = $this->subcategory_delimiter;
  326.         $regex = "/\\DELIMITER((?:[^\\\\\DELIMITER]|\\\\.)*)/";
  327.         $regex = str_replace('DELIMITER', $delimiter, $regex);
  328.         $names = preg_split($regex, $category, 0, PREG_SPLIT_DELIM_CAPTURE);
  329.         $id = null;  
  330.         $parent = 0;
  331.        
  332.         // Для каждой категории
  333.         foreach($names as $name)
  334.         {
  335.             // Заменяем \/ на /
  336.             $name = trim(str_replace("\\$delimiter", $delimiter, $name));
  337.             if(!empty($name))
  338.             {
  339.                 // Найдем категорию по имени
  340.                 $this->db->query('SELECT id FROM __categories WHERE name=? AND parent_id=?', $name, $parent);
  341.                 $id = $this->db->result('id');
  342.                
  343.                 // Если не найдена - добавим ее
  344.                 if(empty($id))
  345.                     $id = $this->categories->add_category(array('name'=>$name, 'parent_id'=>$parent, 'meta_title'=>$name,  'meta_keywords'=>$name,  'meta_description'=>$name, 'url'=>$this->translit($name)));
  346.  
  347.                 $parent = $id;
  348.             }  
  349.         }
  350.         return $id;
  351.     }
  352.  
  353.     private function translit($text)
  354.     {
  355.         $ru = split('-', "А-а-Б-б-В-в-Ґ-ґ-Г-г-Д-д-Е-е-Ё-ё-Є-є-Ж-ж-З-з-И-и-І-і-Ї-ї-Й-й-К-к-Л-л-М-м-Н-н-О-о-П-п-Р-р-С-с-Т-т-У-у-Ф-ф-Х-х-Ц-ц-Ч-ч-Ш-ш-Щ-щ-Ъ-ъ-Ы-ы-Ь-ь-Э-э-Ю-ю-Я-я");
  356.         $en = split('-', "A-a-B-b-V-v-G-g-G-g-D-d-E-e-E-e-E-e-ZH-zh-Z-z-I-i-I-i-I-i-J-j-K-k-L-l-M-m-N-n-O-o-P-p-R-r-S-s-T-t-U-u-F-f-H-h-TS-ts-CH-ch-SH-sh-SCH-sch---Y-y---E-e-YU-yu-YA-ya");
  357.  
  358.         $res = str_replace($ru, $en, $text);
  359.         $res = preg_replace("/[\s]+/ui", '-', $res);
  360.         $res = strtolower($res);
  361.         return $res;  
  362.     }
  363.    
  364.     // Фозвращает внутреннее название колонки по названию колонки в файле
  365.     private function internal_column_name($name)
  366.     {
  367.         $name = trim($name);
  368.         $name = str_replace('/', '', $name);
  369.         $name = str_replace('\/', '', $name);
  370.         foreach($this->columns_names as $i=>$names)
  371.         {
  372.             foreach($names as $n)
  373.                 if(!empty($name) && preg_match("/^".preg_quote($name)."$/ui", $n))
  374.                     return $i;
  375.         }
  376.         return false;              
  377.     }
  378. }
  379.  
  380. $import_ajax = new ImportAjax();
  381. header("Content-type: application/json; charset=UTF-8");
  382. header("Cache-Control: must-revalidate");
  383. header("Pragma: no-cache");
  384. header("Expires: -1");     
  385.        
  386. $json = json_encode($import_ajax->import());
  387. print $json;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement