Skip to content

Commit 43c6d10

Browse files
committed
- Still allow collections inside the filterBy method - this "undoes" the planned breaking change with the compound filters
- extracted the query building of the post data into its own method to clean up the query method and simplify debugging - added the method "addFilters" to FilterBag to quickly add multiple filters
1 parent 241ce71 commit 43c6d10

File tree

4 files changed

+96
-29
lines changed

4 files changed

+96
-29
lines changed

src/Endpoints/Database.php

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use FiveamCode\LaravelNotionApi\Notion;
99
use FiveamCode\LaravelNotionApi\Query\Filters\Filter;
1010
use FiveamCode\LaravelNotionApi\Query\Filters\FilterBag;
11+
use FiveamCode\LaravelNotionApi\Query\Filters\Operators;
1112
use FiveamCode\LaravelNotionApi\Query\Sorting;
1213
use Illuminate\Support\Collection;
1314

@@ -38,8 +39,8 @@ class Database extends Endpoint
3839
/**
3940
* Database constructor.
4041
*
41-
* @param string $databaseId
42-
* @param Notion $notion
42+
* @param string $databaseId
43+
* @param Notion $notion
4344
*
4445
* @throws \FiveamCode\LaravelNotionApi\Exceptions\HandlingException
4546
* @throws \FiveamCode\LaravelNotionApi\Exceptions\LaravelNotionAPIException
@@ -61,15 +62,26 @@ public function __construct(string $databaseId, Notion $notion)
6162
*/
6263
public function query(): PageCollection
6364
{
65+
$response = $this
66+
->post(
67+
$this->url(Endpoint::DATABASES . "/{$this->databaseId}/query"),
68+
$this->getPostData()
69+
)
70+
->json();
71+
72+
return new PageCollection($response);
73+
}
74+
75+
public function getPostData():array {
6476
$postData = [];
6577

6678
if ($this->sorts->isNotEmpty()) {
6779
$postData['sorts'] = Sorting::sortQuery($this->sorts);
6880
}
6981

70-
if ($this->filter !== null && ! is_null($this->filterBag)) {
82+
if ($this->filter !== null && !is_null($this->filterBag)) {
7183
throw new HandlingException('Please provide either a filter bag or a single filter.');
72-
} elseif ($this->filter !== null || ! is_null($this->filterBag)) {
84+
} elseif ($this->filter !== null || !is_null($this->filterBag)) {
7385
$postData['filter'] = $this->filterData;
7486
}
7587

@@ -81,14 +93,7 @@ public function query(): PageCollection
8193
$postData['page_size'] = $this->pageSize;
8294
}
8395

84-
$response = $this
85-
->post(
86-
$this->url(Endpoint::DATABASES."/{$this->databaseId}/query"),
87-
$postData
88-
)
89-
->json();
90-
91-
return new PageCollection($response);
96+
return $postData;
9297
}
9398

9499
/**
@@ -97,12 +102,12 @@ public function query(): PageCollection
97102
*
98103
* @throws HandlingException
99104
*
100-
* @todo As soon as this package drops PHP 7.4 support, we can use union types here (FilterBag and Filter)
101105
*/
102-
public function filterBy($filter): Database // TODO that's a breaking change
106+
public function filterBy(Collection|Filter|FilterBag $filter): Database
103107
{
104-
$this->checkFilterType($filter);
105-
108+
if($filter instanceof Collection) {
109+
return $this->filterByCollection($filter);
110+
}
106111
if ($filter instanceof FilterBag) {
107112
return $this->filterByBag($filter);
108113
}
@@ -113,6 +118,11 @@ public function filterBy($filter): Database // TODO that's a breaking change
113118
return $this;
114119
}
115120

121+
/**
122+
* @param Filter $filter
123+
* @return $this
124+
* @throws HandlingException
125+
*/
116126
public function filterBySingleFilter(Filter $filter): Database
117127
{
118128
$this->filter = $filter;
@@ -122,8 +132,8 @@ public function filterBySingleFilter(Filter $filter): Database
122132
}
123133

124134
/**
125-
* @param FilterBag $filterBag
126-
* @return $this
135+
* @param FilterBag $filterBag
136+
* @return Database $this
127137
*/
128138
public function filterByBag(FilterBag $filterBag): Database
129139
{
@@ -134,7 +144,18 @@ public function filterByBag(FilterBag $filterBag): Database
134144
}
135145

136146
/**
137-
* @param Collection|Sorting $sorts
147+
* @param Collection $filterCollection
148+
* @return Database $this
149+
*/
150+
public function filterByCollection(Collection $filterCollection): Database {
151+
$filterBag = new FilterBag(Operators::OR);
152+
$filterBag->addFilters($filterCollection);
153+
154+
return $this->filterByBag($filterBag);
155+
}
156+
157+
/**
158+
* @param Collection|Sorting $sorts
138159
* @return Database $this
139160
*
140161
* @throws HandlingException
@@ -150,14 +171,14 @@ public function sortBy(Sorting|Collection $sorts): Database
150171
$this->sorts = $sorts;
151172
break;
152173
default:
153-
throw new HandlingException("The parameter 'sorts' must be either a instance of the class Sorting or a Collection of Sortings.");
174+
throw new HandlingException("The parameter 'sorts' must be either a instance of the class Sorting or a Collection of sortings.");
154175
}
155176

156177
return $this;
157178
}
158179

159180
/**
160-
* @param EntityCollection $entityCollection
181+
* @param EntityCollection $entityCollection
161182
* @return $this
162183
*/
163184
public function offsetByResponse(EntityCollection $entityCollection): Database
@@ -166,11 +187,4 @@ public function offsetByResponse(EntityCollection $entityCollection): Database
166187

167188
return $this;
168189
}
169-
170-
private function checkFilterType($filter): void
171-
{
172-
if (! ($filter instanceof Filter || $filter instanceof FilterBag)) {
173-
throw new HandlingException('Please provide either a filter bag or a single filter.');
174-
}
175-
}
176190
}

src/Query/Filters/FilterBag.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,18 @@ public function addFilter(Filter $filter): self
6969
return $this;
7070
}
7171

72+
public function addFilters(Collection $filters): self
73+
{
74+
foreach ($filters as $filter) {
75+
if(!$filter instanceof Filter) {
76+
throw new HandlingException('The filter bag must only contain filter objects.');
77+
}
78+
$this->addFilter($filter);
79+
}
80+
81+
return $this;
82+
}
83+
7284
/**
7385
* @throws HandlingException|Throwable
7486
*/

tests/EndpointDatabaseTest.php

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
use FiveamCode\LaravelNotionApi\Endpoints\Database;
44
use FiveamCode\LaravelNotionApi\Entities\Collections\PageCollection;
55
use FiveamCode\LaravelNotionApi\Entities\Page;
6+
use FiveamCode\LaravelNotionApi\Exceptions\HandlingException;
67
use FiveamCode\LaravelNotionApi\Exceptions\NotionException;
78
use FiveamCode\LaravelNotionApi\Query\Filters\Filter;
9+
use FiveamCode\LaravelNotionApi\Query\Filters\FilterBag;
10+
use FiveamCode\LaravelNotionApi\Query\Filters\Operators;
811
use FiveamCode\LaravelNotionApi\Query\Sorting;
912
use FiveamCode\LaravelNotionApi\Query\StartCursor;
1013
use Illuminate\Support\Collection;
@@ -33,6 +36,24 @@
3336
$this->assertInstanceOf(Database::class, $endpoint);
3437
});
3538

39+
it('allows a filter, filter bag or collection of filters inside the filterBy method', function () {
40+
$filter = Filter::textFilter('Name', Operators::CONTAINS, 'Grace');
41+
$filterCollection = (new Collection)->add($filter);
42+
$filterBag = (new FilterBag(Operators::AND))->addFilter($filter);
43+
44+
$endpoint = Notion::database('8284f3ff77e24d4a939d19459e4d6bdc');
45+
46+
$endpoint->filterBy($filter);
47+
$endpoint->filterBy($filterCollection);
48+
$endpoint->filterBy($filterBag);
49+
50+
$this->expectException(HandlingException::class);
51+
$this->expectExceptionMessage('The filter bag must only contain filter objects.');
52+
53+
$filterCollection->add(1);
54+
$endpoint->filterBy($filterCollection);
55+
});
56+
3657
it('queries a database with filter and sorting and processes result', function ($limit) {
3758
// success /v1/databases/DATABASE_DOES_EXIST/query
3859
Http::fake([
@@ -92,7 +113,7 @@
92113
),
93114
]);
94115

95-
// Let's search for something that doesn't exists
116+
// Let's search for something that doesn't exist
96117
$filters = new Collection();
97118

98119
$filter = Filter::rawFilter(

tests/FilterTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use FiveamCode\LaravelNotionApi\Exceptions\HandlingException;
44
use FiveamCode\LaravelNotionApi\Query\Filters\Filter;
55
use FiveamCode\LaravelNotionApi\Query\Filters\Operators;
6+
use Illuminate\Support\Collection;
67

78
it('creates a text filter with the given data', function () {
89
$filter = Filter::textFilter('Name', Operators::EQUALS, 'Ada Lovelace');
@@ -39,3 +40,22 @@
3940
$this->expectExceptionMessage('Invalid filter definition.');
4041
$filter->toArray();
4142
});
43+
44+
it('converts a collection of filters to a filter bag with an OR operator', function () {
45+
$filter = Filter::textFilter('Name', Operators::CONTAINS, 'Grace');
46+
$filterCollection = (new Collection())->add($filter);
47+
48+
$endpoint = Notion::database('8284f3ff77e24d4a939d19459e4d6bdc');
49+
50+
$endpoint->filterBy($filterCollection);
51+
52+
$queryData = $endpoint->getPostData();
53+
54+
$this->assertArrayHasKey('filter', $queryData);
55+
$this->assertArrayHasKey('or', $queryData['filter']);
56+
$this->assertArrayHasKey('property', $queryData['filter']['or'][0]);
57+
$this->assertEquals('Name', $queryData['filter']['or'][0]['property']);
58+
$this->assertArrayHasKey('text', $queryData['filter']['or'][0]);
59+
$this->assertArrayHasKey('contains', $queryData['filter']['or'][0]['text']);
60+
$this->assertEquals('Grace', $queryData['filter']['or'][0]['text']['contains']);
61+
});

0 commit comments

Comments
 (0)