Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
45.18% |
75 / 166 |
|
0.00% |
0 / 6 |
CRAP | |
0.00% |
0 / 1 |
Installer | |
45.18% |
75 / 166 |
|
0.00% |
0 / 6 |
289.57 | |
0.00% |
0 / 1 |
install | |
38.46% |
5 / 13 |
|
0.00% |
0 / 1 |
7.73 | |||
installExternal | |
81.08% |
30 / 37 |
|
0.00% |
0 / 1 |
11.82 | |||
createReference | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
12 | |||
createCollection | |
87.50% |
14 / 16 |
|
0.00% |
0 / 1 |
4.03 | |||
createType | |
0.00% |
0 / 29 |
|
0.00% |
0 / 1 |
42 | |||
uploadMedia | |
45.61% |
26 / 57 |
|
0.00% |
0 / 1 |
30.46 |
1 | <?php |
2 | /** |
3 | * Jingga |
4 | * |
5 | * PHP Version 8.1 |
6 | * |
7 | * @package Modules\Media\Admin |
8 | * @copyright Dennis Eichhorn |
9 | * @license OMS License 2.0 |
10 | * @version 1.0.0 |
11 | * @link https://jingga.app |
12 | */ |
13 | declare(strict_types=1); |
14 | |
15 | namespace Modules\Media\Admin; |
16 | |
17 | use Modules\Admin\Models\AccountMapper; |
18 | use Modules\Admin\Models\NullAccount; |
19 | use Modules\Media\Models\Collection; |
20 | use Modules\Media\Models\CollectionMapper; |
21 | use Modules\Media\Models\PathSettings; |
22 | use phpOMS\Application\ApplicationAbstract; |
23 | use phpOMS\Config\SettingsInterface; |
24 | use phpOMS\Message\Http\HttpRequest; |
25 | use phpOMS\Message\Http\HttpResponse; |
26 | use phpOMS\Module\InstallerAbstract; |
27 | use phpOMS\Module\ModuleInfo; |
28 | use phpOMS\System\File\Local\Directory; |
29 | use phpOMS\System\File\Local\File; |
30 | use phpOMS\System\File\PathException; |
31 | use phpOMS\Uri\HttpUri; |
32 | |
33 | /** |
34 | * Installer class. |
35 | * |
36 | * @package Modules\Media\Admin |
37 | * @license OMS License 2.0 |
38 | * @link https://jingga.app |
39 | * @since 1.0.0 |
40 | */ |
41 | final class Installer extends InstallerAbstract |
42 | { |
43 | /** |
44 | * Path of the file |
45 | * |
46 | * @var string |
47 | * @since 1.0.0 |
48 | */ |
49 | public const PATH = __DIR__; |
50 | |
51 | /** |
52 | * {@inheritdoc} |
53 | */ |
54 | public static function install(ApplicationAbstract $app, ModuleInfo $info, SettingsInterface $cfgHandler) : void |
55 | { |
56 | if (!\is_dir(__DIR__ . '/../Files')) { |
57 | \mkdir(__DIR__ . '/../Files'); |
58 | } |
59 | |
60 | if (!\is_dir(__DIR__ . '/../../../temp')) { |
61 | \mkdir(__DIR__ . '/../../../temp'); |
62 | } |
63 | |
64 | parent::install($app, $info, $cfgHandler); |
65 | |
66 | // Create directory for admin account |
67 | // All other accounts are automatically created in the admin module whenever they get created |
68 | // However, the admin account is created before the Media module is installed |
69 | // Because of this, the directory needs to be created manually after the Media installation |
70 | // The admin account should be the only DB account, but we use a loop of all accounts to avoid bugs |
71 | /** @var \Modules\Admin\Models\Account[] $accounts */ |
72 | $accounts = AccountMapper::getAll()->execute(); |
73 | |
74 | foreach ($accounts as $account) { |
75 | $collection = new Collection(); |
76 | $collection->name = ((string) $account->id) . ' ' . $account->login; |
77 | $collection->setVirtualPath('/Accounts'); |
78 | $collection->setPath('/Modules/Media/Files/Accounts/' . ((string) $account->id)); |
79 | // The installation is always run by the admin account since the module is a "base" module which is always installed during the application setup |
80 | $collection->createdBy = new NullAccount(1); |
81 | |
82 | CollectionMapper::create()->execute($collection); |
83 | } |
84 | } |
85 | |
86 | /** |
87 | * Install data from providing modules. |
88 | * |
89 | * The data can be either directories which should be created or files which should be "uploaded" |
90 | * |
91 | * @param ApplicationAbstract $app Application |
92 | * @param array $data Additional data |
93 | * |
94 | * @return array |
95 | * |
96 | * @throws PathException |
97 | * @throws \Exception |
98 | * |
99 | * @since 1.0.0 |
100 | */ |
101 | public static function installExternal(ApplicationAbstract $app, array $data) : array |
102 | { |
103 | if (!\is_file($data['path'] ?? '')) { |
104 | throw new PathException($data['path'] ?? ''); |
105 | } |
106 | |
107 | $mediaFile = \file_get_contents($data['path'] ?? ''); |
108 | if ($mediaFile === false) { |
109 | throw new PathException($data['path'] ?? ''); // @codeCoverageIgnore |
110 | } |
111 | |
112 | $mediaData = \json_decode($mediaFile, true) ?? []; |
113 | if ($mediaData === false) { |
114 | throw new \Exception(); // @codeCoverageIgnore |
115 | } |
116 | |
117 | $apiApp = new class() extends ApplicationAbstract |
118 | { |
119 | protected string $appName = 'Api'; |
120 | }; |
121 | |
122 | $apiApp->dbPool = $app->dbPool; |
123 | $apiApp->unitId = $app->unitId; |
124 | $apiApp->accountManager = $app->accountManager; |
125 | $apiApp->appSettings = $app->appSettings; |
126 | $apiApp->moduleManager = $app->moduleManager; |
127 | $apiApp->eventManager = $app->eventManager; |
128 | |
129 | $result = [ |
130 | 'collection' => [], |
131 | 'upload' => [], |
132 | 'type' => [], |
133 | ]; |
134 | |
135 | if (!\is_dir(__DIR__ . '/../../../temp')) { |
136 | \mkdir(__DIR__ . '/../../../temp'); |
137 | } |
138 | |
139 | /** @var array<string, array> $mediaData */ |
140 | foreach ($mediaData as $media) { |
141 | switch ($media['type']) { |
142 | case 'collection': |
143 | $result['collection'][] = self::createCollection($apiApp, $media); |
144 | break; |
145 | case 'upload': |
146 | $result['upload'][] = self::uploadMedia($apiApp, $media); |
147 | break; |
148 | case 'type': |
149 | $result['type'][] = self::createType($apiApp, $media); |
150 | break; |
151 | case 'reference': |
152 | $result['reference'][] = self::createReference($apiApp, $media); |
153 | break; |
154 | default: |
155 | } |
156 | } |
157 | |
158 | return $result; |
159 | } |
160 | |
161 | /** |
162 | * Create collection. |
163 | * |
164 | * @param ApplicationAbstract $app Application |
165 | * @param array{path?:string, name?:string, virtualPath?:string, create_directory?:bool} $data Media info |
166 | * |
167 | * @return array |
168 | * |
169 | * @since 1.0.0 |
170 | */ |
171 | private static function createReference(ApplicationAbstract $app, array $data) : array |
172 | { |
173 | /** @var \Modules\Media\Controller\ApiController $module */ |
174 | $module = $app->moduleManager->getModuleInstance('Media'); |
175 | |
176 | $response = new HttpResponse(); |
177 | $request = new HttpRequest(new HttpUri('')); |
178 | |
179 | $request->header->account = 1; |
180 | $request->setData('name', $data['name'] ?? ''); |
181 | $request->setData('virtualpath', $data['from'] ?? '/'); |
182 | $request->setData('child', $data['to'] ?? '/'); |
183 | |
184 | $module->apiReferenceCreate($request, $response); |
185 | |
186 | $responseData = $response->get(''); |
187 | if (!\is_array($responseData)) { |
188 | return []; |
189 | } |
190 | |
191 | return \is_array($responseData['response']) |
192 | ? $responseData['response'] |
193 | : $responseData['response']->toArray(); |
194 | } |
195 | |
196 | /** |
197 | * Create collection. |
198 | * |
199 | * @param ApplicationAbstract $app Application |
200 | * @param array{path?:string, name?:string, virtualPath?:string, create_directory?:bool} $data Media info |
201 | * |
202 | * @return array |
203 | * |
204 | * @since 1.0.0 |
205 | */ |
206 | private static function createCollection(ApplicationAbstract $app, array $data) : array |
207 | { |
208 | /** @var \Modules\Media\Controller\ApiController $module */ |
209 | $module = $app->moduleManager->getModuleInstance('Media'); |
210 | |
211 | $path = isset($data['path']) ? ($data['path']) : $data['virtualPath'] ?? ''; |
212 | |
213 | $response = new HttpResponse(); |
214 | $request = new HttpRequest(new HttpUri('')); |
215 | |
216 | $request->header->account = 1; |
217 | $request->setData('name', $data['name'] ?? ''); |
218 | $request->setData('virtualpath', $data['virtualPath'] ?? '/'); |
219 | $request->setData('path', $path); |
220 | $request->setData('create_directory', $data['create_directory'] ?? false); |
221 | |
222 | $module->apiCollectionCreate($request, $response); |
223 | |
224 | $responseData = $response->get(''); |
225 | if (!\is_array($responseData)) { |
226 | return []; |
227 | } |
228 | |
229 | return \is_array($responseData['response']) |
230 | ? $responseData['response'] |
231 | : $responseData['response']->toArray(); |
232 | } |
233 | |
234 | /** |
235 | * Create type. |
236 | * |
237 | * @param ApplicationAbstract $app Application |
238 | * @param array $data Media info |
239 | * |
240 | * @return array |
241 | * |
242 | * @since 1.0.0 |
243 | */ |
244 | private static function createType(ApplicationAbstract $app, array $data) : array |
245 | { |
246 | /** @var \Modules\Media\Controller\ApiController $module */ |
247 | $module = $app->moduleManager->get('Media'); |
248 | |
249 | $response = new HttpResponse(); |
250 | $request = new HttpRequest(new HttpUri('')); |
251 | |
252 | $request->header->account = 1; |
253 | $request->setData('name', $data['name'] ?? ''); |
254 | |
255 | if (!empty($data['l11n'])) { |
256 | $request->setData('title', \reset($data['l11n'])['title']); |
257 | $request->setData('lang', \reset($data['l11n'])['lang']); |
258 | } |
259 | |
260 | $module->apiMediaTypeCreate($request, $response); |
261 | |
262 | $responseData = $response->get(''); |
263 | if (!\is_array($responseData)) { |
264 | return []; |
265 | } |
266 | |
267 | $type = $responseData['response']; |
268 | $id = $type->id; |
269 | |
270 | $isFirst = true; |
271 | foreach ($data['l11n'] as $l11n) { |
272 | if ($isFirst) { |
273 | $isFirst = false; |
274 | continue; |
275 | } |
276 | |
277 | $response = new HttpResponse(); |
278 | $request = new HttpRequest(new HttpUri('')); |
279 | |
280 | $request->header->account = 1; |
281 | $request->setData('title', $l11n['title'] ?? ''); |
282 | $request->setData('lang', $l11n['lang'] ?? null); |
283 | $request->setData('type', $id); |
284 | |
285 | $module->apiMediaTypeL11nCreate($request, $response); |
286 | } |
287 | |
288 | return \is_array($type) |
289 | ? $type |
290 | : $type->toArray(); |
291 | } |
292 | |
293 | /** |
294 | * Upload media. |
295 | * |
296 | * @param ApplicationAbstract $app Application |
297 | * @param array $data Media info |
298 | * |
299 | * @return array |
300 | * |
301 | * @since 1.0.0 |
302 | */ |
303 | private static function uploadMedia(ApplicationAbstract $app, array $data) : array |
304 | { |
305 | /** @var \Modules\Media\Controller\ApiController $module */ |
306 | $module = $app->moduleManager->get('Media'); |
307 | |
308 | $response = new HttpResponse(); |
309 | $request = new HttpRequest(new HttpUri('')); |
310 | |
311 | $request->header->account = 1; |
312 | $request->setData('path', empty($data['path'] ?? '') ? '' : $data['path']); |
313 | $request->setData('virtualPath', |
314 | (string) ( |
315 | $data['create_collection'] |
316 | ? \rtrim($data['virtualPath'] ?? '/', '/') . '/' . ((string) ($data['name'] ?? '')) |
317 | : ($data['virtualPath'] ?? '/') |
318 | ) |
319 | ); |
320 | $request->setData('type', $data['media_type'] ?? null); // = identifier for modules |
321 | $request->setData('pathsettings', $data['path_setting'] ?? PathSettings::FILE_PATH); |
322 | |
323 | $tempPath = __DIR__ . '/../../../temp/'; |
324 | |
325 | foreach ($data['files'] as $file) { |
326 | $filePath = __DIR__ . '/../../..' . $file; |
327 | |
328 | if (\is_file($filePath)) { |
329 | File::copy($filePath, $tempPath . $file, true); |
330 | |
331 | $request->addFile([ |
332 | 'size' => \filesize($tempPath . $file), |
333 | 'name' => \basename($file), |
334 | 'tmp_name' => $tempPath . $file, |
335 | 'error' => \UPLOAD_ERR_OK, |
336 | ]); |
337 | } if (\is_dir($filePath)) { |
338 | Directory::copy($filePath, $tempPath . \basename($filePath), true); |
339 | |
340 | $iterator = new \RecursiveIteratorIterator( |
341 | new \RecursiveDirectoryIterator($tempPath . \basename($filePath), \RecursiveDirectoryIterator::SKIP_DOTS), |
342 | \RecursiveIteratorIterator::SELF_FIRST |
343 | ); |
344 | |
345 | /** @var \DirectoryIterator $iterator */ |
346 | foreach ($iterator as $item) { |
347 | if ($item->isDir()) { |
348 | continue; |
349 | } |
350 | |
351 | $request->addFile([ |
352 | 'size' => \filesize($item->getPathname()), |
353 | 'name' => \basename($item->getPathname()), |
354 | 'tmp_name' => $item->getPathname(), |
355 | 'error' => \UPLOAD_ERR_OK, |
356 | ]); |
357 | } |
358 | } |
359 | } |
360 | |
361 | $module->apiMediaUpload($request, $response); |
362 | |
363 | $uploadedIds = $response->getDataArray('')['response']; |
364 | |
365 | if ($data['create_collection'] ?? false) { |
366 | $response = new HttpResponse(); |
367 | $request = new HttpRequest(new HttpUri('')); |
368 | |
369 | $request->header->account = 1; |
370 | $request->setData('name', (string) ($data['name'] ?? '')); |
371 | $request->setData('virtualpath', (string) ($data['virtualPath'] ?? '/')); |
372 | $request->setData('path', (string) ($data['path'] ?? '/Modules/Media/Files/' . ((string) ($data['name'] ?? '')))); |
373 | $request->setData('media-list', \json_encode($uploadedIds)); |
374 | |
375 | $module->apiCollectionCreate($request, $response); |
376 | } |
377 | |
378 | $responseData = $response->get(''); |
379 | if (!\is_array($responseData)) { |
380 | return []; |
381 | } |
382 | |
383 | return \is_array($responseData['response']) |
384 | ? $responseData['response'] |
385 | : $responseData['response']->toArray(); |
386 | } |
387 | } |