Passed
Pull Request — master (#75)
by
unknown
10:29
created

DataStream::detach()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 5
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Stream;
6
7
use App\Stream\Value\DataResponseProvider;
8
use Psr\Http\Message\StreamInterface;
9
10
final class DataStream implements StreamInterface
11
{
12
    private DataResponseProvider $data;
13
    private bool $readable = false;
14
    private ?int $size = null;
15
    private bool $seekable = false;
16
    private int $caret = 0;
17
18
    public function __construct(DataResponseProvider $body)
19
    {
20
        $this->data = $body;
21
    }
22
    public function __toString(): string
23
    {
24
        try {
25
            if ($this->isSeekable()) {
26
                $this->seek(0);
27
            }
28
            return $this->getContents();
29
        } catch (\Exception $e) {
30
            return '';
31
        }
32
    }
33
    public function close(): void
34
    {
35
        if ($this->data !== null) {
36
            $this->detach();
37
        }
38
    }
39
    public function detach()
40
    {
41
        $result = $this->data;
42
        $this->data = null;
43
        return $result;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $result returns the type App\Stream\Value\DataResponseProvider which is incompatible with the return type mandated by Psr\Http\Message\StreamInterface::detach() of null|resource.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
44
    }
45
    public function getSize(): ?int
46
    {
47
        return $this->size;
48
    }
49
    public function tell(): int
50
    {
51
        return $this->caret;
52
    }
53
    public function eof(): bool
54
    {
55
        return $this->data === null;
56
    }
57
    public function isSeekable(): bool
58
    {
59
        return $this->seekable;
60
    }
61
    public function seek($offset, $whence = \SEEK_SET): void
62
    {
63
        throw new \RuntimeException('Stream is not seekable.');
64
    }
65
    public function rewind(): void
66
    {
67
        $this->caret = 0;
68
    }
69
    public function isWritable(): bool
70
    {
71
        return false;
72
    }
73
    public function write($string): int
74
    {
75
        throw new \RuntimeException('Cannot write to a non-writable stream.');
76
    }
77
    public function isReadable(): bool
78
    {
79
        return $this->readable;
80
    }
81
    public function read($length): string
82
    {
83
        throw new \RuntimeException('Stream should be rendered.');
84
    }
85
    public function getContents(): string
86
    {
87
        return $this->read(PHP_INT_MAX);
88
    }
89
    public function getMetadata($key = null)
90
    {
91
        if (!isset($this->data)) {
92
            return $key ? null : [];
93
        }
94
95
        $meta = [
96
            'seekable' => $this->isSeekable(),
97
            'eof' => $this->eof(),
98
        ];
99
100
        if (null === $key) {
101
            return $meta;
102
        }
103
104
        return $meta[$key] ?? null;
105
    }
106
107
    public function getData(): DataResponseProvider
108
    {
109
        return $this->data;
110
    }
111
}
112