Skip to content

Commit 9a4ea95

Browse files
committed
Merge branch 'feat/navigation-blog-api' into 'main'
Feat/navigation blog api See merge request cslant/inhouse/blog/blog-api-package!99
2 parents e8b4c6a + 1c9f35b commit 9a4ea95

File tree

4 files changed

+165
-0
lines changed

4 files changed

+165
-0
lines changed

routes/blog-api.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use CSlant\Blog\Api\Http\Actions\Post\PostGetCustomFiltersAction;
55
use CSlant\Blog\Api\Http\Actions\Author\AuthorGetProfileAction;
66
use CSlant\Blog\Api\Http\Actions\Post\PostGetViewCountAction;
7+
use CSlant\Blog\Api\Http\Actions\Post\PostGetNavigateAction;
78
use CSlant\Blog\Api\Http\Actions\Tag\TagGetFiltersAction;
89
use CSlant\Blog\Api\Http\Controllers\CategoryController;
910
use CSlant\Blog\Api\Http\Controllers\MetaBoxController;
@@ -41,6 +42,7 @@
4142
Route::get('custom-filters', PostGetCustomFiltersAction::class);
4243
Route::get('{slug}', [PostController::class, 'findBySlug']);
4344
Route::get('{slug}/view-count', PostGetViewCountAction::class);
45+
Route::get('{slug}/navigate', PostGetNavigateAction::class);
4446
Route::post('{id}/increment-views', PostStoreViewCountAction::class)
4547
->middleware('api-action-rate-limiter:post-views');
4648
});
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php
2+
3+
namespace CSlant\Blog\Api\Http\Actions\Post;
4+
5+
use Botble\Blog\Repositories\Interfaces\PostInterface;
6+
use CSlant\Blog\Api\Http\Resources\Post\PostNavigateResource;
7+
use CSlant\Blog\Core\Facades\Base\SlugHelper;
8+
use CSlant\Blog\Core\Http\Responses\Base\BaseHttpResponse;
9+
use CSlant\Blog\Core\Models\Post;
10+
use CSlant\Blog\Core\Models\Slug;
11+
use Illuminate\Http\JsonResponse;
12+
use Illuminate\Http\RedirectResponse;
13+
use Illuminate\Http\Resources\Json\JsonResource;
14+
use OpenApi\Attributes\Get;
15+
use OpenApi\Attributes\Parameter;
16+
use OpenApi\Attributes\Response;
17+
use OpenApi\Attributes\Schema;
18+
19+
/**
20+
* Class PostGetNavigateAction
21+
*
22+
* @package CSlant\Blog\Api\Http\Actions\Post
23+
*
24+
* @method BaseHttpResponse httpResponse()
25+
* @method BaseHttpResponse setData(mixed $data)
26+
* @method BaseHttpResponse|JsonResource|JsonResponse|RedirectResponse toApiResponse()
27+
*/
28+
class PostGetNavigateAction
29+
{
30+
public function __construct(
31+
protected PostInterface $postRepository
32+
) {
33+
}
34+
35+
/**
36+
* @group Blog API
37+
*
38+
* @param string $slug
39+
*
40+
* @return BaseHttpResponse|JsonResource|JsonResponse|RedirectResponse
41+
*/
42+
#[
43+
Get(
44+
path: "/posts/{slug}/navigate",
45+
operationId: "postGetNavigate",
46+
description: "Get the previous and next posts by slug
47+
This API will return both previous and next posts for navigation purposes.
48+
",
49+
summary: "Get previous and next posts for navigation",
50+
tags: ["Post"],
51+
parameters: [
52+
new Parameter(
53+
name: 'slug',
54+
description: 'Post slug',
55+
in: 'path',
56+
required: true,
57+
schema: new Schema(type: 'string')
58+
),
59+
],
60+
responses: [
61+
new Response(
62+
response: 200,
63+
description: 'Navigation posts retrieved successfully',
64+
),
65+
new Response(
66+
response: 404,
67+
description: 'Post not found',
68+
),
69+
]
70+
)
71+
]
72+
public function __invoke(string $slug): BaseHttpResponse|JsonResponse|JsonResource|RedirectResponse
73+
{
74+
/** @var Slug $slug */
75+
$slug = SlugHelper::getSlug($slug, SlugHelper::getPrefix(Post::getBaseModel()));
76+
77+
if (!$slug) {
78+
return $this
79+
->httpResponse()
80+
->setError()
81+
->setCode(404)
82+
->setMessage('Post not found');
83+
}
84+
85+
$navigationPosts = $this->postRepository->getNavigatePosts($slug->reference_id);
86+
87+
return $this
88+
->httpResponse()
89+
->setData(new PostNavigateResource($navigationPosts))
90+
->toApiResponse();
91+
}
92+
93+
/**
94+
* @return BaseHttpResponse
95+
*/
96+
protected function httpResponse(): BaseHttpResponse
97+
{
98+
return new BaseHttpResponse;
99+
}
100+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace CSlant\Blog\Api\Http\Resources\Post;
4+
5+
use Illuminate\Http\Request;
6+
use Illuminate\Http\Resources\Json\JsonResource;
7+
8+
/**
9+
* Post Navigate Resource for combined previous/next response
10+
*/
11+
class PostNavigateResource extends JsonResource
12+
{
13+
/**
14+
* @param Request $request
15+
*
16+
* @return array<string, mixed>
17+
*/
18+
public function toArray($request): array
19+
{
20+
return [
21+
'previous' => $this->resource['previous'] ? new PostNavigationResource($this->resource['previous']) : null,
22+
'next' => $this->resource['next'] ? new PostNavigationResource($this->resource['next']) : null,
23+
];
24+
}
25+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
namespace CSlant\Blog\Api\Http\Resources\Post;
4+
5+
use CSlant\Blog\Core\Facades\Base\Media\RvMedia;
6+
use CSlant\Blog\Core\Models\Post;
7+
use Illuminate\Http\Request;
8+
use Illuminate\Http\Resources\Json\JsonResource;
9+
10+
/**
11+
* Post Navigation Resource for previous/next navigation
12+
*/
13+
class PostNavigationResource extends JsonResource
14+
{
15+
/**
16+
* @param Request $request
17+
*
18+
* @return array<string, mixed>
19+
*/
20+
public function toArray($request): array
21+
{
22+
if (!$this->resource) {
23+
return [];
24+
}
25+
26+
/** @var Post $this */
27+
return [
28+
'id' => $this->id,
29+
'name' => $this->name,
30+
'description' => $this->description,
31+
'slug' => $this->slug,
32+
'url' => $this->url,
33+
'image' => $this->image ? RvMedia::getImageUrl($this->image) : null,
34+
'created_at' => $this->created_at,
35+
'updated_at' => $this->updated_at,
36+
];
37+
}
38+
}

0 commit comments

Comments
 (0)