├── .gitignore
├── EcomDev
├── ConfigurableDisableIdentities
│ ├── composer.json
│ ├── etc
│ │ ├── di.xml
│ │ └── module.xml
│ └── registration.php
├── ConfigurableProductPreloader
│ ├── Loader
│ │ ├── ConfigurablePrice.php
│ │ ├── ConfigurableSalable.php
│ │ └── ConfigurableTierPrice.php
│ ├── Plugin
│ │ ├── ConfigurablePriceResolverPlugin.php
│ │ ├── ConfigurableSalableCheckPlugin.php
│ │ ├── ConfigurableTierPriceCalculatorPlugin.php
│ │ └── ConfigurableTypeSalableCheckPlugin.php
│ ├── composer.json
│ ├── etc
│ │ ├── di.xml
│ │ └── module.xml
│ └── registration.php
└── NoPriceCache
│ ├── Plugin
│ └── AvoidCachingProductPrice.php
│ ├── composer.json
│ ├── etc
│ ├── di.xml
│ └── module.xml
│ └── registration.php
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | /var/*
2 | !/var/.htaccess
3 |
4 |
--------------------------------------------------------------------------------
/EcomDev/ConfigurableDisableIdentities/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ecom-dev/configurable-disable-identities",
3 | "version": "1.0.0",
4 | "description": "N/A",
5 | "type": "magento2-module",
6 | "require": {
7 | "magento/framework": "*",
8 | "ecomdev/magento2-configurable-preloader": "1.0.*"
9 | },
10 | "license": [
11 | "Massachusetts Institute of Technology License (MITL)"
12 | ],
13 | "autoload": {
14 | "files": [
15 | "registration.php"
16 | ],
17 | "psr-4": {
18 | "EcomDev\\ConfigurableDisableIdentities\\": ""
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/EcomDev/ConfigurableDisableIdentities/etc/di.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/EcomDev/ConfigurableDisableIdentities/etc/module.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/EcomDev/ConfigurableDisableIdentities/registration.php:
--------------------------------------------------------------------------------
1 | resourceConnection = $resourceConnection;
24 | }
25 |
26 | /** @inheritDoc */
27 | public function load(ScopeFilter $filter, array $products): array
28 | {
29 | $configurableProductIds = [];
30 |
31 | foreach ($products as $product) {
32 | if ($product->isType(Configurable::TYPE_CODE)) {
33 | $configurableProductIds[] = $product->getId();
34 | }
35 | }
36 |
37 | if (!$configurableProductIds) {
38 | return [];
39 | }
40 |
41 | $connection = $this->resourceConnection->getConnection('catalog');
42 | $priceIndexTable = $this->resourceConnection->getTableName('catalog_product_index_price','catalog');
43 | $relationTable = $this->resourceConnection->getTableName('catalog_product_super_link','catalog');
44 | $select = $connection->select();
45 |
46 | $select
47 | ->from(['index' => $priceIndexTable], [])
48 | ->join(['relation' => $relationTable], 'relation.product_id = index.entity_id', [])
49 | ->columns([
50 | 'entity_id' => 'relation.parent_id',
51 | 'price' => 'MIN(index.price)',
52 | 'final_price' => 'MIN(index.final_price)',
53 | ])
54 | ->group('relation.parent_id')
55 | ->where('relation.parent_id IN(?)', $configurableProductIds)
56 | ->where('index.customer_group_id = ?', $filter->getCustomerGroupId())
57 | ->where('index.website_id = ?', $filter->getWebsiteId())
58 | ;
59 |
60 | return $connection->fetchAssoc($select);
61 | }
62 |
63 | public function isApplicable(string $type): bool
64 | {
65 | return $type === self::TYPE_LIST;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/EcomDev/ConfigurableProductPreloader/Loader/ConfigurableSalable.php:
--------------------------------------------------------------------------------
1 | stockResolver = $stockResolver;
36 | $this->indexTableNameResolver = $indexTableNameResolver;
37 | $this->storeManager = $storeManager;
38 | $this->resourceConnection = $resourceConnection;
39 | }
40 |
41 | public function load(ScopeFilter $filter, array $products): array
42 | {
43 | $configurableProductIds = [];
44 |
45 | foreach ($products as $product) {
46 | if ($product->isType(Configurable::TYPE_CODE)) {
47 | $configurableProductIds[] = $product->getId();
48 | }
49 | }
50 |
51 | if (!$configurableProductIds) {
52 | return [];
53 | }
54 |
55 | $websiteCode = $this->storeManager->getWebsite($filter->getWebsiteId())->getCode();
56 | $stock = $this->stockResolver->execute(SalesChannelInterface::TYPE_WEBSITE, $websiteCode);
57 | $connection = $this->resourceConnection->getConnection('catalog');
58 | $relationTable = $this->resourceConnection->getTableName('catalog_product_super_link','catalog');
59 | $productTable = $this->resourceConnection->getTableName('catalog_product_entity','catalog');
60 | $indexTableName = $this->indexTableNameResolver->execute((int)$stock->getStockId());
61 | $select = $connection->select();
62 |
63 | $select
64 | ->from(['relation' => $relationTable], [])
65 | ->join(['product' => $productTable], 'relation.product_id = product.entity_id', [])
66 | ->join(['index' => $indexTableName], 'product.sku = index.sku', [])
67 | ->columns([
68 | 'entity_id' => 'relation.parent_id',
69 | 'is_salable' => 'MAX(index.is_salable)',
70 | ])
71 | ->group('relation.parent_id')
72 | ->where('relation.parent_id IN(?)', $configurableProductIds);
73 | ;
74 |
75 | return $connection->fetchAssoc($select);
76 | }
77 |
78 | public function isApplicable(string $type): bool
79 | {
80 | return true;
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/EcomDev/ConfigurableProductPreloader/Loader/ConfigurableTierPrice.php:
--------------------------------------------------------------------------------
1 | resourceConnection = $resourceConnection;
27 | }
28 |
29 | public function load(ScopeFilter $filter, array $products): array
30 | {
31 | $configurableProductIds = [];
32 |
33 | foreach ($products as $product) {
34 | if ($product->isType(Configurable::TYPE_CODE)) {
35 | $configurableProductIds[] = $product->getId();
36 | }
37 | }
38 |
39 | if (!$configurableProductIds) {
40 | return [];
41 | }
42 |
43 | $connection = $this->resourceConnection->getConnection('catalog');
44 | $tierPriceTable = $this->resourceConnection->getTableName('catalog_product_entity_tier_price','catalog');
45 | $relationTable = $this->resourceConnection->getTableName('catalog_product_super_link','catalog');
46 | $select = $connection->select();
47 |
48 | $select
49 | ->from(['tier_price' => $tierPriceTable], [])
50 | ->join(['relation' => $relationTable], 'relation.product_id = tier_price.entity_id', [])
51 | ->columns([
52 | 'entity_id' => 'relation.parent_id',
53 | 'tier_price' => 'MIN(tier_price.value)'
54 | ])
55 | ->group('relation.parent_id')
56 | ->where('relation.parent_id IN(?)', $configurableProductIds)
57 | ->where('tier_price.customer_group_id = ? OR tier_price.all_groups = 1', $filter->getCustomerGroupId())
58 | ->where('tier_price.website_id = ?', $filter->getWebsiteId())
59 | ;
60 |
61 | return $connection->fetchAssoc($select);
62 | }
63 |
64 | public function isApplicable(string $type): bool
65 | {
66 | return $type === self::TYPE_LIST;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/EcomDev/ConfigurableProductPreloader/Plugin/ConfigurablePriceResolverPlugin.php:
--------------------------------------------------------------------------------
1 | loadService = $loadService;
22 | }
23 |
24 | public function aroundResolvePrice(ConfigurablePriceResolver $subject, callable $proceed, SaleableInterface $product)
25 | {
26 | $productId = (int)$product->getId();
27 |
28 | if ($this->loadService->has($productId, ConfigurablePrice::DATA_KEY)) {
29 | return (float)($this->loadService->get($productId, ConfigurablePrice::DATA_KEY)['final_price'] ?? 0);
30 | }
31 |
32 | return $proceed($product);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/EcomDev/ConfigurableProductPreloader/Plugin/ConfigurableSalableCheckPlugin.php:
--------------------------------------------------------------------------------
1 | loadService = $loadService;
23 | }
24 |
25 | public function afterIsSalable(SalableResolver $subject, $result, SaleableInterface $salableItem)
26 | {
27 | $productId = (int)$salableItem->getId();
28 | $canProcess = $salableItem->getTypeId() === Configurable::TYPE_CODE && $result;
29 | if ($canProcess && $this->loadService->has($productId, ConfigurableSalable::DATA_KEY)) {
30 | return (bool)($this->loadService->get($productId, ConfigurableSalable::DATA_KEY)['is_salable'] ?? false);
31 | }
32 | return $result;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/EcomDev/ConfigurableProductPreloader/Plugin/ConfigurableTierPriceCalculatorPlugin.php:
--------------------------------------------------------------------------------
1 | loadService = $loadService;
23 | }
24 |
25 | public function aroundGetValue(MinimalTierPriceCalculator $subject, callable $proceed, SaleableInterface $saleableItem)
26 | {
27 | $productId = (int)$saleableItem->getId();
28 |
29 | if ($saleableItem->getTypeId() === Configurable::TYPE_CODE
30 | && $this->loadService->has($productId, ConfigurableTierPrice::DATA_KEY)) {
31 | $tierPrice = ($this->loadService->get($productId, ConfigurableTierPrice::DATA_KEY)['tier_price'] ?? null);
32 |
33 | return $tierPrice ? (float)$tierPrice : null;
34 | }
35 | return $proceed($saleableItem);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/EcomDev/ConfigurableProductPreloader/Plugin/ConfigurableTypeSalableCheckPlugin.php:
--------------------------------------------------------------------------------
1 | loadService = $loadService;
22 | }
23 |
24 | public function aroundIsSalable(Configurable $subject, callable $proceed, Product $product)
25 | {
26 | $productId = (int)$product->getId();
27 |
28 | if (!$this->loadService->has($productId, ConfigurableSalable::DATA_KEY)) {
29 | return $proceed($product);
30 | }
31 | $isSalable = ((int)$product->getStatus()) === Product\Attribute\Source\Status::STATUS_ENABLED;
32 | $isSalable = $isSalable
33 | && $this->loadService->get($productId, ConfigurableSalable::DATA_KEY)['is_salable'] ?? false;
34 |
35 | return $isSalable;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/EcomDev/ConfigurableProductPreloader/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ecomdev/magento2-configurable-preloader",
3 | "version": "1.0.0",
4 | "description": "Preloader for configurable data",
5 | "type": "magento2-module",
6 | "require": {
7 | "magento/framework": "*",
8 | "ecomdev/magento2-product-data-preloader": "*"
9 | },
10 | "license": [
11 | "MIT"
12 | ],
13 | "autoload": {
14 | "files": [
15 | "registration.php"
16 | ],
17 | "psr-4": {
18 | "EcomDev\\ConfigurableProductPreloader\\": ""
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/EcomDev/ConfigurableProductPreloader/etc/di.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | - EcomDev\ConfigurableProductPreloader\Loader\ConfigurablePrice
7 | - EcomDev\ConfigurableProductPreloader\Loader\ConfigurableSalable
8 | - EcomDev\ConfigurableProductPreloader\Loader\ConfigurableTierPrice
9 |
10 |
11 |
12 |
13 |
14 |
15 |
19 |
20 |
21 |
22 |
23 |
27 |
28 |
29 |
30 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/EcomDev/ConfigurableProductPreloader/etc/module.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/EcomDev/ConfigurableProductPreloader/registration.php:
--------------------------------------------------------------------------------
1 | setData('cache_lifetime', false);
23 | return [];
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/EcomDev/NoPriceCache/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ecom-dev/no-price-cache",
3 | "version": "1.0.0",
4 | "description": "N/A",
5 | "type": "magento2-module",
6 | "require": {
7 | "magento/framework": "*"
8 | },
9 | "license": [
10 | "Proprietary"
11 | ],
12 | "autoload": {
13 | "files": [
14 | "registration.php"
15 | ],
16 | "psr-4": {
17 | "EcomDev\\NoPriceCache\\": ""
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/EcomDev/NoPriceCache/etc/di.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/EcomDev/NoPriceCache/etc/module.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/EcomDev/NoPriceCache/registration.php:
--------------------------------------------------------------------------------
1 |