Completed
Push — master ( 1e6c6a...16c231 )
by Greg
10s
created

FormatterOptions::setListDelimiter()   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 LIST_DELIMITER = 'list-delimiter';
50
    const TERMINAL_WIDTH = 'width';
51
52
    /**
53
     * Create a new FormatterOptions with the configuration data and the
54
     * user-specified options for this request.
55
     *
56
     * @see FormatterOptions::setInput()
57
     * @param array $configurationData
58
     * @param array $options
59
     */
60
    public function __construct($configurationData = [], $options = [])
61
    {
62
        $this->configurationData = $configurationData;
63
        $this->options = $options;
64
    }
65
66
    /**
67
     * Create a new FormatterOptions object with new configuration data (provided),
68
     * and the same options data as this instance.
69
     *
70
     * @param array $configurationData
71
     * @return FormatterOptions
72
     */
73
    public function override($configurationData)
74
    {
75
        $override = new self();
76
        $override
77
            ->setConfigurationData($configurationData + $this->getConfigurationData())
78
            ->setOptions($this->getOptions());
79
        return $override;
80
    }
81
82
    public function setTableStyle($style)
83
    {
84
        return $this->setConfigurationValue(self::TABLE_STYLE, $style);
85
    }
86
87
    public function setDelimiter($delimiter)
88
    {
89
        return $this->setConfigurationValue(self::DELIMITER, $delimiter);
90
    }
91
92
    public function setListDelimiter($listDelimiter)
93
    {
94
        return $this->setConfigurationValue(self::LIST_DELIMITER, $listDelimiter);
95
    }
96
97
98
99
    public function setIncludeFieldLables($includFieldLables)
100
    {
101
        return $this->setConfigurationValue(self::INCLUDE_FIELD_LABELS, $includFieldLables);
102
    }
103
104
    public function setListOrientation($listOrientation)
105
    {
106
        return $this->setConfigurationValue(self::LIST_ORIENTATION, $listOrientation);
107
    }
108
109
    public function setRowLabels($rowLabels)
110
    {
111
        return $this->setConfigurationValue(self::ROW_LABELS, $rowLabels);
112
    }
113
114
    public function setDefaultFields($fields)
115
    {
116
        return $this->setConfigurationValue(self::DEFAULT_FIELDS, $fields);
117
    }
118
119
    public function setFieldLabels($fieldLabels)
120
    {
121
        return $this->setConfigurationValue(self::FIELD_LABELS, $fieldLabels);
122
    }
123
124
    public function setDefaultStringField($defaultStringField)
125
    {
126
        return $this->setConfigurationValue(self::DEFAULT_STRING_FIELD, $defaultStringField);
127
    }
128
129
    public function setWidth($width)
130
    {
131
        return $this->setConfigurationValue(self::TERMINAL_WIDTH, $width);
132
    }
133
134
    /**
135
     * Get a formatter option
136
     *
137
     * @param string $key
138
     * @param array $defaults
139
     * @param mixed $default
140
     * @return mixed
141
     */
142
    public function get($key, $defaults = [], $default = false)
143
    {
144
        $value = $this->fetch($key, $defaults, $default);
145
        return $this->parse($key, $value);
146
    }
147
148
    /**
149
     * Return the XmlSchema to use with --format=xml for data types that support
150
     * that.  This is used when an array needs to be converted into xml.
151
     *
152
     * @return XmlSchema
153
     */
154
    public function getXmlSchema()
155
    {
156
        return new XmlSchema();
157
    }
158
159
    /**
160
     * Determine the format that was requested by the caller.
161
     *
162
     * @param array $defaults
163
     * @return string
164
     */
165
    public function getFormat($defaults = [])
166
    {
167
        return $this->get(self::FORMAT, [], $this->get(self::DEFAULT_FORMAT, $defaults, ''));
168
    }
169
170
    /**
171
     * Look up a key, and return its raw value.
172
     *
173
     * @param string $key
174
     * @param array $defaults
175
     * @param mixed $default
176
     * @return mixed
177
     */
178
    protected function fetch($key, $defaults = [], $default = false)
179
    {
180
        $defaults = $this->defaultsForKey($key, $defaults, $default);
181
        $values = $this->fetchRawValues($defaults);
182
        return $values[$key];
183
    }
184
185
    /**
186
     * Reduce provided defaults to the single item identified by '$key',
187
     * if it exists, or an empty array otherwise.
188
     *
189
     * @param string $key
190
     * @param array $defaults
191
     * @return array
192
     */
193
    protected function defaultsForKey($key, $defaults, $default = false)
194
    {
195
        if (array_key_exists($key, $defaults)) {
196
            return [$key => $defaults[$key]];
197
        }
198
        return [$key => $default];
199
    }
200
201
    /**
202
     * Look up all of the items associated with the provided defaults.
203
     *
204
     * @param array $defaults
205
     * @return array
206
     */
207
    protected function fetchRawValues($defaults = [])
208
    {
209
        return array_merge(
210
            $defaults,
211
            $this->getConfigurationData(),
212
            $this->getOptions(),
213
            $this->getInputOptions($defaults)
214
        );
215
    }
216
217
    /**
218
     * Given the raw value for a specific key, do any type conversion
219
     * (e.g. from a textual list to an array) needed for the data.
220
     *
221
     * @param string $key
222
     * @param mixed $value
223
     * @return mixed
224
     */
225
    protected function parse($key, $value)
226
    {
227
        $optionFormat = $this->getOptionFormat($key);
228
        if (!empty($optionFormat) && is_string($value)) {
229
            return $this->$optionFormat($value);
230
        }
231
        return $value;
232
    }
233
234
    /**
235
     * Convert from a textual list to an array
236
     *
237
     * @param string $value
238
     * @return array
239
     */
240
    public function parsePropertyList($value)
241
    {
242
        return PropertyParser::parse($value);
243
    }
244
245
    /**
246
     * Given a specific key, return the class method name of the
247
     * parsing method for data stored under this key.
248
     *
249
     * @param string $key
250
     * @return string
251
     */
252
    protected function getOptionFormat($key)
253
    {
254
        $propertyFormats = [
255
            self::ROW_LABELS => 'PropertyList',
256
            self::FIELD_LABELS => 'PropertyList',
257
        ];
258
        if (array_key_exists($key, $propertyFormats)) {
259
            return "parse{$propertyFormats[$key]}";
260
        }
261
        return '';
262
    }
263
264
    /**
265
     * Change the configuration data for this formatter options object.
266
     *
267
     * @param array $configurationData
268
     * @return FormatterOptions
269
     */
270
    public function setConfigurationData($configurationData)
271
    {
272
        $this->configurationData = $configurationData;
273
        return $this;
274
    }
275
276
    /**
277
     * Change one configuration value for this formatter option.
278
     *
279
     * @param string $key
280
     * @param mixed $value
281
     * @return FormetterOptions
282
     */
283
    protected function setConfigurationValue($key, $value)
284
    {
285
        $this->configurationData[$key] = $value;
286
        return $this;
287
    }
288
289
    /**
290
     * Change one configuration value for this formatter option, but only
291
     * if it does not already have a value set.
292
     *
293
     * @param string $key
294
     * @param mixed $value
295
     * @return FormetterOptions
296
     */
297
    public function setConfigurationDefault($key, $value)
298
    {
299
        if (!array_key_exists($key, $this->configurationData)) {
300
            return $this->setConfigurationValue($key, $value);
301
        }
302
        return $this;
303
    }
304
305
    /**
306
     * Return a reference to the configuration data for this object.
307
     *
308
     * @return array
309
     */
310
    public function getConfigurationData()
311
    {
312
        return $this->configurationData;
313
    }
314
315
    /**
316
     * Set all of the options that were specified by the user for this request.
317
     *
318
     * @param array $options
319
     * @return FormatterOptions
320
     */
321
    public function setOptions($options)
322
    {
323
        $this->options = $options;
324
        return $this;
325
    }
326
327
    /**
328
     * Change one option value specified by the user for this request.
329
     *
330
     * @param string $key
331
     * @param mixed $value
332
     * @return FormatterOptions
333
     */
334
    public function setOption($key, $value)
335
    {
336
        $this->options[$key] = $value;
337
        return $this;
338
    }
339
340
    /**
341
     * Return a reference to the user-specified options for this request.
342
     *
343
     * @return array
344
     */
345
    public function getOptions()
346
    {
347
        return $this->options;
348
    }
349
350
    /**
351
     * Provide a Symfony Console InputInterface containing the user-specified
352
     * options for this request.
353
     *
354
     * @param InputInterface $input
355
     * @return type
356
     */
357
    public function setInput(InputInterface $input)
358
    {
359
        $this->input = $input;
360
    }
361
362
    /**
363
     * Return all of the options from the provided $defaults array that
364
     * exist in our InputInterface object.
365
     *
366
     * @param array $defaults
367
     * @return array
368
     */
369
    public function getInputOptions($defaults)
370
    {
371
        if (!isset($this->input)) {
372
            return [];
373
        }
374
        $options = [];
375
        foreach ($defaults as $key => $value) {
376
            if ($this->input->hasOption($key)) {
377
                $result = $this->input->getOption($key);
378
                if (isset($result)) {
379
                    $options[$key] = $this->input->getOption($key);
380
                }
381
            }
382
        }
383
        return $options;
384
    }
385
}
386