Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 40
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
CollectionMapper
0.00% covered (danger)
0.00%
0 / 40
0.00% covered (danger)
0.00%
0 / 2
272
0.00% covered (danger)
0.00%
0 / 1
 getByVirtualPath
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 getCollectionsByPath
0.00% covered (danger)
0.00%
0 / 34
0.00% covered (danger)
0.00%
0 / 1
240
1<?php
2/**
3 * Jingga
4 *
5 * PHP Version 8.1
6 *
7 * @package   Modules\Media\Models
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\Models;
16
17use Modules\Admin\Models\Account;
18use phpOMS\DataStorage\Database\Mapper\ReadMapper;
19
20/**
21 * Mapper class.
22 *
23 * @package Modules\Media\Models
24 * @license OMS License 2.0
25 * @link    https://jingga.app
26 * @since   1.0.0
27 *
28 * @template T of Collection
29 * @extends MediaMapper<T>
30 */
31final class CollectionMapper extends MediaMapper
32{
33    /**
34     * Has many relation.
35     *
36     * @var array<string, array{mapper:class-string, table:string, self?:?string, external?:?string, column?:string}>
37     * @since 1.0.0
38     */
39    public const HAS_MANY = [
40        'sources' => [
41            'mapper'   => MediaMapper::class,
42            'table'    => 'media_relation',
43            'external' => 'media_relation_src',
44            'self'     => 'media_relation_dst',
45        ],
46    ];
47
48    /**
49     * Model to use by the mapper.
50     *
51     * @var class-string<T>
52     * @since 1.0.0
53     */
54    public const MODEL = Collection::class;
55
56    /**
57     * Get media based on virtual path.
58     *
59     * The virtual path is equivalent to the directory path on a file system.
60     *
61     * A media model also has a file path, this however doesn't have to be the same as the virtual path
62     * and in fact most of the time it is different. This is because the location on a hard drive or web
63     * drive should not have any impact on the media file/media structure in the application.
64     *
65     * As a result media files are structured by virutal path in the app, by file path on the file system
66     * and by Collections which can have sub-collections as well. Collections allow to reference files
67     * in a different virtual path and are therfore similar to "symlinks", except that they don't reference
68     * a file but create a new virtual media model which groups other media models together in a new virtual
69     * path if so desired without deleting or moving the orginal media files.
70     *
71     * @param string $virtualPath Virtual path
72     * @param int    $status      Media status
73     *
74     * @return ReadMapper
75     *
76     * @since 1.0.0
77     */
78    public static function getByVirtualPath(string $virtualPath = '/', int $status = MediaStatus::NORMAL) : ReadMapper
79    {
80        return self::getAll()
81            ->where('virtualPath', $virtualPath)
82            ->with('createdBy')
83            ->with('tags')
84            ->where('status', $status)
85            ->where('class', MediaClass::COLLECTION);
86    }
87
88    /**
89     * Get collections and optionally hard drive directories.
90     *
91     * @param string $virtualPath     Virtual path
92     * @param bool   $showDirectories Show local hard drive directories
93     *
94     * @return array
95     *
96     * @since 1.0.0
97     */
98    public static function getCollectionsByPath(string $virtualPath, bool $showDirectories = false) : array
99    {
100        /** @var Media[] $collection */
101        $collection = self::getByVirtualPath($virtualPath)->with('sources')->execute();
102        $parent     = [];
103
104        if ($showDirectories) {
105            $parent = self::getParentCollection($virtualPath)->execute();
106            if (\is_array($parent) && \is_dir(__DIR__ . '/../../Media/Files' . $virtualPath)) {
107                $parent       = new Collection();
108                $parent->name = \basename($virtualPath);
109                $parent->setVirtualPath(\dirname($virtualPath));
110                $parent->setPath(\dirname($virtualPath));
111                $parent->isAbsolute = false;
112            }
113
114            if ($parent instanceof Collection) {
115                $collection += $parent->getSources();
116
117                /** @var string[] $glob */
118                $glob = $parent->isAbsolute
119                    ? $parent->getPath() . '/' . $parent->name . '/*'
120                    : \glob(__DIR__ . '/../Files/' . \rtrim($parent->getPath(), '/') . '/' . $parent->name . '/*');
121                $glob = $glob === false ? [] : $glob;
122
123                foreach ($glob as $file) {
124                    if (!\is_dir($file)) {
125                        continue;
126                    }
127
128                    foreach ($collection as $obj) {
129                        if (($obj->extension !== 'collection'
130                                && !empty($obj->extension)
131                                && $obj->name . '.' . $obj->extension === \basename($file))
132                            || ($obj->extension === 'collection'
133                                && $obj->name === \basename($file))
134                        ) {
135                            continue 2;
136                        }
137                    }
138
139                    $pathinfo = \pathinfo($file);
140
141                    $localMedia            = new Collection();
142                    $localMedia->name      = $pathinfo['filename'];
143                    $localMedia->extension = $pathinfo['extension'] ?? '';
144                    $localMedia->setVirtualPath($virtualPath);
145                    $localMedia->createdBy = new Account();
146
147                    $collection[] = $localMedia;
148                }
149            }
150        }
151
152        return [$collection, $parent];
153    }
154}