]> BookStack Code Mirror - bookstack/blob - app/Api/ApiEntityListFormatter.php
Comments: Moved to tab UI, Converted tabs component to ts
[bookstack] / app / Api / ApiEntityListFormatter.php
1 <?php
2
3 namespace BookStack\Api;
4
5 use BookStack\Entities\Models\BookChild;
6 use BookStack\Entities\Models\Entity;
7 use BookStack\Entities\Models\Page;
8
9 class ApiEntityListFormatter
10 {
11     /**
12      * The list to be formatted.
13      * @var Entity[]
14      */
15     protected array $list = [];
16
17     /**
18      * The fields to show in the formatted data.
19      * Can be a plain string array item for a direct model field (If existing on model).
20      * If the key is a string, with a callable value, the return value of the callable
21      * will be used for the resultant value. A null return value will omit the property.
22      * @var array<string|int, string|callable>
23      */
24     protected array $fields = [
25         'id',
26         'name',
27         'slug',
28         'book_id',
29         'chapter_id',
30         'draft',
31         'template',
32         'priority',
33         'created_at',
34         'updated_at',
35     ];
36
37     public function __construct(array $list)
38     {
39         $this->list = $list;
40
41         // Default dynamic fields
42         $this->withField('url', fn(Entity $entity) => $entity->getUrl());
43     }
44
45     /**
46      * Add a field to be used in the formatter, with the property using the given
47      * name and value being the return type of the given callback.
48      */
49     public function withField(string $property, callable $callback): self
50     {
51         $this->fields[$property] = $callback;
52         return $this;
53     }
54
55     /**
56      * Show the 'type' property in the response reflecting the entity type.
57      * EG: page, chapter, bookshelf, book
58      * To be included in results with non-pre-determined types.
59      */
60     public function withType(): self
61     {
62         $this->withField('type', fn(Entity $entity) => $entity->getType());
63         return $this;
64     }
65
66     /**
67      * Include tags in the formatted data.
68      */
69     public function withTags(): self
70     {
71         $this->withField('tags', fn(Entity $entity) => $entity->tags);
72         return $this;
73     }
74
75     /**
76      * Include parent book/chapter info in the formatted data.
77      */
78     public function withParents(): self
79     {
80         $this->withField('book', function (Entity $entity) {
81             if ($entity instanceof BookChild && $entity->book) {
82                 return $entity->book->only(['id', 'name', 'slug']);
83             }
84             return null;
85         });
86
87         $this->withField('chapter', function (Entity $entity) {
88             if ($entity instanceof Page && $entity->chapter) {
89                 return $entity->chapter->only(['id', 'name', 'slug']);
90             }
91             return null;
92         });
93
94         return $this;
95     }
96
97     /**
98      * Format the data and return an array of formatted content.
99      * @return array[]
100      */
101     public function format(): array
102     {
103         $results = [];
104
105         foreach ($this->list as $item) {
106             $results[] = $this->formatSingle($item);
107         }
108
109         return $results;
110     }
111
112     /**
113      * Format a single entity item to a plain array.
114      */
115     protected function formatSingle(Entity $entity): array
116     {
117         $result = [];
118         $values = (clone $entity)->toArray();
119
120         foreach ($this->fields as $field => $callback) {
121             if (is_string($callback)) {
122                 $field = $callback;
123                 if (!isset($values[$field])) {
124                     continue;
125                 }
126                 $value = $values[$field];
127             } else {
128                 $value = $callback($entity);
129                 if (is_null($value)) {
130                     continue;
131                 }
132             }
133
134             $result[$field] = $value;
135         }
136
137         return $result;
138     }
139 }