Passed
Push — master ( 88d9d6...ec4c8d )
by Tom
04:42
created

Streams::__destruct()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 5
c 1
b 0
f 0
nc 3
nop 0
dl 0
loc 7
ccs 6
cts 6
cp 1
crap 5
rs 9.6111
1
<?php
2
3
/* this file is part of pipelines */
4
5
namespace Ktomk\Pipelines\Cli;
6
7
/**
8
 * For the standard streams used in the CLI application, output
9
 * to both standard output and standard error is available in
10
 * an encapsulated manner.
11
 *
12
 * @package Ktomk\Pipelines\Cli
13
 */
14
class Streams
15
{
16
    /**
17
     * @var array
18
     */
19
    private $handles;
20
21
    /**
22
     * Create streams from environment (standard streams)
23
     *
24
     * @return Streams
25
     */
26 1
    public static function create()
27
    {
28
        // PHP Doc Bug #43283 CLI does not define STDOUT/STDERR with stdin script
29 1
        $care = !defined('STDIN');
30
31 1
        $in = $care ? constant('STDIN') : 'php://stdin';
32 1
        $out = $care ? constant('STDOUT') : 'php://stdout';
33 1
        $err = $care ? constant('STDERR') : 'php://stderr';
34
35 1
        return new self($in, $out, $err);
36
    }
37
38
    /**
39
     * Streams constructor.
40
     *
41
     * handles can be null (noop), a resource (reuse) or a string that
42
     * is opened before use (currently on creation, could be postponed)
43
     *
44
     * @param null|resource|string $in
45
     * @param null|resource|string $out
46
     * @param null|resource|string $err
47
     */
48 7
    public function __construct($in = null, $out = null, $err = null)
49
    {
50 7
        $this->handles = array();
51 7
        $this->addHandle($in);
52 6
        $this->addHandle($out);
53 6
        $this->addHandle($err);
54 6
    }
55
56 6
    public function __destruct()
57
    {
58 6
        foreach ($this->handles as $handle => $descriptor) {
59 6
            list($resource, $context) = $descriptor;
60 6
            if ($resource && is_string($context) && is_resource($resource)) {
61 4
                fclose($resource);
62 4
                $this->handles[$handle][0] = null;
63
            }
64
        }
65 6
    }
66
67
    /**
68
     * @param string $string
69
     *
70
     * @return void
71
     */
72 1
    public function __invoke($string)
73
    {
74 1
        $this->out(sprintf("%s\n", $string));
75 1
    }
76
77
    /**
78
     * @param string $string
79
     *
80
     * @return void
81
     */
82 4
    public function out($string)
83
    {
84 4
        $handle = $this->handles[1][0];
85 4
        is_resource($handle) && fwrite($handle, $string);
86 4
    }
87
88
    /**
89
     * @param string $string
90
     *
91
     * @return void
92
     */
93 1
    public function err($string)
94
    {
95 1
        $handle = $this->handles[2][0];
96 1
        is_resource($handle) && fwrite($handle, $string);
97 1
    }
98
99
    /**
100
     * @param Streams $streams
101
     * @param int $handle
102
     *
103
     * @return void
104
     */
105 1
    public function copyHandle(Streams $streams, $handle)
106
    {
107 1
        $array = $streams->handles[$handle];
108
109
        // just in case the resource was opened by streams, remove the
110
        // association to the path
111 1
        if (is_resource($array[0])) {
112 1
            $array[1] = null;
113
        }
114
115 1
        $this->handles[$handle] = $array;
116 1
    }
117
118
    /**
119
     * @param null|resource|string $context
120
     *
121
     * @throws \RuntimeException
122
     *
123
     * @return void
124
     */
125 7
    private function addHandle($context)
126
    {
127 7
        $num = count($this->handles);
128 7
        if (null === $context || is_resource($context)) {
129
            $new = array(
130 5
                $context,
131
                null,
132
            );
133
        } else {
134 5
            $resource = fopen($context, 0 === $num ? 'r' : 'w');
135 5
            if (false === $resource) {
136 1
                throw new \RuntimeException(sprintf(
137 1
                    "failed to open '%s' for %s",
138
                    $context,
139 1
                    0 === $num ? 'reading' : 'writing'
140
                ));
141
            }
142
            $new = array(
143 4
                $resource,
144 4
                $context,
145
            );
146
        }
147
148 6
        $this->handles[$num] = $new;
149 6
    }
150
}
151