├── vendor ├── tinify │ └── tinify │ │ ├── .gitignore │ │ ├── test │ │ ├── examples │ │ │ ├── dummy.png │ │ │ └── voormedia.png │ │ ├── helper.php │ │ ├── TinifyResultMetaTest.php │ │ ├── TinifyResultTest.php │ │ ├── integration.php │ │ ├── TinifyTest.php │ │ └── curl_mock.php │ │ ├── CHANGES.md │ │ ├── phpunit.xml │ │ ├── update-cacert.sh │ │ ├── lib │ │ ├── Tinify │ │ │ ├── ResultMeta.php │ │ │ ├── Result.php │ │ │ ├── Exception.php │ │ │ ├── Source.php │ │ │ └── Client.php │ │ └── Tinify.php │ │ ├── composer.json │ │ ├── LICENSE │ │ ├── README.md │ │ └── .travis.yml ├── symfony │ ├── deprecation-contracts │ │ ├── .gitignore │ │ ├── CHANGELOG.md │ │ ├── composer.json │ │ ├── function.php │ │ ├── LICENSE │ │ └── README.md │ ├── polyfill-php80 │ │ ├── Resources │ │ │ └── stubs │ │ │ │ ├── ValueError.php │ │ │ │ ├── UnhandledMatchError.php │ │ │ │ ├── PhpToken.php │ │ │ │ ├── Stringable.php │ │ │ │ └── Attribute.php │ │ ├── README.md │ │ ├── LICENSE │ │ ├── composer.json │ │ ├── bootstrap.php │ │ ├── PhpToken.php │ │ └── Php80.php │ ├── polyfill-php73 │ │ ├── Resources │ │ │ └── stubs │ │ │ │ └── JsonException.php │ │ ├── README.md │ │ ├── Php73.php │ │ ├── LICENSE │ │ ├── bootstrap.php │ │ └── composer.json │ ├── process │ │ ├── Exception │ │ │ ├── ExceptionInterface.php │ │ │ ├── LogicException.php │ │ │ ├── RuntimeException.php │ │ │ ├── InvalidArgumentException.php │ │ │ ├── ProcessSignaledException.php │ │ │ ├── ProcessFailedException.php │ │ │ └── ProcessTimedOutException.php │ │ ├── composer.json │ │ ├── README.md │ │ ├── LICENSE │ │ ├── Pipes │ │ │ ├── PipesInterface.php │ │ │ ├── UnixPipes.php │ │ │ ├── AbstractPipes.php │ │ │ └── WindowsPipes.php │ │ ├── ProcessUtils.php │ │ ├── PhpProcess.php │ │ ├── InputStream.php │ │ ├── ExecutableFinder.php │ │ ├── PhpExecutableFinder.php │ │ └── CHANGELOG.md │ └── options-resolver │ │ ├── Options.php │ │ ├── Exception │ │ ├── ExceptionInterface.php │ │ ├── InvalidArgumentException.php │ │ ├── OptionDefinitionException.php │ │ ├── MissingOptionsException.php │ │ ├── AccessException.php │ │ ├── InvalidOptionsException.php │ │ ├── UndefinedOptionsException.php │ │ ├── NoConfigurationException.php │ │ └── NoSuchOptionException.php │ │ ├── README.md │ │ ├── composer.json │ │ ├── LICENSE │ │ ├── CHANGELOG.md │ │ ├── OptionConfigurator.php │ │ └── Debug │ │ └── OptionsResolverIntrospector.php ├── ps │ └── image-optimizer │ │ ├── .github │ │ └── FUNDING.yml │ │ ├── src │ │ └── ImageOptimizer │ │ │ ├── Exception │ │ │ ├── Exception.php │ │ │ └── CommandNotFound.php │ │ │ ├── WrapperOptimizer.php │ │ │ ├── Optimizer.php │ │ │ ├── TypeGuesser │ │ │ ├── TypeGuesser.php │ │ │ ├── ExtensionTypeGuesser.php │ │ │ ├── GdTypeGuesser.php │ │ │ └── SmartTypeGuesser.php │ │ │ ├── CommandOptimizer.php │ │ │ ├── SmartOptimizer.php │ │ │ ├── SuppressErrorOptimizer.php │ │ │ ├── ChainOptimizer.php │ │ │ ├── ChangedOutputOptimizer.php │ │ │ └── Command.php │ │ ├── .travis.yml │ │ ├── composer.json │ │ ├── LICENSE │ │ ├── CHANGELOG.md │ │ └── README.md ├── psr │ └── log │ │ ├── Psr │ │ └── Log │ │ │ ├── InvalidArgumentException.php │ │ │ ├── Test │ │ │ ├── DummyTest.php │ │ │ ├── TestLogger.php │ │ │ └── LoggerInterfaceTest.php │ │ │ ├── LoggerAwareInterface.php │ │ │ ├── LogLevel.php │ │ │ ├── LoggerAwareTrait.php │ │ │ ├── NullLogger.php │ │ │ ├── LoggerInterface.php │ │ │ ├── AbstractLogger.php │ │ │ └── LoggerTrait.php │ │ ├── composer.json │ │ ├── LICENSE │ │ └── README.md ├── autoload.php └── composer │ ├── autoload_namespaces.php │ ├── autoload_psr4.php │ ├── autoload_files.php │ ├── autoload_classmap.php │ ├── platform_check.php │ ├── LICENSE │ ├── autoload_real.php │ ├── autoload_static.php │ └── installed.php ├── .gitignore ├── pages ├── index.php └── config.php ├── boot.php ├── composer.json ├── uninstall.php ├── .travis.yml ├── package.yml ├── .github └── workflows │ └── publish-to-redaxo.yml ├── lang ├── de_de.lang └── en_gb.lang ├── LICENSE ├── README.md └── lib └── rex_effect_optimize.php /vendor/tinify/tinify/.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | -------------------------------------------------------------------------------- /vendor/tinify/tinify/test/examples/dummy.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vendor/symfony/deprecation-contracts/.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | composer.lock 3 | phpunit.xml 4 | -------------------------------------------------------------------------------- /vendor/ps/image-optimizer/.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [psliwa] 2 | custom: https://www.paypal.me/psliwa 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/.DS_Store 2 | .DS_Store 3 | vendor/composer/* 4 | composer.lock 5 | vendor/autoload.php 6 | composer.lock 7 | -------------------------------------------------------------------------------- /pages/index.php: -------------------------------------------------------------------------------- 1 | i18n('title')); 4 | rex_be_controller::includeCurrentPageSubPath(); 5 | -------------------------------------------------------------------------------- /boot.php: -------------------------------------------------------------------------------- 1 | isAvailable()) { 3 | rex_media_manager::addEffect('rex_effect_optimize'); 4 | } 5 | -------------------------------------------------------------------------------- /vendor/tinify/tinify/test/examples/voormedia.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FriendsOfREDAXO/minify_images/HEAD/vendor/tinify/tinify/test/examples/voormedia.png -------------------------------------------------------------------------------- /vendor/psr/log/Psr/Log/InvalidArgumentException.php: -------------------------------------------------------------------------------- 1 | setQuery('delete from ' . rex::getTable('media_manager_type_effect') . ' where effect = "optimize"'); 5 | } catch (rex_sql_exception $e) { 6 | } 7 | -------------------------------------------------------------------------------- /vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php: -------------------------------------------------------------------------------- 1 | array($vendorDir . '/ps/image-optimizer/src'), 10 | ); 11 | -------------------------------------------------------------------------------- /vendor/tinify/tinify/CHANGES.md: -------------------------------------------------------------------------------- 1 | ## 1.5.2 2 | * Fail early if version of curl/openssl is too old. 3 | 4 | ## 1.5.1 5 | * Expose status of exceptions. 6 | 7 | ## 1.5.0 8 | * Retry failed requests by default. 9 | * Throw clearer errors when curl is installed but disabled. 10 | 11 | ## 1.4.0 12 | * Support for HTTP proxies. 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - '7.1' # REDAXO5.8+ min-php version 5 | 6 | cache: 7 | directories: 8 | - $HOME/.composer/cache 9 | 10 | before_install: 11 | - phpenv config-rm xdebug.ini || echo "xdebug not available" 12 | 13 | script: 14 | - composer require --dev friendsofredaxo/linter 15 | - vendor/bin/rexlint 16 | -------------------------------------------------------------------------------- /vendor/psr/log/Psr/Log/Test/DummyTest.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | test 5 | 6 | 7 | 8 | 9 | lib 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /vendor/psr/log/Psr/Log/LoggerAwareInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | if (\PHP_VERSION_ID < 70300) { 13 | class JsonException extends Exception 14 | { 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /vendor/ps/image-optimizer/src/ImageOptimizer/Optimizer.php: -------------------------------------------------------------------------------- 1 | "$dir/cacert.pem" 18 | -------------------------------------------------------------------------------- /vendor/psr/log/Psr/Log/LoggerAwareTrait.php: -------------------------------------------------------------------------------- 1 | logger = $logger; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /vendor/ps/image-optimizer/src/ImageOptimizer/TypeGuesser/TypeGuesser.php: -------------------------------------------------------------------------------- 1 | meta = $meta; 10 | } 11 | 12 | public function width() { 13 | return intval($this->meta["image-width"]); 14 | } 15 | 16 | public function height() { 17 | return intval($this->meta["image-height"]); 18 | } 19 | 20 | public function location() { 21 | return isset($this->meta["location"]) ? $this->meta["location"] : null; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /vendor/symfony/process/Exception/ExceptionInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Process\Exception; 13 | 14 | /** 15 | * Marker Interface for the Process Component. 16 | * 17 | * @author Johannes M. Schmitt 18 | */ 19 | interface ExceptionInterface extends \Throwable 20 | { 21 | } 22 | -------------------------------------------------------------------------------- /vendor/symfony/process/Exception/LogicException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Process\Exception; 13 | 14 | /** 15 | * LogicException for the Process Component. 16 | * 17 | * @author Romain Neutron 18 | */ 19 | class LogicException extends \LogicException implements ExceptionInterface 20 | { 21 | } 22 | -------------------------------------------------------------------------------- /vendor/symfony/options-resolver/Options.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\OptionsResolver; 13 | 14 | /** 15 | * Contains resolved option values. 16 | * 17 | * @author Bernhard Schussek 18 | * @author Tobias Schultze 19 | */ 20 | interface Options extends \ArrayAccess, \Countable 21 | { 22 | } 23 | -------------------------------------------------------------------------------- /vendor/symfony/process/Exception/RuntimeException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Process\Exception; 13 | 14 | /** 15 | * RuntimeException for the Process Component. 16 | * 17 | * @author Johannes M. Schmitt 18 | */ 19 | class RuntimeException extends \RuntimeException implements ExceptionInterface 20 | { 21 | } 22 | -------------------------------------------------------------------------------- /vendor/symfony/options-resolver/Exception/ExceptionInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\OptionsResolver\Exception; 13 | 14 | /** 15 | * Marker interface for all exceptions thrown by the OptionsResolver component. 16 | * 17 | * @author Bernhard Schussek 18 | */ 19 | interface ExceptionInterface extends \Throwable 20 | { 21 | } 22 | -------------------------------------------------------------------------------- /vendor/symfony/process/Exception/InvalidArgumentException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Process\Exception; 13 | 14 | /** 15 | * InvalidArgumentException for the Process Component. 16 | * 17 | * @author Romain Neutron 18 | */ 19 | class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface 20 | { 21 | } 22 | -------------------------------------------------------------------------------- /vendor/symfony/options-resolver/Exception/InvalidArgumentException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\OptionsResolver\Exception; 13 | 14 | /** 15 | * Thrown when an argument is invalid. 16 | * 17 | * @author Bernhard Schussek 18 | */ 19 | class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface 20 | { 21 | } 22 | -------------------------------------------------------------------------------- /vendor/symfony/options-resolver/Exception/OptionDefinitionException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\OptionsResolver\Exception; 13 | 14 | /** 15 | * Thrown when two lazy options have a cyclic dependency. 16 | * 17 | * @author Bernhard Schussek 18 | */ 19 | class OptionDefinitionException extends \LogicException implements ExceptionInterface 20 | { 21 | } 22 | -------------------------------------------------------------------------------- /vendor/symfony/polyfill-php73/README.md: -------------------------------------------------------------------------------- 1 | Symfony Polyfill / Php73 2 | ======================== 3 | 4 | This component provides functions added to PHP 7.3 core: 5 | 6 | - [`array_key_first`](https://php.net/array_key_first) 7 | - [`array_key_last`](https://php.net/array_key_last) 8 | - [`hrtime`](https://php.net/function.hrtime) 9 | - [`is_countable`](https://php.net/is_countable) 10 | - [`JsonException`](https://php.net/JsonException) 11 | 12 | More information can be found in the 13 | [main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). 14 | 15 | License 16 | ======= 17 | 18 | This library is released under the [MIT license](LICENSE). 19 | -------------------------------------------------------------------------------- /vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php: -------------------------------------------------------------------------------- 1 | flags = $flags; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /vendor/symfony/options-resolver/Exception/MissingOptionsException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\OptionsResolver\Exception; 13 | 14 | /** 15 | * Exception thrown when a required option is missing. 16 | * 17 | * Add the option to the passed options array. 18 | * 19 | * @author Bernhard Schussek 20 | */ 21 | class MissingOptionsException extends InvalidArgumentException 22 | { 23 | } 24 | -------------------------------------------------------------------------------- /vendor/composer/autoload_psr4.php: -------------------------------------------------------------------------------- 1 | array($vendorDir . '/tinify/tinify/lib/Tinify'), 10 | 'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'), 11 | 'Symfony\\Polyfill\\Php73\\' => array($vendorDir . '/symfony/polyfill-php73'), 12 | 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'), 13 | 'Symfony\\Component\\OptionsResolver\\' => array($vendorDir . '/symfony/options-resolver'), 14 | 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), 15 | ); 16 | -------------------------------------------------------------------------------- /vendor/psr/log/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "psr/log", 3 | "description": "Common interface for logging libraries", 4 | "keywords": ["psr", "psr-3", "log"], 5 | "homepage": "https://github.com/php-fig/log", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "PHP-FIG", 10 | "homepage": "https://www.php-fig.org/" 11 | } 12 | ], 13 | "require": { 14 | "php": ">=5.3.0" 15 | }, 16 | "autoload": { 17 | "psr-4": { 18 | "Psr\\Log\\": "Psr/Log/" 19 | } 20 | }, 21 | "extra": { 22 | "branch-alias": { 23 | "dev-master": "1.1.x-dev" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /vendor/composer/autoload_files.php: -------------------------------------------------------------------------------- 1 | $vendorDir . '/symfony/polyfill-php80/bootstrap.php', 10 | '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php', 11 | '0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php', 12 | '74ed299072414d276bb7568fe71d5b0c' => $vendorDir . '/tinify/tinify/lib/Tinify.php', 13 | '9635627915aaea7a98d6d14d04ca5b56' => $vendorDir . '/tinify/tinify/lib/Tinify/Exception.php', 14 | ); 15 | -------------------------------------------------------------------------------- /vendor/ps/image-optimizer/.travis.yml: -------------------------------------------------------------------------------- 1 | dist: xenial 2 | sudo: required 3 | 4 | language: php 5 | 6 | php: 7 | - 7.3 8 | - 7.4 9 | - 8.0 10 | 11 | env: 12 | matrix: 13 | - COMPOSER_FLAGS="--prefer-lowest" 14 | - COMPOSER_FLAGS="" 15 | 16 | before_script: 17 | - sudo apt-get update 18 | - sudo apt-get install jpegoptim 19 | - sudo apt-get install pngquant 20 | - sudo apt-get install gifsicle 21 | - sudo apt-get install optipng 22 | - sudo apt-get install libjpeg-progs 23 | - npm install -g svgo@1.3.2 24 | - travis_retry composer self-update 25 | - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-source 26 | 27 | script: 28 | - vendor/bin/phpunit 29 | -------------------------------------------------------------------------------- /lang/de_de.lang: -------------------------------------------------------------------------------- 1 | minify_images_title = Minify (Bilder) 2 | 3 | minify_images_config = Konfiguration 4 | minify_images_readme = Hilfe und Dokumentation 5 | 6 | minify_images_config_optimization_tool = Optimierungs-Tool 7 | minify_images_config_tinify_key = Tinify API-Key 8 | minify_images_config_tinify_key_note = https://tinypng.com/developers 9 | minify_images_config_save = Speichern 10 | minify_images_config_saved = Einstellungen wurden gespeichert! 11 | 12 | #permissions 13 | perm_general_minify_images[] = Rechte für Minify (Bilder)-AddOn 14 | perm_general_minify_images[config] = Rechte für die Seite 'Konfiguration' des Minify (Bilder)-AddOns 15 | 16 | #effects 17 | minify_images_effect_optimize = Bild: Minify 18 | -------------------------------------------------------------------------------- /lang/en_gb.lang: -------------------------------------------------------------------------------- 1 | minify_images_title = Minify (Images) 2 | 3 | minify_images_config = Configuration 4 | minify_images_readme = Help and documentation 5 | 6 | minify_images_config_optimization_tool = Optimization tool 7 | minify_images_config_tinify_key = Tinify API key 8 | minify_images_config_tinify_key_note = https://tinypng.com/developers 9 | minify_images_config_save = Save 10 | minify_images_config_saved = Settings successfully saved! 11 | 12 | #permissions 13 | perm_general_minify_images[] = Permissions for the Minify (images) addOn 14 | perm_general_minify_images[config] = Permissions for the page 'configuration' of the Minify (images) addOn 15 | 16 | #effects 17 | minify_images_effect_optimize = Image: Minify 18 | -------------------------------------------------------------------------------- /vendor/symfony/options-resolver/README.md: -------------------------------------------------------------------------------- 1 | OptionsResolver Component 2 | ========================= 3 | 4 | The OptionsResolver component is `array_replace` on steroids. It allows you to 5 | create an options system with required options, defaults, validation (type, 6 | value), normalization and more. 7 | 8 | Resources 9 | --------- 10 | 11 | * [Documentation](https://symfony.com/doc/current/components/options_resolver.html) 12 | * [Contributing](https://symfony.com/doc/current/contributing/index.html) 13 | * [Report issues](https://github.com/symfony/symfony/issues) and 14 | [send Pull Requests](https://github.com/symfony/symfony/pulls) 15 | in the [main Symfony repository](https://github.com/symfony/symfony) 16 | -------------------------------------------------------------------------------- /vendor/symfony/options-resolver/Exception/AccessException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\OptionsResolver\Exception; 13 | 14 | /** 15 | * Thrown when trying to read an option outside of or write it inside of 16 | * {@link \Symfony\Component\OptionsResolver\Options::resolve()}. 17 | * 18 | * @author Bernhard Schussek 19 | */ 20 | class AccessException extends \LogicException implements ExceptionInterface 21 | { 22 | } 23 | -------------------------------------------------------------------------------- /vendor/symfony/options-resolver/Exception/InvalidOptionsException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\OptionsResolver\Exception; 13 | 14 | /** 15 | * Thrown when the value of an option does not match its validation rules. 16 | * 17 | * You should make sure a valid value is passed to the option. 18 | * 19 | * @author Bernhard Schussek 20 | */ 21 | class InvalidOptionsException extends InvalidArgumentException 22 | { 23 | } 24 | -------------------------------------------------------------------------------- /vendor/symfony/options-resolver/Exception/UndefinedOptionsException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\OptionsResolver\Exception; 13 | 14 | /** 15 | * Exception thrown when an undefined option is passed. 16 | * 17 | * You should remove the options in question from your code or define them 18 | * beforehand. 19 | * 20 | * @author Bernhard Schussek 21 | */ 22 | class UndefinedOptionsException extends InvalidArgumentException 23 | { 24 | } 25 | -------------------------------------------------------------------------------- /vendor/tinify/tinify/test/TinifyResultMetaTest.php: -------------------------------------------------------------------------------- 1 | "100")); 8 | $this->assertSame(100, $result->width()); 9 | } 10 | 11 | public function testWithMetadataHeightShouldReturnImageHeight() { 12 | $result = new Tinify\ResultMeta(array("image-height" => "60")); 13 | $this->assertSame(60, $result->height()); 14 | } 15 | 16 | public function testWithMetadataLocationShouldReturnImageLocation() { 17 | $result = new Tinify\ResultMeta(array("location" => "https://example.com/image.png")); 18 | $this->assertSame("https://example.com/image.png", $result->location()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /vendor/psr/log/Psr/Log/NullLogger.php: -------------------------------------------------------------------------------- 1 | logger) { }` 11 | * blocks. 12 | */ 13 | class NullLogger extends AbstractLogger 14 | { 15 | /** 16 | * Logs with an arbitrary level. 17 | * 18 | * @param mixed $level 19 | * @param string $message 20 | * @param array $context 21 | * 22 | * @return void 23 | * 24 | * @throws \Psr\Log\InvalidArgumentException 25 | */ 26 | public function log($level, $message, array $context = array()) 27 | { 28 | // noop 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /vendor/symfony/process/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "symfony/process", 3 | "type": "library", 4 | "description": "Executes commands in sub-processes", 5 | "keywords": [], 6 | "homepage": "https://symfony.com", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "Fabien Potencier", 11 | "email": "fabien@symfony.com" 12 | }, 13 | { 14 | "name": "Symfony Community", 15 | "homepage": "https://symfony.com/contributors" 16 | } 17 | ], 18 | "require": { 19 | "php": ">=7.2.5", 20 | "symfony/polyfill-php80": "^1.16" 21 | }, 22 | "autoload": { 23 | "psr-4": { "Symfony\\Component\\Process\\": "" }, 24 | "exclude-from-classmap": [ 25 | "/Tests/" 26 | ] 27 | }, 28 | "minimum-stability": "dev" 29 | } 30 | -------------------------------------------------------------------------------- /vendor/tinify/tinify/lib/Tinify/Result.php: -------------------------------------------------------------------------------- 1 | meta = $meta; 10 | $this->data = $data; 11 | } 12 | 13 | public function data() { 14 | return $this->data; 15 | } 16 | 17 | public function toBuffer() { 18 | return $this->data; 19 | } 20 | 21 | public function toFile($path) { 22 | return file_put_contents($path, $this->toBuffer()); 23 | } 24 | 25 | public function size() { 26 | return intval($this->meta["content-length"]); 27 | } 28 | 29 | public function mediaType() { 30 | return $this->meta["content-type"]; 31 | } 32 | 33 | public function contentType() { 34 | return $this->mediaType(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /vendor/ps/image-optimizer/src/ImageOptimizer/CommandOptimizer.php: -------------------------------------------------------------------------------- 1 | command = $command; 15 | $this->extraArgs = $extraArgs; 16 | } 17 | 18 | public function optimize(string $filepath): void 19 | { 20 | $customArgs = [$filepath]; 21 | 22 | if($this->extraArgs) { 23 | $customArgs = array_merge( 24 | is_callable($this->extraArgs) ? call_user_func($this->extraArgs, $filepath) : $this->extraArgs, 25 | $customArgs 26 | ); 27 | } 28 | 29 | $this->command->execute($customArgs); 30 | } 31 | } -------------------------------------------------------------------------------- /vendor/symfony/options-resolver/Exception/NoConfigurationException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\OptionsResolver\Exception; 13 | 14 | use Symfony\Component\OptionsResolver\Debug\OptionsResolverIntrospector; 15 | 16 | /** 17 | * Thrown when trying to introspect an option definition property 18 | * for which no value was configured inside the OptionsResolver instance. 19 | * 20 | * @see OptionsResolverIntrospector 21 | * 22 | * @author Maxime Steinhausser 23 | */ 24 | class NoConfigurationException extends \RuntimeException implements ExceptionInterface 25 | { 26 | } 27 | -------------------------------------------------------------------------------- /vendor/composer/autoload_classmap.php: -------------------------------------------------------------------------------- 1 | $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', 10 | 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', 11 | 'JsonException' => $vendorDir . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', 12 | 'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', 13 | 'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', 14 | 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', 15 | 'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', 16 | ); 17 | -------------------------------------------------------------------------------- /vendor/symfony/polyfill-php80/README.md: -------------------------------------------------------------------------------- 1 | Symfony Polyfill / Php80 2 | ======================== 3 | 4 | This component provides features added to PHP 8.0 core: 5 | 6 | - `Stringable` interface 7 | - [`fdiv`](https://php.net/fdiv) 8 | - `ValueError` class 9 | - `UnhandledMatchError` class 10 | - `FILTER_VALIDATE_BOOL` constant 11 | - [`get_debug_type`](https://php.net/get_debug_type) 12 | - [`preg_last_error_msg`](https://php.net/preg_last_error_msg) 13 | - [`str_contains`](https://php.net/str_contains) 14 | - [`str_starts_with`](https://php.net/str_starts_with) 15 | - [`str_ends_with`](https://php.net/str_ends_with) 16 | - [`get_resource_id`](https://php.net/get_resource_id) 17 | 18 | More information can be found in the 19 | [main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md). 20 | 21 | License 22 | ======= 23 | 24 | This library is released under the [MIT license](LICENSE). 25 | -------------------------------------------------------------------------------- /vendor/ps/image-optimizer/src/ImageOptimizer/TypeGuesser/ExtensionTypeGuesser.php: -------------------------------------------------------------------------------- 1 | typeGuessers[] = new GdTypeGuesser(); 18 | } catch (\RuntimeException $e) { 19 | // ignore, skip GdTypeGuesser 20 | } 21 | $this->typeGuessers[] = new ExtensionTypeGuesser(); 22 | } 23 | 24 | public function guess(string $filepath): string 25 | { 26 | foreach($this->typeGuessers as $typeGuesser) { 27 | $type = $typeGuesser->guess($filepath); 28 | 29 | if($type !== self::TYPE_UNKNOWN) { 30 | return $type; 31 | } 32 | } 33 | 34 | return self::TYPE_UNKNOWN; 35 | } 36 | } -------------------------------------------------------------------------------- /vendor/symfony/options-resolver/Exception/NoSuchOptionException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\OptionsResolver\Exception; 13 | 14 | /** 15 | * Thrown when trying to read an option that has no value set. 16 | * 17 | * When accessing optional options from within a lazy option or normalizer you should first 18 | * check whether the optional option is set. You can do this with `isset($options['optional'])`. 19 | * In contrast to the {@link UndefinedOptionsException}, this is a runtime exception that can 20 | * occur when evaluating lazy options. 21 | * 22 | * @author Tobias Schultze 23 | */ 24 | class NoSuchOptionException extends \OutOfBoundsException implements ExceptionInterface 25 | { 26 | } 27 | -------------------------------------------------------------------------------- /vendor/tinify/tinify/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tinify/tinify", 3 | "description": "PHP client for the Tinify API. Tinify compresses your images intelligently. Read more at https://tinify.com.", 4 | "keywords": [ 5 | "tinify", 6 | "tinypng", 7 | "tinyjpg", 8 | "compress", 9 | "images", 10 | "api" 11 | ], 12 | 13 | "homepage": "https://tinify.com/developers", 14 | "license": "MIT", 15 | 16 | "support": { 17 | "email": "support@tinify.com" 18 | }, 19 | 20 | "authors": [{ 21 | "name": "Rolf Timmermans", 22 | "email": "rolftimmermans@voormedia.com" 23 | }], 24 | 25 | "require": { 26 | "php": ">=5.3.0", 27 | "ext-curl": "*", 28 | "ext-json": "*", 29 | "lib-curl": ">=7.20.0" 30 | }, 31 | 32 | "require-dev": { 33 | "symfony/yaml": "~2.0", 34 | "phpunit/phpunit": "~4.0" 35 | }, 36 | 37 | "autoload": { 38 | "files": ["lib/Tinify.php", "lib/Tinify/Exception.php"], 39 | "psr-4": {"Tinify\\": "lib/Tinify/"} 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /vendor/symfony/deprecation-contracts/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "symfony/deprecation-contracts", 3 | "type": "library", 4 | "description": "A generic function and convention to trigger deprecation notices", 5 | "homepage": "https://symfony.com", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Nicolas Grekas", 10 | "email": "p@tchwork.com" 11 | }, 12 | { 13 | "name": "Symfony Community", 14 | "homepage": "https://symfony.com/contributors" 15 | } 16 | ], 17 | "require": { 18 | "php": ">=8.0.2" 19 | }, 20 | "autoload": { 21 | "files": [ 22 | "function.php" 23 | ] 24 | }, 25 | "minimum-stability": "dev", 26 | "extra": { 27 | "branch-alias": { 28 | "dev-main": "3.0-dev" 29 | }, 30 | "thanks": { 31 | "name": "symfony/contracts", 32 | "url": "https://github.com/symfony/contracts" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /vendor/ps/image-optimizer/src/ImageOptimizer/SmartOptimizer.php: -------------------------------------------------------------------------------- 1 | optimizers = $optimizers; 21 | $this->typeGuesser = $typeGuesser ?: new SmartTypeGuesser(); 22 | } 23 | 24 | public function optimize(string $filepath): void 25 | { 26 | $type = $this->typeGuesser->guess($filepath); 27 | 28 | if(!isset($this->optimizers[$type])) { 29 | throw new Exception(sprintf('Optimizer for type "%s" not found.', $type)); 30 | } 31 | 32 | $this->optimizers[$type]->optimize($filepath); 33 | } 34 | } -------------------------------------------------------------------------------- /vendor/composer/platform_check.php: -------------------------------------------------------------------------------- 1 | = 80002)) { 8 | $issues[] = 'Your Composer dependencies require a PHP version ">= 8.0.2". You are running ' . PHP_VERSION . '.'; 9 | } 10 | 11 | if ($issues) { 12 | if (!headers_sent()) { 13 | header('HTTP/1.1 500 Internal Server Error'); 14 | } 15 | if (!ini_get('display_errors')) { 16 | if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { 17 | fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL); 18 | } elseif (!headers_sent()) { 19 | echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; 20 | } 21 | } 22 | trigger_error( 23 | 'Composer detected issues in your platform: ' . implode(' ', $issues), 24 | E_USER_ERROR 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /vendor/ps/image-optimizer/src/ImageOptimizer/SuppressErrorOptimizer.php: -------------------------------------------------------------------------------- 1 | optimizer = $optimizer; 18 | $this->logger = $logger; 19 | } 20 | 21 | public function optimize(string $filepath): void 22 | { 23 | try { 24 | $this->optimizer->optimize($filepath); 25 | } catch (Exception $e) { 26 | $this->logger->error('Error during image optimization. See exception for more details.', [ 'exception' => $e ]); 27 | } 28 | } 29 | 30 | public function unwrap(): Optimizer 31 | { 32 | return $this->optimizer instanceof WrapperOptimizer ? $this->optimizer->unwrap() : $this->optimizer; 33 | } 34 | } -------------------------------------------------------------------------------- /vendor/symfony/options-resolver/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "symfony/options-resolver", 3 | "type": "library", 4 | "description": "Provides an improved replacement for the array_replace PHP function", 5 | "keywords": ["options", "config", "configuration"], 6 | "homepage": "https://symfony.com", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "Fabien Potencier", 11 | "email": "fabien@symfony.com" 12 | }, 13 | { 14 | "name": "Symfony Community", 15 | "homepage": "https://symfony.com/contributors" 16 | } 17 | ], 18 | "require": { 19 | "php": ">=7.2.5", 20 | "symfony/deprecation-contracts": "^2.1|^3", 21 | "symfony/polyfill-php73": "~1.0", 22 | "symfony/polyfill-php80": "^1.16" 23 | }, 24 | "autoload": { 25 | "psr-4": { "Symfony\\Component\\OptionsResolver\\": "" }, 26 | "exclude-from-classmap": [ 27 | "/Tests/" 28 | ] 29 | }, 30 | "minimum-stability": "dev" 31 | } 32 | -------------------------------------------------------------------------------- /vendor/ps/image-optimizer/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ps/image-optimizer", 3 | "type": "library", 4 | "description": "Image optimization / compression library. This library is able to optimize png, jpg and gif files in very easy and handy way. It uses optipng, pngquant, pngcrush, pngout, gifsicle, jpegoptim and jpegtran tools.", 5 | "keywords": ["image optimizer", "compression", "image", "optimization", "jpegoptim", "optipng"], 6 | "minimum-stability": "stable", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "Piotr Sliwa", 11 | "email": "peter.pl7@gmail.com" 12 | } 13 | ], 14 | "autoload": { 15 | "psr-0": { 16 | "ImageOptimizer": "src/" 17 | } 18 | }, 19 | "require": { 20 | "php": "^7.3 | ^8.0", 21 | "symfony/process": "~3.3 | ~4.0 | ~5.0", 22 | "symfony/options-resolver": "~3.3 | ~4.0 | ~5.0", 23 | "psr/log": "^1.0" 24 | }, 25 | "require-dev": { 26 | "phpunit/phpunit": "^9.0", 27 | "ext-gd": "*" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /vendor/symfony/polyfill-php73/Php73.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Polyfill\Php73; 13 | 14 | /** 15 | * @author Gabriel Caruso 16 | * @author Ion Bazan 17 | * 18 | * @internal 19 | */ 20 | final class Php73 21 | { 22 | public static $startAt = 1533462603; 23 | 24 | /** 25 | * @param bool $asNum 26 | * 27 | * @return array|float|int 28 | */ 29 | public static function hrtime($asNum = false) 30 | { 31 | $ns = microtime(false); 32 | $s = substr($ns, 11) - self::$startAt; 33 | $ns = 1E9 * (float) $ns; 34 | 35 | if ($asNum) { 36 | $ns += $s * 1E9; 37 | 38 | return \PHP_INT_SIZE === 4 ? $ns : (int) $ns; 39 | } 40 | 41 | return [$s, (int) $ns]; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /vendor/symfony/process/README.md: -------------------------------------------------------------------------------- 1 | Process Component 2 | ================= 3 | 4 | The Process component executes commands in sub-processes. 5 | 6 | Sponsor 7 | ------- 8 | 9 | The Process component for Symfony 5.4/6.0 is [backed][1] by [SensioLabs][2]. 10 | 11 | As the creator of Symfony, SensioLabs supports companies using Symfony, with an 12 | offering encompassing consultancy, expertise, services, training, and technical 13 | assistance to ensure the success of web application development projects. 14 | 15 | Help Symfony by [sponsoring][3] its development! 16 | 17 | Resources 18 | --------- 19 | 20 | * [Documentation](https://symfony.com/doc/current/components/process.html) 21 | * [Contributing](https://symfony.com/doc/current/contributing/index.html) 22 | * [Report issues](https://github.com/symfony/symfony/issues) and 23 | [send Pull Requests](https://github.com/symfony/symfony/pulls) 24 | in the [main Symfony repository](https://github.com/symfony/symfony) 25 | 26 | [1]: https://symfony.com/backers 27 | [2]: https://sensiolabs.com 28 | [3]: https://symfony.com/sponsor 29 | -------------------------------------------------------------------------------- /vendor/ps/image-optimizer/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Piotr Śliwa 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Friends Of REDAXO 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/symfony/polyfill-php80/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 Fabien Potencier 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/symfony/process/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2004-2022 Fabien Potencier 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/symfony/polyfill-php73/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018-2019 Fabien Potencier 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/composer/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Copyright (c) Nils Adermann, Jordi Boggiano 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is furnished 9 | to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | 22 | -------------------------------------------------------------------------------- /vendor/psr/log/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 PHP Framework Interoperability Group 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/symfony/deprecation-contracts/function.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | if (!function_exists('trigger_deprecation')) { 13 | /** 14 | * Triggers a silenced deprecation notice. 15 | * 16 | * @param string $package The name of the Composer package that is triggering the deprecation 17 | * @param string $version The version of the package that introduced the deprecation 18 | * @param string $message The message of the deprecation 19 | * @param mixed ...$args Values to insert in the message using printf() formatting 20 | * 21 | * @author Nicolas Grekas 22 | */ 23 | function trigger_deprecation(string $package, string $version, string $message, mixed ...$args): void 24 | { 25 | @trigger_error(($package || $version ? "Since $package $version: " : '').($args ? vsprintf($message, $args) : $message), \E_USER_DEPRECATED); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /vendor/symfony/options-resolver/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2004-2022 Fabien Potencier 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/symfony/deprecation-contracts/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020-2022 Fabien Potencier 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/tinify/tinify/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2013-2018 Tinify 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/symfony/polyfill-php73/bootstrap.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | use Symfony\Polyfill\Php73 as p; 13 | 14 | if (\PHP_VERSION_ID >= 70300) { 15 | return; 16 | } 17 | 18 | if (!function_exists('is_countable')) { 19 | function is_countable($value) { return is_array($value) || $value instanceof Countable || $value instanceof ResourceBundle || $value instanceof SimpleXmlElement; } 20 | } 21 | if (!function_exists('hrtime')) { 22 | require_once __DIR__.'/Php73.php'; 23 | p\Php73::$startAt = (int) microtime(true); 24 | function hrtime($as_number = false) { return p\Php73::hrtime($as_number); } 25 | } 26 | if (!function_exists('array_key_first')) { 27 | function array_key_first(array $array) { foreach ($array as $key => $value) { return $key; } } 28 | } 29 | if (!function_exists('array_key_last')) { 30 | function array_key_last(array $array) { return key(array_slice($array, -1, 1, true)); } 31 | } 32 | -------------------------------------------------------------------------------- /vendor/symfony/polyfill-php73/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "symfony/polyfill-php73", 3 | "type": "library", 4 | "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", 5 | "keywords": ["polyfill", "shim", "compatibility", "portable"], 6 | "homepage": "https://symfony.com", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "Nicolas Grekas", 11 | "email": "p@tchwork.com" 12 | }, 13 | { 14 | "name": "Symfony Community", 15 | "homepage": "https://symfony.com/contributors" 16 | } 17 | ], 18 | "require": { 19 | "php": ">=7.1" 20 | }, 21 | "autoload": { 22 | "psr-4": { "Symfony\\Polyfill\\Php73\\": "" }, 23 | "files": [ "bootstrap.php" ], 24 | "classmap": [ "Resources/stubs" ] 25 | }, 26 | "minimum-stability": "dev", 27 | "extra": { 28 | "branch-alias": { 29 | "dev-main": "1.23-dev" 30 | }, 31 | "thanks": { 32 | "name": "symfony/polyfill", 33 | "url": "https://github.com/symfony/polyfill" 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /vendor/symfony/process/Exception/ProcessSignaledException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Process\Exception; 13 | 14 | use Symfony\Component\Process\Process; 15 | 16 | /** 17 | * Exception that is thrown when a process has been signaled. 18 | * 19 | * @author Sullivan Senechal 20 | */ 21 | final class ProcessSignaledException extends RuntimeException 22 | { 23 | private $process; 24 | 25 | public function __construct(Process $process) 26 | { 27 | $this->process = $process; 28 | 29 | parent::__construct(sprintf('The process has been signaled with signal "%s".', $process->getTermSignal())); 30 | } 31 | 32 | public function getProcess(): Process 33 | { 34 | return $this->process; 35 | } 36 | 37 | public function getSignal(): int 38 | { 39 | return $this->getProcess()->getTermSignal(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /vendor/symfony/polyfill-php80/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "symfony/polyfill-php80", 3 | "type": "library", 4 | "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", 5 | "keywords": ["polyfill", "shim", "compatibility", "portable"], 6 | "homepage": "https://symfony.com", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "Ion Bazan", 11 | "email": "ion.bazan@gmail.com" 12 | }, 13 | { 14 | "name": "Nicolas Grekas", 15 | "email": "p@tchwork.com" 16 | }, 17 | { 18 | "name": "Symfony Community", 19 | "homepage": "https://symfony.com/contributors" 20 | } 21 | ], 22 | "require": { 23 | "php": ">=7.1" 24 | }, 25 | "autoload": { 26 | "psr-4": { "Symfony\\Polyfill\\Php80\\": "" }, 27 | "files": [ "bootstrap.php" ], 28 | "classmap": [ "Resources/stubs" ] 29 | }, 30 | "minimum-stability": "dev", 31 | "extra": { 32 | "branch-alias": { 33 | "dev-main": "1.23-dev" 34 | }, 35 | "thanks": { 36 | "name": "symfony/polyfill", 37 | "url": "https://github.com/symfony/polyfill" 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /vendor/tinify/tinify/lib/Tinify/Exception.php: -------------------------------------------------------------------------------- 1 | = 400 && $status <= 499) { 12 | $klass = "Tinify\ClientException"; 13 | } else if($status >= 500 && $status <= 599) { 14 | $klass = "Tinify\ServerException"; 15 | } else { 16 | $klass = "Tinify\Exception"; 17 | } 18 | 19 | if (empty($message)) $message = "No message was provided"; 20 | return new $klass($message, $type, $status); 21 | } 22 | 23 | function __construct($message, $type = NULL, $status = NULL) { 24 | $this->status = $status; 25 | if ($status) { 26 | parent::__construct($message . " (HTTP " . $status . "/" . $type . ")"); 27 | } else { 28 | parent::__construct($message); 29 | } 30 | } 31 | } 32 | 33 | class AccountException extends Exception {} 34 | class ClientException extends Exception {} 35 | class ServerException extends Exception {} 36 | class ConnectionException extends Exception {} 37 | -------------------------------------------------------------------------------- /vendor/symfony/deprecation-contracts/README.md: -------------------------------------------------------------------------------- 1 | Symfony Deprecation Contracts 2 | ============================= 3 | 4 | A generic function and convention to trigger deprecation notices. 5 | 6 | This package provides a single global function named `trigger_deprecation()` that triggers silenced deprecation notices. 7 | 8 | By using a custom PHP error handler such as the one provided by the Symfony ErrorHandler component, 9 | the triggered deprecations can be caught and logged for later discovery, both on dev and prod environments. 10 | 11 | The function requires at least 3 arguments: 12 | - the name of the Composer package that is triggering the deprecation 13 | - the version of the package that introduced the deprecation 14 | - the message of the deprecation 15 | - more arguments can be provided: they will be inserted in the message using `printf()` formatting 16 | 17 | Example: 18 | ```php 19 | trigger_deprecation('symfony/blockchain', '8.9', 'Using "%s" is deprecated, use "%s" instead.', 'bitcoin', 'fabcoin'); 20 | ``` 21 | 22 | This will generate the following message: 23 | `Since symfony/blockchain 8.9: Using "bitcoin" is deprecated, use "fabcoin" instead.` 24 | 25 | While not necessarily recommended, the deprecation notices can be completely ignored by declaring an empty 26 | `function trigger_deprecation() {}` in your application. 27 | -------------------------------------------------------------------------------- /vendor/ps/image-optimizer/src/ImageOptimizer/ChainOptimizer.php: -------------------------------------------------------------------------------- 1 | optimizers = $optimizers; 21 | $this->executeFirst = $executeFirst; 22 | $this->logger = $logger; 23 | } 24 | 25 | public function optimize(string $filepath): void 26 | { 27 | $exceptions = []; 28 | foreach($this->optimizers as $optimizer) { 29 | try { 30 | $optimizer->optimize($filepath); 31 | 32 | if($this->executeFirst) break; 33 | } catch (Exception $e) { 34 | $this->logger->error('Error during image optimization. See exception for more details.', [ 'exception' => $e ]); 35 | $exceptions[] = $e; 36 | } 37 | } 38 | 39 | if(count($exceptions) === count($this->optimizers)) { 40 | throw new Exception(sprintf('All optimizers failed to optimize the file: %s', $filepath)); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /vendor/tinify/tinify/README.md: -------------------------------------------------------------------------------- 1 | [Build Status](https://travis-ci.org/tinify/tinify-php) 2 | 3 | # Tinify API client for PHP 4 | 5 | PHP client for the Tinify API, used for [TinyPNG](https://tinypng.com) and [TinyJPG](https://tinyjpg.com). Tinify compresses your images intelligently. Read more at [http://tinify.com](http://tinify.com). 6 | 7 | ## Documentation 8 | 9 | [Go to the documentation for the PHP client](https://tinypng.com/developers/reference/php). 10 | 11 | ## Installation 12 | 13 | Install the API client with Composer. Add this to your `composer.json`: 14 | 15 | ```json 16 | { 17 | "require": { 18 | "tinify/tinify": "*" 19 | } 20 | } 21 | ``` 22 | 23 | Then install with: 24 | 25 | ``` 26 | composer install 27 | ``` 28 | 29 | Use autoloading to make the client available in PHP: 30 | 31 | ```php 32 | require_once("vendor/autoload.php"); 33 | ``` 34 | 35 | ## Usage 36 | 37 | ```php 38 | Tinify\setKey("YOUR_API_KEY"); 39 | Tinify\fromFile("unoptimized.png")->toFile("optimized.png"); 40 | ``` 41 | 42 | ## Running tests 43 | 44 | ``` 45 | composer install 46 | vendor/bin/phpunit 47 | ``` 48 | 49 | ### Integration tests 50 | 51 | ``` 52 | composer install 53 | TINIFY_KEY=$YOUR_API_KEY vendor/bin/phpunit --no-configuration test/integration.php 54 | ``` 55 | 56 | ## License 57 | 58 | This software is licensed under the MIT License. [View the license](LICENSE). 59 | -------------------------------------------------------------------------------- /vendor/tinify/tinify/test/TinifyResultTest.php: -------------------------------------------------------------------------------- 1 | "100"), "image data"); 8 | $this->assertSame(100, $result->width()); 9 | } 10 | 11 | public function testWithMetaAndDataHeightShouldReturnImageHeight() { 12 | $result = new Tinify\Result(array("image-height" => "60"), "image data"); 13 | $this->assertSame(60, $result->height()); 14 | } 15 | 16 | public function testWithMetaAndDataLocationShouldReturnNull() { 17 | $result = new Tinify\ResultMeta(array(), "image data"); 18 | $this->assertSame(null, $result->location()); 19 | } 20 | 21 | public function testWithMetaAndDataSizeShouldReturnContentLength() { 22 | $result = new Tinify\Result(array("content-length" => "450"), "image data"); 23 | $this->assertSame(450, $result->size()); 24 | } 25 | 26 | public function testWithMetaAndDataContentTypeShouldReturnMimeType() { 27 | $result = new Tinify\Result(array("content-type" => "image/png"), "image data"); 28 | $this->assertSame("image/png", $result->contentType()); 29 | } 30 | 31 | public function testWithMetaAndDataToBufferShouldReturnImageData() { 32 | $result = new Tinify\Result(array(), "image data"); 33 | $this->assertSame("image data", $result->toBuffer()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /vendor/ps/image-optimizer/src/ImageOptimizer/ChangedOutputOptimizer.php: -------------------------------------------------------------------------------- 1 | outputPattern = $outputPattern; 14 | $this->optimizer = $optimizer; 15 | } 16 | 17 | public function optimize(string $filepath): void 18 | { 19 | $fileInfo = pathinfo($filepath); 20 | $outputFilepath = str_replace( 21 | ['%basename%', '%filename%', '%ext%'], 22 | [$fileInfo['dirname'], $fileInfo['filename'], isset($fileInfo['extension']) ? '.'.$fileInfo['extension'] : ''], 23 | $this->outputPattern 24 | ); 25 | 26 | $outputChanaged = $outputFilepath !== $filepath; 27 | 28 | if ($outputChanaged) { 29 | copy($filepath, $outputFilepath); 30 | $filepath = $outputFilepath; 31 | } 32 | 33 | try { 34 | $this->optimizer->optimize($filepath); 35 | } catch (\Throwable $exception) { 36 | if ($outputChanaged) { 37 | unlink($filepath); 38 | } 39 | 40 | throw $exception; 41 | } 42 | } 43 | 44 | public function unwrap(): Optimizer 45 | { 46 | return $this->optimizer instanceof WrapperOptimizer ? $this->optimizer->unwrap() : $this->optimizer; 47 | } 48 | } -------------------------------------------------------------------------------- /vendor/psr/log/README.md: -------------------------------------------------------------------------------- 1 | PSR Log 2 | ======= 3 | 4 | This repository holds all interfaces/classes/traits related to 5 | [PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md). 6 | 7 | Note that this is not a logger of its own. It is merely an interface that 8 | describes a logger. See the specification for more details. 9 | 10 | Installation 11 | ------------ 12 | 13 | ```bash 14 | composer require psr/log 15 | ``` 16 | 17 | Usage 18 | ----- 19 | 20 | If you need a logger, you can use the interface like this: 21 | 22 | ```php 23 | logger = $logger; 34 | } 35 | 36 | public function doSomething() 37 | { 38 | if ($this->logger) { 39 | $this->logger->info('Doing work'); 40 | } 41 | 42 | try { 43 | $this->doSomethingElse(); 44 | } catch (Exception $exception) { 45 | $this->logger->error('Oh no!', array('exception' => $exception)); 46 | } 47 | 48 | // do something useful 49 | } 50 | } 51 | ``` 52 | 53 | You can then pick one of the implementations of the interface to get a logger. 54 | 55 | If you want to implement the interface, you can require this package and 56 | implement `Psr\Log\LoggerInterface` in your code. Please read the 57 | [specification text](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) 58 | for details. 59 | -------------------------------------------------------------------------------- /vendor/symfony/process/Exception/ProcessFailedException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Process\Exception; 13 | 14 | use Symfony\Component\Process\Process; 15 | 16 | /** 17 | * Exception for failed processes. 18 | * 19 | * @author Johannes M. Schmitt 20 | */ 21 | class ProcessFailedException extends RuntimeException 22 | { 23 | private $process; 24 | 25 | public function __construct(Process $process) 26 | { 27 | if ($process->isSuccessful()) { 28 | throw new InvalidArgumentException('Expected a failed process, but the given process was successful.'); 29 | } 30 | 31 | $error = sprintf('The command "%s" failed.'."\n\nExit Code: %s(%s)\n\nWorking directory: %s", 32 | $process->getCommandLine(), 33 | $process->getExitCode(), 34 | $process->getExitCodeText(), 35 | $process->getWorkingDirectory() 36 | ); 37 | 38 | if (!$process->isOutputDisabled()) { 39 | $error .= sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s", 40 | $process->getOutput(), 41 | $process->getErrorOutput() 42 | ); 43 | } 44 | 45 | parent::__construct($error); 46 | 47 | $this->process = $process; 48 | } 49 | 50 | public function getProcess() 51 | { 52 | return $this->process; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /vendor/symfony/polyfill-php80/bootstrap.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | use Symfony\Polyfill\Php80 as p; 13 | 14 | if (\PHP_VERSION_ID >= 80000) { 15 | return; 16 | } 17 | 18 | if (!defined('FILTER_VALIDATE_BOOL') && defined('FILTER_VALIDATE_BOOLEAN')) { 19 | define('FILTER_VALIDATE_BOOL', \FILTER_VALIDATE_BOOLEAN); 20 | } 21 | 22 | if (!function_exists('fdiv')) { 23 | function fdiv(float $num1, float $num2): float { return p\Php80::fdiv($num1, $num2); } 24 | } 25 | if (!function_exists('preg_last_error_msg')) { 26 | function preg_last_error_msg(): string { return p\Php80::preg_last_error_msg(); } 27 | } 28 | if (!function_exists('str_contains')) { 29 | function str_contains(?string $haystack, ?string $needle): bool { return p\Php80::str_contains($haystack ?? '', $needle ?? ''); } 30 | } 31 | if (!function_exists('str_starts_with')) { 32 | function str_starts_with(?string $haystack, ?string $needle): bool { return p\Php80::str_starts_with($haystack ?? '', $needle ?? ''); } 33 | } 34 | if (!function_exists('str_ends_with')) { 35 | function str_ends_with(?string $haystack, ?string $needle): bool { return p\Php80::str_ends_with($haystack ?? '', $needle ?? ''); } 36 | } 37 | if (!function_exists('get_debug_type')) { 38 | function get_debug_type($value): string { return p\Php80::get_debug_type($value); } 39 | } 40 | if (!function_exists('get_resource_id')) { 41 | function get_resource_id($resource): int { return p\Php80::get_resource_id($resource); } 42 | } 43 | -------------------------------------------------------------------------------- /vendor/symfony/process/Pipes/PipesInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Process\Pipes; 13 | 14 | /** 15 | * PipesInterface manages descriptors and pipes for the use of proc_open. 16 | * 17 | * @author Romain Neutron 18 | * 19 | * @internal 20 | */ 21 | interface PipesInterface 22 | { 23 | public const CHUNK_SIZE = 16384; 24 | 25 | /** 26 | * Returns an array of descriptors for the use of proc_open. 27 | */ 28 | public function getDescriptors(): array; 29 | 30 | /** 31 | * Returns an array of filenames indexed by their related stream in case these pipes use temporary files. 32 | * 33 | * @return string[] 34 | */ 35 | public function getFiles(): array; 36 | 37 | /** 38 | * Reads data in file handles and pipes. 39 | * 40 | * @param bool $blocking Whether to use blocking calls or not 41 | * @param bool $close Whether to close pipes if they've reached EOF 42 | * 43 | * @return string[] An array of read data indexed by their fd 44 | */ 45 | public function readAndWrite(bool $blocking, bool $close = false): array; 46 | 47 | /** 48 | * Returns if the current state has open file handles or pipes. 49 | */ 50 | public function areOpen(): bool; 51 | 52 | /** 53 | * Returns if pipes are able to read output. 54 | */ 55 | public function haveReadSupport(): bool; 56 | 57 | /** 58 | * Closes file handles and pipes. 59 | */ 60 | public function close(); 61 | } 62 | -------------------------------------------------------------------------------- /vendor/tinify/tinify/.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - 5.4 4 | - 5.5 5 | - 5.6 6 | - 7.0 7 | - 7.1 8 | - 7.2 9 | - nightly 10 | env: 11 | global: 12 | secure: BFdcLqU/07l3/NGaSZA5+VSB5FSVSwTL9wAyrJSD1N7jN2HzFTE4xxxmcVrAqq6t+jhZqajXcSf8/DTUKyLcmWXGw3JkseHx3ofHw5p2E4Mp+dUvNMh+3KgAABCPm5zEBUgnhNGwFqL+WA/cgXIJY1/sv87u/mg63ojvf3orKJ3KMxFFsVbGo553XYVsiSUXfzvV3foqPdcV9D0SZ0v7IiLcsuwtDRtfJ/udgSZ2C2LFiOek1dLwbjM3inMBPkfLcpuvC2l8Z1CyW5ptxYRrHHJqCMbdRmmwGH04hxRju54EJKX5PGTyDhfG9Kyiu8/hQCtDL4jNQlVNAKbvHrRTnLogoMKhHMRaAIDMNI+lcQB9OHHuureYAqL7gJvRmE2sfN/OAbzizYJ2z+yXvjaKJsd2htrHff8hgvl0M3guhP+mA5C9ubibzGiCD66kdeqS5tJi3EH7wk9GO75lFm3tlZEWZ4FJCwgyFQRZGMGSRJC5cWvW4QlGLHeVnWwnf9CM9/B2oD21LraccgCZhpIbib5/XJ2vTQO0V2ke3kXT1D9E3P8E2eClxnge1aShUSy+d5kMTNeLxkfalgGEviWqA236XLzS8+MjWzNWy3+roBb63Vh0OPp4GyTO810U16Y5lwCMegVrxusnz9bCo1HbK1w2k8D7Ueb/O7LEFYaZSD4= 13 | matrix: 14 | allow_failures: 15 | - php: nightly 16 | include: 17 | - dist: precise 18 | php: 5.3 19 | - dist: trusty 20 | php: hhvm 21 | - dist: trusty 22 | php: 5.6 23 | env: INTEGRATION_TESTS=true 24 | script: "if [ \"$TRAVIS_PULL_REQUEST\" == \"false\" ]; then vendor/bin/phpunit --no-configuration test/integration.php; fi" 25 | before_script: composer install 26 | script: vendor/bin/phpunit 27 | notifications: 28 | email: false 29 | slack: 30 | secure: W1cEp+ctAD+in3hA/gansbUYrFZsR3EMd7s/XiK2mfAxRRXPCPgCvv0PWpYelJ5F2AnHXkmBP3USKFDhKN+JLmOOxrZpjzh4ve9QSNs4IPgcrU4meQYSgJ3uovS7h4fqAmqhQKL+FpAnrXAmXWGXVPCPtneySsMTyU6kNdmVfulxXRMJ+kLHtFQlT+U7cPYG0f8FkKR2u5CbRsdjUvoZHwbK7jmWpUcCi2O0A1vvMMEMEOG+iuayWW/RbfSfKIgM/SZG0pGYpoAB7I8XfYns7IyLhkJAw18jIWnowF4DuBusNRdr3zIfwC7bSlLKMFYJYpEsiLFCaeGZgp1NbYJ77DvqpwNp9xmoPz9rFGNe7Re+i13pjNWhEnwc5N3St7x8DYNhUC3L0upQ2FWZSomMM7ghlc6GIVtlXYrRJ5AnxIjSWyLRcTRU5Pf/PPRckOTiuLnVgUZNMVIlAHlRV7c/pUVDjbPvjcOajdXnpcd3+5cuKyzCYpXugIfJ9Hzsozq0yCHDKjo8ssAU+5H3mEfB7M25Rtd2awObb3zqOyUPm+J3M/dzql95cF+zj2SWQsBF/ViwkHo+9SoAr/FYqCZveiS0w9vzoKzbGXVDYCfFD+GlEMJ2b8zw4d2sqmIbw24jGq1ZPgczrpD5fcbI2TaheKBkgWvsBJFFO5KbGWqzHIM= 31 | -------------------------------------------------------------------------------- /vendor/symfony/process/Exception/ProcessTimedOutException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Process\Exception; 13 | 14 | use Symfony\Component\Process\Process; 15 | 16 | /** 17 | * Exception that is thrown when a process times out. 18 | * 19 | * @author Johannes M. Schmitt 20 | */ 21 | class ProcessTimedOutException extends RuntimeException 22 | { 23 | public const TYPE_GENERAL = 1; 24 | public const TYPE_IDLE = 2; 25 | 26 | private $process; 27 | private $timeoutType; 28 | 29 | public function __construct(Process $process, int $timeoutType) 30 | { 31 | $this->process = $process; 32 | $this->timeoutType = $timeoutType; 33 | 34 | parent::__construct(sprintf( 35 | 'The process "%s" exceeded the timeout of %s seconds.', 36 | $process->getCommandLine(), 37 | $this->getExceededTimeout() 38 | )); 39 | } 40 | 41 | public function getProcess() 42 | { 43 | return $this->process; 44 | } 45 | 46 | public function isGeneralTimeout() 47 | { 48 | return self::TYPE_GENERAL === $this->timeoutType; 49 | } 50 | 51 | public function isIdleTimeout() 52 | { 53 | return self::TYPE_IDLE === $this->timeoutType; 54 | } 55 | 56 | public function getExceededTimeout() 57 | { 58 | switch ($this->timeoutType) { 59 | case self::TYPE_GENERAL: 60 | return $this->process->getTimeout(); 61 | 62 | case self::TYPE_IDLE: 63 | return $this->process->getIdleTimeout(); 64 | 65 | default: 66 | throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType)); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /vendor/ps/image-optimizer/src/ImageOptimizer/Command.php: -------------------------------------------------------------------------------- 1 | cmd = $bin; 29 | $this->args = $args; 30 | $this->timeout = $timeout; 31 | } 32 | 33 | public function execute(array $customArgs = []): void 34 | { 35 | $process = new Process(array_merge([$this->cmd], $this->args, $customArgs)); 36 | $process->setTimeout($this->timeout); 37 | 38 | try { 39 | $exitCode = $process->run(); 40 | $commandLine = $process->getCommandLine(); 41 | $output = $process->getOutput().PHP_EOL.$process->getErrorOutput(); 42 | 43 | if($exitCode == 127) { 44 | throw new CommandNotFound(sprintf('Command "%s" not found.', $this->cmd)); 45 | } 46 | 47 | if($exitCode !== 0 || stripos($output, 'error') !== false || stripos($output, 'permission') !== false) { 48 | throw new Exception(sprintf('Command failed, return code: %d, command: %s, stderr: %s', $exitCode, $commandLine, trim($output))); 49 | } 50 | } catch(RuntimeException $e) { 51 | throw new Exception($e->getMessage(), $e->getCode(), $e); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /vendor/ps/image-optimizer/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | CHANGELOG 2 | ========= 3 | 4 | * 2.0.5 (2021-09-30) 5 | 6 | * [#77] Fixed the bug that the copied files were not deleted when the optimization failed 7 | 8 | * 2.0.4 (2021-02-23) 9 | 10 | * [#75] Support for PHP8 11 | 12 | * 2.0.2 (2020-01-11) 13 | 14 | * [#73] Support for Symfony 5 15 | 16 | * 2.0.1 (2019-09-24) 17 | 18 | * [#70] Change log level from notice to error and change log message 19 | 20 | * 2.0.0 (2019-07-13) 21 | 22 | * [#21] Add configurable timeout for single optimizer. Use 23 | symfony-process component as an implementation. 24 | * [#60] Skip larger files for pngquant optimizer 25 | * Adopt source code to more modern php versions (7.1+) 26 | * [#61] New option - allow to change output filepath 27 | (`output_filepath_pattern` option) 28 | 29 | * 1.2.2 (2019-06-21) 30 | 31 | * [#58] Easy way to add custom optimizers. 32 | * [#57] Clear error message when "exec" function is not available. 33 | 34 | * 1.2.1 (2018-12-17) 35 | 36 | * [#64] Bump psr/log version to 1.* 37 | 38 | * 1.2.0 (2018-04-11) 39 | 40 | * [#46] Add support for svg files (using svgo library) 41 | 42 | * 1.1.3 (2018-04-09) 43 | 44 | * [#53, #54, #50] Compatibility with Symfony 4 45 | 46 | * 1.1.2 (2017-07-21) 47 | 48 | * [#44] Throw exception for Permissions Denied 49 | 50 | * 1.1.1 (2017-06-28) 51 | 52 | * [#30] Fix "Command not found" issue related to open_basedir 53 | 54 | * 1.1.0 (2017-03-25) 55 | 56 | * [#8] Chain optimizers' better behaviour: 57 | * execute only first successful optimizer by default (new options: `execute_only_first_png_optimizer` and `execute_only_first_jpeg_optimizer`) 58 | * ignore error when first optimizer fails, but second one succeeds 59 | * report an error when all optimizers fail (an error is ignored when `ignore_errors` is enabled) 60 | * BC break - `ChainOptimizer` constructor now requires 2nd parameter, and adds 3rd parameter logger: 61 | ```diff 62 | - public function __construct(array $optimizers, $executeFirst = false) 63 | + public function __construct(array $optimizers, $executeFirst, LoggerInterface $logger) 64 | ``` 65 | -------------------------------------------------------------------------------- /vendor/symfony/process/ProcessUtils.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Process; 13 | 14 | use Symfony\Component\Process\Exception\InvalidArgumentException; 15 | 16 | /** 17 | * ProcessUtils is a bunch of utility methods. 18 | * 19 | * This class contains static methods only and is not meant to be instantiated. 20 | * 21 | * @author Martin Hasoň 22 | */ 23 | class ProcessUtils 24 | { 25 | /** 26 | * This class should not be instantiated. 27 | */ 28 | private function __construct() 29 | { 30 | } 31 | 32 | /** 33 | * Validates and normalizes a Process input. 34 | * 35 | * @param string $caller The name of method call that validates the input 36 | * @param mixed $input The input to validate 37 | * 38 | * @return mixed 39 | * 40 | * @throws InvalidArgumentException In case the input is not valid 41 | */ 42 | public static function validateInput(string $caller, $input) 43 | { 44 | if (null !== $input) { 45 | if (\is_resource($input)) { 46 | return $input; 47 | } 48 | if (\is_string($input)) { 49 | return $input; 50 | } 51 | if (is_scalar($input)) { 52 | return (string) $input; 53 | } 54 | if ($input instanceof Process) { 55 | return $input->getIterator($input::ITER_SKIP_ERR); 56 | } 57 | if ($input instanceof \Iterator) { 58 | return $input; 59 | } 60 | if ($input instanceof \Traversable) { 61 | return new \IteratorIterator($input); 62 | } 63 | 64 | throw new InvalidArgumentException(sprintf('"%s" only accepts strings, Traversable objects or stream resources.', $caller)); 65 | } 66 | 67 | return $input; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Minify (Bilder) 2 | 3 | Das AddOn stellt einen __Effekt für REDAXOs Media Manager__ zur Verfügung, über den Bilder optimiert werden können. Die Optimierung kann direkt auf dem Server oder über einen externen Dienst (TinyPNG) erfolgen. 4 | 5 | ![Screenshot](https://raw.githubusercontent.com/FriendsOfREDAXO/minify_images/assets/minify_images_01.png) 6 | 7 | ### Anwendung 8 | 9 | 1. AddOn installieren und aktivieren. 10 | 2. In der Konfiguration des AddOn eins der angebotenen Optimierungs-Tools auswählen. 11 | 3. In der Konfiguration des Media Managers die gewünschte Bildqualität einstellen. 12 | 4. Dem gewünschten Mediatyp den Effekt `Bild: Minify` hinzufügen. 13 | 14 | #### ImageOptimizer 15 | 16 | ImageOptimizer nutzt verschiedene bekannte Bildoptimierer wie __optipng, pngquant, jpegoptim oder svgo__. Bitte beachten, dass diese auf dem Webserver installiert sein müssen! Infos dazu finden sich in der Dokumentation: [https://github.com/psliwa/image-optimizer](https://github.com/psliwa/image-optimizer) 17 | 18 | #### Tinify (extern) 19 | 20 | Tinify nutzt den __externen Webdienst__ [TinyPNG](https://tinypng.com), der Bilder über einen speziellen Algorithmus optimiert, um eine möglichst geringe Dateigröße bei optimaler Qualität zu erzielen. 21 | 22 | Der Dienst ist in geringem Umfang kostenlos, bei normaler Nutzung aber kostenpflichtig. Es ist eine Anmeldung erforderlich. Danach wird ein __API-Key__ bereitgestellt, der in der Konfiguration des AddOns eingetragen werden muss. 23 | 24 | #### Imagemagick 25 | 26 | Imagemagick ist ein __populärer Bildprozessor__, der leider nicht auf allen Webservern installiert ist. Wenn er jedoch installiert ist, leistet er hervorragende Dienste. 27 | 28 | 29 | ### Funktion 30 | 31 | Das AddOn stellt den Effekt `Bild: Minify` bereit, der im Media Manager angewendet werden kann. Damit wird das Bild dem ausgewählten Optimierungs-Tool übergeben. Sollte dieses Tool aus verschiedenen Gründen nicht funktionieren, greift REDAXOs normaler Bildprozess, und das Bild wird einfach nicht weiter optimiert. Im Fehlerlog (unter System > Logdateien) sollte dann ersichtlich sein, aus welchen Gründen die Optimierung nicht funktioniert hat. 32 | 33 | 34 | ### Credits 35 | 36 | * [Friends Of REDAXO](https://github.com/FriendsOfREDAXO) Gemeinsame REDAXO-Entwicklung! 37 | * [Thomas Kaegi](https://github.com/phoebusryan) für die initiale Entwicklung 38 | -------------------------------------------------------------------------------- /vendor/tinify/tinify/lib/Tinify/Source.php: -------------------------------------------------------------------------------- 1 | request("post", "/shrink", $string); 14 | return new self($response->headers["location"]); 15 | } 16 | 17 | public static function fromUrl($url) { 18 | $body = array("source" => array("url" => $url)); 19 | $response = Tinify::getClient()->request("post", "/shrink", $body); 20 | return new self($response->headers["location"]); 21 | } 22 | 23 | public function __construct($url, $commands = array()) { 24 | $this->url = $url; 25 | $this->commands = $commands; 26 | } 27 | 28 | public function preserve() { 29 | $options = $this->flatten(func_get_args()); 30 | $commands = array_merge($this->commands, array("preserve" => $options)); 31 | return new self($this->url, $commands); 32 | } 33 | 34 | public function resize($options) { 35 | $commands = array_merge($this->commands, array("resize" => $options)); 36 | return new self($this->url, $commands); 37 | } 38 | 39 | public function store($options) { 40 | $response = Tinify::getClient()->request("post", $this->url, 41 | array_merge($this->commands, array("store" => $options))); 42 | return new Result($response->headers, $response->body); 43 | } 44 | 45 | public function result() { 46 | $response = Tinify::getClient()->request("get", $this->url, $this->commands); 47 | return new Result($response->headers, $response->body); 48 | } 49 | 50 | public function toFile($path) { 51 | return $this->result()->toFile($path); 52 | } 53 | 54 | public function toBuffer() { 55 | return $this->result()->toBuffer(); 56 | } 57 | 58 | private static function flatten($options) { 59 | $flattened = array(); 60 | foreach ($options as $option) { 61 | if (is_array($option)) { 62 | $flattened = array_merge($flattened, $option); 63 | } else { 64 | array_push($flattened, $option); 65 | } 66 | } 67 | return $flattened; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /vendor/tinify/tinify/lib/Tinify.php: -------------------------------------------------------------------------------- 1 | request("post", "/shrink"); 90 | } catch (AccountException $err) { 91 | if ($err->status == 429) return true; 92 | throw $err; 93 | } catch (ClientException $err) { 94 | return true; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /vendor/symfony/polyfill-php80/PhpToken.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Polyfill\Php80; 13 | 14 | /** 15 | * @author Fedonyuk Anton 16 | * 17 | * @internal 18 | */ 19 | class PhpToken implements \Stringable 20 | { 21 | /** 22 | * @var int 23 | */ 24 | public $id; 25 | 26 | /** 27 | * @var string 28 | */ 29 | public $text; 30 | 31 | /** 32 | * @var int 33 | */ 34 | public $line; 35 | 36 | /** 37 | * @var int 38 | */ 39 | public $pos; 40 | 41 | public function __construct(int $id, string $text, int $line = -1, int $position = -1) 42 | { 43 | $this->id = $id; 44 | $this->text = $text; 45 | $this->line = $line; 46 | $this->pos = $position; 47 | } 48 | 49 | public function getTokenName(): ?string 50 | { 51 | if ('UNKNOWN' === $name = token_name($this->id)) { 52 | $name = \strlen($this->text) > 1 || \ord($this->text) < 32 ? null : $this->text; 53 | } 54 | 55 | return $name; 56 | } 57 | 58 | /** 59 | * @param int|string|array $kind 60 | */ 61 | public function is($kind): bool 62 | { 63 | foreach ((array) $kind as $value) { 64 | if (\in_array($value, [$this->id, $this->text], true)) { 65 | return true; 66 | } 67 | } 68 | 69 | return false; 70 | } 71 | 72 | public function isIgnorable(): bool 73 | { 74 | return \in_array($this->id, [\T_WHITESPACE, \T_COMMENT, \T_DOC_COMMENT, \T_OPEN_TAG], true); 75 | } 76 | 77 | public function __toString(): string 78 | { 79 | return (string) $this->text; 80 | } 81 | 82 | /** 83 | * @return static[] 84 | */ 85 | public static function tokenize(string $code, int $flags = 0): array 86 | { 87 | $line = 1; 88 | $position = 0; 89 | $tokens = token_get_all($code, $flags); 90 | foreach ($tokens as $index => $token) { 91 | if (\is_string($token)) { 92 | $id = \ord($token); 93 | $text = $token; 94 | } else { 95 | [$id, $text, $line] = $token; 96 | } 97 | $tokens[$index] = new static($id, $text, $line, $position); 98 | $position += \strlen($text); 99 | } 100 | 101 | return $tokens; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /vendor/symfony/process/PhpProcess.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Process; 13 | 14 | use Symfony\Component\Process\Exception\LogicException; 15 | use Symfony\Component\Process\Exception\RuntimeException; 16 | 17 | /** 18 | * PhpProcess runs a PHP script in an independent process. 19 | * 20 | * $p = new PhpProcess(''); 21 | * $p->run(); 22 | * print $p->getOutput()."\n"; 23 | * 24 | * @author Fabien Potencier 25 | */ 26 | class PhpProcess extends Process 27 | { 28 | /** 29 | * @param string $script The PHP script to run (as a string) 30 | * @param string|null $cwd The working directory or null to use the working dir of the current PHP process 31 | * @param array|null $env The environment variables or null to use the same environment as the current PHP process 32 | * @param int $timeout The timeout in seconds 33 | * @param array|null $php Path to the PHP binary to use with any additional arguments 34 | */ 35 | public function __construct(string $script, string $cwd = null, array $env = null, int $timeout = 60, array $php = null) 36 | { 37 | if (null === $php) { 38 | $executableFinder = new PhpExecutableFinder(); 39 | $php = $executableFinder->find(false); 40 | $php = false === $php ? null : array_merge([$php], $executableFinder->findArguments()); 41 | } 42 | if ('phpdbg' === \PHP_SAPI) { 43 | $file = tempnam(sys_get_temp_dir(), 'dbg'); 44 | file_put_contents($file, $script); 45 | register_shutdown_function('unlink', $file); 46 | $php[] = $file; 47 | $script = null; 48 | } 49 | 50 | parent::__construct($php, $cwd, $env, $script, $timeout); 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | */ 56 | public static function fromShellCommandline(string $command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60) 57 | { 58 | throw new LogicException(sprintf('The "%s()" method cannot be called when using "%s".', __METHOD__, self::class)); 59 | } 60 | 61 | /** 62 | * {@inheritdoc} 63 | */ 64 | public function start(callable $callback = null, array $env = []) 65 | { 66 | if (null === $this->getCommandLine()) { 67 | throw new RuntimeException('Unable to find the PHP executable.'); 68 | } 69 | 70 | parent::start($callback, $env); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /vendor/symfony/process/InputStream.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Process; 13 | 14 | use Symfony\Component\Process\Exception\RuntimeException; 15 | 16 | /** 17 | * Provides a way to continuously write to the input of a Process until the InputStream is closed. 18 | * 19 | * @author Nicolas Grekas 20 | * 21 | * @implements \IteratorAggregate 22 | */ 23 | class InputStream implements \IteratorAggregate 24 | { 25 | /** @var callable|null */ 26 | private $onEmpty = null; 27 | private $input = []; 28 | private $open = true; 29 | 30 | /** 31 | * Sets a callback that is called when the write buffer becomes empty. 32 | */ 33 | public function onEmpty(callable $onEmpty = null) 34 | { 35 | $this->onEmpty = $onEmpty; 36 | } 37 | 38 | /** 39 | * Appends an input to the write buffer. 40 | * 41 | * @param resource|string|int|float|bool|\Traversable|null $input The input to append as scalar, 42 | * stream resource or \Traversable 43 | */ 44 | public function write($input) 45 | { 46 | if (null === $input) { 47 | return; 48 | } 49 | if ($this->isClosed()) { 50 | throw new RuntimeException(sprintf('"%s" is closed.', static::class)); 51 | } 52 | $this->input[] = ProcessUtils::validateInput(__METHOD__, $input); 53 | } 54 | 55 | /** 56 | * Closes the write buffer. 57 | */ 58 | public function close() 59 | { 60 | $this->open = false; 61 | } 62 | 63 | /** 64 | * Tells whether the write buffer is closed or not. 65 | */ 66 | public function isClosed() 67 | { 68 | return !$this->open; 69 | } 70 | 71 | /** 72 | * @return \Traversable 73 | */ 74 | #[\ReturnTypeWillChange] 75 | public function getIterator() 76 | { 77 | $this->open = true; 78 | 79 | while ($this->open || $this->input) { 80 | if (!$this->input) { 81 | yield ''; 82 | continue; 83 | } 84 | $current = array_shift($this->input); 85 | 86 | if ($current instanceof \Iterator) { 87 | yield from $current; 88 | } else { 89 | yield $current; 90 | } 91 | if (!$this->input && $this->open && null !== $onEmpty = $this->onEmpty) { 92 | $this->write($onEmpty($this)); 93 | } 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /vendor/symfony/process/ExecutableFinder.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Process; 13 | 14 | /** 15 | * Generic executable finder. 16 | * 17 | * @author Fabien Potencier 18 | * @author Johannes M. Schmitt 19 | */ 20 | class ExecutableFinder 21 | { 22 | private $suffixes = ['.exe', '.bat', '.cmd', '.com']; 23 | 24 | /** 25 | * Replaces default suffixes of executable. 26 | */ 27 | public function setSuffixes(array $suffixes) 28 | { 29 | $this->suffixes = $suffixes; 30 | } 31 | 32 | /** 33 | * Adds new possible suffix to check for executable. 34 | */ 35 | public function addSuffix(string $suffix) 36 | { 37 | $this->suffixes[] = $suffix; 38 | } 39 | 40 | /** 41 | * Finds an executable by name. 42 | * 43 | * @param string $name The executable name (without the extension) 44 | * @param string|null $default The default to return if no executable is found 45 | * @param array $extraDirs Additional dirs to check into 46 | * 47 | * @return string|null 48 | */ 49 | public function find(string $name, string $default = null, array $extraDirs = []) 50 | { 51 | if (ini_get('open_basedir')) { 52 | $searchPath = array_merge(explode(\PATH_SEPARATOR, ini_get('open_basedir')), $extraDirs); 53 | $dirs = []; 54 | foreach ($searchPath as $path) { 55 | // Silencing against https://bugs.php.net/69240 56 | if (@is_dir($path)) { 57 | $dirs[] = $path; 58 | } else { 59 | if (basename($path) == $name && @is_executable($path)) { 60 | return $path; 61 | } 62 | } 63 | } 64 | } else { 65 | $dirs = array_merge( 66 | explode(\PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')), 67 | $extraDirs 68 | ); 69 | } 70 | 71 | $suffixes = ['']; 72 | if ('\\' === \DIRECTORY_SEPARATOR) { 73 | $pathExt = getenv('PATHEXT'); 74 | $suffixes = array_merge($pathExt ? explode(\PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes); 75 | } 76 | foreach ($suffixes as $suffix) { 77 | foreach ($dirs as $dir) { 78 | if (@is_file($file = $dir.\DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === \DIRECTORY_SEPARATOR || @is_executable($file))) { 79 | return $file; 80 | } 81 | } 82 | } 83 | 84 | return $default; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /vendor/composer/autoload_real.php: -------------------------------------------------------------------------------- 1 | = 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); 32 | if ($useStaticLoader) { 33 | require __DIR__ . '/autoload_static.php'; 34 | 35 | call_user_func(\Composer\Autoload\ComposerStaticInitcbd2864030567235a54cb2e210e0f7cb::getInitializer($loader)); 36 | } else { 37 | $map = require __DIR__ . '/autoload_namespaces.php'; 38 | foreach ($map as $namespace => $path) { 39 | $loader->set($namespace, $path); 40 | } 41 | 42 | $map = require __DIR__ . '/autoload_psr4.php'; 43 | foreach ($map as $namespace => $path) { 44 | $loader->setPsr4($namespace, $path); 45 | } 46 | 47 | $classMap = require __DIR__ . '/autoload_classmap.php'; 48 | if ($classMap) { 49 | $loader->addClassMap($classMap); 50 | } 51 | } 52 | 53 | $loader->register(true); 54 | 55 | if ($useStaticLoader) { 56 | $includeFiles = Composer\Autoload\ComposerStaticInitcbd2864030567235a54cb2e210e0f7cb::$files; 57 | } else { 58 | $includeFiles = require __DIR__ . '/autoload_files.php'; 59 | } 60 | foreach ($includeFiles as $fileIdentifier => $file) { 61 | composerRequirecbd2864030567235a54cb2e210e0f7cb($fileIdentifier, $file); 62 | } 63 | 64 | return $loader; 65 | } 66 | } 67 | 68 | /** 69 | * @param string $fileIdentifier 70 | * @param string $file 71 | * @return void 72 | */ 73 | function composerRequirecbd2864030567235a54cb2e210e0f7cb($fileIdentifier, $file) 74 | { 75 | if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { 76 | $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; 77 | 78 | require $file; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /vendor/tinify/tinify/test/integration.php: -------------------------------------------------------------------------------- 1 | toFile($path); 22 | 23 | $size = filesize($path); 24 | $contents = fread(fopen($path, "rb"), $size); 25 | 26 | $this->assertGreaterThan(1000, $size); 27 | $this->assertLessThan(1500, $size); 28 | 29 | /* width == 137 */ 30 | $this->assertContains("\0\0\0\x89", $contents); 31 | $this->assertNotContains("Copyright Voormedia", $contents); 32 | } 33 | 34 | public function testShouldCompressFromUrl() { 35 | $path = tempnam(sys_get_temp_dir(), "tinify-php"); 36 | $source = \Tinify\fromUrl("https://raw.githubusercontent.com/tinify/tinify-php/master/test/examples/voormedia.png"); 37 | $source->toFile($path); 38 | 39 | $size = filesize($path); 40 | $contents = fread(fopen($path, "rb"), $size); 41 | 42 | $this->assertGreaterThan(1000, $size); 43 | $this->assertLessThan(1500, $size); 44 | 45 | /* width == 137 */ 46 | $this->assertContains("\0\0\0\x89", $contents); 47 | $this->assertNotContains("Copyright Voormedia", $contents); 48 | } 49 | 50 | public function testShouldResize() { 51 | $path = tempnam(sys_get_temp_dir(), "tinify-php"); 52 | self::$optimized->resize(array("method" => "fit", "width" => 50, "height" => 20))->toFile($path); 53 | 54 | $size = filesize($path); 55 | $contents = fread(fopen($path, "rb"), $size); 56 | 57 | $this->assertGreaterThan(500, $size); 58 | $this->assertLessThan(1000, $size); 59 | 60 | /* width == 50 */ 61 | $this->assertContains("\0\0\0\x32", $contents); 62 | $this->assertNotContains("Copyright Voormedia", $contents); 63 | } 64 | 65 | public function testShouldPreserveMetadata() { 66 | $path = tempnam(sys_get_temp_dir(), "tinify-php"); 67 | self::$optimized->preserve("copyright", "creation")->toFile($path); 68 | 69 | $size = filesize($path); 70 | $contents = fread(fopen($path, "rb"), $size); 71 | 72 | $this->assertGreaterThan(1000, $size); 73 | $this->assertLessThan(2000, $size); 74 | 75 | /* width == 137 */ 76 | $this->assertContains("\0\0\0\x89", $contents); 77 | $this->assertContains("Copyright Voormedia", $contents); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /pages/config.php: -------------------------------------------------------------------------------- 1 | isValid()) { 8 | 9 | echo rex_view::error(rex_i18n::msg('csrf_token_invalid')); 10 | } else { 11 | 12 | $this->setConfig(rex_post('config', [ 13 | ['optimization_tool', 'string'], 14 | ['tinify_key', 'string'], 15 | ])); 16 | echo rex_view::success($this->i18n('config_saved')); 17 | } 18 | } 19 | 20 | 21 | $content = '
'; 22 | 23 | $formElements = []; 24 | 25 | // optimization_tool 26 | $sel_optimization_tool = new rex_select(); 27 | $sel_optimization_tool->setid('minify-config-optimization_tool'); 28 | $sel_optimization_tool->setName('config[optimization_tool]'); 29 | $sel_optimization_tool->setSize(1); 30 | $sel_optimization_tool->setAttribute('class', 'form-control selectpicker'); 31 | $sel_optimization_tool->setSelected($this->getConfig('optimization_tool')); 32 | $sel_optimization_tool->addOption('', 'none'); 33 | $sel_optimization_tool->addOption('ImageOptimizer (optipng / pngquant / jpegoptim / svgo / …)', 'ImageOptimizer'); 34 | $sel_optimization_tool->addOption('Tinify (tinyJPEG / tinyPNG)', 'Tinify'); 35 | $sel_optimization_tool->addOption('ImageMagick', 'Imagick'); 36 | 37 | $n = []; 38 | $n['label'] = ''; 39 | $n['field'] = $sel_optimization_tool->get(); 40 | $formElements[] = $n; 41 | 42 | // tinify_key 43 | $n = []; 44 | $n['label'] = ''; 45 | $n['field'] = ''; 46 | $n['note'] = $this->i18n('minify_images_config_tinify_key_note'); 47 | $formElements[] = $n; 48 | 49 | $fragment = new rex_fragment(); 50 | $fragment->setVar('elements', $formElements, false); 51 | $content .= $fragment->parse('core/form/container.php'); 52 | 53 | 54 | $formElements = []; 55 | $n = []; 56 | $n['field'] = ''; 57 | $formElements[] = $n; 58 | 59 | $fragment = new rex_fragment(); 60 | $fragment->setVar('flush', true); 61 | $fragment->setVar('elements', $formElements, false); 62 | $buttons = $fragment->parse('core/form/submit.php'); 63 | 64 | 65 | $fragment = new rex_fragment(); 66 | $fragment->setVar('class', 'edit'); 67 | $fragment->setVar('title', $this->i18n('config')); 68 | $fragment->setVar('body', $content, false); 69 | $fragment->setVar('buttons', $buttons, false); 70 | $content = $fragment->parse('core/page/section.php'); 71 | 72 | echo ' 73 |
74 | ' . $csrfToken->getHiddenField() . ' 75 | ' . $content . ' 76 |
'; 77 | -------------------------------------------------------------------------------- /vendor/symfony/process/PhpExecutableFinder.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Process; 13 | 14 | /** 15 | * An executable finder specifically designed for the PHP executable. 16 | * 17 | * @author Fabien Potencier 18 | * @author Johannes M. Schmitt 19 | */ 20 | class PhpExecutableFinder 21 | { 22 | private $executableFinder; 23 | 24 | public function __construct() 25 | { 26 | $this->executableFinder = new ExecutableFinder(); 27 | } 28 | 29 | /** 30 | * Finds The PHP executable. 31 | * 32 | * @return string|false 33 | */ 34 | public function find(bool $includeArgs = true) 35 | { 36 | if ($php = getenv('PHP_BINARY')) { 37 | if (!is_executable($php)) { 38 | $command = '\\' === \DIRECTORY_SEPARATOR ? 'where' : 'command -v'; 39 | if ($php = strtok(exec($command.' '.escapeshellarg($php)), \PHP_EOL)) { 40 | if (!is_executable($php)) { 41 | return false; 42 | } 43 | } else { 44 | return false; 45 | } 46 | } 47 | 48 | if (@is_dir($php)) { 49 | return false; 50 | } 51 | 52 | return $php; 53 | } 54 | 55 | $args = $this->findArguments(); 56 | $args = $includeArgs && $args ? ' '.implode(' ', $args) : ''; 57 | 58 | // PHP_BINARY return the current sapi executable 59 | if (\PHP_BINARY && \in_array(\PHP_SAPI, ['cgi-fcgi', 'cli', 'cli-server', 'phpdbg'], true)) { 60 | return \PHP_BINARY.$args; 61 | } 62 | 63 | if ($php = getenv('PHP_PATH')) { 64 | if (!@is_executable($php) || @is_dir($php)) { 65 | return false; 66 | } 67 | 68 | return $php; 69 | } 70 | 71 | if ($php = getenv('PHP_PEAR_PHP_BIN')) { 72 | if (@is_executable($php) && !@is_dir($php)) { 73 | return $php; 74 | } 75 | } 76 | 77 | if (@is_executable($php = \PHP_BINDIR.('\\' === \DIRECTORY_SEPARATOR ? '\\php.exe' : '/php')) && !@is_dir($php)) { 78 | return $php; 79 | } 80 | 81 | $dirs = [\PHP_BINDIR]; 82 | if ('\\' === \DIRECTORY_SEPARATOR) { 83 | $dirs[] = 'C:\xampp\php\\'; 84 | } 85 | 86 | return $this->executableFinder->find('php', false, $dirs); 87 | } 88 | 89 | /** 90 | * Finds the PHP executable arguments. 91 | * 92 | * @return array 93 | */ 94 | public function findArguments() 95 | { 96 | $arguments = []; 97 | if ('phpdbg' === \PHP_SAPI) { 98 | $arguments[] = '-qrr'; 99 | } 100 | 101 | return $arguments; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /vendor/symfony/options-resolver/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | CHANGELOG 2 | ========= 3 | 4 | 5.3 5 | --- 6 | 7 | * Add prototype definition for nested options 8 | 9 | 5.1.0 10 | ----- 11 | 12 | * added fluent configuration of options using `OptionResolver::define()` 13 | * added `setInfo()` and `getInfo()` methods 14 | * updated the signature of method `OptionsResolver::setDeprecated()` to `OptionsResolver::setDeprecation(string $option, string $package, string $version, $message)` 15 | * deprecated `OptionsResolverIntrospector::getDeprecationMessage()`, use `OptionsResolverIntrospector::getDeprecation()` instead 16 | 17 | 5.0.0 18 | ----- 19 | 20 | * added argument `$triggerDeprecation` to `OptionsResolver::offsetGet()` 21 | 22 | 4.3.0 23 | ----- 24 | 25 | * added `OptionsResolver::addNormalizer` method 26 | 27 | 4.2.0 28 | ----- 29 | 30 | * added support for nested options definition 31 | * added `setDeprecated` and `isDeprecated` methods 32 | 33 | 3.4.0 34 | ----- 35 | 36 | * added `OptionsResolverIntrospector` to inspect options definitions inside an `OptionsResolver` instance 37 | * added array of types support in allowed types (e.g int[]) 38 | 39 | 2.6.0 40 | ----- 41 | 42 | * deprecated OptionsResolverInterface 43 | * [BC BREAK] removed "array" type hint from OptionsResolverInterface methods 44 | setRequired(), setAllowedValues(), addAllowedValues(), setAllowedTypes() and 45 | addAllowedTypes() 46 | * added OptionsResolver::setDefault() 47 | * added OptionsResolver::hasDefault() 48 | * added OptionsResolver::setNormalizer() 49 | * added OptionsResolver::isRequired() 50 | * added OptionsResolver::getRequiredOptions() 51 | * added OptionsResolver::isMissing() 52 | * added OptionsResolver::getMissingOptions() 53 | * added OptionsResolver::setDefined() 54 | * added OptionsResolver::isDefined() 55 | * added OptionsResolver::getDefinedOptions() 56 | * added OptionsResolver::remove() 57 | * added OptionsResolver::clear() 58 | * deprecated OptionsResolver::replaceDefaults() 59 | * deprecated OptionsResolver::setOptional() in favor of setDefined() 60 | * deprecated OptionsResolver::isKnown() in favor of isDefined() 61 | * [BC BREAK] OptionsResolver::isRequired() returns true now if a required 62 | option has a default value set 63 | * [BC BREAK] merged Options into OptionsResolver and turned Options into an 64 | interface 65 | * deprecated Options::overload() (now in OptionsResolver) 66 | * deprecated Options::set() (now in OptionsResolver) 67 | * deprecated Options::get() (now in OptionsResolver) 68 | * deprecated Options::has() (now in OptionsResolver) 69 | * deprecated Options::replace() (now in OptionsResolver) 70 | * [BC BREAK] Options::get() (now in OptionsResolver) can only be used within 71 | lazy option/normalizer closures now 72 | * [BC BREAK] removed Traversable interface from Options since using within 73 | lazy option/normalizer closures resulted in exceptions 74 | * [BC BREAK] removed Options::all() since using within lazy option/normalizer 75 | closures resulted in exceptions 76 | * [BC BREAK] OptionDefinitionException now extends LogicException instead of 77 | RuntimeException 78 | * [BC BREAK] normalizers are not executed anymore for unset options 79 | * normalizers are executed after validating the options now 80 | * [BC BREAK] an UndefinedOptionsException is now thrown instead of an 81 | InvalidOptionsException when non-existing options are passed 82 | -------------------------------------------------------------------------------- /vendor/psr/log/Psr/Log/LoggerInterface.php: -------------------------------------------------------------------------------- 1 | log(LogLevel::EMERGENCY, $message, $context); 25 | } 26 | 27 | /** 28 | * Action must be taken immediately. 29 | * 30 | * Example: Entire website down, database unavailable, etc. This should 31 | * trigger the SMS alerts and wake you up. 32 | * 33 | * @param string $message 34 | * @param mixed[] $context 35 | * 36 | * @return void 37 | */ 38 | public function alert($message, array $context = array()) 39 | { 40 | $this->log(LogLevel::ALERT, $message, $context); 41 | } 42 | 43 | /** 44 | * Critical conditions. 45 | * 46 | * Example: Application component unavailable, unexpected exception. 47 | * 48 | * @param string $message 49 | * @param mixed[] $context 50 | * 51 | * @return void 52 | */ 53 | public function critical($message, array $context = array()) 54 | { 55 | $this->log(LogLevel::CRITICAL, $message, $context); 56 | } 57 | 58 | /** 59 | * Runtime errors that do not require immediate action but should typically 60 | * be logged and monitored. 61 | * 62 | * @param string $message 63 | * @param mixed[] $context 64 | * 65 | * @return void 66 | */ 67 | public function error($message, array $context = array()) 68 | { 69 | $this->log(LogLevel::ERROR, $message, $context); 70 | } 71 | 72 | /** 73 | * Exceptional occurrences that are not errors. 74 | * 75 | * Example: Use of deprecated APIs, poor use of an API, undesirable things 76 | * that are not necessarily wrong. 77 | * 78 | * @param string $message 79 | * @param mixed[] $context 80 | * 81 | * @return void 82 | */ 83 | public function warning($message, array $context = array()) 84 | { 85 | $this->log(LogLevel::WARNING, $message, $context); 86 | } 87 | 88 | /** 89 | * Normal but significant events. 90 | * 91 | * @param string $message 92 | * @param mixed[] $context 93 | * 94 | * @return void 95 | */ 96 | public function notice($message, array $context = array()) 97 | { 98 | $this->log(LogLevel::NOTICE, $message, $context); 99 | } 100 | 101 | /** 102 | * Interesting events. 103 | * 104 | * Example: User logs in, SQL logs. 105 | * 106 | * @param string $message 107 | * @param mixed[] $context 108 | * 109 | * @return void 110 | */ 111 | public function info($message, array $context = array()) 112 | { 113 | $this->log(LogLevel::INFO, $message, $context); 114 | } 115 | 116 | /** 117 | * Detailed debug information. 118 | * 119 | * @param string $message 120 | * @param mixed[] $context 121 | * 122 | * @return void 123 | */ 124 | public function debug($message, array $context = array()) 125 | { 126 | $this->log(LogLevel::DEBUG, $message, $context); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /vendor/composer/autoload_static.php: -------------------------------------------------------------------------------- 1 | __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php', 11 | '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php', 12 | '0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php', 13 | '74ed299072414d276bb7568fe71d5b0c' => __DIR__ . '/..' . '/tinify/tinify/lib/Tinify.php', 14 | '9635627915aaea7a98d6d14d04ca5b56' => __DIR__ . '/..' . '/tinify/tinify/lib/Tinify/Exception.php', 15 | ); 16 | 17 | public static $prefixLengthsPsr4 = array ( 18 | 'T' => 19 | array ( 20 | 'Tinify\\' => 7, 21 | ), 22 | 'S' => 23 | array ( 24 | 'Symfony\\Polyfill\\Php80\\' => 23, 25 | 'Symfony\\Polyfill\\Php73\\' => 23, 26 | 'Symfony\\Component\\Process\\' => 26, 27 | 'Symfony\\Component\\OptionsResolver\\' => 34, 28 | ), 29 | 'P' => 30 | array ( 31 | 'Psr\\Log\\' => 8, 32 | ), 33 | ); 34 | 35 | public static $prefixDirsPsr4 = array ( 36 | 'Tinify\\' => 37 | array ( 38 | 0 => __DIR__ . '/..' . '/tinify/tinify/lib/Tinify', 39 | ), 40 | 'Symfony\\Polyfill\\Php80\\' => 41 | array ( 42 | 0 => __DIR__ . '/..' . '/symfony/polyfill-php80', 43 | ), 44 | 'Symfony\\Polyfill\\Php73\\' => 45 | array ( 46 | 0 => __DIR__ . '/..' . '/symfony/polyfill-php73', 47 | ), 48 | 'Symfony\\Component\\Process\\' => 49 | array ( 50 | 0 => __DIR__ . '/..' . '/symfony/process', 51 | ), 52 | 'Symfony\\Component\\OptionsResolver\\' => 53 | array ( 54 | 0 => __DIR__ . '/..' . '/symfony/options-resolver', 55 | ), 56 | 'Psr\\Log\\' => 57 | array ( 58 | 0 => __DIR__ . '/..' . '/psr/log/Psr/Log', 59 | ), 60 | ); 61 | 62 | public static $prefixesPsr0 = array ( 63 | 'I' => 64 | array ( 65 | 'ImageOptimizer' => 66 | array ( 67 | 0 => __DIR__ . '/..' . '/ps/image-optimizer/src', 68 | ), 69 | ), 70 | ); 71 | 72 | public static $classMap = array ( 73 | 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', 74 | 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 75 | 'JsonException' => __DIR__ . '/..' . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', 76 | 'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php', 77 | 'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', 78 | 'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', 79 | 'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', 80 | ); 81 | 82 | public static function getInitializer(ClassLoader $loader) 83 | { 84 | return \Closure::bind(function () use ($loader) { 85 | $loader->prefixLengthsPsr4 = ComposerStaticInitcbd2864030567235a54cb2e210e0f7cb::$prefixLengthsPsr4; 86 | $loader->prefixDirsPsr4 = ComposerStaticInitcbd2864030567235a54cb2e210e0f7cb::$prefixDirsPsr4; 87 | $loader->prefixesPsr0 = ComposerStaticInitcbd2864030567235a54cb2e210e0f7cb::$prefixesPsr0; 88 | $loader->classMap = ComposerStaticInitcbd2864030567235a54cb2e210e0f7cb::$classMap; 89 | 90 | }, null, ClassLoader::class); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /lib/rex_effect_optimize.php: -------------------------------------------------------------------------------- 1 | media->asImage(); 15 | 16 | $format = $this->media->getFormat(); 17 | $filepath = rex_path::addonCache($this->addonName, 'temp_' . microtime()); 18 | 19 | rex_dir::create(dirname($filepath)); 20 | 21 | switch ($format) { 22 | case 'jpeg': 23 | imagejpeg($this->media->getImage(), $filepath, rex_config::get('media_manager', 'jpg_quality', 80)); 24 | break; 25 | case 'png': 26 | imagepng($this->media->getImage(), $filepath, rex_config::get('media_manager', 'png_compression', 5)); 27 | break; 28 | case 'gif': 29 | imagegif($this->media->getImage(), $filepath); 30 | break; 31 | } 32 | 33 | switch (rex_addon::get($this->addonName)->getConfig('optimization_tool')) { 34 | 35 | case 'ImageOptimizer': 36 | try { 37 | $factory = new OptimizerFactory([ 38 | 'ignore_errors' => false, 39 | ]); 40 | $optimizer = $factory->get(); 41 | $optimizer->optimize($filepath); 42 | } catch (Exception $e) { 43 | rex_logger::logException($e); 44 | } 45 | break; 46 | 47 | case 'Imagick': 48 | if (!extension_loaded('imagick')) { 49 | rex_logger::logError(E_WARNING, 'Minify: ImageMagick selected but not available', __FILE__, __LINE__); 50 | } else { 51 | try { 52 | $iMagick = new Imagick(); 53 | $iMagick->readImage($filepath); 54 | $iMagick->optimizeImageLayers(); 55 | 56 | switch ($format) { 57 | case 'jpeg': 58 | $iMagick->setImageCompression(Imagick::COMPRESSION_JPEG); 59 | break; 60 | default: 61 | $iMagick->setImageCompression(Imagick::COMPRESSION_UNDEFINED); 62 | break; 63 | } 64 | 65 | $iMagick->setImageCompressionQuality(rex_config::get('media_manager', 'jpg_quality', 80)); 66 | $iMagick->stripImage(); 67 | $iMagick->writeImages($filepath, true); 68 | } catch (Exception $e) { 69 | rex_logger::logException($e); 70 | } 71 | } 72 | break; 73 | 74 | case 'Tinify': 75 | $key = rex_addon::get($this->addonName)->getConfig('tinify_key'); 76 | if (!$key) { 77 | rex_logger::logError(E_WARNING, 'Minify: Tinify selected but no API key provided', __FILE__, __LINE__); 78 | } else { 79 | try { 80 | Tinify::setKey($key); 81 | validate(); 82 | fromFile($filepath)->toFile($filepath); 83 | } catch (\Tinify\Exception $e) { 84 | rex_logger::logException($e); 85 | } 86 | } 87 | break; 88 | } 89 | 90 | $this->media->setImage(imagecreatefromstring(rex_file::get($filepath))); 91 | 92 | unlink($filepath); 93 | } 94 | 95 | public function getName() 96 | { 97 | return rex_i18n::msg('minify_images_effect_optimize'); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /vendor/composer/installed.php: -------------------------------------------------------------------------------- 1 | array( 3 | 'pretty_version' => 'dev-master', 4 | 'version' => 'dev-master', 5 | 'type' => 'library', 6 | 'install_path' => __DIR__ . '/../../', 7 | 'aliases' => array(), 8 | 'reference' => 'd9f47fa0e16c5be139f01214530b705a766ba3de', 9 | 'name' => 'friendsofredaxo/minify_images', 10 | 'dev' => true, 11 | ), 12 | 'versions' => array( 13 | 'friendsofredaxo/minify_images' => array( 14 | 'pretty_version' => 'dev-master', 15 | 'version' => 'dev-master', 16 | 'type' => 'library', 17 | 'install_path' => __DIR__ . '/../../', 18 | 'aliases' => array(), 19 | 'reference' => 'd9f47fa0e16c5be139f01214530b705a766ba3de', 20 | 'dev_requirement' => false, 21 | ), 22 | 'ps/image-optimizer' => array( 23 | 'pretty_version' => '2.0.5', 24 | 'version' => '2.0.5.0', 25 | 'type' => 'library', 26 | 'install_path' => __DIR__ . '/../ps/image-optimizer', 27 | 'aliases' => array(), 28 | 'reference' => '591d0a147599fa9c5e39d7a9b56df0e4b033849d', 29 | 'dev_requirement' => false, 30 | ), 31 | 'psr/log' => array( 32 | 'pretty_version' => '1.1.4', 33 | 'version' => '1.1.4.0', 34 | 'type' => 'library', 35 | 'install_path' => __DIR__ . '/../psr/log', 36 | 'aliases' => array(), 37 | 'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11', 38 | 'dev_requirement' => false, 39 | ), 40 | 'symfony/deprecation-contracts' => array( 41 | 'pretty_version' => 'v3.0.1', 42 | 'version' => '3.0.1.0', 43 | 'type' => 'library', 44 | 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', 45 | 'aliases' => array(), 46 | 'reference' => '26954b3d62a6c5fd0ea8a2a00c0353a14978d05c', 47 | 'dev_requirement' => false, 48 | ), 49 | 'symfony/options-resolver' => array( 50 | 'pretty_version' => 'v5.4.3', 51 | 'version' => '5.4.3.0', 52 | 'type' => 'library', 53 | 'install_path' => __DIR__ . '/../symfony/options-resolver', 54 | 'aliases' => array(), 55 | 'reference' => 'cc1147cb11af1b43f503ac18f31aa3bec213aba8', 56 | 'dev_requirement' => false, 57 | ), 58 | 'symfony/polyfill-php73' => array( 59 | 'pretty_version' => 'v1.25.0', 60 | 'version' => '1.25.0.0', 61 | 'type' => 'library', 62 | 'install_path' => __DIR__ . '/../symfony/polyfill-php73', 63 | 'aliases' => array(), 64 | 'reference' => 'cc5db0e22b3cb4111010e48785a97f670b350ca5', 65 | 'dev_requirement' => false, 66 | ), 67 | 'symfony/polyfill-php80' => array( 68 | 'pretty_version' => 'v1.25.0', 69 | 'version' => '1.25.0.0', 70 | 'type' => 'library', 71 | 'install_path' => __DIR__ . '/../symfony/polyfill-php80', 72 | 'aliases' => array(), 73 | 'reference' => '4407588e0d3f1f52efb65fbe92babe41f37fe50c', 74 | 'dev_requirement' => false, 75 | ), 76 | 'symfony/process' => array( 77 | 'pretty_version' => 'v5.4.8', 78 | 'version' => '5.4.8.0', 79 | 'type' => 'library', 80 | 'install_path' => __DIR__ . '/../symfony/process', 81 | 'aliases' => array(), 82 | 'reference' => '597f3fff8e3e91836bb0bd38f5718b56ddbde2f3', 83 | 'dev_requirement' => false, 84 | ), 85 | 'tinify/tinify' => array( 86 | 'pretty_version' => '1.5.3', 87 | 'version' => '1.5.3.0', 88 | 'type' => 'library', 89 | 'install_path' => __DIR__ . '/../tinify/tinify', 90 | 'aliases' => array(), 91 | 'reference' => 'f971971ca4b4f0185277a81ba695640d47833852', 92 | 'dev_requirement' => false, 93 | ), 94 | ), 95 | ); 96 | -------------------------------------------------------------------------------- /vendor/psr/log/Psr/Log/LoggerTrait.php: -------------------------------------------------------------------------------- 1 | log(LogLevel::EMERGENCY, $message, $context); 26 | } 27 | 28 | /** 29 | * Action must be taken immediately. 30 | * 31 | * Example: Entire website down, database unavailable, etc. This should 32 | * trigger the SMS alerts and wake you up. 33 | * 34 | * @param string $message 35 | * @param array $context 36 | * 37 | * @return void 38 | */ 39 | public function alert($message, array $context = array()) 40 | { 41 | $this->log(LogLevel::ALERT, $message, $context); 42 | } 43 | 44 | /** 45 | * Critical conditions. 46 | * 47 | * Example: Application component unavailable, unexpected exception. 48 | * 49 | * @param string $message 50 | * @param array $context 51 | * 52 | * @return void 53 | */ 54 | public function critical($message, array $context = array()) 55 | { 56 | $this->log(LogLevel::CRITICAL, $message, $context); 57 | } 58 | 59 | /** 60 | * Runtime errors that do not require immediate action but should typically 61 | * be logged and monitored. 62 | * 63 | * @param string $message 64 | * @param array $context 65 | * 66 | * @return void 67 | */ 68 | public function error($message, array $context = array()) 69 | { 70 | $this->log(LogLevel::ERROR, $message, $context); 71 | } 72 | 73 | /** 74 | * Exceptional occurrences that are not errors. 75 | * 76 | * Example: Use of deprecated APIs, poor use of an API, undesirable things 77 | * that are not necessarily wrong. 78 | * 79 | * @param string $message 80 | * @param array $context 81 | * 82 | * @return void 83 | */ 84 | public function warning($message, array $context = array()) 85 | { 86 | $this->log(LogLevel::WARNING, $message, $context); 87 | } 88 | 89 | /** 90 | * Normal but significant events. 91 | * 92 | * @param string $message 93 | * @param array $context 94 | * 95 | * @return void 96 | */ 97 | public function notice($message, array $context = array()) 98 | { 99 | $this->log(LogLevel::NOTICE, $message, $context); 100 | } 101 | 102 | /** 103 | * Interesting events. 104 | * 105 | * Example: User logs in, SQL logs. 106 | * 107 | * @param string $message 108 | * @param array $context 109 | * 110 | * @return void 111 | */ 112 | public function info($message, array $context = array()) 113 | { 114 | $this->log(LogLevel::INFO, $message, $context); 115 | } 116 | 117 | /** 118 | * Detailed debug information. 119 | * 120 | * @param string $message 121 | * @param array $context 122 | * 123 | * @return void 124 | */ 125 | public function debug($message, array $context = array()) 126 | { 127 | $this->log(LogLevel::DEBUG, $message, $context); 128 | } 129 | 130 | /** 131 | * Logs with an arbitrary level. 132 | * 133 | * @param mixed $level 134 | * @param string $message 135 | * @param array $context 136 | * 137 | * @return void 138 | * 139 | * @throws \Psr\Log\InvalidArgumentException 140 | */ 141 | abstract public function log($level, $message, array $context = array()); 142 | } 143 | -------------------------------------------------------------------------------- /vendor/symfony/polyfill-php80/Php80.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Polyfill\Php80; 13 | 14 | /** 15 | * @author Ion Bazan 16 | * @author Nico Oelgart 17 | * @author Nicolas Grekas 18 | * 19 | * @internal 20 | */ 21 | final class Php80 22 | { 23 | public static function fdiv(float $dividend, float $divisor): float 24 | { 25 | return @($dividend / $divisor); 26 | } 27 | 28 | public static function get_debug_type($value): string 29 | { 30 | switch (true) { 31 | case null === $value: return 'null'; 32 | case \is_bool($value): return 'bool'; 33 | case \is_string($value): return 'string'; 34 | case \is_array($value): return 'array'; 35 | case \is_int($value): return 'int'; 36 | case \is_float($value): return 'float'; 37 | case \is_object($value): break; 38 | case $value instanceof \__PHP_Incomplete_Class: return '__PHP_Incomplete_Class'; 39 | default: 40 | if (null === $type = @get_resource_type($value)) { 41 | return 'unknown'; 42 | } 43 | 44 | if ('Unknown' === $type) { 45 | $type = 'closed'; 46 | } 47 | 48 | return "resource ($type)"; 49 | } 50 | 51 | $class = \get_class($value); 52 | 53 | if (false === strpos($class, '@')) { 54 | return $class; 55 | } 56 | 57 | return (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous'; 58 | } 59 | 60 | public static function get_resource_id($res): int 61 | { 62 | if (!\is_resource($res) && null === @get_resource_type($res)) { 63 | throw new \TypeError(sprintf('Argument 1 passed to get_resource_id() must be of the type resource, %s given', get_debug_type($res))); 64 | } 65 | 66 | return (int) $res; 67 | } 68 | 69 | public static function preg_last_error_msg(): string 70 | { 71 | switch (preg_last_error()) { 72 | case \PREG_INTERNAL_ERROR: 73 | return 'Internal error'; 74 | case \PREG_BAD_UTF8_ERROR: 75 | return 'Malformed UTF-8 characters, possibly incorrectly encoded'; 76 | case \PREG_BAD_UTF8_OFFSET_ERROR: 77 | return 'The offset did not correspond to the beginning of a valid UTF-8 code point'; 78 | case \PREG_BACKTRACK_LIMIT_ERROR: 79 | return 'Backtrack limit exhausted'; 80 | case \PREG_RECURSION_LIMIT_ERROR: 81 | return 'Recursion limit exhausted'; 82 | case \PREG_JIT_STACKLIMIT_ERROR: 83 | return 'JIT stack limit exhausted'; 84 | case \PREG_NO_ERROR: 85 | return 'No error'; 86 | default: 87 | return 'Unknown error'; 88 | } 89 | } 90 | 91 | public static function str_contains(string $haystack, string $needle): bool 92 | { 93 | return '' === $needle || false !== strpos($haystack, $needle); 94 | } 95 | 96 | public static function str_starts_with(string $haystack, string $needle): bool 97 | { 98 | return 0 === strncmp($haystack, $needle, \strlen($needle)); 99 | } 100 | 101 | public static function str_ends_with(string $haystack, string $needle): bool 102 | { 103 | if ('' === $needle || $needle === $haystack) { 104 | return true; 105 | } 106 | 107 | if ('' === $haystack) { 108 | return false; 109 | } 110 | 111 | $needleLength = \strlen($needle); 112 | 113 | return $needleLength <= \strlen($haystack) && 0 === substr_compare($haystack, $needle, -$needleLength); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /vendor/symfony/options-resolver/OptionConfigurator.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\OptionsResolver; 13 | 14 | use Symfony\Component\OptionsResolver\Exception\AccessException; 15 | 16 | final class OptionConfigurator 17 | { 18 | private $name; 19 | private $resolver; 20 | 21 | public function __construct(string $name, OptionsResolver $resolver) 22 | { 23 | $this->name = $name; 24 | $this->resolver = $resolver; 25 | $this->resolver->setDefined($name); 26 | } 27 | 28 | /** 29 | * Adds allowed types for this option. 30 | * 31 | * @return $this 32 | * 33 | * @throws AccessException If called from a lazy option or normalizer 34 | */ 35 | public function allowedTypes(string ...$types): self 36 | { 37 | $this->resolver->setAllowedTypes($this->name, $types); 38 | 39 | return $this; 40 | } 41 | 42 | /** 43 | * Sets allowed values for this option. 44 | * 45 | * @param mixed ...$values One or more acceptable values/closures 46 | * 47 | * @return $this 48 | * 49 | * @throws AccessException If called from a lazy option or normalizer 50 | */ 51 | public function allowedValues(...$values): self 52 | { 53 | $this->resolver->setAllowedValues($this->name, $values); 54 | 55 | return $this; 56 | } 57 | 58 | /** 59 | * Sets the default value for this option. 60 | * 61 | * @param mixed $value The default value of the option 62 | * 63 | * @return $this 64 | * 65 | * @throws AccessException If called from a lazy option or normalizer 66 | */ 67 | public function default($value): self 68 | { 69 | $this->resolver->setDefault($this->name, $value); 70 | 71 | return $this; 72 | } 73 | 74 | /** 75 | * Defines an option configurator with the given name. 76 | */ 77 | public function define(string $option): self 78 | { 79 | return $this->resolver->define($option); 80 | } 81 | 82 | /** 83 | * Marks this option as deprecated. 84 | * 85 | * @param string $package The name of the composer package that is triggering the deprecation 86 | * @param string $version The version of the package that introduced the deprecation 87 | * @param string|\Closure $message The deprecation message to use 88 | * 89 | * @return $this 90 | */ 91 | public function deprecated(string $package, string $version, $message = 'The option "%name%" is deprecated.'): self 92 | { 93 | $this->resolver->setDeprecated($this->name, $package, $version, $message); 94 | 95 | return $this; 96 | } 97 | 98 | /** 99 | * Sets the normalizer for this option. 100 | * 101 | * @return $this 102 | * 103 | * @throws AccessException If called from a lazy option or normalizer 104 | */ 105 | public function normalize(\Closure $normalizer): self 106 | { 107 | $this->resolver->setNormalizer($this->name, $normalizer); 108 | 109 | return $this; 110 | } 111 | 112 | /** 113 | * Marks this option as required. 114 | * 115 | * @return $this 116 | * 117 | * @throws AccessException If called from a lazy option or normalizer 118 | */ 119 | public function required(): self 120 | { 121 | $this->resolver->setRequired($this->name); 122 | 123 | return $this; 124 | } 125 | 126 | /** 127 | * Sets an info message for an option. 128 | * 129 | * @return $this 130 | * 131 | * @throws AccessException If called from a lazy option or normalizer 132 | */ 133 | public function info(string $info): self 134 | { 135 | $this->resolver->setInfo($this->name, $info); 136 | 137 | return $this; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /vendor/symfony/options-resolver/Debug/OptionsResolverIntrospector.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\OptionsResolver\Debug; 13 | 14 | use Symfony\Component\OptionsResolver\Exception\NoConfigurationException; 15 | use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException; 16 | use Symfony\Component\OptionsResolver\OptionsResolver; 17 | 18 | /** 19 | * @author Maxime Steinhausser 20 | * 21 | * @final 22 | */ 23 | class OptionsResolverIntrospector 24 | { 25 | private $get; 26 | 27 | public function __construct(OptionsResolver $optionsResolver) 28 | { 29 | $this->get = \Closure::bind(function ($property, $option, $message) { 30 | /** @var OptionsResolver $this */ 31 | if (!$this->isDefined($option)) { 32 | throw new UndefinedOptionsException(sprintf('The option "%s" does not exist.', $option)); 33 | } 34 | 35 | if (!\array_key_exists($option, $this->{$property})) { 36 | throw new NoConfigurationException($message); 37 | } 38 | 39 | return $this->{$property}[$option]; 40 | }, $optionsResolver, $optionsResolver); 41 | } 42 | 43 | /** 44 | * @return mixed 45 | * 46 | * @throws NoConfigurationException on no configured value 47 | */ 48 | public function getDefault(string $option) 49 | { 50 | return ($this->get)('defaults', $option, sprintf('No default value was set for the "%s" option.', $option)); 51 | } 52 | 53 | /** 54 | * @return \Closure[] 55 | * 56 | * @throws NoConfigurationException on no configured closures 57 | */ 58 | public function getLazyClosures(string $option): array 59 | { 60 | return ($this->get)('lazy', $option, sprintf('No lazy closures were set for the "%s" option.', $option)); 61 | } 62 | 63 | /** 64 | * @return string[] 65 | * 66 | * @throws NoConfigurationException on no configured types 67 | */ 68 | public function getAllowedTypes(string $option): array 69 | { 70 | return ($this->get)('allowedTypes', $option, sprintf('No allowed types were set for the "%s" option.', $option)); 71 | } 72 | 73 | /** 74 | * @return mixed[] 75 | * 76 | * @throws NoConfigurationException on no configured values 77 | */ 78 | public function getAllowedValues(string $option): array 79 | { 80 | return ($this->get)('allowedValues', $option, sprintf('No allowed values were set for the "%s" option.', $option)); 81 | } 82 | 83 | /** 84 | * @throws NoConfigurationException on no configured normalizer 85 | */ 86 | public function getNormalizer(string $option): \Closure 87 | { 88 | return current($this->getNormalizers($option)); 89 | } 90 | 91 | /** 92 | * @throws NoConfigurationException when no normalizer is configured 93 | */ 94 | public function getNormalizers(string $option): array 95 | { 96 | return ($this->get)('normalizers', $option, sprintf('No normalizer was set for the "%s" option.', $option)); 97 | } 98 | 99 | /** 100 | * @return string|\Closure 101 | * 102 | * @throws NoConfigurationException on no configured deprecation 103 | * 104 | * @deprecated since Symfony 5.1, use "getDeprecation()" instead. 105 | */ 106 | public function getDeprecationMessage(string $option) 107 | { 108 | trigger_deprecation('symfony/options-resolver', '5.1', 'The "%s()" method is deprecated, use "getDeprecation()" instead.', __METHOD__); 109 | 110 | return $this->getDeprecation($option)['message']; 111 | } 112 | 113 | /** 114 | * @throws NoConfigurationException on no configured deprecation 115 | */ 116 | public function getDeprecation(string $option): array 117 | { 118 | return ($this->get)('deprecated', $option, sprintf('No deprecation was set for the "%s" option.', $option)); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /vendor/symfony/process/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | CHANGELOG 2 | ========= 3 | 4 | 5.2.0 5 | ----- 6 | 7 | * added `Process::setOptions()` to set `Process` specific options 8 | * added option `create_new_console` to allow a subprocess to continue 9 | to run after the main script exited, both on Linux and on Windows 10 | 11 | 5.1.0 12 | ----- 13 | 14 | * added `Process::getStartTime()` to retrieve the start time of the process as float 15 | 16 | 5.0.0 17 | ----- 18 | 19 | * removed `Process::inheritEnvironmentVariables()` 20 | * removed `PhpProcess::setPhpBinary()` 21 | * `Process` must be instantiated with a command array, use `Process::fromShellCommandline()` when the command should be parsed by the shell 22 | * removed `Process::setCommandLine()` 23 | 24 | 4.4.0 25 | ----- 26 | 27 | * deprecated `Process::inheritEnvironmentVariables()`: env variables are always inherited. 28 | * added `Process::getLastOutputTime()` method 29 | 30 | 4.2.0 31 | ----- 32 | 33 | * added the `Process::fromShellCommandline()` to run commands in a shell wrapper 34 | * deprecated passing a command as string when creating a `Process` instance 35 | * deprecated the `Process::setCommandline()` and the `PhpProcess::setPhpBinary()` methods 36 | * added the `Process::waitUntil()` method to wait for the process only for a 37 | specific output, then continue the normal execution of your application 38 | 39 | 4.1.0 40 | ----- 41 | 42 | * added the `Process::isTtySupported()` method that allows to check for TTY support 43 | * made `PhpExecutableFinder` look for the `PHP_BINARY` env var when searching the php binary 44 | * added the `ProcessSignaledException` class to properly catch signaled process errors 45 | 46 | 4.0.0 47 | ----- 48 | 49 | * environment variables will always be inherited 50 | * added a second `array $env = []` argument to the `start()`, `run()`, 51 | `mustRun()`, and `restart()` methods of the `Process` class 52 | * added a second `array $env = []` argument to the `start()` method of the 53 | `PhpProcess` class 54 | * the `ProcessUtils::escapeArgument()` method has been removed 55 | * the `areEnvironmentVariablesInherited()`, `getOptions()`, and `setOptions()` 56 | methods of the `Process` class have been removed 57 | * support for passing `proc_open()` options has been removed 58 | * removed the `ProcessBuilder` class, use the `Process` class instead 59 | * removed the `getEnhanceWindowsCompatibility()` and `setEnhanceWindowsCompatibility()` methods of the `Process` class 60 | * passing a not existing working directory to the constructor of the `Symfony\Component\Process\Process` class is not 61 | supported anymore 62 | 63 | 3.4.0 64 | ----- 65 | 66 | * deprecated the ProcessBuilder class 67 | * deprecated calling `Process::start()` without setting a valid working directory beforehand (via `setWorkingDirectory()` or constructor) 68 | 69 | 3.3.0 70 | ----- 71 | 72 | * added command line arrays in the `Process` class 73 | * added `$env` argument to `Process::start()`, `run()`, `mustRun()` and `restart()` methods 74 | * deprecated the `ProcessUtils::escapeArgument()` method 75 | * deprecated not inheriting environment variables 76 | * deprecated configuring `proc_open()` options 77 | * deprecated configuring enhanced Windows compatibility 78 | * deprecated configuring enhanced sigchild compatibility 79 | 80 | 2.5.0 81 | ----- 82 | 83 | * added support for PTY mode 84 | * added the convenience method "mustRun" 85 | * deprecation: Process::setStdin() is deprecated in favor of Process::setInput() 86 | * deprecation: Process::getStdin() is deprecated in favor of Process::getInput() 87 | * deprecation: Process::setInput() and ProcessBuilder::setInput() do not accept non-scalar types 88 | 89 | 2.4.0 90 | ----- 91 | 92 | * added the ability to define an idle timeout 93 | 94 | 2.3.0 95 | ----- 96 | 97 | * added ProcessUtils::escapeArgument() to fix the bug in escapeshellarg() function on Windows 98 | * added Process::signal() 99 | * added Process::getPid() 100 | * added support for a TTY mode 101 | 102 | 2.2.0 103 | ----- 104 | 105 | * added ProcessBuilder::setArguments() to reset the arguments on a builder 106 | * added a way to retrieve the standard and error output incrementally 107 | * added Process:restart() 108 | 109 | 2.1.0 110 | ----- 111 | 112 | * added support for non-blocking processes (start(), wait(), isRunning(), stop()) 113 | * enhanced Windows compatibility 114 | * added Process::getExitCodeText() that returns a string representation for 115 | the exit code returned by the process 116 | * added ProcessBuilder 117 | -------------------------------------------------------------------------------- /vendor/symfony/process/Pipes/UnixPipes.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Process\Pipes; 13 | 14 | use Symfony\Component\Process\Process; 15 | 16 | /** 17 | * UnixPipes implementation uses unix pipes as handles. 18 | * 19 | * @author Romain Neutron 20 | * 21 | * @internal 22 | */ 23 | class UnixPipes extends AbstractPipes 24 | { 25 | private $ttyMode; 26 | private $ptyMode; 27 | private $haveReadSupport; 28 | 29 | public function __construct(?bool $ttyMode, bool $ptyMode, $input, bool $haveReadSupport) 30 | { 31 | $this->ttyMode = $ttyMode; 32 | $this->ptyMode = $ptyMode; 33 | $this->haveReadSupport = $haveReadSupport; 34 | 35 | parent::__construct($input); 36 | } 37 | 38 | public function __sleep(): array 39 | { 40 | throw new \BadMethodCallException('Cannot serialize '.__CLASS__); 41 | } 42 | 43 | public function __wakeup() 44 | { 45 | throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); 46 | } 47 | 48 | public function __destruct() 49 | { 50 | $this->close(); 51 | } 52 | 53 | /** 54 | * {@inheritdoc} 55 | */ 56 | public function getDescriptors(): array 57 | { 58 | if (!$this->haveReadSupport) { 59 | $nullstream = fopen('/dev/null', 'c'); 60 | 61 | return [ 62 | ['pipe', 'r'], 63 | $nullstream, 64 | $nullstream, 65 | ]; 66 | } 67 | 68 | if ($this->ttyMode) { 69 | return [ 70 | ['file', '/dev/tty', 'r'], 71 | ['file', '/dev/tty', 'w'], 72 | ['file', '/dev/tty', 'w'], 73 | ]; 74 | } 75 | 76 | if ($this->ptyMode && Process::isPtySupported()) { 77 | return [ 78 | ['pty'], 79 | ['pty'], 80 | ['pty'], 81 | ]; 82 | } 83 | 84 | return [ 85 | ['pipe', 'r'], 86 | ['pipe', 'w'], // stdout 87 | ['pipe', 'w'], // stderr 88 | ]; 89 | } 90 | 91 | /** 92 | * {@inheritdoc} 93 | */ 94 | public function getFiles(): array 95 | { 96 | return []; 97 | } 98 | 99 | /** 100 | * {@inheritdoc} 101 | */ 102 | public function readAndWrite(bool $blocking, bool $close = false): array 103 | { 104 | $this->unblock(); 105 | $w = $this->write(); 106 | 107 | $read = $e = []; 108 | $r = $this->pipes; 109 | unset($r[0]); 110 | 111 | // let's have a look if something changed in streams 112 | set_error_handler([$this, 'handleError']); 113 | if (($r || $w) && false === stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) { 114 | restore_error_handler(); 115 | // if a system call has been interrupted, forget about it, let's try again 116 | // otherwise, an error occurred, let's reset pipes 117 | if (!$this->hasSystemCallBeenInterrupted()) { 118 | $this->pipes = []; 119 | } 120 | 121 | return $read; 122 | } 123 | restore_error_handler(); 124 | 125 | foreach ($r as $pipe) { 126 | // prior PHP 5.4 the array passed to stream_select is modified and 127 | // lose key association, we have to find back the key 128 | $read[$type = array_search($pipe, $this->pipes, true)] = ''; 129 | 130 | do { 131 | $data = @fread($pipe, self::CHUNK_SIZE); 132 | $read[$type] .= $data; 133 | } while (isset($data[0]) && ($close || isset($data[self::CHUNK_SIZE - 1]))); 134 | 135 | if (!isset($read[$type][0])) { 136 | unset($read[$type]); 137 | } 138 | 139 | if ($close && feof($pipe)) { 140 | fclose($pipe); 141 | unset($this->pipes[$type]); 142 | } 143 | } 144 | 145 | return $read; 146 | } 147 | 148 | /** 149 | * {@inheritdoc} 150 | */ 151 | public function haveReadSupport(): bool 152 | { 153 | return $this->haveReadSupport; 154 | } 155 | 156 | /** 157 | * {@inheritdoc} 158 | */ 159 | public function areOpen(): bool 160 | { 161 | return (bool) $this->pipes; 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /vendor/tinify/tinify/test/TinifyTest.php: -------------------------------------------------------------------------------- 1 | dummyFile = __DIR__ . "/examples/dummy.png"; 11 | } 12 | 13 | public function testKeyShouldResetClientWithNewKey() { 14 | CurlMock::register("https://api.tinify.com/", array("status" => 200)); 15 | Tinify\setKey("abcde"); 16 | Tinify\Tinify::getClient(); 17 | Tinify\setKey("fghij"); 18 | $client = Tinify\Tinify::getClient(); 19 | $client->request("get", "/"); 20 | 21 | $this->assertSame("api:fghij", CurlMock::last(CURLOPT_USERPWD)); 22 | } 23 | 24 | public function testAppIdentifierShouldResetClientWithNewAppIdentifier() { 25 | CurlMock::register("https://api.tinify.com/", array("status" => 200)); 26 | Tinify\setKey("abcde"); 27 | Tinify\setAppIdentifier("MyApp/1.0"); 28 | Tinify\Tinify::getClient(); 29 | Tinify\setAppIdentifier("MyApp/2.0"); 30 | $client = Tinify\Tinify::getClient(); 31 | $client->request("get", "/"); 32 | 33 | $this->assertSame(Tinify\Client::userAgent() . " MyApp/2.0", CurlMock::last(CURLOPT_USERAGENT)); 34 | } 35 | 36 | public function testProxyShouldResetClientWithNewProxy() { 37 | CurlMock::register("https://api.tinify.com/", array("status" => 200)); 38 | Tinify\setKey("abcde"); 39 | Tinify\setProxy("http://localhost"); 40 | Tinify\Tinify::getClient(); 41 | Tinify\setProxy("http://user:pass@localhost:8080"); 42 | $client = Tinify\Tinify::getClient(); 43 | $client->request("get", "/"); 44 | 45 | $this->assertSame(Tinify\Client::userAgent() . " MyApp/2.0", CurlMock::last(CURLOPT_USERAGENT)); 46 | } 47 | 48 | public function testClientWithKeyShouldReturnClient() { 49 | Tinify\setKey("abcde"); 50 | $this->assertInstanceOf("Tinify\Client", Tinify\Tinify::getClient()); 51 | } 52 | 53 | public function testClientWithoutKeyShouldThrowException() { 54 | $this->setExpectedException("Tinify\AccountException"); 55 | Tinify\Tinify::getClient(); 56 | } 57 | 58 | public function testClientWithInvalidProxyShouldThrowException() { 59 | $this->setExpectedException("Tinify\ConnectionException"); 60 | Tinify\setKey("abcde"); 61 | Tinify\setProxy("http-bad-url"); 62 | Tinify\Tinify::getClient(); 63 | } 64 | 65 | public function testSetClientShouldReplaceClient() { 66 | Tinify\setKey("abcde"); 67 | Tinify\Tinify::setClient("foo"); 68 | $this->assertSame("foo", Tinify\Tinify::getClient()); 69 | } 70 | 71 | public function testValidateWithValidKeyShouldReturnTrue() { 72 | Tinify\setKey("valid"); 73 | CurlMock::register("https://api.tinify.com/shrink", array( 74 | "status" => 400, "body" => '{"error":"Input missing","message":"No input"}' 75 | )); 76 | $this->assertTrue(Tinify\validate()); 77 | } 78 | 79 | public function testValidateWithLimitedKeyShouldReturnTrue() { 80 | Tinify\setKey("invalid"); 81 | CurlMock::register("https://api.tinify.com/shrink", array( 82 | "status" => 429, "body" => '{"error":"Too many requests","message":"Your monthly limit has been exceeded"}' 83 | )); 84 | $this->assertTrue(Tinify\validate()); 85 | } 86 | 87 | public function testValidateWithErrorShouldThrowException() { 88 | Tinify\setKey("invalid"); 89 | CurlMock::register("https://api.tinify.com/shrink", array( 90 | "status" => 401, "body" => '{"error":"Unauthorized","message":"Credentials are invalid"}' 91 | )); 92 | $this->setExpectedException("Tinify\AccountException"); 93 | Tinify\validate(); 94 | } 95 | 96 | public function testFromFileShouldReturnSource() { 97 | CurlMock::register("https://api.tinify.com/shrink", array( 98 | "status" => 201, "headers" => array("Location" => "https://api.tinify.com/some/location") 99 | )); 100 | Tinify\setKey("valid"); 101 | $this->assertInstanceOf("Tinify\Source", Tinify\fromFile($this->dummyFile)); 102 | } 103 | 104 | public function testFromBufferShouldReturnSource() { 105 | CurlMock::register("https://api.tinify.com/shrink", array( 106 | "status" => 201, "headers" => array("Location" => "https://api.tinify.com/some/location") 107 | )); 108 | Tinify\setKey("valid"); 109 | $this->assertInstanceOf("Tinify\Source", Tinify\fromBuffer("png file")); 110 | } 111 | 112 | public function testFromUrlShouldReturnSource() { 113 | CurlMock::register("https://api.tinify.com/shrink", array( 114 | "status" => 201, "headers" => array("Location" => "https://api.tinify.com/some/location") 115 | )); 116 | Tinify\setKey("valid"); 117 | $this->assertInstanceOf("Tinify\Source", Tinify\fromUrl("http://example.com/test.jpg")); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /vendor/psr/log/Psr/Log/Test/TestLogger.php: -------------------------------------------------------------------------------- 1 | $level, 73 | 'message' => $message, 74 | 'context' => $context, 75 | ]; 76 | 77 | $this->recordsByLevel[$record['level']][] = $record; 78 | $this->records[] = $record; 79 | } 80 | 81 | public function hasRecords($level) 82 | { 83 | return isset($this->recordsByLevel[$level]); 84 | } 85 | 86 | public function hasRecord($record, $level) 87 | { 88 | if (is_string($record)) { 89 | $record = ['message' => $record]; 90 | } 91 | return $this->hasRecordThatPasses(function ($rec) use ($record) { 92 | if ($rec['message'] !== $record['message']) { 93 | return false; 94 | } 95 | if (isset($record['context']) && $rec['context'] !== $record['context']) { 96 | return false; 97 | } 98 | return true; 99 | }, $level); 100 | } 101 | 102 | public function hasRecordThatContains($message, $level) 103 | { 104 | return $this->hasRecordThatPasses(function ($rec) use ($message) { 105 | return strpos($rec['message'], $message) !== false; 106 | }, $level); 107 | } 108 | 109 | public function hasRecordThatMatches($regex, $level) 110 | { 111 | return $this->hasRecordThatPasses(function ($rec) use ($regex) { 112 | return preg_match($regex, $rec['message']) > 0; 113 | }, $level); 114 | } 115 | 116 | public function hasRecordThatPasses(callable $predicate, $level) 117 | { 118 | if (!isset($this->recordsByLevel[$level])) { 119 | return false; 120 | } 121 | foreach ($this->recordsByLevel[$level] as $i => $rec) { 122 | if (call_user_func($predicate, $rec, $i)) { 123 | return true; 124 | } 125 | } 126 | return false; 127 | } 128 | 129 | public function __call($method, $args) 130 | { 131 | if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) { 132 | $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3]; 133 | $level = strtolower($matches[2]); 134 | if (method_exists($this, $genericMethod)) { 135 | $args[] = $level; 136 | return call_user_func_array([$this, $genericMethod], $args); 137 | } 138 | } 139 | throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()'); 140 | } 141 | 142 | public function reset() 143 | { 144 | $this->records = []; 145 | $this->recordsByLevel = []; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php: -------------------------------------------------------------------------------- 1 | ". 26 | * 27 | * Example ->error('Foo') would yield "error Foo". 28 | * 29 | * @return string[] 30 | */ 31 | abstract public function getLogs(); 32 | 33 | public function testImplements() 34 | { 35 | $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger()); 36 | } 37 | 38 | /** 39 | * @dataProvider provideLevelsAndMessages 40 | */ 41 | public function testLogsAtAllLevels($level, $message) 42 | { 43 | $logger = $this->getLogger(); 44 | $logger->{$level}($message, array('user' => 'Bob')); 45 | $logger->log($level, $message, array('user' => 'Bob')); 46 | 47 | $expected = array( 48 | $level.' message of level '.$level.' with context: Bob', 49 | $level.' message of level '.$level.' with context: Bob', 50 | ); 51 | $this->assertEquals($expected, $this->getLogs()); 52 | } 53 | 54 | public function provideLevelsAndMessages() 55 | { 56 | return array( 57 | LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'), 58 | LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'), 59 | LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'), 60 | LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'), 61 | LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'), 62 | LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'), 63 | LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'), 64 | LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'), 65 | ); 66 | } 67 | 68 | /** 69 | * @expectedException \Psr\Log\InvalidArgumentException 70 | */ 71 | public function testThrowsOnInvalidLevel() 72 | { 73 | $logger = $this->getLogger(); 74 | $logger->log('invalid level', 'Foo'); 75 | } 76 | 77 | public function testContextReplacement() 78 | { 79 | $logger = $this->getLogger(); 80 | $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar')); 81 | 82 | $expected = array('info {Message {nothing} Bob Bar a}'); 83 | $this->assertEquals($expected, $this->getLogs()); 84 | } 85 | 86 | public function testObjectCastToString() 87 | { 88 | if (method_exists($this, 'createPartialMock')) { 89 | $dummy = $this->createPartialMock('Psr\Log\Test\DummyTest', array('__toString')); 90 | } else { 91 | $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString')); 92 | } 93 | $dummy->expects($this->once()) 94 | ->method('__toString') 95 | ->will($this->returnValue('DUMMY')); 96 | 97 | $this->getLogger()->warning($dummy); 98 | 99 | $expected = array('warning DUMMY'); 100 | $this->assertEquals($expected, $this->getLogs()); 101 | } 102 | 103 | public function testContextCanContainAnything() 104 | { 105 | $closed = fopen('php://memory', 'r'); 106 | fclose($closed); 107 | 108 | $context = array( 109 | 'bool' => true, 110 | 'null' => null, 111 | 'string' => 'Foo', 112 | 'int' => 0, 113 | 'float' => 0.5, 114 | 'nested' => array('with object' => new DummyTest), 115 | 'object' => new \DateTime, 116 | 'resource' => fopen('php://memory', 'r'), 117 | 'closed' => $closed, 118 | ); 119 | 120 | $this->getLogger()->warning('Crazy context data', $context); 121 | 122 | $expected = array('warning Crazy context data'); 123 | $this->assertEquals($expected, $this->getLogs()); 124 | } 125 | 126 | public function testContextExceptionKeyCanBeExceptionOrOtherValues() 127 | { 128 | $logger = $this->getLogger(); 129 | $logger->warning('Random message', array('exception' => 'oops')); 130 | $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail'))); 131 | 132 | $expected = array( 133 | 'warning Random message', 134 | 'critical Uncaught Exception!' 135 | ); 136 | $this->assertEquals($expected, $this->getLogs()); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /vendor/tinify/tinify/test/curl_mock.php: -------------------------------------------------------------------------------- 1 | 471808, 11 | "version" => "7.51.0", 12 | "features" => 951197, 13 | ); 14 | 15 | private static $urls = array(); 16 | private static $requests = array(); 17 | private static $version = array(); 18 | 19 | public $options = array(); 20 | public $response; 21 | public $closed = false; 22 | 23 | public static function version_info() { 24 | return self::$version; 25 | } 26 | 27 | public static function set_version_info_key($key, $value) { 28 | self::$version[$key] = $value; 29 | } 30 | 31 | public static function register($url, $request, $response = NULL) { 32 | if (!$response) { 33 | $response = $request; 34 | $request = NULL; 35 | } 36 | 37 | if (!isset(self::$urls[$url])) { 38 | self::$urls[$url] = array(); 39 | } 40 | 41 | array_push(self::$urls[$url], array($request, $response)); 42 | } 43 | 44 | public static function reset() { 45 | self::$requests = array(); 46 | self::$urls = array(); 47 | self::$version = self::$defaultVersion; 48 | } 49 | 50 | public static function last_has($key) { 51 | $lastReq = self::$requests[count(self::$requests) - 1]; 52 | return array_key_exists($key, $lastReq->options); 53 | } 54 | 55 | public static function last($key = null) { 56 | $lastReq = self::$requests[count(self::$requests) - 1]; 57 | if ($key) { 58 | return $lastReq->options[$key]; 59 | } else { 60 | return $lastReq; 61 | } 62 | } 63 | 64 | public function close() { 65 | $this->closed = true; 66 | } 67 | 68 | public function exec() { 69 | if ($this->closed) { 70 | throw new CurlMockException("Curl already closed"); 71 | } 72 | array_push(self::$requests, $this); 73 | 74 | $queue = &self::$urls[$this->options[CURLOPT_URL]]; 75 | list($this->request, $this->response) = $queue[0]; 76 | 77 | /* Keep last request as fallback. */ 78 | if (count($queue) > 1) array_shift($queue); 79 | 80 | if ($this->request) { 81 | if ($this->request["body"]) { 82 | if ($this->options[CURLOPT_POSTFIELDS] != $this->request["body"]) { 83 | throw new Exception("Body '" . $this->options[CURLOPT_POSTFIELDS] . 84 | "' does not match expected '" . $this->request["body"] . "'"); 85 | } 86 | } 87 | } 88 | 89 | if (isset($this->response["headers"])) { 90 | $headers = ""; 91 | foreach ($this->response["headers"] as $header => $value) { 92 | $headers .= $header . ": " . $value . "\r\n"; 93 | } 94 | $this->response["headers"] = $headers . "\r\n"; 95 | } else { 96 | $this->response["headers"] = "\r\n"; 97 | } 98 | 99 | if (!isset($this->response["body"])) { 100 | $this->response["body"] = ""; 101 | } 102 | 103 | if (array_key_exists("return", $this->response)) { 104 | return $this->response["return"]; 105 | } else if (isset($this->response["status"])) { 106 | return $this->response["headers"] . $this->response["body"]; 107 | } else { 108 | return false; 109 | } 110 | } 111 | 112 | public function setopt_array($array) { 113 | if ($this->closed) { 114 | throw new CurlMockException("Curl already closed"); 115 | } 116 | foreach ($array as $key => $value) { 117 | $this->options[$key] = $value; 118 | } 119 | } 120 | 121 | public function setopt($key, $value) { 122 | if ($this->closed) { 123 | throw new CurlMockException("Curl already closed"); 124 | } 125 | $this->options[$key] = $value; 126 | } 127 | 128 | public function getinfo($key) { 129 | if ($this->closed) { 130 | throw new CurlMockException("Curl already closed"); 131 | } 132 | switch ($key) { 133 | case CURLINFO_HTTP_CODE: 134 | return isset($this->response["status"]) ? $this->response["status"] : 0; 135 | case CURLINFO_HEADER_SIZE: 136 | return strlen($this->response["headers"]); 137 | default: 138 | throw new Exception("Bad key $key"); 139 | } 140 | } 141 | 142 | public function error() { 143 | if ($this->closed) { 144 | throw new CurlMockException("Curl already closed"); 145 | } 146 | return $this->response["error"]; 147 | } 148 | 149 | public function errno() { 150 | if ($this->closed) { 151 | throw new CurlMockException("Curl already closed"); 152 | } 153 | return $this->response["errno"]; 154 | } 155 | } 156 | 157 | function curl_version() { 158 | return CurlMock::version_info(); 159 | } 160 | 161 | function curl_init() { 162 | return new CurlMock(); 163 | } 164 | 165 | function curl_exec($mock) { 166 | return $mock->exec(); 167 | } 168 | 169 | function curl_close($mock) { 170 | $mock->close(); 171 | } 172 | 173 | function curl_setopt_array($mock, $array) { 174 | return $mock->setopt_array($array); 175 | } 176 | 177 | function curl_setopt($mock, $key, $value) { 178 | return $mock->setopt($key, $value); 179 | } 180 | 181 | function curl_getinfo($mock, $key) { 182 | return $mock->getinfo($key); 183 | } 184 | 185 | function curl_error($mock) { 186 | return $mock->error(); 187 | } 188 | 189 | function curl_errno($mock) { 190 | return $mock->errno(); 191 | } 192 | -------------------------------------------------------------------------------- /vendor/symfony/process/Pipes/AbstractPipes.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Process\Pipes; 13 | 14 | use Symfony\Component\Process\Exception\InvalidArgumentException; 15 | 16 | /** 17 | * @author Romain Neutron 18 | * 19 | * @internal 20 | */ 21 | abstract class AbstractPipes implements PipesInterface 22 | { 23 | public $pipes = []; 24 | 25 | private $inputBuffer = ''; 26 | private $input; 27 | private $blocked = true; 28 | private $lastError; 29 | 30 | /** 31 | * @param resource|string|int|float|bool|\Iterator|null $input 32 | */ 33 | public function __construct($input) 34 | { 35 | if (\is_resource($input) || $input instanceof \Iterator) { 36 | $this->input = $input; 37 | } elseif (\is_string($input)) { 38 | $this->inputBuffer = $input; 39 | } else { 40 | $this->inputBuffer = (string) $input; 41 | } 42 | } 43 | 44 | /** 45 | * {@inheritdoc} 46 | */ 47 | public function close() 48 | { 49 | foreach ($this->pipes as $pipe) { 50 | if (\is_resource($pipe)) { 51 | fclose($pipe); 52 | } 53 | } 54 | $this->pipes = []; 55 | } 56 | 57 | /** 58 | * Returns true if a system call has been interrupted. 59 | */ 60 | protected function hasSystemCallBeenInterrupted(): bool 61 | { 62 | $lastError = $this->lastError; 63 | $this->lastError = null; 64 | 65 | // stream_select returns false when the `select` system call is interrupted by an incoming signal 66 | return null !== $lastError && false !== stripos($lastError, 'interrupted system call'); 67 | } 68 | 69 | /** 70 | * Unblocks streams. 71 | */ 72 | protected function unblock() 73 | { 74 | if (!$this->blocked) { 75 | return; 76 | } 77 | 78 | foreach ($this->pipes as $pipe) { 79 | stream_set_blocking($pipe, 0); 80 | } 81 | if (\is_resource($this->input)) { 82 | stream_set_blocking($this->input, 0); 83 | } 84 | 85 | $this->blocked = false; 86 | } 87 | 88 | /** 89 | * Writes input to stdin. 90 | * 91 | * @throws InvalidArgumentException When an input iterator yields a non supported value 92 | */ 93 | protected function write(): ?array 94 | { 95 | if (!isset($this->pipes[0])) { 96 | return null; 97 | } 98 | $input = $this->input; 99 | 100 | if ($input instanceof \Iterator) { 101 | if (!$input->valid()) { 102 | $input = null; 103 | } elseif (\is_resource($input = $input->current())) { 104 | stream_set_blocking($input, 0); 105 | } elseif (!isset($this->inputBuffer[0])) { 106 | if (!\is_string($input)) { 107 | if (!is_scalar($input)) { 108 | throw new InvalidArgumentException(sprintf('"%s" yielded a value of type "%s", but only scalars and stream resources are supported.', get_debug_type($this->input), get_debug_type($input))); 109 | } 110 | $input = (string) $input; 111 | } 112 | $this->inputBuffer = $input; 113 | $this->input->next(); 114 | $input = null; 115 | } else { 116 | $input = null; 117 | } 118 | } 119 | 120 | $r = $e = []; 121 | $w = [$this->pipes[0]]; 122 | 123 | // let's have a look if something changed in streams 124 | if (false === @stream_select($r, $w, $e, 0, 0)) { 125 | return null; 126 | } 127 | 128 | foreach ($w as $stdin) { 129 | if (isset($this->inputBuffer[0])) { 130 | $written = fwrite($stdin, $this->inputBuffer); 131 | $this->inputBuffer = substr($this->inputBuffer, $written); 132 | if (isset($this->inputBuffer[0])) { 133 | return [$this->pipes[0]]; 134 | } 135 | } 136 | 137 | if ($input) { 138 | while (true) { 139 | $data = fread($input, self::CHUNK_SIZE); 140 | if (!isset($data[0])) { 141 | break; 142 | } 143 | $written = fwrite($stdin, $data); 144 | $data = substr($data, $written); 145 | if (isset($data[0])) { 146 | $this->inputBuffer = $data; 147 | 148 | return [$this->pipes[0]]; 149 | } 150 | } 151 | if (feof($input)) { 152 | if ($this->input instanceof \Iterator) { 153 | $this->input->next(); 154 | } else { 155 | $this->input = null; 156 | } 157 | } 158 | } 159 | } 160 | 161 | // no input to read on resource, buffer is empty 162 | if (!isset($this->inputBuffer[0]) && !($this->input instanceof \Iterator ? $this->input->valid() : $this->input)) { 163 | $this->input = null; 164 | fclose($this->pipes[0]); 165 | unset($this->pipes[0]); 166 | } elseif (!$w) { 167 | return [$this->pipes[0]]; 168 | } 169 | 170 | return null; 171 | } 172 | 173 | /** 174 | * @internal 175 | */ 176 | public function handleError(int $type, string $msg) 177 | { 178 | $this->lastError = $msg; 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /vendor/tinify/tinify/lib/Tinify/Client.php: -------------------------------------------------------------------------------- 1 | options = array( 35 | CURLOPT_BINARYTRANSFER => true, 36 | CURLOPT_RETURNTRANSFER => true, 37 | CURLOPT_HEADER => true, 38 | CURLOPT_USERPWD => "api:" . $key, 39 | CURLOPT_CAINFO => self::caBundle(), 40 | CURLOPT_SSL_VERIFYPEER => true, 41 | CURLOPT_USERAGENT => join(" ", array_filter(array(self::userAgent(), $app_identifier))), 42 | ); 43 | 44 | if ($proxy) { 45 | $parts = parse_url($proxy); 46 | if (isset($parts["host"])) { 47 | $this->options[CURLOPT_PROXYTYPE] = CURLPROXY_HTTP; 48 | $this->options[CURLOPT_PROXY] = $parts["host"]; 49 | } else { 50 | throw new ConnectionException("Invalid proxy"); 51 | } 52 | 53 | if (isset($parts["port"])) { 54 | $this->options[CURLOPT_PROXYPORT] = $parts["port"]; 55 | } 56 | 57 | $creds = ""; 58 | if (isset($parts["user"])) $creds .= $parts["user"]; 59 | if (isset($parts["pass"])) $creds .= ":" . $parts["pass"]; 60 | 61 | if ($creds) { 62 | $this->options[CURLOPT_PROXYAUTH] = CURLAUTH_ANY; 63 | $this->options[CURLOPT_PROXYUSERPWD] = $creds; 64 | } 65 | } 66 | } 67 | 68 | function request($method, $url, $body = NULL) { 69 | $header = array(); 70 | if (is_array($body)) { 71 | if (!empty($body)) { 72 | $body = json_encode($body); 73 | array_push($header, "Content-Type: application/json"); 74 | } else { 75 | $body = NULL; 76 | } 77 | } 78 | 79 | for ($retries = self::RETRY_COUNT; $retries >= 0; $retries--) { 80 | if ($retries < self::RETRY_COUNT) { 81 | usleep(self::RETRY_DELAY * 1000); 82 | } 83 | 84 | $request = curl_init(); 85 | if ($request === false || $request === null) { 86 | throw new ConnectionException( 87 | "Error while connecting: curl extension is not functional or disabled." 88 | ); 89 | } 90 | 91 | curl_setopt_array($request, $this->options); 92 | 93 | $url = strtolower(substr($url, 0, 6)) == "https:" ? $url : self::API_ENDPOINT . $url; 94 | curl_setopt($request, CURLOPT_URL, $url); 95 | curl_setopt($request, CURLOPT_CUSTOMREQUEST, strtoupper($method)); 96 | 97 | if (count($header) > 0) { 98 | curl_setopt($request, CURLOPT_HTTPHEADER, $header); 99 | } 100 | 101 | if ($body) { 102 | curl_setopt($request, CURLOPT_POSTFIELDS, $body); 103 | } 104 | 105 | $response = curl_exec($request); 106 | 107 | if (is_string($response)) { 108 | $status = curl_getinfo($request, CURLINFO_HTTP_CODE); 109 | $headerSize = curl_getinfo($request, CURLINFO_HEADER_SIZE); 110 | curl_close($request); 111 | 112 | $headers = self::parseHeaders(substr($response, 0, $headerSize)); 113 | $body = substr($response, $headerSize); 114 | 115 | if (isset($headers["compression-count"])) { 116 | Tinify::setCompressionCount(intval($headers["compression-count"])); 117 | } 118 | 119 | if ($status >= 200 && $status <= 299) { 120 | return (object) array("body" => $body, "headers" => $headers); 121 | } 122 | 123 | $details = json_decode($body); 124 | if (!$details) { 125 | $message = sprintf("Error while parsing response: %s (#%d)", 126 | PHP_VERSION_ID >= 50500 ? json_last_error_msg() : "Error", 127 | json_last_error()); 128 | $details = (object) array( 129 | "message" => $message, 130 | "error" => "ParseError" 131 | ); 132 | } 133 | 134 | if ($retries > 0 && $status >= 500) continue; 135 | throw Exception::create($details->message, $details->error, $status); 136 | } else { 137 | $message = sprintf("%s (#%d)", curl_error($request), curl_errno($request)); 138 | curl_close($request); 139 | if ($retries > 0) continue; 140 | throw new ConnectionException("Error while connecting: " . $message); 141 | } 142 | } 143 | } 144 | 145 | protected static function parseHeaders($headers) { 146 | if (!is_array($headers)) { 147 | $headers = explode("\r\n", $headers); 148 | } 149 | 150 | $res = array(); 151 | foreach ($headers as $header) { 152 | if (empty($header)) continue; 153 | $split = explode(":", $header, 2); 154 | if (count($split) === 2) { 155 | $res[strtolower($split[0])] = trim($split[1]); 156 | } 157 | } 158 | return $res; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /vendor/ps/image-optimizer/README.md: -------------------------------------------------------------------------------- 1 | # Image Optimizer [![Build Status](https://travis-ci.org/psliwa/image-optimizer.svg?branch=master)](https://travis-ci.org/psliwa/image-optimizer) 2 | 3 | This library is handy and very easy to use optimizer for image files. It uses [optipng][2], [pngquant][1], [jpegoptim][6], [svgo][9] and few more libraries, 4 | so before use it you should install proper libraries on your server. Project contains Vagrantfile that defines testing 5 | virtual machine with all libraries installed, so you can check Vagrantfile how to install all those stuff. 6 | 7 | Thanks to ImageOptimizer and libraries that it uses, your image files can be **10%-70% smaller**. 8 | 9 | # Installation 10 | 11 | Using composer: 12 | 13 | composer require ps/image-optimizer 14 | 15 | # Basic usage 16 | 17 | ```php 18 | $factory = new \ImageOptimizer\OptimizerFactory(); 19 | $optimizer = $factory->get(); 20 | 21 | $filepath = /* path to image */; 22 | 23 | $optimizer->optimize($filepath); 24 | //optimized file overwrites original one 25 | ``` 26 | 27 | # Configuration 28 | 29 | By default optimizer does not throw any exception, if file can not be optimized or optimizing library for given file is 30 | not installed, optimizer will not touch original file. This behaviour is ok when you want to eventually optimize files 31 | uploaded by user. When in your use case optimization fault should cause exception, `ignore_errors` option was created 32 | especially for you. 33 | 34 | This library is very smart, you do not have to configure paths to all binaries of libraries that are used by ImageOptimizer, 35 | library will be looking for those binaries in few places, so if binaries are placed in standard places, it will be found 36 | automatically. 37 | 38 | Supported options: 39 | 40 | * `ignore_errors` (default: true) 41 | * `single_optimizer_timeout_in_seconds` (default: 60) - useful when you 42 | want to have control how long optimizing lasts. For example in some 43 | cases optimizing may not be worth when it takes big amount of time. 44 | Pass `null` in order to turn off timeout. 45 | * `output_filepath_pattern` (default: `%basename%/%filename%%ext%`) - 46 | destination where optimized file will be stored. By default it 47 | overrides original file. There are 3 placehoders: `%basename%`, 48 | `%filename%` (without extension and dot) and `%ext%` (extension with 49 | dot) which will be replaced by values from original file. 50 | * `execute_only_first_png_optimizer` (default: true) - execute the first 51 | successful or all `png` optimizers 52 | * `execute_only_first_jpeg_optimizer` (default: true) - execute the first successful or all `jpeg` optimizers 53 | * `optipng_options` (default: `array('-i0', '-o2', '-quiet')`) - an array of arguments to pass to the library 54 | * `pngquant_options` (default: `array('--force')`) 55 | * `pngcrush_options` (default: `array('-reduce', '-q', '-ow')`) 56 | * `pngout_options` (default: `array('-s3', '-q', '-y')`) 57 | * `advpng_options` (default: `array('-z', '-4', '-q')`) 58 | * `gifsicle_options` (default: `array('-b', '-O5')`) 59 | * `jpegoptim_options` (default: `array('--strip-all', '--all-progressive')`) 60 | * `jpegtran_options` (default: `array('-optimize', '-progressive')`) 61 | * `svgo_options` (default: `array('--disable=cleanupIDs')`) 62 | * `custom_optimizers` (default `array()`) 63 | * `optipng_bin` (default: will be guessed) - you can enforce paths to binaries, but by default it will be guessed 64 | * `pngquant_bin` 65 | * `pngcrush_bin` 66 | * `pngout_bin` 67 | * `advpng_bin` 68 | * `gifsicle_bin` 69 | * `jpegoptim_bin` 70 | * `jpegtran_bin` 71 | * `svgo_bin` 72 | 73 | You can pass array of options as first argument of `ImageOptimizer\OptimizerFactory` constructor. Second argument is 74 | optionally `Psr\LoggerInterface`. 75 | 76 | ```php 77 | $factory = new \ImageOptimizer\OptimizerFactory(array('ignore_errors' => false), $logger); 78 | ``` 79 | 80 | # Supported optimizers 81 | 82 | * default (`smart`) - it guess file type and choose optimizer for this file type 83 | * `png` - chain of optimizers for png files, by default it uses `pngquant` and `optipng`. `pngquant` is lossy optimization 84 | * `jpg` - first of two optimizations will be executed: `jpegtran` or `jpegoptim` 85 | * `gif` - alias to `gifsicle` 86 | * `pngquant` - [homepage][1] 87 | * `optipng` - [homepage][2] 88 | * `pngcrush` - [homepage][3] 89 | * `pngout` - [homepage][4] 90 | * `advpng` - [homepage][5] 91 | * `jpegtran` - [homepage][6] 92 | * `jpegoptim` - [homepage][7] 93 | * `gifsicle` - [homepage][8] 94 | * `svgo` - [homepage][9] 95 | 96 | You can obtain concrete optimizer by passing his name to `ImageOptimizer\OptimizerFactory`::`get` method: 97 | 98 | ```php 99 | //default optimizer is `smart` 100 | $optimizer = $factory->get(); 101 | 102 | //png optimizer 103 | $pngOptimizer = $factory->get('png'); 104 | 105 | //jpegoptim optimizer etc. 106 | $jpgOptimizer = $factory->get('jpegoptim'); 107 | ``` 108 | 109 | # Custom optimizers 110 | 111 | You can easily define custom optimizers: 112 | 113 | ```php 114 | $factory = new \ImageOptimizer\OptimizerFactory(array('custom_optimizers' => array( 115 | 'some_optimizier' => array( 116 | 'command' => 'some_command', 117 | 'args' => array('-some-flag') 118 | ) 119 | )), $logger); 120 | ``` 121 | 122 | And then usage: 123 | 124 | ```php 125 | $customOptimizer = $factory->get('some_optimizier'); 126 | ``` 127 | 128 | # I got "All optimizers failed to optimize the file" 129 | 130 | Probably you don't have required optimazers installed. Let's have a look 131 | at `Vagrantfile` file in order to see an example how to install those 132 | commands. 133 | 134 | In order to see all intermediate errors, you can use logger (be default 135 | `NullLogger` is used, so logs are not available): 136 | 137 | ```php 138 | class StdoutLogger extends \Psr\Log\AbstractLogger { 139 | public function log($level, $message, array $context = array()) { 140 | echo $message."\n"; 141 | } 142 | } 143 | 144 | $factory = new \ImageOptimizer\OptimizerFactory(array(), new StdoutLogger()); 145 | 146 | $factory->get()->optimize('yourfile.jpg'); 147 | 148 | // and have a look at stdout 149 | ``` 150 | 151 | # License 152 | 153 | **MIT** 154 | 155 | [1]: http://pngquant.org/ 156 | [2]: http://optipng.sourceforge.net/ 157 | [3]: http://pmt.sourceforge.net/pngcrush/ 158 | [4]: http://www.jonof.id.au/kenutils 159 | [5]: http://advancemame.sourceforge.net/doc-advpng.html 160 | [6]: http://jpegclub.org/jpegtran/ 161 | [7]: http://freecode.com/projects/jpegoptim 162 | [8]: http://www.lcdf.org/gifsicle/ 163 | [9]: https://github.com/svg/svgo 164 | -------------------------------------------------------------------------------- /vendor/symfony/process/Pipes/WindowsPipes.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\Process\Pipes; 13 | 14 | use Symfony\Component\Process\Exception\RuntimeException; 15 | use Symfony\Component\Process\Process; 16 | 17 | /** 18 | * WindowsPipes implementation uses temporary files as handles. 19 | * 20 | * @see https://bugs.php.net/51800 21 | * @see https://bugs.php.net/65650 22 | * 23 | * @author Romain Neutron 24 | * 25 | * @internal 26 | */ 27 | class WindowsPipes extends AbstractPipes 28 | { 29 | private $files = []; 30 | private $fileHandles = []; 31 | private $lockHandles = []; 32 | private $readBytes = [ 33 | Process::STDOUT => 0, 34 | Process::STDERR => 0, 35 | ]; 36 | private $haveReadSupport; 37 | 38 | public function __construct($input, bool $haveReadSupport) 39 | { 40 | $this->haveReadSupport = $haveReadSupport; 41 | 42 | if ($this->haveReadSupport) { 43 | // Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big. 44 | // Workaround for this problem is to use temporary files instead of pipes on Windows platform. 45 | // 46 | // @see https://bugs.php.net/51800 47 | $pipes = [ 48 | Process::STDOUT => Process::OUT, 49 | Process::STDERR => Process::ERR, 50 | ]; 51 | $tmpDir = sys_get_temp_dir(); 52 | $lastError = 'unknown reason'; 53 | set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; }); 54 | for ($i = 0;; ++$i) { 55 | foreach ($pipes as $pipe => $name) { 56 | $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name); 57 | 58 | if (!$h = fopen($file.'.lock', 'w')) { 59 | if (file_exists($file.'.lock')) { 60 | continue 2; 61 | } 62 | restore_error_handler(); 63 | throw new RuntimeException('A temporary file could not be opened to write the process output: '.$lastError); 64 | } 65 | if (!flock($h, \LOCK_EX | \LOCK_NB)) { 66 | continue 2; 67 | } 68 | if (isset($this->lockHandles[$pipe])) { 69 | flock($this->lockHandles[$pipe], \LOCK_UN); 70 | fclose($this->lockHandles[$pipe]); 71 | } 72 | $this->lockHandles[$pipe] = $h; 73 | 74 | if (!($h = fopen($file, 'w')) || !fclose($h) || !$h = fopen($file, 'r')) { 75 | flock($this->lockHandles[$pipe], \LOCK_UN); 76 | fclose($this->lockHandles[$pipe]); 77 | unset($this->lockHandles[$pipe]); 78 | continue 2; 79 | } 80 | $this->fileHandles[$pipe] = $h; 81 | $this->files[$pipe] = $file; 82 | } 83 | break; 84 | } 85 | restore_error_handler(); 86 | } 87 | 88 | parent::__construct($input); 89 | } 90 | 91 | public function __sleep(): array 92 | { 93 | throw new \BadMethodCallException('Cannot serialize '.__CLASS__); 94 | } 95 | 96 | public function __wakeup() 97 | { 98 | throw new \BadMethodCallException('Cannot unserialize '.__CLASS__); 99 | } 100 | 101 | public function __destruct() 102 | { 103 | $this->close(); 104 | } 105 | 106 | /** 107 | * {@inheritdoc} 108 | */ 109 | public function getDescriptors(): array 110 | { 111 | if (!$this->haveReadSupport) { 112 | $nullstream = fopen('NUL', 'c'); 113 | 114 | return [ 115 | ['pipe', 'r'], 116 | $nullstream, 117 | $nullstream, 118 | ]; 119 | } 120 | 121 | // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/51800) 122 | // We're not using file handles as it can produce corrupted output https://bugs.php.net/65650 123 | // So we redirect output within the commandline and pass the nul device to the process 124 | return [ 125 | ['pipe', 'r'], 126 | ['file', 'NUL', 'w'], 127 | ['file', 'NUL', 'w'], 128 | ]; 129 | } 130 | 131 | /** 132 | * {@inheritdoc} 133 | */ 134 | public function getFiles(): array 135 | { 136 | return $this->files; 137 | } 138 | 139 | /** 140 | * {@inheritdoc} 141 | */ 142 | public function readAndWrite(bool $blocking, bool $close = false): array 143 | { 144 | $this->unblock(); 145 | $w = $this->write(); 146 | $read = $r = $e = []; 147 | 148 | if ($blocking) { 149 | if ($w) { 150 | @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6); 151 | } elseif ($this->fileHandles) { 152 | usleep(Process::TIMEOUT_PRECISION * 1E6); 153 | } 154 | } 155 | foreach ($this->fileHandles as $type => $fileHandle) { 156 | $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]); 157 | 158 | if (isset($data[0])) { 159 | $this->readBytes[$type] += \strlen($data); 160 | $read[$type] = $data; 161 | } 162 | if ($close) { 163 | ftruncate($fileHandle, 0); 164 | fclose($fileHandle); 165 | flock($this->lockHandles[$type], \LOCK_UN); 166 | fclose($this->lockHandles[$type]); 167 | unset($this->fileHandles[$type], $this->lockHandles[$type]); 168 | } 169 | } 170 | 171 | return $read; 172 | } 173 | 174 | /** 175 | * {@inheritdoc} 176 | */ 177 | public function haveReadSupport(): bool 178 | { 179 | return $this->haveReadSupport; 180 | } 181 | 182 | /** 183 | * {@inheritdoc} 184 | */ 185 | public function areOpen(): bool 186 | { 187 | return $this->pipes && $this->fileHandles; 188 | } 189 | 190 | /** 191 | * {@inheritdoc} 192 | */ 193 | public function close() 194 | { 195 | parent::close(); 196 | foreach ($this->fileHandles as $type => $handle) { 197 | ftruncate($handle, 0); 198 | fclose($handle); 199 | flock($this->lockHandles[$type], \LOCK_UN); 200 | fclose($this->lockHandles[$type]); 201 | } 202 | $this->fileHandles = $this->lockHandles = []; 203 | } 204 | } 205 | --------------------------------------------------------------------------------