Passed
Push — master ( 5e712b...61b36a )
by Tom
02:52
created

Streams::copyHandle()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 2
dl 0
loc 11
ccs 5
cts 5
cp 1
crap 2
rs 9.4285
c 0
b 0
f 0
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
     * private marker that instance should close handles on dtor
23
     * @var bool
24
     */
25
    private $closeOnDestruct;
26
27
    /**
28
     * Create streams from environment (standard streams)
29
     */
30 1
    public static function create()
31
    {
32
        // PHP Doc Bug #43283 CLI does not define STDOUT/STDERR with stdin script
33 1
        $care = !defined('STDIN');
34
35 1
        $in = $care ? constant('STDIN') : 'php://stdin';
36 1
        $out = $care ? constant('STDOUT') : 'php://stdout';
37 1
        $err = $care ? constant('STDERR') : 'php://stderr';
38
39 1
        $streams = new self($in, $out, $err);
40 1
        $streams->closeOnDestruct = $care;
41
42 1
        return $streams;
43
    }
44
45
    /**
46
     * Streams constructor.
47
     *|string
48
     * handles can be null (noop), a resource (reuse) or a string that
49
     * is opened before use (currently on creation, could be postponed)
50
     *
51
     * @param resource|null|string $in
52
     * @param resource|null|string $out
53
     * @param resource|null|string $err
54
     */
55 7
    public function __construct($in = null, $out = null, $err = null)
56
    {
57 7
        $this->handles = array();
58 7
        $this->addHandle($in);
59 6
        $this->addHandle($out);
60 6
        $this->addHandle($err);
61 6
    }
62
63 1
    public function __invoke($string)
64
    {
65 1
        $this->out(sprintf("%s\n", $string));
66 1
    }
67
68 4
    public function out($string)
69
    {
70 4
        $handle = $this->handles[1][0];
71 4
        is_resource($handle) && fputs($handle, $string);
0 ignored issues
show
Bug introduced by
The call to fputs() has too few arguments starting with length. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

71
        is_resource($handle) && /** @scrutinizer ignore-call */ fputs($handle, $string);

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
72 4
    }
73
74 1
    public function err($string)
75
    {
76 1
        $handle = $this->handles[2][0];
77 1
        is_resource($handle) && fputs($handle, $string);
0 ignored issues
show
Bug introduced by
The call to fputs() has too few arguments starting with length. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

77
        is_resource($handle) && /** @scrutinizer ignore-call */ fputs($handle, $string);

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
78 1
    }
79
80
    /**
81
     * @param Streams $streams
82
     * @param int $handle
83
     */
84 1
    public function copyHandle(Streams $streams, $handle)
85
    {
86 1
        $array = $streams->handles[$handle];
87
88
        // just in case the resource was opened by streams, remove the
89
        // association to the path
90 1
        if (is_resource($array[0])) {
91 1
            $array[1] = null;
92
        }
93
94 1
        $this->handles[$handle] = $array;
95 1
    }
96
97
    /**
98
     * @param null|resource|string $context
99
     */
100 7
    private function addHandle($context)
101
    {
102 7
        $num = count($this->handles);
103 7
        if (null === $context || is_resource($context)) {
104
            $new = array(
105 5
                $context,
106
                null,
107
            );
108
        } else {
109 5
            $resource = fopen($context, 0 === $num ? 'r' : 'w');
110 5
            if (false === $resource) {
111 1
                throw new \RuntimeException(sprintf(
112 1
                    "failed to open '%s' for %s",
113 1
                    $context,
114 1
                    0 === $num ? 'reading' : 'writing'
115
                ));
116
            }
117
            $new = array(
118 4
                $resource,
119 4
                $context,
120
            );
121
        }
122
123 6
        $this->handles[$num] = $new;
124 6
    }
125
126 6
    public function __destruct()
127
    {
128 6
        foreach ($this->handles as $handle => $descriptor) {
129 6
            list($resource, $context) = $descriptor;
130 6
            if ($resource && is_string($context) && is_resource($resource)) {
131 4
                fclose($resource);
132 6
                $this->handles[$handle][0] = null;
133
            }
134
        }
135 6
    }
136
}
137