]> BookStack Code Mirror - bookstack/blob - app/Http/Controllers/Api/SearchApiController.php
Added "page_include_parse" theme event
[bookstack] / app / Http / Controllers / Api / SearchApiController.php
1 <?php
2
3 namespace BookStack\Http\Controllers\Api;
4
5 use BookStack\Entities\Models\Entity;
6 use BookStack\Search\SearchOptions;
7 use BookStack\Search\SearchResultsFormatter;
8 use BookStack\Search\SearchRunner;
9 use Illuminate\Http\Request;
10
11 class SearchApiController extends ApiController
12 {
13     protected $searchRunner;
14     protected $resultsFormatter;
15
16     protected $rules = [
17         'all' => [
18             'query'  => ['required'],
19             'page'   => ['integer', 'min:1'],
20             'count'  => ['integer', 'min:1', 'max:100'],
21         ],
22     ];
23
24     public function __construct(SearchRunner $searchRunner, SearchResultsFormatter $resultsFormatter)
25     {
26         $this->searchRunner = $searchRunner;
27         $this->resultsFormatter = $resultsFormatter;
28     }
29
30     /**
31      * Run a search query against all main content types (shelves, books, chapters & pages)
32      * in the system. Takes the same input as the main search bar within the BookStack
33      * interface as a 'query' parameter. See https://www.bookstackapp.com/docs/user/searching/
34      * for a full list of search term options. Results contain a 'type' property to distinguish
35      * between: bookshelf, book, chapter & page.
36      *
37      * The paging parameters and response format emulates a standard listing endpoint
38      * but standard sorting and filtering cannot be done on this endpoint. If a count value
39      * is provided this will only be taken as a suggestion. The results in the response
40      * may currently be up to 4x this value.
41      */
42     public function all(Request $request)
43     {
44         $this->validate($request, $this->rules['all']);
45
46         $options = SearchOptions::fromString($request->get('query') ?? '');
47         $page = intval($request->get('page', '0')) ?: 1;
48         $count = min(intval($request->get('count', '0')) ?: 20, 100);
49
50         $results = $this->searchRunner->searchEntities($options, 'all', $page, $count);
51         $this->resultsFormatter->format($results['results']->all(), $options);
52
53         /** @var Entity $result */
54         foreach ($results['results'] as $result) {
55             $result->setVisible([
56                 'id', 'name', 'slug', 'book_id',
57                 'chapter_id', 'draft', 'template',
58                 'created_at', 'updated_at',
59                 'tags', 'type', 'preview_html', 'url',
60             ]);
61             $result->setAttribute('type', $result->getType());
62             $result->setAttribute('url', $result->getUrl());
63             $result->setAttribute('preview_html', [
64                 'name'    => (string) $result->getAttribute('preview_name'),
65                 'content' => (string) $result->getAttribute('preview_content'),
66             ]);
67         }
68
69         return response()->json([
70             'data'  => $results['results'],
71             'total' => $results['total'],
72         ]);
73     }
74 }