diff --git a/CHANGELOG.md b/CHANGELOG.md index d6e565f61..744fee94f 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # CHANGE LOG +## 3.17.1 + +### Updates +- Removed `Magento\Catalog\Model\Product\Url` preference +- Moved `algolia_algoliasearch_plugin_category_url` plugin to global area so it can be used in the new indexers +- Added "Extension/Magento versions support" paragraphs to the README file. + ## 3.17.0 ### Features diff --git a/Model/Product/Url.php b/Model/Product/Url.php deleted file mode 100755 index a43da214b..000000000 --- a/Model/Product/Url.php +++ /dev/null @@ -1,150 +0,0 @@ -objectManager = $objectManager; - parent::__construct($urlFactory, $storeManager, $filter, $sidResolver, $urlFinder, $data); - } - - /** - * The only rewritten line in this method is the return statement - * - * @param Product $product - * @param array $params - * - * @throws \Magento\Framework\Exception\NoSuchEntityException - * - * @return string - * - */ - public function getUrl(Product $product, $params = []) - { - $routePath = ''; - $routeParams = $params; - - $storeId = $product->getStoreId(); - - $categoryId = $this->getCategoryId($product, $params); - - $urlDataObject = $product->getData('url_data_object'); - if ($urlDataObject !== null) { - $requestPath = $urlDataObject->getUrlRewrite(); - $routeParams['_scope'] = $urlDataObject->getStoreId(); - } else { - $requestPath = $product->getRequestPath(); - if (empty($requestPath) && $requestPath !== false) { - $filterData = [ - UrlRewrite::ENTITY_ID => $product->getId(), - UrlRewrite::ENTITY_TYPE => ProductUrlRewriteGenerator::ENTITY_TYPE, - UrlRewrite::STORE_ID => $storeId, - UrlRewrite::REDIRECT_TYPE => 0, - ]; - if ($categoryId) { - $filterData[UrlRewrite::METADATA]['category_id'] = $categoryId; - } - $rewrite = $this->urlFinder->findOneByData($filterData); - if ($rewrite) { - $requestPath = $rewrite->getRequestPath(); - $product->setRequestPath($requestPath); - } else { - $product->setRequestPath(false); - } - } - } - - if (isset($routeParams['_scope'])) { - $storeId = $this->storeManager->getStore($routeParams['_scope'])->getId(); - } - - // Loose (==) comparison on purpose - if ($storeId != $this->storeManager->getStore()->getId()) { - $routeParams['_scope_to_url'] = true; - } - - if ($requestPath) { - $routeParams['_direct'] = $requestPath; - } else { - $routePath = 'catalog/product/view'; - $routeParams['id'] = $product->getId(); - $routeParams['s'] = $product->getUrlKey(); - if ($categoryId) { - $routeParams['category'] = $categoryId; - } - } - - // reset cached URL instance GET query params - if (!isset($routeParams['_query'])) { - $routeParams['_query'] = []; - } - - /* - * This is the only line changed from the default method. - * For reference, the original line: - * $this->getUrlInstance()->setScope($storeId)->getUrl($routePath, $routeParams); - * getUrlInstance() is a private method, so a new method has been written that - * will create a frontend Url object - * if the store scope is not the admin scope. - */ - return $this->getStoreScopeUrlInstance($storeId)->getUrl($routePath, $routeParams); - } - - /** - * If the store id passed in is admin (0), will return a Backend Url object (Default \Magento\Backend\Model\Url), - * otherwise returns the default Url object (default \Magento\Framework\Url) - * - * @param int $storeId - * - * @return mixed - */ - public function getStoreScopeUrlInstance($storeId) - { - if (!$storeId) { - return $this->objectManager->create(\Magento\Backend\Model\Url::class); - } - - return $this->objectManager->create(\Magento\Framework\Url::class); - } - - private function getCategoryId(Product $product, $params) - { - $categoryId = null; - - if (!isset($params['_ignore_category']) - && $product->getCategoryId() - && !$product->getData('do_not_use_category_id')) { - $categoryId = $product->getCategoryId(); - } - - return $categoryId; - } -} diff --git a/README.md b/README.md index eaead7ab1..eb7618983 100755 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ Algolia Search & Discovery extension for Magento 2 ================================================== -![Latest version](https://img.shields.io/badge/latest-3.17.0-green) +![Latest version](https://img.shields.io/badge/latest-3.17.1-green) ![Magento 2](https://img.shields.io/badge/Magento-2.4.7+-orange) -![PHP](https://img.shields.io/badge/PHP-8.1%2C8.2%2C8.3%2C8.4-blue) +![PHP](https://img.shields.io/badge/PHP-8.2%2C8.3%2C8.4-blue) [![CircleCI](https://circleci.com/gh/algolia/algoliasearch-magento-2/tree/main.svg?style=svg)](https://circleci.com/gh/algolia/algoliasearch-magento-2/tree/main) @@ -35,6 +35,16 @@ Magento 2.3 and earlier versions are no longer supported by the Algolia extensio Version 3.x of our extension is compatible with Magento 2.4. Review the [Customisation](https://github.com/algolia/algoliasearch-magento-2#customisation) section to learn more about the differences between our extension versions. +### Extension versions support + +We support the two latest minor versions of our extension (see "Extension Version" column in the compatibility matrix below) : +- The 2 latest minor versions are maintained with security and critical bug fixes. +- The latest minor version is maintained with "general" bug fixes as well. + +### Magento versions support + +We support the 2 or 3 latest patch versions of Magento depending on releases overlap (see matrix below): + | Extension Version | End of Life | Magento | PHP | |-------------------|-------------|------------------------------|----------------------------------------| | v3.7.x | 10/10/2023 | `~2.3.7\|\|~2.4.5\|\|~2.4.6` | `~7.3.0\|\|~7.4.0\|\|~8.1.0\|\|~8.2.0` | @@ -45,8 +55,9 @@ Version 3.x of our extension is compatible with Magento 2.4. Review the [Customi | v3.12.x | 8/2/2024 | `~2.4.6` | `~8.1.0\|\|~8.2.0` | | v3.13.x | 4/9/2025 | `~2.4.6` | `~8.1.0\|\|~8.2.0` | | v3.14.x | 9/1/2025 | `~2.4.6\|\|~2.4.7` | `~8.1.0\|\|~8.2.0\|\|~8.3.0` | -| v3.15.x | N/A | `~2.4.6\|\|~2.4.7` | `~8.1.0\|\|~8.2.0\|\|~8.3.0` | +| v3.15.x | 12/1/2025 | `~2.4.6\|\|~2.4.7` | `~8.1.0\|\|~8.2.0\|\|~8.3.0` | | v3.16.x | N/A | `~2.4.7\|\|~2.4.8` | `~8.2.0\|\|~8.3.0\|\|~8.4.0` | +| v3.17.x | N/A | `~2.4.7\|\|~2.4.8` | `~8.2.0\|\|~8.3.0\|\|~8.4.0` | ## Documentation @@ -80,15 +91,15 @@ Please check our [Custom Extension](https://github.com/algolia/algoliasearch-cus Knowing the version of each Algolia JavaScript library will help you understand what is available for you to leverage in terms of customisation. This table will help you determine which documentation to reference when you start working on your customisation. | Extension Version | autocomplete.js | instantsearch.js | search-insights.js | recommend-js.js | -|-------------------|--------------------------------------------------------------------|--------------------------------------------------------------------------------|----------------------------------------------------------------------|-------------------------------------------------------------| -| v3.x | [0.38.0](https://github.com/algolia/autocomplete.js/tree/v0.38.0)* | [4.15.0](https://github.com/algolia/instantsearch.js/tree/v4.15.0)* | [1.7.1](https://github.com/algolia/search-insights.js/tree/v1.7.1) | NA | -| v3.9.1 | [1.6.3](https://github.com/algolia/autocomplete.js/tree/v1.6.3)* | [4.41.0](https://github.com/algolia/instantsearch.js/tree/v4.41.0)* | [1.7.1](https://github.com/algolia/search-insights.js/tree/v1.7.1) | [1.5.0](https://github.com/algolia/recommend/tree/v1.5.0) | -| v3.10.x | [1.6.3](https://github.com/algolia/autocomplete.js/tree/v1.6.3)* | [4.41.0](https://github.com/algolia/instantsearch.js/tree/v4.41.0)* | [1.7.1](https://github.com/algolia/search-insights.js/tree/v1.7.1) | [1.8.0](https://github.com/algolia/recommend/tree/v1.8.0) | -| v3.11.0 | [1.6.3](https://github.com/algolia/autocomplete.js/tree/v1.6.3)* | [4.41.0](https://github.com/algolia/instantsearch.js/tree/v4.41.0)* | [2.6.0](https://github.com/algolia/search-insights.js/tree/v2.6.0) | [1.8.0](https://github.com/algolia/recommend/tree/v1.8.0) | -| v3.13.0 | [1.6.3](https://github.com/algolia/autocomplete.js/tree/v1.6.3)* | [4.63.0](https://github.com/algolia/instantsearch/tree/instantsearch.js%404.63.0)* | [2.11.0](https://github.com/algolia/search-insights.js/tree/v2.11.0) | [1.8.0](https://github.com/algolia/recommend/tree/v1.8.0) | -| v3.14.x | [1.6.3](https://github.com/algolia/autocomplete.js/tree/v1.6.3)* | [4.63.0](https://github.com/algolia/instantsearch/tree/instantsearch.js%404.63.0)* | [2.11.0](https://github.com/algolia/search-insights.js/tree/v2.11.0) | [1.15.0](https://github.com/algolia/recommend/tree/v1.15.0) | -| v3.15.x | [1.17.9](https://github.com/algolia/autocomplete.js/tree/v1.17.9) | [4.77.0](https://github.com/algolia/instantsearch/tree/instantsearch.js%404.77.0) | [2.17.3](https://github.com/algolia/search-insights.js/tree/v2.17.3) | [1.16.0](https://github.com/algolia/recommend/tree/v1.16.0) | -| v3.16.x | [1.18.1](https://github.com/algolia/autocomplete.js/tree/v1.18.1) | [4.78.0](https://github.com/algolia/instantsearch/tree/instantsearch.js%404.78.0) | [2.17.3](https://github.com/algolia/search-insights.js/tree/v2.17.3) | [1.16.0](https://github.com/algolia/recommend/tree/v1.16.0) | +|-----------------|--------------------------------------------------------------------|--------------------------------------------------------------------------------|----------------------------------------------------------------------|-------------------------------------------------------------| +| v3.x | [0.38.0](https://github.com/algolia/autocomplete.js/tree/v0.38.0)* | [4.15.0](https://github.com/algolia/instantsearch.js/tree/v4.15.0)* | [1.7.1](https://github.com/algolia/search-insights.js/tree/v1.7.1) | NA | +| v3.9.1 | [1.6.3](https://github.com/algolia/autocomplete.js/tree/v1.6.3)* | [4.41.0](https://github.com/algolia/instantsearch.js/tree/v4.41.0)* | [1.7.1](https://github.com/algolia/search-insights.js/tree/v1.7.1) | [1.5.0](https://github.com/algolia/recommend/tree/v1.5.0) | +| v3.10.x | [1.6.3](https://github.com/algolia/autocomplete.js/tree/v1.6.3)* | [4.41.0](https://github.com/algolia/instantsearch.js/tree/v4.41.0)* | [1.7.1](https://github.com/algolia/search-insights.js/tree/v1.7.1) | [1.8.0](https://github.com/algolia/recommend/tree/v1.8.0) | +| v3.11.0 | [1.6.3](https://github.com/algolia/autocomplete.js/tree/v1.6.3)* | [4.41.0](https://github.com/algolia/instantsearch.js/tree/v4.41.0)* | [2.6.0](https://github.com/algolia/search-insights.js/tree/v2.6.0) | [1.8.0](https://github.com/algolia/recommend/tree/v1.8.0) | +| v3.13.0 | [1.6.3](https://github.com/algolia/autocomplete.js/tree/v1.6.3)* | [4.63.0](https://github.com/algolia/instantsearch/tree/instantsearch.js%404.63.0)* | [2.11.0](https://github.com/algolia/search-insights.js/tree/v2.11.0) | [1.8.0](https://github.com/algolia/recommend/tree/v1.8.0) | +| v3.14.x | [1.6.3](https://github.com/algolia/autocomplete.js/tree/v1.6.3)* | [4.63.0](https://github.com/algolia/instantsearch/tree/instantsearch.js%404.63.0)* | [2.11.0](https://github.com/algolia/search-insights.js/tree/v2.11.0) | [1.15.0](https://github.com/algolia/recommend/tree/v1.15.0) | +| v3.15.x | [1.17.9](https://github.com/algolia/autocomplete.js/tree/v1.17.9) | [4.77.0](https://github.com/algolia/instantsearch/tree/instantsearch.js%404.77.0) | [2.17.3](https://github.com/algolia/search-insights.js/tree/v2.17.3) | [1.16.0](https://github.com/algolia/recommend/tree/v1.16.0) | +| >=v3.16.x | [1.18.1](https://github.com/algolia/autocomplete.js/tree/v1.18.1) | [4.78.0](https://github.com/algolia/instantsearch/tree/instantsearch.js%404.78.0) | [2.17.3](https://github.com/algolia/search-insights.js/tree/v2.17.3) | [1.16.0](https://github.com/algolia/recommend/tree/v1.16.0) | * In earlier versions of the extension, the Autocomplete and InstantSearch libraries were accessible via the `algoliaBundle` global. This bundle was a prepackaged JavaScript file that contained dependencies for the frontend experience. What was included in this bundle can be seen here: https://github.com/algolia/algoliasearch-extensions-bundle/blob/ISv4/package.json diff --git a/Test/Integration/Indexing/Category/MultiStoreCategoriesTest.php b/Test/Integration/Indexing/Category/MultiStoreCategoriesTest.php index 70d5939b3..77cdd8a17 100644 --- a/Test/Integration/Indexing/Category/MultiStoreCategoriesTest.php +++ b/Test/Integration/Indexing/Category/MultiStoreCategoriesTest.php @@ -11,9 +11,10 @@ use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory; use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Store\Api\Data\StoreInterface; /** - * @magentoDataFixture Magento/Store/_files/second_website_with_two_stores.php + * @magentoDataFixture Algolia_AlgoliaSearch::Test/Integration/_files/second_website_with_two_stores_and_products.php * @magentoDbIsolation disabled * @magentoAppIsolation enabled */ @@ -64,6 +65,20 @@ public function testMultiStoreCategoryIndices() $defaultStore = $this->storeRepository->get('default'); $fixtureSecondStore = $this->storeRepository->get('fixture_second_store'); + // Check the base url of the categories + $this->validateEntityUrl( + 'categories', + self::BAGS_CATEGORY_ID, + $defaultStore, + "http://default.test/" + ); + $this->validateEntityUrl( + 'categories', + self::BAGS_CATEGORY_ID, + $fixtureSecondStore, + "http://fixture_second_store.test/" + ); + $bagsCategory = $this->loadCategory(self::BAGS_CATEGORY_ID, $defaultStore->getId()); $this->assertEquals(self::BAGS_CATEGORY_NAME, $bagsCategory->getName()); diff --git a/Test/Integration/Indexing/MultiStoreTestCase.php b/Test/Integration/Indexing/MultiStoreTestCase.php index d00c75d34..92d96c9e0 100644 --- a/Test/Integration/Indexing/MultiStoreTestCase.php +++ b/Test/Integration/Indexing/MultiStoreTestCase.php @@ -123,6 +123,23 @@ protected function setupStore(StoreInterface $store, bool $enableInstantSearch = $this->indicesConfigurator->saveConfigurationToAlgolia($store->getId()); } + /** + * Fetch a category from an index and check its base url + * + * @param StoreInterface $store + * @param string $baseUrl + * @return void + * @throws NoSuchEntityException + * @throws AlgoliaException + */ + protected function validateEntityUrl(string $entity, string $entityId, StoreInterface $store, string $baseUrl): void + { + $indexOptions = $this->getIndexOptions($entity, $store->getId()); + $results = $this->algoliaConnector->getObjects($indexOptions, [$entityId]); + $hit = reset($results['results']); + $this->assertStringContainsString($baseUrl, $hit['url']); + } + /** * @throws ExceededRetriesException * @throws AlgoliaException diff --git a/Test/Integration/Indexing/Product/MultiStoreProductsTest.php b/Test/Integration/Indexing/Product/MultiStoreProductsTest.php index 4ccc573f7..cfb060a14 100644 --- a/Test/Integration/Indexing/Product/MultiStoreProductsTest.php +++ b/Test/Integration/Indexing/Product/MultiStoreProductsTest.php @@ -2,6 +2,7 @@ namespace Algolia\AlgoliaSearch\Test\Integration\Indexing\Product; +use Algolia\AlgoliaSearch\Exceptions\AlgoliaException; use Algolia\AlgoliaSearch\Service\Product\BatchQueueProcessor as ProductBatchQueueProcessor; use Algolia\AlgoliaSearch\Test\Integration\Indexing\MultiStoreTestCase; use Magento\Catalog\Api\Data\ProductInterface; @@ -10,6 +11,7 @@ use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Indexer\IndexerRegistry; +use Magento\Store\Api\Data\StoreInterface; use Magento\Store\Api\WebsiteRepositoryInterface; /** @@ -117,6 +119,29 @@ public function testMultiStoreProductIndices() $fixtureSecondStore->getId() ); + // Check the base url of the products + $this->validateEntityUrl( + 'products', + self::VOYAGE_YOGA_BAG_ID, + $defaultStore, + "http://default.test/" + ); + + $this->validateEntityUrl( + 'products', + self::VOYAGE_YOGA_BAG_ID, + $fixtureSecondStore, + "http://fixture_second_store.test/" + ); + + $this->validateEntityUrl( + 'products', + self::VOYAGE_YOGA_BAG_ID, + $fixtureThirdStore, + "http://fixture_third_store.test/" + ); + + // Unassign product from a single website (removed from test website (second and third store)) $baseWebsite = $this->websiteRepository->get('base'); diff --git a/Test/Integration/TestCase.php b/Test/Integration/TestCase.php index 8d1378067..639574f49 100644 --- a/Test/Integration/TestCase.php +++ b/Test/Integration/TestCase.php @@ -2,6 +2,7 @@ namespace Algolia\AlgoliaSearch\Test\Integration; +use Algolia\AlgoliaSearch\Api\Data\IndexOptionsInterface; use Algolia\AlgoliaSearch\Exceptions\AlgoliaException; use Algolia\AlgoliaSearch\Exceptions\ExceededRetriesException; use Algolia\AlgoliaSearch\Helper\ConfigHelper; @@ -21,6 +22,8 @@ abstract class TestCase extends \Algolia\AlgoliaSearch\Test\TestCase { + const DEFAULT_STORE_ID = 1; + /** * @var ObjectManagerInterface */ @@ -262,4 +265,20 @@ function runOnce(callable $callback, ?string $key = null): mixed return null; } + + /** + * @param string $indexSuffix + * @param int|null $storeId + * @param bool|null $isTmp + * @return IndexOptionsInterface + * @throws NoSuchEntityException + */ + protected function getIndexOptions( + string $indexSuffix, + ?int $storeId = self::DEFAULT_STORE_ID, + ?bool $isTmp = null + ): IndexOptionsInterface + { + return $this->indexOptionsBuilder->buildWithComputedIndex('_' . $indexSuffix, $storeId, $isTmp); + } } diff --git a/Test/Integration/_files/second_website_with_two_stores_and_products.php b/Test/Integration/_files/second_website_with_two_stores_and_products.php index 468512dfb..6a94d557e 100644 --- a/Test/Integration/_files/second_website_with_two_stores_and_products.php +++ b/Test/Integration/_files/second_website_with_two_stores_and_products.php @@ -87,6 +87,22 @@ $configManager->setValue('algoliasearch_indexing_manager/algolia_indexing/enable_indexing', 1, 'store', 'fixture_second_store'); $configManager->setValue('algoliasearch_indexing_manager/algolia_indexing/enable_indexing', 1, 'store', 'fixture_third_store'); +// Set base urls +$configManager->setValue('web/secure/base_url', 'http://default.test/', 'store', 'default'); +$configManager->setValue('web/unsecure/base_url', 'http://default.test/', 'store', 'default'); +$configManager->setValue('web/secure/base_link_url', 'http://default.test/', 'store', 'default'); +$configManager->setValue('web/unsecure/base_link_url', 'http://default.test/', 'store', 'default'); + +$configManager->setValue('web/secure/base_url', 'http://fixture_second_store.test/', 'store', 'fixture_second_store'); +$configManager->setValue('web/unsecure/base_url', 'http://fixture_second_store.test/', 'store', 'fixture_second_store'); +$configManager->setValue('web/secure/base_link_url', 'http://fixture_second_store.test/', 'store', 'fixture_second_store'); +$configManager->setValue('web/unsecure/base_link_url', 'http://fixture_second_store.test/', 'store', 'fixture_second_store'); + +$configManager->setValue('web/secure/base_url', 'http://fixture_third_store.test/', 'store', 'fixture_third_store'); +$configManager->setValue('web/unsecure/base_url','http://fixture_third_store.test/', 'store', 'fixture_third_store'); +$configManager->setValue('web/secure/base_link_url', 'http://fixture_third_store.test/', 'store', 'fixture_third_store'); +$configManager->setValue('web/unsecure/base_link_url','http://fixture_third_store.test/', 'store', 'fixture_third_store'); + /* Refresh CatalogSearch index */ /** @var IndexerRegistry $indexerRegistry */ $indexerRegistry = Bootstrap::getObjectManager() diff --git a/composer.json b/composer.json index 3ad156dc2..367ba6cdb 100755 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "description": "Algolia Search & Discovery extension for Magento 2", "type": "magento2-module", "license": ["MIT"], - "version": "3.17.0", + "version": "3.17.1", "require": { "php": "~8.2|~8.3|~8.4", "magento/framework": "~103.0", diff --git a/etc/adminhtml/di.xml b/etc/adminhtml/di.xml index 21acfa5d2..1894eaea0 100755 --- a/etc/adminhtml/di.xml +++ b/etc/adminhtml/di.xml @@ -1,10 +1,6 @@ - - - - diff --git a/etc/di.xml b/etc/di.xml index 31dbd6a2c..2dc2616cd 100755 --- a/etc/di.xml +++ b/etc/di.xml @@ -17,6 +17,10 @@ + + + + diff --git a/etc/module.xml b/etc/module.xml index f450526eb..e49466459 100755 --- a/etc/module.xml +++ b/etc/module.xml @@ -1,6 +1,6 @@ - +