Added url and preview_html params to search API results
Allows easy direct linking and usage of the HTML preview content we show in the UI when viewing search results. Note: preview_html content is a rough representation only, it does not match exactly what was matched in the database-search-operation which finds the results. For #3096 and #3080
This commit is contained in:
parent
e6c8ecba9c
commit
b22dd3cb88
3 changed files with 58 additions and 2 deletions
|
@ -4,12 +4,14 @@ namespace BookStack\Http\Controllers\Api;
|
||||||
|
|
||||||
use BookStack\Entities\Models\Entity;
|
use BookStack\Entities\Models\Entity;
|
||||||
use BookStack\Entities\Tools\SearchOptions;
|
use BookStack\Entities\Tools\SearchOptions;
|
||||||
|
use BookStack\Entities\Tools\SearchResultsFormatter;
|
||||||
use BookStack\Entities\Tools\SearchRunner;
|
use BookStack\Entities\Tools\SearchRunner;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class SearchApiController extends ApiController
|
class SearchApiController extends ApiController
|
||||||
{
|
{
|
||||||
protected $searchRunner;
|
protected $searchRunner;
|
||||||
|
protected $resultsFormatter;
|
||||||
|
|
||||||
protected $rules = [
|
protected $rules = [
|
||||||
'all' => [
|
'all' => [
|
||||||
|
@ -19,9 +21,10 @@ class SearchApiController extends ApiController
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
public function __construct(SearchRunner $searchRunner)
|
public function __construct(SearchRunner $searchRunner, SearchResultsFormatter $resultsFormatter)
|
||||||
{
|
{
|
||||||
$this->searchRunner = $searchRunner;
|
$this->searchRunner = $searchRunner;
|
||||||
|
$this->resultsFormatter = $resultsFormatter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,6 +48,7 @@ class SearchApiController extends ApiController
|
||||||
$count = min(intval($request->get('count', '0')) ?: 20, 100);
|
$count = min(intval($request->get('count', '0')) ?: 20, 100);
|
||||||
|
|
||||||
$results = $this->searchRunner->searchEntities($options, 'all', $page, $count);
|
$results = $this->searchRunner->searchEntities($options, 'all', $page, $count);
|
||||||
|
$this->resultsFormatter->format($results['results']->all(), $options);
|
||||||
|
|
||||||
/** @var Entity $result */
|
/** @var Entity $result */
|
||||||
foreach ($results['results'] as $result) {
|
foreach ($results['results'] as $result) {
|
||||||
|
@ -52,9 +56,14 @@ class SearchApiController extends ApiController
|
||||||
'id', 'name', 'slug', 'book_id',
|
'id', 'name', 'slug', 'book_id',
|
||||||
'chapter_id', 'draft', 'template',
|
'chapter_id', 'draft', 'template',
|
||||||
'created_at', 'updated_at',
|
'created_at', 'updated_at',
|
||||||
'tags', 'type',
|
'tags', 'type', 'preview_html', 'url',
|
||||||
]);
|
]);
|
||||||
$result->setAttribute('type', $result->getType());
|
$result->setAttribute('type', $result->getType());
|
||||||
|
$result->setAttribute('url', $result->getUrl());
|
||||||
|
$result->setAttribute('preview_html', [
|
||||||
|
'name' => (string) $result->getAttribute('preview_name'),
|
||||||
|
'content' => (string) $result->getAttribute('preview_content'),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
|
|
|
@ -8,6 +8,11 @@
|
||||||
"created_at": "2021-11-14T15:57:35.000000Z",
|
"created_at": "2021-11-14T15:57:35.000000Z",
|
||||||
"updated_at": "2021-11-14T15:57:35.000000Z",
|
"updated_at": "2021-11-14T15:57:35.000000Z",
|
||||||
"type": "chapter",
|
"type": "chapter",
|
||||||
|
"url": "https://example.com/books/my-book/chapter/a-chapter-for-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"
|
||||||
|
},
|
||||||
"tags": []
|
"tags": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -21,6 +26,11 @@
|
||||||
"created_at": "2021-05-15T16:28:10.000000Z",
|
"created_at": "2021-05-15T16:28:10.000000Z",
|
||||||
"updated_at": "2021-11-14T15:56:49.000000Z",
|
"updated_at": "2021-11-14T15:56:49.000000Z",
|
||||||
"type": "page",
|
"type": "page",
|
||||||
|
"url": "https://example.com/books/my-book/page/the-hows-and-whys-of-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..."
|
||||||
|
},
|
||||||
"tags": [
|
"tags": [
|
||||||
{
|
{
|
||||||
"name": "Animal",
|
"name": "Animal",
|
||||||
|
@ -45,6 +55,11 @@
|
||||||
"created_at": "2020-11-29T21:55:07.000000Z",
|
"created_at": "2020-11-29T21:55:07.000000Z",
|
||||||
"updated_at": "2021-11-14T16:02:39.000000Z",
|
"updated_at": "2021-11-14T16:02:39.000000Z",
|
||||||
"type": "page",
|
"type": "page",
|
||||||
|
"url": "https://example.com/books/my-book/page/how-advanced-are-cats",
|
||||||
|
"preview_html": {
|
||||||
|
"name": "How advanced are <strong>cats</strong>?",
|
||||||
|
"content": "<strong>cats</strong> are some of the most advanced animals in the world."
|
||||||
|
},
|
||||||
"tags": []
|
"tags": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -36,6 +36,38 @@ class SearchApiTest extends TestCase
|
||||||
$resp->assertJsonFragment(['name' => $uniqueTerm, 'type' => 'bookshelf']);
|
$resp->assertJsonFragment(['name' => $uniqueTerm, 'type' => 'bookshelf']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function test_all_endpoint_returns_entity_url()
|
||||||
|
{
|
||||||
|
/** @var Page $page */
|
||||||
|
$page = Page::query()->first();
|
||||||
|
$page->update(['name' => 'name with superuniquevalue within']);
|
||||||
|
$page->indexForSearch();
|
||||||
|
|
||||||
|
$resp = $this->actingAsApiAdmin()->getJson($this->baseEndpoint . '?query=superuniquevalue');
|
||||||
|
$resp->assertJsonFragment([
|
||||||
|
'type' => 'page',
|
||||||
|
'url' => $page->getUrl(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_all_endpoint_returns_items_with_preview_html()
|
||||||
|
{
|
||||||
|
/** @var Book $book */
|
||||||
|
$book = Book::query()->first();
|
||||||
|
$book->update(['name' => 'name with superuniquevalue within', 'description' => 'Description with superuniquevalue within']);
|
||||||
|
$book->indexForSearch();
|
||||||
|
|
||||||
|
$resp = $this->actingAsApiAdmin()->getJson($this->baseEndpoint . '?query=superuniquevalue');
|
||||||
|
$resp->assertJsonFragment([
|
||||||
|
'type' => 'book',
|
||||||
|
'url' => $book->getUrl(),
|
||||||
|
'preview_html' => [
|
||||||
|
'name' => 'name with <strong>superuniquevalue</strong> within',
|
||||||
|
'content' => 'Description with <strong>superuniquevalue</strong> within',
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
public function test_all_endpoint_requires_query_parameter()
|
public function test_all_endpoint_requires_query_parameter()
|
||||||
{
|
{
|
||||||
$resp = $this->actingAsApiEditor()->get($this->baseEndpoint);
|
$resp = $this->actingAsApiEditor()->get($this->baseEndpoint);
|
||||||
|
|
Loading…
Reference in a new issue