Completed
Push — master ( 243ce4...6a66a3 )
by Greg
01:47
created

FormatterOptions::setCsvEscapeChar()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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