Skip to content

Commit 526b214

Browse files
authored
Fix resource pagination (#470)
1 parent 4b8a3fc commit 526b214

File tree

11 files changed

+200
-26
lines changed

11 files changed

+200
-26
lines changed

src/Generators/ControllerGenerator.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,20 @@ protected function buildMethods(Controller $controller)
142142
$method = str_replace('* @return \\Illuminate\\Http\\Response', '* @return \\' . $fqcn, $method);
143143
$this->addImport($controller, $fqcn);
144144
$body .= self::INDENT . $statement->output() . PHP_EOL;
145+
146+
if ($statement->paginate()) {
147+
if (! Str::contains($body, '::all();')) {
148+
$queryStatement = new QueryStatement('all', [$statement->reference()]);
149+
$body = implode(PHP_EOL, [
150+
self::INDENT . $queryStatement->output($statement->reference()),
151+
PHP_EOL . $body
152+
]);
153+
154+
$this->addImport($controller, $this->determineModel($controller, $queryStatement->model()));
155+
}
156+
157+
$body = str_replace('::all();', '::paginate();', $body);
158+
}
145159
} elseif ($statement instanceof RedirectStatement) {
146160
$body .= self::INDENT . $statement->output() . PHP_EOL;
147161
} elseif ($statement instanceof RespondStatement) {

src/Models/Statements/QueryStatement.php

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,7 @@ public function __construct(string $operation, array $clauses = [])
2626
$this->operation = $operation;
2727
$this->clauses = $clauses;
2828

29-
if ($operation === 'all' && !empty($clauses)) {
30-
$this->model = Str::studly(Str::singular($clauses[0]));
31-
}
29+
$this->determineModel($this->model);
3230
}
3331

3432
public function operation(): string
@@ -51,11 +49,11 @@ public function output(string $controller): string
5149
$model = $this->determineModel($controller);
5250

5351
if ($this->operation() === 'all') {
54-
if (is_null($this->model())) {
55-
return '$' . Str::camel(Str::plural($model)) . ' = ' . $model . '::all();';
56-
} else {
57-
return '$' . Str::camel($this->clauses()[0]) . ' = ' . $this->model() . '::all();';
58-
}
52+
return '$' . Str::camel(Str::plural($model)) . ' = ' . $model . '::all();';
53+
}
54+
55+
if ($this->operation() === 'paginate') {
56+
return '$' . Str::camel(Str::plural($model)) . ' = ' . $model . '::paginate();';
5957
}
6058

6159
$methods = [];
@@ -117,15 +115,23 @@ private function pluckName(string $field)
117115
return Str::lower(Str::plural(str_replace('.', '_', $field)));
118116
}
119117

120-
return Str::lower('Post' . '_' . Str::plural($field));
118+
return Str::lower($this->model . '_' . Str::plural($field));
121119
}
122120

123-
private function determineModel(string $prefix)
121+
private function determineModel(?string $controller)
124122
{
125-
if (empty($this->model())) {
126-
return Str::studly(Str::singular($prefix));
123+
if (! is_null($controller) && ! empty($controller)) {
124+
$this->model = Str::studly(Str::singular($controller));
125+
}
126+
127+
if (
128+
is_null($this->model()) &&
129+
! empty($this->clauses()) &&
130+
! in_array($this->operation(), ['count','exists'])
131+
) {
132+
$this->model = Str::studly(Str::singular(Str::before(Str::after($this->clauses()[0], ':'), '.')));
127133
}
128134

129-
return Str::studly($this->model());
135+
return $this->model();
130136
}
131137
}

src/Models/Statements/ResourceStatement.php

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,6 @@ public function paginate(): bool
5454

5555
public function output(): string
5656
{
57-
$code = 'return new ' . $this->name();
58-
$code .= '($' . $this->reference();
59-
60-
if ($this->paginate()) {
61-
$code .= '->paginate()';
62-
}
63-
64-
$code .= ');';
65-
66-
return $code;
57+
return sprintf('return new %s($%s);', $this->name(), $this->reference());
6758
}
6859
}

tests/Feature/Generators/ControllerGeneratorTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ public function controllerTreeDataProvider()
208208
['drafts/respond-statements.yaml', 'app/Http/Controllers/Api/PostController.php', 'controllers/respond-statements.php'],
209209
['drafts/resource-statements.yaml', 'app/Http/Controllers/UserController.php', 'controllers/resource-statements.php'],
210210
['drafts/save-without-validation.yaml', 'app/Http/Controllers/PostController.php', 'controllers/save-without-validation.php'],
211+
['drafts/api-resource-pagination.yaml', 'app/Http/Controllers/PostController.php', 'controllers/api-resource-pagination.php'],
211212
['drafts/api-routes-example.yaml', 'app/Http/Controllers/Api/CertificateController.php', 'controllers/api-routes-example.php'],
212213
['drafts/invokable-controller.yaml', 'app/Http/Controllers/ReportController.php', 'controllers/invokable-controller.php'],
213214
['drafts/invokable-controller-shorthand.yaml', 'app/Http/Controllers/ReportController.php', 'controllers/invokable-controller-shorthand.php'],

tests/Feature/Generators/Statements/ResourceGeneratorTest.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,40 @@ public function output_writes_namespaced_classes()
136136
'created' => ['app/Http/Resources/Api/CertificateCollection.php', 'app/Http/Resources/Api/CertificateResource.php'],
137137
], $this->subject->output($tree));
138138
}
139+
140+
/**
141+
* @test
142+
*/
143+
public function output_api_resource_pagination()
144+
{
145+
$this->files->expects('stub')
146+
->with('resource.stub')
147+
->andReturn(file_get_contents('stubs/resource.stub'));
148+
149+
$this->files->shouldReceive('exists')
150+
->with('app/Http/Resources')
151+
->andReturns(false, true);
152+
$this->files->expects('makeDirectory')
153+
->with('app/Http/Resources', 0755, true);
154+
155+
$this->files->expects('exists')
156+
->times(3)
157+
->with('app/Http/Resources/PostResource.php')
158+
->andReturns(false, true, true);
159+
$this->files->expects('put')
160+
->with('app/Http/Resources/PostResource.php', $this->fixture('resources/api-post-resource.php'));
161+
162+
$this->files->expects('exists')
163+
->with('app/Http/Resources/PostCollection.php')
164+
->andReturns(false);
165+
$this->files->expects('put')
166+
->with('app/Http/Resources/PostCollection.php', $this->fixture('resources/api-resource-pagination.php'));
167+
168+
$tokens = $this->blueprint->parse($this->fixture('drafts/api-resource-pagination.yaml'));
169+
$tree = $this->blueprint->analyze($tokens);
170+
171+
$this->assertEquals([
172+
'created' => ['app/Http/Resources/PostCollection.php', 'app/Http/Resources/PostResource.php'],
173+
], $this->subject->output($tree));
174+
}
139175
}

tests/Feature/Lexers/StatementLexerTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,7 @@ public function it_returns_a_query_get_statement()
589589

590590
$this->assertEquals('get', $actual[0]->operation());
591591
$this->assertSame(['where:post.title', 'order:post.created_at'], $actual[0]->clauses());
592-
$this->assertNull($actual[0]->model());
592+
$this->assertSame('Post', $actual[0]->model());
593593
}
594594

595595
/**
@@ -608,7 +608,7 @@ public function it_returns_a_query_pluck_statement()
608608

609609
$this->assertEquals('pluck', $actual[0]->operation());
610610
$this->assertSame(['order:post.created_at', 'pluck:id'], $actual[0]->clauses());
611-
$this->assertNull($actual[0]->model());
611+
$this->assertSame('Post', $actual[0]->model());
612612
}
613613

614614
/**
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
namespace App\Http\Controllers;
4+
5+
use App\Http\Requests\PostStoreRequest;
6+
use App\Http\Requests\PostUpdateRequest;
7+
use App\Http\Resources\PostCollection;
8+
use App\Http\Resources\PostResource;
9+
use App\Post;
10+
use Illuminate\Http\Request;
11+
12+
class PostController extends Controller
13+
{
14+
/**
15+
* @param \Illuminate\Http\Request $request
16+
* @return \App\Http\Resources\PostCollection
17+
*/
18+
public function index(Request $request)
19+
{
20+
$posts = Post::paginate();
21+
22+
return new PostCollection($posts);
23+
}
24+
25+
/**
26+
* @param \App\Http\Requests\PostStoreRequest $request
27+
* @return \App\Http\Resources\PostResource
28+
*/
29+
public function store(PostStoreRequest $request)
30+
{
31+
$post = Post::create($request->validated());
32+
33+
return new PostResource($post);
34+
}
35+
36+
/**
37+
* @param \Illuminate\Http\Request $request
38+
* @param \App\Post $post
39+
* @return \App\Http\Resources\PostResource
40+
*/
41+
public function show(Request $request, Post $post)
42+
{
43+
return new PostResource($post);
44+
}
45+
46+
/**
47+
* @param \App\Http\Requests\PostUpdateRequest $request
48+
* @param \App\Post $post
49+
* @return \App\Http\Resources\PostResource
50+
*/
51+
public function update(PostUpdateRequest $request, Post $post)
52+
{
53+
$post->update($request->validated());
54+
55+
return new PostResource($post);
56+
}
57+
58+
/**
59+
* @param \Illuminate\Http\Request $request
60+
* @param \App\Post $post
61+
* @return \Illuminate\Http\Response
62+
*/
63+
public function destroy(Request $request, Post $post)
64+
{
65+
$post->delete();
66+
67+
return response()->noContent();
68+
}
69+
}

tests/fixtures/controllers/resource-statements.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ class UserController extends Controller
1515
*/
1616
public function index(Request $request)
1717
{
18-
return new UserCollection($users->paginate());
18+
$users = User::paginate();
19+
20+
return new UserCollection($users);
1921
}
2022

2123
/**
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
models:
2+
Post:
3+
title: string
4+
body: text
5+
controllers:
6+
Post:
7+
resource: api
8+
index:
9+
query: all
10+
resource: 'paginate:posts'
11+
seeders: Post
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace App\Http\Resources;
4+
5+
use Illuminate\Http\Resources\Json\JsonResource;
6+
7+
class PostResource extends JsonResource
8+
{
9+
/**
10+
* Transform the resource into an array.
11+
*
12+
* @param \Illuminate\Http\Request $request
13+
* @return array
14+
*/
15+
public function toArray($request)
16+
{
17+
return [
18+
'id' => $this->id,
19+
'title' => $this->title,
20+
'body' => $this->body,
21+
];
22+
}
23+
}

0 commit comments

Comments
 (0)