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 */
13declare(strict_types=1);
14
15namespace Modules\Media\Controller;
16
17use Model\SettingMapper;
18use Modules\Admin\Models\Account;
19use Modules\Admin\Models\PermissionAbstractMapper;
20use Modules\Media\Models\Collection;
21use Modules\Media\Models\CollectionMapper;
22use Modules\Media\Models\Media;
23use Modules\Media\Models\MediaClass;
24use Modules\Media\Models\MediaMapper;
25use Modules\Media\Models\MediaTypeL11nMapper;
26use Modules\Media\Models\MediaTypeMapper;
27use Modules\Media\Models\NullMedia;
28use Modules\Media\Models\PermissionCategory;
29use Modules\Media\Theme\Backend\Components\Media\ElementView;
30use Modules\Media\Theme\Backend\Components\Media\ListView;
31use Modules\Media\Views\MediaView;
32use phpOMS\Account\PermissionType;
33use phpOMS\Contract\RenderableInterface;
34use phpOMS\Message\RequestAbstract;
35use phpOMS\Message\ResponseAbstract;
36use phpOMS\Utils\StringUtils;
37use 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 */
48final 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}