Skip to content

Commit f381883

Browse files
committed
v1.1.0
1 parent 6085213 commit f381883

File tree

9 files changed

+312
-8
lines changed

9 files changed

+312
-8
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"require-dev": {
1818
"phpunit/phpunit": "^10",
1919
"orchestra/testbench": "^8.5",
20-
"nunomaduro/collision": "^7.4"
20+
"nunomaduro/collision": "^7.5"
2121
},
2222
"autoload": {
2323
"psr-4": {

phpunit.xml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.1/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true">
3+
<testsuites>
4+
<testsuite name="Unit">
5+
<directory suffix="Test.php">./tests/Unit</directory>
6+
</testsuite>
7+
<testsuite name="Integration">
8+
<directory suffix="Test.php">./tests/Integration</directory>
9+
</testsuite>
10+
</testsuites>
11+
<coverage/>
12+
<source>
13+
<include>
14+
<directory suffix=".php">./app</directory>
15+
</include>
16+
</source>
17+
</phpunit>

src/Builder/Builder.php

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<?php
2+
3+
namespace Olekjs\Elasticsearch\Builder;
4+
5+
use Illuminate\Support\Traits\Conditionable;
6+
use LogicException;
7+
use Olekjs\Elasticsearch\Client;
8+
use Olekjs\Elasticsearch\Contracts\ClientInterface;
9+
use Olekjs\Elasticsearch\Dto\SearchResponseDto;
10+
11+
class Builder
12+
{
13+
use Conditionable;
14+
15+
private string $index;
16+
17+
private array $query;
18+
19+
private array $body = [];
20+
21+
public function __construct(private readonly ClientInterface $client)
22+
{
23+
}
24+
25+
public static function query(?ClientInterface $client = null): Builder
26+
{
27+
if (is_null($client)) {
28+
$client = new Client();
29+
}
30+
31+
return new Builder($client);
32+
}
33+
34+
public function index(string $index): self
35+
{
36+
$this->index = $index;
37+
38+
return $this;
39+
}
40+
41+
public function where(string $field, string $value): self
42+
{
43+
$this->query['bool']['filter'][]['term'][$field . '.keyword'] = $value;
44+
45+
return $this;
46+
}
47+
48+
public function whereLike(string $field, string|int|float|array $value): self
49+
{
50+
$this->query['bool']['filter'][]['term'][$field] = $value;
51+
52+
return $this;
53+
}
54+
55+
public function whereIn(string $field, array $values): self
56+
{
57+
$this->query['bool']['filter'][]['terms'][$field] = $values;
58+
59+
return $this;
60+
}
61+
62+
public function offset(int $offset): self
63+
{
64+
$this->body['from'] = $offset;
65+
66+
return $this;
67+
}
68+
69+
public function limit(int $limit): self
70+
{
71+
$this->body['size'] = $limit;
72+
73+
return $this;
74+
}
75+
76+
public function get(): SearchResponseDto
77+
{
78+
if (!isset($this->index)) {
79+
throw new LogicException('Index name is required.');
80+
}
81+
82+
if (isset($this->query)) {
83+
$this->body['query'] = $this->query;
84+
}
85+
86+
if (empty($this->body)) {
87+
$this->body['query'] = [
88+
'match_all' => (object)[]
89+
];
90+
}
91+
92+
return $this->client->search($this->index, $this->body);
93+
}
94+
95+
public function getIndex(): string
96+
{
97+
return $this->index;
98+
}
99+
100+
public function getBody(): array
101+
{
102+
return $this->body;
103+
}
104+
105+
public function getQuery(): array
106+
{
107+
return $this->query;
108+
}
109+
}

src/Contracts/AbstractIndex.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace Olekjs\Elasticsearch\Contracts;
4+
5+
use Olekjs\Elasticsearch\Builder\Builder;
6+
7+
abstract class AbstractIndex
8+
{
9+
protected string $index;
10+
11+
public function getIndexName(): string
12+
{
13+
return $this->index;
14+
}
15+
16+
public static function query(): Builder
17+
{
18+
$index = (new static)->getIndexName();
19+
20+
return Builder::query()->index($index);
21+
}
22+
}

src/Providers/ElasticsearchServiceProvider.php

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,9 @@
33
namespace Olekjs\Elasticsearch\Providers;
44

55
use Illuminate\Support\ServiceProvider;
6-
use Olekjs\Elasticsearch\Client;
76

87
class ElasticsearchServiceProvider extends ServiceProvider
98
{
10-
public function register(): void
11-
{
12-
$this->app->bind(Client::class, Client::class);
13-
}
14-
159
public function boot(): void
1610
{
1711
$this->mergeConfigFrom(__DIR__ . '/../../config/services.php', 'services');

tests/Integration/ClientTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?php
22

3-
namespace Olekjs\Tests\Integration;
3+
namespace Olekjs\Elasticsearch\Tests\Integration;
44

55
use Illuminate\Support\Facades\Http;
66
use Olekjs\Elasticsearch\Client;

tests/Support/CustomIndex.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Olekjs\Elasticsearch\Tests\Support;
4+
5+
use Olekjs\Elasticsearch\Contracts\AbstractIndex;
6+
7+
class CustomIndex extends AbstractIndex
8+
{
9+
protected string $index = 'test';
10+
}

tests/Unit/BuilderTest.php

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
<?php
2+
3+
namespace Olekjs\Elasticsearch\Tests\Unit;
4+
5+
use Olekjs\Elasticsearch\Builder\Builder;
6+
use Olekjs\Elasticsearch\Client;
7+
use Olekjs\Elasticsearch\Dto\SearchResponseDto;
8+
use PHPUnit\Framework\TestCase;
9+
10+
class BuilderTest extends TestCase
11+
{
12+
public function testIndexMethod(): void
13+
{
14+
$builder = Builder::query()->index('test');
15+
16+
$this->assertSame('test', $builder->getIndex());
17+
}
18+
19+
public function testWhereMethod(): void
20+
{
21+
$builder = Builder::query()->where('email', 'test@test.com');
22+
23+
$this->assertSame([
24+
'bool' => ['filter' => [['term' => ['email.keyword' => 'test@test.com']]]]
25+
], $builder->getQuery());
26+
}
27+
28+
public function testWhereLikeMethod(): void
29+
{
30+
$builder = Builder::query()->whereLike('name', 'test');
31+
32+
$this->assertSame([
33+
'bool' => ['filter' => [['term' => ['name' => 'test']]]]
34+
], $builder->getQuery());
35+
}
36+
37+
public function testWhereInMethod(): void
38+
{
39+
$builder = Builder::query()->whereIn('_id', [123, 321]);
40+
41+
$this->assertSame([
42+
'bool' => ['filter' => [['terms' => ['_id' => [123, 321]]]]]
43+
], $builder->getQuery());
44+
}
45+
46+
public function testOffsetMethod(): void
47+
{
48+
$builder = Builder::query()->offset(10);
49+
50+
$this->assertSame(['from' => 10], $builder->getBody());
51+
}
52+
53+
public function testLimitMethod(): void
54+
{
55+
$builder = Builder::query()->limit(10);
56+
57+
$this->assertSame(['size' => 10], $builder->getBody());
58+
}
59+
60+
public function testGetMethod(): void
61+
{
62+
$client = $this->getMockBuilder(Client::class)->getMock();
63+
64+
$results = Builder::query($client)->index('test')->get();
65+
66+
$this->assertInstanceOf(SearchResponseDto::class, $results);
67+
}
68+
69+
public function testConditionableTrait(): void
70+
{
71+
$builder = Builder::query()->when(
72+
true,
73+
fn(Builder $builder) => $builder->where('email', 'test@test.com')
74+
);
75+
76+
$this->assertSame([
77+
'bool' => ['filter' => [['term' => ['email.keyword' => 'test@test.com']]]]
78+
], $builder->getQuery());
79+
80+
$builder = Builder::query()->when(
81+
false,
82+
fn(Builder $builder) => $builder->where('email', 'test@test.com')
83+
);
84+
85+
$this->assertEmpty($builder->getBody());
86+
}
87+
88+
public function testChainedMethods(): void
89+
{
90+
$builder = Builder::query()
91+
->where('email', 'test@test.com')
92+
->where('slug', 'test-slug')
93+
->whereLike('name', 'test')
94+
->whereIn('_id', [123, 321])
95+
->limit(10);
96+
97+
$this->assertSame(['size' => 10], $builder->getBody());
98+
99+
$this->assertSame(
100+
[
101+
'bool' => [
102+
'filter' => [
103+
[
104+
'term' => [
105+
'email.keyword' => 'test@test.com'
106+
]
107+
],
108+
[
109+
'term' => [
110+
'slug.keyword' => 'test-slug'
111+
]
112+
],
113+
[
114+
'term' => [
115+
'name' => 'test'
116+
]
117+
],
118+
[
119+
'terms' => [
120+
'_id' => [123, 321]
121+
]
122+
]
123+
]
124+
]
125+
],
126+
$builder->getQuery()
127+
);
128+
}
129+
}

tests/Unit/CustomIndexTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace Unit;
4+
5+
use Olekjs\Elasticsearch\Builder\Builder;
6+
use Olekjs\Elasticsearch\Client;
7+
use Olekjs\Elasticsearch\Contracts\AbstractIndex;
8+
use Olekjs\Elasticsearch\Dto\SearchResponseDto;
9+
use Olekjs\Elasticsearch\Tests\Support\CustomIndex;
10+
use PHPUnit\Framework\TestCase;
11+
12+
class CustomIndexTest extends TestCase
13+
{
14+
public function testCustomIndexMethod(): void
15+
{
16+
$customIndex = new CustomIndex();
17+
18+
$this->assertSame('test', $customIndex->getIndexName());
19+
$this->assertInstanceOf(Builder::class, $customIndex->query());
20+
$this->assertInstanceOf(Builder::class, CustomIndex::query());
21+
$this->assertSame('test', CustomIndex::query()->getIndex());
22+
}
23+
}

0 commit comments

Comments
 (0)