Skip to content
Merged
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
13 changes: 7 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@
"psr/log": "^3"
},
"require-dev": {
"phpunit/phpunit": "^10.0",
"phpunit/phpunit": "^11.0",
"mockery/mockery": "^1.5",
"infection/infection": "^0.29",
"symplify/easy-coding-standard": "^9.0",
"nunomaduro/larastan": "^2.5",
"phpstan/phpstan-mockery": "^1.1",
"orchestra/testbench": "*",
"dg/bypass-finals": "^1.8"
"phpstan/phpstan-mockery": "^2.0",
"orchestra/testbench": "^10.0",
"dg/bypass-finals": "^1.8",
"larastan/larastan": "^3.0"
},
"autoload": {
"psr-4": {
Expand All @@ -50,7 +50,8 @@
},
"config": {
"allow-plugins": {
"infection/extension-installer": false
"infection/extension-installer": false,
"php-http/discovery": false
}
}
}
5 changes: 0 additions & 5 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,3 @@ parameters:
message: "#^PHPDoc tag @var for variable \\$class has invalid type Laravel\\\\Scout\\\\Searchable\\.$#"
count: 1
path: src/Infrastructure/Console/ElasticSearch.php

-
message: "#^Call to an undefined method JeroenG\\\\Explorer\\\\Domain\\\\IndexManagement\\\\IndexConfigurationInterface\\:\\:getAliasConfiguration\\(\\)\\.$#"
count: 2
path: tests/Unit/IndexManagement/ElasticIndexConfigurationRepositoryTest.php
3 changes: 2 additions & 1 deletion phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
includes:
- ./vendor/nunomaduro/larastan/extension.neon
- ./vendor/larastan/larastan/extension.neon
- ./vendor/phpstan/phpstan-mockery/extension.neon
- phpstan-baseline.neon

parameters:
level: 5
treatPhpDocTypesAsCertain: false
paths:
- src
- tests
Expand Down
4 changes: 2 additions & 2 deletions src/Infrastructure/Scout/ElasticEngine.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class ElasticEngine extends Engine

private ?LoggerInterface $logger;

private static ?array $lastQuery;
private static array $lastQuery;

public function __construct(
IndexAdapterInterface $indexAdapter,
Expand All @@ -56,7 +56,7 @@ public function update($models): void
return;
}

/** @var Explored $firstModel */
/** @var Model&Explored $firstModel */
$firstModel = $models->first();

$indexConfiguration = $this->indexConfigurationRepository->findForIndex($firstModel->searchableAs());
Expand Down
31 changes: 28 additions & 3 deletions src/Infrastructure/Scout/ScoutSearchCommandBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use JeroenG\Explorer\Domain\Syntax\Compound\QueryType;
use JeroenG\Explorer\Domain\Syntax\Invert;
use JeroenG\Explorer\Domain\Syntax\MultiMatch;
use JeroenG\Explorer\Domain\Syntax\Range;
use JeroenG\Explorer\Domain\Syntax\Sort;
use JeroenG\Explorer\Domain\Syntax\Term;
use JeroenG\Explorer\Domain\Syntax\Terms;
Expand Down Expand Up @@ -158,7 +159,7 @@ public function getFields(): array

public function getBoolQuery(): BoolQuery
{
return $this->boolQuery ?? new BoolQuery();
return $this->boolQuery;
}

public function setMust(array $must): void
Expand Down Expand Up @@ -270,8 +271,32 @@ public function buildQuery(): array
$compound->add('must', new MultiMatch($this->query, $this->getDefaultSearchFields()));
}

foreach ($this->wheres as $field => $value) {
$compound->add('filter', new Term($field, $value));
foreach ($this->wheres as $field => $where) {
/**
* From Scout 10 to Scout 11 the where method changed from accepting a field and value to accepting an
* array with field, operator and value. This is to support operators other than =. To support both
* versions we check if the where is an array and has a field key. If not we assume it's the old version
* and convert it to the new version.
*/
if (!is_array($where) || !array_key_exists('field', $where)) {
$where = [
'field' => $field,
'operator' => '=',
'value' => $where,
];
}

$whereQuery = match ($where['operator']) {
'=' => new Term($where['field'], $where['value']),
'!=' => Invert::query(new Term($where['field'], $where['value'])),
'>' => new Range($where['field'], ['gt' => $where['value']]),
'>=' => new Range($where['field'], ['gte' => $where['value']]),
'<' => new Range($where['field'], ['lt' => $where['value']]),
'<=' => new Range($where['field'], ['lte' => $where['value']]),
default => new Term($where['field'], $where['value']), // Default to term query for unknown operators
};

$compound->add('filter', $whereQuery);
}

foreach ($this->whereIns as $field => $values) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

final class SourceFilterTest extends TestCase
{
/** @dataProvider provideSourceFilterValues */
#[\PHPUnit\Framework\Attributes\DataProvider('provideSourceFilterValues')]
public function test_it_builds(array $expectedValue, SourceFilter $subject): void
{
Assert::assertSame([ '_source' => $expectedValue ], $subject->build());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

final class TrackTotalHitsTest extends TestCase
{
/** @dataProvider provideTrackTotalHitCounts */
#[\PHPUnit\Framework\Attributes\DataProvider('provideTrackTotalHitCounts')]
public function test_it_tracks_count(int $count): void
{
Assert::assertSame([ 'track_total_hits' => $count ], TrackTotalHits::count($count)->build());
Expand Down
8 changes: 2 additions & 6 deletions tests/Unit/Domain/Syntax/SortOrderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,14 @@ public function test_it_uses_default_missing_when_creating_sort_order(): void
], $sort->build());
}

/**
* @dataProvider provideSortOrderStrings
*/
#[\PHPUnit\Framework\Attributes\DataProvider('provideSortOrderStrings')]
public function test_sort_order_can_be_created_from_sort_string(string $expectedResult, string $sortString): void
{
$subject = SortOrder::fromString($sortString);
Assert::assertSame($expectedResult, $subject->build());
}

/**
* @dataProvider provideMissingSortOrderStrings
*/
#[\PHPUnit\Framework\Attributes\DataProvider('provideMissingSortOrderStrings')]
public function test_sort_order_can_be_created_from_sort_string_and_missing(array $expectedResult, string $sortString, string $missing): void
{
$subject = SortOrder::for($sortString, $missing);
Expand Down
2 changes: 1 addition & 1 deletion tests/Unit/ElasticClientBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ final class ElasticClientBuilderTest extends MockeryTestCase

private const CONNECTION_STRING = 'https://example.com:9222';

/** @dataProvider provideClientConfigs */
#[\PHPUnit\Framework\Attributes\DataProvider('provideClientConfigs')]
public function test_it_creates_client_with_config(array $config, ClientBuilder $expectedBuilder): void
{
$configRepository = new ConfigRepository([ 'explorer' => $config ]);
Expand Down
63 changes: 61 additions & 2 deletions tests/Unit/FinderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use JeroenG\Explorer\Tests\Support\ClientExpectation;
use JeroenG\Explorer\Tests\Support\FakeElasticResponse;
use Mockery\Adapter\Phpunit\MockeryTestCase;
use PHPUnit\Framework\Attributes\DataProvider;

class FinderTest extends MockeryTestCase
{
Expand Down Expand Up @@ -116,7 +117,11 @@ public function test_it_accepts_must_should_filter_and_where_queries(): void
$builder->setMust([new Matching('title', 'Lorem Ipsum')]);
$builder->setShould([new Matching('text', 'consectetur adipiscing elit')]);
$builder->setFilter([new Term('published', true)]);
$builder->setWheres(['subtitle' => 'Dolor sit amet']);
$builder->setWheres([[
'field' => 'subtitle',
'operator' => '=',
'value' => 'Dolor sit amet',
]]);
$builder->setWhereIns(['tags' => ['t1', 't2']]);
$builder->setQuery('fuzzy search');

Expand Down Expand Up @@ -167,7 +172,11 @@ public function test_it_accepts_must_should_filter_and_where_not_in_queries(): v
$builder->setMust([new Matching('title', 'Lorem Ipsum')]);
$builder->setShould([new Matching('text', 'consectetur adipiscing elit')]);
$builder->setFilter([new Term('published', true)]);
$builder->setWheres(['subtitle' => 'Dolor sit amet']);
$builder->setWheres([[
'field' => 'subtitle',
'operator' => '=',
'value' => 'Dolor sit amet',
]]);
$builder->setWhereNotIns(['tags' => ['t1']]);
$builder->setQuery('fuzzy search');

Expand All @@ -177,6 +186,56 @@ public function test_it_accepts_must_should_filter_and_where_not_in_queries(): v
self::assertCount(2, $results);
}

#[DataProvider('scoutWhereOperatorProvider')]
public function test_it_accepts_all_scout_where_operators(string $operator, array $expectedFilter): void
{
$client = ClientExpectation::create();
$client->expectSearch(
[
'index' => self::TEST_INDEX,
'body' => [
'query' => [
'bool' => [
'must' => [],
'should' => [],
'filter' => [$expectedFilter],
],
],
],
],
FakeElasticResponse::array([
'hits' => [
'total' => ['value' => 0],
'hits' => [],
],
])
);

$builder = new ScoutSearchCommandBuilder();
$builder->setIndex(self::TEST_INDEX);
$builder->setWheres([[
'field' => 'age',
'operator' => $operator,
'value' => 18,
]]);

$subject = new Finder($client->getMock(), $builder);

self::assertCount(0, $subject->find());
}

public static function scoutWhereOperatorProvider(): array
{
return [
'=' => ['=', ['term' => ['age' => ['value' => 18, 'boost' => 1.0]]]],
'!=' => ['!=', ['bool' => ['must_not' => ['term' => ['age' => ['value' => 18, 'boost' => 1.0]]]]]],
'>' => ['>', ['range' => ['age' => ['gt' => 18, 'boost' => 1.0]]]],
'>=' => ['>=', ['range' => ['age' => ['gte' => 18, 'boost' => 1.0]]]],
'<' => ['<', ['range' => ['age' => ['lt' => 18, 'boost' => 1.0]]]],
'<=' => ['<=', ['range' => ['age' => ['lte' => 18, 'boost' => 1.0]]]],
];
}

public function test_it_accepts_a_query_for_paginated_search(): void
{
$client = ClientExpectation::create();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public function test_it_throws_on_invalid_model(): void
iterator_to_array($repository->getConfigurations())[0] ?? null;
}

/** @dataProvider invalidIndices */
#[\PHPUnit\Framework\Attributes\DataProvider('invalidIndices')]
public function test_it_errors_on_invalid_indices($indices, string $error): void
{
$repository = new ElasticIndexConfigurationRepository($indices);
Expand Down Expand Up @@ -178,7 +178,6 @@ public function test_it_can_find_a_single_index(): void

$config = $repository->findForIndex('encyclopedia');

self::assertNotNull($config);
self::assertEquals($indices['encyclopedia']['properties'], $config->getProperties());
self::assertEquals($indices['encyclopedia']['settings'], $config->getSettings());
self::assertEquals('encyclopedia', $config->getName());
Expand Down Expand Up @@ -221,6 +220,7 @@ public function test_it_can_turn_off_pruning_for_aliased_indices(): void
{
$indices = ['encyclopedia' => ['aliased' => true, 'settings' => [], 'properties' => []]];
$repository = new ElasticIndexConfigurationRepository($indices, false);
/** @var AliasedIndexConfiguration $config */
$config = $repository->findForIndex('encyclopedia');
self::assertInstanceOf(IndexAliasConfiguration::class, $config->getAliasConfiguration());
self::assertFalse($config->getAliasConfiguration()->shouldOldAliasesBePruned());
Expand All @@ -237,10 +237,8 @@ public function test_it_can_set_default_settings_for_all_indices(): void
$configModel = $repository->findForIndex(':searchable_as:');
$configArray = $repository->findForIndex('encyclopedia');

self::assertNotNull($configModel);
self::assertEquals($defaultSettings, $configModel->getSettings());

self::assertNotNull($configArray);
self::assertEquals($defaultSettings, $configArray->getSettings());
}

Expand All @@ -255,15 +253,13 @@ public function test_it_can_override_default_index_settings_on_a_per_index_level
$configModel = $repository->findForIndex(':searchable_as:');
$configArray = $repository->findForIndex('encyclopedia');

self::assertNotNull($configModel);
self::assertNotEquals($defaultSettings, $configModel->getSettings());
self::assertNotEquals([], $configModel->getSettings());

self::assertNotNull($configArray);
self::assertNotEquals($defaultSettings, $configArray->getSettings());
self::assertEquals($indices['encyclopedia']['settings'], $configArray->getSettings());
}

public function test_it_throws_exception_if_index_settings_method_not_defined_with_analyser(): void
{
$defaultSettings = ['index' => ['max_result_window' => 100000]];
Expand All @@ -288,11 +284,9 @@ public function test_it_does_not_throw_exception_if_analyser_and_index_settings_
$configModel = $repository->findForIndex(':searchable_as:');
$configArray = $repository->findForIndex('encyclopedia');

self::assertNotNull($configModel);
self::assertNotEquals($defaultSettings, $configModel->getSettings());
self::assertNotEquals([], $configModel->getSettings());

self::assertNotNull($configArray);
self::assertNotEquals($defaultSettings, $configArray->getSettings());
self::assertEquals($indices['encyclopedia']['settings'], $configArray->getSettings());
}
Expand Down
2 changes: 1 addition & 1 deletion tests/Unit/IndexManagement/IndexAliasConfigurationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public function test_prune_property(): void
self::assertFalse($doNotPrune->shouldOldAliasesBePruned());
}

/** @dataProvider aliasProvider */
#[\PHPUnit\Framework\Attributes\DataProvider('aliasProvider')]
public function test_it_can_get_the_different_aliases(string $alias, string $method): void
{
$config = IndexAliasConfiguration::create(
Expand Down
1 change: 0 additions & 1 deletion tests/Unit/IndexManagement/IndexMappingNormalizerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ public function test_it_normalizes_mapping(): void

$normalizedMapping = $normalizer->normalize($mapping);

self::assertNotNull($normalizedMapping);
self::assertEquals($normalizedMapping['fld'], $normalizedMapping['fld']);
self::assertEquals([ 'type' => 'integer' ], $normalizedMapping['other']);

Expand Down
4 changes: 2 additions & 2 deletions tests/Unit/ScoutSearchCommandBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public function test_it_gets_searchable_fields(): void
self::assertSame(self::TEST_SEARCHABLE_FIELDS, $subject->getDefaultSearchFields());
}

/** @dataProvider buildCommandProvider */
#[\PHPUnit\Framework\Attributes\DataProvider('buildCommandProvider')]
public function test_it_sets_data_based_on_the_scout_builder(string $method, mixed $expected): void
{
$builder = Mockery::mock(Builder::class);
Expand All @@ -87,7 +87,7 @@ public function test_it_sets_data_based_on_the_scout_builder(string $method, mix
self::assertSame($expected, $subject->$getter());
}

/** @dataProvider buildCommandProvider */
#[\PHPUnit\Framework\Attributes\DataProvider('buildCommandProvider')]
public function test_it_works_with_setters_and_getters(string $method, mixed $expected): void
{
$command = new ScoutSearchCommandBuilder();
Expand Down
14 changes: 5 additions & 9 deletions tests/Unit/Syntax/Compound/BoolQueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,8 @@ public function test_it_can_build_an_empty_query(): void
self::assertSame($expected, $query);
}

/**
* @dataProvider queryTypeProvider
* @param string $type
*/
/** @param string $type */
#[\PHPUnit\Framework\Attributes\DataProvider('queryTypeProvider')]
public function test_it_accepts_different_types_of_queries_by_method(string $type): void
{
$subject = new BoolQuery();
Expand All @@ -53,10 +51,8 @@ public function test_it_accepts_different_types_of_queries_by_method(string $typ
self::assertSame($expected, $query['bool'][$type]);
}

/**
* @dataProvider queryTypeProvider
* @param string $type
*/
/** @param string $type */
#[\PHPUnit\Framework\Attributes\DataProvider('queryTypeProvider')]
public function test_it_accepts_different_types_of_queries_by_add(string $type): void
{
$subject = new BoolQuery();
Expand All @@ -72,10 +68,10 @@ public function test_it_accepts_different_types_of_queries_by_add(string $type):
}

/**
* @dataProvider syntaxProvider
* @param string $className
* @param array $args
*/
#[\PHPUnit\Framework\Attributes\DataProvider('syntaxProvider')]
public function test_it_accepts_different_types_of_syntax(string $className, array $args): void
{
$subject = new BoolQuery();
Expand Down
Loading