UploadedFile::getStream()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 5
cts 5
cp 1
rs 9.9
c 0
b 0
f 0
cc 2
nc 2
nop 0
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Aidphp\Http;
6
7
use Psr\Http\Message\UploadedFileInterface;
8
use Psr\Http\Message\StreamInterface;
9
use InvalidArgumentException;
10
use RuntimeException;
11
12
class UploadedFile implements UploadedFileInterface
13
{
14
    private $clientFilename;
15
    private $clientMediaType;
16
    private $error;
17
    private $file;
18
    private $moved = false;
19
    private $size;
20
    private $stream;
21
22 36
    public function __construct($streamOrFile, int $size, int $errorStatus, ?string $clientFilename = null, ?string $clientMediaType = null)
23
    {
24 36
        if (0 > $errorStatus || 8 < $errorStatus)
25
        {
26 2
            throw new InvalidArgumentException('Invalid error status for UploadedFile');
27
        }
28
29 34
        $this->error = $errorStatus;
30 34
        $this->size  = $size;
31 34
        $this->clientFilename  = $clientFilename;
32 34
        $this->clientMediaType = $clientMediaType;
33
34 34
        if ($this->isOk())
35
        {
36 26
            $this->setStreamOrFile($streamOrFile);
37
        }
38 27
    }
39
40 12
    public function getStream(): StreamInterface
41
    {
42 12
        $this->validateActive();
43
44 5
        if ($this->stream instanceof StreamInterface)
45
        {
46 4
            return $this->stream;
47
        }
48
49 1
        return new Stream(fopen($this->file, 'r'));
50
    }
51
52 11
    public function moveTo($targetPath): void
53
    {
54 11
        $this->validateActive();
55
56 11
        if (! is_string($targetPath) || empty($targetPath))
57
        {
58 8
            throw new InvalidArgumentException('Invalid path provided for move operation; must be a non-empty string');
59
        }
60
61 3
        if (null !== $this->file)
62
        {
63 1
            $this->moved = ('cli' == php_sapi_name()) ? rename($this->file, $targetPath) : move_uploaded_file($this->file, $targetPath);
64
        }
65
        else
66
        {
67 2
            $this->writeFile($targetPath);
68 2
            $this->moved = true;
69
        }
70
71 3
        if (false === $this->moved)
72
        {
73
            throw new RuntimeException('Uploaded file could not be moved to "' . $targetPath . '"');
74
        }
75 3
    }
76
77 4
    public function getSize(): ?int
78
    {
79 4
        return $this->size;
80
    }
81
82 3
    public function getError(): int
83
    {
84 3
        return $this->error;
85
    }
86
87 4
    public function getClientFilename(): ?string
88
    {
89 4
        return $this->clientFilename;
90
    }
91
92 4
    public function getClientMediaType(): ?string
93
    {
94 4
        return $this->clientMediaType;
95
    }
96
97 26
    private function setStreamOrFile($streamOrFile): void
98
    {
99 26
        if (is_string($streamOrFile))
100
        {
101 15
            $this->file = $streamOrFile;
102
        }
103 11
        elseif (is_resource($streamOrFile))
104
        {
105 1
            $this->stream = new Stream($streamOrFile);
106
        }
107 10
        elseif ($streamOrFile instanceof StreamInterface)
108
        {
109 3
            $this->stream = $streamOrFile;
110
        }
111
        else
112
        {
113 7
            throw new InvalidArgumentException('Invalid stream or file provided for UploadedFile');
114
        }
115 19
    }
116
117 34
    private function isOk(): bool
118
    {
119 34
        return UPLOAD_ERR_OK === $this->error;
120
    }
121
122 21
    private function validateActive(): void
123
    {
124 21
        if (false === $this->isOk())
125
        {
126 7
            throw new RuntimeException('Cannot retrieve stream due to upload error');
127
        }
128
129 14
        if ($this->moved)
130
        {
131 1
            throw new RuntimeException('Cannot retrieve stream after it has already been moved');
132
        }
133 14
    }
134
135 2
    private function writeFile(string $path): void
136
    {
137 2
        $stream = $this->getStream();
138
139 2
        if ($stream->isSeekable())
140
        {
141 2
            $stream->rewind();
142
        }
143
144 2
        $handle = fopen($path, 'wb');
145
146 2
        while (! $stream->eof())
147
        {
148 2
            fwrite($handle, $stream->read(1048576));
149
        }
150
151 2
        fclose($handle);
152
    }
153
}