]> BookStack Code Mirror - bookstack/blob - app/References/ReferenceStore.php
Thumbnails: Fixed thumnail orientation
[bookstack] / app / References / ReferenceStore.php
1 <?php
2
3 namespace BookStack\References;
4
5 use BookStack\Entities\EntityProvider;
6 use BookStack\Entities\Models\Entity;
7 use Illuminate\Database\Eloquent\Collection;
8
9 class ReferenceStore
10 {
11     public function __construct(
12         protected EntityProvider $entityProvider
13     ) {
14     }
15
16     /**
17      * Update the outgoing references for the given entity.
18      */
19     public function updateForEntity(Entity $entity): void
20     {
21         $this->updateForEntities([$entity]);
22     }
23
24     /**
25      * Update the outgoing references for all entities in the system.
26      */
27     public function updateForAll(): void
28     {
29         Reference::query()->delete();
30
31         foreach ($this->entityProvider->all() as $entity) {
32             $entity->newQuery()->select(['id', $entity->htmlField])->chunk(100, function (Collection $entities) {
33                 $this->updateForEntities($entities->all());
34             });
35         }
36     }
37
38     /**
39      * Update the outgoing references for the entities in the given array.
40      *
41      * @param Entity[] $entities
42      */
43     protected function updateForEntities(array $entities): void
44     {
45         if (count($entities) === 0) {
46             return;
47         }
48
49         $parser = CrossLinkParser::createWithEntityResolvers();
50         $references = [];
51
52         $this->dropReferencesFromEntities($entities);
53
54         foreach ($entities as $entity) {
55             $models = $parser->extractLinkedModels($entity->getAttribute($entity->htmlField));
56
57             foreach ($models as $model) {
58                 $references[] = [
59                     'from_id'   => $entity->id,
60                     'from_type' => $entity->getMorphClass(),
61                     'to_id'     => $model->id,
62                     'to_type'   => $model->getMorphClass(),
63                 ];
64             }
65         }
66
67         foreach (array_chunk($references, 1000) as $referenceDataChunk) {
68             Reference::query()->insert($referenceDataChunk);
69         }
70     }
71
72     /**
73      * Delete all the existing references originating from the given entities.
74      * @param Entity[] $entities
75      */
76     protected function dropReferencesFromEntities(array $entities): void
77     {
78         $IdsByType = [];
79
80         foreach ($entities as $entity) {
81             $type = $entity->getMorphClass();
82             if (!isset($IdsByType[$type])) {
83                 $IdsByType[$type] = [];
84             }
85
86             $IdsByType[$type][] = $entity->id;
87         }
88
89         foreach ($IdsByType as $type => $entityIds) {
90             Reference::query()
91                 ->where('from_type', '=', $type)
92                 ->whereIn('from_id', $entityIds)
93                 ->delete();
94         }
95     }
96 }