StreamRenderer::toStream()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 5
cts 5
cp 1
rs 9.9332
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
1
<?php
2
/**
3
 * This file is part of the BEAR.Middleware package.
4
 *
5
 * @license http://opensource.org/licenses/MIT MIT
6
 */
7
namespace BEAR\Middleware\Module;
8
9
use BEAR\Resource\RenderInterface;
10
use BEAR\Resource\ResourceObject;
11
use Ray\Di\Di\Named;
12
13
class StreamRenderer implements RenderInterface
14
{
15
    /**
16
     * @var RenderInterface
17
     */
18
    private $renderer;
19
20
    /**
21
     * @var resource
22
     */
23
    private $stream;
24
25
    /**
26
     * Pushed stream
27
     *
28
     * @var resource[]
29
     */
30
    private $streams;
31
32
    /**
33
     * @var array
34
     */
35
    private $hash = [];
36
37
    /**
38
     * @param RenderInterface $renderer
39
     *
40
     * @Named("renderer=original,stream=BEAR\Middleware\Annotation\Stream")
41
     */
42 6
    public function __construct(RenderInterface $renderer, $stream)
43
    {
44 6
        $this->renderer = $renderer;
45 6
        $this->stream = $stream;
46 6
    }
47
48
    /**
49
     * {@inheritdoc}
50
     */
51 5
    public function render(ResourceObject $ro)
52
    {
53 5
        if (is_array($ro->body)) {
54 3
            $this->pushArrayBody($ro);
55
56 3
            return $this->renderer->render($ro);
57
        }
58
59 2
        return $this->pushScalarBody($ro);
60
    }
61
62
    /**
63
     * Covert string + stream holder to stream
64
     *
65
     * @param string $string
66
     *
67
     * @return resource
68
     */
69 5
    public function toStream($string)
70
    {
71 5
        if (! $this->hash) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->hash of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
72 2
            fwrite($this->stream, $string);
73
74 2
            return $this->stream;
75
        }
76
77 3
        return $this->mergeStream($string, $this->stream);
78
    }
79
80
    /**
81
     * @param resource $item
82
     *
83
     * @return string
84
     */
85 3
    private function pushStream($item)
86
    {
87 3
        $id = uniqid('STREAM_' . mt_rand(), true) . '_';
88 3
        $this->streams[$id] = $item; // push
89 3
        $this->hash[] = $id;
90 3
        $item = $id;
91
92 3
        return $item;
93
    }
94
95
    /**
96
     * @param string   $string
97
     * @param resource $stream
98
     *
99
     * @return resource
100
     */
101 3
    private function mergeStream($string, $stream)
102
    {
103 3
        rewind($stream);
104 3
        $regex = sprintf('/(%s)/', implode('|', $this->hash));
105 3
        preg_match_all($regex, $string, $match, PREG_SET_ORDER);
106 3
        $list = $this->collect($match);
0 ignored issues
show
Bug introduced by
It seems like $match can also be of type null; however, BEAR\Middleware\Module\StreamRenderer::collect() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
107 3
        $bodies = preg_split($regex, $string);
108 3
        foreach ($bodies as $body) {
109 3
            fwrite($stream, $body);
110 3
            $index = array_shift($list);
111 3
            if (isset($this->streams[$index])) {
112 3
                $popStream = $this->streams[$index];
113 3
                rewind($popStream);
114 3
                stream_copy_to_stream($popStream, $stream);
115
            }
116
        }
117
118 3
        return $stream;
119
    }
120
121
    /**
122
     * @param array $match
123
     *
124
     * @return array
125
     */
126 3
    private function collect(array $match)
127
    {
128 3
        $list = [];
129 3
        foreach ($match as $item) {
130 3
            $list[] = $item[0];
131
        }
132
133 3
        return $list;
134
    }
135
136
    /**
137
     * @param ResourceObject $ro
138
     *
139
     * @return string
140
     */
141 2
    private function pushScalarBody(ResourceObject $ro)
142
    {
143 2
        if (is_resource($ro->body) && get_resource_type($ro->body) == 'stream') {
144 1
            return $this->pushStream($ro->body);
145
        }
146
147 1
        return $this->renderer->render($ro);
148
    }
149
150
    /**
151
     * @param ResourceObject $ro
152
     */
153 3
    private function pushArrayBody(ResourceObject $ro)
154
    {
155 3
        foreach ($ro->body as &$item) {
156 3
            if (is_resource($item) && get_resource_type($item) == 'stream') {
157 2
                $item = $this->pushStream($item);
158
            }
159
        }
160 3
    }
161
}
162