From 6b08b60de6b005f7e022312cc756d806fecfd494 Mon Sep 17 00:00:00 2001 From: Tony Date: Thu, 18 May 2023 17:12:05 +0200 Subject: [PATCH 1/3] Fixed the behaviour of $forceLog parameter for Mage::log() (#3263) --- app/Mage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Mage.php b/app/Mage.php index 6da6d72d5e9..b88e1379c35 100644 --- a/app/Mage.php +++ b/app/Mage.php @@ -871,7 +871,7 @@ public static function log($message, $level = null, $file = '', $forceLog = fals $level = is_null($level) ? Zend_Log::DEBUG : $level; - if (!self::$_isDeveloperMode && $level > $maxLogLevel) { + if (!self::$_isDeveloperMode && $level > $maxLogLevel && !$forceLog) { return; } From 12aab258daace8e1327012f4295b9fd65ed06752 Mon Sep 17 00:00:00 2001 From: Scott Moore Date: Thu, 18 May 2023 17:15:06 -0400 Subject: [PATCH 2/3] Added support for Google Analytics 4 Enhanced eCommerce (#3198) Co-authored-by: Fabrizio Balliano --- .../core/Mage/GoogleAnalytics/Block/Ga.php | 189 +++++++++++++++--- .../Mage/GoogleAnalytics/Model/Observer.php | 26 +++ .../core/Mage/GoogleAnalytics/etc/config.xml | 16 ++ 3 files changed, 207 insertions(+), 24 deletions(-) diff --git a/app/code/core/Mage/GoogleAnalytics/Block/Ga.php b/app/code/core/Mage/GoogleAnalytics/Block/Ga.php index 26141d8299f..581214a3543 100644 --- a/app/code/core/Mage/GoogleAnalytics/Block/Ga.php +++ b/app/code/core/Mage/GoogleAnalytics/Block/Ga.php @@ -197,36 +197,177 @@ protected function _getOrdersTrackingCodeUniversal() */ protected function _getOrdersTrackingCodeAnalytics4() { + $result = []; + $request = $this->getRequest(); + $moduleName = $request->getModuleName(); + $controllerName = $request->getControllerName(); + + //purchase events $orderIds = $this->getOrderIds(); - if (empty($orderIds) || !is_array($orderIds)) { - return ''; + if (!empty($orderIds) && is_array($orderIds)) { + $collection = Mage::getResourceModel('sales/order_collection') + ->addFieldToFilter('entity_id', ['in' => $orderIds]); + /** @var Mage_Sales_Model_Order $order */ + foreach ($collection as $order) { + $orderData = [ + 'currency' => $order->getBaseCurrencyCode(), + 'transaction_id' => $order->getIncrementId(), + 'value' => number_format($order->getBaseGrandTotal(), 2), + 'coupon' => strtoupper($order->getCouponCode()), + 'shipping' => number_format($order->getBaseShippingAmount(), 2), + 'tax' => number_format($order->getBaseTaxAmount(), 2), + 'items' => [] + ]; + + /** @var Mage_Sales_Model_Order_Item $item */ + foreach ($order->getAllVisibleItems() as $item) { + $orderData['items'][] = [ + 'item_id' => $item->getSku(), + 'item_name' => $item->getName(), + 'quantity' => $item->getQtyOrdered(), + 'price' => $item->getBasePrice(), + 'discount' => $item->getBaseDiscountAmount() + ]; + } + $result[] = "gtag('event', 'purchase', " . json_encode($orderData, JSON_THROW_ON_ERROR) . ");"; + } } - $collection = Mage::getResourceModel('sales/order_collection') - ->addFieldToFilter('entity_id', ['in' => $orderIds]); - $result = []; - /** @var Mage_Sales_Model_Order $order */ - foreach ($collection as $order) { - $orderData = [ - 'currency' => $order->getBaseCurrencyCode(), - 'transaction_id' => $order->getIncrementId(), - 'value' => number_format($order->getBaseGrandTotal(), 2), - 'coupon' => strtoupper($order->getCouponCode()), - 'shipping' => number_format($order->getBaseShippingAmount(), 2), - 'tax' => number_format($order->getBaseTaxAmount(), 2), - 'items' => [] + + //Begin advanced eCommerce events + //product page + if ($moduleName == 'catalog' && $controllerName == 'product') { + $productViewed = Mage::registry('current_product'); + $eventData = []; + $eventData['currency'] = Mage::app()->getStore()->getCurrentCurrencyCode(); + $eventData['value'] = number_format($productViewed->getFinalPrice(), 2); + $eventData['items'] = []; + $eventData['items'][] = [ + 'id' => $productViewed->getSku(), + 'name' => $productViewed->getName(), + 'list_name' => 'Product Detail Page', + 'brand' => $productViewed->getAttributeText('manufacturer'), + 'category' => 'Products', + 'price' => number_format($productViewed->getFinalPrice(), 2), ]; - /** @var Mage_Sales_Model_Order_Item $item */ - foreach ($order->getAllVisibleItems() as $item) { - $orderData['items'][] = [ - 'item_id' => $item->getSku(), - 'item_name' => $item->getName(), - 'quantity' => $item->getQtyOrdered(), - 'price' => $item->getBasePrice(), - 'discount' => $item->getBaseDiscountAmount() + $result[] = "gtag('event', 'view_item', " . json_encode($eventData, JSON_THROW_ON_ERROR) . ");"; + } + + //category page + elseif ($moduleName == 'catalog' && $controllerName == 'category') { + $layer = Mage::getSingleton('catalog/layer'); + $category = $layer->getCurrentCategory(); + $productCollection = clone $layer->getProductCollection(); + $toolbarBlock = Mage::app()->getLayout()->getBlock('product_list_toolbar'); + $pageSize = $toolbarBlock->getLimit(); + $currentPage = $toolbarBlock->getCurrentPage(); + if ($pageSize !== 'all') { + $productCollection->setPageSize($pageSize)->setCurPage($currentPage); + } + $eventData = []; + $eventData['currency'] = Mage::app()->getStore()->getCurrentCurrencyCode(); + $eventData['value'] = 0.00; + $eventData['item_list_id'] = 'category_'.$category->getUrlKey(); + $eventData['item_list_name'] = $category->getName(); + $eventData['items'] = []; + + foreach ($productCollection as $productViewed) { + $eventData['items'][] = [ + 'id' => $productViewed->getSku(), + 'name' => $productViewed->getName(), + 'list_name' => 'Product Detail Page', + 'brand' => $productViewed->getAttributeText('manufacturer'), + 'category' => 'Products', + 'price' => number_format($productViewed->getFinalPrice(), 2), + ]; + $eventData['value'] += $productViewed->getFinalPrice(); + } + $eventData['value'] = number_format($eventData['value'], 2); + $result[] = "gtag('event', 'view_item_list', " . json_encode($eventData, JSON_THROW_ON_ERROR) . ");"; + } + + //cart + elseif ($moduleName == 'checkout' && $controllerName == 'cart') { + $removedProduct = Mage::getSingleton('core/session')->getRemovedProductCart(); + if ($removedProduct) { + $_removedProduct = Mage::getModel('catalog/product')->load($removedProduct); + $eventData = []; + $eventData['currency'] = Mage::app()->getStore()->getCurrentCurrencyCode(); + $eventData['value'] = number_format($_removedProduct->getFinalPrice(), 2); + $eventData['items'] = []; + $eventData['items'][] = [ + 'id' => $_removedProduct->getSku(), + 'name' => $_removedProduct->getName(), + 'list_name' => 'Product Detail Page', + 'brand' => $_removedProduct->getAttributeText('manufacturer'), + 'category' => 'Products', + 'price' => number_format($_removedProduct->getFinalPrice(), 2), + ]; + $result[] = "gtag('event', 'remove_from_cart', " . json_encode($eventData, JSON_THROW_ON_ERROR) . ");"; + Mage::getSingleton('core/session')->unsRemovedProductCart(); + } + + $addedProduct = Mage::getSingleton('core/session')->getAddedProductCart(); + if ($addedProduct) { + $_addedProduct = Mage::getModel('catalog/product')->load($addedProduct); + $eventData = []; + $eventData['currency'] = Mage::app()->getStore()->getCurrentCurrencyCode(); + $eventData['value'] = number_format($_addedProduct->getFinalPrice(), 2); + $eventData['items'] = []; + $eventData['items'][] = [ + 'id' => $_addedProduct->getSku(), + 'name' => $_addedProduct->getName(), + 'list_name' => 'Product Detail Page', + 'brand' => $_addedProduct->getAttributeText('manufacturer'), + 'category' => 'Products', + 'price' => number_format($_addedProduct->getFinalPrice(), 2), + ]; + $result[] = "gtag('event', 'add_to_cart', " . json_encode($eventData, JSON_THROW_ON_ERROR) . ");"; + Mage::getSingleton('core/session')->unsAddedProductCart(); + } + + $productCollection = Mage::getSingleton('checkout/session')->getQuote()->getAllVisibleItems(); + $eventData = []; + $eventData['currency'] = Mage::app()->getStore()->getCurrentCurrencyCode(); + $eventData['value'] = 0.00; + $eventData['items'] = []; + + foreach ($productCollection as $productInCart) { + $eventData['items'][] = [ + 'id' => $productInCart->getSku(), + 'name' => $productInCart->getName(), + 'list_name' => 'Product Detail Page', + 'brand' => $productInCart->getAttributeText('manufacturer'), + 'category' => 'Products', + 'price' => number_format($productInCart->getFinalPrice(), 2), + ]; + $eventData['value'] += $productInCart->getFinalPrice(); + } + $eventData['value'] = number_format($eventData['value'], 2); + $result[] = "gtag('event', 'view_cart', " . json_encode($eventData, JSON_THROW_ON_ERROR) . ");"; + } + + //begin checkout + elseif ($moduleName == 'checkout' && $controllerName == 'onepage') { + $productCollection = Mage::getSingleton('checkout/session')->getQuote()->getAllVisibleItems(); + $eventData = []; + $eventData['currency'] = Mage::app()->getStore()->getCurrentCurrencyCode(); + $eventData['value'] = 0.00; + $eventData['items'] = []; + + foreach ($productCollection as $productInCart) { + $eventData['items'][] = [ + 'id' => $productInCart->getSku(), + 'name' => $productInCart->getName(), + 'list_name' => 'Product Detail Page', + 'brand' => $productInCart->getAttributeText('manufacturer'), + 'category' => 'Products', + 'price' => number_format($productInCart->getFinalPrice(), 2), ]; + $eventData['value'] += $productInCart->getFinalPrice(); } - $result[] = "gtag('event', 'purchase', " . json_encode($orderData, JSON_THROW_ON_ERROR) . ");"; + $eventData['value'] = number_format($eventData['value'], 2); + $result[] = "gtag('event', 'begin_checkout', " . json_encode($eventData, JSON_THROW_ON_ERROR) . ");"; } return implode("\n", $result); } diff --git a/app/code/core/Mage/GoogleAnalytics/Model/Observer.php b/app/code/core/Mage/GoogleAnalytics/Model/Observer.php index 341f29b21cc..667241f6f59 100644 --- a/app/code/core/Mage/GoogleAnalytics/Model/Observer.php +++ b/app/code/core/Mage/GoogleAnalytics/Model/Observer.php @@ -49,4 +49,30 @@ public function setGoogleAnalyticsOnOrderSuccessPageView(Varien_Event_Observer $ $block->setOrderIds($orderIds); } } + + /** + * Add 'removed item' from cart into session for GA4 block to render event on cart view + * + * @param Varien_Event_Observer $observer + */ + public function removeItemFromCartGoogleAnalytics(Varien_Event_Observer $observer) + { + $productRemoved = $observer->getEvent()->getQuoteItem()->getProduct(); + if ($productRemoved) { + Mage::getSingleton('core/session')->setRemovedProductCart($productRemoved->getId()); + } + } + + /** + * Add 'added item' to cart into session for GA4 block to render event on cart view + * + * @param Varien_Event_Observer $observer + */ + public function addItemToCartGoogleAnalytics(Varien_Event_Observer $observer) + { + $productAdded = $observer->getEvent()->getQuoteItem()->getProduct(); + if ($productAdded) { + Mage::getSingleton('core/session')->setAddedProductCart($productAdded->getId()); + } + } } diff --git a/app/code/core/Mage/GoogleAnalytics/etc/config.xml b/app/code/core/Mage/GoogleAnalytics/etc/config.xml index 5af53d94f74..8f7750a93b9 100644 --- a/app/code/core/Mage/GoogleAnalytics/etc/config.xml +++ b/app/code/core/Mage/GoogleAnalytics/etc/config.xml @@ -72,6 +72,22 @@ + + + + googleanalytics/observer + removeItemFromCartGoogleAnalytics + + + + + + + googleanalytics/observer + addItemToCartGoogleAnalytics + + + From d6927f9911566c3571e89414ae2693a5cece8d71 Mon Sep 17 00:00:00 2001 From: Colin Mollenhour Date: Thu, 18 May 2023 17:16:01 -0400 Subject: [PATCH 3/3] Optimize count queries by removing all joins if there are no where clauses using joined tables and all joins are left joins (#2210) --- lib/Varien/Data/Collection/Db.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/lib/Varien/Data/Collection/Db.php b/lib/Varien/Data/Collection/Db.php index 75d3fbc91e6..1126bed1297 100644 --- a/lib/Varien/Data/Collection/Db.php +++ b/lib/Varien/Data/Collection/Db.php @@ -239,7 +239,32 @@ public function getSelectCountSql() $countSelect->columns("COUNT(DISTINCT " . implode(", ", $group) . ")"); } else { $countSelect->columns('COUNT(*)'); + + // Simple optimization - remove all joins if there are no where clauses using joined tables and all joins are left joins + $leftJoins = array_filter($countSelect->getPart(Zend_Db_Select::FROM), function($table) { + return ($table['joinType'] == Zend_Db_Select::LEFT_JOIN || $table['joinType'] == Zend_Db_Select::FROM); + }); + if (count($leftJoins) == count($countSelect->getPart(Zend_Db_Select::FROM))) { + $mainTable = array_filter($leftJoins, function ($table) { + return $table['joinType'] == Zend_Db_Select::FROM; + }); + $mainTable = key($mainTable); + $mainTable = preg_quote($mainTable, '/'); + $pattern = "/^$mainTable\\.\\w+/"; + $whereUsingJoin = array_filter($countSelect->getPart(Zend_Db_Select::WHERE), function ($clause) use ($pattern) { + $clauses = preg_split('/(^|\s+)(AND|OR)\s+/', $clause, -1, PREG_SPLIT_NO_EMPTY); + return array_filter($clauses, function ($clause) use ($pattern) { + $clause = preg_replace('/[()`\s]+/', '', $clause); + return !preg_match($pattern, $clause); + }); + }); + if (empty($whereUsingJoin)) { + $from = array_slice($leftJoins, 0, 1); + $countSelect->setPart(Zend_Db_Select::FROM, $from); + } + } } + return $countSelect; }