Skip to content

Commit a02414e

Browse files
committed
Merge branch 'main' into feature/get-list-newest-authors-#28
# Conflicts: # routes/blog-api.php
2 parents 66175de + 572954d commit a02414e

File tree

7 files changed

+198
-9
lines changed

7 files changed

+198
-9
lines changed

Diff for: phpstan-baseline.neon

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ parameters:
1212
- message: '#Cannot cast mixed to string#'
1313
path: '*'
1414

15+
- message: '#Cannot cast mixed to int#'
16+
path: '*'
17+
1518
- message: '#Method CSlant\\Blog\\Api\\Services\\SlugService::getSlugModel\(\) has no return type specified#'
1619
path: src/Services/SlugService.php
1720

Diff for: routes/blog-api.php

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
<?php
22

33
use CSlant\Blog\Api\Http\Actions\Author\AuthorGetListAction;
4-
use CSlant\Blog\Api\Http\Actions\Author\AuthorAction;
5-
use CSlant\Blog\Api\Http\Actions\Post\ViewCountAction;
4+
use CSlant\Blog\Api\Http\Actions\Post\PostGetByTagsAction;
5+
use CSlant\Blog\Api\Http\Actions\Author\AuthorGetProfileAction;
6+
use CSlant\Blog\Api\Http\Actions\Post\PostGetViewCountAction;
67
use CSlant\Blog\Api\Http\Controllers\CategoryController;
78
use CSlant\Blog\Api\Http\Controllers\MetaBoxController;
89
use CSlant\Blog\Api\Http\Controllers\PostController;
@@ -29,14 +30,15 @@
2930

3031
Route::group(['prefix' => 'authors'], function () {
3132
Route::get('/', AuthorGetListAction::class);
32-
Route::get('/{authorId}', AuthorAction::class);
33+
Route::get('/{authorId}', AuthorGetProfileAction::class);
3334
});
3435

3536
Route::group(['prefix' => 'posts'], function () {
3637
Route::get('/', [PostController::class, 'index']);
3738
Route::get('filters', [PostController::class, 'getFilters']);
39+
Route::get('get-by-tags', PostGetByTagsAction::class);
3840
Route::get('{slug}', [PostController::class, 'findBySlug']);
39-
Route::get('{slug}/view-count', ViewCountAction::class);
41+
Route::get('{slug}/view-count', PostGetViewCountAction::class);
4042
});
4143

4244
Route::group(['prefix' => 'categories'], function () {

Diff for: src/Http/Actions/Author/AuthorAction.php renamed to src/Http/Actions/Author/AuthorGetProfileAction.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
* @method BaseHttpResponse setData(mixed $data)
3131
* @method BaseHttpResponse|JsonResource|JsonResponse|RedirectResponse toApiResponse()
3232
*/
33-
class AuthorAction extends Action
33+
class AuthorGetProfileAction extends Action
3434
{
3535
/**
3636
* @param int $authorId

Diff for: src/Http/Actions/Post/PostGetByTagsAction.php

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
<?php
2+
3+
namespace CSlant\Blog\Api\Http\Actions\Post;
4+
5+
use Botble\Base\Http\Responses\BaseHttpResponse;
6+
use CSlant\Blog\Api\Http\Resources\Post\ListPostResource;
7+
use CSlant\Blog\Api\OpenApi\Schemas\Resources\Post\PostListResourceSchema;
8+
use CSlant\Blog\Api\Services\PostService;
9+
use CSlant\Blog\Core\Http\Actions\Action;
10+
use CSlant\Blog\Core\Supports\Base\FilterPost;
11+
use Illuminate\Http\JsonResponse;
12+
use Illuminate\Http\RedirectResponse;
13+
use Illuminate\Http\Request;
14+
use Illuminate\Http\Resources\Json\JsonResource;
15+
use OpenApi\Attributes\Get;
16+
use OpenApi\Attributes\Items;
17+
use OpenApi\Attributes\JsonContent;
18+
use OpenApi\Attributes\Parameter;
19+
use OpenApi\Attributes\Property;
20+
use OpenApi\Attributes\Response;
21+
use OpenApi\Attributes\Schema;
22+
23+
/**
24+
* Class GetByTagsAction
25+
*
26+
* @group Blog API
27+
*
28+
* @authenticated
29+
*
30+
* @method BaseHttpResponse httpResponse()
31+
* @method BaseHttpResponse setData(mixed $data)
32+
* @method BaseHttpResponse|JsonResource|JsonResponse|RedirectResponse toApiResponse()
33+
*/
34+
class PostGetByTagsAction extends Action
35+
{
36+
protected PostService $postService;
37+
38+
public function __construct(PostService $postService)
39+
{
40+
$this->postService = $postService;
41+
}
42+
43+
/**
44+
* @param Request $request
45+
*
46+
* @group Blog
47+
*
48+
* @queryParam Find by list tag id of post.
49+
*
50+
* @return BaseHttpResponse|JsonResource|JsonResponse|RedirectResponse
51+
*/
52+
#[
53+
Get(
54+
path: "/posts/get-by-tags",
55+
operationId: "postGetByTag",
56+
description: "Get list post of the tag by tag id
57+
58+
This API will get record from the database and return list post of the tag by tag id.
59+
",
60+
summary: "Get list post of the tag by tag id",
61+
tags: ["Post"],
62+
parameters: [
63+
new Parameter(
64+
name: 'tags',
65+
description: 'Filter posts by tag specific tag IDs.',
66+
in: 'query',
67+
required: false,
68+
schema: new Schema(
69+
type: 'array',
70+
items: new Items(description: 'Input the exclude tag ID', type: 'integer'),
71+
default: null
72+
)
73+
),
74+
new Parameter(
75+
name: 'per_page',
76+
description: 'Number of items per page',
77+
in: 'query',
78+
required: false,
79+
schema: new Schema(type: 'integer', default: 10)
80+
),
81+
new Parameter(
82+
name: 'page',
83+
description: 'Page number',
84+
in: 'query',
85+
required: false,
86+
schema: new Schema(type: 'integer', default: 1)
87+
),
88+
],
89+
responses: [
90+
new Response(
91+
response: 200,
92+
description: "Get list posts by tag successfully",
93+
content: new JsonContent(
94+
properties: [
95+
new Property(
96+
property: 'error',
97+
description: 'Error status',
98+
type: 'boolean',
99+
default: false
100+
),
101+
new Property(
102+
property: "data",
103+
ref: PostListResourceSchema::class,
104+
description: "Data of model",
105+
type: "object",
106+
),
107+
]
108+
)
109+
),
110+
new Response(
111+
ref: \CSlant\Blog\Api\OpenApi\Responses\Errors\BadRequestResponseSchema::class,
112+
response: 400,
113+
),
114+
new Response(
115+
ref: \CSlant\Blog\Api\OpenApi\Responses\Errors\ErrorNotFoundResponseSchema::class,
116+
response: 404,
117+
),
118+
new Response(
119+
ref: \CSlant\Blog\Api\OpenApi\Responses\Errors\InternalServerResponseSchema::class,
120+
response: 500,
121+
),
122+
]
123+
)
124+
]
125+
public function __invoke(Request $request): BaseHttpResponse|JsonResponse|JsonResource|RedirectResponse
126+
{
127+
$filters = FilterPost::setFilters($request->input());
128+
129+
$data = $this->postService->getPostByTags((array) $filters);
130+
131+
return $this
132+
->httpResponse()
133+
->setData(ListPostResource::collection($data))
134+
->toApiResponse();
135+
}
136+
}

Diff for: src/Http/Actions/Post/ViewCountAction.php renamed to src/Http/Actions/Post/PostGetViewCountAction.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@
3333
* @method BaseHttpResponse setData(mixed $data)
3434
* @method BaseHttpResponse|JsonResource|JsonResponse|RedirectResponse toApiResponse()
3535
*/
36-
class ViewCountAction extends Action
36+
class PostGetViewCountAction extends Action
3737
{
3838
/**
3939
* @param string $slug
4040
*
4141
* @group Blog
42-
* @queryParam slug Find by slug of post.
42+
* @queryParam Find by slug of post.
4343
* @return BaseHttpResponse|JsonResource|JsonResponse|RedirectResponse
4444
*/
4545
#[

Diff for: src/Http/Resources/Author/AuthorWithPostResource.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ public function toArray($request): array
2020
{
2121
/** @var User $this */
2222
$posts = $this->posts()
23-
->orderBy($request->get('order_by', 'created_at'), $request->get('order', 'DESC'))
24-
->paginate($request->get('per_page', 10));
23+
->orderBy((string) $request->get('order_by', 'created_at'), (string) $request->get('order', 'DESC'))
24+
->paginate($request->integer('per_page', 10));
2525

2626
return [
2727
'id' => $this->id,

Diff for: src/Services/PostService.php

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
namespace CSlant\Blog\Api\Services;
4+
5+
use CSlant\Blog\Core\Http\Responses\Base\BaseHttpResponse;
6+
use CSlant\Blog\Core\Models\Post;
7+
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
8+
use Illuminate\Database\Eloquent\Builder;
9+
use Illuminate\Support\Arr;
10+
11+
/**
12+
* Class PostService
13+
*
14+
* @package CSlant\Blog\Api\Services
15+
*
16+
* @method BaseHttpResponse httpResponse()
17+
*/
18+
class PostService
19+
{
20+
/**
21+
* Get posts by tags.
22+
*
23+
* @param array<string, mixed> $filters
24+
*
25+
* @return LengthAwarePaginator<Post>
26+
*/
27+
public function getPostByTags(array $filters): LengthAwarePaginator
28+
{
29+
$data = Post::query();
30+
31+
if ($filters['tags'] !== null) {
32+
$tags = array_filter((array) $filters['tags']);
33+
34+
$data = $data->whereHas('tags', function (Builder $query) use ($tags): void {
35+
$query->whereIn('tags.id', $tags);
36+
});
37+
}
38+
39+
$orderBy = Arr::get($filters, 'order_by', 'updated_at');
40+
$order = Arr::get($filters, 'order', 'desc');
41+
42+
$data = $data
43+
->wherePublished()
44+
->orderBy($orderBy, $order);
45+
46+
return $data->paginate((int) $filters['per_page']);
47+
}
48+
}

0 commit comments

Comments
 (0)