Output   A
last analyzed

Complexity

Total Complexity 34

Size/Duplication

Total Lines 307
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Test Coverage

Coverage 96.47%

Importance

Changes 0
Metric Value
wmc 34
lcom 1
cbo 7
dl 0
loc 307
ccs 82
cts 85
cp 0.9647
rs 9.68
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\Exceptions\InvalidArgumentException;
6
use League\CLImate\Exceptions\UnexpectedValueException;
7
use League\CLImate\Util\Writer\WriterInterface;
8
9
class Output
10
{
11
    /**
12
     * The content to be output
13
     *
14
     * @var string $content
15
     */
16
    protected $content;
17
18
    /**
19
     * Whether or not to add a new line after the output
20
     *
21
     * @var boolean $new_line
22
     */
23
    protected $new_line = true;
24
25
    /**
26
     * The array of available writers
27
     *
28
     * @var array[] $writers
29
     */
30
    protected $writers = [];
31
32
    /**
33
     * Default writers when one isn't specifed
34
     *
35
     * @var WriterInterface[] $default
36
     */
37
    protected $default = [];
38
39
    /**
40
     * Writers to be used just once
41
     *
42
     * @var null|array $once
43
     */
44
    protected $once;
45
46 972
    protected $persist = false;
47
48 972
    public function __construct()
49 972
    {
50 972
        $this->add('out', new Writer\StdOut);
51
        $this->add('error', new Writer\StdErr);
52 972
        $this->add('buffer', new Writer\Buffer);
53 972
54
        $this->defaultTo('out');
55
    }
56
57
    /**
58 40
     * Dictate that a new line should not be added after the output
59
     */
60 40
    public function sameLine()
61
    {
62 40
        $this->new_line = false;
63
64
        return $this;
65
    }
66
67
    /**
68
     * Add a writer to the available writers
69
     *
70
     * @param string $key
71
     * @param WriterInterface|array $writer
72
     *
73 972
     * @return \League\CLImate\Util\Output
74
     */
75 972
    public function add($key, $writer)
76
    {
77 972
        $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 75 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...
78
79
        return $this;
80
    }
81
82
    /**
83
     * Set the default writer
84
     *
85 972
     * @param string|array $keys
86
     */
87 972
    public function defaultTo($keys)
88 972
    {
89
        $this->default = $this->getWriters($keys);
90
    }
91
92
    /**
93
     * Add a default writer
94
     *
95 4
     * @param string|array $keys
96
     */
97 4
    public function addDefault($keys)
98 4
    {
99
        $this->default = array_merge($this->default, $this->getWriters($keys));
100
    }
101
102
    /**
103
     * Register a writer to be used just once
104
     *
105
     * @param string|array $keys
106
     *
107 8
     * @return \League\CLImate\Util\Output
108
     */
109 8
    public function once($keys)
110
    {
111 8
        $this->once = $this->getWriters($keys);
112
113
        return $this;
114
    }
115
116
    /**
117
     * Persist or un-persist one time writers (for multi-line output)
118
     *
119
     * @param bool $persist
120
     *
121 4
     * @return \League\CLImate\Util\Output
122
     */
123 4
    public function persist($persist = true)
124
    {
125 4
        $this->persist = (bool) $persist;
126 4
127 4
        if (!$this->persist) {
128
            $this->resetOneTimers();
129 4
        }
130
131
        return $this;
132
    }
133
134
    /**
135
     * Get a specific writer
136
     *
137
     * @param string $writer
138
     *
139
     * @return WriterInterface|array
140 4
     * @throws UnexpectedValueException if writer key doesn't exist
141
     */
142 4
    public function get($writer)
143
    {
144
        if (!array_key_exists($writer, $this->writers)) {
145
            throw new UnexpectedValueException('Unknown writer [' . $writer . ']');
146 4
        }
147 4
148
        if (count($this->writers[$writer]) == 1) {
149
            return reset($this->writers[$writer]);
150
        }
151
152
        return $this->writers[$writer];
153
    }
154
155
    /**
156
     * Get the currently available writers
157
     *
158 4
     * @return array
159
     */
160 4
    public function getAvailable()
161
    {
162 4
        $writers = [];
163 4
164 4
        foreach ($this->writers as $key => $writer) {
165
            $writers[$key] = $this->getReadable($writer);
166 4
        }
167
168
        return $writers;
169
    }
170
171
    /**
172
     * Write the content using the provided writer
173
     *
174 80
     * @param  string $content
175
     */
176 80
    public function write($content)
177 40
    {
178 40
        if ($this->new_line) {
179
            $content .= PHP_EOL;
180 80
        }
181 80
182 68
        foreach ($this->getCurrentWriters() as $writer) {
183
            $writer->write($content);
184 68
        }
185 68
186
        $this->resetOneTimers();
187
    }
188
189
    /**
190
     * Resolve the writer(s) down to an array of WriterInterface classes
191
     *
192
     * @param WriterInterface|array|string $writer
193
     *
194 972
     * @return array
195
     */
196 972
    protected function resolve($writer)
197
    {
198 972
        $resolver = 'resolve' . ucwords(gettype($writer)) . 'Writer';
199 972
200
        if (method_exists($this, $resolver) && $resolved = $this->{$resolver}($writer)) {
201
            return $resolved;
202 8
        }
203
204
        $this->handleUnknownWriter($writer);
205
    }
206
207
    /**
208
     * @param array $writer
209
     *
210 972
     * @return array
211
     */
212 972
    protected function resolveArrayWriter($writer)
213
    {
214
        return Helper::flatten(array_map([$this, 'resolve'], $writer));
215
    }
216
217
    /**
218
     * @param object $writer
219
     *
220 972
     * @return WriterInterface|false
221
     */
222 972
    protected function resolveObjectWriter($writer)
223 972
    {
224
        if ($writer instanceof WriterInterface) {
225
            return $writer;
226 4
        }
227
228
        return false;
229
    }
230
231
    /**
232
     * @param string $writer
233
     *
234 12
     * @return array|false
235
     */
236 12
    protected function resolveStringWriter($writer)
237 8
    {
238
        if (is_string($writer) && array_key_exists($writer, $this->writers)) {
239
            return $this->writers[$writer];
240 4
        }
241
242
        return false;
243
    }
244
245
    /**
246
     * @param mixed $writer
247 8
     * @throws InvalidArgumentException For non-valid writer
248
     */
249
    protected function handleUnknownWriter($writer)
250
    {
251 8
        // If we've gotten this far and don't know what it is,
252 4
        // let's at least try and give a helpful error message
253 4
        if (is_object($writer)) {
254
            throw new InvalidArgumentException('Class [' . get_class($writer) . '] must implement '
255
                                    . 'League\CLImate\Util\Writer\WriterInterface.');
256
        }
257 4
258
        // No idea, just tell them we can't resolve it
259
        throw new InvalidArgumentException('Unable to resolve writer [' . $writer . ']');
260
    }
261
262
    /**
263
     * Get the readable version of the writer(s)
264
     *
265
     * @param array $writer
266
     *
267 4
     * @return string|array
268
     */
269 4
    protected function getReadable(array $writer)
270
    {
271 4
        $classes = array_map('get_class', $writer);
272 4
273
        if (count($classes) == 1) {
274
            return reset($classes);
275 4
        }
276
277
        return $classes;
278
    }
279
280
    /**
281
     * Get the writers based on their keys
282
     *
283
     * @param string|array $keys
284
     *
285 972
     * @return array
286
     */
287 972
    protected function getWriters($keys)
288
    {
289 972
        $writers = array_flip(Helper::toArray($keys));
290
291
        return Helper::flatten(array_intersect_key($this->writers, $writers));
292
    }
293
294
    /**
295 80
     * @return WriterInterface[]
296
     */
297 80
    protected function getCurrentWriters()
298
    {
299
        return $this->once ?: $this->default;
300
    }
301
302
    /**
303 68
     * Reset anything only used for the current content being written
304
     */
305
    protected function resetOneTimers()
306 68
    {
307
        // Reset new line flag for next time
308 68
        $this->new_line = true;
309
310 68
        if (!$this->persist) {
311 68
            // Reset once since we only want to use it... once.
312 68
            $this->once = null;
313
        }
314
    }
315
}
316