Passed
Push — master ( 399339...9c419c )
by Petr
08:15
created

ProcessFile::readFileStream()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 8
c 0
b 0
f 0
nc 3
nop 1
dl 0
loc 12
ccs 8
cts 8
cp 1
crap 3
rs 10
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\TLang;
10
use kalanis\kw_paths\Extras\TPathTransform;
11
use kalanis\kw_paths\PathsException;
12
use Throwable;
13
14
15
/**
16
 * Class ProcessFile
17
 * @package kalanis\kw_files\Processing\Volume
18
 * Process files in many ways
19
 */
20
class ProcessFile implements Interfaces\IProcessFiles, Interfaces\IProcessFileStreams
21
{
22
    use TLang;
23
    use TPath;
24
    use TPathTransform;
25
26 20
    public function __construct(string $path = '', ?Interfaces\IFLTranslations $lang = null)
27
    {
28 20
        $this->setPath($path);
29 20
        $this->setFlLang($lang);
30 20
    }
31
32 2
    public function readFile(array $entry, ?int $offset = null, ?int $length = null): string
33
    {
34 2
        $path = $this->fullPath($entry);
35
        try {
36 2
            if (!is_null($length)) {
37 1
                $content = @file_get_contents($path, false, null, intval($offset), $length);
38 2
            } elseif (!is_null($offset)) {
39 1
                $content = @file_get_contents($path, false, null, $offset);
40
            } else {
41 2
                $content = @file_get_contents($path);
42
            }
43 2
            if (false !== $content) {
44 1
                return strval($content);
45
            }
46 1
            throw new FilesException($this->getFlLang()->flCannotLoadFile($path));
47 1
        } catch (Throwable $ex) {
48
            // @codeCoverageIgnoreStart
49 1
            throw new FilesException($ex->getMessage(), $ex->getCode(), $ex);
50
        }
51
        // @codeCoverageIgnoreEnd
52
    }
53
54 3
    public function readFileStream(array $entry)
55
    {
56 3
        $path = $this->fullPath($entry);
57
        try {
58 3
            $handle = @fopen($path, 'rb');
59 3
            if (false !== $handle) {
60 2
                return $handle;
61
            }
62 1
            throw new FilesException($this->getFlLang()->flCannotLoadFile($path));
63 1
        } catch (Throwable $ex) {
64
            // @codeCoverageIgnoreStart
65 1
            throw new FilesException($ex->getMessage(), $ex->getCode(), $ex);
66
        }
67
        // @codeCoverageIgnoreEnd
68
    }
69
70 6
    public function saveFile(array $entry, string $content, ?int $offset = null, int $mode = 0): bool
71
    {
72 6
        $this->checkSupportedModes($mode);
73 5
        $path = $this->fullPath($entry);
74
        try {
75 5
            if (FILE_APPEND == $mode) {
76 1
                $handler = @fopen($path, 'ab');
77
            } else {
78 4
                $handler = @fopen($path, 'wb');
79
            }
80 5
            if (false === $handler) {
81
                // @codeCoverageIgnoreStart
82 1
                throw new FilesException($this->getFlLang()->flCannotOpenFile($path));
83
            }
84
            // @codeCoverageIgnoreEnd
85 5
            if (!is_null($offset)) {
86 3
                if (0 != @fseek($handler, $offset)) {
87
                    // @codeCoverageIgnoreStart
88 3
                    throw new FilesException($this->getFlLang()->flCannotSeekFile($path));
89
                }
90
                // @codeCoverageIgnoreEnd
91
            } else {
92 3
                if (!@rewind($handler)) {
93
                    // @codeCoverageIgnoreStart
94
                    throw new FilesException($this->getFlLang()->flCannotSeekFile($path));
95
                }
96
                // @codeCoverageIgnoreEnd
97
            }
98 5
            if (false === @fwrite($handler, $content)) {
99
                // @codeCoverageIgnoreStart
100
                throw new FilesException($this->getFlLang()->flCannotWriteFile($path));
101
            }
102
            // @codeCoverageIgnoreEnd
103 5
            return @fclose($handler);
104 1
        } catch (Throwable $ex) {
105
            // @codeCoverageIgnoreStart
106 1
            throw new FilesException($this->getFlLang()->flCannotSaveFile($path), $ex->getCode(), $ex);
107
        }
108
        // @codeCoverageIgnoreEnd
109
    }
110
111 5
    public function saveFileStream(array $entry, $content, int $mode = 0): bool
112
    {
113 5
        $this->checkSupportedModes($mode);
114 4
        $path = $this->fullPath($entry);
115
        try {
116 4
            if (FILE_APPEND == $mode) { // append to the end
117 1
                $handler = @fopen($path, 'ab');
118
            } else { // rewrite all from offset
119 3
                $handler = @fopen($path, 'wb');
120
            }
121 4
            if (false === $handler) {
122
                // @codeCoverageIgnoreStart
123 1
                throw new FilesException($this->getFlLang()->flCannotOpenFile($path));
124
            }
125
            // @codeCoverageIgnoreEnd
126 4
            if (false === @stream_copy_to_stream($content, $handler)) {
127
                // @codeCoverageIgnoreStart
128
                throw new FilesException($this->getFlLang()->flCannotWriteFile($path));
129
            }
130
            // @codeCoverageIgnoreEnd
131 4
            return @fclose($handler);
132 1
        } catch (Throwable $ex) {
133
            // @codeCoverageIgnoreStart
134 1
            throw new FilesException($this->getFlLang()->flCannotSaveFile($path), $ex->getCode(), $ex);
135
        }
136
        // @codeCoverageIgnoreEnd
137
    }
138
139
    /**
140
     * @param int<0, max> $mode
141
     * @throws FilesException
142
     */
143 11
    protected function checkSupportedModes(int $mode): void
144
    {
145 11
        if (!in_array($mode, [0, FILE_APPEND])) {
146 2
            throw new FilesException($this->getFlLang()->flBadMode($mode));
147
        }
148 9
    }
149
150 1
    public function copyFile(array $source, array $dest): bool
151
    {
152 1
        $src = $this->fullPath($source);
153 1
        $dst = $this->fullPath($dest);
154
        try {
155 1
            return @copy($src, $dst);
156
            // @codeCoverageIgnoreStart
157
        } catch (Throwable $ex) {
158
            throw new FilesException($this->getFlLang()->flCannotCopyFile($src, $dst), $ex->getCode(), $ex);
159
        }
160
        // @codeCoverageIgnoreEnd
161
    }
162
163 1
    public function copyFileStream(array $source, array $dest): bool
164
    {
165 1
        $stream = $this->readFileStream($source);
166 1
        if (!@rewind($stream)) {
167
            // @codeCoverageIgnoreStart
168
            throw new FilesException($this->getFlLang()->flCannotSeekFile($this->fullPath($source)));
169
        }
170
        // @codeCoverageIgnoreEnd
171 1
        return $this->saveFileStream($dest, $stream);
172
    }
173
174 1
    public function moveFile(array $source, array $dest): bool
175
    {
176 1
        $src = $this->fullPath($source);
177 1
        $dst = $this->fullPath($dest);
178
        try {
179 1
            return @rename($src, $dst);
180
            // @codeCoverageIgnoreStart
181
        } catch (Throwable $ex) {
182
            throw new FilesException($this->getFlLang()->flCannotMoveFile($src, $dst), $ex->getCode(), $ex);
183
        }
184
        // @codeCoverageIgnoreEnd
185
    }
186
187 1
    public function moveFileStream(array $source, array $dest): bool
188
    {
189 1
        $r1 = $this->copyFileStream($source, $dest);
190 1
        $r2 = $this->deleteFile($source);
191 1
        return $r1 && $r2;
192
    }
193
194 2
    public function deleteFile(array $entry): bool
195
    {
196 2
        $path = $this->fullPath($entry);
197
        try {
198 2
            return @unlink($path);
199
            // @codeCoverageIgnoreStart
200
        } catch (Throwable $ex) {
201
            throw new FilesException($this->getFlLang()->flCannotRemoveFile($path), $ex->getCode(), $ex);
202
        }
203
        // @codeCoverageIgnoreEnd
204
    }
205
206
    /**
207
     * @param array<string> $path
208
     * @throws PathsException
209
     * @return string
210
     */
211 14
    protected function fullPath(array $path): string
212
    {
213 14
        return $this->getPath() . DIRECTORY_SEPARATOR . $this->compactName($path);
214
    }
215
216
    /**
217
     * @return string
218
     * @codeCoverageIgnore only when path fails
219
     */
220
    protected function noDirectoryDelimiterSet(): string
221
    {
222
        return $this->getFlLang()->flNoDirectoryDelimiterSet();
223
    }
224
}
225