Skip to content

Commit f606711

Browse files
committed
respective book and chapter structure added.
1 parent 90a8070 commit f606711

File tree

5 files changed

+103
-246
lines changed

5 files changed

+103
-246
lines changed

app/Api/ApiEntityListFormatter.php

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,6 @@ class ApiEntityListFormatter
1313
*/
1414
protected array $list = [];
1515

16-
/**
17-
* Whether to include related titles in the response.
18-
*/
19-
protected bool $includeRelatedTitles = false;
20-
2116
/**
2217
* The fields to show in the formatted data.
2318
* Can be a plain string array item for a direct model field (If existing on model).
@@ -79,20 +74,18 @@ public function withTags(): self
7974
/**
8075
* Enable the inclusion of related book and chapter titles in the response.
8176
*/
82-
public function withRelatedTitles(): self
77+
public function withRelatedData(): self
8378
{
84-
$this->includeRelatedTitles = true;
85-
86-
$this->withField('book_title', function (Entity $entity) {
79+
$this->withField('book', function (Entity $entity) {
8780
if (method_exists($entity, 'book')) {
88-
return $entity->book?->name;
81+
return $entity->book()->select(['id', 'name', 'slug'])->first();
8982
}
9083
return null;
9184
});
9285

93-
$this->withField('chapter_title', function (Entity $entity) {
86+
$this->withField('chapter', function (Entity $entity) {
9487
if ($entity instanceof Page && $entity->chapter_id) {
95-
return optional($entity->getAttribute('chapter'))->name;
88+
return $entity->chapter()->select(['id', 'name', 'slug'])->first();
9689
}
9790
return null;
9891
});
@@ -106,9 +99,7 @@ public function withRelatedTitles(): self
10699
*/
107100
public function format(): array
108101
{
109-
if ($this->includeRelatedTitles) {
110-
$this->loadRelatedTitles();
111-
}
102+
$this->loadRelatedData();
112103

113104
$results = [];
114105

@@ -122,7 +113,7 @@ public function format(): array
122113
/**
123114
* Eager load the related book and chapter data when needed.
124115
*/
125-
protected function loadRelatedTitles(): void
116+
protected function loadRelatedData(): void
126117
{
127118
$pages = collect($this->list)->filter(fn($item) => $item instanceof Page);
128119

app/Search/SearchApiController.php

Lines changed: 9 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,9 @@ class SearchApiController extends ApiController
1717
'query' => ['required'],
1818
'page' => ['integer', 'min:1'],
1919
'count' => ['integer', 'min:1', 'max:100'],
20-
'include' => ['string', 'regex:/^[a-zA-Z,]*$/'],
2120
],
2221
];
2322

24-
/**
25-
* Valid include parameters and their corresponding formatter methods.
26-
* These parameters allow for additional related data, like titles or tags,
27-
* to be included in the search results when requested via the API.
28-
*/
29-
protected const VALID_INCLUDES = [
30-
'titles' => 'withRelatedTitles',
31-
'tags' => 'withTags',
32-
];
33-
3423
public function __construct(SearchRunner $searchRunner, SearchResultsFormatter $resultsFormatter)
3524
{
3625
$this->searchRunner = $searchRunner;
@@ -44,13 +33,6 @@ public function __construct(SearchRunner $searchRunner, SearchResultsFormatter $
4433
* for a full list of search term options. Results contain a 'type' property to distinguish
4534
* between: bookshelf, book, chapter & page.
4635
*
47-
* This method now supports the 'include' parameter, which allows API clients to specify related
48-
* fields (such as titles or tags) that should be included in the search results.
49-
*
50-
* The 'include' parameter is a comma-separated string. For example, adding `include=titles,tags`
51-
* will include both titles and tags in the API response. If the parameter is not provided, only
52-
* basic entity data will be returned.
53-
*
5436
* The paging parameters and response format emulates a standard listing endpoint
5537
* but standard sorting and filtering cannot be done on this endpoint. If a count value
5638
* is provided this will only be taken as a suggestion. The results in the response
@@ -63,49 +45,22 @@ public function all(Request $request)
6345
$options = SearchOptions::fromString($request->get('query') ?? '');
6446
$page = intval($request->get('page', '0')) ?: 1;
6547
$count = min(intval($request->get('count', '0')) ?: 20, 100);
66-
$includes = $this->parseIncludes($request->get('include', ''));
6748

6849
$results = $this->searchRunner->searchEntities($options, 'all', $page, $count);
6950
$this->resultsFormatter->format($results['results']->all(), $options);
7051

71-
$formatter = new ApiEntityListFormatter($results['results']->all());
72-
$formatter->withType(); // Always include type as it's essential for search results
73-
74-
foreach ($includes as $include) {
75-
if (isset(self::VALID_INCLUDES[$include])) {
76-
$method = self::VALID_INCLUDES[$include];
77-
$formatter->$method();
78-
}
79-
}
80-
81-
$formatter->withField('preview_html', function (Entity $entity) {
82-
return [
83-
'name' => (string) $entity->getAttribute('preview_name'),
84-
'content' => (string) $entity->getAttribute('preview_content'),
85-
];
86-
});
52+
$data = (new ApiEntityListFormatter($results['results']->all()))
53+
->withType()->withTags()->withRelatedData()
54+
->withField('preview_html', function (Entity $entity) {
55+
return [
56+
'name' => (string) $entity->getAttribute('preview_name'),
57+
'content' => (string) $entity->getAttribute('preview_content'),
58+
];
59+
})->format();
8760

8861
return response()->json([
89-
'data' => $formatter->format(),
62+
'data' => $data,
9063
'total' => $results['total'],
9164
]);
9265
}
93-
94-
/**
95-
* Parse and validate the include parameter.
96-
*
97-
* @param string $includeString Comma-separated list of includes
98-
* @return array<string>
99-
*/
100-
protected function parseIncludes(string $includeString): array
101-
{
102-
if (empty($includeString)) {
103-
return [];
104-
}
105-
106-
return array_filter(
107-
explode(',', strtolower($includeString)),
108-
fn($include) => isset (self::VALID_INCLUDES[$include])
109-
);
110-
}
11166
}

dev/api/requests/search-all.http

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
GET /api/search?query=cats+{created_by:me}&page=1&count=2&include=titles,tags
1+
GET /api/search?query=cats+{created_by:me}&page=1&count=2

dev/api/responses/search-all.json

Lines changed: 86 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,92 @@
11
{
2-
"data": [
3-
{
4-
"id": 84,
5-
"book_id": 1,
6-
"slug": "a-chapter-for-cats",
7-
"name": "A chapter for cats",
8-
"created_at": "2021-11-14T15:57:35.000000Z",
9-
"updated_at": "2021-11-14T15:57:35.000000Z",
10-
"type": "chapter",
11-
"url": "https://example.com/books/my-book/chapter/a-chapter-for-cats",
12-
"book_title": "Cats",
13-
"preview_html": {
14-
"name": "A chapter for <strong>cats</strong>",
15-
"content": "...once a bunch of <strong>cats</strong> named tony...behaviour of <strong>cats</strong> is unsuitable"
16-
},
17-
"tags": []
18-
},
19-
{
20-
"name": "The hows and whys of cats",
21-
"id": 396,
22-
"slug": "the-hows-and-whys-of-cats",
23-
"book_id": 1,
24-
"chapter_id": 75,
25-
"draft": false,
26-
"template": false,
27-
"created_at": "2021-05-15T16:28:10.000000Z",
28-
"updated_at": "2021-11-14T15:56:49.000000Z",
29-
"type": "page",
30-
"url": "https://example.com/books/my-book/page/the-hows-and-whys-of-cats",
31-
"book_title": "Cats",
32-
"chapter_title": "A chapter for cats",
33-
"preview_html": {
34-
"name": "The hows and whys of <strong>cats</strong>",
35-
"content": "...people ask why <strong>cats</strong>? but there are...the reason that <strong>cats</strong> are fast are due to..."
36-
},
37-
"tags": [
2+
"data": [
383
{
39-
"name": "Animal",
40-
"value": "Cat",
41-
"order": 0
4+
"id": 84,
5+
"book_id": 1,
6+
"slug": "a-chapter-for-cats",
7+
"name": "A chapter for cats",
8+
"created_at": "2021-11-14T15:57:35.000000Z",
9+
"updated_at": "2021-11-14T15:57:35.000000Z",
10+
"type": "chapter",
11+
"url": "https://example.com/books/my-book/chapter/a-chapter-for-cats",
12+
"book": {
13+
"id": 1,
14+
"name": "Cats",
15+
"slug": "cats"
16+
},
17+
"preview_html": {
18+
"name": "A chapter for <strong>cats</strong>",
19+
"content": "...once a bunch of <strong>cats</strong> named tony...behaviour of <strong>cats</strong> is unsuitable"
20+
},
21+
"tags": []
4222
},
4323
{
44-
"name": "Category",
45-
"value": "Top Content",
46-
"order": 0
24+
"name": "The hows and whys of cats",
25+
"id": 396,
26+
"slug": "the-hows-and-whys-of-cats",
27+
"book_id": 1,
28+
"chapter_id": 75,
29+
"draft": false,
30+
"template": false,
31+
"created_at": "2021-05-15T16:28:10.000000Z",
32+
"updated_at": "2021-11-14T15:56:49.000000Z",
33+
"type": "page",
34+
"url": "https://example.com/books/my-book/page/the-hows-and-whys-of-cats",
35+
"book": {
36+
"id": 1,
37+
"name": "Cats",
38+
"slug": "cats"
39+
},
40+
"chapter": {
41+
"id": 84,
42+
"name": "A chapter for cats",
43+
"slug": "a-chapter-for-cats"
44+
},
45+
"preview_html": {
46+
"name": "The hows and whys of <strong>cats</strong>",
47+
"content": "...people ask why <strong>cats</strong>? but there are...the reason that <strong>cats</strong> are fast are due to..."
48+
},
49+
"tags": [
50+
{
51+
"name": "Animal",
52+
"value": "Cat",
53+
"order": 0
54+
},
55+
{
56+
"name": "Category",
57+
"value": "Top Content",
58+
"order": 0
59+
}
60+
]
61+
},
62+
{
63+
"name": "How advanced are cats?",
64+
"id": 362,
65+
"slug": "how-advanced-are-cats",
66+
"book_id": 13,
67+
"chapter_id": 73,
68+
"draft": false,
69+
"template": false,
70+
"created_at": "2020-11-29T21:55:07.000000Z",
71+
"updated_at": "2021-11-14T16:02:39.000000Z",
72+
"type": "page",
73+
"url": "https://example.com/books/my-book/page/how-advanced-are-cats",
74+
"book": {
75+
"id": 1,
76+
"name": "Cats",
77+
"slug": "cats"
78+
},
79+
"chapter": {
80+
"id": 84,
81+
"name": "A chapter for cats",
82+
"slug": "a-chapter-for-cats"
83+
},
84+
"preview_html": {
85+
"name": "How advanced are <strong>cats</strong>?",
86+
"content": "<strong>cats</strong> are some of the most advanced animals in the world."
87+
},
88+
"tags": []
4789
}
48-
]
49-
},
50-
{
51-
"name": "How advanced are cats?",
52-
"id": 362,
53-
"slug": "how-advanced-are-cats",
54-
"book_id": 13,
55-
"chapter_id": 73,
56-
"draft": false,
57-
"template": false,
58-
"created_at": "2020-11-29T21:55:07.000000Z",
59-
"updated_at": "2021-11-14T16:02:39.000000Z",
60-
"type": "page",
61-
"url": "https://example.com/books/my-book/page/how-advanced-are-cats",
62-
"book_title": "Cats",
63-
"chapter_title": "A chapter for cats",
64-
"preview_html": {
65-
"name": "How advanced are <strong>cats</strong>?",
66-
"content": "<strong>cats</strong> are some of the most advanced animals in the world."
67-
},
68-
"tags": []
69-
}
70-
],
71-
"total": 3
90+
],
91+
"total": 3
7292
}

0 commit comments

Comments
 (0)