Skip to content

Commit 76bed0a

Browse files
authored
Merge pull request #1754 from algolia/release/3.14.5-dev
Release/3.14.5
2 parents ca83e9a + 2d78797 commit 76bed0a

33 files changed

+1645
-234
lines changed

Api/Product/ReplicaManagerInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public function syncReplicasToAlgolia(int $storeId, array $primaryIndexSettings)
3131
/**
3232
* Delete the replica indices on a store index
3333
* @param int $storeId
34-
* @param bool $unused Defaults to false - if true identifies any straggler indices and deletes those, otherwise deletes the replicas it knows aobut
34+
* @param bool $unused Defaults to false - if true identifies any straggler indices and deletes those, otherwise deletes the replicas it knows about
3535
* @return void
3636
*
3737
* @throws LocalizedException

Block/Configuration.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ public function getConfiguration()
275275
'autofocus' => true,
276276
'resultPageUrl' => $this->getCatalogSearchHelper()->getResultUrl(),
277277
'request' => [
278-
'query' => htmlspecialchars(html_entity_decode($query)),
278+
'query' => htmlspecialchars(html_entity_decode((string)$query)),
279279
'refinementKey' => $refinementKey,
280280
'refinementValue' => $refinementValue,
281281
'categoryId' => $categoryId,

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
# CHANGE LOG
22

3+
## 3.14.5
4+
5+
### Features
6+
- Added new CLI command for synonyms deduplication
7+
8+
### Updates
9+
- Updated integration tests to use `AlgoliaConnector`
10+
- Updated `ReplicaManager` service to handle multi stores properly with a `$storeId` parameter.
11+
12+
### Bug Fixes
13+
- Fixed a bug where full page cache (FPC) didn't work on category pages
14+
- Fixed customer groups prices ranges on configurable products
15+
- Fixed a bug where excluded websites weren't taken into account while indexing customer prices on products. (thanks @kamilszewczyk)
16+
- Fixed `RebuildReplicasPatch` bug where replica detach logic wasn't properly applied in some cases.
17+
- Fixed a bug where credentials errors weren't gracefully handled on the SKU reindexing form
18+
- Fixed a bug where the `q` parameter wasn't properly handled in case it was missing on the catalogsearch page. (thanks @PromInc)
19+
- Fixed Recommend model validation when configuration is saved in the Magento admin.
20+
321
## 3.14.4
422

523
### Features

Console/Command/AbstractReplicaCommand.php

Lines changed: 3 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -2,123 +2,11 @@
22

33
namespace Algolia\AlgoliaSearch\Console\Command;
44

5-
use Algolia\AlgoliaSearch\Service\StoreNameFetcher;
6-
use Magento\Framework\App\Area;
7-
use Magento\Framework\App\State;
8-
use Magento\Framework\Exception\LocalizedException;
9-
use Symfony\Component\Console\Command\Command;
10-
use Symfony\Component\Console\Input\InputArgument;
11-
use Symfony\Component\Console\Input\InputInterface;
12-
use Symfony\Component\Console\Output\OutputInterface;
13-
use Symfony\Component\Console\Question\ConfirmationQuestion;
14-
15-
abstract class AbstractReplicaCommand extends Command
5+
abstract class AbstractReplicaCommand extends AbstractStoreCommand
166
{
17-
protected const STORE_ARGUMENT = 'store';
18-
19-
protected ?OutputInterface $output = null;
20-
protected ?InputInterface $input = null;
21-
22-
public function __construct(
23-
protected State $state,
24-
protected StoreNameFetcher $storeNameFetcher,
25-
?string $name = null
26-
)
27-
{
28-
parent::__construct($name);
29-
}
30-
31-
abstract protected function getReplicaCommandName(): string;
32-
33-
abstract protected function getCommandDescription(): string;
34-
35-
abstract protected function getStoreArgumentDescription(): string;
36-
37-
abstract protected function getAdditionalDefinition(): array;
38-
39-
/**
40-
* @inheritDoc
41-
*/
42-
protected function configure(): void
43-
{
44-
$definition = [$this->getStoreArgumentDefinition()];
45-
$definition = array_merge($definition, $this->getAdditionalDefinition());
46-
47-
$this->setName($this->getCommandName())
48-
->setDescription($this->getCommandDescription())
49-
->setDefinition($definition);
50-
51-
parent::configure();
52-
}
53-
54-
protected function getStoreArgumentDefinition(): InputArgument {
55-
return new InputArgument(
56-
self::STORE_ARGUMENT,
57-
InputArgument::OPTIONAL | InputArgument::IS_ARRAY,
58-
$this->getStoreArgumentDescription()
59-
);
60-
}
61-
62-
public function getCommandName(): string
63-
{
64-
return 'algolia:replicas:' . $this->getReplicaCommandName();
65-
}
66-
67-
protected function setAreaCode(): void
68-
{
69-
try {
70-
$this->state->setAreaCode(Area::AREA_CRONTAB);
71-
} catch (LocalizedException) {
72-
// Area code is already set - nothing to do
73-
}
74-
}
75-
76-
/**
77-
* @param InputInterface $input
78-
* @return int[]
79-
*/
80-
protected function getStoreIds(InputInterface $input): array
81-
{
82-
return (array) $input->getArgument(self::STORE_ARGUMENT);
83-
}
84-
85-
/**
86-
* @param int[] $storeIds
87-
* @return string
88-
*/
89-
protected function getOperationTargetLabel(array $storeIds): string
90-
{
91-
return ($storeIds ? count($storeIds) : 'all') . ' store' . (!$storeIds || count($storeIds) > 1 ? 's' : '');
92-
}
93-
94-
/**
95-
* Generate a CLI operation announcement based on passed store arguments
96-
* @param string $msg Use {{target} in message as a placeholder for inserting the generated target label
97-
* @param int[] $storeIds
98-
* @return string
99-
*/
100-
protected function decorateOperationAnnouncementMessage(string $msg, array $storeIds): string
7+
protected function getCommandPrefix(): string
1018
{
102-
$msg = str_replace('{{target}}', $this->getOperationTargetLabel($storeIds), $msg);
103-
return ($storeIds)
104-
? "<info>$msg: " . join(", ", $this->storeNameFetcher->getStoreNames($storeIds)) . '</info>'
105-
: "<info>$msg</info>";
9+
return parent::getCommandPrefix() . 'replicas:';
10610
}
10711

108-
protected function confirmOperation(string $okMessage = '', string $cancelMessage = 'Operation cancelled'): bool
109-
{
110-
$helper = $this->getHelper('question');
111-
$question = new ConfirmationQuestion('<question>Are you sure wish to proceed? (y/n)</question> ', false);
112-
if (!$helper->ask($this->input, $this->output, $question)) {
113-
if ($cancelMessage) {
114-
$this->output->writeln("<comment>$cancelMessage</comment>");
115-
}
116-
return false;
117-
}
118-
119-
if ($okMessage) {
120-
$this->output->writeln("<comment>$okMessage</comment>");
121-
}
122-
return true;
123-
}
12412
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
<?php
2+
3+
namespace Algolia\AlgoliaSearch\Console\Command;
4+
5+
use Algolia\AlgoliaSearch\Service\StoreNameFetcher;
6+
use Magento\Framework\App\Area;
7+
use Magento\Framework\App\State;
8+
use Magento\Framework\Exception\LocalizedException;
9+
use Magento\Framework\Exception\NoSuchEntityException;
10+
use Symfony\Component\Console\Command\Command;
11+
use Symfony\Component\Console\Input\InputArgument;
12+
use Symfony\Component\Console\Input\InputInterface;
13+
use Symfony\Component\Console\Output\OutputInterface;
14+
use Symfony\Component\Console\Question\ConfirmationQuestion;
15+
16+
abstract class AbstractStoreCommand extends Command
17+
{
18+
protected const STORE_ARGUMENT = 'store_id';
19+
20+
protected ?OutputInterface $output = null;
21+
protected ?InputInterface $input = null;
22+
23+
abstract protected function getCommandName(): string;
24+
abstract protected function getCommandDescription(): string;
25+
abstract protected function getAdditionalDefinition(): array;
26+
abstract protected function getStoreArgumentDescription(): string;
27+
28+
public function __construct(
29+
protected State $state,
30+
protected StoreNameFetcher $storeNameFetcher,
31+
?string $name = null
32+
)
33+
{
34+
parent::__construct($name);
35+
}
36+
37+
protected function getCommandPrefix(): string
38+
{
39+
return 'algolia:';
40+
}
41+
42+
protected function getFullCommandName(): string
43+
{
44+
return $this->getCommandPrefix() . $this->getCommandName();
45+
}
46+
47+
/**
48+
* @inheritDoc
49+
*/
50+
protected function configure(): void
51+
{
52+
$definition = [$this->getStoreArgumentDefinition()];
53+
$definition = array_merge($definition, $this->getAdditionalDefinition());
54+
55+
$this->setName($this->getFullCommandName())
56+
->setDescription($this->getCommandDescription())
57+
->setDefinition($definition);
58+
59+
parent::configure();
60+
}
61+
62+
protected function setAreaCode(): void
63+
{
64+
try {
65+
$this->state->setAreaCode(Area::AREA_CRONTAB);
66+
} catch (LocalizedException $e) {
67+
// Area code is already set - nothing to do - but report regardless
68+
$this->output->writeln("Unable to set area code due to the following error: " . $e->getMessage());
69+
}
70+
}
71+
72+
/**
73+
* @param InputInterface $input
74+
* @return int[]
75+
* @throws LocalizedException
76+
*/
77+
protected function getStoreIds(InputInterface $input): array
78+
{
79+
return $this->validateStoreIds((array) $input->getArgument(self::STORE_ARGUMENT));
80+
}
81+
82+
/**
83+
* @param array $storeIds
84+
* @return int[]
85+
* @throws LocalizedException
86+
*/
87+
protected function validateStoreIds(array $storeIds): array
88+
{
89+
foreach ($storeIds as $storeId) {
90+
if (!ctype_digit($storeId) || (int) $storeId < 1) {
91+
throw new LocalizedException(__("Store ID argument must be an integer"));
92+
}
93+
}
94+
95+
return array_map('intval', $storeIds);
96+
}
97+
98+
protected function getStoreArgumentDefinition(): InputArgument {
99+
return new InputArgument(
100+
self::STORE_ARGUMENT,
101+
InputArgument::OPTIONAL | InputArgument::IS_ARRAY,
102+
$this->getStoreArgumentDescription()
103+
);
104+
}
105+
106+
/**
107+
* @param int[] $storeIds
108+
* @return string
109+
*/
110+
protected function getOperationTargetLabel(array $storeIds): string
111+
{
112+
return ($storeIds ? count($storeIds) : 'all') . ' store' . (!$storeIds || count($storeIds) > 1 ? 's' : '');
113+
}
114+
115+
/**
116+
* Generate a CLI operation announcement based on passed store arguments
117+
* @param string $msg Use {{target} in message as a placeholder for inserting the generated target label
118+
* @param int[] $storeIds
119+
* @return string
120+
* @throws NoSuchEntityException
121+
*/
122+
protected function decorateOperationAnnouncementMessage(string $msg, array $storeIds): string
123+
{
124+
$msg = str_replace('{{target}}', $this->getOperationTargetLabel($storeIds), $msg);
125+
return ($storeIds)
126+
? "<info>$msg: " . join(", ", $this->storeNameFetcher->getStoreNames($storeIds)) . '</info>'
127+
: "<info>$msg</info>";
128+
}
129+
130+
protected function confirmOperation(string $okMessage = '', string $cancelMessage = 'Operation cancelled'): bool
131+
{
132+
$helper = $this->getHelper('question');
133+
$question = new ConfirmationQuestion('<question>Are you sure wish to proceed? (y/n)</question> ', false);
134+
if (!$helper->ask($this->input, $this->output, $question)) {
135+
if ($cancelMessage) {
136+
$this->output->writeln("<comment>$cancelMessage</comment>");
137+
}
138+
return false;
139+
}
140+
141+
if ($okMessage) {
142+
$this->output->writeln("<comment>$okMessage</comment>");
143+
}
144+
return true;
145+
}
146+
}

Console/Command/ReplicaDeleteCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public function __construct(
3333
parent::__construct($state, $storeNameFetcher, $name);
3434
}
3535

36-
protected function getReplicaCommandName(): string
36+
protected function getCommandName(): string
3737
{
3838
return 'delete';
3939
}

Console/Command/ReplicaDisableVirtualCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public function __construct(
4242
parent::__construct($state, $storeNameFetcher, $name);
4343
}
4444

45-
protected function getReplicaCommandName(): string
45+
protected function getCommandName(): string
4646
{
4747
return 'disable-virtual-replicas';
4848
}

Console/Command/ReplicaRebuildCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public function __construct(
3838
parent::__construct($appState, $storeNameFetcher, $name);
3939
}
4040

41-
protected function getReplicaCommandName(): string
41+
protected function getCommandName(): string
4242
{
4343
return 'rebuild';
4444
}

Console/Command/ReplicaSyncCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public function __construct(
3535
parent::__construct($appState, $storeNameFetcher, $name);
3636
}
3737

38-
protected function getReplicaCommandName(): string
38+
protected function getCommandName(): string
3939
{
4040
return 'sync';
4141
}

0 commit comments

Comments
 (0)