Skip to content

Commit 8beaed2

Browse files
authored
Merge pull request #13 from pionl/geo-bounding-box-query
Add bottomLeft / topRight settings to geo bounding box query
2 parents aa8cf0b + 9ff6960 commit 8beaed2

File tree

2 files changed

+98
-7
lines changed

2 files changed

+98
-7
lines changed

src/Query/GeoBoundingBoxQuery.php

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Erichard\ElasticQueryBuilder\Contracts\QueryInterface;
88
use Erichard\ElasticQueryBuilder\Entities\GpsPointEntity;
99
use Erichard\ElasticQueryBuilder\Features\HasField;
10+
use Exception;
1011

1112
/**
1213
* @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-geo-bounding-box-query.html
@@ -17,26 +18,40 @@ class GeoBoundingBoxQuery implements QueryInterface
1718

1819
public function __construct(
1920
string $field,
20-
private GpsPointEntity $topLeft,
21-
private GpsPointEntity $bottomRight
21+
private GpsPointEntity|null $topLeft = null,
22+
private GpsPointEntity|null $bottomRight = null,
23+
private GpsPointEntity|null $topRight = null,
24+
private GpsPointEntity|null $bottomLeft = null,
2225
) {
2326
$this->field = $field;
2427
}
2528

2629
public function build(): array
2730
{
31+
$filters = array_filter([
32+
'top_left' => $this->pointToArray($this->topLeft),
33+
'bottom_right' => $this->pointToArray($this->bottomRight),
34+
'top_right' => $this->pointToArray($this->topRight),
35+
'bottom_left' => $this->pointToArray($this->bottomLeft),
36+
]);
37+
38+
if (count($filters) < 2) {
39+
throw new Exception('GeoBoundingBoxQuery needs at least 2 sides set');
40+
}
41+
2842
return [
2943
'geo_bounding_box' => [
30-
$this->field => [
31-
'top_left' => $this->pointToArray($this->topLeft),
32-
'bottom_right' => $this->pointToArray($this->bottomRight),
33-
],
44+
$this->field => $filters,
3445
],
3546
];
3647
}
3748

38-
protected function pointToArray(GpsPointEntity $entity): array
49+
protected function pointToArray(?GpsPointEntity $entity): ?array
3950
{
51+
if ($entity === null) {
52+
return null;
53+
}
54+
4055
return [
4156
'lat' => $entity->lat,
4257
'lon' => $entity->lon,
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Tests\Erichard\ElasticQueryBuilder\Query;
6+
7+
use Erichard\ElasticQueryBuilder\Entities\GpsPointEntity;
8+
use Erichard\ElasticQueryBuilder\Query\GeoBoundingBoxQuery;
9+
use PHPUnit\Framework\TestCase;
10+
11+
class GeoBoundingBoxQueryTest extends TestCase
12+
{
13+
public function testBuildFailsOnAllNull(): void
14+
{
15+
$this->expectErrorMessage('GeoBoundingBoxQuery needs at least 2 sides set');
16+
(new GeoBoundingBoxQuery('test'))->build();
17+
}
18+
19+
public function testBuildFailsOnOneFilter(): void
20+
{
21+
$this->expectErrorMessage('GeoBoundingBoxQuery needs at least 2 sides set');
22+
(new GeoBoundingBoxQuery(field: 'test', topLeft: new GpsPointEntity(1.1, 2.1)))->build();
23+
}
24+
25+
public function testBuildTopLeftBottomRight(): void
26+
{
27+
$result = (new GeoBoundingBoxQuery(
28+
field: 'test',
29+
topLeft: new GpsPointEntity(1.1, 2.1),
30+
bottomRight: new GpsPointEntity(2.1, 3.1),
31+
))->build();
32+
33+
$this->assertEquals([
34+
'geo_bounding_box' => [
35+
'test' => [
36+
'top_left' => [
37+
'lat' => 1.1,
38+
'lon' => 2.1,
39+
],
40+
'bottom_right' => [
41+
'lat' => 2.1,
42+
'lon' => 3.1,
43+
44+
],
45+
46+
],
47+
],
48+
], $result);
49+
}
50+
51+
public function testBuildTopRightBottomLeft(): void
52+
{
53+
$result = (new GeoBoundingBoxQuery(
54+
field: 'test',
55+
topRight: new GpsPointEntity(1.1, 2.1),
56+
bottomLeft: new GpsPointEntity(2.1, 3.1),
57+
))->build();
58+
59+
$this->assertEquals([
60+
'geo_bounding_box' => [
61+
'test' => [
62+
'top_right' => [
63+
'lat' => 1.1,
64+
'lon' => 2.1,
65+
],
66+
'bottom_left' => [
67+
'lat' => 2.1,
68+
'lon' => 3.1,
69+
70+
],
71+
72+
],
73+
],
74+
], $result);
75+
}
76+
}

0 commit comments

Comments
 (0)