Passed
Push — master ( ede325...51c2a5 )
by Petr
08:48
created

ProcessFile::saveFile()   B

Complexity

Conditions 11
Paths 64

Size

Total Lines 49
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 11.209

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 11
eloc 28
c 2
b 0
f 0
nc 64
nop 4
dl 0
loc 49
ccs 22
cts 25
cp 0.88
crap 11.209
rs 7.3166

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 (@is_file($path)) {
79 2
                    $handler = @fopen($path, 'ab+');
80 2
                    if (false === $handler) {
81
                        // @codeCoverageIgnoreStart
82
                        throw new FilesException($this->getFlLang()->flCannotOpenFile($path));
83
                    }
84 2
                    if (!is_null($offset)) {
85 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

85
                        /** @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...
86 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

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