Output   A
last analyzed

Coupling/Cohesion

Components 1
Dependencies 5

Complexity

Total Complexity 34

Size/Duplication

Total Lines 307
Duplicated Lines 0 %

Test Coverage

Coverage 96.47%

Importance

Changes 0
Metric Value
wmc 34
lcom 1
cbo 5
dl 0
loc 307
ccs 82
cts 85
cp 0.9647
rs 9.2
c 0
b 0
f 0

19 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
A sameLine() 0 6 1
A add() 0 6 1
A defaultTo() 0 4 1
A addDefault() 0 4 1
A once() 0 6 1
A persist() 0 10 2
A get() 0 12 3
A getAvailable() 0 10 2
A write() 0 12 3
A resolve() 0 10 3
A resolveArrayWriter() 0 4 1
A resolveObjectWriter() 0 8 2
A resolveStringWriter() 0 8 3
A handleUnknownWriter() 0 12 2
A getReadable() 0 10 2
A getWriters() 0 6 1
A getCurrentWriters() 0 4 2
A resetOneTimers() 0 10 2
1
<?php
2
3
namespace League\CLImate\Util;
4
5
use League\CLImate\Util\Writer\WriterInterface;
6
7
class Output
8
{
9
    /**
10
     * The content to be output
11
     *
12
     * @var string $content
13
     */
14
    protected $content;
15
16
    /**
17
     * Whether or not to add a new line after the output
18
     *
19
     * @var boolean $new_line
20
     */
21
    protected $new_line = true;
22
23
    /**
24
     * The array of available writers
25
     *
26
     * @var array[] $writers
27
     */
28
    protected $writers = [];
29
30
    /**
31
     * Default writers when one isn't specifed
32
     *
33
     * @var WriterInterface[] $default
34
     */
35
    protected $default = [];
36
37
    /**
38
     * Writers to be used just once
39
     *
40
     * @var null|array $once
41
     */
42
    protected $once;
43
44
    protected $persist = false;
45
46 956
    public function __construct()
47
    {
48 956
        $this->add('out', new Writer\StdOut);
49 956
        $this->add('error', new Writer\StdErr);
50 956
        $this->add('buffer', new Writer\Buffer);
51
52 956
        $this->defaultTo('out');
53 956
    }
54
55
    /**
56
     * Dictate that a new line should not be added after the output
57
     */
58 40
    public function sameLine()
59
    {
60 40
        $this->new_line = false;
61
62 40
        return $this;
63
    }
64
65
    /**
66
     * Add a writer to the available writers
67
     *
68
     * @param string $key
69
     * @param WriterInterface|array $writer
70
     *
71
     * @return \League\CLImate\Util\Output
72
     */
73 956
    public function add($key, $writer)
74
    {
75 956
        $this->writers[$key] = $this->resolve(Helper::toArray($writer));
0 ignored issues
show
Bug introduced by Joe Tannenbaum
It seems like $writer defined by parameter $writer on line 73 can also be of type object<League\CLImate\Ut...Writer\WriterInterface>; however, League\CLImate\Util\Helper::toArray() does only seem to accept string|array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
76
77 956
        return $this;
78
    }
79
80
    /**
81
     * Set the default writer
82
     *
83
     * @param string|array $keys
84
     */
85 956
    public function defaultTo($keys)
86
    {
87 956
        $this->default = $this->getWriters($keys);
88 956
    }
89
90
    /**
91
     * Add a default writer
92
     *
93
     * @param string|array $keys
94
     */
95 4
    public function addDefault($keys)
96
    {
97 4
        $this->default = array_merge($this->default, $this->getWriters($keys));
98 4
    }
99
100
    /**
101
     * Register a writer to be used just once
102
     *
103
     * @param string|array $keys
104
     *
105
     * @return \League\CLImate\Util\Output
106
     */
107 8
    public function once($keys)
108
    {
109 8
        $this->once = $this->getWriters($keys);
110
111 8
        return $this;
112
    }
113
114
    /**
115
     * Persist or un-persist one time writers (for multi-line output)
116
     *
117
     * @param bool $persist
118
     *
119
     * @return \League\CLImate\Util\Output
120
     */
121 4
    public function persist($persist = true)
122
    {
123 4
        $this->persist = (bool) $persist;
124
125 4
        if (!$this->persist) {
126 4
            $this->resetOneTimers();
127 4
        }
128
129 4
        return $this;
130
    }
131
132
    /**
133
     * Get a specific writer
134
     *
135
     * @throws \Exception if writer key doesn't exist
136
     * @param string $writer
137
     *
138
     * @return WriterInterface|array
139
     */
140 4
    public function get($writer)
141
    {
142 4
        if (!array_key_exists($writer, $this->writers)) {
143
            throw new \Exception('Unknown writer [' . $writer . ']');
144
        }
145
146 4
        if (count($this->writers[$writer]) == 1) {
147 4
            return reset($this->writers[$writer]);
148
        }
149
150
        return $this->writers[$writer];
151
    }
152
153
    /**
154
     * Get the currently available writers
155
     *
156
     * @return array
157
     */
158 4
    public function getAvailable()
159
    {
160 4
        $writers = [];
161
162 4
        foreach ($this->writers as $key => $writer) {
163 4
            $writers[$key] = $this->getReadable($writer);
164 4
        }
165
166 4
        return $writers;
167
    }
168
169
    /**
170
     * Write the content using the provided writer
171
     *
172
     * @param  string $content
173
     */
174 80
    public function write($content)
175
    {
176 80
        if ($this->new_line) {
177 40
            $content .= PHP_EOL;
178 40
        }
179
180 80
        foreach ($this->getCurrentWriters() as $writer) {
181 80
            $writer->write($content);
182 68
        }
183
184 68
        $this->resetOneTimers();
185 68
    }
186
187
    /**
188
     * Resolve the writer(s) down to an array of WriterInterface classes
189
     *
190
     * @param WriterInterface|array|string $writer
191
     *
192
     * @return array
193
     */
194 956
    protected function resolve($writer)
195
    {
196 956
        $resolver = 'resolve' . ucwords(gettype($writer)) . 'Writer';
197
198 956
        if (method_exists($this, $resolver) && $resolved = $this->{$resolver}($writer)) {
199 956
            return $resolved;
200
        }
201
202 8
        $this->handleUnknownWriter($writer);
203
    }
204
205
    /**
206
     * @param array $writer
207
     *
208
     * @return array
209
     */
210 956
    protected function resolveArrayWriter($writer)
211
    {
212 956
        return Helper::flatten(array_map([$this, 'resolve'], $writer));
213
    }
214
215
    /**
216
     * @param object $writer
217
     *
218
     * @return WriterInterface|false
219
     */
220 956
    protected function resolveObjectWriter($writer)
221
    {
222 956
        if ($writer instanceof WriterInterface) {
223 956
            return $writer;
224
        }
225
226 4
        return false;
227
    }
228
229
    /**
230
     * @param string $writer
231
     *
232
     * @return array|false
233
     */
234 12
    protected function resolveStringWriter($writer)
235
    {
236 12
        if (is_string($writer) && array_key_exists($writer, $this->writers)) {
237 8
            return $this->writers[$writer];
238
        }
239
240 4
        return false;
241
    }
242
243
    /**
244
     * @param mixed $writer
245
     * @throws \Exception For non-valid writer
246
     */
247 8
    protected function handleUnknownWriter($writer)
248
    {
249
        // If we've gotten this far and don't know what it is,
250
        // let's at least try and give a helpful error message
251 8
        if (is_object($writer)) {
252 4
            throw new \Exception('Class [' . get_class($writer) . '] must implement '
253 4
                                    . 'League\CLImate\Util\Writer\WriterInterface.');
254
        }
255
256
        // No idea, just tell them we can't resolve it
257 4
        throw new \Exception('Unable to resolve writer [' . $writer . ']');
258
    }
259
260
    /**
261
     * Get the readable version of the writer(s)
262
     *
263
     * @param array $writer
264
     *
265
     * @return string|array
266
     */
267 4
    protected function getReadable(array $writer)
268
    {
269 4
        $classes = array_map('get_class', $writer);
270
271 4
        if (count($classes) == 1) {
272 4
            return reset($classes);
273
        }
274
275 4
        return $classes;
276
    }
277
278
    /**
279
     * Get the writers based on their keys
280
     *
281
     * @param string|array $keys
282
     *
283
     * @return array
284
     */
285 956
    protected function getWriters($keys)
286
    {
287 956
        $writers = array_flip(Helper::toArray($keys));
288
289 956
        return Helper::flatten(array_intersect_key($this->writers, $writers));
290
    }
291
292
    /**
293
     * @return WriterInterface[]
294
     */
295 80
    protected function getCurrentWriters()
296
    {
297 80
        return $this->once ?: $this->default;
298
    }
299
300
    /**
301
     * Reset anything only used for the current content being written
302
     */
303 68
    protected function resetOneTimers()
304
    {
305
        // Reset new line flag for next time
306 68
        $this->new_line = true;
307
308 68
        if (!$this->persist) {
309
            // Reset once since we only want to use it... once.
310 68
            $this->once = null;
311 68
        }
312 68
    }
313
}
314