3 namespace BookStack\Entities\Tools;
5 use BookStack\App\Model;
6 use BookStack\Entities\Queries\EntityQueries;
7 use Illuminate\Database\Eloquent\Relations\Relation;
9 class MixedEntityListLoader
11 public function __construct(
12 protected EntityQueries $queries,
17 * Efficiently load in entities for listing onto the given list
18 * where entities are set as a relation via the given name.
19 * This will look for a model id and type via 'name_id' and 'name_type'.
20 * @param Model[] $relations
22 public function loadIntoRelations(array $relations, string $relationName, bool $loadParents): void
25 foreach ($relations as $relation) {
26 $type = $relation->getAttribute($relationName . '_type');
27 $id = $relation->getAttribute($relationName . '_id');
29 if (!isset($idsByType[$type])) {
30 $idsByType[$type] = [];
33 $idsByType[$type][] = $id;
36 $modelMap = $this->idsByTypeToModelMap($idsByType, $loadParents);
38 foreach ($relations as $relation) {
39 $type = $relation->getAttribute($relationName . '_type');
40 $id = $relation->getAttribute($relationName . '_id');
41 $related = $modelMap[$type][strval($id)] ?? null;
43 $relation->setRelation($relationName, $related);
49 * @param array<string, int[]> $idsByType
50 * @return array<string, array<int, Model>>
52 protected function idsByTypeToModelMap(array $idsByType, bool $eagerLoadParents): array
56 foreach ($idsByType as $type => $ids) {
57 $models = $this->queries->visibleForList($type)
59 ->with($eagerLoadParents ? $this->getRelationsToEagerLoad($type) : [])
62 if (count($models) > 0) {
63 $modelMap[$type] = [];
66 foreach ($models as $model) {
67 $modelMap[$type][strval($model->id)] = $model;
74 protected function getRelationsToEagerLoad(string $type): array
77 $loadVisible = fn (Relation $query) => $query->scopes('visible');
79 if ($type === 'chapter' || $type === 'page') {
80 $toLoad['book'] = $loadVisible;
83 if ($type === 'page') {
84 $toLoad['chapter'] = $loadVisible;