3 namespace BookStack\Entities\Tools;
5 use BookStack\Entities\EntityProvider;
6 use BookStack\Entities\Models\Entity;
7 use BookStack\Entities\Models\SearchTerm;
8 use Illuminate\Support\Collection;
15 protected $searchTerm;
20 protected $entityProvider;
22 public function __construct(SearchTerm $searchTerm, EntityProvider $entityProvider)
24 $this->searchTerm = $searchTerm;
25 $this->entityProvider = $entityProvider;
29 * Index the given entity.
31 public function indexEntity(Entity $entity)
33 $this->deleteEntityTerms($entity);
34 $nameTerms = $this->generateTermArrayFromText($entity->name, 5 * $entity->searchFactor);
35 $bodyTerms = $this->generateTermArrayFromText($entity->getText(), 1 * $entity->searchFactor);
36 $terms = array_merge($nameTerms, $bodyTerms);
37 foreach ($terms as $index => $term) {
38 $terms[$index]['entity_type'] = $entity->getMorphClass();
39 $terms[$index]['entity_id'] = $entity->id;
41 $this->searchTerm->newQuery()->insert($terms);
45 * Index multiple Entities at once.
47 * @param Entity[] $entities
49 protected function indexEntities(array $entities)
52 foreach ($entities as $entity) {
53 $nameTerms = $this->generateTermArrayFromText($entity->name, 5 * $entity->searchFactor);
54 $bodyTerms = $this->generateTermArrayFromText($entity->getText(), 1 * $entity->searchFactor);
55 foreach (array_merge($nameTerms, $bodyTerms) as $term) {
56 $term['entity_id'] = $entity->id;
57 $term['entity_type'] = $entity->getMorphClass();
62 $chunkedTerms = array_chunk($terms, 500);
63 foreach ($chunkedTerms as $termChunk) {
64 $this->searchTerm->newQuery()->insert($termChunk);
69 * Delete and re-index the terms for all entities in the system.
71 public function indexAllEntities()
73 $this->searchTerm->newQuery()->truncate();
75 foreach ($this->entityProvider->all() as $entityModel) {
76 $selectFields = ['id', 'name', $entityModel->textField];
77 $entityModel->newQuery()
79 ->select($selectFields)
80 ->chunk(1000, function (Collection $entities) {
81 $this->indexEntities($entities->all());
87 * Delete related Entity search terms.
89 public function deleteEntityTerms(Entity $entity)
91 $entity->searchTerms()->delete();
95 * Create a scored term array from the given text.
97 protected function generateTermArrayFromText(string $text, int $scoreAdjustment = 1): array
99 $tokenMap = []; // {TextToken => OccurrenceCount}
100 $splitChars = " \n\t.,!?:;()[]{}<>`'\"";
101 $token = strtok($text, $splitChars);
103 while ($token !== false) {
104 if (!isset($tokenMap[$token])) {
105 $tokenMap[$token] = 0;
108 $token = strtok($splitChars);
112 foreach ($tokenMap as $token => $count) {
115 'score' => $count * $scoreAdjustment,