Skip to content

Commit da9f86a

Browse files
authored
Merge pull request #114 from 5am-code/feature/allow-filter-collections
Still allow filter collections
2 parents 241ce71 + e818d67 commit da9f86a

File tree

4 files changed

+92
-23
lines changed

4 files changed

+92
-23
lines changed

src/Endpoints/Database.php

Lines changed: 38 additions & 22 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

@@ -60,6 +61,18 @@ public function __construct(string $databaseId, Notion $notion)
6061
* @throws \FiveamCode\LaravelNotionApi\Exceptions\NotionException
6162
*/
6263
public function query(): PageCollection
64+
{
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
6376
{
6477
$postData = [];
6578

@@ -81,28 +94,20 @@ public function query(): PageCollection
8194
$postData['page_size'] = $this->pageSize;
8295
}
8396

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

94100
/**
95101
* @param $filter
96102
* @return Database $this
97103
*
98104
* @throws HandlingException
99-
*
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,12 @@ 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+
*
125+
* @throws HandlingException
126+
*/
116127
public function filterBySingleFilter(Filter $filter): Database
117128
{
118129
$this->filter = $filter;
@@ -123,7 +134,7 @@ public function filterBySingleFilter(Filter $filter): Database
123134

124135
/**
125136
* @param FilterBag $filterBag
126-
* @return $this
137+
* @return Database $this
127138
*/
128139
public function filterByBag(FilterBag $filterBag): Database
129140
{
@@ -133,6 +144,18 @@ public function filterByBag(FilterBag $filterBag): Database
133144
return $this;
134145
}
135146

147+
/**
148+
* @param Collection $filterCollection
149+
* @return Database $this
150+
*/
151+
public function filterByCollection(Collection $filterCollection): Database
152+
{
153+
$filterBag = new FilterBag(Operators::OR);
154+
$filterBag->addFilters($filterCollection);
155+
156+
return $this->filterByBag($filterBag);
157+
}
158+
136159
/**
137160
* @param Collection|Sorting $sorts
138161
* @return Database $this
@@ -150,7 +173,7 @@ public function sortBy(Sorting|Collection $sorts): Database
150173
$this->sorts = $sorts;
151174
break;
152175
default:
153-
throw new HandlingException("The parameter 'sorts' must be either a instance of the class Sorting or a Collection of Sortings.");
176+
throw new HandlingException("The parameter 'sorts' must be either a instance of the class Sorting or a Collection of sortings.");
154177
}
155178

156179
return $this;
@@ -166,11 +189,4 @@ public function offsetByResponse(EntityCollection $entityCollection): Database
166189

167190
return $this;
168191
}
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-
}
176192
}

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)