Passed
Branch feature/2.1-geodispersion-dev (1d61a8)
by Jonathan
61:21
created

CertificateFilesystemService::filesystem()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 5
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 9
rs 10
1
<?php
2
3
/**
4
 * webtrees-lib: MyArtJaub library for webtrees
5
 *
6
 * @package MyArtJaub\Webtrees
7
 * @subpackage Certificates
8
 * @author Jonathan Jaubart <[email protected]>
9
 * @copyright Copyright (c) 2021, Jonathan Jaubart
10
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3
11
 */
12
13
declare(strict_types=1);
14
15
namespace MyArtJaub\Webtrees\Module\Certificates\Services;
16
17
use Fisharebest\Flysystem\Adapter\ChrootAdapter;
18
use Fisharebest\Webtrees\Registry;
19
use Fisharebest\Webtrees\Tree;
20
use Illuminate\Support\Collection;
21
use League\Flysystem\Filesystem;
22
use League\Flysystem\FilesystemException;
23
use League\Flysystem\FilesystemOperator;
24
use League\Flysystem\StorageAttributes;
25
use League\Flysystem\UnableToRetrieveMetadata;
26
use MyArtJaub\Webtrees\Module\Certificates\Factories\CertificateImageFactory;
27
use MyArtJaub\Webtrees\Module\Certificates\Model\Certificate;
28
29
/**
30
 * Service for accessing certificates on the file system..
31
 */
32
class CertificateFilesystemService
33
{
34
    /**
35
     * @var array<int,FilesystemOperator> $filesystem
36
     */
37
    private $filesystem = [];
38
39
    /**
40
     * Get the filesystem containing certificates for a tree.
41
     *
42
     * @param Tree $tree
43
     * @return FilesystemOperator
44
     */
45
    public function filesystem(Tree $tree): FilesystemOperator
46
    {
47
        if (!isset($this->filesystem[$tree->id()])) {
48
            $cert_dir = $tree->getPreference('MAJ_CERTIF_ROOTDIR', 'certificates/');
49
            $adapter   = new ChrootAdapter(Registry::filesystem()->data(), $cert_dir);
50
51
            $this->filesystem[$tree->id()] = new FileSystem($adapter);
52
        }
53
        return $this->filesystem[$tree->id()];
54
    }
55
56
    /**
57
     * Set the filesystem containing certificates for a tree.
58
     *
59
     * @param Tree $tree
60
     * @param FilesystemOperator $filesystem
61
     */
62
    public function setFilesystem(Tree $tree, FilesystemOperator $filesystem): void
63
    {
64
        $this->filesystem[$tree->id()] = $filesystem;
65
    }
66
67
    /**
68
     * Create the Certificate object defined by a path on the filesystem.
69
     *
70
     * @param Tree $tree
71
     * @param string $path
72
     * @return Certificate|NULL
73
     */
74
    public function certificate(Tree $tree, string $path): ?Certificate
75
    {
76
        $filesystem = $this->filesystem($tree);
77
        if ($filesystem->fileExists($path) && $this->isFileSupported($filesystem, $path)) {
78
            return new Certificate($tree, $path);
79
        }
80
        return null;
81
    }
82
83
    /**
84
     * Get the cities (first-level folder) available in a the filesystem.
85
     *
86
     * @param Tree $tree
87
     * @return string[]
88
     */
89
    public function cities(Tree $tree): array
90
    {
91
        return $this->filesystem($tree)
92
            ->listContents('')
93
            ->filter(function (StorageAttributes $attributes): bool {
94
                return $attributes->isDir();
95
            })->map(function (StorageAttributes $attributes): string {
96
                return $attributes->path();
97
            })->toArray();
98
    }
99
100
    /**
101
     * Get the certificates available for a city (first-level folder).
102
     *
103
     * @param Tree $tree
104
     * @param string $city
105
     * @return Collection<Certificate>
106
     */
107
    public function certificatesForCity(Tree $tree, string $city): Collection
108
    {
109
        $filesystem = $this->filesystem($tree);
110
        $certificate_paths = collect($filesystem
111
            ->listContents($city)
112
            ->filter(function (StorageAttributes $attributes) use ($filesystem): bool {
113
                return $attributes->isFile() && $this->isFileSupported($filesystem, $attributes->path());
114
            })->map(function (StorageAttributes $attributes): string {
115
                return $attributes->path();
116
            })->toArray());
117
118
        return $certificate_paths->map(function (string $path) use ($tree): Certificate {
119
            return new Certificate($tree, $path);
120
        });
121
    }
122
123
    /**
124
     * Get the certificates available for a city (first-level folder), containing a specified text.
125
     *
126
     * @param Tree $tree
127
     * @param string $city
128
     * @param string $contains
129
     * @return Collection<Certificate>
130
     */
131
    public function certificatesForCityContaining(Tree $tree, string $city, string $contains): Collection
132
    {
133
        $filesystem = $this->filesystem($tree);
134
        $certificate_paths = collect($filesystem
135
            ->listContents($city)
136
            ->filter(function (StorageAttributes $attributes) use ($filesystem, $contains): bool {
137
                return $attributes->isFile() && $this->isFileSupported($filesystem, $attributes->path())
138
                    && mb_stripos($attributes->path(), $contains) !== false;
139
            })->map(function (StorageAttributes $attributes): string {
140
                return $attributes->path();
141
            })->toArray());
142
143
        return $certificate_paths->map(function (string $path) use ($tree): Certificate {
144
            return new Certificate($tree, $path);
145
        });
146
    }
147
148
    /**
149
     * Check if a file on the filesystem is supported by the certificate module.
150
     *
151
     * @param FilesystemOperator $filesystem
152
     * @param string $path
153
     * @return bool
154
     */
155
    protected function isFileSupported(FilesystemOperator $filesystem, string $path): bool
156
    {
157
        try {
158
            $mime = $filesystem->mimeType($path);
159
            return Registry::cache()->array()->remember(
160
                'maj-certif-supportedfiles-' . $mime,
161
                function () use ($mime): bool {
162
                    return app(CertificateImageFactory::class)->isMimeTypeSupported($mime);
163
                }
164
            );
165
        } catch (UnableToRetrieveMetadata | FilesystemException $ex) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
166
        }
167
        return false;
168
    }
169
}
170