]> BookStack Code Mirror - bookstack/blob - app/Search/SearchApiController.php
Copying: Fixed issue with non-page links to page permalinks
[bookstack] / app / Search / SearchApiController.php
1 <?php
2
3 declare(strict_types=1);
4
5 namespace BookStack\Search;
6
7 use BookStack\Api\ApiEntityListFormatter;
8 use BookStack\Entities\Models\Entity;
9 use BookStack\Http\ApiController;
10 use Illuminate\Http\JsonResponse;
11 use Illuminate\Http\Request;
12
13 class SearchApiController extends ApiController
14 {
15     protected array $rules = [
16         'all' => [
17             'query' => ['required'],
18             'page'  => ['integer', 'min:1'],
19             'count' => ['integer', 'min:1', 'max:100'],
20         ],
21     ];
22
23     public function __construct(
24         protected SearchRunner $searchRunner,
25         protected SearchResultsFormatter $resultsFormatter
26     ) {
27     }
28
29     /**
30      * Run a search query against all main content types (shelves, books, chapters & pages)
31      * in the system. Takes the same input as the main search bar within the BookStack
32      * interface as a 'query' parameter. See https://www.bookstackapp.com/docs/user/searching/
33      * for a full list of search term options. Results contain a 'type' property to distinguish
34      * between: bookshelf, book, chapter & page.
35      *
36      * The paging parameters and response format emulates a standard listing endpoint
37      * but standard sorting and filtering cannot be done on this endpoint.
38      */
39     public function all(Request $request): JsonResponse
40     {
41         $this->validate($request, $this->rules['all']);
42
43         $options = SearchOptions::fromString($request->get('query') ?? '');
44         $page = intval($request->get('page', '0')) ?: 1;
45         $count = min(intval($request->get('count', '0')) ?: 20, 100);
46
47         $results = $this->searchRunner->searchEntities($options, 'all', $page, $count);
48         $this->resultsFormatter->format($results['results']->all(), $options);
49
50         $data = (new ApiEntityListFormatter($results['results']->all()))
51             ->withType()->withTags()->withParents()
52             ->withField('preview_html', function (Entity $entity) {
53                 return [
54                     'name' => (string) $entity->getAttribute('preview_name'),
55                     'content' => (string) $entity->getAttribute('preview_content'),
56                 ];
57             })->format();
58
59         return response()->json([
60             'data' => $data,
61             'total' => $results['total'],
62         ]);
63     }
64 }