Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | n/a |
0 / 0 |
n/a |
0 / 0 |
CRAP | n/a |
0 / 0 |
|||
BackendController | n/a |
0 / 0 |
n/a |
0 / 0 |
72 | n/a |
0 / 0 |
|||
viewMediaList | n/a |
0 / 0 |
n/a |
0 / 0 |
24 | |||||
viewMediaSingle | n/a |
0 / 0 |
n/a |
0 / 0 |
7 | |||||
createMediaView | n/a |
0 / 0 |
n/a |
0 / 0 |
36 | |||||
viewModuleSettings | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
viewMediaTypeSettings | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
viewMediaUpload | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
viewMediaFileCreate | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
viewMediaCollectionCreate | n/a |
0 / 0 |
n/a |
0 / 0 |
1 |
1 | <?php |
2 | /** |
3 | * Jingga |
4 | * |
5 | * PHP Version 8.1 |
6 | * |
7 | * @package Modules\Media |
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\Controller; |
16 | |
17 | use Model\SettingMapper; |
18 | use Modules\Admin\Models\Account; |
19 | use Modules\Admin\Models\PermissionAbstractMapper; |
20 | use Modules\Media\Models\Collection; |
21 | use Modules\Media\Models\CollectionMapper; |
22 | use Modules\Media\Models\Media; |
23 | use Modules\Media\Models\MediaClass; |
24 | use Modules\Media\Models\MediaMapper; |
25 | use Modules\Media\Models\MediaTypeL11nMapper; |
26 | use Modules\Media\Models\MediaTypeMapper; |
27 | use Modules\Media\Models\NullMedia; |
28 | use Modules\Media\Models\PermissionCategory; |
29 | use Modules\Media\Theme\Backend\Components\Media\ElementView; |
30 | use Modules\Media\Theme\Backend\Components\Media\ListView; |
31 | use Modules\Media\Views\MediaView; |
32 | use phpOMS\Account\PermissionType; |
33 | use phpOMS\Contract\RenderableInterface; |
34 | use phpOMS\Message\RequestAbstract; |
35 | use phpOMS\Message\ResponseAbstract; |
36 | use phpOMS\Utils\StringUtils; |
37 | use phpOMS\Views\View; |
38 | |
39 | /** |
40 | * Media class. |
41 | * |
42 | * @package Modules\Media |
43 | * @license OMS License 2.0 |
44 | * @link https://jingga.app |
45 | * @since 1.0.0 |
46 | * @codeCoverageIgnore |
47 | */ |
48 | final class BackendController extends Controller |
49 | { |
50 | use FileUploaderTrait; |
51 | |
52 | /** |
53 | * Routing end-point for application behaviour. |
54 | * |
55 | * @param RequestAbstract $request Request |
56 | * @param ResponseAbstract $response Response |
57 | * @param array $data Generic data |
58 | * |
59 | * @return RenderableInterface |
60 | * |
61 | * @since 1.0.0 |
62 | * @codeCoverageIgnore |
63 | */ |
64 | public function viewMediaList(RequestAbstract $request, ResponseAbstract $response, array $data = []) : RenderableInterface |
65 | { |
66 | $view = new View($this->app->l11nManager, $request, $response); |
67 | $view->setTemplate('/Modules/Media/Theme/Backend/media-list'); |
68 | |
69 | $path = \str_replace('+', ' ', $request->getDataString('path') ?? '/'); |
70 | |
71 | $hasPermission = $this->app->accountManager->get($request->header->account) |
72 | ->hasPermission( |
73 | PermissionType::READ, |
74 | $this->app->unitId, |
75 | $this->app->appId, |
76 | self::NAME, |
77 | PermissionCategory::MEDIA, |
78 | ); |
79 | |
80 | $mediaMapper = MediaMapper::getByVirtualPath($path)->where('tags/title/language', $request->header->l11n->language); |
81 | |
82 | if (!$hasPermission) { |
83 | $permWhere = PermissionAbstractMapper::helper($this->app->dbPool->get('select')) |
84 | ->groups($this->app->accountManager->get($request->header->account)->getGroupIds()) |
85 | ->account($request->header->account) |
86 | ->units([null, $this->app->unitId]) |
87 | ->apps([null, 'Api', $this->app->appId]) |
88 | ->modules([null, self::NAME]) |
89 | ->categories([null, PermissionCategory::MEDIA]) |
90 | ->permission(PermissionType::READ) |
91 | ->query(MediaMapper::PRIMARYFIELD); |
92 | |
93 | $mediaMapper->where('', $permWhere); |
94 | } |
95 | |
96 | /** @var Media[] $media */ |
97 | $media = $mediaMapper->execute(); |
98 | |
99 | $collectionMapper = CollectionMapper::getParentCollection($path) |
100 | ->where('tags/title/language', $request->header->l11n->language); |
101 | |
102 | if (!$hasPermission) { |
103 | $permWhere = PermissionAbstractMapper::helper($this->app->dbPool->get('select')) |
104 | ->groups($this->app->accountManager->get($request->header->account)->getGroupIds()) |
105 | ->account($request->header->account) |
106 | ->units([null, $this->app->unitId]) |
107 | ->apps([null, 'Api', $this->app->appName]) |
108 | ->modules([null, self::NAME]) |
109 | ->categories([null, PermissionCategory::MEDIA]) |
110 | ->permission(PermissionType::READ) |
111 | ->query(MediaMapper::PRIMARYFIELD); |
112 | |
113 | $collectionMapper->where('', $permWhere); |
114 | } |
115 | |
116 | /** @var \Modules\Media\Models\Collection $collection */ |
117 | $collection = $collectionMapper->execute(); |
118 | |
119 | if ((empty($collection) || $collection->id === 0) && \is_dir(__DIR__ . '/../Files' . $path)) { |
120 | $collection = new Collection(); |
121 | $collection->name = \basename($path); |
122 | $collection->setVirtualPath(\dirname($path)); |
123 | $collection->setPath($path); |
124 | $collection->isAbsolute = false; |
125 | } |
126 | |
127 | if ($collection instanceof Collection && $collection->id > 0) { |
128 | $collectionSources = $collection->getSources(); |
129 | foreach ($collectionSources as $source) { |
130 | foreach ($media as $obj) { |
131 | if ($obj->id === $source->id) { |
132 | continue 2; |
133 | } |
134 | } |
135 | |
136 | $media[] = $source; |
137 | } |
138 | |
139 | /** @var string[] $glob */ |
140 | $glob = $collection->isAbsolute |
141 | ? \glob($collection->getPath() . '/' . $collection->name . '/*') |
142 | : \glob(__DIR__ . '/../Files/' . \trim($collection->getVirtualPath(), '/') . '/' . $collection->name . '/*'); |
143 | $glob = $glob === false ? [] : $glob; |
144 | |
145 | $unIndexedFiles = []; |
146 | |
147 | foreach ($glob as $file) { |
148 | $basename = \basename($file); |
149 | $realpath = \realpath($file); |
150 | if (($basename[0] === '_' && \strlen($basename) === 5) || $realpath === false) { |
151 | continue; |
152 | } |
153 | |
154 | foreach ($media as $obj) { |
155 | if ($obj->name === $basename |
156 | || $obj->name . '.' . $obj->extension === $basename |
157 | || ($obj->getPath() !== '' && StringUtils::endsWith($realpath, $obj->getPath())) |
158 | ) { |
159 | continue 2; |
160 | } |
161 | } |
162 | |
163 | $pathinfo = \pathinfo($file); |
164 | |
165 | $localMedia = new Media(); |
166 | $localMedia->name = $pathinfo['basename']; |
167 | $localMedia->extension = \is_dir($file) ? 'collection' : $pathinfo['extension'] ?? ''; |
168 | $localMedia->createdBy = new Account(); |
169 | $localMedia->class = $localMedia->extension === 'collection' |
170 | ? MediaClass::SYSTEM_DIRECTORY |
171 | : MediaClass::SYSTEM_FILE; |
172 | $localMedia->setVirtualPath($path); |
173 | |
174 | $unIndexedFiles[] = $localMedia; |
175 | } |
176 | |
177 | $media = \array_merge($media, $unIndexedFiles); |
178 | } |
179 | |
180 | $view->data['media'] = $media; |
181 | $view->data['path'] = $path; |
182 | $view->data['account'] = $this->app->accountManager->get($request->header->account); |
183 | |
184 | return $view; |
185 | } |
186 | |
187 | /** |
188 | * Routing end-point for application behaviour. |
189 | * |
190 | * @param RequestAbstract $request Request |
191 | * @param ResponseAbstract $response Response |
192 | * @param array $data Generic data |
193 | * |
194 | * @return RenderableInterface |
195 | * |
196 | * @since 1.0.0 |
197 | * @codeCoverageIgnore |
198 | */ |
199 | public function viewMediaSingle(RequestAbstract $request, ResponseAbstract $response, array $data = []) : RenderableInterface |
200 | { |
201 | $view = new MediaView($this->app->l11nManager, $request, $response); |
202 | $view->setTemplate('/Modules/Media/Theme/Backend/media-single'); |
203 | $view->data['nav'] = $this->app->moduleManager->get('Navigation')->createNavigationMid(1000401001, $request, $response); |
204 | |
205 | $id = $request->getDataInt('id'); |
206 | if ($id === 0) { |
207 | $path = \urldecode($request->getDataString('path') ?? ''); |
208 | $media = new NullMedia(); |
209 | |
210 | if (\is_file(__DIR__ . '/../Files' . $path)) { |
211 | $name = \explode('.', \basename($path)); |
212 | |
213 | $media->name = $name[0]; |
214 | $media->extension = $name[\count($name) - 1] ?? ''; |
215 | $media->setVirtualPath(\dirname($path)); |
216 | $media->setPath('/Modules/Media/Files/' . \ltrim($path, '\\/')); |
217 | $media->isAbsolute = false; |
218 | |
219 | $view->data['view'] = $this->createMediaView($media, $request, $response); |
220 | } |
221 | } else { |
222 | /** @var \Modules\Media\Models\Media $media */ |
223 | $media = MediaMapper::get() |
224 | ->with('createdBy') |
225 | ->with('tags') |
226 | ->with('tags/title') |
227 | ->with('content') |
228 | ->where('id', $id) |
229 | ->where('tags/title/language', $request->header->l11n->language) |
230 | ->execute(); |
231 | |
232 | if ($media->class === MediaClass::COLLECTION) { |
233 | /** @var \Modules\Media\Models\Media[] $files */ |
234 | $files = MediaMapper::getByVirtualPath( |
235 | $media->getVirtualPath() . ($media->getVirtualPath() !== '/' ? '/' : '') . $media->name |
236 | )->where('tags/title/language', $request->header->l11n->language)->execute(); |
237 | |
238 | /** @var \Modules\Media\Models\Collection $collection */ |
239 | $collection = CollectionMapper::get()->where('id', $id)->execute(); |
240 | $media = \array_merge($files, $collection->getSources()); |
241 | |
242 | $view->data['path'] = $collection->getVirtualPath() . '/' . $collection->name; |
243 | $view->setTemplate('/Modules/Media/Theme/Backend/media-list'); |
244 | } else { |
245 | $sub = $request->getDataString('sub') ?? ''; |
246 | if (\is_dir($media->getPath() . $sub)) { |
247 | $listView = new ListView($this->app->l11nManager, $request, $response); |
248 | $listView->setTemplate('/modules/Media/Theme/Backend/Components/Media/list'); |
249 | $view->data['view'] = $listView; |
250 | } elseif ($media->class === MediaClass::REFERENCE) { |
251 | /** @var \Modules\Media\Models\Media $media */ |
252 | $media->source = MediaMapper::get() |
253 | ->with('createdBy') |
254 | ->with('tags') |
255 | ->with('tags/title') |
256 | ->with('content') |
257 | ->where('id', $media->source?->id ?? 0) |
258 | ->where('tags/title/language', $request->header->l11n->language) |
259 | ->execute(); |
260 | |
261 | $view->data['view'] = $this->createMediaView($media->source, $request, $response); |
262 | } else { |
263 | $view->data['view'] = $this->createMediaView($media, $request, $response); |
264 | } |
265 | } |
266 | } |
267 | |
268 | $view->data['account'] = $this->app->accountManager->get($request->header->account); |
269 | $view->data['media'] = $media; |
270 | |
271 | return $view; |
272 | } |
273 | |
274 | /** |
275 | * Create media view |
276 | * |
277 | * @param Media $media Media |
278 | * |
279 | * @return View |
280 | * |
281 | * @since 1.0.0 |
282 | */ |
283 | private function createMediaView(Media $media, RequestAbstract $request, ResponseAbstract $response) : View |
284 | { |
285 | $view = new ElementView($this->app->l11nManager, $request, $response); |
286 | |
287 | if ($media->hasPassword() |
288 | && !$media->comparePassword((string) $request->getData('password')) |
289 | ) { |
290 | $view->setTemplate('/Modules/Media/Theme/Backend/Components/Media/invalidPassword'); |
291 | |
292 | return $view; |
293 | } |
294 | |
295 | if ($media->isEncrypted) { |
296 | $media = $this->app->moduleManager->get('Media', 'Api')->prepareEncryptedMedia($media, $request); |
297 | |
298 | if ($media->id === 0) { |
299 | $view->setTemplate('/Modules/Media/Theme/Backend/Components/Media/invalidPassword'); |
300 | |
301 | return $view; |
302 | } |
303 | } |
304 | |
305 | switch (\strtolower($media->extension)) { |
306 | case 'pdf': |
307 | $view->setTemplate('/Modules/Media/Theme/Backend/Components/Media/pdf'); |
308 | break; |
309 | case 'c': |
310 | case 'cpp': |
311 | case 'h': |
312 | case 'php': |
313 | case 'js': |
314 | case 'css': |
315 | case 'rs': |
316 | case 'py': |
317 | case 'r': |
318 | $view->setTemplate('/Modules/Media/Theme/Backend/Components/Media/text'); |
319 | break; |
320 | case 'txt': |
321 | case 'cfg': |
322 | case 'log': |
323 | $view->setTemplate('/Modules/Media/Theme/Backend/Components/Media/text'); |
324 | break; |
325 | case 'md': |
326 | $view->setTemplate('/Modules/Media/Theme/Backend/Components/Media/markdown'); |
327 | break; |
328 | case 'csv': |
329 | $view->setTemplate('/Modules/Media/Theme/Backend/Components/Media/csv'); |
330 | break; |
331 | case 'xls': |
332 | case 'xlsx': |
333 | $view->setTemplate('/Modules/Media/Theme/Backend/Components/Media/spreadsheet'); |
334 | break; |
335 | case 'doc': |
336 | case 'docx': |
337 | $view->setTemplate('/Modules/Media/Theme/Backend/Components/Media/word'); |
338 | break; |
339 | case 'ppt': |
340 | case 'pptx': |
341 | $view->setTemplate('/Modules/Media/Theme/Backend/Components/Media/powerpoint'); |
342 | break; |
343 | case 'json': |
344 | $view->setTemplate('/Modules/Media/Theme/Backend/Components/Media/json'); |
345 | break; |
346 | case 'jpg': |
347 | case 'jpeg': |
348 | case 'gif': |
349 | case 'png': |
350 | $view->setTemplate('/Modules/Media/Theme/Backend/Components/Media/image'); |
351 | break; |
352 | case 'mp3': |
353 | $view->setTemplate('/Modules/Media/Theme/Backend/Components/Media/audio'); |
354 | break; |
355 | case 'mp4': |
356 | case 'mpeg': |
357 | $view->setTemplate('/Modules/Media/Theme/Backend/Components/Media/video'); |
358 | break; |
359 | case 'zip': |
360 | $view->setTemplate('/Modules/Media/Theme/Backend/Components/Media/archive'); |
361 | break; |
362 | default: |
363 | $view->setTemplate('/Modules/Media/Theme/Backend/Components/Media/default'); |
364 | } |
365 | |
366 | return $view; |
367 | } |
368 | |
369 | /** |
370 | * Routing end-point for application behaviour. |
371 | * |
372 | * @param RequestAbstract $request Request |
373 | * @param ResponseAbstract $response Response |
374 | * @param array $data Generic data |
375 | * |
376 | * @return RenderableInterface |
377 | * |
378 | * @since 1.0.0 |
379 | * @codeCoverageIgnore |
380 | */ |
381 | public function viewModuleSettings(RequestAbstract $request, ResponseAbstract $response, array $data = []) : RenderableInterface |
382 | { |
383 | $view = new View($this->app->l11nManager, $request, $response); |
384 | $view->data['nav'] = $this->app->moduleManager->get('Navigation')->createNavigationMid(1000105001, $request, $response); |
385 | |
386 | $id = $request->getDataString('id') ?? ''; |
387 | |
388 | $settings = SettingMapper::getAll()->where('module', $id)->execute(); |
389 | $view->data['settings'] = $settings; |
390 | |
391 | $types = MediaTypeMapper::getAll()->with('title')->where('title/language', $response->header->l11n->language)->execute(); |
392 | $view->data['types'] = $types; |
393 | |
394 | $view->setTemplate('/Modules/' . static::NAME . '/Admin/Settings/Theme/Backend/settings'); |
395 | |
396 | return $view; |
397 | } |
398 | |
399 | /** |
400 | * Routing end-point for application behaviour. |
401 | * |
402 | * @param RequestAbstract $request Request |
403 | * @param ResponseAbstract $response Response |
404 | * @param array $data Generic data |
405 | * |
406 | * @return RenderableInterface |
407 | * |
408 | * @since 1.0.0 |
409 | * @codeCoverageIgnore |
410 | */ |
411 | public function viewMediaTypeSettings(RequestAbstract $request, ResponseAbstract $response, array $data = []) : RenderableInterface |
412 | { |
413 | $view = new View($this->app->l11nManager, $request, $response); |
414 | $view->setTemplate('/Modules/' . static::NAME . '/Admin/Settings/Theme/Backend/settings-type'); |
415 | |
416 | /** @var \phpOMS\Localization\BaseStringL11n $type */ |
417 | $type = MediaTypeMapper::get() |
418 | ->with('title') |
419 | ->where('title/language', $response->header->l11n->language) |
420 | ->where('id', (int) $request->getData('id')) |
421 | ->execute(); |
422 | |
423 | $view->data['nav'] = $this->app->moduleManager->get('Navigation')->createNavigationMid(1007501001, $request, $response); |
424 | $view->data['type'] = $type; |
425 | |
426 | $l11n = MediaTypeL11nMapper::getAll()->where('type', $type->id)->execute(); |
427 | $view->data['l11n'] = $l11n; |
428 | |
429 | return $view; |
430 | } |
431 | |
432 | /** |
433 | * Routing end-point for application behaviour. |
434 | * |
435 | * @param RequestAbstract $request Request |
436 | * @param ResponseAbstract $response Response |
437 | * @param array $data Generic data |
438 | * |
439 | * @return RenderableInterface |
440 | * |
441 | * @since 1.0.0 |
442 | * @codeCoverageIgnore |
443 | */ |
444 | public function viewMediaUpload(RequestAbstract $request, ResponseAbstract $response, array $data = []) : RenderableInterface |
445 | { |
446 | $view = new View($this->app->l11nManager, $request, $response); |
447 | $view->setTemplate('/Modules/Media/Theme/Backend/media-upload'); |
448 | |
449 | return $view; |
450 | } |
451 | |
452 | /** |
453 | * Routing end-point for application behaviour. |
454 | * |
455 | * @param RequestAbstract $request Request |
456 | * @param ResponseAbstract $response Response |
457 | * @param array $data Generic data |
458 | * |
459 | * @return RenderableInterface |
460 | * |
461 | * @since 1.0.0 |
462 | * @codeCoverageIgnore |
463 | */ |
464 | public function viewMediaFileCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : RenderableInterface |
465 | { |
466 | $view = new View($this->app->l11nManager, $request, $response); |
467 | $view->setTemplate('/Modules/Media/Theme/Backend/media-file-create'); |
468 | |
469 | $editor = new \Modules\Editor\Theme\Backend\Components\Editor\BaseView($this->app->l11nManager, $request, $response); |
470 | $view->data['editor'] = $editor; |
471 | |
472 | return $view; |
473 | } |
474 | |
475 | /** |
476 | * Routing end-point for application behaviour. |
477 | * |
478 | * @param RequestAbstract $request Request |
479 | * @param ResponseAbstract $response Response |
480 | * @param array $data Generic data |
481 | * |
482 | * @return RenderableInterface |
483 | * |
484 | * @since 1.0.0 |
485 | * @codeCoverageIgnore |
486 | */ |
487 | public function viewMediaCollectionCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : RenderableInterface |
488 | { |
489 | $view = new View($this->app->l11nManager, $request, $response); |
490 | $view->setTemplate('/Modules/Media/Theme/Backend/media-collection-create'); |
491 | |
492 | return $view; |
493 | } |
494 | } |