diff --git a/Config/module.xml b/Config/module.xml
index 73ffb79..d9271c2 100644
--- a/Config/module.xml
+++ b/Config/module.xml
@@ -13,7 +13,7 @@
en_USfr_FR
- 3.0.0
+ 3.0.1Bertrand TOURLONIAS
diff --git a/Config/routing.xml b/Config/routing.xml
index e8f7a94..938dd12 100644
--- a/Config/routing.xml
+++ b/Config/routing.xml
@@ -65,6 +65,10 @@
GoogleShoppingXml\Controller\GoogleFieldAssociationController::setEanRuleAction
+
+ GoogleShoppingXml\Controller\GoogleFieldAssociationController::setCompatibilitySqlAction
+
+
diff --git a/Controller/GoogleFieldAssociationController.php b/Controller/GoogleFieldAssociationController.php
index 579ebdb..805ce9f 100644
--- a/Controller/GoogleFieldAssociationController.php
+++ b/Controller/GoogleFieldAssociationController.php
@@ -2,6 +2,7 @@
namespace GoogleShoppingXml\Controller;
+use GoogleShoppingXml\Form\CompatibilitySqlForm;
use GoogleShoppingXml\GoogleShoppingXml;
use GoogleShoppingXml\Model\GoogleshoppingxmlGoogleFieldAssociation;
use GoogleShoppingXml\Model\GoogleshoppingxmlGoogleFieldAssociationQuery;
@@ -9,7 +10,9 @@
use Thelia\Core\HttpFoundation\Request;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
+use Thelia\Core\Template\ParserContext;
use Thelia\Core\Translation\Translator;
+use Thelia\Log\Tlog;
class GoogleFieldAssociationController extends BaseAdminController
{
@@ -232,4 +235,28 @@ public function setEanRuleAction(Request $httpRequest)
return $this->generateRedirectFromRoute("admin.module.configure", array(), $redirectParameters);
}
+
+ public function setCompatibilitySqlAction(ParserContext $parserContext)
+ {
+ $form = $this->createForm(CompatibilitySqlForm::getName());
+
+ try {
+ $compatibilityForm = $this->validateForm($form);
+
+ GoogleShoppingXml::setConfigValue(GoogleShoppingXml::ENABLE_SQL_8_COMPATIBILITY, $compatibilityForm->get('enable_optimisation')->getData());
+
+ return $this->generateSuccessRedirect($form);
+ }catch (\Exception $exception) {
+ Tlog::getInstance()->error($exception->getMessage());
+
+ $form->setErrorMessage($exception->getMessage());
+
+ $parserContext
+ ->addForm($form)
+ ->setGeneralError($exception->getMessage())
+ ;
+
+ return $this->generateErrorRedirect($form);
+ }
+ }
}
diff --git a/Form/CompatibilitySqlForm.php b/Form/CompatibilitySqlForm.php
new file mode 100644
index 0000000..51e229d
--- /dev/null
+++ b/Form/CompatibilitySqlForm.php
@@ -0,0 +1,29 @@
+formBuilder
+ ->add(
+ 'enable_optimisation',
+ CheckboxType::class,
+ [
+ 'label' => Translator::getInstance()->trans("Enable sql 8 optimisations"),
+ 'label_attr' => array(
+ 'for' => 'enable_sql_8'
+ ),
+ 'data' => (bool)GoogleShoppingXml::getConfigValue(GoogleShoppingXml::ENABLE_SQL_8_COMPATIBILITY),
+ 'required'=> false
+ ]
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/GoogleShoppingXml.php b/GoogleShoppingXml.php
index d4a4209..fa1fe7a 100644
--- a/GoogleShoppingXml.php
+++ b/GoogleShoppingXml.php
@@ -17,6 +17,8 @@ class GoogleShoppingXml extends BaseModule
/* @var string */
const UPDATE_PATH = __DIR__ . DS . 'Config' . DS . 'update';
+ const ENABLE_SQL_8_COMPATIBILITY = 'enable_sql_8_compatibility';
+
public function preActivation(ConnectionInterface $con = null)
{
if (!$this->getConfigValue('is_initialized', false)) {
diff --git a/Service/GoogleModel/GoogleProductModel.php b/Service/GoogleModel/GoogleProductModel.php
index 61c70af..032a315 100644
--- a/Service/GoogleModel/GoogleProductModel.php
+++ b/Service/GoogleModel/GoogleProductModel.php
@@ -207,7 +207,7 @@ public function setPrice(float $price): GoogleProductModel
* @param string $item_group_id
* @return GoogleProductModel
*/
- public function setItemGroupId(string $item_group_id): GoogleProductModel
+ public function setItemGroupId(?string $item_group_id): GoogleProductModel
{
$this->item_group_id = $item_group_id;
return $this;
@@ -217,7 +217,7 @@ public function setItemGroupId(string $item_group_id): GoogleProductModel
* @param string $brand
* @return GoogleProductModel
*/
- public function setBrand(string $brand): GoogleProductModel
+ public function setBrand(?string $brand): GoogleProductModel
{
$this->brand = $brand;
return $this;
@@ -227,7 +227,7 @@ public function setBrand(string $brand): GoogleProductModel
* @param string $google_product_category
* @return GoogleProductModel
*/
- public function setGoogleProductCategory(string $google_product_category): GoogleProductModel
+ public function setGoogleProductCategory(?string $google_product_category): GoogleProductModel
{
$this->google_product_category = $google_product_category;
return $this;
@@ -247,7 +247,7 @@ public function setCondition($condition = null): GoogleProductModel
* @param string $product_type
* @return GoogleProductModel
*/
- public function setProductType(string $product_type): GoogleProductModel
+ public function setProductType(?string $product_type): GoogleProductModel
{
$this->product_type = $product_type;
return $this;
@@ -257,7 +257,7 @@ public function setProductType(string $product_type): GoogleProductModel
* @param array $shipping
* @return GoogleProductModel
*/
- public function setshipping(array $shipping): GoogleProductModel
+ public function setshipping(?array $shipping): GoogleProductModel
{
$this->shipping = $shipping;
return $this;
@@ -266,7 +266,7 @@ public function setshipping(array $shipping): GoogleProductModel
/**
* @param int $imageId
*/
- public function setImageLink(int $imageId): void
+ public function setImageLink(?int $imageId): void
{
$this->image_link = URL::getInstance()->absoluteUrl("legacy-image-library/product_image_$imageId/full/max/0/default.jpg");
}
diff --git a/Service/Provider/ProductProvider.php b/Service/Provider/ProductProvider.php
index c40e625..b41e9d7 100644
--- a/Service/Provider/ProductProvider.php
+++ b/Service/Provider/ProductProvider.php
@@ -2,6 +2,8 @@
namespace GoogleShoppingXml\Service\Provider;
+use GoogleShoppingXml\GoogleShoppingXml;
+use OpenApi\Model\Api\Product;
use PDO;
use Generator;
use GoogleShoppingXml\Model\GoogleshoppingxmlFeed;
@@ -9,7 +11,13 @@
use GoogleShoppingXml\Service\ShippingService;
use Propel\Runtime\Exception\PropelException;
use Symfony\Component\HttpFoundation\RequestStack;
+use Thelia\Core\Template\Loop\ProductSaleElementsImage;
+use Thelia\Model\Base\ProductQuery;
+use Thelia\Model\Category;
+use Thelia\Model\CategoryQuery;
use Thelia\Model\ConfigQuery;
+use Thelia\Model\ProductImageQuery;
+use Thelia\Model\ProductSaleElementsProductImageQuery;
use Thelia\Model\TaxRuleQuery;
use Thelia\TaxEngine\Calculator;
use Thelia\Tools\MoneyFormat;
@@ -55,18 +63,66 @@ public function getDataGenerator(GoogleshoppingxmlFeed $feed, MoneyFormat $money
$taxCalculator = new Calculator();
$taxeRules = $this->getTaxeRules();
+ $shipping = $this->shipingService->buildShippingArray($feed, $moneyFormat);
+
+ $optimisation = GoogleShoppingXml::getConfigValue(GoogleShoppingXml::ENABLE_SQL_8_COMPATIBILITY);
/** @var $resultStatement */
- $resultStatement = $this->sqlQueryService->getPses($locale);
- $shipping = $this->shipingService->buildShippingArray($feed, $moneyFormat);
+
+ if ($optimisation) {
+ $resultStatement = $this->sqlQueryService->getPsesWithSqlOptimisation($locale);
+ } else {
+ $resultStatement = $this->sqlQueryService->getPses($locale);
+ }
while ($row = $resultStatement->fetch(PDO::FETCH_ASSOC)) {
$taxCalculator->loadTaxRuleWithoutProduct($taxeRules[$row['TAX_RULE_ID']], $feed->getCountry());
+ $row['title'] = $row['product_title'];
+
+ if (null !== $row['attrib_title']) {
+ $row['title'] .= ' - '.$row['attrib_title'];
+ }
+
+ if (!$optimisation) {
+
+ $pseImage = ProductSaleElementsProductImageQuery::create()
+ ->filterByProductSaleElementsId($row['id'])
+ ->findOne();
+
+ $productImage = ProductImageQuery::create()
+ ->useProductQuery()
+ ->useProductSaleElementsQuery()
+ ->filterById($row['id'])
+ ->endUse()
+ ->endUse()
+ ->orderByPosition()
+ ->findOne();
+
+ $row['image_link'] = $pseImage ? $pseImage->getProductImageId() : $productImage?->getId();
+
+ $path = $this->getCategories(CategoryQuery::create()->findPk($row['default_category_id']), $locale);
+
+ $row['product_type'] = implode(' > ', $path);
+ }
+
yield (new GoogleProductModel($taxCalculator, $moneyFormat, $shipping, $feed->getCurrency(), 'g:'))->build($row);
}
}
+ private function getCategories(Category $category, $locale)
+ {
+ if ($category->getParent() !== 0){
+ $parentCategory = CategoryQuery::create()->findPk($category->getParent());
+ $path = $this->getCategories($parentCategory, $locale);
+ }
+
+ $category->setLocale($locale);
+ $path[] = $category->getTitle();
+
+ return $path;
+ }
+
/**
* @return array
*/
diff --git a/Service/Provider/SQLQueryService.php b/Service/Provider/SQLQueryService.php
index d8fc8a0..36410bf 100644
--- a/Service/Provider/SQLQueryService.php
+++ b/Service/Provider/SQLQueryService.php
@@ -3,6 +3,8 @@
namespace GoogleShoppingXml\Service\Provider;
use Propel\Runtime\Propel;
+use Thelia\Model\Map\ProductSaleElementsTableMap;
+use Thelia\Model\ProductSaleElementsQuery;
use Thelia\Tools\URL;
class SQLQueryService
@@ -10,7 +12,7 @@ class SQLQueryService
/**
* @param string $locale
*/
- public function getPses(string $locale)
+ public function getPsesWithSqlOptimisation(string $locale)
{
$baseUrl = URL::getInstance()->absoluteUrl('/');
@@ -30,9 +32,9 @@ public function getPses(string $locale)
), attribute_title AS (
SELECT ac.product_sale_elements_id AS id, GROUP_CONCAT(DISTINCT avi.title ORDER BY a.id SEPARATOR " - ") AS title
from attribute_combination AS ac
- JOIN attribute a ON a.id = ac.attribute_id
- JOIN attribute_av av ON ac.attribute_av_id = av.id
- JOIN attribute_av_i18n avi ON av.id = avi.id
+ LEFT JOIN attribute a ON a.id = ac.attribute_id
+ LEFT JOIN attribute_av av ON ac.attribute_av_id = av.id
+ LEFT JOIN attribute_av_i18n avi ON av.id = avi.id
WHERE avi.locale=:p1
GROUP BY ac.product_sale_elements_id
@@ -52,7 +54,8 @@ public function getPses(string $locale)
SELECT
pse.id AS "id",
- CONCAT(pi.title," - ", attrib.title) AS "title",
+ pi.title AS "product_title",
+ attrib.title AS "attrib_title",
pi.description AS "description",
IF(pse.quantity>0, "in stock", "out of stock") AS "availability",
CONCAT(@BASEURL := "' . $baseUrl . '",rurl.url) AS "link",
@@ -69,19 +72,19 @@ public function getPses(string $locale)
FROM `product_sale_elements`AS pse
- JOIN product AS p ON pse.product_id = p.id
- JOIN product_i18n AS pi ON p.id = pi.id
- JOIN attribute_title AS attrib ON attrib.id = pse.id
- JOIN rewriting_url AS rurl ON rurl.view = "product" AND rurl.view_id = p.id
- JOIN product_price AS pp ON pp.product_sale_elements_id = pse.id
- JOIN brand AS b ON b.id = p.brand_id
- JOIN brand_i18n AS bi ON b.id = bi.id
- JOIN product_category AS pc ON pc.product_id=p.id AND pc.default_category=1
- JOIN product_images_query AS pimgs ON pimgs.pid=p.id
+ LEFT JOIN product AS p ON pse.product_id = p.id
+ LEFT JOIN product_i18n AS pi ON p.id = pi.id
+ LEFT JOIN attribute_title AS attrib ON attrib.id = pse.id
+ LEFT JOIN rewriting_url AS rurl ON rurl.view = "product" AND rurl.view_id = p.id
+ LEFT JOIN product_price AS pp ON pp.product_sale_elements_id = pse.id
+ LEFT JOIN brand AS b ON b.id = p.brand_id
+ LEFT JOIN brand_i18n AS bi ON b.id = bi.id
+ LEFT JOIN product_category AS pc ON pc.product_id=p.id AND pc.default_category=1
+ LEFT JOIN product_images_query AS pimgs ON pimgs.pid=p.id
LEFT JOIN pse_images_query AS pseimgs ON pseimgs.pseid=pse.id
- JOIN category AS c ON c.id=pc.category_id
- JOIN googleshoppingxml_taxonomy AS gt ON gt.thelia_category_id = c.id
- JOIN category_path cp ON cp.id = pc.category_id
+ LEFT JOIN category AS c ON c.id=pc.category_id
+ LEFT JOIN googleshoppingxml_taxonomy AS gt ON gt.thelia_category_id = c.id
+ LEFT JOIN category_path cp ON cp.id = pc.category_id
WHERE
@@ -110,4 +113,69 @@ public function getPses(string $locale)
return $stmt;
}
+
+ public function getPses(string $locale)
+ {
+ $baseUrl = URL::getInstance()->absoluteUrl('/');
+
+ $sql = '
+ SELECT
+ pse.id AS "id",
+ pi.title AS "product_title",
+ GROUP_CONCAT(DISTINCT avi.title ORDER BY a.id SEPARATOR " - ") AS "attrib_title",
+ pi.description AS "description",
+ IF(pse.quantity>0, "in stock", "out of stock") AS "availability",
+ CONCAT(@BASEURL := "' . $baseUrl . '",rurl.url) AS "link",
+ IF(pse.promo=1, pp.promo_price, pp.price) AS "price",
+ bi.title AS "brand",
+ IF(pse.ean_code!="", "yes", "no") AS "identifier_exists",
+ pse.ean_code AS "gtin",
+ p.ref AS "item_group_id",
+ gt.google_category AS "google_product_category",
+ "new" AS "condition",
+ p.tax_rule_id AS "TAX_RULE_ID",
+ c.id AS "default_category_id"
+
+ FROM `product_sale_elements`AS pse
+
+ LEFT JOIN product AS p ON pse.product_id = p.id
+ LEFT JOIN product_i18n AS pi ON p.id = pi.id
+ LEFT JOIN attribute_combination AS ac ON ac.product_sale_elements_id = pse.id
+ LEFT JOIN attribute AS a ON a.id = ac.attribute_id
+ LEFT JOIN attribute_av AS av ON ac.attribute_av_id = av.id
+ LEFT JOIN attribute_av_i18n AS avi ON av.id = avi.id
+ LEFT JOIN rewriting_url AS rurl ON rurl.view = "product" AND rurl.view_id = p.id
+ LEFT JOIN product_price AS pp ON pp.product_sale_elements_id = pse.id
+ LEFT JOIN brand AS b ON b.id = p.brand_id
+ LEFT JOIN brand_i18n AS bi ON b.id = bi.id
+ LEFT JOIN product_category AS pc ON pc.product_id=p.id AND pc.default_category=1
+ LEFT JOIN category AS c ON c.id=pc.category_id
+ LEFT JOIN googleshoppingxml_taxonomy AS gt ON gt.thelia_category_id = c.id
+
+ WHERE
+
+ pi.locale=:p2
+ AND rurl.view_locale=:p3
+ AND bi.locale=:p4
+ AND p.visible=1
+ AND pi.title!=""
+ AND pi.description!=""
+
+ GROUP BY pse.id';
+
+ $con = Propel::getConnection();
+
+ /** @var PDOStatement $stmt */
+ $stmt = $con->prepare($sql);
+
+ //$stmt->bindValue(':p1', $locale);
+ $stmt->bindValue(':p2', $locale);
+ $stmt->bindValue(':p3', $locale);
+ $stmt->bindValue(':p4', $locale);
+
+ $stmt->execute();
+
+ return $stmt;
+
+ }
}
\ No newline at end of file
diff --git a/templates/backOffice/default/include/config_tab_advanced.html b/templates/backOffice/default/include/config_tab_advanced.html
index 58f36a8..4498074 100644
--- a/templates/backOffice/default/include/config_tab_advanced.html
+++ b/templates/backOffice/default/include/config_tab_advanced.html
@@ -180,4 +180,26 @@
+
+
\ No newline at end of file
diff --git a/templates/backOffice/default/module-configuration.html b/templates/backOffice/default/module-configuration.html
new file mode 100644
index 0000000..e69de29