Skip to content

Commit 0e9ffba

Browse files
authored
10.4.0 (#689)
* feat: adding the filtered query builder as a second argument in props of getters * Fix styling * fix: adding query filtered to request * Fix styling * fix: wip --------- Co-authored-by: binaryk <[email protected]>
1 parent 8ae860e commit 0e9ffba

File tree

7 files changed

+119
-14
lines changed

7 files changed

+119
-14
lines changed

docs-v3/content/docs/api/getters.md

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,27 @@ public function handle(Request $request)
143143
}
144144
```
145145

146+
#### Accessing the filtered query
147+
148+
For index getters, you can access the filtered query builder via `$request->filteredQuery()`. This query builder already has all filters, search queries, and other query modifiers applied by Restify:
149+
150+
```php
151+
public function handle(Request $request): JsonResponse
152+
{
153+
// Get the filtered query builder with all applied filters, search, etc.
154+
$query = $request->filteredQuery();
155+
156+
// You can further refine the query
157+
$data = $query->where('status', 'active')->get();
158+
159+
return response()->json([
160+
'data' => $data,
161+
]);
162+
}
163+
```
164+
165+
This allows you to build upon the existing query without having to manually apply filters again.
166+
146167
## Getter customizations
147168

148169
Getters could be easily customized.
@@ -278,16 +299,26 @@ Index getters are used when you have to apply them for many items.
278299

279300
### Index getter definition
280301

281-
The index getter definition differs in how it receives arguments for the `handle` method.
302+
The index getter definition receives only the `$request` in the `handle` method. You can access the filtered query builder using `$request->filteredQuery()`:
282303

283304
```php
284305
public function handle(Request $request): JsonResponse
285306
{
286-
//
307+
// Get the filtered query builder with all applied filters, search, etc.
308+
$query = $request->filteredQuery();
309+
310+
// You can further refine the query
311+
$data = $query->where('status', 'active')->get();
312+
313+
return response()->json([
314+
'data' => $data,
315+
]);
287316
}
288317

289318
```
290319

320+
The filtered query builder contains all repository filters, search queries, and other query modifiers already applied. This allows you to leverage existing filters without re-implementing them.
321+
291322
### Index getter registration
292323

293324
To register an index getter, we have to use the `->onlyOnIndex()` accessor:

src/Http/Requests/Concerns/InteractWithRepositories.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Binaryk\LaravelRestify\Repositories\Repository;
88
use Binaryk\LaravelRestify\Repositories\RepositoryInstance;
99
use Binaryk\LaravelRestify\Restify;
10+
use Binaryk\LaravelRestify\Services\Search\RepositorySearchService;
1011
use Illuminate\Database\Eloquent\Builder;
1112
use Illuminate\Database\Eloquent\Model;
1213
use Illuminate\Database\Eloquent\Relations\Relation;
@@ -121,4 +122,9 @@ public function isViaRepository(): bool
121122

122123
return $parentRepository && $parentRepositoryId;
123124
}
125+
126+
public function filteredQuery(): Builder
127+
{
128+
return RepositorySearchService::make()->search($this, $this->repository());
129+
}
124130
}

src/MCP/Bootstrap/BootMcpTools.php

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ protected function discoverCustomTools(): Collection
140140
protected function discoverRepositoryTools(): Collection
141141
{
142142
return collect(Restify::$repositories)
143-
->filter(fn(string $repo): bool => in_array(HasMcpTools::class, class_uses_recursive($repo)))
144-
->flatMap(fn(string $repoClass): Collection => $this->discoverRepositoryOperations($repoClass))
143+
->filter(fn (string $repo): bool => in_array(HasMcpTools::class, class_uses_recursive($repo)))
144+
->flatMap(fn (string $repoClass): Collection => $this->discoverRepositoryOperations($repoClass))
145145
->values();
146146
}
147147

@@ -211,10 +211,10 @@ protected function discoverActions(string $repositoryClass, Repository $reposito
211211
$actionRequest = app(McpActionRequest::class);
212212

213213
return $repository->resolveActions($actionRequest)
214-
->filter(fn($action): bool => $action instanceof Action)
215-
->filter(fn(Action $action): bool => $action->isShownOnMcp($actionRequest, $repository))
216-
->filter(fn(Action $action): bool => $action->authorizedToSee($actionRequest))
217-
->unique(fn(Action $action): string => $action->uriKey())
214+
->filter(fn ($action): bool => $action instanceof Action)
215+
->filter(fn (Action $action): bool => $action->isShownOnMcp($actionRequest, $repository))
216+
->filter(fn (Action $action): bool => $action->authorizedToSee($actionRequest))
217+
->unique(fn (Action $action): string => $action->uriKey())
218218
->map(function (Action $action) use ($repositoryClass, $repository): array {
219219
$instance = new ActionTool($repositoryClass, $action);
220220

@@ -241,10 +241,10 @@ protected function discoverGetters(string $repositoryClass, Repository $reposito
241241
$getterRequest = app(McpGetterRequest::class);
242242

243243
return $repository->resolveGetters($getterRequest)
244-
->filter(fn($getter): bool => $getter instanceof Getter)
245-
->filter(fn(Getter $getter): bool => $getter->isShownOnMcp($getterRequest, $repository))
246-
->filter(fn(Getter $getter): bool => $getter->authorizedToSee($getterRequest))
247-
->unique(fn(Getter $getter): string => $getter->uriKey())
244+
->filter(fn ($getter): bool => $getter instanceof Getter)
245+
->filter(fn (Getter $getter): bool => $getter->isShownOnMcp($getterRequest, $repository))
246+
->filter(fn (Getter $getter): bool => $getter->authorizedToSee($getterRequest))
247+
->unique(fn (Getter $getter): string => $getter->uriKey())
248248
->map(function (Getter $getter) use ($repositoryClass, $repository): array {
249249
$instance = new GetterTool($repositoryClass, $getter);
250250

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace Binaryk\LaravelRestify\Tests\Fixtures\Post\Getters;
4+
5+
use Binaryk\LaravelRestify\Getters\Getter;
6+
use Illuminate\Http\JsonResponse;
7+
use Illuminate\Http\Request;
8+
9+
class PostsFilteredQueryGetter extends Getter
10+
{
11+
public static $uriKey = 'posts-filtered-query-getter';
12+
13+
public function handle(Request $request): JsonResponse
14+
{
15+
$query = $request->filteredQuery();
16+
17+
$count = $query->count();
18+
19+
return response()->json([
20+
'message' => 'filtered query works',
21+
'count' => $count,
22+
]);
23+
}
24+
}

tests/Fixtures/Post/PostRepository.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Binaryk\LaravelRestify\Http\Requests\ActionRequest;
88
use Binaryk\LaravelRestify\Http\Requests\RestifyRequest;
99
use Binaryk\LaravelRestify\Repositories\Repository;
10+
use Binaryk\LaravelRestify\Tests\Fixtures\Post\Getters\PostsFilteredQueryGetter;
1011
use Binaryk\LaravelRestify\Tests\Fixtures\Post\Getters\PostsIndexGetter;
1112
use Binaryk\LaravelRestify\Tests\Fixtures\Post\Getters\PostsIndexInvokableGetter;
1213
use Binaryk\LaravelRestify\Tests\Fixtures\Post\Getters\PostsShowGetter;
@@ -139,6 +140,7 @@ public function getters(RestifyRequest $request): array
139140
PostsIndexGetter::make(),
140141
PostsShowGetter::make()->onlyOnShow(),
141142
UnauthenticatedActionGetter::make()->withoutMiddleware(AuthorizeRestify::class),
143+
PostsFilteredQueryGetter::make(),
142144
new PostsShowInvokableGetter,
143145
new PostsIndexInvokableGetter,
144146
];

tests/Getters/ListGettersControllerTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public function test_could_list_getters_for_repository(): void
1616
fn (AssertableJson $json) => $json
1717
->has('data')
1818
->where('data.0.uriKey', 'posts-index-getter')
19-
->count('data', 4)
19+
->count('data', 5)
2020
->etc()
2121
);
2222
}
@@ -31,7 +31,7 @@ public function test_could_list_getters_for_given_repository(): void
3131
fn (AssertableJson $json) => $json
3232
->has('data')
3333
->where('data.1.uriKey', 'posts-show-getter')
34-
->count('data', 5)
34+
->count('data', 6)
3535
->etc()
3636
);
3737
}

tests/Getters/PerformGetterControllerTest.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
namespace Binaryk\LaravelRestify\Tests\Getters;
44

5+
use Binaryk\LaravelRestify\Tests\Fixtures\Post\Getters\PostsFilteredQueryGetter;
56
use Binaryk\LaravelRestify\Tests\Fixtures\Post\Getters\PostsIndexGetter;
67
use Binaryk\LaravelRestify\Tests\Fixtures\Post\Getters\PostsIndexInvokableGetter;
78
use Binaryk\LaravelRestify\Tests\Fixtures\Post\Getters\PostsShowGetter;
89
use Binaryk\LaravelRestify\Tests\Fixtures\Post\Getters\PostsShowInvokableGetter;
10+
use Binaryk\LaravelRestify\Tests\Fixtures\Post\Post;
911
use Binaryk\LaravelRestify\Tests\Fixtures\Post\PostRepository;
1012
use Binaryk\LaravelRestify\Tests\IntegrationTestCase;
1113
use Illuminate\Testing\Fluent\AssertableJson;
@@ -62,4 +64,44 @@ public function test_could_perform_repository_invokable_getter(): void
6264
->etc()
6365
);
6466
}
67+
68+
public function test_getter_can_access_filtered_query(): void
69+
{
70+
// Create 5 posts: 3 active, 2 inactive
71+
Post::factory()->count(3)->create(['is_active' => true]);
72+
Post::factory()->count(2)->create(['is_active' => false]);
73+
74+
// Call getter without filter - should return all 5 posts
75+
$this
76+
->getJson(PostRepository::getter(PostsFilteredQueryGetter::class))
77+
->assertOk()
78+
->assertJson(
79+
fn (AssertableJson $json) => $json
80+
->where('message', 'filtered query works')
81+
->where('count', 5)
82+
->etc()
83+
);
84+
85+
// Call getter with active filter - should return only 3 active posts
86+
$this
87+
->getJson(PostRepository::getter(PostsFilteredQueryGetter::class).'?is_active=1')
88+
->assertOk()
89+
->assertJson(
90+
fn (AssertableJson $json) => $json
91+
->where('message', 'filtered query works')
92+
->where('count', 3)
93+
->etc()
94+
);
95+
96+
// Call getter with inactive filter - should return only 2 inactive posts
97+
$this
98+
->getJson(PostRepository::getter(PostsFilteredQueryGetter::class).'?is_active=0')
99+
->assertOk()
100+
->assertJson(
101+
fn (AssertableJson $json) => $json
102+
->where('message', 'filtered query works')
103+
->where('count', 2)
104+
->etc()
105+
);
106+
}
65107
}

0 commit comments

Comments
 (0)