Completed
Push — master ( 07093b...5f598b )
by Greg
02:37 queued 42s
created

FormatterOptions::setDelimiter()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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