3 namespace BookStack\Search;
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 BookStack\Search\Vectors\VectorSearchRunner;
10 use Illuminate\Http\Request;
12 class SearchController extends Controller
14 public function __construct(
15 protected SearchRunner $searchRunner,
16 protected PageQueries $pageQueries,
21 * Searches all entities.
23 public function search(Request $request, SearchResultsFormatter $formatter)
25 $searchOpts = SearchOptions::fromRequest($request);
26 $fullSearchString = $searchOpts->toString();
27 $this->setPageTitle(trans('entities.search_for_term', ['term' => $fullSearchString]));
29 $page = intval($request->get('page', '0')) ?: 1;
30 $nextPageLink = url('/search?term=' . urlencode($fullSearchString) . '&page=' . ($page + 1));
32 $results = $this->searchRunner->searchEntities($searchOpts, 'all', $page, 20);
33 $formatter->format($results['results']->all(), $searchOpts);
35 return view('search.all', [
36 'entities' => $results['results'],
37 'totalResults' => $results['total'],
38 'searchTerm' => $fullSearchString,
39 'hasNextPage' => $results['has_more'],
40 'nextPageLink' => $nextPageLink,
41 'options' => $searchOpts,
46 * Searches all entities within a book.
48 public function searchBook(Request $request, int $bookId)
50 $term = $request->get('term', '');
51 $results = $this->searchRunner->searchBook($bookId, $term);
53 return view('entities.list', ['entities' => $results]);
57 * Searches all entities within a chapter.
59 public function searchChapter(Request $request, int $chapterId)
61 $term = $request->get('term', '');
62 $results = $this->searchRunner->searchChapter($chapterId, $term);
64 return view('entities.list', ['entities' => $results]);
68 * Search for a list of entities and return a partial HTML response of matching entities.
69 * Returns the most popular entities if no search is provided.
71 public function searchForSelector(Request $request, QueryPopular $queryPopular)
73 $entityTypes = $request->filled('types') ? explode(',', $request->get('types')) : ['page', 'chapter', 'book'];
74 $searchTerm = $request->get('term', false);
75 $permission = $request->get('permission', 'view');
77 // Search for entities otherwise show most popular
78 if ($searchTerm !== false) {
79 $searchTerm .= ' {type:' . implode('|', $entityTypes) . '}';
80 $entities = $this->searchRunner->searchEntities(SearchOptions::fromString($searchTerm), 'all', 1, 20)['results'];
82 $entities = $queryPopular->run(20, 0, $entityTypes);
85 return view('search.parts.entity-selector-list', ['entities' => $entities, 'permission' => $permission]);
89 * Search for a list of templates to choose from.
91 public function templatesForSelector(Request $request)
93 $searchTerm = $request->get('term', false);
95 if ($searchTerm !== false) {
96 $searchOptions = SearchOptions::fromString($searchTerm);
97 $searchOptions->setFilter('is_template');
98 $entities = $this->searchRunner->searchEntities($searchOptions, 'page', 1, 20)['results'];
100 $entities = $this->pageQueries->visibleTemplates()
101 ->where('draft', '=', false)
102 ->orderBy('updated_at', 'desc')
107 return view('search.parts.entity-selector-list', [
108 'entities' => $entities,
109 'permission' => 'view'
114 * Search for a list of entities and return a partial HTML response of matching entities
115 * to be used as a result preview suggestion list for global system searches.
117 public function searchSuggestions(Request $request)
119 $searchTerm = $request->get('term', '');
120 $entities = $this->searchRunner->searchEntities(SearchOptions::fromString($searchTerm), 'all', 1, 5)['results'];
122 foreach ($entities as $entity) {
123 $entity->setAttribute('preview_content', '');
126 return view('search.parts.entity-suggestion-list', [
127 'entities' => $entities->slice(0, 5)
132 * Search siblings items in the system.
134 public function searchSiblings(Request $request, SiblingFetcher $siblingFetcher)
136 $type = $request->get('entity_type', null);
137 $id = $request->get('entity_id', null);
139 $entities = $siblingFetcher->fetch($type, $id);
141 return view('entities.list-basic', ['entities' => $entities, 'style' => 'compact']);
144 public function searchQuery(Request $request, VectorSearchRunner $runner)
146 $query = $request->get('query', '');
149 $results = $runner->run($query);
154 return view('search.query', [
155 'results' => $results,