Passed
Push — master ( 1f33ad...fba3db )
by Petr
08:38
created

ProcessFile::writeStream()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3.1406

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 3
nop 2
dl 0
loc 15
rs 10
c 0
b 0
f 0
ccs 6
cts 8
cp 0.75
crap 3.1406
1
<?php
2
3
namespace kalanis\kw_files\Processing\Volume;
4
5
6
use kalanis\kw_files\FilesException;
7
use kalanis\kw_files\Interfaces\IFLTranslations;
8
use kalanis\kw_files\Interfaces\IProcessFiles;
9
use kalanis\kw_files\Processing\TPath;
10
use kalanis\kw_files\Traits\TLang;
11
use kalanis\kw_files\Traits\TStreamToPos;
12
use kalanis\kw_files\Traits\TToStream;
13
use kalanis\kw_paths\Extras\TPathTransform;
14
use kalanis\kw_paths\PathsException;
15
use Throwable;
16
17
18
/**
19
 * Class ProcessFile
20
 * @package kalanis\kw_files\Processing\Volume
21
 * Process files in many ways
22
 */
23
class ProcessFile implements IProcessFiles
24
{
25
    use TLang;
26
    use TPath;
27
    use TPathTransform;
28
    use TStreamToPos;
29
    use TToStream;
30
31 11
    public function __construct(string $path = '', ?IFLTranslations $lang = null)
32
    {
33 11
        $this->setPath($path);
34 11
        $this->setLang($lang);
35 11
    }
36
37 2
    public function readFile(array $entry, ?int $offset = null, ?int $length = null)
38
    {
39 2
        $path = $this->fullPath($entry);
40
        try {
41 2
            if (!is_null($length)) {
42 1
                $content = @file_get_contents($path, false, null, intval($offset), $length);
43 2
            } elseif (!is_null($offset)) {
44 1
                $content = @file_get_contents($path, false, null, $offset);
45
            } else {
46 2
                $content = @file_get_contents($path);
47
            }
48 2
            if (false !== $content) {
49 1
                return $content;
50
            }
51 1
            throw new FilesException($this->getLang()->flCannotLoadFile($path));
52 1
        } catch (Throwable $ex) {
53
            // @codeCoverageIgnoreStart
54 1
            throw new FilesException($ex->getMessage(), $ex->getCode(), $ex);
55
        }
56
        // @codeCoverageIgnoreEnd
57
    }
58
59 4
    public function saveFile(array $entry, $content, ?int $offset = null): bool
60
    {
61 4
        $path = $this->fullPath($entry);
62
        try {
63 4
            if (is_null($offset)) {  // rewrite all
64 3
                $this->writeStream($path, $this->toStream($path, $content));
65
            } else { // append from position
66 2
                if (file_exists($path)) {
67 1
                    $handler = @fopen($path, 'rb');
68 1
                    if (false === $handler) {
69
                        // @codeCoverageIgnoreStart
70
                        throw new FilesException($this->getLang()->flCannotOpenFile($path));
71
                    }
72
                    // @codeCoverageIgnoreEnd
73
                    // must be extra - need that original file handler
74 1
                    $result = $this->addStreamToPosition(
75 1
                        $handler, // original content
76 1
                        $this->toStream(
77 1
                            $path,
78
                            $content
79
                        ),
80
                        $offset
81
                    );
82 1
                    /** @scrutinizer ignore-unhandled */@fclose($handler);
83 1
                    $this->writeStream($path, $result);
84
                } else {
85 1
                    $this->writeStream(
86 1
                        $path,
87 1
                        $this->addStreamToPosition(
88 1
                            fopen('php://memory', 'rb+'), // no original content
89 1
                            $this->toStream(
90 1
                                $path,
91
                                $content
92
                            ),
93
                            $offset
94
                        )
95
                    );
96
                }
97
            }
98 4
            return true;
99 1
        } catch (Throwable $ex) {
100
            // @codeCoverageIgnoreStart
101 1
            throw new FilesException($this->getLang()->flCannotSaveFile($path), $ex->getCode(), $ex);
102
        }
103
        // @codeCoverageIgnoreEnd
104
    }
105
106
    /**
107
     * @param string $path
108
     * @param resource $content
109
     * @throws FilesException
110
     */
111 4
    protected function writeStream(string $path, $content): void
112
    {
113 4
        $pointer = @fopen($path, 'wb');
114 4
        if (false === $pointer) {
115
            // @codeCoverageIgnoreStart
116 1
            throw new FilesException($this->getLang()->flCannotOpenFile($path));
117
        }
118
        // @codeCoverageIgnoreEnd
119 4
        if (false === @stream_copy_to_stream($pointer, $content, -1, 0)) {
120
            // @codeCoverageIgnoreStart
121
            /** @scrutinizer ignore-unhandled */@fclose($pointer);
122
            throw new FilesException($this->getLang()->flCannotWriteFile($path));
123
        }
124
        // @codeCoverageIgnoreEnd
125 4
        /** @scrutinizer ignore-unhandled */@fclose($pointer);
126 4
    }
127
128 1
    public function copyFile(array $source, array $dest): bool
129
    {
130 1
        $src = $this->fullPath($source);
131 1
        $dst = $this->fullPath($dest);
132
        try {
133 1
            return @copy($src, $dst);
134
            // @codeCoverageIgnoreStart
135
        } catch (Throwable $ex) {
136
            throw new FilesException($this->getLang()->flCannotCopyFile($src, $dst), $ex->getCode(), $ex);
137
        }
138
        // @codeCoverageIgnoreEnd
139
    }
140
141 1
    public function moveFile(array $source, array $dest): bool
142
    {
143 1
        $src = $this->fullPath($source);
144 1
        $dst = $this->fullPath($dest);
145
        try {
146 1
            return @rename($src, $dst);
147
            // @codeCoverageIgnoreStart
148
        } catch (Throwable $ex) {
149
            throw new FilesException($this->getLang()->flCannotMoveFile($src, $dst), $ex->getCode(), $ex);
150
        }
151
        // @codeCoverageIgnoreEnd
152
    }
153
154 1
    public function deleteFile(array $entry): bool
155
    {
156 1
        $path = $this->fullPath($entry);
157
        try {
158 1
            return @unlink($path);
159
            // @codeCoverageIgnoreStart
160
        } catch (Throwable $ex) {
161
            throw new FilesException($this->getLang()->flCannotRemoveFile($path), $ex->getCode(), $ex);
162
        }
163
        // @codeCoverageIgnoreEnd
164
    }
165
166
    /**
167
     * @param array<string> $path
168
     * @throws PathsException
169
     * @return string
170
     */
171 7
    protected function fullPath(array $path): string
172
    {
173 7
        return $this->getPath() . DIRECTORY_SEPARATOR . $this->compactName($path);
174
    }
175
176
    /**
177
     * @return string
178
     * @codeCoverageIgnore only when path fails
179
     */
180
    protected function noDirectoryDelimiterSet(): string
181
    {
182
        return $this->getLang()->flNoDirectoryDelimiterSet();
183
    }
184
}
185