1 <?php namespace BookStack\Entities\Tools;
3 use BookStack\Entities\EntityProvider;
4 use BookStack\Entities\Models\Entity;
5 use BookStack\Entities\Models\SearchTerm;
6 use Illuminate\Support\Collection;
13 protected $searchTerm;
18 protected $entityProvider;
21 public function __construct(SearchTerm $searchTerm, EntityProvider $entityProvider)
23 $this->searchTerm = $searchTerm;
24 $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
46 * @param Entity[] $entities
48 protected function indexEntities(array $entities)
51 foreach ($entities as $entity) {
52 $nameTerms = $this->generateTermArrayFromText($entity->name, 5 * $entity->searchFactor);
53 $bodyTerms = $this->generateTermArrayFromText($entity->getText(), 1 * $entity->searchFactor);
54 foreach (array_merge($nameTerms, $bodyTerms) as $term) {
55 $term['entity_id'] = $entity->id;
56 $term['entity_type'] = $entity->getMorphClass();
61 $chunkedTerms = array_chunk($terms, 500);
62 foreach ($chunkedTerms as $termChunk) {
63 $this->searchTerm->newQuery()->insert($termChunk);
68 * Delete and re-index the terms for all entities in the system.
70 public function indexAllEntities()
72 $this->searchTerm->newQuery()->truncate();
74 foreach ($this->entityProvider->all() as $entityModel) {
75 $selectFields = ['id', 'name', $entityModel->textField];
76 $entityModel->newQuery()
78 ->select($selectFields)
79 ->chunk(1000, function (Collection $entities) {
80 $this->indexEntities($entities->all());
86 * Delete related Entity search terms.
88 public function deleteEntityTerms(Entity $entity)
90 $entity->searchTerms()->delete();
94 * Create a scored term array from the given text.
96 protected function generateTermArrayFromText(string $text, int $scoreAdjustment = 1): array
98 $tokenMap = []; // {TextToken => OccurrenceCount}
99 $splitChars = " \n\t.,!?:;()[]{}<>`'\"";
100 $token = strtok($text, $splitChars);
102 while ($token !== false) {
103 if (!isset($tokenMap[$token])) {
104 $tokenMap[$token] = 0;
107 $token = strtok($splitChars);
111 foreach ($tokenMap as $token => $count) {
114 'score' => $count * $scoreAdjustment