Skip to content

Commit

Permalink
Merge branch 'rashadkhan359/development' into development
Browse files Browse the repository at this point in the history
  • Loading branch information
ssddanbrown committed Dec 3, 2024
2 parents 18ab38a + fec4445 commit 5164375
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 25 deletions.
36 changes: 34 additions & 2 deletions app/Api/ApiEntityListFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

namespace BookStack\Api;

use BookStack\Entities\Models\BookChild;
use BookStack\Entities\Models\Entity;
use BookStack\Entities\Models\Page;

class ApiEntityListFormatter
{
Expand All @@ -20,8 +22,16 @@ class ApiEntityListFormatter
* @var array<string|int, string|callable>
*/
protected array $fields = [
'id', 'name', 'slug', 'book_id', 'chapter_id', 'draft',
'template', 'priority', 'created_at', 'updated_at',
'id',
'name',
'slug',
'book_id',
'chapter_id',
'draft',
'template',
'priority',
'created_at',
'updated_at',
];

public function __construct(array $list)
Expand Down Expand Up @@ -62,6 +72,28 @@ public function withTags(): self
return $this;
}

/**
* Include parent book/chapter info in the formatted data.
*/
public function withParents(): self
{
$this->withField('book', function (Entity $entity) {
if ($entity instanceof BookChild && $entity->book) {
return $entity->book->only(['id', 'name', 'slug']);
}
return null;
});

$this->withField('chapter', function (Entity $entity) {
if ($entity instanceof Page && $entity->chapter) {
return $entity->chapter->only(['id', 'name', 'slug']);
}
return null;
});

return $this;
}

/**
* Format the data and return an array of formatted content.
* @return array[]
Expand Down
23 changes: 10 additions & 13 deletions app/Search/SearchApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,18 @@

class SearchApiController extends ApiController
{
protected SearchRunner $searchRunner;
protected SearchResultsFormatter $resultsFormatter;

protected $rules = [
'all' => [
'query' => ['required'],
'page' => ['integer', 'min:1'],
'count' => ['integer', 'min:1', 'max:100'],
'query' => ['required'],
'page' => ['integer', 'min:1'],
'count' => ['integer', 'min:1', 'max:100'],
],
];

public function __construct(SearchRunner $searchRunner, SearchResultsFormatter $resultsFormatter)
{
$this->searchRunner = $searchRunner;
$this->resultsFormatter = $resultsFormatter;
public function __construct(
protected SearchRunner $searchRunner,
protected SearchResultsFormatter $resultsFormatter
) {
}

/**
Expand All @@ -50,16 +47,16 @@ public function all(Request $request)
$this->resultsFormatter->format($results['results']->all(), $options);

$data = (new ApiEntityListFormatter($results['results']->all()))
->withType()->withTags()
->withType()->withTags()->withParents()
->withField('preview_html', function (Entity $entity) {
return [
'name' => (string) $entity->getAttribute('preview_name'),
'name' => (string) $entity->getAttribute('preview_name'),
'content' => (string) $entity->getAttribute('preview_content'),
];
})->format();

return response()->json([
'data' => $data,
'data' => $data,
'total' => $results['total'],
]);
}
Expand Down
2 changes: 1 addition & 1 deletion dev/api/requests/search-all.http
Original file line number Diff line number Diff line change
@@ -1 +1 @@
GET /api/search?query=cats+{created_by:me}&page=1&count=2
GET /api/search?query=cats+{created_by:me}&page=1&count=2
33 changes: 29 additions & 4 deletions dev/api/responses/search-all.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@
"created_at": "2021-11-14T15:57:35.000000Z",
"updated_at": "2021-11-14T15:57:35.000000Z",
"type": "chapter",
"url": "https://example.com/books/my-book/chapter/a-chapter-for-cats",
"url": "https://example.com/books/cats/chapter/a-chapter-for-cats",
"book": {
"id": 1,
"name": "Cats",
"slug": "cats"
},
"preview_html": {
"name": "A chapter for <strong>cats</strong>",
"content": "...once a bunch of <strong>cats</strong> named tony...behaviour of <strong>cats</strong> is unsuitable"
Expand All @@ -26,7 +31,17 @@
"created_at": "2021-05-15T16:28:10.000000Z",
"updated_at": "2021-11-14T15:56:49.000000Z",
"type": "page",
"url": "https://example.com/books/my-book/page/the-hows-and-whys-of-cats",
"url": "https://example.com/books/cats/page/the-hows-and-whys-of-cats",
"book": {
"id": 1,
"name": "Cats",
"slug": "cats"
},
"chapter": {
"id": 75,
"name": "A chapter for cats",
"slug": "a-chapter-for-cats"
},
"preview_html": {
"name": "The hows and whys of <strong>cats</strong>",
"content": "...people ask why <strong>cats</strong>? but there are...the reason that <strong>cats</strong> are fast are due to..."
Expand Down Expand Up @@ -55,7 +70,17 @@
"created_at": "2020-11-29T21:55:07.000000Z",
"updated_at": "2021-11-14T16:02:39.000000Z",
"type": "page",
"url": "https://example.com/books/my-book/page/how-advanced-are-cats",
"url": "https://example.com/books/big-cats/page/how-advanced-are-cats",
"book": {
"id": 13,
"name": "Big Cats",
"slug": "big-cats"
},
"chapter": {
"id": 73,
"name": "A chapter for bigger cats",
"slug": "a-chapter-for-bigger-cats"
},
"preview_html": {
"name": "How advanced are <strong>cats</strong>?",
"content": "<strong>cats</strong> are some of the most advanced animals in the world."
Expand All @@ -64,4 +89,4 @@
}
],
"total": 3
}
}
52 changes: 47 additions & 5 deletions tests/Api/SearchApiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class SearchApiTest extends TestCase
{
use TestsApi;

protected $baseEndpoint = '/api/search';
protected string $baseEndpoint = '/api/search';

public function test_all_endpoint_returns_search_filtered_results_with_query()
{
Expand Down Expand Up @@ -45,7 +45,7 @@ public function test_all_endpoint_returns_entity_url()
$resp = $this->actingAsApiAdmin()->getJson($this->baseEndpoint . '?query=superuniquevalue');
$resp->assertJsonFragment([
'type' => 'page',
'url' => $page->getUrl(),
'url' => $page->getUrl(),
]);
}

Expand All @@ -57,10 +57,10 @@ public function test_all_endpoint_returns_items_with_preview_html()

$resp = $this->actingAsApiAdmin()->getJson($this->baseEndpoint . '?query=superuniquevalue');
$resp->assertJsonFragment([
'type' => 'book',
'url' => $book->getUrl(),
'type' => 'book',
'url' => $book->getUrl(),
'preview_html' => [
'name' => 'name with <strong>superuniquevalue</strong> within',
'name' => 'name with <strong>superuniquevalue</strong> within',
'content' => 'Description with <strong>superuniquevalue</strong> within',
],
]);
Expand All @@ -74,4 +74,46 @@ public function test_all_endpoint_requires_query_parameter()
$resp = $this->actingAsApiEditor()->get($this->baseEndpoint . '?query=myqueryvalue');
$resp->assertOk();
}

public function test_all_endpoint_includes_parent_details_where_visible()
{
$page = $this->entities->pageWithinChapter();
$chapter = $page->chapter;
$book = $page->book;

$page->update(['name' => 'name with superextrauniquevalue within']);
$page->indexForSearch();

$editor = $this->users->editor();
$this->actingAsApiEditor();
$resp = $this->getJson($this->baseEndpoint . '?query=superextrauniquevalue');
$resp->assertJsonFragment([
'id' => $page->id,
'type' => 'page',
'book' => [
'id' => $book->id,
'name' => $book->name,
'slug' => $book->slug,
],
'chapter' => [
'id' => $chapter->id,
'name' => $chapter->name,
'slug' => $chapter->slug,
],
]);

$this->permissions->disableEntityInheritedPermissions($chapter);
$this->permissions->setEntityPermissions($page, ['view'], [$editor->roles()->first()]);

$resp = $this->getJson($this->baseEndpoint . '?query=superextrauniquevalue');
$resp->assertJsonPath('data.0.id', $page->id);
$resp->assertJsonPath('data.0.book.name', $book->name);
$resp->assertJsonMissingPath('data.0.chapter');

$this->permissions->disableEntityInheritedPermissions($book);

$resp = $this->getJson($this->baseEndpoint . '?query=superextrauniquevalue');
$resp->assertJsonPath('data.0.id', $page->id);
$resp->assertJsonMissingPath('data.0.book.name');
}
}

0 comments on commit 5164375

Please sign in to comment.