Skip to content

Commit 1f37bf9

Browse files
authored
Merge pull request #93 from Lomkit/fix/belongs-to-many-search-query
Fix/belongs to many search query
2 parents 6063ef9 + a63e307 commit 1f37bf9

10 files changed

+130
-6
lines changed

Diff for: README.md

-1
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,3 @@ Here is a quick look at what you can do using API search method:
9292
- Refactor the response class
9393
- Plain text search using Laravel Scout
9494
- Alias for includes / aggregates
95-
- Add accurate examples in auto documentation

Diff for: src/Concerns/Resource/Relationable.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ public function relation($name)
2727
return $relation->relation === $relationName;
2828
});
2929

30-
if ($isSubRelation && Str::contains($nestedRelation = Str::after($name, '.'), '.')) {
30+
if ($isSubRelation) {
31+
$nestedRelation = Str::after($name, '.');
32+
3133
return $relation->resource()->relation($nestedRelation);
3234
}
3335

Diff for: src/Query/Traits/PerformSearch.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ public function filter($field, $operator, $value, $type = 'and', $nested = null)
8585

8686
// Here we assume the user has asked a relation filter
8787
if (Str::contains($field, '.')) {
88-
$relation = $this->resource->relation($field);
88+
$relation = $this->resource->relation(
89+
Str::beforeLast($field, '.')
90+
);
8991

9092
return $relation->filter($this->queryBuilder, $field, $operator, $value, $type, function ($query) use ($relation) {
9193
$relation->applySearchQuery($query);

Diff for: src/helpers.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
*/
1111
function relation_without_pivot(string $relation)
1212
{
13-
return \Illuminate\Support\Str::contains($relation, '.pivot.') ?
14-
\Illuminate\Support\Str::replaceLast('pivot.', '', $relation) :
13+
return \Illuminate\Support\Str::contains($relation, '.pivot.') || \Illuminate\Support\Str::endsWith($relation, '.pivot') ?
14+
\Illuminate\Support\Str::replaceLast('.pivot', '', $relation) :
1515
$relation;
1616
}
1717
}

Diff for: tests/Feature/Controllers/SearchIncludingRelationshipsOperationsTest.php

+72
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
namespace Lomkit\Rest\Tests\Feature\Controllers;
44

5+
use Illuminate\Support\Arr;
56
use Illuminate\Support\Facades\Gate;
67
use Lomkit\Rest\Http\Requests\RestRequest;
8+
use Lomkit\Rest\Relations\Relation;
79
use Lomkit\Rest\Tests\Feature\TestCase;
810
use Lomkit\Rest\Tests\Support\Database\Factories\BelongsToManyRelationFactory;
911
use Lomkit\Rest\Tests\Support\Database\Factories\BelongsToRelationFactory;
@@ -259,6 +261,76 @@ public function test_getting_a_list_of_resources_including_belongs_to_has_many_r
259261
);
260262
}
261263

264+
public function test_getting_a_list_of_resources_including_distant_relation_with_intermediary_search_query_condition(): void
265+
{
266+
$matchingModel = ModelFactory::new()->create(
267+
['number' => 1]
268+
)->fresh();
269+
270+
$belongsToMany = BelongsToManyRelationFactory::new()
271+
->for($matchingModel)
272+
->create();
273+
274+
$matchingModel2 = ModelFactory::new()
275+
->afterCreating(function (Model $model) use ($belongsToMany) {
276+
$model->belongsToManyQueryChangesRelation()
277+
->attach($belongsToMany);
278+
})
279+
->create()->fresh();
280+
281+
Gate::policy(Model::class, GreenPolicy::class);
282+
Gate::policy(BelongsToManyRelation::class, GreenPolicy::class);
283+
284+
$response = $this->post(
285+
'/api/models/search',
286+
[
287+
'search' => [
288+
'includes' => [
289+
['relation' => 'belongsToManyRelation.model'],
290+
],
291+
],
292+
],
293+
['Accept' => 'application/json']
294+
);
295+
296+
$matchingModelBelongsToManyQueryChangesRelations = $matchingModel2->belongsToManyQueryChangesRelation;
297+
298+
$this->assertResourcePaginated(
299+
$response,
300+
[$matchingModel, $matchingModel2],
301+
new ModelResource(),
302+
[
303+
[
304+
'belongs_to_many_relation' => [],
305+
],
306+
[
307+
'belongs_to_many_relation' => $matchingModelBelongsToManyQueryChangesRelations
308+
->map(function (BelongsToManyRelation $belongsToManyRelation) {
309+
return array_merge(
310+
$belongsToManyRelation
311+
->only((new BelongsToManyResource())->getFields(app()->make(RestRequest::class))),
312+
[
313+
'model' => null,
314+
'belongs_to_many_pivot' => Arr::only(
315+
$belongsToManyRelation
316+
->belongs_to_many_pivot
317+
->toArray(),
318+
Arr::first(
319+
(new ModelResource())->getRelations(app()->make(RestRequest::class)),
320+
function (Relation $relation) {
321+
return $relation->relation === 'belongsToManyRelation';
322+
}
323+
)->getPivotFields()
324+
),
325+
]
326+
);
327+
})
328+
->toArray(),
329+
],
330+
]
331+
);
332+
}
333+
262334
public function test_getting_a_list_of_resources_including_has_one_relation(): void
263335
{
264336
$matchingModel = ModelFactory::new()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class() extends Migration {
8+
/**
9+
* Run the migrations.
10+
*
11+
* @return void
12+
*/
13+
public function up()
14+
{
15+
Schema::table('belongs_to_many_relations', function (Blueprint $table) {
16+
$table->foreignIdFor(\Lomkit\Rest\Tests\Support\Models\Model::class)->nullable()->constrained();
17+
});
18+
}
19+
};

Diff for: tests/Support/Models/BelongsToManyRelation.php

+5
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,9 @@ public function models()
1010
{
1111
return $this->belongsToMany(\Lomkit\Rest\Tests\Support\Models\Model::class);
1212
}
13+
14+
public function model()
15+
{
16+
return $this->belongsTo(Model::class);
17+
}
1318
}

Diff for: tests/Support/Models/Model.php

+7
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ public function belongsToRelation()
2525
return $this->belongsTo(BelongsToRelation::class);
2626
}
2727

28+
public function belongsToManyQueryChangesRelation()
29+
{
30+
return $this->belongsToMany(BelongsToManyRelation::class)
31+
->as('belongs_to_many_pivot')
32+
->withPivot('created_at', 'updated_at', 'number');
33+
}
34+
2835
public function hasOneThroughRelation()
2936
{
3037
return $this->hasOneThrough(HasOneThroughRelation::class, HasOneRelation::class);

Diff for: tests/Support/Rest/Resources/BelongsToManyResource.php

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Lomkit\Rest\Concerns\Resource\DisableGates;
66
use Lomkit\Rest\Http\Requests\RestRequest;
77
use Lomkit\Rest\Http\Resource;
8+
use Lomkit\Rest\Relations\BelongsTo;
89
use Lomkit\Rest\Tests\Support\Models\BelongsToManyRelation;
910

1011
class BelongsToManyResource extends Resource
@@ -15,7 +16,9 @@ class BelongsToManyResource extends Resource
1516

1617
public function relations(RestRequest $request): array
1718
{
18-
return [];
19+
return [
20+
BelongsTo::make('model', ModelQueryChangedResource::class),
21+
];
1922
}
2023

2124
public function fields(RestRequest $request): array
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace Lomkit\Rest\Tests\Support\Rest\Resources;
4+
5+
class ModelQueryChangedResource extends ModelResource
6+
{
7+
public function searchQuery(\Lomkit\Rest\Http\Requests\RestRequest $request, \Illuminate\Contracts\Database\Eloquent\Builder $query)
8+
{
9+
$query = parent::searchQuery($request, $query);
10+
11+
$query->where('number', 10000);
12+
13+
return $query;
14+
}
15+
}

0 commit comments

Comments
 (0)