Skip to content

Commit 5f5e9ed

Browse files
authored
Merge pull request #1669 from algolia/fix/MAGE-1097-queryid-3.14
MAGE-1097: Handle add to cart redirect for Insights (3.14.4)
2 parents 77d540c + 6b746bf commit 5f5e9ed

File tree

3 files changed

+207
-0
lines changed

3 files changed

+207
-0
lines changed
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
<?php
2+
3+
namespace Algolia\AlgoliaSearch\Plugin;
4+
5+
use Algolia\AlgoliaSearch\Helper\ConfigHelper;
6+
use Magento\Catalog\Api\ProductRepositoryInterface;
7+
use Magento\Catalog\Model\Product;
8+
use Magento\CatalogInventory\Api\StockRegistryInterface;
9+
use Magento\Checkout\Model\Cart;
10+
use Magento\Checkout\Model\Cart\RequestInfoFilterInterface;
11+
use Magento\Checkout\Model\Session;
12+
use Magento\Framework\DataObject;
13+
use Magento\Framework\Event\ManagerInterface;
14+
use Magento\Framework\Exception\LocalizedException;
15+
use Magento\Framework\Exception\NoSuchEntityException;
16+
use Magento\Store\Model\StoreManagerInterface;
17+
18+
class AddToCartRedirectForInsights
19+
{
20+
/**
21+
* @var RequestInfoFilterInterface
22+
*/
23+
private $requestInfoFilter;
24+
25+
public function __construct(
26+
protected StoreManagerInterface $storeManager,
27+
protected ProductRepositoryInterface $productRepository,
28+
protected Session $checkoutSession,
29+
protected StockRegistryInterface $stockRegistry,
30+
protected ManagerInterface $eventManager,
31+
protected ConfigHelper $configHelper,
32+
) {}
33+
34+
/**
35+
* @param Cart $cartModel
36+
* @param int|Product $productInfo
37+
* @param array|int|DataObject|null $requestInfo
38+
*
39+
* @return null
40+
*
41+
* @throws LocalizedException
42+
* @throws NoSuchEntityException
43+
*/
44+
public function beforeAddProduct(Cart $cartModel, int|Product $productInfo, array|int|DataObject $requestInfo = null)
45+
{
46+
// First, check is Insights are enabled
47+
if (!$this->configHelper->isClickConversionAnalyticsEnabled($this->storeManager->getStore()->getId())) {
48+
return;
49+
}
50+
51+
// If the request doesn't have any insights info, no need to handle it
52+
if (!isset($requestInfo['referer']) || !isset($requestInfo['queryID']) || !isset($requestInfo['indexName'])) {
53+
return;
54+
}
55+
56+
// Check if the request comes from the PLP handled by InstantSearch
57+
if ($requestInfo['referer'] != 'instantsearch') {
58+
return;
59+
}
60+
61+
$product = $this->getProduct($productInfo);
62+
$productId = $product->getId();
63+
64+
if ($productId) {
65+
$request = $this->getQtyRequest($product, $requestInfo);
66+
67+
try {
68+
$result = $product->getTypeInstance()->prepareForCartAdvanced($request, $product);
69+
} catch (LocalizedException $e) {
70+
$this->checkoutSession->setUseNotice(false);
71+
$result = $e->getMessage();
72+
}
73+
74+
// if the result is a string, this mean that the product can't be added to the cart
75+
// see Magento\Quote\Model\Quote::addProduct()
76+
// Here we need to add the insights information to the redirect
77+
if (is_string($result)) {
78+
$redirectUrl = $product->getUrlModel()->getUrl(
79+
$product,
80+
[
81+
'_query' => [
82+
'objectID' => $product->getId(),
83+
'queryID' => $requestInfo['queryID'],
84+
'indexName' => $requestInfo['indexName']
85+
]
86+
]
87+
);
88+
89+
$this->checkoutSession->setRedirectUrl($redirectUrl);
90+
if ($this->checkoutSession->getUseNotice() === null) {
91+
$this->checkoutSession->setUseNotice(true);
92+
}
93+
throw new LocalizedException(__($result));
94+
}
95+
}
96+
}
97+
98+
/**
99+
* @param $productInfo
100+
*
101+
* @return Product
102+
*
103+
* @throws NoSuchEntityException
104+
* @throws LocalizedException
105+
*/
106+
protected function getProduct($productInfo): Product
107+
{
108+
$product = null;
109+
if ($productInfo instanceof Product) {
110+
$product = $productInfo;
111+
if (!$product->getId()) {
112+
throw new LocalizedException(
113+
__("The product wasn't found. Verify the product and try again.")
114+
);
115+
}
116+
} elseif (is_int($productInfo) || is_string($productInfo)) {
117+
$storeId = $this->storeManager->getStore()->getId();
118+
try {
119+
$product = $this->productRepository->getById($productInfo, false, $storeId);
120+
} catch (NoSuchEntityException $e) {
121+
throw new LocalizedException(
122+
__("The product wasn't found. Verify the product and try again."),
123+
$e
124+
);
125+
}
126+
} else {
127+
throw new LocalizedException(
128+
__("The product wasn't found. Verify the product and try again.")
129+
);
130+
}
131+
$currentWebsiteId = $this->storeManager->getStore()->getWebsiteId();
132+
if (!is_array($product->getWebsiteIds()) || !in_array($currentWebsiteId, $product->getWebsiteIds())) {
133+
throw new LocalizedException(
134+
__("The product wasn't found. Verify the product and try again.")
135+
);
136+
}
137+
return $product;
138+
}
139+
140+
/**
141+
* Get request quantity
142+
*
143+
* @param Product $product
144+
* @param DataObject|int|array $request
145+
* @return int|DataObject
146+
*/
147+
protected function getQtyRequest($product, $request = 0)
148+
{
149+
$request = $this->getProductRequest($request);
150+
$stockItem = $this->stockRegistry->getStockItem($product->getId(), $product->getStore()->getWebsiteId());
151+
$minimumQty = $stockItem->getMinSaleQty();
152+
//If product quantity is not specified in request and there is set minimal qty for it
153+
if ($minimumQty
154+
&& $minimumQty > 0
155+
&& !$request->getQty()
156+
) {
157+
$request->setQty($minimumQty);
158+
}
159+
160+
return $request;
161+
}
162+
163+
/**
164+
* Get request for product add to cart procedure
165+
*
166+
* @param DataObject|int|array $requestInfo
167+
* @return DataObject
168+
* @throws LocalizedException
169+
*/
170+
protected function getProductRequest($requestInfo)
171+
{
172+
if ($requestInfo instanceof DataObject) {
173+
$request = $requestInfo;
174+
} elseif (is_numeric($requestInfo)) {
175+
$request = new DataObject(['qty' => $requestInfo]);
176+
} elseif (is_array($requestInfo)) {
177+
$request = new DataObject($requestInfo);
178+
} else {
179+
throw new LocalizedException(
180+
__('We found an invalid request for adding product to quote.')
181+
);
182+
}
183+
$this->getRequestInfoFilter()->filter($request);
184+
185+
return $request;
186+
}
187+
188+
/**
189+
* Getter for RequestInfoFilter
190+
*
191+
* @return RequestInfoFilterInterface
192+
*/
193+
protected function getRequestInfoFilter()
194+
{
195+
if ($this->requestInfoFilter === null) {
196+
$this->requestInfoFilter = \Magento\Framework\App\ObjectManager::getInstance()
197+
->get(RequestInfoFilterInterface::class);
198+
}
199+
return $this->requestInfoFilter;
200+
}
201+
}

etc/frontend/di.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,8 @@
2020
<type name="Magento\Framework\View\Element\AbstractBlock">
2121
<plugin name="remove_related_upsell_block" type="Algolia\AlgoliaSearch\Plugin\RemovePdpProductsBlock" />
2222
</type>
23+
24+
<type name="Magento\Checkout\Model\Cart">
25+
<plugin name="handle_redirect_for_insights" type="Algolia\AlgoliaSearch\Plugin\AddToCartRedirectForInsights" />
26+
</type>
2327
</config>

view/frontend/templates/instant/hit.phtml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ $origFormatedVar = $block->escapeHtml('price' . $priceKey . '_original_formated'
8585
<form data-role="tocart-form" action="{{ addToCart.action }}" method="post">
8686
<input type="hidden" name="queryID" value="{{__queryID}}">
8787
<input type="hidden" name="product" value="{{objectID}}">
88+
<input type="hidden" name="indexName" value="{{__indexName}}">
89+
<input type="hidden" name="referer" value="instantsearch">
8890
{{#_highlightResult.default_bundle_options}}<input type="hidden" name="bundle_option[{{ optionId }}]" value="{{selectionId}}">{{/_highlightResult.default_bundle_options}}
8991
<input type="hidden" name="{{ addToCart.redirectUrlParam }}" value="{{ addToCart.uenc }}">
9092
<input name="form_key" type="hidden" value="{{ addToCart.formKey }}">

0 commit comments

Comments
 (0)