PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 3.2.5
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v3.2.5
4.7.0 4.6.1 4.6.0 4.5.5 4.5.4 4.5.3 4.5.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.5 3.2.6 3.2.7 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.7.0 3.7.1 All 111 releases
wp-optimize / vendor / rosell-dk / webp-convert / src / Convert / Converters / BaseTraits / OptionsTrait.php

OptionsTrait.php in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance 3.2.5, at vendor/rosell-dk/webp-convert/src/Convert/Converters/BaseTraits/OptionsTrait.php

582 lines 24.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WebPConvert\Convert\Converters\BaseTraits;
4
5 use WebPConvert\Convert\Converters\Stack;
6 use WebPConvert\Convert\Exceptions\ConversionFailed\ConversionSkippedException;
7 use WebPConvert\Options\Exceptions\InvalidOptionValueException;
8 use WebPConvert\Options\Exceptions\InvalidOptionTypeException;
9
10 use WebPConvert\Options\GhostOption;
11 use WebPConvert\Options\Options;
12 use WebPConvert\Options\OptionFactory;
13
14 /**
15 * Trait for handling options
16 *
17 * This trait is currently only used in the AbstractConverter class. It has been extracted into a
18 * trait in order to bundle the methods concerning options.
19 *
20 * @package WebPConvert
21 * @author Bjørn Rosell <[email protected]>
22 * @since Class available since Release 2.0.0
23 */
24 trait OptionsTrait
25 {
26
27 abstract public function log($msg, $style = '');
28 abstract public function logLn($msg, $style = '');
29 abstract protected function getMimeTypeOfSource();
30
31 /** @var array Provided conversion options (array of simple objects)*/
32 public $providedOptions;
33
34 /** @var array Calculated conversion options (merge of default options and provided options)*/
35 protected $options;
36
37 /** @var Options */
38 protected $options2;
39
40 /**
41 * Get the "general" options (options that are standard in the meaning that they
42 * are generally available (unless specifically marked as unsupported by a given converter)
43 *
44 * @param string $imageType (png | jpeg) The image type - determines the defaults
45 *
46 * @return array Array of options
47 */
48 public function getGeneralOptions($imageType)
49 {
50 $isPng = ($imageType == 'png');
51
52 /*
53 return [
54 //new IntegerOption('auto-limit-adjustment', 5, -100, 100),
55 new BooleanOption('log-call-arguments', false),
56 new BooleanOption('skip', false),
57 new BooleanOption('use-nice', false),
58 new ArrayOption('jpeg', []),
59 new ArrayOption('png', [])
60 ];*/
61
62 $introMd = 'https://github.com/rosell-dk/webp-convert/blob/master/docs/v2.0/' .
63 'converting/introduction-for-converting.md';
64
65 return OptionFactory::createOptions([
66 ['encoding', 'string', [
67 'title' => 'Encoding',
68 'description' => 'Set encoding for the webp. ' .
69 'If you choose "auto", webp-convert will ' .
70 'convert to both lossy and lossless and pick the smallest result',
71 'default' => 'auto',
72 'enum' => ['auto', 'lossy', 'lossless'],
73 'ui' => [
74 'component' => 'select',
75 'links' => [['Guide', $introMd . '#auto-selecting-between-losslesslossy-encoding']],
76 ]
77 ]],
78 ['quality', 'int', [
79 'title' => 'Quality (Lossy)',
80 'description' =>
81 'Quality for lossy encoding. ' .
82 'In case you enable "auto-limit", you can consider this property a maximum quality.',
83 'default' => ($isPng ? 85 : 75),
84 'default-png' => 85,
85 'default-jpeg' => 75,
86 //'minimum' => 0,
87 //'maximum' => 100,
88 "oneOf" => [
89 ["type" => "number", "minimum" => 0, 'maximum' => 100],
90 ["type" => "string", "enum" => ["auto"]]
91 ],
92 'ui' => [
93 'component' => 'slider',
94 'display' => "option('encoding') != 'lossless'"
95 ]
96 ]],
97 ['auto-limit', 'boolean', [
98 'title' => 'Auto-limit',
99 'description' =>
100 'Enable this option to prevent an unnecessarily high quality setting for low ' .
101 'quality jpegs. It works by adjusting quality setting down to the quality of the jpeg. ' .
102 'Converting ie a jpeg with quality:50 to ie quality:80 does not get you better quality ' .
103 'than converting it to quality:80, but it does get you a much bigger file - so you ' .
104 'really should enable this option.' . "\n\n" .
105 'The option is ignored for PNG and never adjusts quality up. ' . "\n\n" .
106 'The feature requires Imagick, ImageMagick or Gmagick in order to detect the quality of ' .
107 'the jpeg. ' . "\n\n" .
108 'PS: The "auto-limit" option is relative new. However, before this option, you could achieve ' .
109 'the same by setting quality to "auto" and specifying a "max-quality" and a "default-quality". ' .
110 'These are deprecated now, but still works.',
111 'default' => true,
112 'ui' => [
113 'component' => 'checkbox',
114 'advanced' => true,
115 'links' => [
116 [
117 'Guide',
118 $introMd . '#preventing-unnecessarily-high-quality-setting-for-low-quality-jpegs'
119 ]
120 ],
121 'display' => "option('encoding') != 'lossless'"
122 ]
123 ]],
124 ['alpha-quality', 'int', [
125 'title' => 'Alpha quality',
126 'description' =>
127 'Quality of alpha channel. ' .
128 'Often, there is no need for high quality transparency layer and in some cases you ' .
129 'can tweak this all the way down to 10 and save a lot in file size. The option only ' .
130 'has effect with lossy encoding, and of course only on images with transparency.',
131 'default' => 85,
132 'minimum' => 0,
133 'maximum' => 100,
134 'ui' => [
135 'component' => 'slider',
136 'links' => [['Guide', $introMd . '#alpha-quality']],
137 'display' => "(option('encoding') != 'lossless') && (imageType!='jpeg')"
138 ]
139 ]],
140 ['near-lossless', 'int', [
141 'title' => '"Near lossless" quality',
142 'description' =>
143 'This option allows you to get impressively better compression for lossless encoding, with ' .
144 'minimal impact on visual quality. The range is 0 (maximum preprocessing) to 100 (no ' .
145 'preprocessing). Read the guide for more info.',
146 'default' => 60,
147 'minimum' => 0,
148 'maximum' => 100,
149 'ui' => [
150 'component' => 'slider',
151 'links' => [['Guide', $introMd . '#near-lossless']],
152 'display' => "option('encoding') != 'lossy'"
153 ]
154 ]],
155 ['metadata', 'string', [
156 'title' => 'Metadata',
157 'description' =>
158 'Determines which metadata that should be copied over to the webp. ' .
159 'Setting it to "all" preserves all metadata, setting it to "none" strips all metadata. ' .
160 '*cwebp* can take a comma-separated list of which kinds of metadata that should be copied ' .
161 '(ie "exif,icc"). *gd* will always remove all metadata and *ffmpeg* will always keep all ' .
162 'metadata. The rest can either strip all or keep all (they will keep all, unless the option ' .
163 'is set to *none*)',
164 'default' => 'none',
165 'ui' => [
166 'component' => 'multi-select',
167 'options' => ['all', 'none', 'exif', 'icc', 'xmp'],
168 ]
169 // TODO: set regex validation
170 ]],
171 ['method', 'int', [
172 'title' => 'Reduction effort (0-6)',
173 'description' =>
174 'Controls the trade off between encoding speed and the compressed file size and quality. ' .
175 'Possible values range from 0 to 6. 0 is fastest. 6 results in best quality and compression. ' .
176 'PS: The option corresponds to the "method" option in libwebp',
177 'default' => 6,
178 'minimum' => 0,
179 'maximum' => 6,
180 'ui' => [
181 'component' => 'slider',
182 'advanced' => true,
183 ]
184 ]],
185 ['sharp-yuv', 'boolean', [
186 'title' => 'Sharp YUV',
187 'description' =>
188 'Better RGB->YUV color conversion (sharper and more accurate) at the expense of a little extra ' .
189 'conversion time.',
190 'default' => true,
191 'ui' => [
192 'component' => 'checkbox',
193 'advanced' => true,
194 'links' => [
195 ['Ctrl.blog', 'https://www.ctrl.blog/entry/webp-sharp-yuv.html'],
196 ],
197 ]
198 ]],
199 ['auto-filter', 'boolean', [
200 'title' => 'Auto-filter',
201 'description' =>
202 'Turns auto-filter on. ' .
203 'This algorithm will spend additional time optimizing the filtering strength to reach a well-' .
204 'balanced quality. Unfortunately, it is extremely expensive in terms of computation. It takes ' .
205 'about 5-10 times longer to do a conversion. A 1MB picture which perhaps typically takes about ' .
206 '2 seconds to convert, will takes about 15 seconds to convert with auto-filter. ',
207 'default' => false,
208 'ui' => [
209 'component' => 'checkbox',
210 'advanced' => true,
211 ]
212 ]],
213 ['low-memory', 'boolean', [
214 'title' => 'Low memory',
215 'description' =>
216 'Reduce memory usage of lossy encoding at the cost of ~30% longer encoding time and marginally ' .
217 'larger output size. Only effective when the *method* option is 3 or more. Read more in ' .
218 '[the docs](https://developers.google.com/speed/webp/docs/cwebp)',
219 'default' => false,
220 'ui' => [
221 'component' => 'checkbox',
222 'advanced' => true,
223 'display' => "(option('encoding') != 'lossless') && (option('method')>2)"
224 ]
225 ]],
226 ['preset', 'string', [
227 'title' => 'Preset',
228 'description' =>
229 'Using a preset will set many of the other options to suit a particular type of ' .
230 'source material. It even overrides them. It does however not override the quality option. ' .
231 '"none" means that no preset will be set',
232 'default' => 'none',
233 'enum' => ['none', 'default', 'photo', 'picture', 'drawing', 'icon', 'text'],
234 'ui' => [
235 'component' => 'select',
236 'advanced' => true,
237 ]
238 ]],
239 ['size-in-percentage', 'int', ['default' => null, 'minimum' => 0, 'maximum' => 100, 'allow-null' => true]],
240 ['skip', 'boolean', ['default' => false]],
241 ['log-call-arguments', 'boolean', ['default' => false]],
242 // TODO: use-nice should not be a "general" option
243 //['use-nice', 'boolean', ['default' => false]],
244 ['jpeg', 'array', ['default' => []]],
245 ['png', 'array', ['default' => []]],
246
247 // Deprecated options
248 ['default-quality', 'int', [
249 'default' => ($isPng ? 85 : 75),
250 'minimum' => 0,
251 'maximum' => 100,
252 'deprecated' => true]
253 ],
254 ['max-quality', 'int', ['default' => 85, 'minimum' => 0, 'maximum' => 100, 'deprecated' => true]],
255 ]);
256 }
257
258 /**
259 * Get the unique options for a converter
260 *
261 * @param string $imageType (png | jpeg) The image type - determines the defaults
262 *
263 * @return array Array of options
264 */
265 public function getUniqueOptions($imageType)
266 {
267 return [];
268 }
269
270 /**
271 * Create options.
272 *
273 * The options created here will be available to all converters.
274 * Individual converters may add options by overriding this method.
275 *
276 * @param string $imageType (png | jpeg) The image type - determines the defaults
277 *
278 * @return void
279 */
280 protected function createOptions($imageType = 'png')
281 {
282 $this->options2 = new Options();
283 $this->options2->addOptions(... $this->getGeneralOptions($imageType));
284 $this->options2->addOptions(... $this->getUniqueOptions($imageType));
285 }
286
287 /**
288 * Set "provided options" (options provided by the user when calling convert().
289 *
290 * This also calculates the protected options array, by merging in the default options, merging
291 * jpeg and png options and merging prefixed options (such as 'vips-quality').
292 * The resulting options array are set in the protected property $this->options and can be
293 * retrieved using the public ::getOptions() function.
294 *
295 * @param array $providedOptions (optional)
296 * @return void
297 */
298 public function setProvidedOptions($providedOptions = [])
299 {
300 $imageType = ($this->getMimeTypeOfSource() == 'image/png' ? 'png' : 'jpeg');
301 $this->createOptions($imageType);
302
303 $this->providedOptions = $providedOptions;
304
305 if (isset($this->providedOptions['png'])) {
306 if ($this->getMimeTypeOfSource() == 'image/png') {
307 $this->providedOptions = array_merge($this->providedOptions, $this->providedOptions['png']);
308 // $this->logLn(print_r($this->providedOptions, true));
309 unset($this->providedOptions['png']);
310 }
311 }
312
313 if (isset($this->providedOptions['jpeg'])) {
314 if ($this->getMimeTypeOfSource() == 'image/jpeg') {
315 $this->providedOptions = array_merge($this->providedOptions, $this->providedOptions['jpeg']);
316 unset($this->providedOptions['jpeg']);
317 }
318 }
319
320 // merge down converter-prefixed options
321 $converterId = self::getConverterId();
322 $strLen = strlen($converterId);
323 foreach ($this->providedOptions as $optionKey => $optionValue) {
324 if (substr($optionKey, 0, $strLen + 1) == ($converterId . '-')) {
325 $this->providedOptions[substr($optionKey, $strLen + 1)] = $optionValue;
326 unset($this->providedOptions[$optionKey]);
327 }
328 }
329
330 // Create options (Option objects)
331 foreach ($this->providedOptions as $optionId => $optionValue) {
332 $this->options2->setOrCreateOption($optionId, $optionValue);
333 }
334 //$this->logLn(print_r($this->options2->getOptions(), true));
335 //$this->logLn($this->options2->getOption('hello'));
336
337 // Create flat associative array of options
338 $this->options = $this->options2->getOptions();
339
340 // - Merge $defaultOptions into provided options
341 //$this->options = array_merge($this->getDefaultOptions(), $this->providedOptions);
342
343 //$this->logOptions();
344 }
345
346 /**
347 * Get the resulting options after merging provided options with default options.
348 *
349 * Note that the defaults depends on the mime type of the source. For example, the default value for quality
350 * is "auto" for jpegs, and 85 for pngs.
351 *
352 * @return array An associative array of options: ['metadata' => 'none', ...]
353 */
354 public function getOptions()
355 {
356 return $this->options;
357 }
358
359 /**
360 * Change an option specifically.
361 *
362 * This method is probably rarely neeeded. We are using it to change the "encoding" option temporarily
363 * in the EncodingAutoTrait.
364 *
365 * @param string $id Id of option (ie "metadata")
366 * @param mixed $value The new value.
367 * @return void
368 */
369 protected function setOption($id, $value)
370 {
371 $this->options[$id] = $value;
372 $this->options2->setOrCreateOption($id, $value);
373 }
374
375 /**
376 * Check options.
377 *
378 * @throws InvalidOptionTypeException if an option have wrong type
379 * @throws InvalidOptionValueException if an option value is out of range
380 * @throws ConversionSkippedException if 'skip' option is set to true
381 * @return void
382 */
383 protected function checkOptions()
384 {
385 $this->options2->check();
386
387 if ($this->options['skip']) {
388 if (($this->getMimeTypeOfSource() == 'image/png') && isset($this->options['png']['skip'])) {
389 throw new ConversionSkippedException(
390 'skipped conversion (configured to do so for PNG)'
391 );
392 } else {
393 throw new ConversionSkippedException(
394 'skipped conversion (configured to do so)'
395 );
396 }
397 }
398 }
399
400 public function logOptions()
401 {
402 $this->logLn('');
403 $this->logLn('Options:');
404 $this->logLn('------------');
405
406 $unsupported = $this->getUnsupportedDefaultOptions();
407 $received = [];
408 $implicitlySet = [];
409 foreach ($this->options2->getOptionsMap() as $id => $option) {
410 if (in_array($id, [
411 'png', 'jpeg', '_skip_input_check', '_suppress_success_message', 'skip', 'log_call_arguments'
412 ])) {
413 continue;
414 }
415 if ($option->isValueExplicitlySet()) {
416 $received[] = $option;
417 } else {
418 if (($option instanceof GhostOption) || in_array($id, $unsupported)) {
419 //$received[] = $option;
420 } else {
421 if (!$option->isDeprecated()) {
422 $implicitlySet[] = $option;
423 }
424 }
425 }
426 }
427
428 if (count($received) > 0) {
429 foreach ($received as $option) {
430 $this->log('- ' . $option->getId() . ': ');
431 if ($option instanceof GhostOption) {
432 $this->log(' (unknown to ' . $this->getConverterId() . ')', 'bold');
433 $this->logLn('');
434 continue;
435 }
436 $this->log($option->getValueForPrint());
437 if ($option->isDeprecated()) {
438 $this->log(' (deprecated)', 'bold');
439 }
440 if (in_array($option->getId(), $unsupported)) {
441 if ($this instanceof Stack) {
442 //$this->log(' *(passed on)*');
443 } else {
444 $this->log(' (unsupported by ' . $this->getConverterId() . ')', 'bold');
445 }
446 }
447 $this->logLn('');
448 }
449 $this->logLn('');
450 $this->logLn(
451 'Note that these are the resulting options after merging down the "jpeg" and "png" options and any ' .
452 'converter-prefixed options'
453 );
454 }
455
456 if (count($implicitlySet) > 0) {
457 $this->logLn('');
458 $this->logLn('Defaults:');
459 $this->logLn('------------');
460 $this->logLn(
461 'The following options was not set, so using the following defaults:'
462 );
463 foreach ($implicitlySet as $option) {
464 $this->log('- ' . $option->getId() . ': ');
465 $this->log($option->getValueForPrint());
466 /*if ($option instanceof GhostOption) {
467 $this->log(' **(ghost)**');
468 }*/
469 $this->logLn('');
470 }
471 }
472 }
473
474 // to be overridden by converters
475 protected function getUnsupportedDefaultOptions()
476 {
477 return [];
478 }
479
480 public function getUnsupportedGeneralOptions()
481 {
482 return $this->getUnsupportedDefaultOptions();
483 }
484
485 /**
486 * Get unique option definitions.
487 *
488 * Gets definitions of the converters "unique" options (that is, those options that
489 * are not general). It was added in order to give GUI's a way to automatically adjust
490 * their setting screens.
491 *
492 * @param bool $filterOutOptionsWithoutUI If options without UI defined should be filtered out
493 * @param string $imageType (png | jpeg) The image type - determines the defaults
494 *
495 * @return array Array of options definitions - ready to be json encoded, or whatever
496 */
497 public function getUniqueOptionDefinitions($filterOutOptionsWithoutUI = true, $imageType = 'jpeg')
498 {
499 $uniqueOptions = new Options();
500 //$uniqueOptions->addOptions(... $this->getUniqueOptions($imageType));
501 foreach ($this->getUniqueOptions($imageType) as $uoption) {
502 $uoption->setId(self::getConverterId() . '-' . $uoption->getId());
503 $uniqueOptions->addOption($uoption);
504 }
505
506 $optionDefinitions = $uniqueOptions->getDefinitions();
507 if ($filterOutOptionsWithoutUI) {
508 $optionDefinitions = array_filter($optionDefinitions, function ($value) {
509 return !is_null($value['ui']);
510 });
511 $optionDefinitions = array_values($optionDefinitions); // re-index
512 }
513 return $optionDefinitions;
514 }
515
516 /**
517 * Get general option definitions.
518 *
519 * Gets definitions of all general options (not just the ones supported by current converter)
520 * For UI's, as a way to automatically adjust their setting screens.
521 *
522 * @param bool $filterOutOptionsWithoutUI If options without UI defined should be filtered out
523 * @param string $imageType (png | jpeg) The image type - determines the defaults
524 *
525 * @return array Array of options definitions - ready to be json encoded, or whatever
526 */
527 public function getGeneralOptionDefinitions($filterOutOptionsWithoutUI = true, $imageType = 'jpeg')
528 {
529 $generalOptions = new Options();
530 $generalOptions->addOptions(... $this->getGeneralOptions($imageType));
531 //$generalOptions->setUI($this->getUIForGeneralOptions($imageType));
532 $optionDefinitions = $generalOptions->getDefinitions();
533 if ($filterOutOptionsWithoutUI) {
534 $optionDefinitions = array_filter($optionDefinitions, function ($value) {
535 return !is_null($value['ui']);
536 });
537 $optionDefinitions = array_values($optionDefinitions); // re-index
538 }
539 return $optionDefinitions;
540 }
541
542 public function getSupportedGeneralOptions($imageType = 'png')
543 {
544 $unsupportedGeneral = $this->getUnsupportedDefaultOptions();
545 $generalOptionsArr = $this->getGeneralOptions($imageType);
546 $supportedIds = [];
547 foreach ($generalOptionsArr as $i => $option) {
548 if (in_array($option->getId(), $unsupportedGeneral)) {
549 unset($generalOptionsArr[$i]);
550 }
551 }
552 return $generalOptionsArr;
553 }
554
555 /**
556 * Get general option definitions.
557 *
558 * Gets definitions of the converters "general" options. (that is, those options that
559 * It was added in order to give GUI's a way to automatically adjust their setting screens.
560 *
561 * @param string $imageType (png | jpeg) The image type - determines the defaults
562 *
563 * @return array Array of options definitions - ready to be json encoded, or whatever
564 */
565 public function getSupportedGeneralOptionDefinitions($imageType = 'png')
566 {
567 $generalOptions = new Options();
568 $generalOptions->addOptions(... $this->getSupportedGeneralOptions($imageType));
569 return $generalOptions->getDefinitions();
570 }
571
572 public function getSupportedGeneralOptionIds()
573 {
574 $supportedGeneralOptions = $this->getSupportedGeneralOptions();
575 $supportedGeneralIds = [];
576 foreach ($supportedGeneralOptions as $option) {
577 $supportedGeneralIds[] = $option->getId();
578 }
579 return $supportedGeneralIds;
580 }
581 }
582