<?php
// catalog/controller/api/product.php
class ControllerApiProduct extends Controller {
    private $error = array();
    protected $null_array = array();
    protected $use_table_seo_url = false;
    protected $posted_categories = '';

    protected function validateData($data) {

        if (!isset($data['names']) || !$data['names']) {
            $this->error['names'] = sprintf($this->language->get('error_required'), 'Names');
        }

        if ($this->error && !isset($this->error['warning'])) {
            $this->error['warning'] = $this->language->get('error_warning');
        }
        return $this->error;
    }

    public function delproduct(){
        $json = array();
        $check = $this->check->checkToken();
        if (!$check) {
            $json['code'] = 401;
            $json['error']['warning'] = $this->language->get('error_permission');
        } else {
            $product_id  = (int)$_REQUEST['product_id'];
            // load model
            $this->load->model('catalog/product');
            $this->model_catalog_product->deleteProduct($product_id);
            $this->cache->deleteLike('index_');
            $json['success']['msg'] = 'delete success';
            $json['code'] = 200;
        }
    }
    //分配库存 $product['sku'],$product['product_id'],$product['act']默认是更新库存
    public function update_stock(){
        $this->load->language('api/product');
        $json = array();
        $check = $this->check->checkToken();

        if (!$check) {
            $json['code'] = 401;
            $json['error']['warning'] = $this->language->get('error_permission');
        } else {
            if (($this->request->server['REQUEST_METHOD'] == 'POST')) {
                //接post body json
                $products = json_decode(file_get_contents("php://input"),true);
                if(!$products) {
                    $this->error['required'] = sprintf($this->language->get('error_required'), '');
                }
                foreach ($products as $k=>$product){
                $action = isset($product['act'])?$product['act']:'update';
                if (!isset($product['product_id']) && !isset($product['skuid'])) {
                    $this->error['required'] = sprintf($this->language->get('error_required'), 'Product_id or Sku_id');
                }
                if (!isset($product['quantity']) || !$product['quantity'] || (int)$product['quantity'] <= 0) {
                    $this->error['required'] = sprintf($this->language->get('error_required'), 'Quantity');
                }

                $product_id  = (int)$product['product_id'];
                $sku_id = $product['skuid'];
                $quantity = (int)$product['quantity'];
                // load model
                $this->load->model('catalog/product');
                $product_org = $this->model_catalog_product->getProduct($product_id);

                //检查产品是否存在
                if(empty($product_org)){
                    $this->error['product_not_exist'] = $this->language->get('error_not_exist');
                }
                if($this->error){
                    if ($this->error && !isset($this->error['warning'])) {
                        $this->error['warning'] = $this->language->get('error_warning');
                        $this->error['code'] = 400;
                    }
                    echo json_encode($this->error);exit;
                }
                $status = false;
                if($action != 'update'){
                    $quantity = (int)$product_org['quantity']+$quantity;
                }
                if($quantity>0){
                    if (!empty($product_id) && !empty($sku_id)) {
                        $where = "product_id = '" . $product_id . "' AND option_skuid='".$sku_id."'";
                        $status = $this->db->query("UPDATE " . DB_PREFIX . "product_option_value SET quantity = '" . $quantity . "' WHERE {$where}");
                    }
                }
                if($status==false){
                    if($this->error){
                        if ($this->error && !isset($this->error['warning'])) {
                            $this->error['warning'] = $this->language->get('text_update_fail');
                            $this->error['code'] = 400;
                        }
                        echo json_encode($this->error);exit;
                    }
                }else{
                    $status=false;
                    //更新产品总库存
                    $product_quantity = 0;
                    $sql = "SELECT * FROM `".DB_PREFIX."product_option_value` WHERE product_id=".$product_id;
                    $query = $this->db->query( $sql );
                    foreach ($query->rows as $product_option_value) {
                        $product_quantity +=$product_option_value['quantity'];
                    }
                    $status = $this->db->query("UPDATE " . DB_PREFIX . "product SET quantity = '" . $product_quantity . "' WHERE product_id=".$product_id);
                }
                }
                if($status){
                    $json['success']['msg'] = $this->language->get('text_modify_success');
                    $json['code'] = 200;
                }
            }
        }
        if (isset($this->request->server['HTTP_ORIGIN'])) {
            $this->response->addHeader('Access-Control-Allow-Origin: ' . $this->request->server['HTTP_ORIGIN']);
            $this->response->addHeader('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
            $this->response->addHeader('Access-Control-Max-Age: 1000');
            $this->response->addHeader('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
        }

        $this->response->addHeader('Content-Type: application/json');
        $this->response->setOutput(json_encode($json));
    }

    public function add($setting = null) {
        $this->load->language('api/product');
        $json = array();
        $check = $this->check->checkToken();
        if (!$check) {
            $json['code'] = 401;
            $json['error']['warning'] = $this->language->get('error_permission');
        } else {
            //接post body json
            $product = !empty($setting)?$setting:json_decode(file_get_contents("php://input"),true);
            if(!$product){
                echo json_encode(['code'=>400,'error_warning'=>sprintf($this->language->get('error_required'), '')]);exit;
            }
            $error =  $this->validateData($product);
            if($error){
                $error['code'] = 400;
                echo json_encode($error);exit;
            }

            // save old url_alias_ids
            $url_alias_ids = array();
            if (!$this->use_table_seo_url) {
                $url_alias_ids = $this->getProductUrlAliasIds();
            }

            // some older versions of OpenCart use the 'product_tag' table
            $query = $this->db->query( "SHOW TABLES LIKE '".DB_PREFIX."product_tag'" );
            $exist_table_product_tag = ($query->num_rows > 0);

            // Opencart versions from 2.0 onwards also have product_description.meta_title
            $sql = "SHOW COLUMNS FROM `".DB_PREFIX."product_description` LIKE 'meta_title'";
            $query = $this->db->query( $sql );
            $exist_meta_title = ($query->num_rows > 0) ? true : false;

            // get pre-defined store_ids
            $available_store_ids = $this->getAvailableStoreIds();

            // find the installed languages
            $languages = $this->getLanguages();

            // find existing manufacturers, only newly specified manufacturers will be added
            $manufacturers = $this->getManufacturers();

            // get weight classes
            $weight_class_ids = $this->getWeightClassIds();

            // get length classes
            $length_class_ids = $this->getLengthClassIds();

            // get list of the field names, some are only available for certain OpenCart versions
            $product_fields = $this->getProductFields();

            $product_id  = (int)$product['product_id'];
            // load model
            $this->load->model('catalog/product');
            $product_org = $this->model_catalog_product->getProduct($product_id);
            if($product_org){
                $product = array_merge($product_org, $product);
            }

            $product_id = $this->storeProductIntoDatabase($product, $languages, $product_fields, $exist_table_product_tag, $exist_meta_title, $available_store_ids, $manufacturers, $weight_class_ids, $length_class_ids, $url_alias_ids);

            if($product_id>0){
                //清除缓存
                //$this->cache->deleteLike('index_');
                //$this->cache->deleteLike('product_detail_'.$product_id);
                $json['success']['msg'] = $this->language->get('text_success');
                $json['code'] = 200;
            }else{
                $json['error']['warning'] = $this->language->get('text_fail');
                $json['code'] = 400;
            }

        }

        if (isset($this->request->server['HTTP_ORIGIN'])) {
            $this->response->addHeader('Access-Control-Allow-Origin: ' . $this->request->server['HTTP_ORIGIN']);
            $this->response->addHeader('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS');
            $this->response->addHeader('Access-Control-Max-Age: 1000');
            $this->response->addHeader('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With');
        }

        $this->response->addHeader('Content-Type: application/json');
        $this->response->setOutput(json_encode($json));
    }

    private function storeFilters($filter,$product_id=null,$category_id=null){
        if(empty($filter) || !is_array($filter)){return;}
        $this->load->model('catalog/filter');
        $this->model_catalog_filter->addFilter($filter,$product_id,$category_id);
    }

    private function getProductId($product){
        if(!empty($product['product_id'])){
            return $product['product_id'];
        }
        $names = isset($product['names'])?$product['names']:'';
        $title = '';
        foreach ($names as $k=>$v){
            $title = $names[$k];
            break;
        }
        $sql ="select * from ".DB_PREFIX."product_description where `name`='{$title}'";
        $query = $this->db->query();
        if($query->row){
            return $query->row['product_id'];
        }else{
            $sql ="select max(product_id) as product_id from ".DB_PREFIX."product";
            $query = $this->db->query($sql);
            if($query->row){
                return intval($query->row['product_id']) + 1;
            }
        }
        return false;
    }
    protected function storeProductIntoDatabase( &$product, &$languages, &$product_fields, $exist_table_product_tag, $exist_meta_title, &$available_store_ids, &$manufacturers, &$weight_class_ids, &$length_class_ids, &$url_alias_ids) {
        // extract the product details
        $product_id = $this->getProductId($product);
        if(!$product_id){return false;}
        $names = isset($product['names'])?$product['names']:'';
        $sku = isset($product['sku'])?$product['sku']:'';
        $quantity = isset($product['quantity'])?$product['quantity']:0;
        $image = !empty($product['image']) && is_array($product['image'])?json_encode($product['image']):'catalog/product/700x700.png';//高清大图
        $upc = isset($product['upc'])?$product['upc']:'';
        $model = isset($product['model'])?$product['model']:'';
        $model = $this->db->escape($model);
        //$image = $this->db->escape($image);
        $shipping = isset($product['shipping'])?$product['shipping']:'Y';
        $shipping = ((strtoupper($shipping)=="YES") || (strtoupper($shipping)=="Y") || (strtoupper($shipping)=="TRUE")) ? 1 : 0;
        $price = isset($product['price'])?$product['price']:0;
        $price = trim($price);
        $points = isset($product['points'])?$product['points']:0;
        $date_added = date('Y-m-d H:i:s');
        $date_modified = date('Y-m-d H:i:s');
        $date_available = date('Y-m-d H:i:s');
        $weight = (!isset($product['weight'])||$product['weight']=="") ? 0 : $product['weight'];
        $default_weight_unit = $this->getDefaultWeightUnit();
        $weight_unit = isset($product['weight_unit'])?$product['weight_unit']:$default_weight_unit;
        $weight_class_id = (isset($weight_class_ids[$weight_unit])) ? $weight_class_ids[$weight_unit] : 0;
        $status = (!isset($product['status'])) ? 'TRUE' : trim($product['status']);
        $status = ((strtoupper($status)=="TRUE") || (strtoupper($status)=="YES") || (strtoupper($status)=="ENABLED") || ($status==1)) ? 1 : 0;
        $tax_class_id = (isset($product['tax_class_id'])) ? $product['tax_class_id'] : 0;
        $viewed = isset($product['viewed'])?$product['viewed']:0;
        $descriptions = isset($product['descriptions'])?$product['descriptions']:'';
        $length = isset($product['length'])?$product['length']:0;
        $width = isset($product['width'])?$product['width']:0;
        $height = isset($product['height'])?$product['height']:0;
        $origin_price = $product['origin_price']??0;
        $meta_descriptions = isset($product['meta_descriptions'])?$product['meta_descriptions']:'';
        if ($exist_meta_title) {
            $meta_titles = isset($product['meta_titles'])?$product['meta_titles']:'';
        }
        $query = $this->db->query("SELECT `stock_status_id`,`name` FROM " . DB_PREFIX . "stock_status WHERE language_id = '" . (int)$this->config->get('config_language_id') . "' ORDER BY `name`");
        $stock_status_id = isset($stock_status_id)?$stock_status_id:$query->rows[0]['stock_status_id'];
        if (!$this->use_table_seo_url) {
            $seo_keyword = isset($product['seo_keyword'])?$product['seo_keyword']:$product_id;
            $keyword = $this->db->escape($seo_keyword);
        }
        $default_measurement_unit = $this->getDefaultMeasurementUnit();
        $length_unit = isset($product['measurement_unit'])?$product['measurement_unit']:$default_measurement_unit;
        $length_class_id = (isset($length_class_ids[$length_unit])) ? $length_class_ids[$length_unit] : 0;
        $sku = $this->db->escape($sku);
        $upc = $this->db->escape($upc);
        if (in_array('ean',$product_fields)) {
            $ean = isset($product['ean'])?$product['ean']:'';
            $ean = $this->db->escape($ean);
        }
        if (in_array('jan',$product_fields)) {
            $jan = isset($product['jan'])?$product['jan']:'';
            $jan = $this->db->escape($jan);
        }
        if (in_array('isbn',$product_fields)) {
            $isbn = isset($product['isbn'])?$product['isbn']:'';
            $isbn = $this->db->escape($isbn);
        }
        if (in_array('mpn',$product_fields)) {
            $mpn = isset($product['mpn'])?$product['mpn']:'';
            $mpn = $this->db->escape($mpn);
        }
        $location = $this->db->escape(isset($product['location'])?$product['location']:'');
        $store_ids = isset($product['store_ids'])?json_decode($product['store_ids'],true):[0];//关联商店
        $related_ids = isset($product['related_ids'])?json_decode($product['related_ids'],true):[];//关联产品id
        $subtract = isset($product['subtract'])?$product['subtract']:'TRUE';
        $subtract = ((strtoupper($subtract)=="TRUE") || (strtoupper($subtract)=="YES") || (strtoupper($subtract)=="ENABLED")) ? 1 : 0;
        $minimum = isset($product['minimum'])?$product['minimum']:1;
        $meta_keywords = isset($product['meta_keywords'])?$product['meta_keywords']:'';
        $tags = isset($product['tags'])?$product['tags']:'';
        $sort_order = isset($product['sort_order'])?$product['sort_order']:0;
        $sold_out = isset($product['sold_out'])?$product['sold_out']:0;
        $proportion = isset($product['proportion'])?$product['proportion']:0;
        $manufacturer_name = isset($product['manufacturer_name'])?$product['manufacturer_name']:'';
        if ($manufacturer_name) {
            $this->storeManufacturerIntoDatabase( $manufacturers, $manufacturer_name, $store_ids, $available_store_ids );
            $manufacturer_id = $manufacturers[$manufacturer_name]['manufacturer_id'];
        } else {
            $manufacturer_id = 0;
        }

        // generate and execute SQL for inserting the product
        $sql  = "REPLACE INTO `".DB_PREFIX."product` (`product_id`,`quantity`,`sku`,`upc`,";
        $sql .= in_array('ean',$product_fields) ? "`ean`," : "";
        $sql .= in_array('jan',$product_fields) ? "`jan`," : "";
        $sql .= in_array('isbn',$product_fields) ? "`isbn`," : "";
        $sql .= in_array('mpn',$product_fields) ? "`mpn`," : "";
        $sql .= "`location`,`stock_status_id`,`model`,`manufacturer_id`,`image`,`shipping`,`price`,`points`,`date_added`,`date_modified`,`date_available`,`weight`,`weight_class_id`,`status`,";
        $sql .= "`tax_class_id`,`viewed`,`length`,`width`,`height`,`length_class_id`,`sort_order`,`subtract`,`minimum`,`proportion`,`sold_out`,`origin_price`) VALUES ";
        $sql .= "($product_id,$quantity,'$sku','$upc',";
        $sql .= in_array('ean',$product_fields) ? "'$ean'," : "";
        $sql .= in_array('jan',$product_fields) ? "'$jan'," : "";
        $sql .= in_array('isbn',$product_fields) ? "'$isbn'," : "";
        $sql .= in_array('mpn',$product_fields) ? "'$mpn'," : "";
        $sql .= "'$location',$stock_status_id,'$model',$manufacturer_id,'$image',$shipping,$price,$points,";
        $sql .= ($date_added=='NOW()') ? "$date_added," : "'$date_added',";
        $sql .= ($date_modified=='NOW()') ? "$date_modified," : "'$date_modified',";
        $sql .= ($date_available=='NOW()') ? "$date_available," : "'$date_available',";
        $sql .= "$weight,$weight_class_id,$status,";
        $sql .= "$tax_class_id,$viewed,$length,$width,$height,'$length_class_id','$sort_order','$subtract','$minimum','$proportion','$sold_out',$origin_price);";
        $this->db->query($sql);
        foreach ($languages as $language) {
            $language_code = $language['code'];
            $language_id = $language['language_id'];
            $name = isset($names[$language_code]) ? $this->db->escape($names[$language_code]) :'';
            $description = isset($descriptions[$language_code]) ? $this->db->escape($descriptions[$language_code]) : '';
            if ($exist_meta_title) {
                $meta_title = isset($meta_titles[$language_code]) ? $this->db->escape($meta_titles[$language_code]) : '';
            }
            $meta_description = isset($meta_descriptions[$language_code]) ? $this->db->escape($meta_descriptions[$language_code]) : '';
            $meta_keyword = isset($meta_keywords[$language_code]) ? $this->db->escape($meta_keywords[$language_code]) : '';
            $tag = isset($tags[$language_code]) ? $this->db->escape($tags[$language_code]) : '';
            if ($exist_table_product_tag) {
                if ($exist_meta_title) {
                    $sql  = "REPLACE INTO `".DB_PREFIX."product_description` (`product_id`, `language_id`, `name`, `description`, `meta_title`, `meta_description`, `meta_keyword`) VALUES ";
                    $sql .= "( $product_id, $language_id, '".$name."', '$description', '$meta_title', '$meta_description', '$meta_keyword' );";
                } else {
                    $sql  = "INSERT INTO `".DB_PREFIX."product_description` (`product_id`, `language_id`, `name`, `description`, `meta_description`, `meta_keyword`) VALUES ";
                    $sql .= "( $product_id, $language_id, '$name', '$description', '$meta_description', '$meta_keyword' );";
                }
                $this->db->query( $sql );
                $sql  = "INSERT INTO `".DB_PREFIX."product_tag` (`product_id`,`language_id`,`tag`) VALUES ";
                $sql .= "($product_id, $language_id, '$tag')";
                $this->db->query($sql);
            } else {
                if ($exist_meta_title) {
                    $sql  = "REPLACE INTO `".DB_PREFIX."product_description` (`product_id`, `language_id`, `name`, `description`, `meta_title`, `meta_description`, `meta_keyword`, `tag`) VALUES ";
                    $sql .= "( $product_id, $language_id, '$name', '$description', '$meta_title', '$meta_description', '$meta_keyword', '$tag' );";
                } else {
                    $sql  = "INSERT INTO `".DB_PREFIX."product_description` (`product_id`, `language_id`, `name`, `description`, `meta_description`, `meta_keyword`, `tag`) VALUES ";
                    $sql .= "( $product_id, $language_id, '$name', '$description', '$meta_description', '$meta_keyword', '$tag' );";
                }
                $this->db->query( $sql );
            }
        }
        //清空该产品的属性
        $sql = "DELETE FROM `".DB_PREFIX."product_attribute` WHERE product_id='".(int)$product_id."'";
        $this->db->query( $sql );
        //产品默认属性处理
        $attrs = !empty($product['attrs'])?$product['attrs']:[];

        foreach($attrs as $attr){
            $this->updateProductAttribute($product_id,$attr,$languages);
        }
        //系统属性处理
        $system['service'] = isset($product['service'])?$product['service']:'';

        $this->updateProductSystemAttribute($product_id,$system,$languages);

        //产品图片处理
        // check for the existence of product_image.sort_order field
        $sql = "SHOW COLUMNS FROM `".DB_PREFIX."product_image` LIKE 'sort_order'";
        $query = $this->db->query( $sql );
        $exist_sort_order = ($query->num_rows > 0) ? true : false;
        $images = !empty($product['images'])?$product['images']:[];
        $old_product_image_ids = $this->deleteAdditionalImage( $product_id );
        $this->storeAdditionalImageIntoDatabase($product_id, $images, $old_product_image_ids, $exist_sort_order,$languages );
        //产品规格处理
        $product_options = !empty($product['sizes']) && is_array($product['sizes'])?$product['sizes']:[];
        $quantity = $this->storeProductOptionIntoDatabase( $product_id,$product_options ,$languages);
        if($quantity>0){
            //更新总库存
            $this->db->query("UPDATE `" . DB_PREFIX . "product` SET `quantity` = '" . $quantity . "' WHERE `product_id` = '" . (int)$product_id . "'");
        }
        //seo设计处理
        if (!$this->use_table_seo_url) {
            if ($keyword) {
                if (isset($url_alias_ids[$product_id])) {
                    $url_alias_id = $url_alias_ids[$product_id];
                    $sql = "REPLACE INTO `".DB_PREFIX."seo_url` (`seo_url_id`,`query`,`keyword`) VALUES ($url_alias_id,'product_id=$product_id','$keyword');";
                    unset($url_alias_ids[$product_id]);
                } else {
                    $sql = "REPLACE INTO `".DB_PREFIX."seo_url` (`query`,`keyword`) VALUES ('product_id=$product_id','$keyword');";
                }
                $this->db->query($sql);
            }
        }
        //产品分类关联
        $categories = isset($product['product_category'])?json_decode($product['product_category'],true):[];
        if(is_array($categories) && count($categories) > 0){
            $sql = "REPLACE INTO `".DB_PREFIX."product_to_category` (`product_id`,`category_id`) VALUES ";
            $first = true;
            foreach ($categories as $category_id) {
                $sql .= ($first) ? "\n" : ",\n";
                $first = false;
                $sql .= "($product_id,$category_id)";
            }
            $sql .= ";";
            $this->db->query($sql);
        }
        //产品filter处理
        $filters = !empty($product['filter']) && is_array($product['filter']) ?$product['filter']:null;
        $this->storeFilters($filters,$product_id,$categories);
        //关联产品到对应店铺
        if(is_array($store_ids) && count($store_ids) > 0){
            foreach ($store_ids as $store_id) {
                if (in_array((int)$store_id,$available_store_ids)) {
                    $sql = "REPLACE INTO `".DB_PREFIX."product_to_store` (`product_id`,`store_id`) VALUES ($product_id,$store_id);";
                    $this->db->query($sql);
                }
            }
        }
        //产品关联
        if(is_array($related_ids) && count($related_ids) > 0){
            $sql = "REPLACE INTO `".DB_PREFIX."product_related` (`product_id`,`related_id`) VALUES ";
            $first = true;
            foreach ($related_ids as $related_id) {
                $sql .= ($first) ? "\n" : ",\n";
                $first = false;
                $sql .= "($product_id,$related_id)";
            }
            $sql .= ";";
            $this->db->query($sql);
        }
        return $product_id;
    }

    protected function storeProductOptionIntoDatabase($product_id ,&$product_options, &$languages) {
        //删除产品规格
        $old_product_option_ids = $this->deleteProductOption( $product_id );
        $old_product_option_value_ids = $this->deleteProductOptionValue( $product_id );
        // Opencart versions from 2.0 onwards use product_option.value instead of the older product_option.option_value


        $quantity = 0;
        foreach ($product_options as $product_option){
            //自动添加option
            if($product_option){
                $option_name = $product_option['name']??'';
                $option_id = 0;
                $option_value_id = 0;
                foreach ($languages as $language) {
                    $language_id = $language['language_id'];
                    $option_name = $product_option['name'][$language['code']]?? $option_name;
                    //查询
                    $sql = "SELECT option_id FROM `".DB_PREFIX."option_description` WHERE `name`='SIZES' AND language_id=".$language_id;
                    $query = $this->db->query( $sql );
                    if($query->num_rows <= 0){
                        if($option_id == 0){
                            $sql = "INSERT INTO `".DB_PREFIX."option` SET `type`='select'";
                            $this->db->query( $sql );
                            $option_id = $this->db->getLastId();
                        }

                        $sql = "INSERT INTO `".DB_PREFIX."option_description` (`name`,`option_id`,`language_id`) VALUES ('SIZES','$option_id','$language_id');";
                        $this->db->query($sql);
                    }else{
                        $option_id =  $query->row['option_id'];
                    }

                    $sql = "SELECT option_value_id FROM `".DB_PREFIX."option_value_description` WHERE `name`='".$option_name."' AND option_id=".$option_id." AND language_id=".$language_id;
                    $query = $this->db->query( $sql );
                    if ($query->num_rows <= 0) {
                        if($option_value_id == 0){
                            $sql = "INSERT INTO `".DB_PREFIX."option_value` SET `option_id`='".$option_id."'";
                            $this->db->query( $sql );
                            $option_value_id = $this->db->getLastId();
                        }

                        $sql = "REPLACE INTO `".DB_PREFIX."option_value_description` (`option_value_id`,`name`,`option_id`,`language_id`) VALUES ('$option_value_id','$option_name','$option_id','$language_id');";
                        $this->db->query($sql);
                    }else{
                        $option_value_id =  $query->row['option_value_id'];
                    }
                }


                // DB query for storing the product option
                $sql = "SHOW COLUMNS FROM `".DB_PREFIX."product_option` LIKE 'value'";
                $query = $this->db->query( $sql );
                $exist_po_value = ($query->num_rows > 0) ? true : false;
                $required = isset($product_option['required'])?$product_option['required']:'TRUE';
                $option_value = isset($product_option['option_value'])?$product_option['option_value']:'';
                $required = ((strtoupper($required)=="TRUE") || (strtoupper($required)=="YES") || (strtoupper($required)=="ENABLED")) ? 1 : 0;
                //查询
                $sql = "SELECT product_option_id FROM `".DB_PREFIX."product_option` WHERE `product_id`='$product_id' AND option_id=".$option_id;
                $query = $this->db->query( $sql );
                if ($query->num_rows <= 0) {
                    if ($exist_po_value) {
                        $sql  = "INSERT INTO `".DB_PREFIX."product_option` (`product_id`,`option_id`,`value`,`required` ) VALUES ";
                    } else {
                        $sql  = "INSERT INTO `".DB_PREFIX."product_option` (`product_id`,`option_id`,`option_value`,`required` ) VALUES ";
                    }
                    $sql .= "($product_id,$option_id,'".$this->db->escape($option_value)."',$required)";
                    $this->db->query($sql);
                    $product_option_id = $this->db->getLastId();
                }else{
                    $product_option_id =  $query->row['product_option_id'];
                }


                $product_option_value = array();
                $product_option_value['product_id'] = $product_id;
                $product_option_value['option_id'] = $option_id;
                $product_option_value['option_value_id'] = $option_value_id;
                $product_option_value['quantity'] = $product_option['inventory'];
                $product_option_value['subtract'] = 'TRUE';
                $product_option_value['price'] = $product_option['sale_price'];
                $product_option_value['origin_price'] = $product_option['origin_price'];
                $product_option_value['option_skuid'] = $product_option['skuid'];
                $product_option_value['icon'] = is_array($product_option['thumb']) && $product_option['thumb']?json_encode($product_option['thumb']):'';
                $product_option_value['images'] = $product_option['images']??'';
                $product_option_value['price_prefix'] = '+';
                $product_option_value['points'] = 0;
                $product_option_value['points_prefix'] = '+';
                $product_option_value['weight'] = 0;
                $product_option_value['weight_prefix'] = '+';
                $product_option_value['product_option_id'] = $product_option_id;
                $product_option_value['min_sale_num'] = $product_option['min_sale_number']??1;
                $product_option_value['status'] = $product_option['status'];
                //组合options
                if($product_option['on_sku']){
                    $product_option_value['is_compose'] = 1;
                    $product_option_value['skus'] = $product_option['on_sku'];
                }
                $this->storeProductOptionValueIntoDatabase( $product_option_value, $old_product_option_value_ids );
                $quantity += intval($product_option['inventory']);
            }
        }
        return $quantity;
    }

    protected function storeProductOptionValueIntoDatabase( &$product_option_value, &$old_product_option_value_ids ) {
        $product_id = $product_option_value['product_id'];
        $option_id = $product_option_value['option_id'];
        $option_value_id = $product_option_value['option_value_id'];
        $quantity = $product_option_value['quantity'];
        $subtract = $product_option_value['subtract'];
        $subtract = ((strtoupper($subtract)=="TRUE") || (strtoupper($subtract)=="YES") || (strtoupper($subtract)=="ENABLED")) ? 1 : 0;
        $price = $product_option_value['price'];
        $price_prefix = $product_option_value['price_prefix'];
        $points = $product_option_value['points'];
        $points_prefix = $product_option_value['points_prefix'];
        $weight = $product_option_value['weight'];
        $weight_prefix = $product_option_value['weight_prefix'];
        $product_option_id = $product_option_value['product_option_id'];
        $option_skuid = $product_option_value['option_skuid'];
        $origin_price = $product_option_value['origin_price'];
        $option_icon = $product_option_value['icon'];

        $option_images = $product_option_value['images']??'';
        $option_min_sale_number = !empty($product_option_value['min_sale_num'])?intval($product_option_value['min_sale_num']):1;
        $option_compose = $product_option_value['is_compose']??0;
        $option_status = $product_option_value['status'];
        $option_skus = !empty($product_option_value['skus']) && is_array($product_option_value['skus'])?"'".$this->db->escape(json_encode($product_option_value['skus']))."'":'null';

        if (isset($old_product_option_value_ids[$product_id][$option_id][$option_value_id])) {
            $product_option_value_id = $old_product_option_value_ids[$product_id][$option_id][$option_value_id];
            $sql  = "INSERT INTO `".DB_PREFIX."product_option_value` ";
            $sql .= "(`product_option_value_id`,`product_option_id`,`product_id`,`option_id`,`option_value_id`,`quantity`,`subtract`,`price`,`price_prefix`,`points`,`points_prefix`,`weight`,`weight_prefix`,`option_skuid`,`origin_price`,`icon`,`images`,`is_compose`,`skus`,`min_sale_num`,`status`) VALUES ";
            $sql .= "($product_option_value_id,$product_option_id,$product_id,$option_id,$option_value_id,$quantity,$subtract,$price,'$price_prefix',$points,'$points_prefix',$weight,'$weight_prefix','$option_skuid','$origin_price','$option_icon','$option_images',$option_compose,$option_skus,$option_min_sale_number,$option_status)";
            $this->db->query($sql);
            unset($old_product_option_value_ids[$product_id][$option_id][$option_value_id]);
        } else {
            $sql  = "INSERT INTO `".DB_PREFIX."product_option_value` ";
            $sql .= "(`product_option_id`,`product_id`,`option_id`,`option_value_id`,`quantity`,`subtract`,`price`,`price_prefix`,`points`,`points_prefix`,`weight`,`weight_prefix`,`option_skuid`,`origin_price`,`icon`,`images`,`is_compose`,`skus`,`min_sale_num`,`status`) VALUES ";
            $sql .= "($product_option_id,$product_id,$option_id,$option_value_id,$quantity,$subtract,$price,'$price_prefix',$points,'$points_prefix',$weight,'$weight_prefix','$option_skuid','$origin_price','$option_icon','$option_images',$option_compose,$option_skus,$option_min_sale_number,$option_status)";
            $this->db->query($sql);
        }
    }

    protected function updateProductSystemAttribute( $product_id, $system, $languages) {
        $attrs = $system;
        if($attrs){
            foreach ($attrs as $key => $attr){
                $attribute_id = 0;
                $data_attribute_group = [];
                $name = $key;
                if($attr){
                    //检查是否有对应分组,并返回分组id
                    $sql = "SELECT attribute_group_id FROM `".DB_PREFIX."attribute_group_description` WHERE `name`='System'";
                    $query = $this->db->query( $sql );
                    if($query->num_rows <= 0){
                        foreach ($languages as $language){
                            $language_id = $language['language_id'];
                            $data_attribute_group['attribute_group_description'][$language_id]['name'] = 'System';
                        }
                        $data_attribute_group['sort_order'] = 0;
                        $attribute_group_id = $this->addAttributeGroup($data_attribute_group);
                    }else{
                        $attribute_group_id =  $query->row['attribute_group_id'];
                    }


                    foreach ($languages as $language){
                        $data = [];
                        $language_id = $language['language_id'];
                        //检查是否有对应属性，并返回属性id
                        $sql = "SELECT attribute_id FROM `".DB_PREFIX."attribute_description` WHERE `name`='".$name."' AND language_id='".$language_id."'";
                        $query = $this->db->query( $sql );
                        $data['attribute_description'][$language_id]['name'] = $name;
                        $data['attribute_group_id'] = $attribute_group_id;
                        $data['sort_order'] = 0;
                        if($query->num_rows <= 0){
                            $attribute_id = $this->addAttribute($data,$attribute_id);
                        }else{
                            $attribute_id =  $query->row['attribute_id'];
                            $attribute_id = $this->addAttribute($data,$attribute_id);
                        }
                        try {
                            $value = json_encode(array_column($attr,$language['code']));
                            if($value){
                                //属性值写入
                                $sql = "SELECT attribute_id FROM `".DB_PREFIX."product_attribute` WHERE product_id='".$product_id."' AND attribute_id='".$attribute_id."' AND language_id=".$language_id." AND text='".$value."'";
                                $query = $this->db->query( $sql );
                                if($query->num_rows <= 0){
                                    $sql  = "INSERT INTO `".DB_PREFIX."product_attribute` (`product_id`,`attribute_id`, `language_id` ,`text`,`sort_order`) VALUES ";
                                    $sql .= "($product_id, $attribute_id, $language_id, '$value','9999');";
                                    $this->db->query( $sql );
                                }
                            }
                        }catch (\Exception $exception){

                        }
                    }
                }
            }
        }
    }

    protected function updateProductAttribute( $product_id, $attrs, $languages) {
        if($attrs){
            $attribute_id = 0;
            $data_attribute_group = [];
            foreach ($languages as $language){
                $data = [];
                $language_id = $language['language_id'];
                //检查是否有对应分组,并返回分组id
                $sql = "SELECT attribute_group_id FROM `".DB_PREFIX."attribute_group_description` WHERE `name`='Default'";
                $query = $this->db->query( $sql );
                if($query->num_rows <= 0){
                    $data_attribute_group['attribute_group_description'][$language_id]['name'] = 'Default';
                    $data_attribute_group['sort_order'] = 0;
                    $attribute_group_id = $this->addAttributeGroup($data_attribute_group);
                }else{
                    $attribute_group_id =  $query->row['attribute_group_id'];
                }

                //检查是否有对应属性，并返回属性id
                $name = $attrs['name'][$language['code']]??'';
                $sort = $attrs['sort'][$language['code']]??9999;
                //属性值写入
                $value = $attrs['value'][$language['code']]??'';
                if($name && $value){
                    $sql = "SELECT attribute_id FROM `".DB_PREFIX."attribute_description` WHERE `name`='".$name."' AND language_id='".$language_id."'";
                    $query = $this->db->query( $sql );
                    $data['attribute_description'][$language_id]['name'] = $name;
                    $data['attribute_group_id'] = $attribute_group_id;
                    $data['sort_order'] = $sort;

                    if($query->num_rows <= 0){
                        $attribute_id = $this->addAttribute($data,$attribute_id);
                    }else{
                        $attribute_id =  $query->row['attribute_id'];
                        $attribute_id = $this->addAttribute($data,$attribute_id);
                    }
                try {
                        $sql = "SELECT attribute_id FROM `" . DB_PREFIX . "product_attribute` WHERE product_id='" . $product_id . "' AND attribute_id='" . $attribute_id . "' AND language_id=" . $language_id . " AND text='" . $value . "'";
                        $query = $this->db->query($sql);
                        if ($query->num_rows <= 0) {
                            $sql = "INSERT INTO `" . DB_PREFIX . "product_attribute` (`product_id`,`attribute_id`, `language_id` ,`text`,`sort_order`) VALUES ";
                            $sql .= "($product_id, $attribute_id, $language_id, '$value'," . $sort . ");";
                            $this->db->query($sql);
                        }else{
                            $sql = "UPDATE `" . DB_PREFIX . "product_attribute` set `sort_order`=$sort,`text` = '$value' where  product_id='" . $product_id . "' AND attribute_id='" . $attribute_id . "' AND language_id=" . $language_id ;
                            $this->db->query($sql);
                        }
                }catch (\Exception $exception){

                }
                }
            }
        }
    }

    public function addAttributeGroup($data) {
        $this->db->query("INSERT INTO " . DB_PREFIX . "attribute_group SET sort_order = '" . (int)$data['sort_order'] . "'");
        $attribute_group_id = $this->db->getLastId();
        foreach ($data['attribute_group_description'] as $language_id => $value) {
            $this->db->query("INSERT INTO " . DB_PREFIX . "attribute_group_description SET attribute_group_id = '" . (int)$attribute_group_id . "', language_id = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'");
        }
        return $attribute_group_id;
    }

    public function addAttribute($data,$attribute_id) {
        if($attribute_id==0){
            $this->db->query("INSERT INTO " . DB_PREFIX . "attribute SET attribute_group_id = '" . (int)$data['attribute_group_id'] . "', sort_order = '" . (int)$data['sort_order'] . "'");
            $attribute_id = $this->db->getLastId();
        }
        foreach ($data['attribute_description'] as $language_id => $value) {
            $sql = "SELECT attribute_id FROM `".DB_PREFIX."attribute_description` WHERE attribute_id = '" . (int)$attribute_id . "' AND `name`='".$value['name']."' AND language_id='".$language_id."'";
            $query = $this->db->query( $sql );
            if($query->num_rows <= 0){
                $sql = "REPLACE INTO " . DB_PREFIX . "attribute_description SET attribute_id = '" . (int)$attribute_id . "', language_id = '" . (int)$language_id . "', `name` = '" . $this->db->escape($value['name']) . "'";
                try{
                    $this->db->query($sql);
                }catch (Exception $e){
                    echo $sql;
                }
            }
        }
        return $attribute_id;
    }

    protected function getProductOptionIds( $product_id ) {
        $sql  = "SELECT product_option_id, option_id FROM `".DB_PREFIX."product_option` ";
        $sql .= "WHERE product_id='".(int)$product_id."'";
        $query = $this->db->query( $sql );
        $product_option_ids = array();
        foreach ($query->rows as $row) {
            $product_option_id = $row['product_option_id'];
            $option_id = $row['option_id'];
            $product_option_ids[$option_id] = $product_option_id;
        }
        return $product_option_ids;
    }

    protected function deleteProductOption( $product_id ) {
        $sql = "SELECT product_option_id, product_id, option_id FROM `".DB_PREFIX."product_option` WHERE product_id='".(int)$product_id."'";
        $query = $this->db->query( $sql );
        $old_product_option_ids = array();
        foreach ($query->rows as $row) {
            $product_option_id = $row['product_option_id'];
            $product_id = $row['product_id'];
            $option_id = $row['option_id'];
            $old_product_option_ids[$product_id][$option_id] = $product_option_id;
        }
        if ($old_product_option_ids) {
            $sql = "DELETE FROM `".DB_PREFIX."product_option` WHERE product_id='".(int)$product_id."'";
            $this->db->query( $sql );
        }
        return $old_product_option_ids;
    }

    protected function deleteProductOptionValue( $product_id ) {
        $sql = "SELECT product_option_value_id, product_id, option_id, option_value_id FROM `".DB_PREFIX."product_option_value` WHERE product_id='".(int)$product_id."'";
        $query = $this->db->query( $sql );
        $old_product_option_value_ids = array();
        foreach ($query->rows as $row) {
            $product_option_value_id = $row['product_option_value_id'];
            $product_id = $row['product_id'];
            $option_id = $row['option_id'];
            $option_value_id = $row['option_value_id'];
            $old_product_option_value_ids[$product_id][$option_id][$option_value_id] = $product_option_value_id;
        }
        if ($old_product_option_value_ids) {
            $sql = "DELETE FROM `".DB_PREFIX."product_option_value` WHERE product_id='".(int)$product_id."'";
            $this->db->query( $sql );
        }
        return $old_product_option_value_ids;
    }

    protected function getProductFields(){
        $query = $this->db->query( "DESCRIBE `".DB_PREFIX."product`" );
        $product_fields = array();
        foreach ($query->rows as $row) {
            $product_fields[] = $row['Field'];
        }
        return $product_fields;
    }

    protected function storeManufacturerIntoDatabase( &$manufacturers, $name, &$store_ids, &$available_store_ids ) {
        foreach ($store_ids as $store_id) {
            if (!in_array( $store_id, $available_store_ids )) {
                continue;
            }
            if (!isset($manufacturers[$name]['manufacturer_id'])) {
                $this->db->query("INSERT INTO ".DB_PREFIX."manufacturer SET name = '".$this->db->escape($name)."', image='', sort_order = '0'");
                $manufacturer_id = $this->db->getLastId();
                if (!isset($manufacturers[$name])) {
                    $manufacturers[$name] = array();
                }
                $manufacturers[$name]['manufacturer_id'] = $manufacturer_id;
            }
            if (!isset($manufacturers[$name]['store_ids'])) {
                $manufacturers[$name]['store_ids'] = array();
            }
            if (!in_array($store_id,$manufacturers[$name]['store_ids'])) {
                $manufacturer_id = $manufacturers[$name]['manufacturer_id'];
                $sql = "INSERT INTO `".DB_PREFIX."manufacturer_to_store` SET manufacturer_id='".(int)$manufacturer_id."', store_id='".(int)$store_id."'";
                $this->db->query( $sql );
                $manufacturers[$name]['store_ids'][] = $store_id;
            }
        }
    }

    protected function getProductUrlAliasIds() {
        $sql  = "SELECT seo_url_id, SUBSTRING( query, CHAR_LENGTH('product_id=')+1 ) AS product_id ";
        $sql .= "FROM `".DB_PREFIX."seo_url` ";
        $sql .= "WHERE query LIKE 'product_id=%'";
        $query = $this->db->query( $sql );
        $url_alias_ids = array();
        foreach ($query->rows as $row) {
            $url_alias_id = $row['seo_url_id'];
            $product_id = $row['product_id'];
            $url_alias_ids[$product_id] = $url_alias_id;
        }
        return $url_alias_ids;
    }

    protected function deleteProducts( $exist_table_product_tag, &$url_alias_ids ) {
        $sql  = "TRUNCATE TABLE `".DB_PREFIX."product`;\n";
        $sql .= "TRUNCATE TABLE `".DB_PREFIX."product_description`;\n";
        $sql .= "TRUNCATE TABLE `".DB_PREFIX."product_to_category`;\n";
        $sql .= "TRUNCATE TABLE `".DB_PREFIX."product_to_store`;\n";
        if (!$this->use_table_seo_url) {
            $sql .= "DELETE FROM `".DB_PREFIX."seo_url` WHERE `query` LIKE 'product_id=%';\n";
        }
        $sql .= "TRUNCATE TABLE `".DB_PREFIX."product_related`;\n";
        $sql .= "TRUNCATE TABLE `".DB_PREFIX."product_to_layout`;\n";
        if ($exist_table_product_tag) {
            $sql .= "TRUNCATE TABLE `".DB_PREFIX."product_tag`;\n";
        }
        $this->multiquery( $sql );
        if (!$this->use_table_seo_url) {
            $sql = "SELECT (MAX(seo_url_id)+1) AS next_seo_url_id FROM `".DB_PREFIX."seo_url` LIMIT 1";
            $query = $this->db->query( $sql );
            $next_seo_url_id = $query->row['next_seo_url_id'];
            $sql = "ALTER TABLE `".DB_PREFIX."seo_url` AUTO_INCREMENT = $next_seo_url_id";
            $this->db->query( $sql );
            $remove = array();
            foreach ($url_alias_ids as $product_id=>$url_alias_id) {
                if ($url_alias_id >= $next_seo_url_id) {
                    $remove[$product_id] = $url_alias_id;
                }
            }
            foreach ($remove as $product_id=>$url_alias_id) {
                unset($url_alias_ids[$product_id]);
            }
        }
    }

    protected function multiquery( $sql ) {
        foreach (explode(";\n", $sql) as $sql) {
            $sql = trim($sql);
            if ($sql) {
                $this->db->query($sql);
            }
        }
    }

    protected function getLayoutIds() {
        $result = $this->db->query( "SELECT * FROM `".DB_PREFIX."layout`" );
        $layout_ids = array();
        foreach ($result->rows as $row) {
            $layout_ids[$row['name']] = $row['layout_id'];
        }
        return $layout_ids;
    }

    protected function getAvailableStoreIds() {
        $sql = "SELECT store_id FROM `".DB_PREFIX."store`;";
        $result = $this->db->query( $sql );
        $store_ids = array(0);
        foreach ($result->rows as $row) {
            if (!in_array((int)$row['store_id'],$store_ids)) {
                $store_ids[] = (int)$row['store_id'];
            }
        }
        return $store_ids;
    }

    protected function getLanguages() {
        $query = $this->db->query( "SELECT * FROM `".DB_PREFIX."language` WHERE `status`=1 ORDER BY `code`" );
        return $query->rows;
    }

    protected function getDefaultWeightUnit() {
        $weight_class_id = $this->config->get( 'config_weight_class_id' );
        $language_id = $this->getDefaultLanguageId();
        $sql = "SELECT unit FROM `".DB_PREFIX."weight_class_description` WHERE language_id='".(int)$language_id."'";
        $query = $this->db->query( $sql );
        if ($query->num_rows > 0) {
            return $query->row['unit'];
        }
        $sql = "SELECT language_id FROM `".DB_PREFIX."language` WHERE code = 'en'";
        $query = $this->db->query( $sql );
        if ($query->num_rows > 0) {
            $language_id = $query->row['language_id'];
            $sql = "SELECT unit FROM `".DB_PREFIX."weight_class_description` WHERE language_id='".(int)$language_id."'";
            $query = $this->db->query( $sql );
            if ($query->num_rows > 0) {
                return $query->row['unit'];
            }
        }
        return 'kg';
    }

    protected function getDefaultLanguageId() {
        $code = $this->config->get('config_language');
        $sql = "SELECT language_id FROM `".DB_PREFIX."language` WHERE code = '$code'";
        $result = $this->db->query( $sql );
        $language_id = 1;
        if ($result->rows) {
            foreach ($result->rows as $row) {
                $language_id = $row['language_id'];
                break;
            }
        }
        return $language_id;
    }

    protected function getDefaultMeasurementUnit() {
        $length_class_id = $this->config->get( 'config_length_class_id' );
        $language_id = $this->getDefaultLanguageId();
        $sql = "SELECT unit FROM `".DB_PREFIX."length_class_description` WHERE language_id='".(int)$language_id."'";
        $query = $this->db->query( $sql );
        if ($query->num_rows > 0) {
            return $query->row['unit'];
        }
        $sql = "SELECT language_id FROM `".DB_PREFIX."language` WHERE code = 'en'";
        $query = $this->db->query( $sql );
        if ($query->num_rows > 0) {
            $language_id = $query->row['language_id'];
            $sql = "SELECT unit FROM `".DB_PREFIX."length_class_description` WHERE language_id='".(int)$language_id."'";
            $query = $this->db->query( $sql );
            if ($query->num_rows > 0) {
                return $query->row['unit'];
            }
        }
        return 'cm';
    }

    protected function getManufacturers() {
        // find all manufacturers already stored in the database
        $manufacturer_ids = array();
        $sql  = "SELECT ms.manufacturer_id, ms.store_id, m.`name` FROM `".DB_PREFIX."manufacturer_to_store` ms ";
        $sql .= "INNER JOIN `".DB_PREFIX."manufacturer` m ON m.manufacturer_id=ms.manufacturer_id";
        $result = $this->db->query( $sql );
        $manufacturers = array();
        foreach ($result->rows as $row) {
            $manufacturer_id = $row['manufacturer_id'];
            $store_id = $row['store_id'];
            $name = $row['name'];
            if (!isset($manufacturers[$name])) {
                $manufacturers[$name] = array();
            }
            if (!isset($manufacturers[$name]['manufacturer_id'])) {
                $manufacturers[$name]['manufacturer_id'] = $manufacturer_id;
            }
            if (!isset($manufacturers[$name]['store_ids'])) {
                $manufacturers[$name]['store_ids'] = array();
            }
            if (!in_array($store_id,$manufacturers[$name]['store_ids'])) {
                $manufacturers[$name]['store_ids'][] = $store_id;
            }
        }
        return $manufacturers;
    }

    protected function getWeightClassIds() {
        // find the default language id
        $language_id = $this->getDefaultLanguageId();

        // find all weight classes already stored in the database
        $weight_class_ids = array();
        $sql = "SELECT `weight_class_id`, `unit` FROM `".DB_PREFIX."weight_class_description` WHERE `language_id`=$language_id;";
        $result = $this->db->query( $sql );
        if ($result->rows) {
            foreach ($result->rows as $row) {
                $weight_class_id = $row['weight_class_id'];
                $unit = $row['unit'];
                if (!isset($weight_class_ids[$unit])) {
                    $weight_class_ids[$unit] = $weight_class_id;
                }
            }
        }

        return $weight_class_ids;
    }

    protected function getLengthClassIds() {
        // find the default language id
        $language_id = $this->getDefaultLanguageId();

        // find all length classes already stored in the database
        $length_class_ids = array();
        $sql = "SELECT `length_class_id`, `unit` FROM `".DB_PREFIX."length_class_description` WHERE `language_id`=$language_id;";
        $result = $this->db->query( $sql );
        if ($result->rows) {
            foreach ($result->rows as $row) {
                $length_class_id = $row['length_class_id'];
                $unit = $row['unit'];
                if (!isset($length_class_ids[$unit])) {
                    $length_class_ids[$unit] = $length_class_id;
                }
            }
        }
        return $length_class_ids;
    }

    protected function storeAdditionalImageIntoDatabase( $product_id, &$images, &$old_product_image_ids, $exist_sort_order=true,$languages ) {
        foreach ($images as $lan_code=>$items){
            $language_id = $this->getLanguageID($lan_code,$languages);
            foreach ($items as $k => $image){
                $image_name = $image;
                if ($exist_sort_order) {
                    $sort_order = $k;
                }
                if (isset($old_product_image_ids[$product_id][$image_name])) {
                    $product_image_id = $old_product_image_ids[$product_id][$image_name];
                    if ($exist_sort_order) {
                        $sql  = "INSERT INTO `".DB_PREFIX."product_image` (`product_image_id`,`product_id`,`image`,`sort_order`,`language_id` ) VALUES ";
                        $sql .= "($product_image_id,$product_id,'".$this->db->escape($image_name)."',$sort_order,$language_id)";
                    } else {
                        $sql  = "INSERT INTO `".DB_PREFIX."product_image` (`product_image_id`,`product_id`,`image`,`language_id`  ) VALUES ";
                        $sql .= "($product_image_id,$product_id,'".$this->db->escape($image_name)."',$language_id)";
                    }
                    $this->db->query($sql);
                    unset($old_product_image_ids[$product_id][$image_name]);
                } else {
                    if ($exist_sort_order) {
                        $sql  = "INSERT INTO `".DB_PREFIX."product_image` (`product_id`,`image`,`sort_order`,`language_id` ) VALUES ";
                        $sql .= "($product_id,'".$this->db->escape($image_name)."',$sort_order,$language_id)";
                    } else {
                        $sql  = "INSERT INTO `".DB_PREFIX."product_image` (`product_id`,`image`,`language_id` ) VALUES ";
                        $sql .= "($product_id,'".$this->db->escape($image_name)."',$language_id)";
                    }
                    $this->db->query($sql);
                }
            }
        }
    }

    private function getLanguageID($code,$languages){
        $language_id = 0;
        foreach ($languages as $k=>$v){
            if($v['code'] == $code){
                $language_id = $v['language_id'];
            }
        }
        return $language_id;
    }

    protected function deleteAdditionalImage( $product_id ) {
        $sql = "SELECT product_image_id, product_id, image FROM `".DB_PREFIX."product_image` WHERE product_id='".(int)$product_id."'";
        $query = $this->db->query( $sql );
        $old_product_image_ids = array();
        foreach ($query->rows as $row) {
            $product_image_id = $row['product_image_id'];
            $product_id = $row['product_id'];
            $image_name = $row['image'];
            $old_product_image_ids[$product_id][$image_name] = $product_image_id;
        }
        if ($old_product_image_ids) {
            $sql = "DELETE FROM `".DB_PREFIX."product_image` WHERE product_id='".(int)$product_id."'";
            $this->db->query( $sql );
        }
        return $old_product_image_ids;
    }
}