Skip to content

Commit d4562da

Browse files
committed
Merge branch 'release/3.16.0-dev' into chore/MAGE-1374-ci-on-3.17
2 parents 4110942 + c52d365 commit d4562da

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+608
-527
lines changed

.circleci/config.yml

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -181,18 +181,18 @@ workflows:
181181
magento-version: ["2.4.6-p11", "2.4.7-p6"]
182182
- notify:
183183
context: mage-slack
184-
magento-integration-test-workflow:
185-
when:
186-
or:
187-
- equal: [ main, << pipeline.git.branch >> ]
188-
- matches:
189-
pattern: ".*release.*"
190-
value: << pipeline.git.branch >>
191-
jobs:
192-
- magento-integration-test:
193-
matrix:
194-
parameters:
195-
php-version: ["8.2"]
196-
magento-version: ["2.4.7-p6"]
197-
- notify:
198-
context: mage-slack
184+
# magento-integration-test-workflow:
185+
# when:
186+
# or:
187+
# - equal: [ main, << pipeline.git.branch >> ]
188+
# - matches:
189+
# pattern: ".*release.*"
190+
# value: << pipeline.git.branch >>
191+
# jobs:
192+
# - magento-integration-test:
193+
# matrix:
194+
# parameters:
195+
# php-version: ["8.2"]
196+
# magento-version: ["2.4.7-p6"]
197+
# - notify:
198+
# context: mage-slack

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,14 @@
2222
- Fixed WSOD error on invalid creds when using manual SKU indexer (also included in 3.15.1).
2323
- Fixed Recommend model validation when configuring through the Magento admin
2424
- Fixed edge case with null queries - thank you @PromInc
25+
- Removed conditional behavior on setting the vary string from the plugin on `\Magento\Framework\App\Http\Context` so that a consistent `X-Magento-Vary` cookie is sent across all requests
2526

2627
### Updates
2728
- `beforecontent.html` is no longer used and has been deprecated. If you're overriding or referencing this file, please update your layout and customizations accordingly.
2829
- An additional separate crontab is no longer needed to run the indexing queue. Enable via admin config to run the queue using Magento's built-in cron.
2930
- `BatchQueueProcessorInterface` has been introduced to decouple Algolia operations for core `Indexer` models.
3031
- Magento will set a default `renderingContent` based on its configured facets. Be sure that "Facet Display" is supported by your Algolia plan before attempting to use.
31-
- Auto full indexing is disabled by default in this release. If you require this legacy feature then it can be re-enabled via the Magento admin under Stores > Configuration > Algolia Search > Indexing Manager
32+
- Auto full indexing can be disabled in this release under Stores > Configuration > Algolia Search > Indexing Manager. We are moving towards more intentional indexing so please note that this will become the default in a future release.
3233
- InstantSearch has been refactored to support customization via JavaScript mixins.
3334
- A new front end hook called `beforeFacetInitialization` has been added which allows a user to extend the functionality by adding, removing or modifying "builder" functions which are used to define a facet config that will drive the rendering of facets.
3435
- Removed InstantSearch enablement dependency in Magento admin to prevent losing facet and sorting config when disabling the feature.
@@ -42,6 +43,8 @@
4243
- Added support for PHPUnit 10
4344
- Added support for Magento 2.4.8 on PHP 8.4 - Special shout out to @jajajaime for his help here
4445
- Refactored code to PHP 8.2 baseline standard
46+
- Added string escaping to untrusted inputs
47+
- The InstantSearch "replace categories" feature must now be explicitly enabled on new instances aligning with our documentation: https://www.algolia.com/doc/integration/magento-2/guides/category-pages/#enable-category-pages
4548

4649
### Breaking Changes
4750
- `ProductHelper::setSettings()` is now taking `IndexOptions` objects as two first parameters instead of index names (strings).

Helper/ConfigHelper.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1233,7 +1233,8 @@ public function preventBackendRendering($storeId = null): bool
12331233
if (!isset($_SERVER['HTTP_USER_AGENT'])) {
12341234
return false;
12351235
}
1236-
$userAgent = mb_strtolower((string) $_SERVER['HTTP_USER_AGENT'], 'utf-8');
1236+
$userAgent = mb_strtolower((string) filter_input(INPUT_SERVER, 'HTTP_USER_AGENT', FILTER_SANITIZE_SPECIAL_CHARS), 'utf-8');
1237+
12371238
$allowedUserAgents = $this->configInterface->getValue(
12381239
self::BACKEND_RENDERING_ALLOWED_USER_AGENTS,
12391240
ScopeInterface::SCOPE_STORE,

Model/Backend/QueueCron.php

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88
class QueueCron extends Value
99
{
10-
const CRON_REGEX = '/^(\*|[0-9,\-\/\*]+)\s+(\*|[0-9,\-\/\*]+)\s+(\*|[0-9,\-\/\*]+)\s+(\*|[0-9,\-\/\*]+)\s+(\*|[0-9,\-\/\*]+)$/';
10+
const CRON_FORMAT_REGEX = '/^(\*|[0-9,\-\/\*]+)\s+(\*|[0-9,\-\/\*]+)\s+(\*|[0-9,\-\/\*]+)\s+(\*|[0-9,\-\/\*]+)\s+(\*|[0-9,\-\/\*]+)$/';
11+
const CRON_DISALLOW_REGEX = '/[^@a-z0-9\*\-,\/ ]/';
1112

1213
protected array $mappings = [
1314
'@yearly' => '0 0 1 1 *',
@@ -27,8 +28,19 @@ public function beforeSave()
2728
$this->setValue($value);
2829
}
2930

30-
if (!preg_match(self::CRON_REGEX, $value)) {
31-
throw new InvalidCronException("Cron expression \"$value\" is not valid.");
31+
if (!preg_match(self::CRON_FORMAT_REGEX, $value)) {
32+
// This use of preg_replace is safe — static regex without /e modifier.
33+
// phpcs:ignore
34+
$safeValue = preg_replace(self::CRON_DISALLOW_REGEX, '', (string) $value);
35+
$msg = ($safeValue !== $value)
36+
? 'Cron expression is invalid.'
37+
: sprintf(
38+
'Cron expression "%s" is not valid.',
39+
htmlspecialchars($safeValue, ENT_QUOTES, 'UTF-8')
40+
);
41+
// Content is already escaped at this point
42+
// phpcs:ignore
43+
throw new InvalidCronException($msg);
3244
}
3345

3446
return parent::beforeSave();

Plugin/RenderingCacheContextPlugin.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Algolia\AlgoliaSearch\Plugin;
44

55
use Algolia\AlgoliaSearch\Helper\ConfigHelper;
6+
use Algolia\AlgoliaSearch\Helper\Configuration\InstantSearchHelper;
67
use Magento\Framework\App\Http\Context as HttpContext;
78
use Magento\Framework\App\Request\Http;
89
use Magento\Framework\Exception\NoSuchEntityException;
@@ -25,7 +26,8 @@ class RenderingCacheContextPlugin
2526
public const CATEGORY_ROUTE = 'catalog/category/view';
2627

2728
public function __construct(
28-
protected ConfigHelper $configHelper,
29+
protected ConfigHelper $baseConfig,
30+
protected InstantSearchHelper $isConfig,
2931
protected StoreManagerInterface $storeManager,
3032
protected Http $request,
3133
protected UrlFinderInterface $urlFinder
@@ -50,7 +52,7 @@ public function afterGetData(HttpContext $subject, array $data): array {
5052
return $data;
5153
}
5254

53-
$context = $this->configHelper->preventBackendRendering() ?
55+
$context = $this->baseConfig->preventBackendRendering() ?
5456
self::RENDERING_WITHOUT_BACKEND :
5557
self::RENDERING_WITH_BACKEND;
5658

@@ -89,6 +91,7 @@ protected function isCategoryRoute(string $path): bool {
8991
*
9092
* @param int $storeId
9193
* @return bool
94+
* @deprecated This method will be removed in a future version
9295
*/
9396
protected function isCategoryPage(int $storeId): bool
9497
{
@@ -104,6 +107,6 @@ protected function isCategoryPage(int $storeId): bool
104107
protected function shouldApplyCacheContext(): bool
105108
{
106109
$storeId = $this->storeManager->getStore()->getId();
107-
return $this->isCategoryPage($storeId) && $this->configHelper->replaceCategories($storeId);
110+
return $this->isConfig->shouldReplaceCategories($storeId);
108111
}
109112
}

Setup/Patch/Schema/ConfigPatch.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ class ConfigPatch implements SchemaPatchInterface
5151
'algoliasearch_instant/instant/instant_selector' => '.columns',
5252
'algoliasearch_instant/instant/number_product_results' => '9',
5353
'algoliasearch_instant/instant/max_values_per_facet' => '10',
54-
'algoliasearch_instant/instant/replace_categories' => '1',
5554
'algoliasearch_instant/instant/show_suggestions_on_no_result_page' => '1',
5655
'algoliasearch_instant/instant/add_to_cart_enable' => '1',
5756
'algoliasearch_instant/instant/infinite_scroll_enable' => '0',

Test/Unit/Model/Backend/QueueCronTest.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ protected function setUp(): void
3131
/**
3232
* @dataProvider valuesProvider
3333
*/
34-
public function testInput($value, $isValid): void
34+
public function testInput($value, $isValid, $canReplay = true): void
3535
{
3636
$this->queueCronModel->setValue($value);
3737

@@ -45,8 +45,11 @@ public function testInput($value, $isValid): void
4545
"Cron expression \"$value\" is not valid but it should be."
4646
);
4747

48+
$msg = $canReplay
49+
? "Cron expression \"$value\" is not valid."
50+
: "Cron expression is invalid.";
4851
$this->assertEquals(
49-
"Cron expression \"$value\" is not valid.",
52+
$msg,
5053
$exception->getMessage()
5154
);
5255
}
@@ -94,6 +97,11 @@ public static function valuesProvider(): array
9497
[
9598
'value' => '@foo', // Not working alias
9699
'isValid' => false
100+
],
101+
[
102+
'value' => '"><script>alert(\'XSS\')</script>',
103+
'isValid' => false,
104+
'canReplay' => false
97105
]
98106
];
99107
}

Test/Unit/Plugin/RenderingCacheContextPluginTest.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,34 @@
33
namespace Algolia\AlgoliaSearch\Test\Unit\Plugin;
44

55
use Algolia\AlgoliaSearch\Helper\ConfigHelper;
6+
use Algolia\AlgoliaSearch\Helper\Configuration\InstantSearchHelper;
67
use Algolia\AlgoliaSearch\Plugin\RenderingCacheContextPlugin;
78
use Magento\Framework\App\Http\Context as HttpContext;
89
use Magento\Framework\App\Request\Http;
910
use Magento\Store\Api\Data\StoreInterface;
1011
use Magento\Store\Model\StoreManagerInterface;
1112
use Magento\UrlRewrite\Model\UrlFinderInterface;
1213
use PHPUnit\Framework\TestCase;
13-
1414
class RenderingCacheContextPluginTest extends TestCase
1515
{
1616
protected ?RenderingCacheContextPlugin $plugin;
1717
protected ?ConfigHelper $configHelper;
18+
19+
protected ?InstantSearchHelper $instantSearchHelper;
1820
protected ?StoreManagerInterface $storeManager;
1921
protected ?Http $request;
2022
protected ?UrlFinderInterface $urlFinder;
21-
2223
protected function setUp(): void
2324
{
2425
$this->configHelper = $this->createMock(ConfigHelper::class);
26+
$this->instantSearchHelper = $this->createMock(InstantSearchHelper::class);
2527
$this->storeManager = $this->createMock(StoreManagerInterface::class);
2628
$this->request = $this->createMock(Http::class);
2729
$this->urlFinder = $this->createMock(UrlFinderInterface::class);
2830

2931
$this->plugin = new RenderingCacheContextPluginTestable(
3032
$this->configHelper,
33+
$this->instantSearchHelper,
3134
$this->storeManager,
3235
$this->request,
3336
$this->urlFinder
@@ -47,7 +50,7 @@ public function testAfterGetDataAddsRenderingContextNoBackendRender(): void
4750
$this->storeManager->method('getStore')->willReturn($this->getStoreMock());
4851

4952
$this->request->method('getControllerName')->willReturn('category');
50-
$this->configHelper->method('replaceCategories')->willReturn(true);
53+
$this->instantSearchHelper->method('shouldReplaceCategories')->willReturn(true);
5154

5255
$result = $this->plugin->afterGetData(
5356
$this->createMock(HttpContext::class),
@@ -66,7 +69,7 @@ public function testAfterGetDataAddsRenderingContextWithBackendRender(): void
6669
$this->storeManager->method('getStore')->willReturn($this->getStoreMock());
6770

6871
$this->request->method('getControllerName')->willReturn('category');
69-
$this->configHelper->method('replaceCategories')->willReturn(true);
72+
$this->instantSearchHelper->method('shouldReplaceCategories')->willReturn(true);
7073

7174
$result = $this->plugin->afterGetData(
7275
$this->createMock(HttpContext::class),
@@ -86,7 +89,7 @@ public function testAfterGetDataDoesNotModifyDataIfNotApplicable(): void
8689

8790
$this->request->method('getControllerName')->willReturn('product');
8891
$this->request->method('getRequestUri')->willReturn('some-product.html');
89-
$this->configHelper->method('replaceCategories')->willReturn(false);
92+
$this->instantSearchHelper->method('shouldReplaceCategories')->willReturn(false);
9093

9194
$data = ['existing_key' => 'existing_value'];
9295
$result = $this->plugin->afterGetData($subject, $data);
@@ -121,7 +124,7 @@ public function testShouldApplyCacheContext(): void
121124
$this->storeManager->method('getStore')->willReturn($this->getStoreMock());
122125

123126
$this->request->method('getControllerName')->willReturn('category');
124-
$this->configHelper->method('replaceCategories')->willReturn(true);
127+
$this->instantSearchHelper->method('shouldReplaceCategories')->willReturn(true);
125128

126129
$this->assertTrue($this->plugin->shouldApplyCacheContext());
127130
}

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"license": ["MIT"],
66
"version": "3.17.0-dev",
77
"require": {
8-
"php": "~8.1|~8.2|~8.3",
8+
"php": "~8.2|~8.3|~8.4",
99
"magento/framework": "~103.0",
1010
"algolia/algoliasearch-client-php": "4.18.3",
1111
"guzzlehttp/guzzle": "^6.3.3|^7.3.0",

etc/config.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
</redirects>
3030
</algoliasearch_autocomplete>
3131
<algoliasearch_instant>
32+
<instant>
33+
<replace_categories>0</replace_categories>
34+
</instant>
3235
<instant_facets>
3336
<facets><![CDATA[{"_1458145454535_587":{"attribute":"price","type":"slider","label":"Price","searchable":"2","create_rule":"2"},"_2541608784525_123":{"attribute":"categories","type":"conjunctive","label":"Categories","searchable":"2","create_rule":"2"},"_3211608784535_456":{"attribute":"color","type":"disjunctive","label":"Colors","searchable":"1","create_rule":"2"}}]]></facets>
3437
<max_values_per_facet>10</max_values_per_facet>

0 commit comments

Comments
 (0)