2021-11-14 11:28:01 -05:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace BookStack\Http\Controllers\Api;
|
|
|
|
|
|
|
|
use BookStack\Entities\Models\Entity;
|
|
|
|
use BookStack\Entities\Tools\SearchOptions;
|
2021-12-06 15:42:04 -05:00
|
|
|
use BookStack\Entities\Tools\SearchResultsFormatter;
|
2021-11-14 11:28:01 -05:00
|
|
|
use BookStack\Entities\Tools\SearchRunner;
|
|
|
|
use Illuminate\Http\Request;
|
|
|
|
|
|
|
|
class SearchApiController extends ApiController
|
|
|
|
{
|
|
|
|
protected $searchRunner;
|
2021-12-06 15:42:04 -05:00
|
|
|
protected $resultsFormatter;
|
2021-11-14 11:28:01 -05:00
|
|
|
|
|
|
|
protected $rules = [
|
|
|
|
'all' => [
|
2021-11-15 06:17:27 -05:00
|
|
|
'query' => ['required'],
|
|
|
|
'page' => ['integer', 'min:1'],
|
2021-11-14 11:28:01 -05:00
|
|
|
'count' => ['integer', 'min:1', 'max:100'],
|
|
|
|
],
|
|
|
|
];
|
|
|
|
|
2021-12-06 15:42:04 -05:00
|
|
|
public function __construct(SearchRunner $searchRunner, SearchResultsFormatter $resultsFormatter)
|
2021-11-14 11:28:01 -05:00
|
|
|
{
|
|
|
|
$this->searchRunner = $searchRunner;
|
2021-12-06 15:42:04 -05:00
|
|
|
$this->resultsFormatter = $resultsFormatter;
|
2021-11-14 11:28:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Run a search query against all main content types (shelves, books, chapters & pages)
|
|
|
|
* in the system. Takes the same input as the main search bar within the BookStack
|
|
|
|
* interface as a 'query' parameter. See https://www.bookstackapp.com/docs/user/searching/
|
|
|
|
* for a full list of search term options. Results contain a 'type' property to distinguish
|
|
|
|
* between: bookshelf, book, chapter & page.
|
|
|
|
*
|
|
|
|
* The paging parameters and response format emulates a standard listing endpoint
|
|
|
|
* but standard sorting and filtering cannot be done on this endpoint. If a count value
|
|
|
|
* is provided this will only be taken as a suggestion. The results in the response
|
|
|
|
* may currently be up to 4x this value.
|
|
|
|
*/
|
|
|
|
public function all(Request $request)
|
|
|
|
{
|
|
|
|
$this->validate($request, $this->rules['all']);
|
|
|
|
|
|
|
|
$options = SearchOptions::fromString($request->get('query') ?? '');
|
|
|
|
$page = intval($request->get('page', '0')) ?: 1;
|
|
|
|
$count = min(intval($request->get('count', '0')) ?: 20, 100);
|
|
|
|
|
|
|
|
$results = $this->searchRunner->searchEntities($options, 'all', $page, $count);
|
2021-12-06 15:42:04 -05:00
|
|
|
$this->resultsFormatter->format($results['results']->all(), $options);
|
2021-11-14 11:28:01 -05:00
|
|
|
|
|
|
|
/** @var Entity $result */
|
|
|
|
foreach ($results['results'] as $result) {
|
|
|
|
$result->setVisible([
|
|
|
|
'id', 'name', 'slug', 'book_id',
|
|
|
|
'chapter_id', 'draft', 'template',
|
|
|
|
'created_at', 'updated_at',
|
2021-12-06 15:42:04 -05:00
|
|
|
'tags', 'type', 'preview_html', 'url',
|
2021-11-14 11:28:01 -05:00
|
|
|
]);
|
|
|
|
$result->setAttribute('type', $result->getType());
|
2021-12-06 15:42:04 -05:00
|
|
|
$result->setAttribute('url', $result->getUrl());
|
|
|
|
$result->setAttribute('preview_html', [
|
|
|
|
'name' => (string) $result->getAttribute('preview_name'),
|
|
|
|
'content' => (string) $result->getAttribute('preview_content'),
|
|
|
|
]);
|
2021-11-14 11:28:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return response()->json([
|
2021-11-15 06:17:27 -05:00
|
|
|
'data' => $results['results'],
|
2021-11-14 11:28:01 -05:00
|
|
|
'total' => $results['total'],
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
}
|