CertificateFilesystemService   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 126
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 43
dl 0
loc 126
rs 10
c 0
b 0
f 0
wmc 14

7 Methods

Rating   Name   Duplication   Size   Complexity  
A filesystem() 0 9 2
A setFilesystem() 0 3 1
A certificate() 0 7 3
A certificatesForCityContaining() 0 11 3
A cities() 0 9 1
A isFileSupported() 0 11 2
A certificatesForCity() 0 10 2
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-2022, 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\I18N;
19
use Fisharebest\Webtrees\Registry;
20
use Fisharebest\Webtrees\Tree;
21
use Illuminate\Support\Collection;
22
use League\Flysystem\Filesystem;
23
use League\Flysystem\FilesystemException;
24
use League\Flysystem\FilesystemOperator;
25
use League\Flysystem\StorageAttributes;
26
use League\Flysystem\UnableToRetrieveMetadata;
27
use MyArtJaub\Webtrees\Module\Certificates\Factories\CertificateImageFactory;
28
use MyArtJaub\Webtrees\Module\Certificates\Model\Certificate;
29
30
/**
31
 * Service for accessing certificates on the file system..
32
 */
33
class CertificateFilesystemService
34
{
35
    /**
36
     * @var array<int,FilesystemOperator> $filesystem
37
     */
38
    private array $filesystem = [];
39
40
    /**
41
     * Get the filesystem containing certificates for a tree.
42
     *
43
     * @param Tree $tree
44
     * @return FilesystemOperator
45
     */
46
    public function filesystem(Tree $tree): FilesystemOperator
47
    {
48
        if (!isset($this->filesystem[$tree->id()])) {
49
            $cert_dir = $tree->getPreference('MAJ_CERTIF_ROOTDIR', 'certificates/');
50
            $adapter   = new ChrootAdapter(Registry::filesystem()->data(), $cert_dir);
51
52
            $this->filesystem[$tree->id()] = new FileSystem($adapter);
53
        }
54
        return $this->filesystem[$tree->id()];
55
    }
56
57
    /**
58
     * Set the filesystem containing certificates for a tree.
59
     *
60
     * @param Tree $tree
61
     * @param FilesystemOperator $filesystem
62
     */
63
    public function setFilesystem(Tree $tree, FilesystemOperator $filesystem): void
64
    {
65
        $this->filesystem[$tree->id()] = $filesystem;
66
    }
67
68
    /**
69
     * Create the Certificate object defined by a path on the filesystem.
70
     *
71
     * @param Tree $tree
72
     * @param string $path
73
     * @return Certificate|NULL
74
     */
75
    public function certificate(Tree $tree, string $path): ?Certificate
76
    {
77
        $filesystem = $this->filesystem($tree);
78
        if ($filesystem->fileExists($path) && $this->isFileSupported($filesystem, $path)) {
79
            return new Certificate($tree, $path);
80
        }
81
        return null;
82
    }
83
84
    /**
85
     * Get the cities (first-level folder) available in a the filesystem.
86
     *
87
     * @param Tree $tree
88
     * @return string[]
89
     */
90
    public function cities(Tree $tree): array
91
    {
92
        $cities =  $this->filesystem($tree)
93
            ->listContents('')
94
            ->filter(fn (StorageAttributes $attributes): bool => $attributes->isDir())
95
            ->map(fn (StorageAttributes $attributes): string => $attributes->path())
96
            ->toArray();
97
        usort($cities, I18N::comparator());
98
        return $cities;
99
    }
100
101
    /**
102
     * Get the certificates available for a city (first-level folder).
103
     *
104
     * @param Tree $tree
105
     * @param string $city
106
     * @return Collection<Certificate>
107
     */
108
    public function certificatesForCity(Tree $tree, string $city): Collection
109
    {
110
        $filesystem = $this->filesystem($tree);
111
        $certificates_paths = $filesystem->listContents($city)
112
            ->filter(fn (StorageAttributes $attributes): bool  =>
113
                $attributes->isFile() && $this->isFileSupported($filesystem, $attributes->path()))
114
            ->map(fn (StorageAttributes $attributes): string => $attributes->path())
115
            ->toArray();
116
        usort($certificates_paths, I18N::comparator());
117
        return collect($certificates_paths)->map(fn (string $path): Certificate => new Certificate($tree, $path));
118
    }
119
120
    /**
121
     * Get the certificates available for a city (first-level folder), containing a specified text.
122
     *
123
     * @param Tree $tree
124
     * @param string $city
125
     * @param string $contains
126
     * @return Collection<Certificate>
127
     */
128
    public function certificatesForCityContaining(Tree $tree, string $city, string $contains): Collection
129
    {
130
        $filesystem = $this->filesystem($tree);
131
        $certificates_paths = $filesystem->listContents($city)
132
            ->filter(fn (StorageAttributes $attributes): bool  =>
133
                $attributes->isFile() && $this->isFileSupported($filesystem, $attributes->path())
134
                && mb_stripos($attributes->path(), $contains) !== false)
135
            ->map(fn (StorageAttributes $attributes): string => $attributes->path())
136
            ->toArray();
137
        usort($certificates_paths, I18N::comparator());
138
        return collect($certificates_paths)->map(fn (string $path): Certificate => new Certificate($tree, $path));
139
    }
140
141
    /**
142
     * Check if a file on the filesystem is supported by the certificate module.
143
     *
144
     * @param FilesystemOperator $filesystem
145
     * @param string $path
146
     * @return bool
147
     */
148
    protected function isFileSupported(FilesystemOperator $filesystem, string $path): bool
149
    {
150
        try {
151
            $mime = $filesystem->mimeType($path);
152
            return Registry::cache()->array()->remember(
0 ignored issues
show
Bug Best Practice introduced by
The expression return Fisharebest\Webtr...ion(...) { /* ... */ }) returns the type Fisharebest\Webtrees\T which is incompatible with the type-hinted return boolean.
Loading history...
153
                'maj-certif-supportedfiles-' . $mime,
154
                fn (): bool => app(CertificateImageFactory::class)->isMimeTypeSupported($mime)
155
            );
156
        } 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...
157
        }
158
        return false;
159
    }
160
}
161