<?php

class Moysklad
{
    private $registry = NULL;
    private $msQueryCount = 0;
    private $ocVersion = NULL;
    const OC_VERSION_3_0 = 30;
    const OC_VERSION_2_3 = 23;
    const OC_VERSION_2_0 = 20;
    const MS_INTEGRATION_SETTING_MS_EXTERNAL_CODE = "externalCode";
    const MS_INTEGRATION_SETTING_MS_CODE = "code";
    const MS_INTEGRATION_SETTING_MS_SKU = "article";
    const MS_INTEGRATION_SETTING_OC_ID = "product_id";
    const MS_INTEGRATION_SETTING_OC_MODEL = "model";
    const MS_INTEGRATION_SETTING_OC_SKU = "sku";
    const MS_INTEGRATION_SETTING_AGENT_SEARCH_NAME = "fio";
    const MS_INTEGRATION_SETTING_AGENT_SEARCH_PHONE = "phone";
    const MS_INTEGRATION_SETTING_AGENT_SEARCH_EMAIL = "email";
    const MS_INTEGRATION_SETTING_CATEGORY_NAME = "name";
    const MS_INTEGRATION_SETTING_CATEGORY_CODE = "code";
    const MS_INTEGRATION_SETTING_CATEGORY_EXTERNAL_CODE = "externalCode";
    const MS_INTEGRATION_SETTING_ORDER_NAME = "name";
    const MS_INTEGRATION_SETTING_ORDER_EXTERNAL_CODE = "externalCode";
    const MODE_LINK_ONLY = 0;
    const MODE_LINK_CREATE = 1;
    const MODE_LINK_CREATE_UPDATE = 2;
    const MODE_UPDATE_ONLY = 3;
    const UPDATE_MODE_BY_TIME = 0;
    const UPDATE_MODE_ALL = 1;
    public function __construct($registry)
    {
        $this->registry = $registry;
        $verTemp = explode(".", VERSION);
        if ($verTemp[0] == "3") {
            $this->ocVersion = self::OC_VERSION_3_0;
        } else {
            if ($verTemp[0] == "2") {
                if ($verTemp[1] == "3") {
                    $this->ocVersion = self::OC_VERSION_2_3;
                } else {
                    $this->ocVersion = self::OC_VERSION_2_0;
                }
            }
        }
    }
    public function __get($key)
    {
        return $this->registry->get($key);
    }
    public function __set($key, $value)
    {
        $this->registry->set($key, $value);
    }
    public function categories($linkMode = self::MODE_LINK_ONLY)
    {
        if (!$this->config->get("ms_integration_categories")) {
            return NULL;
        }
        $this->load->language("extension/module/ms_integration");
        $this->load->model("setting/setting");
        $this->load->model("catalog/category");
        $this->db->query("SET NAMES 'utf8'");
        $catLink = $this->config->get("ms_integration_category_link");
        $create = $this->config->get("ms_integration_create_category");
        $lang = $this->config->get("ms_integration_language");
        $names = $this->config->get("ms_integration_category_name_update");
        $link = "https://online.moysklad.ru/api/remap/1.1/entity/productfolder?limit=100";
        $msCategoryRes = $this->msGet($link);
        $size = $msCategoryRes["meta"]["size"];
        $pages = ceil($size / 100);
        $msCategories = $msCategoryRes["rows"];
        for ($page = 0; $page < $pages; $page++) {
            if ($page != 0) {
                $msCategories = array_merge($msCategories, $this->msGet($link . "&offset=" . $page * 100)["rows"]);
            }
        }
        for ($categoryLevel = 0; !empty($msCategories); $categoryLevel++) {
            foreach ($msCategories as $ck => $msCategory) {
                if (!isset($msCategory["pathName"]) || $msCategory["pathName"] == "") {
                    $currentCategoryLevel = 0;
                } else {
                    $pathName = $msCategory["pathName"];
                    $categoryPath = explode("/", $pathName);
                    $currentCategoryLevel = count($categoryPath);
                }
                if ($categoryLevel != $currentCategoryLevel) {
                    continue;
                }
                $ocCategory = $this->db->query("SELECT * FROM " . DB_PREFIX . "ms_category WHERE ms_id='" . $msCategory["id"] . "'");
                if (0 < $ocCategory->num_rows) {
                    if ($names && self::MODE_LINK_CREATE_UPDATE <= $linkMode && $ocCategory->row["updated"] < $msCategory["updated"]) {
                        $this->db->query("UPDATE " . DB_PREFIX . "category_description SET name='" . $this->escape($msCategory["name"]) . "' WHERE category_id='" . $ocCategory->row["category_id"] . "' AND language_id='" . $lang . "'");
                        $this->db->query("UPDATE `" . DB_PREFIX . "ms_category` set updated='" . $msCategory["updated"] . "' WHERE category_id='" . $ocCategory->row["category_id"] . "'");
                    }
                    unset($msCategories[$ck]);
                    continue;
                }
                if ($linkMode == self::MODE_UPDATE_ONLY) {
                    unset($msCategories[$ck]);
                    continue;
                }
                if ($categoryLevel == 0) {
                    $ocParentCategoryId = 0;
                } else {
                    $tmpHref = $msCategory["productFolder"]["meta"]["href"];
                    $tmpx = explode("/", $tmpHref);
                    $msParentCatId = $tmpx[8];
                    $ocParentCategoryId = $this->db->query("SELECT * FROM " . DB_PREFIX . "ms_category WHERE ms_id='" . $msParentCatId . "'");
                    if ($ocParentCategoryId->num_rows == 0) {
                        unset($msCategories[$ck]);
                        continue;
                    }
                    $ocParentCategoryId = $ocParentCategoryId->row["category_id"];
                }
                if (!isset($msCategory[$catLink])) {
                    unset($msCategories[$ck]);
                    continue;
                }
                switch ($catLink) {
                    case self::MS_INTEGRATION_SETTING_CATEGORY_CODE:
                    case self::MS_INTEGRATION_SETTING_CATEGORY_EXTERNAL_CODE:
                        $ocCategory = $this->db->query("SELECT * FROM " . DB_PREFIX . "category as c JOIN " . DB_PREFIX . "category_description as cd ON c.category_id = cd.category_id WHERE cd.category_id='" . $msCategory[$catLink] . "' AND cd.language_id='" . $lang . "' AND c.parent_id='" . $ocParentCategoryId . "'");
                        break;
                    case self::MS_INTEGRATION_SETTING_CATEGORY_NAME:
                    default:
                        $ocCategory = $this->db->query("SELECT * FROM " . DB_PREFIX . "category as c JOIN " . DB_PREFIX . "category_description as cd ON c.category_id = cd.category_id WHERE cd.name='" . addslashes(mb_convert_encoding($msCategory["name"], "UTF-8")) . "' AND cd.language_id='" . $lang . "' AND c.parent_id='" . $ocParentCategoryId . "'");
                        break;
                }
                if (0 < $ocCategory->num_rows) {
                    $this->db->query("INSERT INTO " . DB_PREFIX . "ms_category SET category_id='" . $ocCategory->row["category_id"] . "', ms_id='" . $msCategory["id"] . "', updated='" . $msCategory["updated"] . "'");
                    if ($names) {
                        $this->db->query("UPDATE " . DB_PREFIX . "category_description SET name='" . $this->escape($msCategory["name"]) . "' WHERE category_id='" . $ocCategory->row["category_id"] . "' AND language_id='" . $lang . "'");
                    }
                } else {
                    if ($create && self::MODE_LINK_CREATE <= $linkMode) {
                        $data = array("parent_id" => $ocParentCategoryId, "column" => "1", "sort_order" => "1", "status" => "1", "category_description" => array($lang => array("name" => isset($msCategory["name"]) ? $this->escape($msCategory["name"]) : "", "description" => isset($msCategory["description"]) ? $this->escape($msCategory["description"]) : "", "meta_title" => isset($msCategory["name"]) ? $this->escape($msCategory["name"]) : "", "meta_description" => isset($msCategory["description"]) ? $this->escape($msCategory["description"]) : "")), "keyword" => $this->slugify($msCategory["name"]));
                        if ($this->ocVersion == self::OC_VERSION_3_0) {
                            $data["product_seo_url"] = array(array($lang => $this->slugify($msCategory["name"])));
                        }
                        if (method_exists($this->model_catalog_category, "addCategory")) {
                            $category_id = $this->model_catalog_category->addCategory($data);
                            $this->db->query("INSERT INTO " . DB_PREFIX . "category_to_store SET store_id='0' , category_id='" . $category_id . "'");
                        } else {
                            $this->db->query("INSERT INTO " . DB_PREFIX . "category SET parent_id = '" . (int) $data["parent_id"] . "', `top` = '0', `column` = '" . (int) $data["column"] . "', sort_order = '" . (int) $data["sort_order"] . "', status = '" . (int) $data["status"] . "', date_modified = NOW(), date_added = NOW()");
                            $category_id = $this->db->getLastId();
                            foreach ($data["category_description"] as $language_id => $value) {
                                $this->db->query("INSERT INTO " . DB_PREFIX . "category_description SET category_id = '" . (int) $category_id . "', language_id = '" . (int) $language_id . "', name = '" . $value["name"] . "', description = '" . $value["description"] . "', meta_title = '" . $value["meta_title"] . "', meta_description = '" . $value["meta_description"] . "'");
                            }
                            $level = 0;
                            $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "category_path` WHERE category_id = '" . (int) $data["parent_id"] . "' ORDER BY `level` ASC");
                            foreach ($query->rows as $result) {
                                $this->db->query("INSERT INTO `" . DB_PREFIX . "category_path` SET `category_id` = '" . (int) $category_id . "', `path_id` = '" . (int) $result["path_id"] . "', `level` = '" . (int) $level . "'");
                                $level++;
                            }
                            $this->db->query("INSERT INTO `" . DB_PREFIX . "category_path` SET `category_id` = '" . (int) $category_id . "', `path_id` = '" . (int) $category_id . "', `level` = '" . (int) $level . "'");
                            $this->db->query("INSERT INTO " . DB_PREFIX . "category_to_store SET store_id='0' , category_id='" . $category_id . "'");
                            $this->db->query("INSERT INTO " . DB_PREFIX . "category_to_layout SET store_id='0' , layout_id='0', category_id='" . $category_id . "'");
                            if ($this->ocVersion == self::OC_VERSION_3_0) {
                                $this->db->query("INSERT INTO " . DB_PREFIX . "seo_url SET store_id = '0', language_id = '" . $lang . "', query = 'category_id=" . (int) $category_id . "', keyword = '" . $this->slugify($msCategory["name"]) . "'");
                            } else {
                                $this->db->query("INSERT INTO " . DB_PREFIX . "url_alias SET query = 'category_id=" . (int) $category_id . "', keyword = '" . $this->slugify($msCategory["name"]) . "'");
                            }
                        }
                        $this->db->query("INSERT INTO `" . DB_PREFIX . "ms_category` set ms_id='" . $msCategory["id"] . "', category_id='" . $category_id . "',updated='" . $msCategory["updated"] . "'");
                        switch ($catLink) {
                            case self::MS_INTEGRATION_SETTING_CATEGORY_CODE:
                                $res = $this->msPut($msCategory["meta"]["href"], array("code" => $category_id));
                                break;
                            case self::MS_INTEGRATION_SETTING_CATEGORY_EXTERNAL_CODE:
                                $res = $this->msPut($msCategory["meta"]["href"], array("externalCode" => $category_id));
                                break;
                        }
                    }
                    unset($msCategories[$ck]);
                }
            }
        }
        if (method_exists($this->model_catalog_category, "repairCategories")) {
            $this->model_catalog_category->repairCategories();
        }
    }
    public function products($linkMode = self::MODE_LINK_ONLY, $updateMode = self::UPDATE_MODE_BY_TIME)
    {
        $this->load->model("catalog/product");
        $offset = date("Z") - 3 * 60 * 60;
        $cronTime = $this->config->get("ms_integration_cron_time");
        if ($cronTime == NULL || $cronTime <= 0) {
            $cronTime = 10;
        }
        $cronOffset = $cronTime * 60 * 3;
        $date = date("Y-m-d H:i:s", time() - $offset - $cronOffset);
        $ms = $this->config->get("ms_integration_ms_id");
        $oc = $this->config->get("ms_integration_oc_id");
        $create = $this->config->get("ms_integration_create_product");
        $pageOffset = 0;
        if ($updateMode == self::UPDATE_MODE_BY_TIME) {
            $link = "https://online.moysklad.ru/api/remap/1.1/entity/assortment?filter=" . urlencode("updated>=" . $date);
        } else {
            $pageOffset = $this->config->get("ms_integration_product_page_cash");
            if (is_numeric($pageOffset)) {
                $link = "https://online.moysklad.ru/api/remap/1.1/entity/assortment?limit=50&offset=" . $pageOffset * 50;
            } else {
                $link = "https://online.moysklad.ru/api/remap/1.1/entity/assortment?limit=50";
            }
        }
        $msProductsRes = $this->msGet($link);
        $size = $msProductsRes["meta"]["size"];
        $pages = ceil($size / 50);
        for ($page = $pageOffset; $page < $pages; $page++) {
            if ($page != $pageOffset) {
                if ($updateMode == self::UPDATE_MODE_BY_TIME) {
                    $link = "https://online.moysklad.ru/api/remap/1.1/entity/assortment?limit=50&offset=" . $page * 50 . "&filter=" . urlencode("updated>=" . $date);
                } else {
                    $link = "https://online.moysklad.ru/api/remap/1.1/entity/assortment?limit=50&offset=" . $page * 50;
                }
                $msProductsRes = $this->msGet($link);
            }
            if (empty($msProductsRes["rows"])) {
                break;
            }
            foreach ($msProductsRes["rows"] as $msProduct) {
                if ($msProduct["meta"]["type"] == "product" || $msProduct["meta"]["type"] == "bundle") {
                    $linkCheck = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ms_product` WHERE ms_id='" . $msProduct["id"] . "' AND type='" . $msProduct["meta"]["type"] . "' limit 1");
                    if ($linkCheck->num_rows == 0) {
                        if ($linkMode == self::MODE_UPDATE_ONLY) {
                            continue;
                        }
                        if (!isset($msProduct[$ms])) {
                            continue;
                        }
                        $product_id = 0;
                        $ocProduct = $this->db->query("SELECT * FROM `" . DB_PREFIX . "product` WHERE " . $oc . "='" . $this->db->escape($msProduct[$ms]) . "' limit 1");
                        if (0 < $ocProduct->num_rows) {
                            $product_id = $ocProduct->row["product_id"];
                        }
                        if ($product_id == 0) {
                            if ($create && self::MODE_LINK_CREATE <= $linkMode) {
                                $this->createProduct($msProduct);
                            }
                        } else {
                            $linkCheck = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ms_product` WHERE product_id='" . $product_id . "' AND type='" . $msProduct["meta"]["type"] . "' limit 1");
                            if (0 < $linkCheck->num_rows) {
                                $this->logging("Товар с " . $oc . " - " . $ocProduct->row[$oc] . " уже связан с " . $linkCheck->row["type"] . ": " . $linkCheck->row["ms_id"]);
                                continue;
                            }
                            $insRes = $this->db->query("INSERT INTO `" . DB_PREFIX . "ms_product` (ms_id,product_id,type) VALUES ('" . $msProduct["id"] . "','" . $product_id . "','" . $msProduct["meta"]["type"] . "')");
                            if (self::MODE_LINK_CREATE_UPDATE <= $linkMode) {
                                $this->updateProduct($product_id, $msProduct, $updateMode);
                            }
                        }
                    } else {
                        $product_id = (int) $linkCheck->row["product_id"];
                        if ($updateMode == self::UPDATE_MODE_ALL && $linkMode == self::MODE_UPDATE_ONLY) {
                            $this->updateProduct($product_id, $msProduct, $updateMode);
                            continue;
                        }
                        if ($linkCheck->row["updated"] < $msProduct["updated"] && self::MODE_LINK_CREATE_UPDATE <= $linkMode) {
                            $this->updateProduct($product_id, $msProduct, $updateMode);
                        }
                    }
                }
            }
            if ($updateMode == self::UPDATE_MODE_ALL) {
                $set = $this->db->query("SELECT * FROM `" . DB_PREFIX . "setting` WHERE `key`='ms_integration_product_page_cash'");
                if ($set->num_rows == 0) {
                    $this->db->query("INSERT INTO `" . DB_PREFIX . "setting` SET `key`='ms_integration_product_page_cash', `code`='ms_integration', `serialized`='0', `value`='" . ($page + 1) . "'");
                } else {
                    $this->db->query("UPDATE `" . DB_PREFIX . "setting` SET `value`='" . ($page + 1) . "' WHERE `key`='ms_integration_product_page_cash' AND `code`='ms_integration'");
                }
            }
        }
        if ($updateMode == self::UPDATE_MODE_ALL) {
            $set = $this->db->query("SELECT * FROM `" . DB_PREFIX . "setting` WHERE `key`='ms_integration_product_page_cash'");
            if ($set->num_rows == 0) {
                $this->db->query("INSERT INTO `" . DB_PREFIX . "setting` SET `key`='ms_integration_product_page_cash', `code`='ms_integration', `serialized`='0', `value`='0'");
            } else {
                $this->db->query("UPDATE `" . DB_PREFIX . "setting` SET `value`='0' WHERE `key`='ms_integration_product_page_cash' AND `code`='ms_integration'");
            }
        }
    }
    public function variants($linkMode = self::MODE_LINK_ONLY, $updateMode = self::UPDATE_MODE_BY_TIME)
    {
        if (!$this->config->get("ms_integration_modifications")) {
            return NULL;
        }
        $offset = date("Z") - 3 * 60 * 60;
        $cronTime = $this->config->get("ms_integration_cron_time");
        if ($cronTime == NULL || $cronTime <= 0) {
            $cronTime = 10;
        }
        $cronOffset = $cronTime * 60 * 3;
        $date = date("Y-m-d H:i:s", time() - $offset - $cronOffset);
        $opCreate = $this->config->get("ms_integration_create_option");
        $productOpCreate = $this->config->get("ms_integration_create_product_option");
        $lang = $this->config->get("ms_integration_language");
        $priceType = $this->config->get("ms_integration_ms_price_type");
        $pageOffset = 0;
        if ($updateMode == self::UPDATE_MODE_BY_TIME) {
            $link = "https://online.moysklad.ru/api/remap/1.1/entity/assortment?filter=" . urlencode("updated>=" . $date);
        } else {
            $pageOffset = $this->config->get("ms_integration_variant_page_cash");
            if (is_numeric($pageOffset)) {
                $link = "https://online.moysklad.ru/api/remap/1.1/entity/assortment?limit=100&offset=" . $pageOffset * 100;
            } else {
                $link = "https://online.moysklad.ru/api/remap/1.1/entity/assortment?limit=100";
            }
        }
        $msProductsRes = $this->msGet($link);
        $size = $msProductsRes["meta"]["size"];
        $pages = ceil($size / 100);
        for ($page = $pageOffset; $page < $pages; $page++) {
            if ($page != $pageOffset) {
                if ($updateMode == self::UPDATE_MODE_BY_TIME) {
                    $link = "https://online.moysklad.ru/api/remap/1.1/entity/assortment?limit=100&offset=" . $page * 100 . "&filter=" . urlencode("updated>=" . $date);
                } else {
                    $link = "https://online.moysklad.ru/api/remap/1.1/entity/assortment?limit=100&offset=" . $page * 100;
                }
                $msProductsRes = $this->msGet($link);
            }
            if (empty($msProductsRes["rows"])) {
                break;
            }
            foreach ($msProductsRes["rows"] as $msVariant) {
                if ($msVariant["meta"]["type"] == "variant") {
                    $tmpHref = $msVariant["product"]["meta"]["href"];
                    $product_ms_arr = explode("/", $tmpHref);
                    $product_ms_id = $product_ms_arr[8];
                    $res = $this->db->query("SELECT product_id FROM " . DB_PREFIX . "ms_product WHERE ms_id='" . $product_ms_id . "' AND type='product'");
                    if (0 < $res->num_rows) {
                        $product_id = $res->row["product_id"];
                        foreach ($msVariant["characteristics"] as $msChar) {
                            $res = $this->db->query("SELECT option_id FROM " . DB_PREFIX . "option_description WHERE name='" . $this->db->escape($msChar["name"]) . "' AND language_id='" . $lang . "'");
                            if ($res->num_rows == 0) {
                                if ($opCreate && self::MODE_LINK_CREATE <= $linkMode && $linkMode != self::MODE_UPDATE_ONLY) {
                                    $this->db->query("INSERT INTO " . DB_PREFIX . "option SET type='select'");
                                    $option_id = $this->db->getLastId();
                                    $this->db->query("INSERT INTO " . DB_PREFIX . "option_description SET option_id='" . $option_id . "',name='" . $this->escape($msChar["name"]) . "',language_id='" . $lang . "'");
                                } else {
                                    continue;
                                }
                            } else {
                                $option_id = $res->row["option_id"];
                            }
                            $res = $this->db->query("SELECT option_value_id FROM " . DB_PREFIX . "option_value_description WHERE name='" . $this->escape($msChar["value"]) . "' AND option_id='" . $option_id . "' AND language_id='" . $lang . "'");
                            if ($res->num_rows == 0) {
                                if ($opCreate && self::MODE_LINK_CREATE <= $linkMode && $linkMode != self::MODE_UPDATE_ONLY) {
                                    $this->db->query("INSERT INTO " . DB_PREFIX . "option_value SET option_id='" . $option_id . "'");
                                    $option_value_id = $this->db->getLastId();
                                    $this->db->query("INSERT INTO " . DB_PREFIX . "option_value_description SET option_value_id='" . $option_value_id . "',name='" . $this->escape($msChar["value"]) . "',language_id='" . $lang . "', option_id='" . $option_id . "'");
                                } else {
                                    continue;
                                }
                            } else {
                                $option_value_id = $res->row["option_value_id"];
                            }
                            $res = $this->db->query("SELECT product_option_id FROM " . DB_PREFIX . "product_option WHERE product_id='" . $product_id . "' AND option_id='" . $option_id . "'");
                            if ($res->num_rows == 0) {
                                if ($productOpCreate && self::MODE_LINK_CREATE <= $linkMode && $linkMode != self::MODE_UPDATE_ONLY) {
                                    $this->db->query("INSERT INTO " . DB_PREFIX . "product_option SET product_id='" . $product_id . "' , option_id='" . $option_id . "', required='1'");
                                    $product_option_id = $this->db->getLastId();
                                } else {
                                    continue;
                                }
                            } else {
                                $product_option_id = $res->row["product_option_id"];
                            }
                            $res = $this->db->query("SELECT product_option_value_id FROM " . DB_PREFIX . "product_option_value WHERE product_id='" . $product_id . "' AND option_id='" . $option_id . "' AND option_value_id='" . $option_value_id . "' AND product_option_id='" . $product_option_id . "'");
                            if ($res->num_rows == 0) {
                                if ($productOpCreate && self::MODE_LINK_CREATE <= $linkMode && $linkMode != self::MODE_UPDATE_ONLY) {
                                    $subtract = $this->config->get("ms_integration_subtract_create") ? 1 : 0;
                                    $price = $msVariant["salePrices"][0]["value"] / 100;
                                    foreach ($msVariant["salePrices"] as $msPrice) {
                                        if ($msPrice["priceType"] == $priceType) {
                                            $price = $msPrice["value"] / 100;
                                        }
                                    }
                                    $quantity = 0;
                                    if (isset($msVariant["quantity"])) {
                                        $quantity = $msVariant["quantity"];
                                    }
                                    $ocProduct = $this->db->query("SELECT price FROM " . DB_PREFIX . "product WHERE product_id='" . $product_id . "'");
                                    if (0 < $ocProduct->num_rows) {
                                        $price = $price - $ocProduct->row["price"];
                                        $pricePrefix = "+";
                                        if ($price < 0) {
                                            $pricePrefix = "-";
                                        }
                                        $price = abs($price);
                                        $this->db->query("INSERT INTO " . DB_PREFIX . "product_option_value SET product_option_id='" . $product_option_id . "', option_value_id='" . $option_value_id . "', product_id='" . $product_id . "' , option_id='" . $option_id . "', subtract='" . $subtract . "', price='" . $price . "', price_prefix='" . $pricePrefix . "', quantity='" . $quantity . "'");
                                        $product_option_value_id = $this->db->getLastId();
                                        $this->db->query("INSERT INTO " . DB_PREFIX . "ms_variant SET product_id='" . $product_id . "', product_option_value_id='" . $product_option_value_id . "', ms_id='" . $product_ms_id . "', var_id='" . $msVariant["id"] . "', updated='" . $msVariant["updated"] . "'");
                                    }
                                }
                            } else {
                                $product_option_value_id = $res->row["product_option_value_id"];
                                $linkCheck = $this->db->query("SELECT * FROM " . DB_PREFIX . "ms_variant WHERE product_option_value_id='" . $product_option_value_id . "'");
                                if ($linkCheck->num_rows == 0) {
                                    if ($linkMode == self::MODE_UPDATE_ONLY) {
                                        continue;
                                    }
                                    $this->db->query("INSERT INTO " . DB_PREFIX . "ms_variant SET product_id='" . $product_id . "', product_option_value_id='" . $product_option_value_id . "', ms_id='" . $product_ms_id . "', var_id='" . $msVariant["id"] . "'");
                                }
                                if (self::MODE_LINK_CREATE_UPDATE <= $linkMode) {
                                    if ($updateMode == self::UPDATE_MODE_BY_TIME && $msVariant["updated"] <= $linkCheck->row["updated"]) {
                                        continue;
                                    }
                                    if ($this->config->get("ms_integration_price_update")) {
                                        $price = $msVariant["salePrices"][0]["value"] / 100;
                                        foreach ($msVariant["salePrices"] as $msPrice) {
                                            if ($msPrice["priceType"] == $priceType) {
                                                $price = $msPrice["value"] / 100;
                                            }
                                        }
                                        $ocProduct = $this->db->query("SELECT price FROM " . DB_PREFIX . "product WHERE product_id='" . $product_id . "'");
                                        if (0 < $ocProduct->num_rows) {
                                            $price = $price - $ocProduct->row["price"];
                                            $pricePrefix = "+";
                                            if ($price < 0) {
                                                $pricePrefix = "-";
                                            }
                                            $price = abs($price);
                                            $this->db->query("UPDATE " . DB_PREFIX . "product_option_value SET price='" . $price . "', price_prefix='" . $pricePrefix . "' WHERE product_option_value_id='" . $product_option_value_id . "'");
                                            $this->db->query("UPDATE " . DB_PREFIX . "ms_variant SET updated='" . $msVariant["updated"] . "' WHERE product_option_value_id='" . $product_option_value_id . "'");
                                        }
                                    }
                                }
                            }
                        }
                    } else {
                        continue;
                    }
                }
            }
            if ($updateMode == self::UPDATE_MODE_ALL) {
                $set = $this->db->query("SELECT * FROM `" . DB_PREFIX . "setting` WHERE `key`='ms_integration_variant_page_cash'");
                if ($set->num_rows == 0) {
                    $this->db->query("INSERT INTO `" . DB_PREFIX . "setting` SET `key`='ms_integration_variant_page_cash', `code`='ms_integration', `serialized`='0', `value`='" . ($page + 1) . "'");
                } else {
                    $this->db->query("UPDATE `" . DB_PREFIX . "setting` SET `value`='" . ($page + 1) . "' WHERE `key`='ms_integration_variant_page_cash' AND `code`='ms_integration'");
                }
            }
        }
        if ($updateMode == self::UPDATE_MODE_ALL) {
            $set = $this->db->query("SELECT * FROM `" . DB_PREFIX . "setting` WHERE `key`='ms_integration_variant_page_cash'");
            if ($set->num_rows == 0) {
                $this->db->query("INSERT INTO `" . DB_PREFIX . "setting` SET `key`='ms_integration_variant_page_cash', `code`='ms_integration', `serialized`='0', `value`='0'");
            } else {
                $this->db->query("UPDATE `" . DB_PREFIX . "setting` SET `value`='0' WHERE `key`='ms_integration_variant_page_cash' AND `code`='ms_integration'");
            }
        }
    }
    public function stock()
    {
        if ($this->config->get("ms_integration_stock") == 0) {
            return NULL;
        }
        $bundleProductFilterArray = array();
        $msProducts = $this->msGet("https://online.moysklad.ru/api/remap/1.2/entity/bundle?limit=100&expand=components");
        $size = $msProducts["meta"]["size"];
        $pages = ceil($size / 100);
        $bundleComponents = array();
        for ($page = 0; $page < $pages; $page++) {
            if ($page != 0) {
                $msProducts = $this->msGet("https://online.moysklad.ru/api/remap/1.2/entity/bundle?limit=100&expand=components&offset=" . $page * 100);
            }
            if (empty($msProducts["rows"])) {
                break;
            }
            foreach ($msProducts["rows"] as $msProduct) {
                $bundleComponents[$msProduct["id"]] = $msProduct["components"]["rows"];
                foreach ($msProduct["components"]["rows"] as $component) {
                    $bundleProductFilterArray[] = $component["assortment"]["meta"]["href"];
                }
            }
        }
        $bundleProductFilterArray = array_unique($bundleProductFilterArray);
        $pageOffset = 0;
        $storeID = $this->config->get("ms_integration_stock_store");
        $storeString = "";
        if ($storeID != "" && $storeID != NULL) {
            $storeID = explode(";", $storeID);
            foreach ($storeID as $st) {
                $storeString .= "store=https://online.moysklad.ru/api/remap/1.2/entity/store/" . $st . ";";
            }
            $link = "https://online.moysklad.ru/api/remap/1.2/report/stock/all?limit=1000&offset=" . $pageOffset * 1000 . "&filter=" . $storeString . ";quantityMode=all&groupBy=variant";
        } else {
            $link = "https://online.moysklad.ru/api/remap/1.2/report/stock/all?limit=1000&offset=" . $pageOffset * 1000 . "&filter=quantityMode=all&groupBy=variant";
        }
        $msProductsRes = $this->msGet($link);
        $size = $msProductsRes["meta"]["size"];
        $pages = ceil($size / 1000);
        $variantsProduct = array();
        $optionsQty = array();
        $bundleProduct = array();
        for ($page = $pageOffset; $page < $pages; $page++) {
            if ($pageOffset < $page) {
                if ($storeID != "" && $storeID != NULL) {
                    $link = "https://online.moysklad.ru/api/remap/1.2/report/stock/all?limit=1000&offset=" . $page * 1000 . "&filter=" . $storeString . ";quantityMode=all&groupBy=variant";
                } else {
                    $link = "https://online.moysklad.ru/api/remap/1.2/report/stock/all?stockMode=all&limit=1000&offset=" . $page * 1000 . "&filter=quantityMode=all&groupBy=variant";
                }
                $msProductsRes = $this->msGet($link);
            }
            foreach ($msProductsRes["rows"] as $msProduct) {
                $url = parse_url($msProduct["meta"]["href"]);
                $tmpHref = $url["path"];
                $id_arr = explode("/", $tmpHref);
                $msId = $id_arr[6];
                $qty = $msProduct["quantity"];
                $tmpHref = $msProduct["meta"]["href"];
                list($tmpExplode) = explode("?", $msProduct["meta"]["href"]);
                if (in_array($tmpExplode, $bundleProductFilterArray)) {
                    $bundleProduct[$tmpExplode] = $qty;
                }
                if ($msProduct["meta"]["type"] == "product") {
                    $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ms_product` WHERE ms_id='" . $msId . "' AND type='product' limit 1");
                    if ($query->num_rows == 0) {
                        continue;
                    }
                    $product_id = $query->row["product_id"];
                    if (isset($variantsProduct[$product_id])) {
                        $variantsProduct[$product_id] += $qty;
                    } else {
                        $variantsProduct[$product_id] = $qty;
                    }
                    if (0 < $qty) {
                        $st = $this->config->get("ms_integration_in_stock_status");
                    } else {
                        $st = $this->config->get("ms_integration_stock_out_status");
                    }
                    switch ($st) {
                        case 0:
                            $this->db->query("UPDATE `" . DB_PREFIX . "product` SET quantity='" . $qty . "', status='0' WHERE product_id='" . (int) $query->row["product_id"] . "'");
                            break;
                        case 1:
                            $this->db->query("UPDATE `" . DB_PREFIX . "product` SET quantity='" . $qty . "', status='1' WHERE product_id='" . (int) $query->row["product_id"] . "'");
                            break;
                        case 2:
                        default:
                            $this->db->query("UPDATE `" . DB_PREFIX . "product` SET quantity='" . $qty . "' WHERE product_id='" . (int) $query->row["product_id"] . "'");
                            break;
                    }
                } else {
                    if ($msProduct["meta"]["type"] == "variant") {
                        $res = $this->db->query("SELECT * FROM " . DB_PREFIX . "ms_variant WHERE var_id='" . $msId . "'");
                        if ($res->num_rows == 0) {
                            continue;
                        }
                        foreach ($res->rows as $linkCheck) {
                            $optId = $linkCheck["product_option_value_id"];
                            $product_id = $linkCheck["product_id"];
                            if (isset($optionsQty[$optId])) {
                                $optionsQty[$optId] += $qty;
                            } else {
                                $optionsQty[$optId] = $qty;
                            }
                        }
                        if (isset($variantsProduct[$product_id])) {
                            $variantsProduct[$product_id] += $qty;
                        } else {
                            $variantsProduct[$product_id] = $qty;
                        }
                    }
                }
            }
        }
        unset($msProductsRes);
        $res = $this->db->query("SELECT product_id FROM " . DB_PREFIX . "ms_product GROUP BY product_id");
        foreach ($res->rows as $row) {
            if (isset($variantsProduct[$row["product_id"]])) {
                $qty = $variantsProduct[$row["product_id"]];
                if (0 < $qty) {
                    $st = $this->config->get("ms_integration_in_stock_status");
                } else {
                    $st = $this->config->get("ms_integration_stock_out_status");
                }
                switch ($st) {
                    case 0:
                        $this->db->query("UPDATE `" . DB_PREFIX . "product` SET quantity='" . $qty . "', status='0' WHERE product_id='" . $row["product_id"] . "'");
                        break;
                    case 1:
                        $this->db->query("UPDATE `" . DB_PREFIX . "product` SET quantity='" . $qty . "', status='1' WHERE product_id='" . $row["product_id"] . "'");
                        break;
                    case 2:
                    default:
                        $this->db->query("UPDATE `" . DB_PREFIX . "product` SET quantity='" . $qty . "' WHERE product_id='" . $row["product_id"] . "'");
                        break;
                }
            }
        }
        $res = $this->db->query("SELECT product_option_value_id FROM " . DB_PREFIX . "ms_variant GROUP BY product_option_value_id");
        foreach ($res->rows as $row) {
            if (isset($optionsQty[$row["product_option_value_id"]])) {
                $qty = $optionsQty[$row["product_option_value_id"]];
                $this->db->query("UPDATE `" . DB_PREFIX . "product_option_value` SET quantity='" . $qty . "' where product_option_value_id='" . $row["product_option_value_id"] . "'");
            }
        }
        foreach ($bundleComponents as $bundleId => $bundle) {
            $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ms_product` WHERE ms_id='" . $bundleId . "' AND type='bundle' limit 1");
            if (0 < $query->num_rows) {
                $bundleQty = 0;
                foreach ($bundle as $cKey => $component) {
                    if ($component["quantity"] <= 0) {
                        $bundleQty = 0;
                        break;
                    }
                    $qty = 0;
                    if (isset($bundleProduct[$component["assortment"]["meta"]["href"]])) {
                        $qty = $bundleProduct[$component["assortment"]["meta"]["href"]];
                    }
                    $bQty = floor($qty / $component["quantity"]);
                    if ($bundleQty == 0) {
                        $bundleQty = $bQty;
                    } else {
                        if ($bQty < $bundleQty) {
                            $bundleQty = $bQty;
                        }
                    }
                }
                if (0 < $bundleQty) {
                    $st = $this->config->get("ms_integration_in_stock_status");
                } else {
                    $st = $this->config->get("ms_integration_stock_out_status");
                }
                switch ($st) {
                    case 0:
                        $this->db->query("UPDATE `" . DB_PREFIX . "product` SET quantity='" . $bundleQty . "', status='0' WHERE product_id='" . (int) $query->row["product_id"] . "'");
                        break;
                    case 1:
                        $this->db->query("UPDATE `" . DB_PREFIX . "product` SET quantity='" . $bundleQty . "', status='1' WHERE product_id='" . (int) $query->row["product_id"] . "'");
                        break;
                    case 2:
                    default:
                        $this->db->query("UPDATE `" . DB_PREFIX . "product` SET quantity='" . $bundleQty . "' WHERE product_id='" . (int) $query->row["product_id"] . "'");
                        break;
                }
            }
        }
    }
    private function createProduct($msProduct)
    {
        $this->load->model("catalog/product");
        $ms = $this->config->get("ms_integration_ms_id");
        $oc = $this->config->get("ms_integration_oc_id");
        $priceType = $this->config->get("ms_integration_ms_price_type");
        $lang = $this->config->get("ms_integration_language");
        $cats = $this->config->get("ms_integration_categories");
        $img = "";
        $quantity = 0;
        $stock = 0;
        if (isset($msProduct["quantity"])) {
            $quantity = $msProduct["quantity"];
        }
        if (isset($msProduct["stock"])) {
            $stock = $msProduct["stock"];
        }
        $price = $msProduct["salePrices"][0]["value"] / 100;
        foreach ($msProduct["salePrices"] as $msPrice) {
            if ($msPrice["priceType"] == $priceType) {
                $price = $msPrice["value"] / 100;
            }
        }
        $data = array("model" => isset($msProduct["code"]) ? $msProduct["code"] : "", "sku" => isset($msProduct["article"]) ? $msProduct["article"] : "", "upc" => "", "ean" => isset($msProduct["barcodes"][0]) ? $msProduct["barcodes"][0] : "", "jan" => "", "isbn" => "", "mpn" => "", "location" => "", "quantity" => $quantity, "minimum" => "", "subtract" => $this->config->get("ms_integration_subtract_create") ? 1 : 0, "stock_status_id" => $this->config->get("ms_integration_stock_status_create"), "date_available" => date("Y-m-d"), "manufacturer_id" => "", "shipping" => $this->config->get("ms_integration_shipping_create") ? 1 : 0, "price" => $price, "points" => "", "weight" => isset($msProduct["weight"]) ? $msProduct["weight"] : "", "weight_class_id" => $this->config->get("config_weight_class_id"), "length" => "", "width" => "", "height" => "", "length_class_id" => $this->config->get("config_length_class_id"), "status" => $this->config->get("ms_integration_status_create"), "tax_class_id" => "", "sort_order" => "1", "product_description" => array($lang => array("name" => isset($msProduct["name"]) ? $msProduct["name"] : "", "description" => isset($msProduct["description"]) ? $msProduct["description"] : "", "tag" => "", "meta_title" => isset($msProduct["name"]) ? $msProduct["name"] : "", "meta_description" => isset($msProduct["description"]) ? $msProduct["description"] : "", "meta_keyword" => "")), "image" => $img, "keyword" => $this->slugify($msProduct["name"]));
        if ($this->ocVersion == self::OC_VERSION_3_0) {
            $data["product_seo_url"] = array(array($lang => $this->slugify($msProduct["name"])));
        }
        if ($oc != self::MS_INTEGRATION_SETTING_OC_ID) {
            $data[$oc] = $msProduct[$ms];
        }
        $product_id = 0;
        if (method_exists($this->model_catalog_product, "addProduct")) {
            $product_id = $this->model_catalog_product->addProduct($data);
        } else {
            $this->db->query("INSERT INTO " . DB_PREFIX . "product SET model = '" . $this->escape($data["model"]) . "', sku = '" . $this->escape($data["sku"]) . "', upc = '" . $this->escape($data["upc"]) . "', ean = '" . $this->escape($data["ean"]) . "', jan = '" . $this->escape($data["jan"]) . "', isbn = '" . $this->escape($data["isbn"]) . "', mpn = '" . $this->escape($data["mpn"]) . "', location = '" . $this->escape($data["location"]) . "', quantity = '" . (int) $data["quantity"] . "', minimum = '" . (int) $data["minimum"] . "', subtract = '" . (int) $data["subtract"] . "', stock_status_id = '" . (int) $data["stock_status_id"] . "', date_available = '" . $this->escape($data["date_available"]) . "', manufacturer_id = '" . (int) $data["manufacturer_id"] . "', shipping = '" . (int) $data["shipping"] . "', price = '" . (double) $data["price"] . "', points = '" . (int) $data["points"] . "', weight = '" . (double) $data["weight"] . "', weight_class_id = '" . (int) $data["weight_class_id"] . "', length = '" . (double) $data["length"] . "', width = '" . (double) $data["width"] . "', height = '" . (double) $data["height"] . "', length_class_id = '" . (int) $data["length_class_id"] . "', status = '" . (int) $data["status"] . "', tax_class_id = '" . (int) $data["tax_class_id"] . "', sort_order = '" . (int) $data["sort_order"] . "', date_added = NOW(), date_modified = NOW()");
            $product_id = $this->db->getLastId();
            foreach ($data["product_description"] as $language_id => $value) {
                $this->db->query("INSERT INTO " . DB_PREFIX . "product_description SET product_id = '" . (int) $product_id . "', language_id = '" . (int) $language_id . "', name = '" . $this->escape($value["name"]) . "', description = '" . $this->escape($value["description"]) . "', meta_title = '" . $this->escape($value["meta_title"]) . "', meta_description = '" . $this->escape($value["meta_description"]) . "'");
            }
            if ($this->ocVersion == self::OC_VERSION_3_0) {
                $this->db->query("INSERT INTO " . DB_PREFIX . "seo_url SET store_id='0', language_id='" . $language_id . "', query='product_id=" . $product_id . "', keyword='" . $this->slugify($msProduct["name"]) . "'");
            } else {
                $this->db->query("INSERT INTO " . DB_PREFIX . "url_alias SET query = 'product_id=" . (int) $product_id . "', keyword = '" . $data["keyword"] . "'");
            }
        }
        if (0 < $product_id) {
            $this->db->query("INSERT INTO `" . DB_PREFIX . "ms_product` (ms_id,product_id,type,updated) VALUES ('" . $msProduct["id"] . "','" . $product_id . "','" . $msProduct["meta"]["type"] . "','" . $msProduct["updated"] . "')");
            $this->db->query("INSERT INTO " . DB_PREFIX . "product_to_store SET store_id='0' , product_id='" . $product_id . "'");
            $this->db->query("INSERT INTO " . DB_PREFIX . "product_to_layout SET store_id='0' , layout_id='0', product_id='" . $product_id . "'");
            if ($oc == self::MS_INTEGRATION_SETTING_OC_ID) {
                $msData = array();
                $msData[$ms] = $product_id;
                $this->msPut($msProduct["meta"]["href"], $msData);
            }
            if (isset($msProduct["image"]["meta"]["href"])) {
                $image_url = $msProduct["image"]["meta"]["href"];
                $topath = DIR_IMAGE . "catalog/";
                $tmpHref = $msProduct["image"]["filename"];
                $tmpExplode = explode(".", $tmpHref);
                $imgFormat = array_pop($tmpExplode);
                $file_path = $topath . "product_" . $product_id . "_0_image." . $imgFormat;
                $rescurl = $this->msGetImage($image_url);
                $fp = fopen($file_path, "w");
                fwrite($fp, $rescurl);
                fclose($fp);
                $img = "catalog/" . "product_" . $product_id . "_0_image." . $imgFormat;
                $this->db->query("UPDATE " . DB_PREFIX . "product SET image = '" . $this->escape($img) . "' WHERE product_id = '" . (int) $product_id . "'");
            }
            if (isset($msProduct["productFolder"]) && $cats) {
                $tmpHref = $msProduct["productFolder"]["meta"]["href"];
                $tmpx = explode("/", $tmpHref);
                $tmp_ms_cat = $tmpx[8];
                $msCat = $this->msGet("https://online.moysklad.ru/api/remap/1.1/entity/productfolder/" . $tmp_ms_cat);
                $res = $this->db->query("DELETE FROM " . DB_PREFIX . "product_to_category where product_id='" . $product_id . "'");
                $this->attachCategory($msCat, $product_id);
            }
        }
    }
    private function updateProduct($product_id, $msProduct, $updateMode = self::UPDATE_MODE_BY_TIME)
    {
        $priceType = $this->config->get("ms_integration_ms_price_type");
        $lang = $this->config->get("ms_integration_language");
        $cats = $this->config->get("ms_integration_categories");
        $updateText = "";
        $updateDescriptionText = "";
        if ($this->config->get("ms_integration_price_update") && isset($msProduct["salePrices"][0]["value"])) {
            $price = $msProduct["salePrices"][0]["value"] / 100;
            foreach ($msProduct["salePrices"] as $msPrice) {
                if ($msPrice["priceType"] == $priceType) {
                    $price = $msPrice["value"] / 100;
                }
            }
            $updateText .= "price = '" . $price . "',";
        }
        if ($this->config->get("ms_integration_ean_update") && isset($msProduct["barcodes"][0])) {
            $updateText .= "ean = '" . $msProduct["barcodes"][0] . "',";
        }
        if ($this->config->get("ms_integration_weight_update") && isset($msProduct["weight"])) {
            $updateText .= "weight = '" . $msProduct["weight"] . "',";
        }
        if ($this->config->get("ms_integration_image_update") && isset($msProduct["image"]["meta"]["href"])) {
            if ($updateMode == self::UPDATE_MODE_BY_TIME) {
                if (date("Y-m-d H:i:s", time() - 12 * 60 * 60) <= $msProduct["image"]["updated"]) {
                    $image_url = $msProduct["image"]["meta"]["href"];
                    $topath = DIR_IMAGE . "catalog/";
                    $tmpHref = $msProduct["image"]["filename"];
                    $tmpExplode = explode(".", $tmpHref);
                    $imgFormat = array_pop($tmpExplode);
                    $file_path = $topath . "product_" . $product_id . "_0_image." . $imgFormat;
                    $rescurl = $this->msGetImage($image_url);
                    $fp = fopen($file_path, "w");
                    fwrite($fp, $rescurl);
                    fclose($fp);
                    $img = "catalog/" . "product_" . $product_id . "_0_image." . $imgFormat;
                    $this->db->query("UPDATE " . DB_PREFIX . "product SET image = '" . $this->escape($img) . "' WHERE product_id = '" . (int) $product_id . "'");
                }
            } else {
                $image_url = $msProduct["image"]["meta"]["href"];
                $topath = DIR_IMAGE . "catalog/";
                $tmpHref = $msProduct["image"]["filename"];
                $tmpExplode = explode(".", $tmpHref);
                $imgFormat = array_pop($tmpExplode);
                $file_path = $topath . "product_" . $product_id . "_0_image." . $imgFormat;
                $rescurl = $this->msGetImage($image_url);
                $fp = fopen($file_path, "w");
                fwrite($fp, $rescurl);
                fclose($fp);
                $img = "catalog/" . "product_" . $product_id . "_0_image." . $imgFormat;
                $this->db->query("UPDATE " . DB_PREFIX . "product SET image = '" . $this->escape($img) . "' WHERE product_id = '" . (int) $product_id . "'");
            }
        }
        if ($updateText != "") {
            $this->db->query("UPDATE " . DB_PREFIX . "product SET " . $updateText . " date_modified = NOW() WHERE product_id = '" . $product_id . "'");
        }
        if ($this->config->get("ms_integration_name_update")) {
            $updateDescriptionText .= "name ='" . $this->escape($msProduct["name"]) . "',";
        }
        if ($this->config->get("ms_integration_description_update") && isset($msProduct["description"])) {
            $updateDescriptionText .= "description = '" . $this->escape($msProduct["description"]) . "',";
        }
        if ($updateDescriptionText != "") {
            $updateDescriptionText = substr($updateDescriptionText, 0, -1);
            $this->db->query("UPDATE " . DB_PREFIX . "product_description SET " . $updateDescriptionText . " WHERE product_id = '" . $product_id . "' AND language_id = '" . $lang . "'");
        }
        if ($cats) {
            if (isset($msProduct["productFolder"])) {
                $tmpHref = $msProduct["productFolder"]["meta"]["href"];
                $tmpx = explode("/", $tmpHref);
                $tmp_ms_cat = $tmpx[8];
                $msCat = $this->msGet("https://online.moysklad.ru/api/remap/1.1/entity/productfolder/" . $tmp_ms_cat);
                $res = $this->db->query("DELETE FROM " . DB_PREFIX . "product_to_category where product_id='" . $product_id . "'");
                $this->attachCategory($msCat, $product_id);
            } else {
                $res = $this->db->query("DELETE FROM " . DB_PREFIX . "product_to_category where product_id='" . $product_id . "'");
            }
        }
        $resL = $this->db->query("SELECT * FROM " . DB_PREFIX . "product_to_layout WHERE product_id='" . $product_id . "'");
        if ($resL->num_rows == 0) {
            $this->db->query("INSERT INTO " . DB_PREFIX . "product_to_layout SET store_id='0' , layout_id='0', product_id='" . $product_id . "'");
        }
        if ($updateMode == self::UPDATE_MODE_BY_TIME) {
            $this->db->query("UPDATE " . DB_PREFIX . "ms_product SET updated='" . $msProduct["updated"] . "' WHERE product_id='" . $product_id . "'");
        }
    }
    private function attachCategory($entity, $productId)
    {
        $resx = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ms_category` WHERE ms_id='" . $entity["id"] . "'");
        if (0 < $resx->num_rows) {
            if (isset($entity["productFolder"])) {
                $this->db->query("INSERT INTO " . DB_PREFIX . "product_to_category SET category_id='" . $resx->row["category_id"] . "' , product_id='" . $productId . "'");
                $tmpHref = $entity["productFolder"]["meta"]["href"];
                $tmpx = explode("/", $tmpHref);
                $tmp_ms_cat = $tmpx[8];
                $msCat = $this->msGet("https://online.moysklad.ru/api/remap/1.1/entity/productfolder/" . $tmp_ms_cat);
                $this->attachCategory($msCat, $productId);
            } else {
                $this->db->query("INSERT INTO " . DB_PREFIX . "product_to_category SET category_id='" . $resx->row["category_id"] . "' , product_id='" . $productId . "'");
                return NULL;
            }
        }
    }
    public function orders($linkMode = self::MODE_LINK_ONLY)
    {
        $create = $this->config->get("ms_integration_old_order_create");
        $orderLink = $this->config->get("ms_integration_order_link");
        if (date("e") != "UTC") {
            $offset = 3 * 60 * 60 - date("Z");
        } else {
            $offset = 0;
        }
        $cronTime = $this->config->get("ms_integration_cron_time");
        if ($cronTime == NULL || $cronTime <= 0) {
            $cronTime = 10;
        }
        $cronOffset = $cronTime * 60 * 3;
        if ($linkMode <= self::MODE_LINK_CREATE) {
            $date = date("Y-m-d H:i:s", time() - 30 * 24 * 60 * 60);
            $orders = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order` WHERE date_added>='" . $date . "' AND order_status_id!='0'");
        } else {
            if ($linkMode == self::MODE_UPDATE_ONLY) {
                $date = date("Y-m-d H:i:s", time() - $offset - $cronOffset);
                $orders = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order` WHERE date_modified>='" . $date . "' AND order_status_id!='0'");
            } else {
                if ($linkMode == self::MODE_LINK_CREATE_UPDATE && $this->ocVersion == self::OC_VERSION_2_0) {
                    $date = date("Y-m-d H:i:s", time() - $offset - $cronOffset);
                    $orders = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order` WHERE date_added>='" . $date . "' AND order_status_id!='0'");
                } else {
                    return false;
                }
            }
        }
        foreach ($orders->rows as $order) {
            if ($linkMode == self::MODE_UPDATE_ONLY) {
                $this->updateOrder($order);
                continue;
            }
            if ($linkMode <= self::MODE_LINK_CREATE) {
                $linkCheck = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ms_order` WHERE order_id='" . $order["order_id"] . "' limit 1");
                if (0 < $linkCheck->num_rows) {
                    continue;
                }
                if (isset($orderLink) && $orderLink != "") {
                    $msOrder = $this->msGet("https://online.moysklad.ru/api/remap/1.1/entity/customerorder?filter=" . $orderLink . "=" . $this->config->get("ms_integration_order_prefix") . $order["order_id"] . $this->config->get("ms_integration_order_suffix"));
                    if (count($msOrder["rows"]) == 0) {
                        if ($create) {
                            $this->sendOrder($order);
                        }
                    } else {
                        $this->db->query("INSERT INTO `" . DB_PREFIX . "ms_order` (ms_id,order_id, updated) VALUES ('" . $msOrder["rows"][0]["id"] . "','" . $order["order_id"] . "', '" . $order["date_modified"] . "')");
                    }
                }
            } else {
                if ($linkMode == self::MODE_LINK_CREATE_UPDATE && $this->ocVersion == self::OC_VERSION_2_0) {
                    $this->sendOrder($order);
                }
            }
        }
    }
    public function sendOrder($order)
    {
        $order_id = $order["order_id"];
        $agentSearch = $this->config->get("ms_integration_agent_search");
        $agent = $this->config->get("ms_integration_ms_agent");
        $reserve = $this->config->get("ms_integration_reserve");
        $store = $this->config->get("ms_integration_ms_store");
        $state = $this->config->get("ms_integration_ms_state");
        $vatEnabled = $this->config->get("ms_integration_ms_vatE");
        $vatIncluding = $this->config->get("ms_integration_ms_vatI");
        $applicable = $this->config->get("ms_integration_ms_applicable");
        $msShipping = $this->config->get("ms_integration_ms_shipping");
        $lang = $this->config->get("ms_integration_language");
        $orderName = $this->config->get("ms_integration_order_name");
        if (date("e") != "UTC") {
            $timeZoneOffset = 3 * 60 * 60 - date("Z");
        } else {
            $timeZoneOffset = 0;
        }
        if ($agent == "") {
            return false;
        }
        if ($state == "sync") {
            $states = $this->msGet("https://online.moysklad.ru/api/remap/1.1/entity/customerorder/metadata");
            $ocStates = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_status WHERE language_id='" . $lang . "'");
        }
        $linkCheck = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ms_order` WHERE order_id='" . $order_id . "' limit 1");
        if (0 < $linkCheck->num_rows) {
            return false;
        }
        $address = "";
        if ($order["shipping_country"] == "") {
            if ($order["payment_country"] != "") {
                $address .= $order["payment_country"] . ", ";
            }
        } else {
            $address .= $order["shipping_country"] . ", ";
        }
        if ($order["shipping_zone"] == "") {
            if ($order["payment_zone"] != "") {
                $address .= $order["payment_zone"] . ", ";
            }
        } else {
            $address .= $order["shipping_zone"] . ", ";
        }
        if ($order["shipping_postcode"] == "") {
            if ($order["payment_postcode"] != "") {
                $address .= $order["payment_postcode"] . ", ";
            }
        } else {
            $address .= $order["shipping_postcode"] . ", ";
        }
        if ($order["shipping_city"] == "") {
            if ($order["payment_city"] != "") {
                $address .= $order["payment_city"] . ", ";
            }
        } else {
            $address .= $order["shipping_city"] . ", ";
        }
        if ($order["shipping_address_1"] == "") {
            if ($order["payment_address_1"] != "" || $order["payment_address_2"] != "") {
                $address .= $order["payment_address_1"] . " " . $order["payment_address_2"];
            }
        } else {
            $address .= $order["shipping_address_1"] . " " . $order["shipping_address_2"];
        }
        $agentFirstName = $order["firstname"];
        $agentLastName = $order["lastname"];
        if ($agentFirstName == "") {
            $agentFirstName = $order["payment_firstname"];
        }
        if ($agentLastName == "") {
            $agentLastName = $order["payment_lastname"];
        }
        if ($agentFirstName == "") {
            $agentFirstName = $order["shipping_firstname"];
        }
        if ($agentLastName == "") {
            $agentLastName = $order["shipping_lastname"];
        }
        $name = $agentFirstName . " " . $agentLastName;
        if ($agent == "create") {
            $link = "";
            switch ($agentSearch) {
                case "fio":
                    $link = "https://online.moysklad.ru/api/remap/1.1/entity/counterparty?filter=" . urlencode("name=" . $name);
                    break;
                case "phone":
                    $link = "https://online.moysklad.ru/api/remap/1.1/entity/counterparty?filter=" . urlencode("phone=" . $order["telephone"]);
                    break;
                case "email":
                    $link = "https://online.moysklad.ru/api/remap/1.1/entity/counterparty?filter=" . urlencode("email=" . $order["email"]);
                    break;
            }
            $json = $this->msGet($link);
            $agent = "";
            if (0 < $json["meta"]["size"]) {
                $agent = $json["rows"][0]["id"];
            } else {
                if ($name == "" || $name == " ") {
                    if ($order["telephone"] != "") {
                        $name = $order["telephone"];
                    } else {
                        if ($order["email"] != "") {
                            $name = $order["email"];
                        } else {
                            $name = "Покупатель для заказа №" . $order["order_id"];
                        }
                    }
                }
                $agentData = array("name" => $name, "legalTitle" => $name, "externalCode" => $order["customer_id"] . "#" . $order["email"], "email" => $order["email"], "phone" => $order["telephone"], "actualAddress" => $address, "legalAddress" => $address, "companyType" => "individual", "tags" => array("клиент интернет-магазина " . parse_url(HTTPS_SERVER, PHP_URL_HOST)));
                $link = "https://online.moysklad.ru/api/remap/1.1/entity/counterparty";
                $result = $this->msPost($link, $agentData);
                $agent = $result["id"];
            }
        }
        $orderState = $state;
        if ($state == "sync") {
            foreach ($states["states"] as $msState) {
                foreach ($ocStates->rows as $status) {
                    if ($status["order_status_id"] == $order["order_status_id"] && $status["name"] == $msState["name"]) {
                        $orderState = $msState["id"];
                    }
                }
            }
        }
        $msData = array("organization" => array("meta" => array("href" => "https://online.moysklad.ru/api/remap/1.1/entity/organization/" . $this->config->get("ms_integration_ms_organization"), "type" => "organization", "mediaType" => "application/json")), "agent" => array("meta" => array("href" => "https://online.moysklad.ru/api/remap/1.1/entity/counterparty/" . $agent, "type" => "counterparty", "mediaType" => "application/json")), "description" => "Номер заказа: " . $order["order_id"] . "\n" . "Телефон.: " . str_replace("+", "", $order["telephone"]) . "\n" . "Имя: " . $name . "\n" . "Email: " . $order["email"] . "\n" . "Адрес: " . $address . "\n" . "Способ оплаты: " . $order["payment_method"] . "\n" . "Метод доставки: " . $order["shipping_method"] . "\n" . "Комментарий:" . $order["comment"], "externalCode" => $this->config->get("ms_integration_order_prefix") . $order["order_id"] . $this->config->get("ms_integration_order_suffix"), "moment" => date("Y-m-d H:i:s", strtotime($order["date_added"]) + $timeZoneOffset), "applicable" => $applicable ? true : false, "vatEnabled" => $vatEnabled ? true : false, "vatIncluded" => $vatIncluding ? true : false);
        if (!$orderName) {
            $msData["name"] = $this->config->get("ms_integration_order_prefix") . $order["order_id"] . $this->config->get("ms_integration_order_suffix");
        }
        if ($store != "") {
            $msData["store"] = array("meta" => array("href" => "https://online.moysklad.ru/api/remap/1.1/entity/store/" . $store, "type" => "store", "mediaType" => "application/json"));
        }
        if ($orderState != "sync" && $state != "") {
            $msData["state"] = array("meta" => array("href" => "https://online.moysklad.ru/api/remap/1.1/entity/customerorder/metadata/states/" . $orderState, "type" => "state", "mediaType" => "application/json"));
        }
        $orderTotals = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_total WHERE order_id = '" . $order["order_id"] . "'");
        $orderTotal = 0;
        $orderSubTotal = 0;
        $orderDiscount = 0;
        $orderShipping = 0;
        $orderTaxes = 0;
        foreach ($orderTotals->rows as $orderTotalTemp) {
            if ($orderTotalTemp["code"] == "total") {
                $orderTotal = $orderTotalTemp["value"];
                continue;
            }
            if ($orderTotalTemp["code"] == "sub_total") {
                $orderSubTotal = $orderTotalTemp["value"];
                continue;
            }
            if ($orderTotalTemp["value"] < 0) {
                $orderDiscount += abs($orderTotalTemp["value"]);
                continue;
            }
            if ($orderTotalTemp["code"] == "shipping") {
                $orderShipping += $orderTotalTemp["value"];
                continue;
            }
            if ($orderTotalTemp["code"] == "tax") {
                $orderTaxes += $orderTotalTemp["value"];
                continue;
            }
            if (0 < $orderTotalTemp["value"]) {
                $orderShipping += $orderTotalTemp["value"];
                continue;
            }
        }
        if (0 < $orderSubTotal) {
            $discountPct = abs($orderDiscount / $orderSubTotal * 100);
        } else {
            $discountPct = 0;
        }
        $order_product_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_product WHERE order_id = '" . (int) $order_id . "'");
        $msPositions = array();
        if (99 < $vatEnabled) {
            $vatEnabled = 99;
        }
        if ($vatEnabled < 0) {
            $vatEnabled = 0;
        }
        foreach ($order_product_query->rows as $product) {
            $options = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_option WHERE order_product_id='" . $product["order_product_id"] . "'");
            if (0 < $options->num_rows) {
                $optionsCount = $options->num_rows;
                $variantsCount = array();
                foreach ($options->rows as $option) {
                    $linkCheck = $this->db->query("SELECT * FROM " . DB_PREFIX . "ms_variant WHERE product_id='" . $product["product_id"] . "' AND product_option_value_id='" . $option["product_option_value_id"] . "'");
                    foreach ($linkCheck->rows as $optLink) {
                        if (!isset($variantsCount[$optLink["var_id"]])) {
                            $variantsCount[$optLink["var_id"]] = 1;
                        } else {
                            $variantsCount[$optLink["var_id"]]++;
                        }
                    }
                }
                $varId = "";
                foreach ($variantsCount as $key => $value) {
                    if ($value == $optionsCount) {
                        $varId = $key;
                        break;
                    }
                }
                if ($varId != "") {
                    $position = array("quantity" => (double) $product["quantity"], "reserve" => $reserve ? (double) $product["quantity"] : 0, "price" => (double) ($product["price"] * 100), "vat" => (double) $vatEnabled, "discount" => $discountPct, "assortment" => array("meta" => array("href" => "https://online.moysklad.ru/api/remap/1.2/entity/variant/" . $varId, "type" => "variant", "mediaType" => "application/json")));
                    $msPositions[] = $position;
                    continue;
                }
            }
            $linkCheck = $this->db->query("SELECT * FROM " . DB_PREFIX . "ms_product WHERE product_id = '" . (int) $product["product_id"] . "' limit 1");
            if (0 < $linkCheck->num_rows) {
                $position = array("quantity" => (double) $product["quantity"], "reserve" => $reserve ? (double) $product["quantity"] : 0, "price" => (double) ($product["price"] * 100), "vat" => (double) $vatEnabled, "discount" => abs($discountPct), "assortment" => array("meta" => array("href" => "https://online.moysklad.ru/api/remap/1.1/entity/" . $linkCheck->row["type"] . "/" . $linkCheck->row["ms_id"], "type" => $linkCheck->row["type"], "mediaType" => "application/json")));
                $msPositions[] = $position;
                continue;
            }
        }
        if ($msShipping && $msShipping != "") {
            $position = array("quantity" => 1, "price" => (double) ($orderShipping * 100), "assortment" => array("meta" => array("href" => "https://online.moysklad.ru/api/remap/1.1/entity/service/" . $msShipping, "type" => "service", "mediaType" => "application/json")));
            $msPositions[] = $position;
        }
        $chunkPositions = array_chunk($msPositions, 100);
        $msData["positions"] = $chunkPositions[0];
        $link = "https://online.moysklad.ru/api/remap/1.1/entity/customerorder";
        $res = $this->msPost($link, $msData);
        if (isset($res["id"])) {
            $this->db->query("INSERT INTO `" . DB_PREFIX . "ms_order` (ms_id,order_id, updated) VALUES ('" . $res["id"] . "','" . $order_id . "', '" . $order["date_modified"] . "')");
            for ($i = 1; $i <= count($chunkPositions); $i++) {
                if (isset($chunkPositions[$i])) {
                    $this->msPost($link . "/" . $res["id"] . "/positions", $chunkPositions[$i]);
                }
            }
        }
        return true;
    }
    public function updateOrder($order)
    {
        $msShipping = $this->config->get("ms_integration_ms_shipping");
        $vatEnabled = $this->config->get("ms_integration_ms_vatE");
        $reserve = $this->config->get("ms_integration_reserve");
        $lang = $this->config->get("ms_integration_language");
        $order_id = $order["order_id"];
        $linkCheck = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ms_order` WHERE order_id='" . $order_id . "' limit 1");
        if ($linkCheck->num_rows == 0) {
            return false;
        }
        $msOrderId = $linkCheck->row["ms_id"];
        if ($linkCheck->row["updated"] < $order["date_modified"]) {
            $orderTotals = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_total WHERE order_id = '" . $order["order_id"] . "'");
            $orderTotal = 0;
            $orderSubTotal = 0;
            $orderDiscount = 0;
            $orderShipping = 0;
            $orderTaxes = 0;
            foreach ($orderTotals->rows as $orderTotalTemp) {
                if ($orderTotalTemp["code"] == "total") {
                    $orderTotal = $orderTotalTemp["value"];
                    continue;
                }
                if ($orderTotalTemp["code"] == "sub_total") {
                    $orderSubTotal = $orderTotalTemp["value"];
                    continue;
                }
                if ($orderTotalTemp["value"] < 0) {
                    $orderDiscount += abs($orderTotalTemp["value"]);
                    continue;
                }
                if ($orderTotalTemp["code"] == "shipping") {
                    $orderShipping += $orderTotalTemp["value"];
                    continue;
                }
                if ($orderTotalTemp["code"] == "tax") {
                    $orderTaxes += $orderTotalTemp["value"];
                    continue;
                }
                if (0 < $orderTotalTemp["value"]) {
                    $orderShipping += $orderTotalTemp["value"];
                    continue;
                }
            }
            $discountPct = abs($orderDiscount / $orderSubTotal * 100);
            $order_product_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_product WHERE order_id = '" . (int) $order_id . "'");
            $msPositions = array();
            foreach ($order_product_query->rows as $product) {
                $options = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_option WHERE order_product_id='" . $product["order_product_id"] . "'");
                if (0 < $options->num_rows) {
                    $optionsCount = $options->num_rows;
                    $variantsCount = array();
                    foreach ($options->rows as $option) {
                        $linkCheck = $this->db->query("SELECT * FROM " . DB_PREFIX . "ms_variant WHERE product_id='" . $product["product_id"] . "' AND product_option_value_id='" . $option["product_option_value_id"] . "'");
                        foreach ($linkCheck->rows as $optLink) {
                            if (!isset($variantsCount[$optLink["var_id"]])) {
                                $variantsCount[$optLink["var_id"]] = 1;
                            } else {
                                $variantsCount[$optLink["var_id"]]++;
                            }
                        }
                    }
                    $varId = "";
                    foreach ($variantsCount as $key => $value) {
                        if ($value == $optionsCount) {
                            $varId = $key;
                            break;
                        }
                    }
                    if ($varId != "") {
                        $position = array("quantity" => (double) $product["quantity"], "reserve" => (double) $product["quantity"], "price" => (double) ($product["price"] * 100), "discount" => $discountPct, "vat" => (double) $vatEnabled, "assortment" => array("meta" => array("href" => "https://online.moysklad.ru/api/remap/1.2/entity/variant/" . $varId, "type" => "variant", "mediaType" => "application/json")));
                        $msPositions[] = $position;
                        continue;
                    }
                }
                $linkCheck = $this->db->query("SELECT * FROM " . DB_PREFIX . "ms_product WHERE product_id = '" . (int) $product["product_id"] . "' limit 1");
                if (0 < $linkCheck->num_rows) {
                    $position = array("quantity" => (double) $product["quantity"], "reserve" => $reserve ? (double) $product["quantity"] : 0, "price" => (double) ($product["price"] * 100), "discount" => abs($discountPct), "vat" => (double) $vatEnabled, "assortment" => array("meta" => array("href" => "https://online.moysklad.ru/api/remap/1.1/entity/" . $linkCheck->row["type"] . "/" . $linkCheck->row["ms_id"], "type" => $linkCheck->row["type"], "mediaType" => "application/json")));
                    $msPositions[] = $position;
                    continue;
                }
            }
            if ($msShipping && $msShipping != "") {
                $position = array("quantity" => 1, "price" => (double) ($orderShipping * 100), "assortment" => array("meta" => array("href" => "https://online.moysklad.ru/api/remap/1.1/entity/service/" . $msShipping, "type" => "service", "mediaType" => "application/json")));
                $msPositions[] = $position;
            }
            $chunkPositions = array_chunk($msPositions, 100);
            if (0 < count($msPositions)) {
                $msDataUpdate = array("positions" => $chunkPositions[0]);
            }
            if ($this->config->get("ms_integration_status_sync_type") == "2") {
                $states = $this->msGet("https://online.moysklad.ru/api/remap/1.1/entity/customerorder/metadata");
                $ocState = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_status WHERE language_id='" . $lang . "' AND order_status_id='" . $order["order_status_id"] . "'");
                $orderState = "";
                if (0 < $ocState->num_rows) {
                    foreach ($states["states"] as $msState) {
                        if ($ocState->row["name"] == $msState["name"]) {
                            $orderState = $msState["id"];
                        }
                    }
                }
                if ($orderState != "") {
                    $msDataUpdate["state"] = array("meta" => array("href" => "https://online.moysklad.ru/api/remap/1.1/entity/customerorder/metadata/states/" . $orderState, "type" => "state", "mediaType" => "application/json"));
                }
            }
            $this->msPut("https://online.moysklad.ru/api/remap/1.1/entity/customerorder/" . $msOrderId, $msDataUpdate);
            for ($i = 1; $i <= count($chunkPositions); $i++) {
                if (isset($chunkPositions[$i])) {
                    $this->msPost("https://online.moysklad.ru/api/remap/1.1/entity/customerorder/" . $msOrderId . "/positions", $chunkPositions[$i]);
                }
            }
        }
    }
    public function updateStates()
    {
        if ($this->config->get("ms_integration_status_sync_type") != "1") {
            return NULL;
        }
        $this->load->model("setting/setting");
        $this->load->model("checkout/order");
        $offset = date("Z") - 3 * 60 * 60;
        $cronTime = $this->config->get("ms_integration_cron_time");
        if ($cronTime == NULL || $cronTime <= 0) {
            $cronTime = 10;
        }
        $cronOffset = $cronTime * 60 * 3;
        $date = date("Y-m-d H:i:s", time() - $offset - $cronOffset);
        $orderMetaData = $this->msGet("https://online.moysklad.ru/api/remap/1.1/entity/customerorder/metadata");
        $lang = $this->config->get("ms_integration_language");
        $query = $this->db->query("SELECT order_status_id, name FROM " . DB_PREFIX . "order_status WHERE language_id = '" . (int) $lang . "' ORDER BY name");
        $order_status_data = $query->rows;
        $link = "https://online.moysklad.ru/api/remap/1.1/entity/customerorder?filter=" . urlencode("updated>=" . $date);
        $msOrderRes = $this->msGet($link);
        $size = $msOrderRes["meta"]["size"];
        $pages = ceil($size / 100);
        for ($page = 0; $page < $pages; $page++) {
            if ($page != 0) {
                $link = "https://online.moysklad.ru/api/remap/1.1/entity/customerorder?limit=100&offset=" . $page * 100 . "&filter=" . urlencode("updated>=" . $date);
                $msOrderRes = $this->msGet($link);
            }
            if (empty($msOrderRes["rows"])) {
                break;
            }
            foreach ($msOrderRes["rows"] as $msOrder) {
                $query = $this->db->query("SELECT * FROM `" . DB_PREFIX . "ms_order` WHERE ms_id='" . $msOrder["id"] . "'");
                if (0 < $query->num_rows) {
                    $order_id = $query->row["order_id"];
                    $newStatusName = "";
                    $newStatusID = 0;
                    $stateHref = $msOrder["state"]["meta"]["href"];
                    $tmpx = explode("/", $stateHref);
                    $tmp_ms_status = $tmpx[10];
                    foreach ($orderMetaData["states"] as $msState) {
                        if ($msState["id"] == $tmp_ms_status) {
                            $newStatusName = $msState["name"];
                        }
                    }
                    if ($newStatusName == "") {
                        continue;
                    }
                    foreach ($order_status_data as $order_status) {
                        if ($order_status["name"] == $newStatusName) {
                            $newStatusID = $order_status["order_status_id"];
                        }
                    }
                    if ($newStatusID == 0) {
                        continue;
                    }
                    $order = $this->model_checkout_order->getOrder($order_id);
                    if ($order["order_status_id"] == $newStatusID) {
                        continue;
                    }
                    $this->model_checkout_order->addOrderHistory($order_id, $newStatusID);
                }
            }
        }
    }
    private function initCurl($msLink)
    {
        if (!$this->checkLicence()) {
            $this->logging("Лезензия не действительна");
            return false;
        }
        if (80 < $this->msQueryCount) {
            sleep(5);
            $this->msQueryCount = 0;
        }
        $curl = curl_init();
        $AUTH_DATA = $this->config->get("ms_integration_ms_login") . ":" . $this->config->get("ms_integration_ms_password");
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_URL, $msLink);
        curl_setopt($curl, CURLOPT_USERPWD, $AUTH_DATA);
        curl_setopt($curl, CURLOPT_HEADER, false);
        curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
        $this->msQueryCount++;
        return $curl;
    }
    public function msGet($msLink)
    {
        $curl = $this->initCurl($msLink);
        if (!$curl) {
            return false;
        }
        curl_setopt($curl, CURLOPT_POST, 0);
        $out = curl_exec($curl);
        curl_close($curl);
        $json = json_decode($out, JSON_UNESCAPED_UNICODE);
        if (isset($json["errors"])) {
            foreach ($json["errors"] as $error) {
                $this->logging("Ошибка при обращение в МС: " . $error["code"] . " - " . $error["error"] . " link: " . $msLink);
            }
        }
        unset($out);
        return $json;
    }
    public function msGetImage($msLink)
    {
        $curl = $this->initCurl($msLink);
        if (!$curl) {
            return false;
        }
        curl_setopt($curl, CURLOPT_POST, 0);
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
        $content = curl_exec($curl);
        $info = curl_getinfo($curl);
        curl_close($curl);
        $response = $info;
        if ($response["http_code"] == 301 || $response["http_code"] == 302) {
            $headers = get_headers($response["redirect_url"]);
            foreach ($headers as $value) {
                $out = file_get_contents($response["redirect_url"]);
                return $out;
            }
        }
        return $content;
    }
    public function msPost($msLink, $data = array())
    {
        $entityData = json_encode($data);
        $curl = $this->initCurl($msLink);
        if (!$curl) {
            return false;
        }
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $entityData);
        $out = curl_exec($curl);
        curl_close($curl);
        $json = json_decode($out, JSON_UNESCAPED_UNICODE);
        if (isset($json["errors"])) {
            foreach ($json["errors"] as $error) {
                $this->logging("Ошибка при создании объекта в МС: " . $error["code"] . " - " . $error["error"] . " link: " . $msLink);
            }
        }
        unset($out);
        return $json;
    }
    public function msPut($msLink, $data = array())
    {
        $entityData = json_encode($data);
        $curl = $this->initCurl($msLink);
        if (!$curl) {
            return false;
        }
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
        curl_setopt($curl, CURLOPT_POSTFIELDS, $entityData);
        $out = curl_exec($curl);
        curl_close($curl);
        $json = json_decode($out, JSON_UNESCAPED_UNICODE);
        if (isset($json["errors"])) {
            foreach ($json["errors"] as $error) {
                $this->logging("Ошибка при обновление объекта в МС: " . $error["code"] . " - " . $error["error"] . " link: " . $msLink);
            }
        }
        unset($out);
        return $json;
    }
    public function logging($message)
    {
        if (33554432 < filesize(DIR_LOGS . "c_log.log")) {
            rename(DIR_LOGS . "c_log.log", DIR_LOGS . "c_log_old.log");
            $hand = fopen(DIR_LOGS . "c_log.log", "w+");
        } else {
            $hand = fopen(DIR_LOGS . "c_log.log", "a+");
        }
        fwrite($hand, date("d-m-Y H:i:s") . " - " . $message . "\n");
        fclose($hand);
    }
    private function escape($value)
    {
        return htmlspecialchars($this->db->escape($value));
    }
    private function slugify($str)
    {
        $str = mb_convert_encoding((string) $str, "UTF-8", mb_list_encodings());
        $char_map = array("А" => "A", "Б" => "B", "В" => "V", "Г" => "G", "Д" => "D", "Е" => "E", "Ё" => "Yo", "Ж" => "Zh", "З" => "Z", "И" => "I", "Й" => "J", "К" => "K", "Л" => "L", "М" => "M", "Н" => "N", "О" => "O", "П" => "P", "Р" => "R", "С" => "S", "Т" => "T", "У" => "U", "Ф" => "F", "Х" => "H", "Ц" => "C", "Ч" => "Ch", "Ш" => "Sh", "Щ" => "Sh", "Ъ" => "", "Ы" => "Y", "Ь" => "", "Э" => "E", "Ю" => "Yu", "Я" => "Ya", "а" => "a", "б" => "b", "в" => "v", "г" => "g", "д" => "d", "е" => "e", "ё" => "yo", "ж" => "zh", "з" => "z", "и" => "i", "й" => "j", "к" => "k", "л" => "l", "м" => "m", "н" => "n", "о" => "o", "п" => "p", "р" => "r", "с" => "s", "т" => "t", "у" => "u", "ф" => "f", "х" => "h", "ц" => "c", "ч" => "ch", "ш" => "sh", "щ" => "sh", "ъ" => "", "ы" => "y", "ь" => "", "э" => "e", "ю" => "yu", "я" => "ya", "Є" => "Ye", "І" => "I", "Ї" => "Yi", "Ґ" => "G", "є" => "ye", "і" => "i", "ї" => "yi", "ґ" => "g");
        $str = str_replace(array("\"", "'"), "", $str);
        $str = str_replace(array_keys($char_map), $char_map, $str);
        $str = preg_replace("/[^\\p{L}\\p{Nd}]+/u", "-", $str);
        $str = preg_replace("/(" . preg_quote("-", "/") . "){2,}/", "\$1", $str);
        $str = trim($str, "-");
        $str = $this->checkSeo($str);
        return mb_strtolower($str, "UTF-8");
    }
    private function checkSeo($str)
    {
        if ($this->ocVersion == self::OC_VERSION_3_0) {
            $checkSEO = $this->db->query("SELECT * FROM " . DB_PREFIX . "seo_url WHERE keyword='" . $str . "'");
        } else {
            $checkSEO = $this->db->query("SELECT * FROM " . DB_PREFIX . "url_alias WHERE keyword = '" . $str . "'");
        }
        if (0 < $checkSEO->num_rows) {
            $str .= rand(0, 9);
            return $this->checkSeo($str);
        }
        return $str;
    }
    public function checkLicence()
    {
        // $licence = $this->config->get("ms_integration_licence");
        // $key = "X+QUZh6TeQYimBF0k2mpB_vZLXxmCBk&PEDub#=NsRlk?YY&Hu33E2hDJT6TG2thM?l.?s&zJXHCGX^FElKxVf+mtgH_K7IME2yZv_AzZ7&,2EK&VlA7+Av^4FL85(B~";
        // $c = base64_decode($licence);
        // $ivlen = openssl_cipher_iv_length($cipher = "AES-128-CBC");
        // $iv = substr($c, 0, $ivlen);
        // $hmac = substr($c, $ivlen, $sha2len = 32);
        // $licence_raw = substr($c, $ivlen + $sha2len);
        // $data = openssl_decrypt($licence_raw, $cipher, $key, $options = OPENSSL_RAW_DATA, $iv);
        // if (!$data) {
        //     return array("licence" => false);
        // }
        // $calcmac = hash_hmac("sha256", $licence_raw, $key, $as_binary = true);
        return array("licence" => true);
        
        // if (hash_equals($hmac, $calcmac)) {
        //     $data = json_decode($data, true);
        //     $licenceDomainAscii = $data["domain"];
        //     $licenceDomainUtf = $data["domain"];
        //     if (defined("INTL_IDNA_VARIANT_UTS46")) {
        //         if (function_exists("idn_to_ascii")) {
        //             $licenceDomainAscii = str_replace("www.", "", idn_to_ascii($licenceDomainAscii, 0, INTL_IDNA_VARIANT_UTS46));
        //         }
        //         if (function_exists("idn_to_utf8")) {
        //             $licenceDomainUtf = str_replace("www.", "", idn_to_utf8($licenceDomainUtf, 0, INTL_IDNA_VARIANT_UTS46));
        //         }
        //     } else {
        //         if (function_exists("idn_to_ascii")) {
        //             $licenceDomainAscii = str_replace("www.", "", idn_to_ascii($licenceDomainAscii));
        //         }
        //         if (function_exists("idn_to_utf8")) {
        //             $licenceDomainUtf = str_replace("www.", "", idn_to_utf8($licenceDomainUtf));
        //         }
        //     }
        //     if ($this->ocVersion == self::OC_VERSION_2_0) {
        //         $serverDomain = str_replace("www.", "", parse_url(HTTPS_SERVER, PHP_URL_HOST));
        //     } else {
        //         $serverDomain = str_replace("www.", "", parse_url($this->config->get("site_ssl"), PHP_URL_HOST));
        //     }
        //     if ($licenceDomainAscii == $serverDomain || $licenceDomainUtf == $serverDomain) {
        //         if (time() - $data["durability"] < $data["date"]) {
        //             if ($data["durability"] / 24 / 60 / 60 < 30) {
        //                 return array("licence" => true, "trial" => date("d.m.Y", $data["date"] + $data["durability"]));
        //             }
        //             return array("licence" => true);
        //         }
        //         return array("licence" => false, "message" => "Срок действия лицензии истек. Срок действия лицензии до " . date("d.m.Y", $data["date"] + $data["durability"]));
        //     }
        //     return array("licence" => false, "message" => "Лицензия выписана для домена: " . $licenceDomainUtf . "<br>Ваш домен: " . $serverDomain);
        // }
        // return array("licence" => false);
    }
    public function getOcVersion()
    {
        return $this->ocVersion;
    }
    public function generateToken()
    {
        $chars = "qazxswedcvfrtgbnhyujmkiolp1234567890QAZXSWEDCVFRTGBNHYUJMKIOLP";
        $max = 8;
        $size = StrLen($chars) - 1;
        $token = NULL;
        while ($max--) {
            $token .= $chars[rand(0, $size)];
        }
        return $token;
    }
}

?>