diff --git a/composer.json b/composer.json index 66d81db24..0afab47d0 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "drupal/diff": "^1.0", "drupal/easy_breadcrumb": "^2.0", "drupal/editoria11y": "^2.0", - "drupal/elasticsearch_connector": "^7.0@alpha", + "drupal/elasticsearch_connector": "^8.0@alpha", "drupal/entity_browser": "^2.5", "drupal/entity_usage": "^2.0@beta", "drupal/eu_cookie_compliance": "1.24", @@ -65,9 +65,13 @@ "drupal/views_bulk_edit": "^2.7", "drupal/views_bulk_operations": "^4.1", "drupal/stage_file_proxy": "^2", + "ruflin/elastica": "^8.0", "league/uri": "^6.0", "php": "^8.1" }, + "require-dev": { + "dg/bypass-finals": "^1.0" + }, "conflict": { "drupal/core": "<10.3", "drupal/core-composer-scaffold": "<10.3", diff --git a/modules/helfi_paragraphs_news_list/helfi_paragraphs_news_list.module b/modules/helfi_paragraphs_news_list/helfi_paragraphs_news_list.module index c170080f6..4da480fa7 100644 --- a/modules/helfi_paragraphs_news_list/helfi_paragraphs_news_list.module +++ b/modules/helfi_paragraphs_news_list/helfi_paragraphs_news_list.module @@ -56,7 +56,7 @@ function helfi_paragraphs_news_list_paragraph_view( $query = $storage ->getQuery(); $query - ->condition('_language', $entity->language()->getId()) + ->condition('search_api_language', $entity->language()->getId()) ->range(0, $entity->getLimit()); $termFilters = [ diff --git a/modules/helfi_paragraphs_news_list/helfi_paragraphs_news_list.services.yml b/modules/helfi_paragraphs_news_list/helfi_paragraphs_news_list.services.yml index a4f85608b..787ac9c57 100644 --- a/modules/helfi_paragraphs_news_list/helfi_paragraphs_news_list.services.yml +++ b/modules/helfi_paragraphs_news_list/helfi_paragraphs_news_list.services.yml @@ -7,5 +7,5 @@ services: class: Drupal\helfi_paragraphs_news_list\ClientBuilder helfi_paragraphs_news_list.elastic_client: - class: Elasticsearch\Client + class: Elastic\Elasticsearch\Client factory: ['@helfi_paragraphs_news_list.elastic_client_factory', 'create'] diff --git a/modules/helfi_paragraphs_news_list/src/ClientBuilder.php b/modules/helfi_paragraphs_news_list/src/ClientBuilder.php index a1818bb25..3cefb9743 100644 --- a/modules/helfi_paragraphs_news_list/src/ClientBuilder.php +++ b/modules/helfi_paragraphs_news_list/src/ClientBuilder.php @@ -8,8 +8,8 @@ use Drupal\helfi_api_base\Environment\EnvironmentResolverInterface; use Drupal\helfi_api_base\Environment\Project; use Drupal\helfi_api_base\Environment\ServiceEnum; -use Elasticsearch\Client; -use Elasticsearch\ClientBuilder as ElasticClientBuilder; +use Elastic\Elasticsearch\Client; +use Elastic\Elasticsearch\ClientBuilder as ElasticClientBuilder; /** * The client builder factory. @@ -25,13 +25,12 @@ final class ClientBuilder { public function __construct( private readonly EnvironmentResolverInterface $environmentResolver, ) { - } /** * Creates a new client instance. * - * @return \Elasticsearch\Client + * @return \Elastic\Elasticsearch\Client * The client. */ public function create() : Client { @@ -51,13 +50,9 @@ public function create() : Client { return ElasticClientBuilder::create() ->setSSLVerification($service->protocol === 'https') ->setHosts([ - [ - 'host' => $service->domain, - 'port' => $service->port, - 'scheme' => $service->protocol, - ], + $service->getAddress(), ]) - ->setConnectionParams([ + ->setHttpClientOptions([ 'client' => [ 'timeout' => 1, 'connect_timeout' => 1, diff --git a/modules/helfi_paragraphs_news_list/src/ElasticExternalEntityBase.php b/modules/helfi_paragraphs_news_list/src/ElasticExternalEntityBase.php index faa3cce27..31c02892a 100644 --- a/modules/helfi_paragraphs_news_list/src/ElasticExternalEntityBase.php +++ b/modules/helfi_paragraphs_news_list/src/ElasticExternalEntityBase.php @@ -1,12 +1,15 @@ client->search($parameters); + return $this->client->search($parameters)->asArray(); } - catch (ElasticsearchException $e) { + catch (ElasticsearchException | TransportException $e) { Error::logException($this->logger, $e); } return []; diff --git a/modules/helfi_paragraphs_news_list/tests/src/Kernel/ExternalEntityStorage/NewsStorageClientTest.php b/modules/helfi_paragraphs_news_list/tests/src/Kernel/ExternalEntityStorage/NewsStorageClientTest.php index 7636bfb5c..2e4a38199 100644 --- a/modules/helfi_paragraphs_news_list/tests/src/Kernel/ExternalEntityStorage/NewsStorageClientTest.php +++ b/modules/helfi_paragraphs_news_list/tests/src/Kernel/ExternalEntityStorage/NewsStorageClientTest.php @@ -5,7 +5,7 @@ namespace Drupal\Tests\helfi_paragraphs_news_list\Kernel\ExternalEntityStorage; use Drupal\helfi_paragraphs_news_list\Entity\ExternalEntity\News; -use Elasticsearch\Client; +use Elastic\Elasticsearch\Client; use Prophecy\Argument; /** @@ -29,32 +29,35 @@ public function testLoadMultiple() : void { $client = $this->prophesize(Client::class); $client->search(Argument::any()) ->shouldBeCalled() - ->willReturn([], [ - 'hits' => [ + ->willReturn( + $this->createElasticsearchResponse([]), + $this->createElasticsearchResponse([ 'hits' => [ - // Working item. - [ - '_source' => [ - 'uuid_langcode' => ['123'], - 'uuid' => ['uuid-123'], - 'title' => ['test title'], - 'field_news_groups' => ['Test groups'], - 'field_news_item_tags' => ['Test tag'], - 'field_news_neighbourhoods' => ['Test neighbourhood'], - 'url' => ['https://localhost'], - 'published_at' => [1234567], - 'short_title' => ['test shorttitle'], + 'hits' => [ + // Working item. + [ + '_source' => [ + 'uuid_langcode' => ['123'], + 'uuid' => ['uuid-123'], + 'title' => ['test title'], + 'field_news_groups' => ['Test groups'], + 'field_news_item_tags' => ['Test tag'], + 'field_news_neighbourhoods' => ['Test neighbourhood'], + 'url' => ['https://localhost'], + 'published_at' => [1234567], + 'short_title' => ['test shorttitle'], + ], ], - ], - // Missing uuid_langcode field. - [ - '_source' => [ - 'uuid' => 'uuid-321', + // Missing uuid_langcode field. + [ + '_source' => [ + 'uuid' => 'uuid-321', + ], ], ], ], - ], - ]); + ]), + ); $client->search(Argument::any()) ->shouldBeCalled(); $sut = $this->getSut($client->reveal()); @@ -87,7 +90,7 @@ public function testQuery(): void { ], ]) ->shouldBeCalled() - ->willReturn([]); + ->willReturn($this->createElasticsearchResponse([])); // Test sort. $client->search([ 'index' => 'news', @@ -99,7 +102,7 @@ public function testQuery(): void { ], ]) ->shouldBeCalled() - ->willReturn([]); + ->willReturn($this->createElasticsearchResponse([])); // Test filters. $client->search([ 'index' => 'news', @@ -129,7 +132,7 @@ public function testQuery(): void { ], ]) ->shouldBeCalled() - ->willReturn([]); + ->willReturn($this->createElasticsearchResponse([])); $this->getSut($client->reveal())->getQuery()->accessCheck(FALSE)->execute(); $this->getSut($client->reveal()) ->getQuery() diff --git a/modules/helfi_paragraphs_news_list/tests/src/Kernel/ExternalEntityStorage/StorageClientTestBase.php b/modules/helfi_paragraphs_news_list/tests/src/Kernel/ExternalEntityStorage/StorageClientTestBase.php index 1aa095977..09c69e09a 100644 --- a/modules/helfi_paragraphs_news_list/tests/src/Kernel/ExternalEntityStorage/StorageClientTestBase.php +++ b/modules/helfi_paragraphs_news_list/tests/src/Kernel/ExternalEntityStorage/StorageClientTestBase.php @@ -7,8 +7,8 @@ use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Tests\helfi_paragraphs_news_list\Kernel\KernelTestBase; use Drupal\external_entities\ExternalEntityStorage; -use Elasticsearch\Client; -use Elasticsearch\Common\Exceptions\BadRequest400Exception; +use Elastic\Elasticsearch\Client; +use Elastic\Elasticsearch\Exception\ClientResponseException; use Prophecy\Argument; /** @@ -27,7 +27,7 @@ abstract protected function getStorageName() : string; /** * Gets the SUT. * - * @param \Elasticsearch\Client $client + * @param \Elastic\Elasticsearch\Client $client * The client mock. * * @return \Drupal\external_entities\ExternalEntityStorage @@ -47,7 +47,7 @@ public function getSut(Client $client) : ExternalEntityStorage { public function testRequestException() : void { $client = $this->prophesize(Client::class); $client->search(Argument::any()) - ->willThrow(new BadRequest400Exception('Message')); + ->willThrow(new ClientResponseException('Message')); $sut = $this->getSut($client->reveal()); $this->assertEmpty($sut->loadMultiple([123])); $this->assertEmpty($sut->getQuery()->accessCheck(FALSE)->execute()); diff --git a/modules/helfi_paragraphs_news_list/tests/src/Kernel/ExternalEntityStorage/TermStorageClientTestBase.php b/modules/helfi_paragraphs_news_list/tests/src/Kernel/ExternalEntityStorage/TermStorageClientTestBase.php index 09f8bebda..32e41badf 100644 --- a/modules/helfi_paragraphs_news_list/tests/src/Kernel/ExternalEntityStorage/TermStorageClientTestBase.php +++ b/modules/helfi_paragraphs_news_list/tests/src/Kernel/ExternalEntityStorage/TermStorageClientTestBase.php @@ -5,7 +5,7 @@ namespace Drupal\Tests\helfi_paragraphs_news_list\Kernel\ExternalEntityStorage; use Drupal\helfi_paragraphs_news_list\Entity\ExternalEntity\Term; -use Elasticsearch\Client; +use Elastic\Elasticsearch\Client; use Prophecy\Argument; /** @@ -28,7 +28,7 @@ public function testLoadMultiple() : void { $client = $this->prophesize(Client::class); $client->search(Argument::any()) ->shouldBeCalled() - ->willReturn([], [ + ->willReturn($this->createElasticsearchResponse([]), $this->createElasticsearchResponse([ 'hits' => [ 'hits' => [ // Working item. @@ -48,7 +48,7 @@ public function testLoadMultiple() : void { ], ], ], - ]); + ])); $client->search(Argument::any()) ->shouldBeCalled(); $sut = $this->getSut($client->reveal()); @@ -85,7 +85,7 @@ public function testQuery(): void { ], ]) ->shouldBeCalled() - ->willReturn([]); + ->willReturn($this->createElasticsearchResponse([])); // Test sort. $client->search([ 'index' => 'news_terms', @@ -103,7 +103,7 @@ public function testQuery(): void { ], ]) ->shouldBeCalled() - ->willReturn([]); + ->willReturn($this->createElasticsearchResponse([])); // Test filters. $client->search([ 'index' => 'news_terms', @@ -134,7 +134,7 @@ public function testQuery(): void { ], ]) ->shouldBeCalled() - ->willReturn([]); + ->willReturn($this->createElasticsearchResponse([])); $this->getSut($client->reveal()) ->getQuery() ->accessCheck(FALSE) diff --git a/modules/helfi_paragraphs_news_list/tests/src/Kernel/KernelTestBase.php b/modules/helfi_paragraphs_news_list/tests/src/Kernel/KernelTestBase.php index ec4d1e0de..6ca07884f 100644 --- a/modules/helfi_paragraphs_news_list/tests/src/Kernel/KernelTestBase.php +++ b/modules/helfi_paragraphs_news_list/tests/src/Kernel/KernelTestBase.php @@ -4,12 +4,14 @@ namespace Drupal\Tests\helfi_paragraphs_news_list\Kernel; +use DG\BypassFinals; use Drupal\KernelTests\KernelTestBase as CoreKernelTestBase; +use Elastic\Elasticsearch\Response\Elasticsearch; /** * Kernel test base for news feed list tests. */ -class KernelTestBase extends CoreKernelTestBase { +abstract class KernelTestBase extends CoreKernelTestBase { /** * {@inheritdoc} @@ -33,6 +35,9 @@ class KernelTestBase extends CoreKernelTestBase { * {@inheritdoc} */ protected function setUp(): void { + // https://github.com/elastic/elasticsearch-php/issues/1227. + BypassFinals::enable(); + parent::setUp(); $this->installConfig(['system', 'paragraphs', 'external_entities']); $this->installEntitySchema('user'); @@ -46,4 +51,16 @@ protected function setUp(): void { $this->installConfig('paragraphs'); } + /** + * Mocks elasticsearch response. + * + * @param array $response + * Response as an array. + */ + protected function createElasticsearchResponse(array $response): Elasticsearch { + $mock = $this->prophesize(Elasticsearch::class); + $mock->asArray()->willReturn($response); + return $mock->reveal(); + } + } diff --git a/modules/helfi_paragraphs_news_list/tests/src/Unit/ClientBuilderTest.php b/modules/helfi_paragraphs_news_list/tests/src/Unit/ClientBuilderTest.php index fe33c1eed..06ac9e64a 100644 --- a/modules/helfi_paragraphs_news_list/tests/src/Unit/ClientBuilderTest.php +++ b/modules/helfi_paragraphs_news_list/tests/src/Unit/ClientBuilderTest.php @@ -8,12 +8,12 @@ use Drupal\Tests\helfi_api_base\Traits\EnvironmentResolverTrait; use Drupal\helfi_api_base\Environment\EnvironmentResolver; use Drupal\helfi_paragraphs_news_list\ClientBuilder; -use Elasticsearch\Client; +use Elastic\Elasticsearch\Client; /** * Tests elastic client builder. * - * @group helfi_api_base + * @group helfi_paragraphs_news_list */ class ClientBuilderTest extends UnitTestCase { diff --git a/modules/helfi_react_search/helfi_react_search.services.yml b/modules/helfi_react_search/helfi_react_search.services.yml index 384cd6280..10c33c387 100644 --- a/modules/helfi_react_search/helfi_react_search.services.yml +++ b/modules/helfi_react_search/helfi_react_search.services.yml @@ -16,4 +16,3 @@ services: - { timeout: '%helfi_react_search.request_timeout%' } Drupal\helfi_react_search\LinkedEvents: ~ - Drupal\helfi_react_search\EventSubscriber\ElasticIndexSubscriber: ~ diff --git a/modules/helfi_react_search/src/EventSubscriber/ElasticIndexSubscriber.php b/modules/helfi_react_search/src/EventSubscriber/ElasticIndexSubscriber.php deleted file mode 100644 index 0cda6d4ed..000000000 --- a/modules/helfi_react_search/src/EventSubscriber/ElasticIndexSubscriber.php +++ /dev/null @@ -1,77 +0,0 @@ - [['stripBoost'], ['addCoordinatesField']], - ]; - } - - /** - * Iterate over fields and remove any boosts. - * - * Search API wants to index fields with 'boost' parameter. - * Index-time boosting has been deprecated in newer Elasticsearch versions. - * This subscriber strips boost from mapping to prevent errors. - * - * @param \Drupal\elasticsearch_connector\Event\PrepareIndexMappingEvent $event - * Event emitted by elasticsearch_connector. - */ - public function stripBoost(PrepareIndexMappingEvent $event): void { - /** @var array $params */ - $params = $event->getIndexMappingParams(); - - // Bail if nothing to check against. - if (!isset($params['body']['properties'])) { - return; - } - - foreach ($params['body']['properties'] as $key => $property) { - if (isset($property['boost'])) { - unset($params['body']['properties'][$key]['boost']); - } - } - - $event->setIndexMappingParams($params); - } - - /** - * Set mapping for unit's coordinates as geo_point field. - * - * @param \Drupal\elasticsearch_connector\Event\PrepareIndexMappingEvent $event - * Event emitted by elasticsearch_connector. - */ - public function addCoordinatesField(PrepareIndexMappingEvent $event): void { - /** @var array $params */ - $params = $event->getIndexMappingParams(); - - if ($params['index'] !== 'schools' && $params['index'] !== 'health_stations') { - return; - } - - $params['body']['properties']['coordinates'] = [ - 'type' => 'geo_point', - ]; - - $event->setIndexMappingParams($params); - } - -} diff --git a/src/Plugin/search_api/data_type/LocationDataType.php b/src/Plugin/search_api/data_type/LocationDataType.php new file mode 100644 index 000000000..ce66c71f3 --- /dev/null +++ b/src/Plugin/search_api/data_type/LocationDataType.php @@ -0,0 +1,18 @@ +