Passed
Push — develop ( 86ea71...c4fa00 )
by Florian
03:58
created

FileStorage::runCallbacks()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2.032

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 4
nc 2
nop 2
dl 0
loc 9
c 1
b 0
f 0
cc 2
ccs 4
cts 5
cp 0.8
crap 2.032
rs 10
1
<?php
2
3
/**
4
 * Copyright (c) Florian Krämer (https://florian-kraemer.net)
5
 * Licensed under The MIT License
6
 * For full copyright and license information, please see the LICENSE.txt
7
 * Redistributions of files must retain the above copyright notice.
8
 *
9
 * @copyright Copyright (c) Florian Krämer (https://florian-kraemer.net)
10
 * @author    Florian Krämer
11
 * @link      https://github.com/Phauthentic
12
 * @license   https://opensource.org/licenses/MIT MIT License
13
 */
14
15
declare(strict_types=1);
16
17
namespace Phauthentic\Infrastructure\Storage;
18
19
use InvalidArgumentException;
20
use League\Flysystem\AdapterInterface;
21
use League\Flysystem\Config;
22
use Phauthentic\Infrastructure\Storage\PathBuilder\PathBuilderInterface;
23
use Phauthentic\Infrastructure\Storage\Processor\Exception\VariantDoesNotExistException;
24
use Phauthentic\Infrastructure\Storage\Processor\Exception\VariantException;
25
use Phauthentic\Infrastructure\Storage\UrlBuilder\UrlBuilderInterface;
26
use RuntimeException;
27
28
/**
29
 * File Storage
30
 */
31
class FileStorage implements FileStorageInterface
32
{
33
    /**
34
     * @var array
35
     */
36
    protected array $callbacks = [
37
        'beforeSave' => [],
38
        'afterSave' => [],
39
        'beforeRemove' => [],
40
        'afterRemove' => [],
41
    ];
42
43
    /**
44
     * @var \Phauthentic\Infrastructure\Storage\PathBuilder\PathBuilderInterface|null
45
     */
46
    protected ?PathBuilderInterface $pathBuilder;
47
48
    /**
49
     * @var \Phauthentic\Infrastructure\Storage\UrlBuilder\UrlBuilderInterface|null
50
     */
51
    protected ?UrlBuilderInterface $urlBuilder;
52
53
    /**
54
     * @var \Phauthentic\Infrastructure\Storage\StorageServiceInterface
55
     */
56
    protected StorageServiceInterface $storageService;
57
58
    /**
59
     * Constructor
60
     *
61
     * @param \Phauthentic\Infrastructure\Storage\StorageServiceInterface $storageService Storage Service
62
     * @param \Phauthentic\Infrastructure\Storage\PathBuilder\PathBuilderInterface|null $pathBuilder Path Builder
63
     * @param \Phauthentic\Infrastructure\Storage\UrlBuilder\UrlBuilderInterface|null $urlBuilder Path Builder
64
     */
65 1
    public function __construct(
66
        StorageServiceInterface $storageService,
67
        ?PathBuilderInterface $pathBuilder = null,
68
        ?UrlBuilderInterface $urlBuilder = null
69
    ) {
70 1
        $this->storageService = $storageService;
71 1
        $this->pathBuilder = $pathBuilder;
72 1
        $this->urlBuilder = $urlBuilder;
73 1
    }
74
75
    /**
76
     * @param string $name Name of the callback
77
     * @return void
78
     */
79 1
    protected function checkCallbackName(string $name): void
80
    {
81 1
        if (!array_key_exists($name, $this->callbacks)) {
82
            throw new InvalidArgumentException(sprintf(
83
                'Invalid callback `%s`, only %s are valid',
84
                $name,
85
                implode(', ', array_keys($this->callbacks))
86
            ));
87
        }
88 1
    }
89
90
    /**
91
     * Adds a callback
92
     *
93
     * @param string $name
94
     * @param callable $callable Callable
95
     * @return void
96
     */
97
    public function addCallback($name, callable $callable): void
98
    {
99
        $this->checkCallbackName($name);
100
        $this->callbacks[$name][] = $callable;
101
    }
102
103
    /**
104
     * @param string $name Name of the callback
105
     * @param \Phauthentic\Infrastructure\Storage\FileInterface $file File
106
     * @return \Phauthentic\Infrastructure\Storage\FileInterface
107
     */
108 1
    public function runCallbacks(string $name, FileInterface $file): FileInterface
109
    {
110 1
        $this->checkCallbackName($name);
111
112 1
        foreach ($this->callbacks[$name] as $callback) {
113
            $file = $callback($file);
114
        }
115
116 1
        return $file;
117
    }
118
119
    /**
120
     * @inheritDoc
121
     * @throws \RuntimeException
122
     */
123 1
    public function store(FileInterface $file, ?Config $config = null): FileInterface
124
    {
125 1
        if ($config === null) {
126 1
            $config = new Config();
127
        }
128
129 1
        if ($this->pathBuilder !== null) {
130 1
            $file = $file->buildPath($this->pathBuilder);
131
        }
132
133 1
        if ($this->urlBuilder !== null) {
134
            $file = $file->buildUrl($this->urlBuilder);
135
        }
136
137 1
        $file = $this->runCallbacks('beforeSave', $file);
138
139 1
        $storage = $this->getStorage($file->storage());
140 1
        $resource = $file->resource();
141 1
        if ($resource === null) {
142
            throw new RuntimeException('No resource given');
143
        }
144 1
        $storage->writeStream($file->path(), $resource, $config);
145
146 1
        return $this->runCallbacks('afterSave', $file);
147
    }
148
149
    /**
150
     * @inheritDoc
151
     */
152 1
    public function remove(FileInterface $file): FileInterface
153
    {
154 1
        $file = $this->runCallbacks('beforeRemove', $file);
155
156
        // Delete all variants of the file
157 1
        foreach ($file->variants() as $variant) {
158
            if (!empty($variant['path'])) {
159
                $this->getStorage($file->storage())->delete($variant['path']);
160
            }
161
        }
162
163
        // Delete the file
164 1
        $this->getStorage($file->storage())->delete($file->path());
165
166 1
        return $this->runCallbacks('afterRemove', $file);
167
    }
168
169
    /**
170
     * @inheritDoc
171
     */
172
    public function removeVariant(FileInterface $file, string $name): FileInterface
173
    {
174
        if (!$file->hasVariant($name)) {
175
            throw VariantDoesNotExistException::withName($name);
176
        }
177
178
        $variant = $file->variant($name);
179
        if (empty($variant['path'])) {
180
            throw new VariantException(sprintf(
181
                'Variant `%s` is missing a path',
182
                $name
183
            ));
184
        }
185
186
        $this->getStorage($file->storage())->delete($variant['path']);
187
188
        $variants = $file->variants();
189
        unset($variants[$name]);
190
191
        return $file->withVariants($variants, false);
192
    }
193
194
    /**
195
     * Gets the storage abstraction to use
196
     *
197
     * @param string $storage Storage name to use
198
     * @return \League\Flysystem\AdapterInterface
199
     */
200 1
    public function getStorage(string $storage): AdapterInterface
201
    {
202 1
        return $this->storageService->adapter($storage);
203
    }
204
}
205