Skip to content

Commit 4fd5700

Browse files
authored
Merge branch '2.4-develop' into Arrows_Uppy_Delivery
2 parents 7a80b35 + fc5cecb commit 4fd5700

File tree

33 files changed

+1200
-81
lines changed

33 files changed

+1200
-81
lines changed

app/code/Magento/ConfigurableProductGraphQl/Model/Wishlist/ChildSku.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,17 @@ public function resolve(
3636

3737
/** @var Product $product */
3838
$product = $value['model'];
39-
$optionProduct = $product->getCustomOption('simple_product')->getProduct();
4039

41-
return $optionProduct->getSku();
40+
/** to handle no child sku selected at add to wishlist time */
41+
$optionsArray = json_decode($product->getCustomOption('info_buyRequest')->getValue(), true);
42+
$superAttribute = $optionsArray['super_attribute'];
43+
$totalSelected = array_filter($superAttribute);
44+
45+
if (count($totalSelected) > 0) {
46+
$optionProduct = $product->getCustomOption('simple_product')->getProduct();
47+
return $optionProduct->getSku();
48+
} else {
49+
return "";
50+
}
4251
}
4352
}

app/code/Magento/CustomerGraphQl/etc/di.xml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,6 @@
3030
<item name="Magento\Customer\Model\Address" xsi:type="object">
3131
Magento\CustomerGraphQl\Model\Resolver\Cache\Customer\Address\TagsStrategy
3232
</item>
33-
<item name="Magento\Newsletter\Model\Subscriber" xsi:type="object">
34-
Magento\CustomerGraphQl\Model\Resolver\Cache\Subscriber\TagsStrategy
35-
</item>
3633
</argument>
3734
</arguments>
3835
</type>

app/code/Magento/CustomerGraphQl/etc/graphql/di.xml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,9 +176,6 @@
176176
<item name="Magento\CustomerGraphQl\Model\Resolver\Customer" xsi:type="string">
177177
Magento\CustomerGraphQl\Model\Resolver\Cache\Customer\ResolverCacheIdentity
178178
</item>
179-
<item name="Magento\CustomerGraphQl\Model\Resolver\IsSubscribed" xsi:type="string">
180-
Magento\CustomerGraphQl\Model\Resolver\Cache\Subscriber\ResolverCacheIdentity
181-
</item>
182179
</argument>
183180
</arguments>
184181
</type>
@@ -208,9 +205,6 @@
208205
<item name="Magento\CustomerGraphQl\Model\Resolver\Customer" xsi:type="array">
209206
<item name="current_customer_id" xsi:type="string">Magento\CustomerGraphQl\Model\Resolver\CacheKey\FactorProvider\CurrentCustomerId</item>
210207
</item>
211-
<item name="Magento\CustomerGraphQl\Model\Resolver\IsSubscribed" xsi:type="array">
212-
<item name="parent_customer_entity_id" xsi:type="string">Magento\CustomerGraphQl\Model\Resolver\CacheKey\FactorProvider\ParentCustomerEntityId</item>
213-
</item>
214208
</argument>
215209
</arguments>
216210
</type>

app/code/Magento/CustomerGraphQl/etc/schema.graphqls

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ type Customer @doc(description: "Defines the customer name, addresses, and other
136136
date_of_birth: String @doc(description: "The customer's date of birth.")
137137
taxvat: String @doc(description: "The customer's Value-added tax (VAT) number (for corporate customers).")
138138
id: Int @doc(description: "The ID assigned to the customer.") @deprecated(reason: "`id` is not needed as part of `Customer`, because on the server side, it can be identified based on the customer token used for authentication. There is no need to know customer ID on the client side.")
139-
is_subscribed: Boolean @doc(description: "Indicates whether the customer is subscribed to the company's newsletter.") @resolver(class: "\\Magento\\CustomerGraphQl\\Model\\Resolver\\IsSubscribed")
139+
is_subscribed: Boolean @doc(description: "Indicates whether the customer is subscribed to the company's newsletter.") @resolver(class: "\\Magento\\NewsletterGraphQl\\Model\\Resolver\\IsSubscribed")
140140
addresses: [CustomerAddress] @doc(description: "An array containing the customer's shipping and billing addresses.") @resolver(class: "\\Magento\\CustomerGraphQl\\Model\\Resolver\\CustomerAddresses")
141141
gender: Int @doc(description: "The customer's gender (Male - 1, Female - 2).")
142142
custom_attributes(attributeCodes: [ID!]): [AttributeValueInterface] @doc(description: "Customer's custom attributes.") @resolver(class: "Magento\\CustomerGraphQl\\Model\\Resolver\\CustomAttributeFilter")

app/code/Magento/Indexer/Block/Backend/Grid/Column/Renderer/Status.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ public function render(\Magento\Framework\DataObject $row)
3333
$class = 'grid-severity-minor';
3434
$text = __('Processing');
3535
break;
36+
case \Magento\Framework\Indexer\StateInterface::STATUS_SUSPENDED:
37+
$class = 'grid-severity-minor';
38+
$text = __('Suspended');
39+
break;
3640
}
3741
return '<span class="' . $class . '"><span>' . $text . '</span></span>';
3842
}
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Indexer\Console\Command;
9+
10+
use Magento\Framework\App\ObjectManagerFactory;
11+
use Magento\Framework\Console\Cli;
12+
use Magento\Framework\Exception\AlreadyExistsException;
13+
use Magento\Framework\Indexer\IndexerInterface;
14+
use Magento\Framework\Indexer\StateInterface;
15+
use Magento\Indexer\Model\ResourceModel\Indexer\State;
16+
use Symfony\Component\Console\Input\InputArgument;
17+
use Symfony\Component\Console\Input\InputInterface;
18+
use Symfony\Component\Console\Input\InputOption;
19+
use Symfony\Component\Console\Output\OutputInterface;
20+
21+
/**
22+
* Command for setting index status for indexers.
23+
*/
24+
class IndexerSetStatusCommand extends AbstractIndexerManageCommand
25+
{
26+
/**#@+
27+
* Names of input arguments or options
28+
*/
29+
private const INPUT_KEY_STATUS = 'status';
30+
/**#@- */
31+
32+
/**
33+
* @var State
34+
*/
35+
private State $stateResourceModel;
36+
37+
/**
38+
* @param State $stateResourceModel
39+
* @param ObjectManagerFactory $objectManagerFactory
40+
*/
41+
public function __construct(
42+
State $stateResourceModel,
43+
ObjectManagerFactory $objectManagerFactory
44+
) {
45+
$this->stateResourceModel = $stateResourceModel;
46+
parent::__construct($objectManagerFactory);
47+
}
48+
49+
/**
50+
* @inheritdoc
51+
*/
52+
protected function configure()
53+
{
54+
$this->setName('indexer:set-status')
55+
->setDescription('Sets the specified indexer status')
56+
->setDefinition($this->getInputList());
57+
58+
parent::configure();
59+
}
60+
61+
/**
62+
* @inheritdoc
63+
*/
64+
protected function execute(InputInterface $input, OutputInterface $output)
65+
{
66+
$errors = $this->validate($input);
67+
if ($errors) {
68+
throw new \InvalidArgumentException(implode("\n", $errors));
69+
}
70+
71+
$newStatus = $input->getArgument(self::INPUT_KEY_STATUS);
72+
$indexers = $this->getIndexers($input);
73+
$returnValue = Cli::RETURN_SUCCESS;
74+
75+
foreach ($indexers as $indexer) {
76+
try {
77+
$this->updateIndexerStatus($indexer, $newStatus, $output);
78+
} catch (\Exception $e) {
79+
$output->writeln($e->getMessage());
80+
$returnValue = Cli::RETURN_FAILURE;
81+
}
82+
}
83+
84+
return $returnValue;
85+
}
86+
87+
/**
88+
* Gets list of arguments for the command.
89+
*
90+
* @return InputOption[]
91+
*/
92+
public function getInputList(): array
93+
{
94+
$modeOptions[] = new InputArgument(
95+
self::INPUT_KEY_STATUS,
96+
InputArgument::REQUIRED,
97+
'Indexer status type [' . StateInterface::STATUS_INVALID
98+
. '|' . StateInterface::STATUS_SUSPENDED . '|' . StateInterface::STATUS_VALID . ']'
99+
);
100+
101+
return array_merge($modeOptions, parent::getInputList());
102+
}
103+
104+
/**
105+
* Checks if all CLI command options are provided.
106+
*
107+
* @param InputInterface $input
108+
* @return string[]
109+
*/
110+
private function validate(InputInterface $input): array
111+
{
112+
$errors = [];
113+
$acceptedValues = [
114+
StateInterface::STATUS_INVALID,
115+
StateInterface::STATUS_SUSPENDED,
116+
StateInterface::STATUS_VALID
117+
];
118+
$inputStatus = $input->getArgument(self::INPUT_KEY_STATUS);
119+
120+
if (!in_array($inputStatus, $acceptedValues, true)) {
121+
$acceptedValuesString = '"' . implode('", "', $acceptedValues) . '"';
122+
$errors[] = sprintf(
123+
'Invalid status "%s". Accepted values are %s.',
124+
$inputStatus,
125+
$acceptedValuesString
126+
);
127+
}
128+
129+
return $errors;
130+
}
131+
132+
/**
133+
* Updates the status of a specified indexer.
134+
*
135+
* @param IndexerInterface $indexer
136+
* @param string $newStatus
137+
* @param OutputInterface $output
138+
* @return void
139+
* @throws AlreadyExistsException
140+
*/
141+
private function updateIndexerStatus(IndexerInterface $indexer, string $newStatus, OutputInterface $output): void
142+
{
143+
$state = $indexer->getState();
144+
$previousStatus = $state->getStatus();
145+
$this->stateResourceModel->save($state->setStatus($newStatus));
146+
$currentStatus = $state->getStatus();
147+
148+
if ($previousStatus !== $currentStatus) {
149+
$output->writeln(
150+
sprintf(
151+
"Index status for Indexer '%s' was changed from '%s' to '%s'.",
152+
$indexer->getTitle(),
153+
$previousStatus,
154+
$currentStatus
155+
)
156+
);
157+
} else {
158+
$output->writeln(sprintf("Index status for Indexer '%s' has not been changed.", $indexer->getTitle()));
159+
}
160+
}
161+
}

app/code/Magento/Indexer/Console/Command/IndexerStatusCommand.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ private function getStatus(Indexer\IndexerInterface $indexer)
9595
case \Magento\Framework\Indexer\StateInterface::STATUS_WORKING:
9696
$status = 'Processing';
9797
break;
98+
case \Magento\Framework\Indexer\StateInterface::STATUS_SUSPENDED:
99+
$status = 'Suspended';
100+
break;
98101
}
99102
return $status;
100103
}

app/code/Magento/Indexer/Model/Indexer.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
namespace Magento\Indexer\Model;
88

9+
use Magento\Framework\DataObject;
910
use Magento\Framework\Indexer\ActionFactory;
1011
use Magento\Framework\Indexer\ActionInterface;
1112
use Magento\Framework\Indexer\ConfigInterface;
@@ -14,13 +15,14 @@
1415
use Magento\Framework\Indexer\StateInterface;
1516
use Magento\Framework\Indexer\StructureFactory;
1617
use Magento\Framework\Indexer\IndexerInterfaceFactory;
18+
use Magento\Framework\Indexer\SuspendableIndexerInterface;
1719

1820
/**
1921
* Indexer model.
2022
*
2123
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2224
*/
23-
class Indexer extends \Magento\Framework\DataObject implements IndexerInterface
25+
class Indexer extends DataObject implements IndexerInterface, SuspendableIndexerInterface
2426
{
2527
/**
2628
* @var string
@@ -332,6 +334,16 @@ public function isInvalid()
332334
return $this->getState()->getStatus() == StateInterface::STATUS_INVALID;
333335
}
334336

337+
/**
338+
* Checks whether indexer is suspended.
339+
*
340+
* @return bool
341+
*/
342+
public function isSuspended(): bool
343+
{
344+
return $this->getState()->getStatus() === StateInterface::STATUS_SUSPENDED;
345+
}
346+
335347
/**
336348
* Check whether indexer is working
337349
*

app/code/Magento/Indexer/Model/Processor.php

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
7+
68
namespace Magento\Indexer\Model;
79

810
use Magento\Framework\App\ObjectManager;
911
use Magento\Framework\Indexer\ConfigInterface;
1012
use Magento\Framework\Indexer\IndexerInterface;
1113
use Magento\Framework\Indexer\IndexerInterfaceFactory;
14+
use Magento\Framework\Indexer\IndexerRegistry;
15+
use Magento\Framework\Indexer\StateInterface;
1216
use Magento\Framework\Mview\ProcessorInterface;
1317
use Magento\Indexer\Model\Processor\MakeSharedIndexValid;
1418

@@ -47,25 +51,33 @@ class Processor
4751
*/
4852
protected $makeSharedValid;
4953

54+
/**
55+
* @var IndexerRegistry
56+
*/
57+
private IndexerRegistry $indexerRegistry;
58+
5059
/**
5160
* @param ConfigInterface $config
5261
* @param IndexerInterfaceFactory $indexerFactory
5362
* @param Indexer\CollectionFactory $indexersFactory
5463
* @param ProcessorInterface $mviewProcessor
5564
* @param MakeSharedIndexValid|null $makeSharedValid
65+
* @param IndexerRegistry|null $indexerRegistry
5666
*/
5767
public function __construct(
5868
ConfigInterface $config,
5969
IndexerInterfaceFactory $indexerFactory,
6070
Indexer\CollectionFactory $indexersFactory,
6171
ProcessorInterface $mviewProcessor,
62-
?MakeSharedIndexValid $makeSharedValid = null
72+
?MakeSharedIndexValid $makeSharedValid = null,
73+
?IndexerRegistry $indexerRegistry = null
6374
) {
6475
$this->config = $config;
6576
$this->indexerFactory = $indexerFactory;
6677
$this->indexersFactory = $indexersFactory;
6778
$this->mviewProcessor = $mviewProcessor;
6879
$this->makeSharedValid = $makeSharedValid ?: ObjectManager::getInstance()->get(MakeSharedIndexValid::class);
80+
$this->indexerRegistry = $indexerRegistry ?: ObjectManager::getInstance()->get(IndexerRegistry::class);
6981
}
7082

7183
/**
@@ -81,7 +93,9 @@ public function reindexAllInvalid()
8193
$indexer->load($indexerId);
8294
$indexerConfig = $this->config->getIndexer($indexerId);
8395

84-
if ($indexer->isInvalid()) {
96+
if ($indexer->isInvalid() && !$indexer->isSuspended()
97+
&& !$this->isSharedIndexSuspended($indexerConfig['shared_index'])
98+
) {
8599
// Skip indexers having shared index that was already complete
86100
$sharedIndex = $indexerConfig['shared_index'] ?? null;
87101
if (!in_array($sharedIndex, $this->sharedIndexesComplete)) {
@@ -97,6 +111,36 @@ public function reindexAllInvalid()
97111
}
98112
}
99113

114+
/**
115+
* Checks if any indexers within a group that share a common 'shared_index' ID are suspended.
116+
*
117+
* @param string|null $sharedIndexId
118+
* @return bool
119+
*/
120+
private function isSharedIndexSuspended(?string $sharedIndexId): bool
121+
{
122+
if ($sharedIndexId === null) {
123+
return false;
124+
}
125+
126+
$indexers = $this->config->getIndexers();
127+
128+
foreach ($indexers as $indexerId => $config) {
129+
// Check if the indexer shares the same 'shared_index'
130+
if (isset($config['shared_index']) && $config['shared_index'] === $sharedIndexId) {
131+
$indexer = $this->indexerRegistry->get($indexerId);
132+
133+
// If any indexer that shares the 'shared_index' is suspended, return true
134+
if ($indexer->getStatus() === StateInterface::STATUS_SUSPENDED) {
135+
return true;
136+
}
137+
}
138+
}
139+
140+
// If none of the shared indexers are suspended, return false
141+
return false;
142+
}
143+
100144
/**
101145
* Regenerate indexes for all indexers
102146
*

0 commit comments

Comments
 (0)