Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 52 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,8 @@ jobs:
- name: Runs Elasticsearch
uses: elastic/elastic-github-actions/elasticsearch@master
with:
stack-version: '7.6.0'
stack-version: '8.4.0'
security-enabled: false
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
Expand All @@ -547,6 +548,56 @@ jobs:
- name: Run Behat tests
run: vendor/bin/behat --out=std --format=progress --profile=elasticsearch --no-interaction

elasticsearch-lowest:
name: Behat (PHP ${{ matrix.php }}) (Elasticsearch) (Symfony lowest)
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
matrix:
php:
- '8.2'
fail-fast: false
env:
APP_ENV: elasticsearch
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Configure sysctl limits
run: |
sudo swapoff -a
sudo sysctl -w vm.swappiness=1
sudo sysctl -w fs.file-max=262144
sudo sysctl -w vm.max_map_count=262144
- name: Runs Elasticsearch
uses: elastic/elastic-github-actions/elasticsearch@master
with:
stack-version: '7.6.0'
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
tools: pecl, composer
extensions: intl, bcmath, curl, openssl, mbstring, mongodb
coverage: none
ini-values: memory_limit=-1
- name: Get composer cache directory
id: composercache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache dependencies
uses: actions/cache@v3
with:
path: ${{ steps.composercache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
restore-keys: ${{ runner.os }}-composer-
- name: Update project dependencies
run: composer update --prefer-lowest --no-interaction --no-progress --ansi
- name: Install PHPUnit
run: vendor/bin/simple-phpunit --version
- name: Clear test app cache
run: tests/Fixtures/app/console cache:clear --ansi
- name: Run Behat tests
run: vendor/bin/behat --out=std --format=progress --profile=elasticsearch --no-interaction

phpunit-no-deprecations:
name: PHPUnit (PHP ${{ matrix.php }}) (no deprecations)
runs-on: ubuntu-latest
Expand Down
7 changes: 4 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"doctrine/mongodb-odm": "^2.2",
"doctrine/mongodb-odm-bundle": "^4.0",
"doctrine/orm": "^2.14",
"elasticsearch/elasticsearch": "^7.11.0",
"elasticsearch/elasticsearch": "^7.11 || ^8.4",
"friends-of-behat/mink-browserkit-driver": "^1.3.1",
"friends-of-behat/mink-extension": "^2.2",
"friends-of-behat/symfony-extension": "^2.1",
Expand Down Expand Up @@ -97,7 +97,7 @@
"symfony/var-exporter" : "<6.1.1",
"phpunit/phpunit": "<9.5",
"phpspec/prophecy": "<1.15",
"elasticsearch/elasticsearch": ">=8.0"
"elasticsearch/elasticsearch": ">=8.0,<8.4"
},
"suggest": {
"doctrine/mongodb-odm-bundle": "To support MongoDB. Only versions 4.0 and later are supported.",
Expand Down Expand Up @@ -135,7 +135,8 @@
"sort-packages": true,
"allow-plugins": {
"composer/package-versions-deprecated": true,
"phpstan/extension-installer": true
"phpstan/extension-installer": true,
"php-http/discovery": true
}
},
"extra": {
Expand Down
2 changes: 2 additions & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,5 @@ parameters:
-
message: '#^Property .+ is unused.$#'
path: tests/Doctrine/Odm/PropertyInfo/Fixtures/DoctrineDummy.php

- '#Elasticsearch\\.*#'
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata;
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
use ApiPlatform\Metadata\Util\Inflector;
use Elastic\Elasticsearch\ClientInterface;
use Elastic\Elasticsearch\Exception\ClientResponseException;
use Elasticsearch\Client;
use Elasticsearch\Common\Exceptions\Missing404Exception;

Expand All @@ -30,7 +32,7 @@
*/
final class CatDocumentMetadataFactory implements DocumentMetadataFactoryInterface
{
public function __construct(private readonly Client $client, private readonly ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, private readonly ?DocumentMetadataFactoryInterface $decorated = null)
public function __construct(private readonly Client|ClientInterface $client, private readonly ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory, private readonly ?DocumentMetadataFactoryInterface $decorated = null)
{
}

Expand Down Expand Up @@ -63,7 +65,7 @@ public function create(string $resourceClass): DocumentMetadata

try {
$this->client->cat()->indices(['index' => $index]);
} catch (Missing404Exception) {
} catch (Missing404Exception|ClientResponseException) {
return $this->handleNotFound($documentMetadata, $resourceClass);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
use ApiPlatform\Metadata\Resource\ResourceMetadataCollection;
use ApiPlatform\Metadata\Util\Inflector;
use Elastic\Elasticsearch\ClientInterface;
use Elastic\Elasticsearch\Exception\ClientResponseException;
use Elastic\Transport\Exception\NoNodeAvailableException;
use Elasticsearch\Client;
use Elasticsearch\Common\Exceptions\Missing404Exception;
use Elasticsearch\Common\Exceptions\NoNodesAvailableException;

final class ElasticsearchProviderResourceMetadataCollectionFactory implements ResourceMetadataCollectionFactoryInterface
{
public function __construct(private readonly Client $client, private readonly ResourceMetadataCollectionFactoryInterface $decorated, private readonly bool $triggerDeprecation = true)
public function __construct(private readonly Client|ClientInterface $client, private readonly ResourceMetadataCollectionFactoryInterface $decorated, private readonly bool $triggerDeprecation = true)
{
if ($this->triggerDeprecation) {
trigger_deprecation('api-platform/core', '3.1', '%s is deprecated and will be removed in v4', self::class);
Expand Down Expand Up @@ -109,7 +112,7 @@ private function hasIndices(Operation $operation): bool
$this->client->cat()->indices(['index' => $index]);

return true;
} catch (Missing404Exception|NoNodesAvailableException) {
} catch (Missing404Exception|NoNodesAvailableException|ClientResponseException|NoNodeAvailableException) {
return false;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Elasticsearch/Paginator.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public function getIterator(): \Traversable
$denormalizationContext = array_merge([AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => true], $this->denormalizationContext);

foreach ($this->documents['hits']['hits'] ?? [] as $document) {
$cacheKey = isset($document['_index'], $document['_type'], $document['_id']) ? md5("{$document['_index']}_{$document['_type']}_{$document['_id']}") : null;
$cacheKey = isset($document['_index'], $document['_id']) ? md5("{$document['_index']}_{$document['_id']}") : null;

if ($cacheKey && \array_key_exists($cacheKey, $this->cachedDenormalizedDocuments)) {
$object = $this->cachedDenormalizedDocuments[$cacheKey];
Expand Down
16 changes: 9 additions & 7 deletions src/Elasticsearch/State/CollectionProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@
use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata;
use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface;
use ApiPlatform\Elasticsearch\Paginator;
use ApiPlatform\Elasticsearch\Util\ElasticsearchVersion;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\Metadata\Util\Inflector;
use ApiPlatform\State\Pagination\Pagination;
use ApiPlatform\State\ProviderInterface;
use Elastic\Elasticsearch\ClientInterface;
use Elastic\Elasticsearch\Response\Elasticsearch;
use Elasticsearch\Client;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;

Expand All @@ -34,9 +35,10 @@
final class CollectionProvider implements ProviderInterface
{
/**
* @param Client|ClientInterface $client
* @param RequestBodySearchCollectionExtensionInterface[] $collectionExtensions
*/
public function __construct(private readonly Client $client, private readonly DocumentMetadataFactoryInterface $documentMetadataFactory, private readonly DenormalizerInterface $denormalizer, private readonly Pagination $pagination, private readonly iterable $collectionExtensions = [])
public function __construct(private $client, private readonly DocumentMetadataFactoryInterface $documentMetadataFactory, private readonly DenormalizerInterface $denormalizer, private readonly Pagination $pagination, private readonly iterable $collectionExtensions = [])
{
}

Expand Down Expand Up @@ -71,12 +73,12 @@ public function provide(Operation $operation, array $uriVariables = [], array $c
'body' => $body,
];

if (null !== $options->getType() && ElasticsearchVersion::supportsMappingType()) {
$params['type'] = $options->getType();
}

$documents = $this->client->search($params);

if ($documents instanceof Elasticsearch) {
$documents = $documents->asArray();
}

return new Paginator(
$this->denormalizer,
$documents,
Expand All @@ -89,7 +91,7 @@ public function provide(Operation $operation, array $uriVariables = [], array $c

private function convertDocumentMetadata(DocumentMetadata $documentMetadata): Options
{
return new Options($documentMetadata->getIndex(), $documentMetadata->getType());
return new Options($documentMetadata->getIndex());
}

private function getIndex(Operation $operation): string
Expand Down
24 changes: 15 additions & 9 deletions src/Elasticsearch/State/ItemProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@
use ApiPlatform\Elasticsearch\Metadata\Document\DocumentMetadata;
use ApiPlatform\Elasticsearch\Metadata\Document\Factory\DocumentMetadataFactoryInterface;
use ApiPlatform\Elasticsearch\Serializer\DocumentNormalizer;
use ApiPlatform\Elasticsearch\Util\ElasticsearchVersion;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\Metadata\Util\Inflector;
use ApiPlatform\State\ProviderInterface;
use Elastic\Elasticsearch\ClientInterface;
use Elastic\Elasticsearch\Exception\ClientResponseException;
use Elastic\Elasticsearch\Response\Elasticsearch;
use Elasticsearch\Client;
use Elasticsearch\Common\Exceptions\Missing404Exception;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;

Expand All @@ -32,7 +35,10 @@
*/
final class ItemProvider implements ProviderInterface
{
public function __construct(private readonly Client $client, private readonly DocumentMetadataFactoryInterface $documentMetadataFactory, private readonly DenormalizerInterface $denormalizer)
/**
* @param Client|ClientInterface $client
*/
public function __construct(private $client, private readonly DocumentMetadataFactoryInterface $documentMetadataFactory, private readonly DenormalizerInterface $denormalizer)
{
}

Expand All @@ -51,18 +57,18 @@ public function provide(Operation $operation, array $uriVariables = [], array $c
}

$params = [
'client' => ['ignore' => 404],
'index' => $options->getIndex() ?? $this->getIndex($operation),
'id' => (string) reset($uriVariables),
];

if (null !== $options->getType() && ElasticsearchVersion::supportsMappingType()) {
$params['type'] = $options->getType();
try {
$document = $this->client->get($params);
} catch (Missing404Exception|ClientResponseException) {
return null;
}

$document = $this->client->get($params);
if (!$document['found']) {
return null;
if ($document instanceof Elasticsearch) {
$document = $document->asArray();
}

$item = $this->denormalizer->denormalize($document, $resourceClass, DocumentNormalizer::FORMAT, [AbstractNormalizer::ALLOW_EXTRA_ATTRIBUTES => true]);
Expand All @@ -75,7 +81,7 @@ public function provide(Operation $operation, array $uriVariables = [], array $c

private function convertDocumentMetadata(DocumentMetadata $documentMetadata): Options
{
return new Options($documentMetadata->getIndex(), $documentMetadata->getType());
return new Options($documentMetadata->getIndex());
}

private function getIndex(Operation $operation): string
Expand Down
14 changes: 0 additions & 14 deletions src/Elasticsearch/State/Options.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ class Options implements OptionsInterface
{
public function __construct(
protected ?string $index = null,
protected ?string $type = null,
) {
}

Expand All @@ -35,17 +34,4 @@ public function withIndex(?string $index): self

return $self;
}

public function getType(): ?string
{
return $this->type;
}

public function withType(?string $type): self
{
$self = clone $this;
$self->type = $type;

return $self;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ class CatDocumentMetadataFactoryTest extends TestCase
{
use ProphecyTrait;

protected function setUp(): void
{
if (class_exists(\Elastic\Elasticsearch\ClientInterface::class)) {
$this->markTestSkipped('\Elastic\Elasticsearch\ClientInterface doesn\'t have cat method signature.');
}
}

public function testConstruct(): void
{
self::assertInstanceOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,13 @@ class ElasticsearchProviderResourceMetadataCollectionFactoryTest extends TestCas

public function testConstruct(): void
{
$client = class_exists(Client::class) ? Client::class : \Elastic\Elasticsearch\ClientInterface::class;

$this->expectDeprecation('Since api-platform/core 3.1: ApiPlatform\Elasticsearch\Metadata\Resource\Factory\ElasticsearchProviderResourceMetadataCollectionFactory is deprecated and will be removed in v4');
self::assertInstanceOf(
ResourceMetadataCollectionFactoryInterface::class,
new ElasticsearchProviderResourceMetadataCollectionFactory(
$this->prophesize(Client::class)->reveal(),
$this->prophesize($client)->reveal(),
$this->prophesize(ResourceMetadataCollectionFactoryInterface::class)->reveal()
)
);
Expand All @@ -52,6 +54,10 @@ public function testConstruct(): void
*/
public function testCreate(?bool $elasticsearchFlag, int $expectedCatCallCount, ?bool $expectedResult): void
{
if (class_exists(\Elastic\Elasticsearch\ClientInterface::class)) {
$this->markTestSkipped('\Elastic\Elasticsearch\ClientInterface doesn\'t have cat method signature.');
}

if (null !== $elasticsearchFlag) {
$solution = $elasticsearchFlag
? sprintf('Pass an instance of %s to $stateOptions instead', Options::class)
Expand Down
9 changes: 6 additions & 3 deletions src/Elasticsearch/Tests/State/CollectionProviderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
use ApiPlatform\Metadata\Resource\ResourceMetadataCollection;
use ApiPlatform\State\Pagination\Pagination;
use Elasticsearch\Client;
use PHPUnit\Framework\TestCase;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
Expand All @@ -38,10 +37,12 @@ final class CollectionProviderTest extends TestCase

public function testConstruct(): void
{
$client = class_exists(\Elasticsearch\Client::class) ? \Elasticsearch\Client::class : \Elastic\Elasticsearch\ClientInterface::class;

self::assertInstanceOf(
CollectionProvider::class,
new CollectionProvider(
$this->prophesize(Client::class)->reveal(),
$this->prophesize($client)->reveal(),
$this->prophesize(DocumentMetadataFactoryInterface::class)->reveal(),
$this->prophesize(DenormalizerInterface::class)->reveal(),
new Pagination()
Expand Down Expand Up @@ -99,7 +100,9 @@ public function testGetCollection(): void
],
];

$clientProphecy = $this->prophesize(Client::class);
$clientClass = class_exists(\Elasticsearch\Client::class) ? \Elasticsearch\Client::class : \Elastic\Elasticsearch\ClientInterface::class;

$clientProphecy = $this->prophesize($clientClass);
$clientProphecy
->search(
Argument::allOf(
Expand Down
Loading