From f2a96e92d1537d83672687247ec08f9bae1f51e7 Mon Sep 17 00:00:00 2001 From: max-baranikov Date: Mon, 28 Dec 2020 14:51:01 +0300 Subject: [PATCH] Using generators in the ICML generation process --- retailcrm/lib/RetailcrmCatalog.php | 493 ++++++++++++++----------- tests/lib/RetailcrmCatalogTest.php | 2 +- tests/lib/RetailcrmHistoryTest.php | 2 +- tests/lib/RetailcrmInventoriesTest.php | 5 +- 4 files changed, 278 insertions(+), 224 deletions(-) diff --git a/retailcrm/lib/RetailcrmCatalog.php b/retailcrm/lib/RetailcrmCatalog.php index eb18ca6..560bed0 100644 --- a/retailcrm/lib/RetailcrmCatalog.php +++ b/retailcrm/lib/RetailcrmCatalog.php @@ -1,4 +1,5 @@ - * @copyright 2020 DIGITAL RETAIL TECHNOLOGIES SL - * @license https://opensource.org/licenses/MIT The MIT License + * @author DIGITAL RETAIL TECHNOLOGIES SL + * @copyright 2020 DIGITAL RETAIL TECHNOLOGIES SL + * @license https://opensource.org/licenses/MIT The MIT License * * Don't forget to prefix your containers with your own identifier * to avoid any conflicts with others containers. @@ -40,35 +41,76 @@ class RetailcrmCatalog public $default_lang; public $default_currency; public $default_country; + public $protocol; + public $version; + public $link; + public $home_category; public function __construct() { - $this->default_lang = (int) Configuration::get('PS_LANG_DEFAULT'); - $this->default_currency = (int) Configuration::get('PS_CURRENCY_DEFAULT'); - $this->default_country = (int) Configuration::get('PS_COUNTRY_DEFAULT'); + $this->default_lang = (int)Configuration::get('PS_LANG_DEFAULT'); + $this->default_currency = (int)Configuration::get('PS_CURRENCY_DEFAULT'); + $this->default_country = (int)Configuration::get('PS_COUNTRY_DEFAULT'); + + $this->protocol = (Configuration::get('PS_SSL_ENABLED')) ? "https://" : "http://"; + $this->version = substr(_PS_VERSION_, 0, 3); + $this->link = new Link(); + $this->home_category = Configuration::get('PS_HOME_CATEGORY'); } public function getData() { - $version = substr(_PS_VERSION_, 0, 3); - $versionSplit = explode('.', $version); - $id_lang = (int) Configuration::get('PS_LANG_DEFAULT'); - $currency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT')); - $shop_url = (Configuration::get('PS_SSL_ENABLED') ? _PS_BASE_URL_SSL_ : _PS_BASE_URL_); - $protocol = (Configuration::get('PS_SSL_ENABLED')) ? "https://" : "http://"; - $homeCategory = Configuration::get('PS_HOME_CATEGORY'); + return array($this->getCategories(), $this->getOffers()); + } - $items = array(); + public function getCategories() + { $categories = array(); + $categoriesIds = array(); + + $types = Category::getCategories($this->default_lang, true, false); + + foreach ($types as $category) { + $categoryId = (empty($category['id_category']) && isset($category['id'])) + ? $category['id'] : $category['id_category']; + + if (!self::isCategoryActive(new Category($categoryId))) { + + continue; + } + + $picture = $this->link->getCatImageLink($category['link_rewrite'], $categoryId, 'category_default'); + + $categoriesIds[] = $categoryId; + $categories[] = array( + 'id' => $categoryId, + 'parentId' => self::getParentCategoryId($categoryId, $category['id_parent']), + 'name' => htmlspecialchars($category['name']), + 'picture' => $picture ? $this->protocol . $picture : '' + ); + } + + foreach ($categories as $key => $innerCategory) { + if (isset($innerCategory['parentId']) + && !empty($innerCategory['parentId']) + && !in_array($innerCategory['parentId'], $categoriesIds) + ) { + $innerCategory['parentId'] = $this->home_category; + $categories[$key] = $innerCategory; + } + } + + return $categories; + } + + public function getOffers() + { + $id_lang = $this->default_lang; + $homeCategory = $this->home_category; + $inactiveCategories = array(); $categoriesIds = array(); - if ($currency->iso_code == 'RUB') { - $currency->iso_code = 'RUR'; - } - - $currencies = Currency::getCurrencies(); - $link = new Link(); $types = Category::getCategories($id_lang, true, false); foreach ($types as $category) { @@ -83,226 +125,237 @@ class RetailcrmCatalog continue; } - $picture = $link->getCatImageLink($category['link_rewrite'], $categoryId, 'category_default'); - $categoriesIds[] = $categoryId; - $categories[] = array( - 'id' => $categoryId, - 'parentId' => self::getParentCategoryId($categoryId, $category['id_parent']), - 'name' => $category['name'], - 'picture' => $picture ? $protocol . $picture : '' - ); } - foreach ($categories as $key => $innerCategory) { - if (isset($innerCategory['parentId']) - && !empty($innerCategory['parentId']) - && !in_array($innerCategory['parentId'], $categoriesIds) - ) { - $innerCategory['parentId'] = $homeCategory; - $categories[$key] = $innerCategory; - } - } + $limit = 2000; + $start = 0; + $count = self::getProductsCount($id_lang); - $products = Product::getProducts($id_lang, 0, 0, 'name', 'asc'); + if ($count > 0) + do { + $products = Product::getProducts($id_lang, $start, $limit, 'name', 'asc'); - foreach ($products AS $product) { - $category = $product['id_category_default']; + foreach ($products as $product) { + $category = $product['id_category_default']; - if (!in_array($category, $categoriesIds)) { - continue; - } - - $currentProductCategories = Product::getProductCategories($product['id_product']); - $categoriesLeft = array_filter( - $currentProductCategories, - function ($val) use ($inactiveCategories, $categoriesIds, $homeCategory) { - if ($val == $homeCategory) { - return false; + if (!in_array($category, $categoriesIds)) { + continue; } - if (in_array($val, $inactiveCategories)) { - return false; - } + $currentProductCategories = Product::getProductCategories($product['id_product']); + $categoriesLeft = array_filter( + $currentProductCategories, + function ($val) use ($inactiveCategories, $categoriesIds, $homeCategory) { + if ($val == $homeCategory) { + return false; + } - return in_array($val, $categoriesIds); - } - ); + if (in_array($val, $inactiveCategories)) { + return false; + } - if (empty($categoriesLeft)) { - continue; - } - - if ($version == "1.3") { - $available_for_order = $product['active'] && $product['quantity']; - } else { - $available_for_order = $product['active'] && $product['available_for_order']; - } - - $crewrite = Category::getLinkRewrite($product['id_category_default'], $id_lang); - $url = $link->getProductLink($product['id_product'], $product['link_rewrite'], $crewrite); - - if (!empty($product['wholesale_price'])) { - $purchasePrice = round($product['wholesale_price'], 2); - } else { - $purchasePrice = null; - } - - $price = !empty($product['rate']) - ? round($product['price'], 2) + (round($product['price'], 2) * $product['rate'] / 100) - : round($product['price'], 2) - ; - - if (!empty($product['manufacturer_name'])) { - $vendor = $product['manufacturer_name']; - } else { - $vendor = null; - } - - if (!empty($product['reference'])) { - $article = htmlspecialchars($product['reference']); - } else { - $article = null; - } - - $weight = round($product['weight'], 2); - if (empty($weight)) { - $weight = null; - } - - $width = round($product['width'], 3); - $height = round($product['height'], 3); - $depth = round($product['depth'], 3); - - if (!empty($width) && !empty($height)) { - $dimensions = implode('/', array($width, $height, $depth)); - } else { - $dimensions = null; - } - - $productForCombination = new Product($product['id_product']); - - $offers = Product::getProductAttributesIds($product['id_product']); - - if (!empty($offers)) { - foreach($offers as $offer) { - $combinations = $productForCombination->getAttributeCombinationsById($offer['id_product_attribute' ], $id_lang); - - if (!empty($combinations)) { - foreach ($combinations as $combination) { - $arSet = array( - 'group_name' => $combination['group_name'], - 'attribute' => $combination['attribute_name'], - ); - - $arComb[] = $arSet; + return in_array($val, $categoriesIds); } - } - - $pictures = array(); - $covers = Image::getImages($id_lang, $product['id_product'], $offer['id_product_attribute']); - - foreach ($covers as $cover) { - $picture = $protocol . $link->getImageLink($product['link_rewrite'], $product['id_product'] . '-' . $cover['id_image'], 'large_default'); - $pictures[] = $picture; - } - - if (!$pictures) { - $image = Image::getCover($product['id_product']); - $picture = $protocol . $link->getImageLink($product['link_rewrite'], $image['id_image'], 'large_default'); - $pictures[] = $picture; - } - - if ($version == "1.3") { - $quantity = $product['quantity']; - } else { - $quantity = (int) StockAvailable::getQuantityAvailableByProduct($product['id_product'], $offer['id_product_attribute']); - } - - $offerCombination = new Combination($offer['id_product_attribute']); - - $offerCombinationPrice = !empty($product['rate']) - ? round($offerCombination->price, 2) + (round($offerCombination->price, 2) * $product['rate'] / 100) - : round($offerCombination->price, 2); - - $offerPrice = round($offerCombinationPrice, 2) + $price; - $offerPrice = $offerPrice > 0 ? $offerPrice : $price; - - if ($offerCombination->wholesale_price > 0) { - $offerPurchasePrice = round($offerCombination->wholesale_price, 2); - } else { - $offerPurchasePrice = $purchasePrice; - } - - if (!empty($offerCombination->reference)) { - $offerArticle = htmlspecialchars($offerCombination->reference); - } else { - $offerArticle = $article; - } - - $item = array( - 'id' => $product['id_product'] . '#' . $offer['id_product_attribute'], - 'productId' => $product['id_product'], - 'productActivity' => ($available_for_order) ? 'Y' : 'N', - 'name' => htmlspecialchars(strip_tags(Product::getProductName($product['id_product'], $offer['id_product_attribute']))), - 'productName' => htmlspecialchars(strip_tags($product['name'])), - 'categoryId' => array($category), - 'picture' => $pictures, - 'url' => $url, - 'quantity' => $quantity > 0 ? $quantity : 0, - 'purchasePrice' => $offerPurchasePrice, - 'price' => round($offerPrice, 2), - 'vendor' => $vendor, - 'article' => $offerArticle, - 'weight' => $weight, - 'dimensions' => $dimensions ); - if (!empty($combinations)) { - foreach ($arComb as $itemComb) { - $item[mb_strtolower($itemComb['group_name'])] = htmlspecialchars($itemComb['attribute']); - } + if (empty($categoriesLeft)) { + continue; } - $items[] = $item; - } - } else { - $pictures = array(); - $covers = Image::getImages($id_lang, $product['id_product'], null); - foreach($covers as $cover) { - $picture = $protocol . $link->getImageLink($product['link_rewrite'], $product['id_product'] . '-' . $cover['id_image'], 'large_default'); - $pictures[] = $picture; + if ($this->version == "1.3") { + $available_for_order = $product['active'] && $product['quantity']; + } else { + $available_for_order = $product['active'] && $product['available_for_order']; + } + + $crewrite = Category::getLinkRewrite($product['id_category_default'], $id_lang); + $url = $this->link->getProductLink($product['id_product'], $product['link_rewrite'], $crewrite); + + if (!empty($product['wholesale_price'])) { + $purchasePrice = round($product['wholesale_price'], 2); + } else { + $purchasePrice = null; + } + + $price = !empty($product['rate']) + ? round($product['price'], 2) + (round($product['price'], 2) * $product['rate'] / 100) + : round($product['price'], 2); + + if (!empty($product['manufacturer_name'])) { + $vendor = $product['manufacturer_name']; + } else { + $vendor = null; + } + + if (!empty($product['reference'])) { + $article = htmlspecialchars($product['reference']); + } else { + $article = null; + } + + $weight = round($product['weight'], 2); + if ($weight === 0.0) { + $weight = null; + } + + $width = round($product['width'], 3); + $height = round($product['height'], 3); + $depth = round($product['depth'], 3); + + if ($width !== 0.0 && $height !== 0.0) { + $dimensions = implode('/', array($width, $height, $depth)); + } else { + $dimensions = null; + } + + $offers = Product::getProductAttributesIds($product['id_product']); + + if (!empty($offers)) { + $productForCombination = new Product($product['id_product']); + + foreach ($offers as $offer) { + $combinations = $productForCombination->getAttributeCombinationsById($offer['id_product_attribute'], $id_lang); + + if (!empty($combinations)) { + foreach ($combinations as $combination) { + $arSet = array( + 'group_name' => $combination['group_name'], + 'attribute' => $combination['attribute_name'], + ); + + $arComb[] = $arSet; + } + } + + $pictures = array(); + $covers = Image::getImages($id_lang, $product['id_product'], $offer['id_product_attribute']); + + foreach ($covers as $cover) { + $picture = $this->protocol . $this->link->getImageLink($product['link_rewrite'], $product['id_product'] . '-' . $cover['id_image'], 'large_default'); + $pictures[] = $picture; + } + + if (!$pictures) { + $image = Image::getCover($product['id_product']); + $picture = $this->protocol . $this->link->getImageLink($product['link_rewrite'], $image['id_image'], 'large_default'); + $pictures[] = $picture; + } + + if ($this->version == "1.3") { + $quantity = $product['quantity']; + } else { + $quantity = (int)StockAvailable::getQuantityAvailableByProduct($product['id_product'], $offer['id_product_attribute']); + } + + $offerCombination = new Combination($offer['id_product_attribute']); + + $offerCombinationPrice = !empty($product['rate']) + ? round($offerCombination->price, 2) + (round($offerCombination->price, 2) * $product['rate'] / 100) + : round($offerCombination->price, 2); + + $offerPrice = round($offerCombinationPrice, 2) + $price; + $offerPrice = $offerPrice > 0 ? $offerPrice : $price; + + if ($offerCombination->wholesale_price > 0) { + $offerPurchasePrice = round($offerCombination->wholesale_price, 2); + } else { + $offerPurchasePrice = $purchasePrice; + } + + if (!empty($offerCombination->reference)) { + $offerArticle = htmlspecialchars($offerCombination->reference); + } else { + $offerArticle = $article; + } + + $item = array( + 'id' => $product['id_product'] . '#' . $offer['id_product_attribute'], + 'productId' => $product['id_product'], + 'productActivity' => ($available_for_order) ? 'Y' : 'N', + 'name' => htmlspecialchars(strip_tags(Product::getProductName($product['id_product'], $offer['id_product_attribute']))), + 'productName' => htmlspecialchars(strip_tags($product['name'])), + 'categoryId' => array($category), + 'picture' => $pictures, + 'url' => $url, + 'quantity' => $quantity > 0 ? $quantity : 0, + 'purchasePrice' => $offerPurchasePrice, + 'price' => round($offerPrice, 2), + 'vendor' => $vendor, + 'article' => $offerArticle, + 'weight' => $weight, + 'dimensions' => $dimensions + ); + + if (!empty($combinations)) { + foreach ($arComb as $itemComb) { + $item[mb_strtolower($itemComb['group_name'])] = htmlspecialchars($itemComb['attribute']); + } + } + + yield $item; + } + } else { + + $pictures = array(); + $covers = Image::getImages($id_lang, $product['id_product'], null); + foreach ($covers as $cover) { + $picture = $this->protocol . $this->link->getImageLink($product['link_rewrite'], $product['id_product'] . '-' . $cover['id_image'], 'large_default'); + $pictures[] = $picture; + } + + if ($this->version == "1.3") { + $quantity = $product['quantity']; + } else { + $quantity = (int)StockAvailable::getQuantityAvailableByProduct($product['id_product']); + } + + yield array( + 'id' => $product['id_product'], + 'productId' => $product['id_product'], + 'productActivity' => ($available_for_order) ? 'Y' : 'N', + 'name' => htmlspecialchars(strip_tags($product['name'])), + 'productName' => htmlspecialchars(strip_tags($product['name'])), + 'categoryId' => array($category), + 'picture' => $pictures, + 'url' => $url, + 'quantity' => $quantity > 0 ? $quantity : 0, + 'purchasePrice' => round($purchasePrice, 2), + 'price' => $price, + 'vendor' => $vendor, + 'article' => $article, + 'weight' => $weight, + 'dimensions' => $dimensions + ); + } } - if ($version == "1.3") { - $quantity = $product['quantity']; - } else { - $quantity = (int) StockAvailable::getQuantityAvailableByProduct($product['id_product']); - } + $start += $limit; + } while ($start < $count && count($products) > 0); + } - $item = array( - 'id' => $product['id_product'], - 'productId' => $product['id_product'], - 'productActivity' => ($available_for_order) ? 'Y' : 'N', - 'name' => htmlspecialchars(strip_tags($product['name'])), - 'productName' => htmlspecialchars(strip_tags($product['name'])), - 'categoryId' => array($category), - 'picture' => $pictures, - 'url' => $url, - 'quantity' => $quantity > 0 ? $quantity : 0, - 'purchasePrice' => round($purchasePrice, 2), - 'price' => $price, - 'vendor' => $vendor, - 'article' => $article, - 'weight' => $weight, - 'dimensions' => $dimensions - ); - - $items[] = $item; - } + private static function getProductsCount( + $id_lang, + Context $context = null + ) + { + if (!$context) { + $context = Context::getContext(); } - return array($categories, $items); + $front = true; + if (!in_array($context->controller->controller_type, array('front', 'modulefront'))) { + $front = false; + } + + $sql = 'SELECT COUNT(product_shop.`id_product`) AS nb + FROM `' . _DB_PREFIX_ . 'product` p + ' . Shop::addSqlAssociation('product', 'p') . ' + LEFT JOIN `' . _DB_PREFIX_ . 'product_lang` pl ON (p.`id_product` = pl.`id_product` ' . Shop::addSqlRestrictionOnLang('pl') . ') + WHERE pl.`id_lang` = ' . (int)$id_lang . + ($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : ''); + + return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql); } /** diff --git a/tests/lib/RetailcrmCatalogTest.php b/tests/lib/RetailcrmCatalogTest.php index 3ceb442..790360a 100644 --- a/tests/lib/RetailcrmCatalogTest.php +++ b/tests/lib/RetailcrmCatalogTest.php @@ -21,7 +21,7 @@ class RetailcrmCatalogTest extends RetailcrmTestCase $products = $this->data[1]; $this->assertNotEmpty($categories); - $this->assertNotEmpty($products); + $this->assertTrue($products->valid()); foreach ($categories as $category) { $this->assertNotEmpty($category); diff --git a/tests/lib/RetailcrmHistoryTest.php b/tests/lib/RetailcrmHistoryTest.php index 40e00e9..d9e872c 100644 --- a/tests/lib/RetailcrmHistoryTest.php +++ b/tests/lib/RetailcrmHistoryTest.php @@ -26,7 +26,7 @@ class RetailcrmHistoryTest extends RetailcrmTestCase $catalog = new RetailcrmCatalog(); $data = $catalog->getData(); - $this->product = $data[1][0]; + $this->product = $data[1]->current(); Configuration::updateValue('RETAILCRM_API_DELIVERY_DEFAULT', 2); Configuration::updateValue('RETAILCRM_API_PAYMENT_DEFAULT', 'bankwire'); diff --git a/tests/lib/RetailcrmInventoriesTest.php b/tests/lib/RetailcrmInventoriesTest.php index a890a73..c587de6 100644 --- a/tests/lib/RetailcrmInventoriesTest.php +++ b/tests/lib/RetailcrmInventoriesTest.php @@ -25,8 +25,9 @@ class RetailcrmInventoriesTest extends RetailcrmTestCase $catalog = new RetailcrmCatalog(); $data = $catalog->getData(); - $this->product1 = $data[1][0]; - $this->product2 = $data[1][1]; + $this->product1 = $data[1]->current(); + $data[1]->next(); + $this->product2 = $data[1]->current(); } /**