<?php namespace BookStack\Services;
use BookStack\Book;
+use BookStack\Bookshelf;
use BookStack\Chapter;
use BookStack\Entity;
use BookStack\Page;
class SearchService
{
protected $searchTerm;
+ protected $bookshelf;
protected $book;
protected $chapter;
protected $page;
protected $db;
protected $permissionService;
+
+ /**
+ * @var Entity[]
+ */
protected $entities;
/**
/**
* SearchService constructor.
* @param SearchTerm $searchTerm
+ * @param Bookshelf $bookshelf
* @param Book $book
* @param Chapter $chapter
* @param Page $page
* @param Connection $db
* @param PermissionService $permissionService
*/
- public function __construct(SearchTerm $searchTerm, Book $book, Chapter $chapter, Page $page, Connection $db, PermissionService $permissionService)
+ public function __construct(SearchTerm $searchTerm, Bookshelf $bookshelf, Book $book, Chapter $chapter, Page $page, Connection $db, PermissionService $permissionService)
{
$this->searchTerm = $searchTerm;
+ $this->bookshelf = $bookshelf;
$this->book = $book;
$this->chapter = $chapter;
$this->page = $page;
$this->db = $db;
$this->entities = [
+ 'bookshelf' => $this->bookshelf,
'page' => $this->page,
'chapter' => $this->chapter,
'book' => $this->book
* @param string $entityType
* @param int $page
* @param int $count - Count of each entity to search, Total returned could can be larger and not guaranteed.
+ * @param string $action
* @return array[int, Collection];
*/
public function searchEntities($searchString, $entityType = 'all', $page = 1, $count = 20, $action = 'view')
{
$this->searchTerm->truncate();
- // Chunk through all books
- $this->book->chunk(1000, function ($books) {
- $this->indexEntities($books);
- });
-
- // Chunk through all chapters
- $this->chapter->chunk(1000, function ($chapters) {
- $this->indexEntities($chapters);
- });
-
- // Chunk through all pages
- $this->page->chunk(1000, function ($pages) {
- $this->indexEntities($pages);
- });
+ foreach ($this->entities as $entityModel) {
+ $selectFields = ['id', 'name', $entityModel->textField];
+ $entityModel->newQuery()->select($selectFields)->chunk(1000, function ($entities) {
+ $this->indexEntities($entities);
+ });
+ }
}
/**
type: {
page: true,
chapter: true,
- book: true
+ book: true,
+ bookshelf: true,
},
exactTerms: [],
tagTerms: [],
exactChange() {
let exactFilter = /"(.+?)"/g;
this.termString = this.termString.replace(exactFilter, '');
- let matchesTerm = this.search.exactTerms.filter(term => {
- return term.trim() !== '';
- }).map(term => {
- return `"${term}"`
- }).join(' ');
+ let matchesTerm = this.search.exactTerms.filter(term => term.trim() !== '').map(term => `"${term}"`).join(' ');
this.appendTerm(matchesTerm);
},
let match = searchString.match(typeFilter);
let type = this.search.type;
if (!match) {
- type.page = type.book = type.chapter = true;
+ type.page = type.book = type.chapter = type.bookshelf = true;
return;
}
let splitTypes = match[1].replace(/ /g, '').split('|');
type.page = (splitTypes.indexOf('page') !== -1);
type.chapter = (splitTypes.indexOf('chapter') !== -1);
type.book = (splitTypes.indexOf('book') !== -1);
+ type.bookshelf = (splitTypes.indexOf('bookshelf') !== -1);
},
typeChange() {
let typeFilter = /{\s?type:\s?(.*?)\s?}/;
let type = this.search.type;
- if (type.page === type.chapter && type.page === type.book) {
+ if (type.page === type.chapter === type.book === type.bookshelf) {
this.termString = this.termString.replace(typeFilter, '');
return;
}
- let selectedTypes = Object.keys(type).filter(type => {return this.search.type[type];}).join('|');
+ let selectedTypes = Object.keys(type).filter(type => this.search.type[type]).join('|');
let typeTerm = '{type:'+selectedTypes+'}';
if (this.termString.match(typeFilter)) {
this.termString = this.termString.replace(typeFilter, typeTerm);
<?php namespace Tests;
+use BookStack\Bookshelf;
use BookStack\Chapter;
use BookStack\Page;
$search->assertSee($page->name);
}
+ public function test_bookshelf_search()
+ {
+ $shelf = Bookshelf::first();
+ $search = $this->asEditor()->get('/search?term=' . urlencode(mb_substr($shelf->name, 0, 3)) . ' {type:bookshelf}');
+ $search->assertStatus(200);
+ $search->assertSee($shelf->name);
+ }
+
public function test_invalid_page_search()
{
$resp = $this->asEditor()->get('/search?term=' . urlencode('<p>test</p>'));