Completed
Push — master ( 31aac0...2b5b42 )
by Greg
10s
created

FormatterOptions::setWidth()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
namespace Consolidation\OutputFormatters\Options;
3
4
use Symfony\Component\Console\Input\InputInterface;
5
use Consolidation\OutputFormatters\Transformations\PropertyParser;
6
use Consolidation\OutputFormatters\StructuredData\Xml\XmlSchema;
7
use Consolidation\OutputFormatters\StructuredData\Xml\XmlSchemaInterface;
8
9
/**
10
 * FormetterOptions holds information that affects the way a formatter
11
 * renders its output.
12
 *
13
 * There are three places where a formatter might get options from:
14
 *
15
 * 1. Configuration associated with the command that produced the output.
16
 *    This is passed in to FormatterManager::write() along with the data
17
 *    to format.  It might originally come from annotations on the command,
18
 *    or it might come from another source.  Examples include the field labels
19
 *    for a table, or the default list of fields to display.
20
 *
21
 * 2. Options specified by the user, e.g. by commandline options.
22
 *
23
 * 3. Default values associated with the formatter itself.
24
 *
25
 * This class caches configuration from sources (1) and (2), and expects
26
 * to be provided the defaults, (3), whenever a value is requested.
27
 */
28
class FormatterOptions
29
{
30
    /** var array */
31
    protected $configurationData = [];
32
    /** var array */
33
    protected $options = [];
34
    /** var InputInterface */
35
    protected $input;
36
37
    const FORMAT = 'format';
38
    const DEFAULT_FORMAT = 'default-format';
39
    const TABLE_STYLE = 'table-style';
40
    const LIST_ORIENTATION = 'list-orientation';
41
    const FIELDS = 'fields';
42
    const FIELD = 'field';
43
    const INCLUDE_FIELD_LABELS = 'include-field-labels';
44
    const ROW_LABELS = 'row-labels';
45
    const FIELD_LABELS = 'field-labels';
46
    const DEFAULT_FIELDS = 'default-fields';
47
    const DEFAULT_STRING_FIELD = 'default-string-field';
48
    const DELIMITER = 'delimiter';
49
    const TERMINAL_WIDTH = 'width';
50
51
    /**
52
     * Create a new FormatterOptions with the configuration data and the
53
     * user-specified options for this request.
54
     *
55
     * @see FormatterOptions::setInput()
56
     * @param array $configurationData
57
     * @param array $options
58
     */
59
    public function __construct($configurationData = [], $options = [])
60
    {
61
        $this->configurationData = $configurationData;
62
        $this->options = $options;
63
    }
64
65
    /**
66
     * Create a new FormatterOptions object with new configuration data (provided),
67
     * and the same options data as this instance.
68
     *
69
     * @param array $configurationData
70
     * @return FormatterOptions
71
     */
72
    public function override($configurationData)
73
    {
74
        $override = new self();
75
        $override
76
            ->setConfigurationData($configurationData + $this->getConfigurationData())
77
            ->setOptions($this->getOptions());
78
        return $override;
79
    }
80
81
    public function setTableStyle($style)
82
    {
83
        return $this->setConfigurationValue(self::TABLE_STYLE, $style);
84
    }
85
86
    public function setIncludeFieldLables($includFieldLables)
87
    {
88
        return $this->setConfigurationValue(self::INCLUDE_FIELD_LABELS, $includFieldLables);
89
    }
90
91
    public function setListOrientation($listOrientation)
92
    {
93
        return $this->setConfigurationValue(self::LIST_ORIENTATION, $listOrientation);
94
    }
95
96
    public function setRowLabels($rowLabels)
97
    {
98
        return $this->setConfigurationValue(self::ROW_LABELS, $rowLabels);
99
    }
100
101
    public function setDefaultFields($fields)
102
    {
103
        return $this->setConfigurationValue(self::DEFAULT_FIELDS, $fields);
104
    }
105
106
    public function setFieldLabels($fieldLabels)
107
    {
108
        return $this->setConfigurationValue(self::FIELD_LABELS, $fieldLabels);
109
    }
110
111
    public function setDefaultStringField($defaultStringField)
112
    {
113
        return $this->setConfigurationValue(self::DEFAULT_STRING_FIELD, $defaultStringField);
114
    }
115
116
    public function setWidth($width)
117
    {
118
        return $this->setConfigurationValue(self::TERMINAL_WIDTH, $width);
119
    }
120
121
    /**
122
     * Get a formatter option
123
     *
124
     * @param string $key
125
     * @param array $defaults
126
     * @param mixed $default
127
     * @return mixed
128
     */
129
    public function get($key, $defaults = [], $default = false)
130
    {
131
        $value = $this->fetch($key, $defaults, $default);
132
        return $this->parse($key, $value);
133
    }
134
135
    /**
136
     * Return the XmlSchema to use with --format=xml for data types that support
137
     * that.  This is used when an array needs to be converted into xml.
138
     *
139
     * @return XmlSchema
140
     */
141
    public function getXmlSchema()
142
    {
143
        return new XmlSchema();
144
    }
145
146
    /**
147
     * Determine the format that was requested by the caller.
148
     *
149
     * @param array $defaults
150
     * @return string
151
     */
152
    public function getFormat($defaults = [])
153
    {
154
        return $this->get(self::FORMAT, [], $this->get(self::DEFAULT_FORMAT, $defaults, ''));
155
    }
156
157
    /**
158
     * Look up a key, and return its raw value.
159
     *
160
     * @param string $key
161
     * @param array $defaults
162
     * @param mixed $default
163
     * @return mixed
164
     */
165
    protected function fetch($key, $defaults = [], $default = false)
166
    {
167
        $defaults = $this->defaultsForKey($key, $defaults, $default);
168
        $values = $this->fetchRawValues($defaults);
169
        return $values[$key];
170
    }
171
172
    /**
173
     * Reduce provided defaults to the single item identified by '$key',
174
     * if it exists, or an empty array otherwise.
175
     *
176
     * @param string $key
177
     * @param array $defaults
178
     * @return array
179
     */
180
    protected function defaultsForKey($key, $defaults, $default = false)
181
    {
182
        if (array_key_exists($key, $defaults)) {
183
            return [$key => $defaults[$key]];
184
        }
185
        return [$key => $default];
186
    }
187
188
    /**
189
     * Look up all of the items associated with the provided defaults.
190
     *
191
     * @param array $defaults
192
     * @return array
193
     */
194
    protected function fetchRawValues($defaults = [])
195
    {
196
        return array_merge(
197
            $defaults,
198
            $this->getConfigurationData(),
199
            $this->getOptions(),
200
            $this->getInputOptions($defaults)
201
        );
202
    }
203
204
    /**
205
     * Given the raw value for a specific key, do any type conversion
206
     * (e.g. from a textual list to an array) needed for the data.
207
     *
208
     * @param string $key
209
     * @param mixed $value
210
     * @return mixed
211
     */
212
    protected function parse($key, $value)
213
    {
214
        $optionFormat = $this->getOptionFormat($key);
215
        if (!empty($optionFormat) && is_string($value)) {
216
            return $this->$optionFormat($value);
217
        }
218
        return $value;
219
    }
220
221
    /**
222
     * Convert from a textual list to an array
223
     *
224
     * @param string $value
225
     * @return array
226
     */
227
    public function parsePropertyList($value)
228
    {
229
        return PropertyParser::parse($value);
230
    }
231
232
    /**
233
     * Given a specific key, return the class method name of the
234
     * parsing method for data stored under this key.
235
     *
236
     * @param string $key
237
     * @return string
238
     */
239
    protected function getOptionFormat($key)
240
    {
241
        $propertyFormats = [
242
            self::ROW_LABELS => 'PropertyList',
243
            self::FIELD_LABELS => 'PropertyList',
244
        ];
245
        if (array_key_exists($key, $propertyFormats)) {
246
            return "parse{$propertyFormats[$key]}";
247
        }
248
        return '';
249
    }
250
251
    /**
252
     * Change the configuration data for this formatter options object.
253
     *
254
     * @param array $configurationData
255
     * @return FormatterOptions
256
     */
257
    public function setConfigurationData($configurationData)
258
    {
259
        $this->configurationData = $configurationData;
260
        return $this;
261
    }
262
263
    /**
264
     * Change one configuration value for this formatter option.
265
     *
266
     * @param string $key
267
     * @param mixed $value
268
     * @return FormetterOptions
269
     */
270
    protected function setConfigurationValue($key, $value)
271
    {
272
        $this->configurationData[$key] = $value;
273
        return $this;
274
    }
275
276
    /**
277
     * Change one configuration value for this formatter option, but only
278
     * if it does not already have a value set.
279
     *
280
     * @param string $key
281
     * @param mixed $value
282
     * @return FormetterOptions
283
     */
284
    public function setConfigurationDefault($key, $value)
285
    {
286
        if (!array_key_exists($key, $this->configurationData)) {
287
            return $this->setConfigurationValue($key, $value);
288
        }
289
        return $this;
290
    }
291
292
    /**
293
     * Return a reference to the configuration data for this object.
294
     *
295
     * @return array
296
     */
297
    public function getConfigurationData()
298
    {
299
        return $this->configurationData;
300
    }
301
302
    /**
303
     * Set all of the options that were specified by the user for this request.
304
     *
305
     * @param array $options
306
     * @return FormatterOptions
307
     */
308
    public function setOptions($options)
309
    {
310
        $this->options = $options;
311
        return $this;
312
    }
313
314
    /**
315
     * Change one option value specified by the user for this request.
316
     *
317
     * @param string $key
318
     * @param mixed $value
319
     * @return FormatterOptions
320
     */
321
    public function setOption($key, $value)
322
    {
323
        $this->options[$key] = $value;
324
        return $this;
325
    }
326
327
    /**
328
     * Return a reference to the user-specified options for this request.
329
     *
330
     * @return array
331
     */
332
    public function getOptions()
333
    {
334
        return $this->options;
335
    }
336
337
    /**
338
     * Provide a Symfony Console InputInterface containing the user-specified
339
     * options for this request.
340
     *
341
     * @param InputInterface $input
342
     * @return type
343
     */
344
    public function setInput(InputInterface $input)
345
    {
346
        $this->input = $input;
347
    }
348
349
    /**
350
     * Return all of the options from the provided $defaults array that
351
     * exist in our InputInterface object.
352
     *
353
     * @param array $defaults
354
     * @return array
355
     */
356
    public function getInputOptions($defaults)
357
    {
358
        if (!isset($this->input)) {
359
            return [];
360
        }
361
        $options = [];
362
        foreach ($defaults as $key => $value) {
363
            if ($this->input->hasOption($key)) {
364
                $result = $this->input->getOption($key);
365
                if (isset($result)) {
366
                    $options[$key] = $this->input->getOption($key);
367
                }
368
            }
369
        }
370
        return $options;
371
    }
372
}
373