Passed
Push — master ( 49221b...48dfef )
by Petr
08:52 queued 06:24
created

ProcessFile::saveFile()   B

Complexity

Conditions 10
Paths 49

Size

Total Lines 47
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 10.1953

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 10
eloc 27
c 2
b 0
f 0
nc 49
nop 4
dl 0
loc 47
ccs 21
cts 24
cp 0.875
crap 10.1953
rs 7.6666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace kalanis\kw_files\Processing\Volume;
4
5
6
use kalanis\kw_files\FilesException;
7
use kalanis\kw_files\Interfaces;
8
use kalanis\kw_files\Processing\TPath;
9
use kalanis\kw_files\Traits\TCheckModes;
10
use kalanis\kw_files\Traits\TLang;
11
use kalanis\kw_paths\Extras\TPathTransform;
12
use kalanis\kw_paths\PathsException;
13
use Throwable;
14
15
16
/**
17
 * Class ProcessFile
18
 * @package kalanis\kw_files\Processing\Volume
19
 * Process files in many ways
20
 */
21
class ProcessFile implements Interfaces\IProcessFiles, Interfaces\IProcessFileStreams
22
{
23
    use TCheckModes;
24
    use TLang;
25
    use TPath;
26
    use TPathTransform;
27
28 20
    public function __construct(string $path = '', ?Interfaces\IFLTranslations $lang = null)
29
    {
30 20
        $this->setPath($path);
31 20
        $this->setFlLang($lang);
32 20
    }
33
34 5
    public function readFile(array $entry, ?int $offset = null, ?int $length = null): string
35
    {
36 5
        $path = $this->fullPath($entry);
37
        try {
38 5
            if (!is_null($length)) {
39 1
                $content = @file_get_contents($path, false, null, intval($offset), $length);
40 5
            } elseif (!is_null($offset)) {
41 1
                $content = @file_get_contents($path, false, null, $offset);
42
            } else {
43 5
                $content = @file_get_contents($path);
44
            }
45 5
            if (false !== $content) {
46 4
                return strval($content);
47
            }
48 1
            throw new FilesException($this->getFlLang()->flCannotLoadFile($path));
49 1
        } catch (Throwable $ex) {
50
            // @codeCoverageIgnoreStart
51 1
            throw new FilesException($ex->getMessage(), $ex->getCode(), $ex);
52
        }
53
        // @codeCoverageIgnoreEnd
54
    }
55
56 3
    public function readFileStream(array $entry)
57
    {
58 3
        $path = $this->fullPath($entry);
59
        try {
60 3
            $handle = @fopen($path, 'rb');
61 3
            if (false !== $handle) {
62 2
                return $handle;
63
            }
64 1
            throw new FilesException($this->getFlLang()->flCannotLoadFile($path));
65 1
        } catch (Throwable $ex) {
66
            // @codeCoverageIgnoreStart
67 1
            throw new FilesException($ex->getMessage(), $ex->getCode(), $ex);
68
        }
69
        // @codeCoverageIgnoreEnd
70
    }
71
72 6
    public function saveFile(array $entry, string $content, ?int $offset = null, int $mode = 0): bool
73
    {
74 6
        $this->checkSupportedModes($mode);
75 5
        $path = $this->fullPath($entry);
76
        try {
77 5
            if (FILE_APPEND == $mode) {
78 2
                if (file_exists($path)) {
79 2
                    $handler = @fopen($path, 'rb+');
80 2
                    if (false === $handler) {
81
                        // @codeCoverageIgnoreStart
82
                        throw new FilesException($this->getFlLang()->flCannotOpenFile($path));
83
                    }
84 2
                    @ftruncate($handler, intval($offset));
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for ftruncate(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

84
                    /** @scrutinizer ignore-unhandled */ @ftruncate($handler, intval($offset));

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
85 2
                    @fseek($handler, intval($offset));
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for fseek(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

85
                    /** @scrutinizer ignore-unhandled */ @fseek($handler, intval($offset));

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
86
                } else {
87 2
                    $handler = @fopen($path, 'ab');
88
                }
89
            } else {
90 4
                $handler = @fopen($path, 'wb');
91
            }
92 5
            if (false === $handler) {
93
                // @codeCoverageIgnoreStart
94 1
                throw new FilesException($this->getFlLang()->flCannotOpenFile($path));
95
            }
96
            // @codeCoverageIgnoreEnd
97 5
            if (!is_null($offset)) {
98 3
                if (0 != @fseek($handler, $offset)) {
99
                    // @codeCoverageIgnoreStart
100 3
                    throw new FilesException($this->getFlLang()->flCannotSeekFile($path));
101
                }
102
                // @codeCoverageIgnoreEnd
103
            } else {
104 3
                if (!@rewind($handler)) {
105
                    // @codeCoverageIgnoreStart
106
                    throw new FilesException($this->getFlLang()->flCannotSeekFile($path));
107
                }
108
                // @codeCoverageIgnoreEnd
109
            }
110 5
            if (false === @fwrite($handler, $content)) {
111
                // @codeCoverageIgnoreStart
112
                throw new FilesException($this->getFlLang()->flCannotWriteFile($path));
113
            }
114
            // @codeCoverageIgnoreEnd
115 5
            return @fclose($handler);
116 1
        } catch (Throwable $ex) {
117
            // @codeCoverageIgnoreStart
118 1
            throw new FilesException($this->getFlLang()->flCannotSaveFile($path), $ex->getCode(), $ex);
119
        }
120
        // @codeCoverageIgnoreEnd
121
    }
122
123 5
    public function saveFileStream(array $entry, $content, int $mode = 0): bool
124
    {
125 5
        $this->checkSupportedModes($mode);
126 4
        $path = $this->fullPath($entry);
127
        try {
128 4
            if (FILE_APPEND == $mode) { // append to the end
129 1
                $handler = @fopen($path, 'ab');
130
            } else { // rewrite all from offset
131 3
                $handler = @fopen($path, 'wb');
132
            }
133 4
            if (false === $handler) {
134
                // @codeCoverageIgnoreStart
135 1
                throw new FilesException($this->getFlLang()->flCannotOpenFile($path));
136
            }
137
            // @codeCoverageIgnoreEnd
138 4
            if (false === @stream_copy_to_stream($content, $handler)) {
139
                // @codeCoverageIgnoreStart
140
                throw new FilesException($this->getFlLang()->flCannotWriteFile($path));
141
            }
142
            // @codeCoverageIgnoreEnd
143 4
            return @fclose($handler);
144 1
        } catch (Throwable $ex) {
145
            // @codeCoverageIgnoreStart
146 1
            throw new FilesException($this->getFlLang()->flCannotSaveFile($path), $ex->getCode(), $ex);
147
        }
148
        // @codeCoverageIgnoreEnd
149
    }
150
151 1
    public function copyFile(array $source, array $dest): bool
152
    {
153 1
        $src = $this->fullPath($source);
154 1
        $dst = $this->fullPath($dest);
155
        try {
156 1
            return @copy($src, $dst);
157
            // @codeCoverageIgnoreStart
158
        } catch (Throwable $ex) {
159
            throw new FilesException($this->getFlLang()->flCannotCopyFile($src, $dst), $ex->getCode(), $ex);
160
        }
161
        // @codeCoverageIgnoreEnd
162
    }
163
164 1
    public function copyFileStream(array $source, array $dest): bool
165
    {
166 1
        $stream = $this->readFileStream($source);
167 1
        if (!@rewind($stream)) {
168
            // @codeCoverageIgnoreStart
169
            throw new FilesException($this->getFlLang()->flCannotSeekFile($this->fullPath($source)));
170
        }
171
        // @codeCoverageIgnoreEnd
172 1
        return $this->saveFileStream($dest, $stream);
173
    }
174
175 1
    public function moveFile(array $source, array $dest): bool
176
    {
177 1
        $src = $this->fullPath($source);
178 1
        $dst = $this->fullPath($dest);
179
        try {
180 1
            return @rename($src, $dst);
181
            // @codeCoverageIgnoreStart
182
        } catch (Throwable $ex) {
183
            throw new FilesException($this->getFlLang()->flCannotMoveFile($src, $dst), $ex->getCode(), $ex);
184
        }
185
        // @codeCoverageIgnoreEnd
186
    }
187
188 1
    public function moveFileStream(array $source, array $dest): bool
189
    {
190 1
        $r1 = $this->copyFileStream($source, $dest);
191 1
        $r2 = $this->deleteFile($source);
192 1
        return $r1 && $r2;
193
    }
194
195 2
    public function deleteFile(array $entry): bool
196
    {
197 2
        $path = $this->fullPath($entry);
198
        try {
199 2
            return @unlink($path);
200
            // @codeCoverageIgnoreStart
201
        } catch (Throwable $ex) {
202
            throw new FilesException($this->getFlLang()->flCannotRemoveFile($path), $ex->getCode(), $ex);
203
        }
204
        // @codeCoverageIgnoreEnd
205
    }
206
207
    /**
208
     * @param array<string> $path
209
     * @throws PathsException
210
     * @return string
211
     */
212 14
    protected function fullPath(array $path): string
213
    {
214 14
        return $this->getPath() . DIRECTORY_SEPARATOR . $this->compactName($path);
215
    }
216
217
    /**
218
     * @return string
219
     * @codeCoverageIgnore only when path fails
220
     */
221
    protected function noDirectoryDelimiterSet(): string
222
    {
223
        return $this->getFlLang()->flNoDirectoryDelimiterSet();
224
    }
225
}
226