Saver::save()   B
last analyzed

Complexity

Conditions 7
Paths 5

Size

Total Lines 37
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 10.1359

Importance

Changes 0
Metric Value
cc 7
eloc 19
nc 5
nop 1
dl 0
loc 37
ccs 12
cts 20
cp 0.6
crap 10.1359
rs 8.8333
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace tkanstantsin\fileupload\saver;
5
6
use League\Flysystem\FilesystemInterface;
7
use tkanstantsin\fileupload\config\InvalidConfigException;
8
use tkanstantsin\fileupload\formatter\File;
9
use tkanstantsin\fileupload\model\IFile;
10
11
/**
12
 * Class Saver allows store processed files.
13
 * E.g. store uploaded files or cache cropped/prepared images.
14
 *
15
 * @todo add option to force rewriting existed file.
16
 */
17
class Saver
18
{
19
    /**
20
     * @var IFile
21
     */
22
    public $file;
23
    /**
24
     * Filesystem where file will be stored
25
     * @var FilesystemInterface
26
     */
27
    public $filesystem;
28
    /**
29
     * File path in $filesystem
30
     * @var string
31
     */
32
    public $path;
33
34
    /**
35
     * Saver constructor.
36
     * @param IFile $file
37
     * @param FilesystemInterface $filesystem
38
     * @param string $path
39
     * @throws InvalidConfigException
40
     */
41 1
    public function __construct(IFile $file, FilesystemInterface $filesystem, string $path)
42
    {
43 1
        $this->file = $file;
44 1
        $this->filesystem = $filesystem;
45 1
        $this->path = $path;
46
47 1
        if ($this->path === '') {
48
            throw new InvalidConfigException('Saver path must be not empty');
49
        }
50 1
    }
51
52
    /**
53
     * Copies, processes and saves file in $filesystem
54
     * @param \tkanstantsin\fileupload\formatter\File $formatter
55
     * @return bool
56
     * @throws \InvalidArgumentException
57
     * @throws \League\Flysystem\FileNotFoundException
58
     */
59 1
    public function save(File $formatter): bool
60
    {
61 1
        $isCached = $this->isSaved();
62 1
        $isEmpty = $this->isEmpty();
63 1
        if ($isCached && !$isEmpty) {
64
            $formatter->triggerEvent(File::EVENT_CACHED);
65
66
            return true;
67
        }
68 1
        if ($isEmpty) {
69
            $formatter->triggerEvent(File::EVENT_EMPTY);
70
71
            return false;
72
        }
73
74
        // checks if path is writable
75
        // create new empty file or override existed one
76
        // also caches empty result for non-formatted files
77 1
        $this->filesystem->put($this->path, null);
78
79 1
        $content = $formatter->getContent();
80 1
        if ($content === false) {
81
            $formatter->triggerEvent(File::EVENT_NOT_FOUND);
82
83
            return false;
84
        }
85 1
        if ($content === '') {
86
            $formatter->triggerEvent(File::EVENT_ERROR);
87
88
            return false;
89
        }
90
91 1
        $saved = $this->write($content);
92
93 1
        $formatter->triggerEvent($saved ? File::EVENT_CACHED : File::EVENT_ERROR);
94
95 1
        return $saved;
96
    }
97
98
    /**
99
     * @return bool
100
     * @throws \League\Flysystem\FileNotFoundException
101
     */
102 1
    protected function isEmpty(): bool
103
    {
104 1
        return $this->filesystem->has($this->path)
105 1
            && $this->filesystem->getSize($this->path) === 0;
106
    }
107
108
    /**
109
     * Checks if file is already in $path.
110
     * @return bool
111
     * @throws \League\Flysystem\FileNotFoundException
112
     */
113 1
    protected function isSaved(): bool
114
    {
115 1
        return $this->filesystem->has($this->path)
116 1
            && $this->filesystem->getTimestamp($this->path) > $this->file->getUpdatedAt();
117
    }
118
119
    /**
120
     * Saves file into $filesystem
121
     * @param $content
122
     * @return bool
123
     * @throws \InvalidArgumentException
124
     */
125 1
    protected function write($content): bool
126
    {
127 1
        if ($content === false || $content === null) {
128
            return false;
129
        }
130
131 1
        return \is_resource($content)
132
            ? $this->filesystem->putStream($this->path, $content)
133 1
            : $this->filesystem->put($this->path, $content);
134
    }
135
}