Skip to content

Commit 9b5baa6

Browse files
milesmcleodmagento-bot
andauthored
fix: [MINT-4753] add plugin to enrich configurable products with sku info if magento inventory management is disabled (#215)
* fix: [MINT-4753] add plugin to enrich configurable products with sku info if magento inventory management is disabled * auto-changelog * fix existing unit test failures * auto-changelog * attemt lint:php fix for CI * auto-changelog * auto-changelog * auto-changelog * fix: use correct 'sku' property instead of 'skus' in non-swatch configurable products * auto-changelog * auto-changelog --------- Co-authored-by: magento-bot <[email protected]>
1 parent 993d89c commit 9b5baa6

File tree

5 files changed

+412
-8
lines changed

5 files changed

+412
-8
lines changed
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
/*
3+
* Copyright Extend (c) 2025. All rights reserved.
4+
* See Extend-COPYING.txt for license details.
5+
*/
6+
7+
namespace Extend\Integration\Plugin\ConfigurableProduct\Block\Product\View\Type\Configurable;
8+
9+
use Magento\ConfigurableProduct\Block\Product\View\Type\Configurable as ConfigurableBlock;
10+
use Magento\Framework\Serialize\Serializer\Json;
11+
use Psr\Log\LoggerInterface;
12+
13+
/**
14+
* Plugin to add SKU information to configurable product JSON config
15+
*
16+
* This plugin ensures that the 'sku' node is present in spConfig regardless of
17+
* whether Magento Inventory Management (MSI) modules are enabled. The Extend
18+
* integration relies on this data to display warranty offers for configurable products.
19+
*
20+
* Background:
21+
* Magento's InventoryConfigurableProductFrontendUi module provides a similar plugin
22+
* (AddAdditionalInfo) that adds SKU data, but only when MSI is enabled. This plugin
23+
* provides a fallback to ensure Extend functionality works even when MSI is disabled.
24+
*/
25+
class AddSkuInfo
26+
{
27+
/**
28+
* @var Json
29+
*/
30+
private $jsonSerializer;
31+
32+
/**
33+
* @var LoggerInterface
34+
*/
35+
private $logger;
36+
37+
/**
38+
* @param Json $jsonSerializer
39+
* @param LoggerInterface $logger
40+
*/
41+
public function __construct(
42+
Json $jsonSerializer,
43+
LoggerInterface $logger
44+
) {
45+
$this->jsonSerializer = $jsonSerializer;
46+
$this->logger = $logger;
47+
}
48+
49+
/**
50+
* Add SKU information to configurable product JSON config
51+
*
52+
* This plugin runs after getJsonConfig() and adds a 'sku' array mapping
53+
* product IDs to SKUs if it's not already present (from MSI).
54+
*
55+
* @param ConfigurableBlock $subject
56+
* @param string $result
57+
* @return string
58+
*/
59+
public function afterGetJsonConfig(ConfigurableBlock $subject, string $result): string
60+
{
61+
try {
62+
$jsonConfig = $this->jsonSerializer->unserialize($result);
63+
64+
// Only add SKU data if it's not already present (avoid duplicate work if MSI is enabled)
65+
if (!isset($jsonConfig['sku']) || empty($jsonConfig['sku'])) {
66+
$jsonConfig['sku'] = $this->getProductVariationsSku($subject);
67+
}
68+
69+
return $this->jsonSerializer->serialize($jsonConfig);
70+
} catch (\Exception $e) {
71+
// Log error but return original result to avoid breaking the page
72+
$this->logger->error(
73+
'Extend Integration: Error adding SKU info to configurable product config',
74+
['exception' => $e->getMessage()]
75+
);
76+
return $result;
77+
}
78+
}
79+
80+
/**
81+
* Get SKU for each product variation
82+
*
83+
* @param ConfigurableBlock $subject
84+
* @return array Array mapping product IDs to SKUs
85+
*/
86+
private function getProductVariationsSku(ConfigurableBlock $subject): array
87+
{
88+
$skus = [];
89+
foreach ($subject->getAllowProducts() as $product) {
90+
$skus[$product->getId()] = $product->getSku();
91+
}
92+
93+
return $skus;
94+
}
95+
}

Test/Unit/Controller/Minicart/CategoriesTest.php

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@
99
use PHPUnit\Framework\TestCase;
1010
use Magento\Catalog\Api\Data\CategoryInterface;
1111
use Magento\Catalog\Api\CategoryRepositoryInterface;
12+
use Magento\Catalog\Api\ProductRepositoryInterface;
1213
use Magento\Checkout\Model\Session as CheckoutSession;
1314
use Magento\Catalog\Model\Product;
1415
use Magento\Quote\Model\Quote;
1516
use Magento\Quote\Model\Quote\Item;
1617
use Magento\Framework\App\Action\Context;
18+
use Magento\Framework\App\RequestInterface;
1719
use Magento\Framework\Controller\Result\Json;
1820
use Magento\Framework\Controller\Result\JsonFactory;
1921
use Extend\Integration\Controller\Minicart\Categories;
@@ -30,6 +32,11 @@ class CategoriesTest extends TestCase
3032
*/
3133
protected $categoryRepository;
3234

35+
/**
36+
* @var ProductRepositoryInterface
37+
*/
38+
protected $productRepository;
39+
3340
/**
3441
* @var JsonFactory
3542
*/
@@ -42,17 +49,26 @@ class CategoriesTest extends TestCase
4249

4350
protected function setUp(): void
4451
{
45-
$context = $this->createStub(Context::class);
52+
// Create a mock request that returns null for getParam (simulating no product_ids parameter)
53+
$request = $this->createMock(RequestInterface::class);
54+
$request->method('getParam')->willReturn(null);
55+
56+
// Create a mock context that provides the request
57+
$context = $this->createMock(Context::class);
58+
$context->method('getRequest')->willReturn($request);
59+
4660
$this->resultJsonFactory = $this->createStub(JsonFactory::class);
4761
$this->checkoutSession = $this->createStub(CheckoutSession::class);
4862
$this->categoryRepository = $this->createStub(CategoryRepositoryInterface::class);
63+
$this->productRepository = $this->createStub(ProductRepositoryInterface::class);
4964

5065
$this->categories = new Categories(
51-
$context,
52-
$this->resultJsonFactory,
53-
$this->checkoutSession,
54-
$this->categoryRepository
55-
);
66+
$context,
67+
$this->resultJsonFactory,
68+
$this->checkoutSession,
69+
$this->categoryRepository,
70+
$this->productRepository
71+
);
5672
}
5773

5874
public function testGetCategories()
@@ -123,7 +139,8 @@ public function testGetCategoriesWhereItemHasNoCategories()
123139
$this->assertEquals([], $this->categories->execute());
124140
}
125141

126-
public function testGetCategoriesWhereItemProductDoesNotExist() {
142+
public function testGetCategoriesWhereItemProductDoesNotExist()
143+
{
127144
$quoteItemMock = $this->getMockBuilder(Item::class)
128145
->disableOriginalConstructor()
129146
->onlyMethods(['getProduct'])

0 commit comments

Comments
 (0)