DockerRawStream   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 111
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Test Coverage

Coverage 73.81%

Importance

Changes 3
Bugs 0 Features 1
Metric Value
wmc 15
c 3
b 0
f 1
lcom 1
cbo 1
dl 0
loc 111
ccs 31
cts 42
cp 0.7381
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A onStdin() 0 4 1
A onStdout() 0 4 1
A onStderr() 0 4 1
A forceRead() 0 10 3
A wait() 0 6 2
B readFrame() 0 28 6
1
<?php
2
3
namespace Docker\Stream;
4
5
use Psr\Http\Message\StreamInterface;
6
7
class DockerRawStream
8
{
9
    const HEADER = 'application/vnd.docker.raw-stream';
10
11
    /** @var StreamInterface Stream for the response */
12
    protected $stream;
13
14
    /** @var callable[] A list of callable to call when there is a stdin output */
15
    protected $onStdinCallables = [];
16
17
    /** @var callable[] A list of callable to call when there is a stdout output */
18
    protected $onStdoutCallables = [];
19
20
    /** @var callable[] A list of callable to call when there is a stderr output */
21
    protected $onStderrCallables = [];
22
23 2
    public function __construct(StreamInterface $stream)
24
    {
25 2
        $this->stream = $stream;
26 2
    }
27
28
    /**
29
     * Add a callable to read stdin
30
     *
31
     * @param callable $callback
32
     */
33
    public function onStdin(callable $callback)
34
    {
35
        $this->onStdinCallables[] = $callback;
36
    }
37
38
    /**
39
     * Add a callable to read stdout
40
     *
41
     * @param callable $callback
42
     */
43 2
    public function onStdout(callable $callback)
44
    {
45 2
        $this->onStdoutCallables[] = $callback;
46 2
    }
47
48
    /**
49
     * Add a callable to read stderr
50
     *
51
     * @param callable $callback
52
     */
53
    public function onStderr(callable $callback)
54
    {
55
        $this->onStderrCallables[] = $callback;
56
    }
57
58
    /**
59
     * Read a frame in the stream
60
     */
61 2
    protected function readFrame()
62
    {
63 2
        $header  = $this->forceRead(8);
64
65 2
        if (strlen($header) < 8) {
66
            return;
67
        }
68
69 2
        $decoded = unpack('C1type/C3/N1size', $header);
70 2
        $output  = $this->forceRead($decoded['size']);
71 2
        $callbackList = [];
72
73 2
        if ($decoded['type'] == 0) {
74
            $callbackList = $this->onStdinCallables;
75
        }
76
77 2
        if ($decoded['type'] == 1) {
78 2
            $callbackList = $this->onStdoutCallables;
79 2
        }
80
81 2
        if ($decoded['type'] == 2) {
82
            $callbackList = $this->onStderrCallables;
83
        }
84
85 2
        foreach ($callbackList as $callback) {
86 2
            $callback($output);
87 2
        }
88 2
    }
89
90
    /**
91
     * Force to have something of the expected size (block)
92
     *
93
     * @param $length
94
     *
95
     * @return string
96
     */
97 2
    private function forceRead($length)
98
    {
99 2
        $read = "";
100
101
        do {
102 2
            $read .= $this->stream->read($length - strlen($read));
103 2
        } while (strlen($read) < $length && !$this->stream->eof());
104
105 2
        return $read;
106
    }
107
108
    /**
109
     * Wait for stream to finish and call callables if defined
110
     */
111 2
    public function wait()
112
    {
113 2
        while (!$this->stream->eof()) {
114 2
            $this->readFrame();
115 2
        }
116 2
    }
117
}
118