Skip to content

Commit f2b93f7

Browse files
authored
fix: prevent query builder from overwriting scopes upon applying filters
Merge pull request #257 from JonErickson/feature/prevent-overwriting-scopes
2 parents b69499a + 65dcff6 commit f2b93f7

File tree

3 files changed

+67
-3
lines changed

3 files changed

+67
-3
lines changed

src/Drivers/Standard/QueryBuilder.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ public function buildQuery($query, Request $request)
7272
$actionMethod = $request->route()->getActionMethod();
7373

7474
if (!$this->intermediateMode) {
75+
$this->applyIncludesToQuery($query, $request);
76+
$this->applyAggregatesToQuery($query, $request);
77+
7578
if (in_array($actionMethod, ['index', 'search', 'show'])) {
7679
if ($actionMethod === 'search') {
7780
$this->applyScopesToQuery($query, $request);
@@ -81,9 +84,6 @@ public function buildQuery($query, Request $request)
8184
}
8285
$this->applySoftDeletesToQuery($query, $request);
8386
}
84-
85-
$this->applyIncludesToQuery($query, $request);
86-
$this->applyAggregatesToQuery($query, $request);
8787
}
8888

8989
return $query;

tests/Fixtures/app/Models/Post.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,28 @@ public function scopePublished(Builder $query)
9494
return $query->where('publish_at', '<', Carbon::now());
9595
}
9696

97+
/**
98+
* @param Builder $query
99+
* @param string $dateTime
100+
* @return Builder|\Illuminate\Database\Query\Builder
101+
*/
97102
public function scopePublishedAt(Builder $query, string $dateTime)
98103
{
99104
return $query->where('publish_at', $dateTime);
100105
}
101106

107+
/**
108+
* @param Builder $query
109+
* @param string $direction
110+
* @return Builder|\Illuminate\Database\Query\Builder
111+
*/
112+
public function scopeOrderComments(Builder $query, string $direction = 'asc')
113+
{
114+
return $query->with(['comments' => function (MorphMany $query) use ($direction) {
115+
$query->orderBy('created_at', $direction);
116+
}]);
117+
}
118+
102119
/**
103120
* @param Builder $query
104121
* @return Builder|\Illuminate\Database\Query\Builder

tests/Unit/Drivers/Standard/QueryBuilderTest.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
namespace Orion\Tests\Unit\Drivers\Standard;
44

5+
use Carbon\Carbon;
56
use Illuminate\Routing\Route;
67
use Mockery;
78
use Orion\Drivers\Standard\ParamsValidator;
89
use Orion\Drivers\Standard\QueryBuilder;
910
use Orion\Drivers\Standard\RelationsResolver;
1011
use Orion\Drivers\Standard\SearchBuilder;
1112
use Orion\Http\Requests\Request;
13+
use Orion\Tests\Fixtures\App\Models\Comment;
1214
use Orion\Tests\Fixtures\App\Models\Post;
1315
use Orion\Tests\Fixtures\App\Models\Team;
1416
use Orion\Tests\Fixtures\App\Models\User;
@@ -127,6 +129,51 @@ function () {
127129
$this->assertSame($postA->id, $posts->first()->id);
128130
}
129131

132+
/** @test */
133+
public function include_relations_do_not_overwrite_scopes_with_same_relations(): void
134+
{
135+
$request = new Request(['include' => 'comments']);
136+
$request->setRouteResolver(
137+
function () {
138+
return new Route('POST', '/api/posts/search', [ControllerStub::class, 'search']);
139+
}
140+
);
141+
$request->query->set(
142+
'scopes',
143+
[
144+
['name' => 'orderComments', 'parameters' => ['asc']],
145+
]
146+
);
147+
148+
$post = factory(Post::class)->create();
149+
150+
$commentA = factory(Comment::class)->make(['created_at' => Carbon::parse('2019-01-01 09:35:14')]);
151+
$commentA->commentable()->associate($post);
152+
$commentA->save();
153+
154+
$commentB = factory(Comment::class)->make(['created_at' => Carbon::parse('2018-01-01 09:35:14')]);
155+
$commentB->commentable()->associate($post);
156+
$commentB->save();
157+
158+
$query = Post::query();
159+
160+
$queryBuilder = new QueryBuilder(
161+
Post::class,
162+
new ParamsValidator(['orderComments'], [], [], [], ['comments']),
163+
new RelationsResolver(['comments'], []),
164+
new SearchBuilder([])
165+
);
166+
$queryBuilder->buildQuery($query, $request);
167+
168+
$posts = $query->get();
169+
170+
$dates = $posts->first()->comments->map(function(Comment $comment) {
171+
return $comment->created_at;
172+
});
173+
174+
$this->assertTrue(Carbon::parse($dates->first())->isBefore(Carbon::parse($dates->last())));
175+
}
176+
130177
/** @test */
131178
public function applying_model_level_fields_filters_with_singular_values(): void
132179
{

0 commit comments

Comments
 (0)