]> BookStack Code Mirror - bookstack/blob - app/Search/SearchController.php
Thumbnails: Fixed thumnail orientation
[bookstack] / app / Search / SearchController.php
1 <?php
2
3 namespace BookStack\Search;
4
5 use BookStack\Entities\Queries\PageQueries;
6 use BookStack\Entities\Queries\QueryPopular;
7 use BookStack\Entities\Tools\SiblingFetcher;
8 use BookStack\Http\Controller;
9 use Illuminate\Http\Request;
10
11 class SearchController extends Controller
12 {
13     public function __construct(
14         protected SearchRunner $searchRunner,
15         protected PageQueries $pageQueries,
16     ) {
17     }
18
19     /**
20      * Searches all entities.
21      */
22     public function search(Request $request, SearchResultsFormatter $formatter)
23     {
24         $searchOpts = SearchOptions::fromRequest($request);
25         $fullSearchString = $searchOpts->toString();
26         $this->setPageTitle(trans('entities.search_for_term', ['term' => $fullSearchString]));
27
28         $page = intval($request->get('page', '0')) ?: 1;
29         $nextPageLink = url('/search?term=' . urlencode($fullSearchString) . '&page=' . ($page + 1));
30
31         $results = $this->searchRunner->searchEntities($searchOpts, 'all', $page, 20);
32         $formatter->format($results['results']->all(), $searchOpts);
33
34         return view('search.all', [
35             'entities'     => $results['results'],
36             'totalResults' => $results['total'],
37             'searchTerm'   => $fullSearchString,
38             'hasNextPage'  => $results['has_more'],
39             'nextPageLink' => $nextPageLink,
40             'options'      => $searchOpts,
41         ]);
42     }
43
44     /**
45      * Searches all entities within a book.
46      */
47     public function searchBook(Request $request, int $bookId)
48     {
49         $term = $request->get('term', '');
50         $results = $this->searchRunner->searchBook($bookId, $term);
51
52         return view('entities.list', ['entities' => $results]);
53     }
54
55     /**
56      * Searches all entities within a chapter.
57      */
58     public function searchChapter(Request $request, int $chapterId)
59     {
60         $term = $request->get('term', '');
61         $results = $this->searchRunner->searchChapter($chapterId, $term);
62
63         return view('entities.list', ['entities' => $results]);
64     }
65
66     /**
67      * Search for a list of entities and return a partial HTML response of matching entities.
68      * Returns the most popular entities if no search is provided.
69      */
70     public function searchForSelector(Request $request, QueryPopular $queryPopular)
71     {
72         $entityTypes = $request->filled('types') ? explode(',', $request->get('types')) : ['page', 'chapter', 'book'];
73         $searchTerm = $request->get('term', false);
74         $permission = $request->get('permission', 'view');
75
76         // Search for entities otherwise show most popular
77         if ($searchTerm !== false) {
78             $searchTerm .= ' {type:' . implode('|', $entityTypes) . '}';
79             $entities = $this->searchRunner->searchEntities(SearchOptions::fromString($searchTerm), 'all', 1, 20)['results'];
80         } else {
81             $entities = $queryPopular->run(20, 0, $entityTypes);
82         }
83
84         return view('search.parts.entity-selector-list', ['entities' => $entities, 'permission' => $permission]);
85     }
86
87     /**
88      * Search for a list of templates to choose from.
89      */
90     public function templatesForSelector(Request $request)
91     {
92         $searchTerm = $request->get('term', false);
93
94         if ($searchTerm !== false) {
95             $searchOptions = SearchOptions::fromString($searchTerm);
96             $searchOptions->setFilter('is_template');
97             $entities = $this->searchRunner->searchEntities($searchOptions, 'page', 1, 20)['results'];
98         } else {
99             $entities = $this->pageQueries->visibleTemplates()
100                 ->where('draft', '=', false)
101                 ->orderBy('updated_at', 'desc')
102                 ->take(20)
103                 ->get();
104         }
105
106         return view('search.parts.entity-selector-list', [
107             'entities' => $entities,
108             'permission' => 'view'
109         ]);
110     }
111
112     /**
113      * Search for a list of entities and return a partial HTML response of matching entities
114      * to be used as a result preview suggestion list for global system searches.
115      */
116     public function searchSuggestions(Request $request)
117     {
118         $searchTerm = $request->get('term', '');
119         $entities = $this->searchRunner->searchEntities(SearchOptions::fromString($searchTerm), 'all', 1, 5)['results'];
120
121         foreach ($entities as $entity) {
122             $entity->setAttribute('preview_content', '');
123         }
124
125         return view('search.parts.entity-suggestion-list', [
126             'entities' => $entities->slice(0, 5)
127         ]);
128     }
129
130     /**
131      * Search siblings items in the system.
132      */
133     public function searchSiblings(Request $request, SiblingFetcher $siblingFetcher)
134     {
135         $type = $request->get('entity_type', null);
136         $id = $request->get('entity_id', null);
137
138         $entities = $siblingFetcher->fetch($type, $id);
139
140         return view('entities.list-basic', ['entities' => $entities, 'style' => 'compact']);
141     }
142 }