Completed
Push — master ( b520c4...41a82a )
by Bjørn
02:59
created

OptionsTrait::getDefaultOptions()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 4
nop 0
dl 0
loc 12
ccs 9
cts 9
cp 1
crap 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace WebPConvert\Convert\Converters\BaseTraits;
4
5
use WebPConvert\Convert\Exceptions\ConversionFailed\ConversionSkippedException;
6
use WebPConvert\Convert\Exceptions\ConversionFailed\InvalidInput\InvalidOptionTypeException;
7
8
/**
9
 * Trait for handling options
10
 *
11
 * This trait is currently only used in the AbstractConverter class. It has been extracted into a
12
 * trait in order to bundle the methods concerning options.
13
 *
14
 * @package    WebPConvert
15
 * @author     Bjørn Rosell <[email protected]>
16
 * @since      Class available since Release 2.0.0
17
 */
18
trait OptionsTrait
19
{
20
21
    /** @var array  Provided conversion options */
22
    public $providedOptions;
23
24
    /** @var array  Calculated conversion options (merge of default options and provided options)*/
25
    protected $options;
26
27
    abstract protected function getMimeTypeOfSource();
28
29
    /** @var array  Definitions of general options (the options that are available on all converters) */
30
    protected static $optionDefinitionsBasic = [
31
        ['quality', 'number|string', 'auto'],    // PS: Default is altered to 85 for PNG in ::getDefaultOptions()
32
        ['max-quality', 'number', 85],
33
        ['default-quality', 'number', 75],       // PS: Default is altered to 85 for PNG in ::getDefaultOptions()
34
        ['metadata', 'string', 'none'],
35
        ['lossless', 'boolean|string', false],  // PS: Default is altered to "auto" for PNG in ::getDefaultOptions()
36
        ['skip', 'boolean', false],
37
    ];
38
39
    /**
40
     * Set "provided options" (options provided by the user when calling convert().
41
     *
42
     * This also calculates the protected options array, by merging in the default options.
43
     * The resulting options array are set in the protected property $this->options and can be
44
     * retrieved using the public ::getOptions() function.
45
     *
46
     * @param   array $providedOptions (optional)
47
     * @return  void
48
     */
49 33
    public function setProvidedOptions($providedOptions = [])
50
    {
51 33
        $this->providedOptions = $providedOptions;
52
53 33
        if (isset($this->providedOptions['png'])) {
54
            if ($this->getMimeTypeOfSource() == 'image/png') {
55
                $this->providedOptions = array_merge($this->providedOptions, $this->providedOptions['png']);
56
//                $this->logLn(print_r($this->providedOptions, true));
57
            }
58
        }
59
60 33
        if (isset($this->providedOptions['jpeg'])) {
61
            if ($this->getMimeTypeOfSource() == 'image/jpeg') {
62
                $this->providedOptions = array_merge($this->providedOptions, $this->providedOptions['jpeg']);
63
            }
64
        }
65
        // -  Merge $defaultOptions into provided options
66 33
        $this->options = array_merge($this->getDefaultOptions(), $this->providedOptions);
67 33
    }
68
69
    /**
70
     * Get the resulting options after merging provided options with default options.
71
     *
72
     * @return array  An associative array of options: ['metadata' => 'none', ...]
73
     */
74
    public function getOptions()
75
    {
76
        return $this->options;
77
    }
78
79
    /**
80
     * Change an option specifically.
81
     *
82
     * This method is probably rarely neeeded. We are using it to change the "lossless" option temporarily
83
     * in the LosslessAutoTrait.
84
     *
85
     * @param  string  $optionName   Name id of option (ie "metadata")
86
     * @param  mixed   $optionValue  The new value.
87
     * @return void
88
     */
89
    protected function setOption($optionName, $optionValue)
90
    {
91
        $this->options[$optionName] = $optionValue;
92
    }
93
94
95
    /**
96
     * Get default options for the converter.
97
     *
98
     * Note that the defaults depends on the mime type of the source. For example, the default value for quality
99
     * is "auto" for jpegs, and 85 for pngs.
100
     *
101
     * @return array  An associative array of option defaults: ['metadata' => 'none', ...]
102
     */
103 33
    public function getDefaultOptions()
104
    {
105 33
        $defaults = [];
106 33
        foreach ($this->getOptionDefinitions() as list($name, $type, $default)) {
107 33
            $defaults[$name] = $default;
108
        }
109 33
        if ($this->getMimeTypeOfSource() == 'image/png') {
110 17
            $defaults['lossless'] = 'auto';
111 17
            $defaults['quality'] = 85;
112 17
            $defaults['default-quality'] = 85;
113
        }
114 33
        return $defaults;
115
    }
116
117
118
    /**
119
     * Get definitions of general options (those available for all converters)
120
     *
121
     * To get only the extra definitions for a specific converter, call
122
     * ::getOptionDefinitionsExtra(). To get both general and extra, merged together, call ::getOptionDefinitions().
123
     *
124
     * @return array  A numeric array of definitions of general options for the converter.
125
     *                Each definition is a numeric array with three items: [option id, type, default value]
126
     */
127
    public function getGeneralOptionDefinitions()
128
    {
129
        return self::$optionDefinitionsBasic;
130
    }
131
132
    /**
133
     * Get definitions of extra options unique for the actual converter.
134
     *
135
     * @return array  A numeric array of definitions of all options for the converter.
136
     *                Each definition is a numeric array with three items: [option id, type, default value]
137
     */
138
    abstract protected function getOptionDefinitionsExtra();
139
140
    /**
141
     * Get option definitions for the converter (includes both general options and the extra options for the converter)
142
     *
143
     * To get only the general options definitions (those available for all converters), call
144
     * ::getGeneralOptionDefinitions(). To get only the extra definitions for a specific converter, call
145
     * ::getOptionDefinitionsExtra().
146
     *
147
     * @return array  A numeric array of definitions of all options for the converter.
148
     *                Each definition is a numeric array with three items: [option id, type, default value]
149
     */
150 33
    public function getOptionDefinitions()
151
    {
152 33
        return array_merge(self::$optionDefinitionsBasic, $this->getOptionDefinitionsExtra());
153
    }
154
155
    /**
156
     *  Check option types generally (against their definitions).
157
     *
158
     *  @throws InvalidOptionTypeException  if type is invalid
159
     *  @return void
160
     */
161 13
    private function checkOptionTypesGenerally()
162
    {
163 13
        foreach ($this->getOptionDefinitions() as $def) {
164 13
            list($optionName, $optionType) = $def;
165 13
            if (isset($this->providedOptions[$optionName])) {
166 10
                $actualType = gettype($this->providedOptions[$optionName]);
167 10
                if ($actualType != $optionType) {
168 6
                    $optionType = str_replace('number', 'integer|double', $optionType);
169 6
                    if (!in_array($actualType, explode('|', $optionType))) {
170
                        throw new InvalidOptionTypeException(
171
                            'The provided ' . $optionName . ' option is not a ' . $optionType .
172 13
                                ' (it is a ' . $actualType . ')'
173
                        );
174
                    }
175
                }
176
            }
177
        }
178 13
    }
179
180
    /**
181
     *  Check quality option
182
     *
183
     *  @throws InvalidOptionTypeException  if value is out of range
184
     *  @return void
185
     */
186 13
    private function checkQualityOption()
187
    {
188 13
        if (!isset($this->providedOptions['quality'])) {
189 13
            return;
190
        }
191 1
        $optionValue = $this->providedOptions['quality'];
192 1
        if (gettype($optionValue) == 'string') {
193 1
            if ($optionValue != 'auto') {
194
                throw new InvalidOptionTypeException(
195
                    'Quality option must be either "auto" or a number between 0-100. ' .
196 1
                    'A string, "' . $optionValue . '" was given'
197
                );
198
            }
199
        } else {
200
            if (($optionValue < 0) || ($optionValue > 100)) {
201
                throw new InvalidOptionTypeException(
202
                    'Quality option must be either "auto" or a number between 0-100. ' .
203
                        'The number you provided (' . strval($optionValue) . ') is out of range.'
204
                );
205
            }
206
        }
207 1
    }
208
209
    /**
210
     *  Check lossless option
211
     *
212
     *  @throws InvalidOptionTypeException  if value is out of range
213
     *  @return void
214
     */
215 13
    private function checkLosslessOption()
216
    {
217 13
        if (!isset($this->providedOptions['lossless'])) {
218 8
            return;
219
        }
220 6
        $optionValue = $this->providedOptions['lossless'];
221 6
        if ((gettype($optionValue) == 'string') && ($optionValue != 'auto')) {
222
            throw new InvalidOptionTypeException(
223
                'Lossless option must be true, false or "auto". It was set to: "' . $optionValue . '"'
224
            );
225
        }
226 6
    }
227
228
    /**
229
     *  Check option types.
230
     *
231
     *  @throws InvalidOptionTypeException  if an option value have wrong type or is out of range
232
     *  @return void
233
     */
234 13
    private function checkOptionTypes()
235
    {
236 13
        $this->checkOptionTypesGenerally();
237 13
        $this->checkQualityOption();
238 13
        $this->checkLosslessOption();
239 13
    }
240
241
    /**
242
     *  Check options.
243
     *
244
     *  @throws InvalidOptionTypeException  if an option value have wrong type or is out of range
245
     *  @throws ConversionSkippedException  if 'skip' option is set to true
246
     *  @return void
247
     */
248 13
    protected function checkOptions()
249
    {
250 13
        $this->checkOptionTypes();
251
252 13
        if ($this->options['skip']) {
253
            if (($this->getMimeTypeOfSource() == 'image/png') && isset($this->options['png']['skip'])) {
254
                throw new ConversionSkippedException(
255
                    'skipped conversion (configured to do so for PNG)'
256
                );
257
            } else {
258
                throw new ConversionSkippedException(
259
                    'skipped conversion (configured to do so)'
260
                );
261
            }
262
        }
263 13
    }
264
}
265