diff --git a/composer.json b/composer.json index 9f7ba9fb..a486d2ce 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "tinify/tiny-compress-images", "description": "Speed up your website. Optimize your JPEG, PNG, and WebP images automatically with TinyPNG.", - "license": "GPL-2.0+", + "license": "GPL-2.0-or-later", "type": "wordpress-plugin", "keywords": [ "plugin" @@ -21,9 +21,12 @@ "mikey179/vfsstream": "~1.5", "mockery/mockery": "~0.9", "phpdocumentor/reflection-docblock": "~2.0", - "squizlabs/php_codesniffer": "~2.2", + "squizlabs/php_codesniffer": "^3.13", "tinify/tinify": "dev-create-key", - "wp-coding-standards/wpcs": "0.11" + "wp-coding-standards/wpcs": "^3.2", + "phpcompatibility/php-compatibility": "^9.3", + "phpcompatibility/phpcompatibility-wp": "^2.1", + "dealerdirect/phpcodesniffer-composer-installer": "^1.2" }, "scripts": { "post-install-cmd": "bin/post-install", @@ -31,7 +34,8 @@ }, "config": { "allow-plugins": { - "composer/installers": true + "composer/installers": true, + "dealerdirect/phpcodesniffer-composer-installer": true } } } diff --git a/composer.lock b/composer.lock index fba67d76..c9dc0943 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "fb7539fb8f55624431051c11d96fd4b5", + "content-hash": "a208b3293cb419abad1ae1481e3d74b4", "packages": [ { "name": "composer/installers", @@ -159,6 +159,102 @@ } ], "packages-dev": [ + { + "name": "dealerdirect/phpcodesniffer-composer-installer", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/composer-installer.git", + "reference": "845eb62303d2ca9b289ef216356568ccc075ffd1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/845eb62303d2ca9b289ef216356568ccc075ffd1", + "reference": "845eb62303d2ca9b289ef216356568ccc075ffd1", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.2", + "php": ">=5.4", + "squizlabs/php_codesniffer": "^3.1.0 || ^4.0" + }, + "require-dev": { + "composer/composer": "^2.2", + "ext-json": "*", + "ext-zip": "*", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcompatibility/php-compatibility": "^9.0 || ^10.0.0@dev", + "yoast/phpunit-polyfills": "^1.0" + }, + "type": "composer-plugin", + "extra": { + "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" + }, + "autoload": { + "psr-4": { + "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Franck Nijhof", + "email": "opensource@frenck.dev", + "homepage": "https://frenck.dev", + "role": "Open source developer" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer Standards Composer Installer Plugin", + "keywords": [ + "PHPCodeSniffer", + "PHP_CodeSniffer", + "code quality", + "codesniffer", + "composer", + "installer", + "phpcbf", + "phpcs", + "plugin", + "qa", + "quality", + "standard", + "standards", + "style guide", + "stylecheck", + "tests" + ], + "support": { + "issues": "https://github.com/PHPCSStandards/composer-installer/issues", + "security": "https://github.com/PHPCSStandards/composer-installer/security/policy", + "source": "https://github.com/PHPCSStandards/composer-installer" + }, + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" + } + ], + "time": "2025-11-11T04:32:07+00:00" + }, { "name": "doctrine/instantiator", "version": "1.5.0", @@ -635,6 +731,394 @@ }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "phpcompatibility/php-compatibility", + "version": "9.3.5", + "source": { + "type": "git", + "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", + "reference": "9fb324479acf6f39452e0655d2429cc0d3914243" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9fb324479acf6f39452e0655d2429cc0d3914243", + "reference": "9fb324479acf6f39452e0655d2429cc0d3914243", + "shasum": "" + }, + "require": { + "php": ">=5.3", + "squizlabs/php_codesniffer": "^2.3 || ^3.0.2" + }, + "conflict": { + "squizlabs/php_codesniffer": "2.6.2" + }, + "require-dev": { + "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0" + }, + "suggest": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Wim Godden", + "homepage": "https://github.com/wimg", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors" + } + ], + "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.", + "homepage": "http://techblog.wimgodden.be/tag/codesniffer/", + "keywords": [ + "compatibility", + "phpcs", + "standards" + ], + "support": { + "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues", + "source": "https://github.com/PHPCompatibility/PHPCompatibility" + }, + "time": "2019-12-27T09:44:58+00:00" + }, + { + "name": "phpcompatibility/phpcompatibility-paragonie", + "version": "1.3.4", + "source": { + "type": "git", + "url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git", + "reference": "244d7b04fc4bc2117c15f5abe23eb933b5f02bbf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/244d7b04fc4bc2117c15f5abe23eb933b5f02bbf", + "reference": "244d7b04fc4bc2117c15f5abe23eb933b5f02bbf", + "shasum": "" + }, + "require": { + "phpcompatibility/php-compatibility": "^9.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "paragonie/random_compat": "dev-master", + "paragonie/sodium_compat": "dev-master" + }, + "suggest": { + "dealerdirect/phpcodesniffer-composer-installer": "^1.0 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Wim Godden", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "lead" + } + ], + "description": "A set of rulesets for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by the Paragonie polyfill libraries.", + "homepage": "http://phpcompatibility.com/", + "keywords": [ + "compatibility", + "paragonie", + "phpcs", + "polyfill", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues", + "security": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/security/policy", + "source": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie" + }, + "funding": [ + { + "url": "https://github.com/PHPCompatibility", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcompatibility", + "type": "thanks_dev" + } + ], + "time": "2025-09-19T17:43:28+00:00" + }, + { + "name": "phpcompatibility/phpcompatibility-wp", + "version": "2.1.8", + "source": { + "type": "git", + "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git", + "reference": "7c8d18b4d90dac9e86b0869a608fa09158e168fa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/7c8d18b4d90dac9e86b0869a608fa09158e168fa", + "reference": "7c8d18b4d90dac9e86b0869a608fa09158e168fa", + "shasum": "" + }, + "require": { + "phpcompatibility/php-compatibility": "^9.0", + "phpcompatibility/phpcompatibility-paragonie": "^1.0", + "squizlabs/php_codesniffer": "^3.3" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^1.0" + }, + "suggest": { + "dealerdirect/phpcodesniffer-composer-installer": "^1.0 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", + "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." + }, + "type": "phpcodesniffer-standard", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Wim Godden", + "role": "lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "lead" + } + ], + "description": "A ruleset for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by WordPress.", + "homepage": "http://phpcompatibility.com/", + "keywords": [ + "compatibility", + "phpcs", + "standards", + "static analysis", + "wordpress" + ], + "support": { + "issues": "https://github.com/PHPCompatibility/PHPCompatibilityWP/issues", + "security": "https://github.com/PHPCompatibility/PHPCompatibilityWP/security/policy", + "source": "https://github.com/PHPCompatibility/PHPCompatibilityWP" + }, + "funding": [ + { + "url": "https://github.com/PHPCompatibility", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcompatibility", + "type": "thanks_dev" + } + ], + "time": "2025-10-18T00:05:59+00:00" + }, + { + "name": "phpcsstandards/phpcsextra", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/PHPCSExtra.git", + "reference": "b598aa890815b8df16363271b659d73280129101" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSExtra/zipball/b598aa890815b8df16363271b659d73280129101", + "reference": "b598aa890815b8df16363271b659d73280129101", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "phpcsstandards/phpcsutils": "^1.2.0", + "squizlabs/php_codesniffer": "^3.13.5 || ^4.0.1" + }, + "require-dev": { + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcsstandards/phpcsdevcs": "^1.2.0", + "phpcsstandards/phpcsdevtools": "^1.2.1", + "phpunit/phpunit": "^4.5 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-stable": "1.x-dev", + "dev-develop": "1.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHPCSExtra/graphs/contributors" + } + ], + "description": "A collection of sniffs and standards for use with PHP_CodeSniffer.", + "keywords": [ + "PHP_CodeSniffer", + "phpcbf", + "phpcodesniffer-standard", + "phpcs", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHPCSStandards/PHPCSExtra/issues", + "security": "https://github.com/PHPCSStandards/PHPCSExtra/security/policy", + "source": "https://github.com/PHPCSStandards/PHPCSExtra" + }, + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" + } + ], + "time": "2025-11-12T23:06:57+00:00" + }, + { + "name": "phpcsstandards/phpcsutils", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/PHPCSUtils.git", + "reference": "d71128c702c180ca3b27c761b6773f883394f162" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/PHPCSUtils/zipball/d71128c702c180ca3b27c761b6773f883394f162", + "reference": "d71128c702c180ca3b27c761b6773f883394f162", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1 || ^0.5 || ^0.6.2 || ^0.7 || ^1.0", + "php": ">=5.4", + "squizlabs/php_codesniffer": "^3.13.5 || ^4.0.1" + }, + "require-dev": { + "ext-filter": "*", + "php-parallel-lint/php-console-highlighter": "^1.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcsstandards/phpcsdevcs": "^1.2.0", + "yoast/phpunit-polyfills": "^1.1.0 || ^2.0.0 || ^3.0.0" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-stable": "1.x-dev", + "dev-develop": "1.x-dev" + } + }, + "autoload": { + "classmap": [ + "PHPCSUtils/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Juliette Reinders Folmer", + "homepage": "https://github.com/jrfnl", + "role": "lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHPCSUtils/graphs/contributors" + } + ], + "description": "A suite of utility functions for use with PHP_CodeSniffer", + "homepage": "https://phpcsutils.com/", + "keywords": [ + "PHP_CodeSniffer", + "phpcbf", + "phpcodesniffer-standard", + "phpcs", + "phpcs3", + "phpcs4", + "standards", + "static analysis", + "tokens", + "utility" + ], + "support": { + "docs": "https://phpcsutils.com/", + "issues": "https://github.com/PHPCSStandards/PHPCSUtils/issues", + "security": "https://github.com/PHPCSStandards/PHPCSUtils/security/policy", + "source": "https://github.com/PHPCSStandards/PHPCSUtils" + }, + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" + } + ], + "time": "2025-11-17T12:58:33+00:00" + }, { "name": "phpdocumentor/reflection-docblock", "version": "2.0.5", @@ -2075,64 +2559,32 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "2.9.2", + "version": "3.13.5", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "2acf168de78487db620ab4bc524135a13cfe6745" + "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/2acf168de78487db620ab4bc524135a13cfe6745", - "reference": "2acf168de78487db620ab4bc524135a13cfe6745", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0ca86845ce43291e8f5692c7356fccf3bcf02bf4", + "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4", "shasum": "" }, "require": { "ext-simplexml": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", - "php": ">=5.1.2" + "php": ">=5.4.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" }, "bin": [ - "scripts/phpcs", - "scripts/phpcbf" + "bin/phpcbf", + "bin/phpcs" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "classmap": [ - "CodeSniffer.php", - "CodeSniffer/CLI.php", - "CodeSniffer/Exception.php", - "CodeSniffer/File.php", - "CodeSniffer/Fixer.php", - "CodeSniffer/Report.php", - "CodeSniffer/Reporting.php", - "CodeSniffer/Sniff.php", - "CodeSniffer/Tokens.php", - "CodeSniffer/Reports/", - "CodeSniffer/Tokenizers/", - "CodeSniffer/DocGenerators/", - "CodeSniffer/Standards/AbstractPatternSniff.php", - "CodeSniffer/Standards/AbstractScopeSniff.php", - "CodeSniffer/Standards/AbstractVariableSniff.php", - "CodeSniffer/Standards/IncorrectPatternException.php", - "CodeSniffer/Standards/Generic/Sniffs/", - "CodeSniffer/Standards/MySource/Sniffs/", - "CodeSniffer/Standards/PEAR/Sniffs/", - "CodeSniffer/Standards/PSR1/Sniffs/", - "CodeSniffer/Standards/PSR2/Sniffs/", - "CodeSniffer/Standards/Squiz/Sniffs/", - "CodeSniffer/Standards/Zend/Sniffs/" - ] - }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" @@ -2140,19 +2592,29 @@ "authors": [ { "name": "Greg Sherwood", - "role": "lead" + "role": "Former lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "Current lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" } ], "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "http://www.squizlabs.com/php-codesniffer", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", "keywords": [ "phpcs", - "standards" + "standards", + "static analysis" ], "support": { - "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", - "source": "https://github.com/squizlabs/PHP_CodeSniffer", - "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", + "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", + "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" }, "funding": [ { @@ -2166,9 +2628,13 @@ { "url": "https://opencollective.com/php_codesniffer", "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" } ], - "time": "2018-11-07T22:31:41+00:00" + "time": "2025-11-04T16:30:35+00:00" }, { "name": "theseer/tokenizer", @@ -2281,22 +2747,40 @@ }, { "name": "wp-coding-standards/wpcs", - "version": "0.11.0", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/WordPress/WordPress-Coding-Standards.git", - "reference": "407e4b85f547a5251185f89ceae6599917343388" + "reference": "d2421de7cec3274ae622c22c744de9a62c7925af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/407e4b85f547a5251185f89ceae6599917343388", - "reference": "407e4b85f547a5251185f89ceae6599917343388", + "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/d2421de7cec3274ae622c22c744de9a62c7925af", + "reference": "d2421de7cec3274ae622c22c744de9a62c7925af", "shasum": "" }, "require": { - "squizlabs/php_codesniffer": "^2.8.1" + "ext-filter": "*", + "ext-libxml": "*", + "ext-tokenizer": "*", + "ext-xmlreader": "*", + "php": ">=5.4", + "phpcsstandards/phpcsextra": "^1.4.0", + "phpcsstandards/phpcsutils": "^1.1.0", + "squizlabs/php_codesniffer": "^3.13.0" }, - "type": "library", + "require-dev": { + "php-parallel-lint/php-console-highlighter": "^1.0.0", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpcompatibility/php-compatibility": "^9.0", + "phpcsstandards/phpcsdevtools": "^1.2.0", + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0" + }, + "suggest": { + "ext-iconv": "For improved results", + "ext-mbstring": "For improved results" + }, + "type": "phpcodesniffer-standard", "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" @@ -2304,20 +2788,28 @@ "authors": [ { "name": "Contributors", - "homepage": "https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/graphs/contributors" + "homepage": "https://github.com/WordPress/WordPress-Coding-Standards/graphs/contributors" } ], "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress coding conventions", "keywords": [ "phpcs", "standards", + "static analysis", "wordpress" ], "support": { - "issues": "https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/issues", - "source": "https://github.com/WordPress/WordPress-Coding-Standards/tree/0.11.0" + "issues": "https://github.com/WordPress/WordPress-Coding-Standards/issues", + "source": "https://github.com/WordPress/WordPress-Coding-Standards", + "wiki": "https://github.com/WordPress/WordPress-Coding-Standards/wiki" }, - "time": "2017-03-20T23:17:58+00:00" + "funding": [ + { + "url": "https://opencollective.com/php_codesniffer", + "type": "custom" + } + ], + "time": "2025-07-24T20:08:31+00:00" } ], "aliases": [], @@ -2331,5 +2823,5 @@ "php": ">=5.3.0" }, "platform-dev": {}, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/phpcs.xml b/phpcs.xml index 8582f134..aa989956 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -1,8 +1,12 @@ - + + + - + + + diff --git a/src/class-tiny-bulk-optimization.php b/src/class-tiny-bulk-optimization.php index 5328abbf..52542ccb 100644 --- a/src/class-tiny-bulk-optimization.php +++ b/src/class-tiny-bulk-optimization.php @@ -24,20 +24,20 @@ class Tiny_Bulk_Optimization { const PAGING_SIZE = 25000; public static function get_optimization_statistics( $settings, $result = null ) { - $stats = array(); - $stats['uploaded-images'] = 0; - $stats['optimized-image-sizes'] = 0; + $stats = array(); + $stats['uploaded-images'] = 0; + $stats['optimized-image-sizes'] = 0; $stats['available-unoptimized-sizes'] = 0; - $stats['optimized-library-size'] = 0; - $stats['unoptimized-library-size'] = 0; - $stats['estimated_credit_use'] = 0; - $stats['available-for-optimization'] = array(); + $stats['optimized-library-size'] = 0; + $stats['unoptimized-library-size'] = 0; + $stats['estimated_credit_use'] = 0; + $stats['available-for-optimization'] = array(); if ( is_null( $result ) ) { $last_image_id = null; do { - $result = self::wpdb_retrieve_images_and_metadata( $last_image_id ); - $stats = self::populate_optimization_statistics( $settings, $result, $stats ); + $result = self::wpdb_retrieve_images_and_metadata( $last_image_id ); + $stats = self::populate_optimization_statistics( $settings, $result, $stats ); $last_image = end( $result ); if ( isset( $last_image['ID'] ) ) { $last_image_id = $last_image['ID']; @@ -51,7 +51,8 @@ public static function get_optimization_statistics( $settings, $result = null ) if ( 0 != $stats['unoptimized-library-size'] ) { $stats['display-percentage'] = round( 100 - - ( $stats['optimized-library-size'] / $stats['unoptimized-library-size'] * 100 ), 1 + ( $stats['optimized-library-size'] / $stats['unoptimized-library-size'] * 100 ), + 1 ); } else { $stats['display-percentage'] = 0; @@ -65,7 +66,7 @@ private static function wpdb_retrieve_images_and_metadata( $start_id ) { // Retrieve posts that have "_wp_attachment_metadata" image metadata // and optionally contain "tiny_compress_images" metadata. $sql_start_id = ( $start_id ? " $wpdb->posts.ID < $start_id AND " : '' ); - $query = + $query = "SELECT $wpdb->posts.ID, $wpdb->posts.post_title, @@ -94,23 +95,24 @@ private static function wpdb_retrieve_images_and_metadata( $start_id ) { ORDER BY ID DESC LIMIT " . self::PAGING_SIZE; - return $wpdb->get_results( $query, ARRAY_A ); // WPCS: unprepared SQL OK. + // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Query is built from internal IDs and constants only. + return $wpdb->get_results( $query, ARRAY_A ); } private static function populate_optimization_statistics( $settings, $result, $stats ) { - $active_sizes = $settings->get_sizes(); + $active_sizes = $settings->get_sizes(); $active_tinify_sizes = $settings->get_active_tinify_sizes(); - $conversion_enabled = $settings->get_conversion_enabled(); + $conversion_enabled = $settings->get_conversion_enabled(); for ( $i = 0; $i < sizeof( $result ); $i++ ) { - $wp_metadata = unserialize( (string) $result[ $i ]['meta_value'] ); + $wp_metadata = unserialize( (string) $result[ $i ]['meta_value'] ); $tiny_metadata = isset( $result[ $i ]['tiny_meta_value'] ) ? unserialize( (string) $result[ $i ]['tiny_meta_value'] ) : array(); if ( ! is_array( $tiny_metadata ) ) { $tiny_metadata = array(); } - $tiny_image = new Tiny_Image( + $tiny_image = new Tiny_Image( $settings, $result[ $i ]['ID'], $wp_metadata, @@ -120,29 +122,32 @@ private static function populate_optimization_statistics( $settings, $result, $s ); $image_stats = $tiny_image->get_statistics( $active_sizes, $active_tinify_sizes ); - $stats['uploaded-images']++; + ++$stats['uploaded-images']; $stats['estimated_credit_use'] += $image_stats['available_uncompressed_sizes']; if ( $conversion_enabled ) { $stats['available-unoptimized-sizes'] += $image_stats['available_unconverted_sizes']; - $stats['optimized-image-sizes'] += + $stats['optimized-image-sizes'] += $image_stats['image_sizes_converted']; - $stats['estimated_credit_use'] += $image_stats['available_unconverted_sizes']; + $stats['estimated_credit_use'] += + $image_stats['available_unconverted_sizes']; } else { $stats['available-unoptimized-sizes'] += - $image_stats['available_uncompressed_sizes']; - $stats['optimized-image-sizes'] += - $image_stats['image_sizes_compressed']; + $image_stats['available_uncompressed_sizes']; + $stats['optimized-image-sizes'] += + $image_stats['image_sizes_compressed']; } - $stats['optimized-library-size'] += $image_stats['compressed_total_size']; + $stats['optimized-library-size'] += $image_stats['compressed_total_size']; $stats['unoptimized-library-size'] += $image_stats['initial_total_size']; - $has_conversions = $image_stats['available_unconverted_sizes'] > 0; - $has_compressions = $image_stats['available_uncompressed_sizes'] > 0; - $has_optimizations = $has_compressions || ($conversion_enabled && $has_conversions); + $has_conversions = $image_stats['available_unconverted_sizes'] > 0; + $has_compressions = $image_stats['available_uncompressed_sizes'] > 0; + $has_optimizations = $has_compressions || ( + $conversion_enabled && $has_conversions + ); if ( $has_optimizations ) { $stats['available-for-optimization'][] = array( - 'ID' => $result[ $i ]['ID'], + 'ID' => $result[ $i ]['ID'], 'post_title' => $result[ $i ]['post_title'], ); } diff --git a/src/class-tiny-cli.php b/src/class-tiny-cli.php index 511b03f9..ba02f3af 100644 --- a/src/class-tiny-cli.php +++ b/src/class-tiny-cli.php @@ -19,13 +19,6 @@ */ class Tiny_Cli { - public static function register_command( $settings ) { - $command_instance = new Tiny_Command( $settings ); - WP_CLI::add_command( 'tiny', $command_instance ); - } -} - -class Tiny_Command { /** * Tinify Settings @@ -38,6 +31,11 @@ public function __construct( $settings ) { $this->tiny_settings = $settings; } + public static function register_command( $settings ) { + $command_instance = new Tiny_Cli( $settings ); + WP_CLI::add_command( 'tiny', $command_instance ); + } + /** * Optimize will process images * @@ -76,7 +74,7 @@ public function optimize( $args, $assoc_args ) { $total = count( $attachments ); WP_CLI::log( 'Optimizing ' . $total . ' images.' ); - $progress = Utils\make_progress_bar( 'Optimizing images', $total ); + $progress = Utils\make_progress_bar( 'Optimizing images', $total ); $optimized = 0; foreach ( $attachments as $attachment_id ) { $attachment_id = intval( $attachment_id ); @@ -90,7 +88,7 @@ public function optimize( $args, $assoc_args ) { try { $result = $this->optimize_attachment( $attachment_id ); if ( isset( $result['success'] ) && $result['success'] > 0 ) { - $optimized++; + ++$optimized; } } catch ( Exception $e ) { WP_CLI::warning( diff --git a/src/class-tiny-compress-client.php b/src/class-tiny-compress-client.php index 5bbf8c9a..5059bd93 100644 --- a/src/class-tiny-compress-client.php +++ b/src/class-tiny-compress-client.php @@ -20,18 +20,18 @@ if ( ! defined( '\Tinify\VERSION' ) ) { /* Load vendored client if it is not yet loaded. */ - require_once dirname( __FILE__ ) . '/vendor/tinify/Tinify/Exception.php'; - require_once dirname( __FILE__ ) . '/vendor/tinify/Tinify/ResultMeta.php'; - require_once dirname( __FILE__ ) . '/vendor/tinify/Tinify/Result.php'; - require_once dirname( __FILE__ ) . '/vendor/tinify/Tinify/Source.php'; - require_once dirname( __FILE__ ) . '/vendor/tinify/Tinify/Client.php'; - require_once dirname( __FILE__ ) . '/vendor/tinify/Tinify.php'; + require_once __DIR__ . '/vendor/tinify/Tinify/Exception.php'; + require_once __DIR__ . '/vendor/tinify/Tinify/ResultMeta.php'; + require_once __DIR__ . '/vendor/tinify/Tinify/Result.php'; + require_once __DIR__ . '/vendor/tinify/Tinify/Source.php'; + require_once __DIR__ . '/vendor/tinify/Tinify/Client.php'; + require_once __DIR__ . '/vendor/tinify/Tinify.php'; } class Tiny_Compress_Client extends Tiny_Compress { private $last_error_code = 0; - private $last_message = ''; + private $last_message = ''; private $proxy; protected function __construct( $api_key, $after_compress_callback ) { @@ -104,17 +104,17 @@ protected function compress( $input, $resize_opts, $preserve_opts, $convert_to ) } $compress_result = $source->result(); - $meta = array( - 'input' => array( + $meta = array( + 'input' => array( 'size' => strlen( $input ), 'type' => Tiny_Helpers::get_mimetype( $input ), ), 'output' => array( - 'size' => $compress_result->size(), - 'type' => $compress_result->mediaType(), - 'width' => $compress_result->width(), + 'size' => $compress_result->size(), + 'type' => $compress_result->mediaType(), + 'width' => $compress_result->width(), 'height' => $compress_result->height(), - 'ratio' => round( $compress_result->size() / strlen( $input ), 4 ), + 'ratio' => round( $compress_result->size() / strlen( $input ), 4 ), ), ); @@ -122,16 +122,18 @@ protected function compress( $input, $resize_opts, $preserve_opts, $convert_to ) $result = array( $buffer, $meta, null ); if ( count( $convert_to ) > 0 ) { - $convert_source = $source->convert( array( - 'type' => $convert_to, - ) ); - $convert_result = $convert_source->result(); + $convert_source = $source->convert( + array( + 'type' => $convert_to, + ) + ); + $convert_result = $convert_source->result(); $meta['convert'] = array( 'type' => $convert_result->mediaType(), 'size' => $convert_result->size(), ); - $convert_buffer = $convert_result->toBuffer(); - $result = array( $buffer, $meta, $convert_buffer ); + $convert_buffer = $convert_result->toBuffer(); + $result = array( $buffer, $meta, $convert_buffer ); } return $result; @@ -167,26 +169,26 @@ public function create_key( $email, $options ) { private function set_request_options( $client ) { /* The client does not let us override cURL properties yet, so we have - to use a reflection property. */ + to use a reflection property. */ $property = new ReflectionProperty( $client, 'options' ); $property->setAccessible( true ); $options = $property->getValue( $client ); if ( TINY_DEBUG ) { - $file = fopen( dirname( __FILE__ ) . '/curl.log', 'w' ); + $file = fopen( __DIR__ . '/curl.log', 'w' ); if ( is_resource( $file ) ) { $options[ CURLOPT_VERBOSE ] = true; - $options[ CURLOPT_STDERR ] = $file; + $options[ CURLOPT_STDERR ] = $file; } } if ( $this->proxy->is_enabled() && $this->proxy->send_through_proxy( $url ) ) { $options[ CURLOPT_PROXYTYPE ] = CURLPROXY_HTTP; - $options[ CURLOPT_PROXY ] = $this->proxy->host(); + $options[ CURLOPT_PROXY ] = $this->proxy->host(); $options[ CURLOPT_PROXYPORT ] = $this->proxy->port(); if ( $this->proxy->use_authentication() ) { - $options[ CURLOPT_PROXYAUTH ] = CURLAUTH_ANY; + $options[ CURLOPT_PROXYAUTH ] = CURLAUTH_ANY; $options[ CURLOPT_PROXYUSERPWD ] = $this->proxy->authentication(); } } diff --git a/src/class-tiny-compress-fopen.php b/src/class-tiny-compress-fopen.php index 4e7a9cd4..0ee72f7f 100644 --- a/src/class-tiny-compress-fopen.php +++ b/src/class-tiny-compress-fopen.php @@ -61,8 +61,8 @@ public function get_key() { } protected function validate() { - $params = $this->request_options( 'GET' ); - $url = Tiny_Config::KEYS_URL . '/' . $this->get_key(); + $params = $this->request_options( 'GET' ); + $url = Tiny_Config::KEYS_URL . '/' . $this->get_key(); list($details, $headers, $status_code) = $this->request( $params, $url ); if ( 429 == $status_code || 400 == $status_code || 200 == $status_code ) { @@ -83,7 +83,7 @@ protected function validate() { } protected function compress( $input, $resize_opts, $preserve_opts, $convert_to ) { - $params = $this->request_options( 'POST', $input ); + $params = $this->request_options( 'POST', $input ); list($details, $headers, $status_code) = $this->request( $params ); $output_url = isset( $headers['location'] ) ? $headers['location'] : null; @@ -106,7 +106,10 @@ protected function compress( $input, $resize_opts, $preserve_opts, $convert_to ) ); } - $params = $this->output_request_options( $resize_opts, $preserve_opts ); + $params = $this->output_request_options( + $resize_opts, + $preserve_opts + ); list($output, $headers, $status_code) = $this->request( $params, $output_url ); if ( $status_code >= 400 && is_array( $output ) && isset( $output['error'] ) ) { @@ -131,16 +134,19 @@ protected function compress( $input, $resize_opts, $preserve_opts, $convert_to ) } $meta = array( - 'input' => array( + 'input' => array( 'size' => strlen( $input ), 'type' => Tiny_Helpers::get_mimetype( $input ), ), 'output' => array( - 'size' => strlen( $output ), - 'type' => $headers['content-type'], - 'width' => intval( $headers['image-width'] ), + 'size' => strlen( $output ), + 'type' => $headers['content-type'], + 'width' => intval( $headers['image-width'] ), 'height' => intval( $headers['image-height'] ), - 'ratio' => round( strlen( $output ) / strlen( $input ), 4 ), + 'ratio' => round( + strlen( $output ) / strlen( $input ), + 4 + ), ), ); @@ -161,11 +167,11 @@ protected function compress( $input, $resize_opts, $preserve_opts, $convert_to ) $convert_params, $output_url ); - $meta['convert'] = array( + $meta['convert'] = array( 'type' => $convert_headers['content-type'], 'size' => strlen( $convert_output ), ); - $convert = $convert_output; + $convert = $convert_output; } @@ -185,13 +191,13 @@ private function request( $params, $url = Tiny_Config::SHRINK_URL ) { } $meta_data = stream_get_meta_data( $request ); - $headers = $meta_data['wrapper_data']; + $headers = $meta_data['wrapper_data']; if ( ! is_array( $headers ) ) { $headers = iterator_to_array( $headers ); } $status_code = $this->parse_status_code( $headers ); - $headers = $this->parse_headers( $headers ); + $headers = $this->parse_headers( $headers ); if ( isset( $headers['compression-count'] ) ) { $this->compression_count = intval( $headers['compression-count'] ); @@ -248,19 +254,22 @@ private function parse_headers( $headers ) { private function request_options( $method, $body = null, $headers = array() ) { return array( 'http' => array( - 'method' => $method, - 'header' => array_merge($headers, array( - 'Authorization: Basic ' . base64_encode( 'api:' . $this->api_key ), - 'User-Agent: ' . self::identifier(), - 'Content-Type: multipart/form-data', - )), - 'content' => $body, + 'method' => $method, + 'header' => array_merge( + $headers, + array( + 'Authorization: Basic ' . base64_encode( 'api:' . $this->api_key ), + 'User-Agent: ' . self::identifier(), + 'Content-Type: multipart/form-data', + ) + ), + 'content' => $body, 'follow_location' => 0, - 'max_redirects' => 1, // Necessary for PHP 5.2 - 'ignore_errors' => true, // Apparently, a 201 is a failure + 'max_redirects' => 1, // Necessary for PHP 5.2 + 'ignore_errors' => true, // Apparently, a 201 is a failure ), - 'ssl' => array( - 'cafile' => $this->get_ca_file(), + 'ssl' => array( + 'cafile' => $this->get_ca_file(), 'verify_peer' => true, ), ); @@ -286,7 +295,7 @@ private function output_request_options( $resize_opts, $preserve_opts ) { } private static function get_ca_file() { - return dirname( __FILE__ ) . '/data/cacert.pem'; + return __DIR__ . '/data/cacert.pem'; } private static function decode( $text ) { @@ -294,8 +303,8 @@ private static function decode( $text ) { if ( null === $result ) { $message = sprintf( 'JSON: %s [%d]', - (PHP_VERSION_ID >= 50500 ? json_last_error_msg() : 'Unknown error'), - (PHP_VERSION_ID >= 50300 ? json_last_error() : 'Error') + ( PHP_VERSION_ID >= 50500 ? json_last_error_msg() : 'Unknown error' ), + ( PHP_VERSION_ID >= 50300 ? json_last_error() : 'Error' ) ); throw new Tiny_Exception( $message, 'JsonError' ); diff --git a/src/class-tiny-compress.php b/src/class-tiny-compress.php index 931d14b0..d17f55c9 100644 --- a/src/class-tiny-compress.php +++ b/src/class-tiny-compress.php @@ -20,9 +20,9 @@ abstract class Tiny_Compress { - const KEY_MISSING = 'Register an account or provide an API key first'; + const KEY_MISSING = 'Register an account or provide an API key first'; const FILE_MISSING = 'File does not exist'; - const WRITE_ERROR = 'No permission to write to file'; + const WRITE_ERROR = 'No permission to write to file'; protected $after_compress_callback; @@ -37,7 +37,7 @@ public static function create( $api_key, $after_compress_callback = null ) { 'NoHttpClient' ); } - return new $class($api_key, $after_compress_callback); + return new $class( $api_key, $after_compress_callback ); } /* Based on pricing April 2016. */ @@ -53,12 +53,12 @@ protected function __construct( $after_compress_callback ) { $this->after_compress_callback = $after_compress_callback; } - public abstract function can_create_key(); - public abstract function get_compression_count(); - public abstract function get_remaining_credits(); - public abstract function get_paying_state(); - public abstract function get_email_address(); - public abstract function get_key(); + abstract public function can_create_key(); + abstract public function get_compression_count(); + abstract public function get_remaining_credits(); + abstract public function get_paying_state(); + abstract public function get_email_address(); + abstract public function get_key(); public function limit_reached() { return $this->get_remaining_credits() === 0; @@ -67,12 +67,12 @@ public function limit_reached() { public function get_status() { if ( $this->get_key() == null ) { return (object) array( - 'ok' => false, + 'ok' => false, 'message' => self::KEY_MISSING, ); } - $result = false; + $result = false; $message = null; try { @@ -88,7 +88,7 @@ public function get_status() { $this->call_after_compress_callback(); return (object) array( - 'ok' => $result, + 'ok' => $result, 'message' => $message, ); } @@ -167,8 +167,8 @@ public function compress_file( return $details; } - protected abstract function validate(); - protected abstract function compress( + abstract protected function validate(); + abstract protected function compress( $input, $resize_options, $preserve_options, @@ -205,14 +205,14 @@ private static function compression_cost( $total ) { if ( $total > 10000 ) { $compressions = $total - 10000; - $cost += $compressions * 0.002; - $total -= $compressions; + $cost += $compressions * 0.002; + $total -= $compressions; } if ( $total > 500 ) { $compressions = $total - 500; - $cost += $compressions * 0.009; - $total -= $compressions; + $cost += $compressions * 0.009; + $total -= $compressions; } return $cost; diff --git a/src/class-tiny-exception.php b/src/class-tiny-exception.php index cc568bcb..ee6d1ff5 100644 --- a/src/class-tiny-exception.php +++ b/src/class-tiny-exception.php @@ -23,13 +23,13 @@ class Tiny_Exception extends Exception { protected $status; public function __construct( $message, $type = null, $status = null ) { - if ( ! is_string( $message ) || ($type && ! is_string( $type )) ) { + if ( ! is_string( $message ) || ( $type && ! is_string( $type ) ) ) { throw new InvalidArgumentException( 'First two arguments must be strings' ); } - $this->type = $type; + $this->type = $type; $this->status = $status; parent::__construct( $message ); diff --git a/src/class-tiny-helpers.php b/src/class-tiny-helpers.php index 1e273bba..89e24cda 100644 --- a/src/class-tiny-helpers.php +++ b/src/class-tiny-helpers.php @@ -60,9 +60,9 @@ public static function replace_file_extension( $mimetype, $filepath ) { return $filepath; } - $dir = $parts['dirname']; - $name = $parts['filename']; - $sep = DIRECTORY_SEPARATOR; + $dir = $parts['dirname']; + $name = $parts['filename']; + $sep = DIRECTORY_SEPARATOR; if ( '.' === $dir ) { return $name . '.' . $extension_new; @@ -102,7 +102,7 @@ private static function mimetype_to_extension( $mimetype ) { public static function get_mimetype( $input ) { if ( class_exists( 'finfo' ) ) { $finfo = new finfo( FILEINFO_MIME_TYPE ); - $mime = $finfo->buffer( $input ); + $mime = $finfo->buffer( $input ); return $mime; } else { throw new Exception( 'finfo extension is not available.' ); diff --git a/src/class-tiny-image-size.php b/src/class-tiny-image-size.php index daa50d47..ca3fd27e 100644 --- a/src/class-tiny-image-size.php +++ b/src/class-tiny-image-size.php @@ -26,7 +26,7 @@ class Tiny_Image_Size { private $_exists; private $_file_size; private $_mime_type; - private $_duplicate = false; + private $_duplicate = false; private $_duplicate_of_size = ''; public function __construct( $filename = null ) { @@ -51,7 +51,7 @@ public function add_tiny_meta_start() { public function add_tiny_meta( $response ) { if ( isset( $this->meta['start'] ) ) { - $this->meta = $response; + $this->meta = $response; $this->meta['end'] = time(); } } @@ -59,8 +59,8 @@ public function add_tiny_meta( $response ) { public function add_tiny_meta_error( $exception ) { if ( isset( $this->meta['start'] ) ) { $this->meta = array( - 'error' => $exception->get_type(), - 'message' => $exception->get_message(), + 'error' => $exception->get_type(), + 'message' => $exception->get_message(), 'timestamp' => time(), ); } @@ -104,7 +104,6 @@ public function mark_as_compressed( $include_conversion = false ) { 'path' => $this->filename, ); } - } public function has_been_compressed() { @@ -133,7 +132,7 @@ public function filesize() { public function mimetype() { if ( is_null( $this->_mime_type ) ) { if ( $this->exists() ) { - $file = file_get_contents( $this->filename ); + $file = file_get_contents( $this->filename ); $this->_mime_type = Tiny_Helpers::get_mimetype( $file ); } else { $this->_mime_type = 'application/octet-stream'; @@ -229,7 +228,7 @@ public function resized() { } public function mark_duplicate( $duplicate_size_name ) { - $this->_duplicate = true; + $this->_duplicate = true; $this->_duplicate_of_size = $duplicate_size_name; } @@ -248,7 +247,7 @@ public function delete_converted_image_size() { } private function recently_started() { - $thirty_minutes_ago = date( 'U' ) - ( 60 * 30 ); + $thirty_minutes_ago = gmdate( 'U' ) - ( 60 * 30 ); return ( isset( $this->meta['start'] ) && $this->meta['start'] > $thirty_minutes_ago diff --git a/src/class-tiny-image.php b/src/class-tiny-image.php index 3a5a2678..d296c7f5 100644 --- a/src/class-tiny-image.php +++ b/src/class-tiny-image.php @@ -26,19 +26,19 @@ class Tiny_Image { private $id; private $name; private $wp_metadata; - private $sizes = array(); + private $sizes = array(); private $statistics = array(); public function __construct( - $settings, - $id, - $wp_metadata = null, - $tiny_metadata = null, - $active_sizes = null, - $active_tinify_sizes = null + $settings, + $id, + $wp_metadata = null, + $tiny_metadata = null, + $active_sizes = null, + $active_tinify_sizes = null ) { - $this->settings = $settings; - $this->id = $id; + $this->settings = $settings; + $this->id = $id; $this->wp_metadata = $wp_metadata; $this->parse_wp_metadata(); $this->parse_tiny_metadata( $tiny_metadata ); @@ -52,22 +52,22 @@ private function parse_wp_metadata() { if ( ! is_array( $this->wp_metadata ) || ! isset( $this->wp_metadata['file'] ) ) { /* No file metadata found, this might be another plugin messing with - metadata. Simply ignore this! */ + metadata. Simply ignore this! */ return; } - $upload_dir = wp_upload_dir(); + $upload_dir = wp_upload_dir(); $path_prefix = $upload_dir['basedir'] . '/'; - $path_info = pathinfo( $this->wp_metadata['file'] ); + $path_info = pathinfo( $this->wp_metadata['file'] ); if ( isset( $path_info['dirname'] ) ) { $path_prefix .= $path_info['dirname'] . '/'; } /* Do not use pathinfo for getting the filename. - It doesn't work when the filename starts with a special character. */ - $path_parts = explode( '/', $this->wp_metadata['file'] ); - $this->name = end( $path_parts ); - $filename = $path_prefix . $this->name; + It doesn't work when the filename starts with a special character. */ + $path_parts = explode( '/', $this->wp_metadata['file'] ); + $this->name = end( $path_parts ); + $filename = $path_prefix . $this->name; $this->sizes[ self::ORIGINAL ] = new Tiny_Image_Size( $filename ); // Ensure 'sizes' exists and is an array to prevent PHP Warnings @@ -81,7 +81,7 @@ private function parse_wp_metadata() { if ( is_array( $size_info ) && isset( $size_info['file'] ) ) { // Add to sanitized metadata $sanitized_sizes[ $size_name ] = $size_info; - $this->sizes[ $size_name ] = new Tiny_Image_Size( + $this->sizes[ $size_name ] = new Tiny_Image_Size( $path_prefix . $size_info['file'] ); } @@ -151,7 +151,7 @@ private function parse_tiny_metadata( $tiny_metadata = null ) { if ( 'original' === $size_name ) { $size_name = '0'; } - $retina_path = wr2x_get_retina( + $retina_path = wr2x_get_retina( $this->sizes[ $size_name ]->filename ); $this->sizes[ $size ] = new Tiny_Image_Size( $retina_path ); @@ -177,7 +177,11 @@ public function get_wp_metadata() { } public function file_type_allowed() { - return in_array( $this->get_mime_type(), array( 'image/jpeg', 'image/png', 'image/webp' ) ); + return in_array( + $this->get_mime_type(), + array( 'image/jpeg', 'image/png', 'image/webp' ), + true + ); } public function get_mime_type() { @@ -190,13 +194,13 @@ public function compress() { } $success = 0; - $failed = 0; + $failed = 0; $active_tinify_sizes = $this->settings->get_active_tinify_sizes(); if ( $this->settings->get_conversion_enabled() ) { $uncompressed_sizes = $this->filter_image_sizes( 'uncompressed', $active_tinify_sizes ); - $unconverted_sizes = $this->filter_image_sizes( 'unconverted', $active_tinify_sizes ); + $unconverted_sizes = $this->filter_image_sizes( 'unconverted', $active_tinify_sizes ); $unprocessed_sizes = $uncompressed_sizes + $unconverted_sizes; } else { @@ -210,7 +214,7 @@ public function compress() { if ( ! $size->is_duplicate() ) { $size->add_tiny_meta_start(); $this->update_tiny_post_meta(); - $resize = $this->settings->get_resize_options( $size_name ); + $resize = $this->settings->get_resize_options( $size_name ); $preserve = $this->settings->get_preserve_options( $size_name ); try { $response = $compressor->compress_file( @@ -226,10 +230,10 @@ public function compress() { $convert_to; $size->add_tiny_meta( $response ); - $success++; + ++$success; } catch ( Tiny_Exception $e ) { $size->add_tiny_meta_error( $e ); - $failed++; + ++$failed; } $this->add_wp_metadata( $size_name, $size ); $this->update_tiny_post_meta(); @@ -244,7 +248,7 @@ public function compress() { return array( 'success' => $success, - 'failed' => $failed, + 'failed' => $failed, ); } @@ -300,8 +304,8 @@ public function add_wp_metadata( $size_name, $size ) { if ( isset( $size->meta['output'] ) ) { $output = $size->meta['output']; if ( isset( $output['width'] ) && isset( $output['height'] ) ) { - $this->wp_metadata['width'] = $output['width']; - $this->wp_metadata['height'] = $output['height']; + $this->wp_metadata['width'] = $output['width']; + $this->wp_metadata['height'] = $output['height']; $this->wp_metadata['filesize'] = $output['size']; } } @@ -322,12 +326,12 @@ public function update_tiny_post_meta() { } public function get_image_sizes() { - $original = isset( $this->sizes[ self::ORIGINAL ] ) + $original = isset( $this->sizes[ self::ORIGINAL ] ) ? array( self::ORIGINAL => $this->sizes[ self::ORIGINAL ], ) : array(); - $compressed = array(); + $compressed = array(); $uncompressed = array(); foreach ( $this->sizes as $size_name => $size ) { if ( self::is_original( $size_name ) ) { @@ -385,7 +389,7 @@ public function get_count( $methods, $count_sizes = null ) { foreach ( $methods as $method ) { if ( $this->sizes[ $size ]->$method() ) { - $stats[ $method ]++; + ++$stats[ $method ]; } } } @@ -394,14 +398,20 @@ public function get_count( $methods, $count_sizes = null ) { public function get_latest_error() { $active_tinify_sizes = $this->settings->get_active_tinify_sizes(); - $error_message = null; - $last_timestamp = null; + $error_message = null; + $last_timestamp = null; foreach ( $this->sizes as $size_name => $size ) { if ( in_array( $size_name, $active_tinify_sizes, true ) ) { if ( isset( $size->meta['error'] ) && isset( $size->meta['message'] ) ) { - if ( null === $last_timestamp || $last_timestamp < $size->meta['timestamp'] ) { + if ( + null === $last_timestamp || + $last_timestamp < $size->meta['timestamp'] + ) { $last_timestamp = $size->meta['timestamp']; - $error_message = Tiny_Helpers::truncate_text( $size->meta['message'], 140 ); + $error_message = Tiny_Helpers::truncate_text( + $size->meta['message'], + 140 + ); } } } @@ -411,11 +421,11 @@ public function get_latest_error() { public function get_savings( $stats ) { $before = $stats['initial_total_size']; - $after = $stats['compressed_total_size']; + $after = $stats['compressed_total_size']; if ( 0 === $before ) { $savings = 0; } else { - $savings = ($before - $after) / $before * 100; + $savings = ( $before - $after ) / $before * 100; } return '' . number_format( $savings, 1 ); } @@ -426,12 +436,12 @@ public function get_statistics( $active_sizes, $active_tinify_sizes ) { return $this->statistics; } - $this->statistics['initial_total_size'] = 0; - $this->statistics['compressed_total_size'] = 0; - $this->statistics['image_sizes_compressed'] = 0; + $this->statistics['initial_total_size'] = 0; + $this->statistics['compressed_total_size'] = 0; + $this->statistics['image_sizes_compressed'] = 0; $this->statistics['available_uncompressed_sizes'] = 0; - $this->statistics['image_sizes_converted'] = 0; - $this->statistics['available_unconverted_sizes'] = 0; + $this->statistics['image_sizes_converted'] = 0; + $this->statistics['available_unconverted_sizes'] = 0; foreach ( $this->sizes as $size_name => $size ) { // skip duplicates or inactive sizes @@ -439,11 +449,11 @@ public function get_statistics( $active_sizes, $active_tinify_sizes ) { continue; } - $file_size = $size->filesize(); - $is_active_size = in_array( $size_name, $active_tinify_sizes, true ); + $file_size = $size->filesize(); + $is_active_size = in_array( $size_name, $active_tinify_sizes, true ); if ( isset( $size->meta['input'] ) ) { - $input_size = (int) $size->meta['input']['size']; + $input_size = (int) $size->meta['input']['size']; $this->statistics['initial_total_size'] += $input_size; if ( isset( $size->meta['output'] ) ) { @@ -452,28 +462,28 @@ public function get_statistics( $active_sizes, $active_tinify_sizes ) { if ( $size->modified() ) { $this->statistics['compressed_total_size'] += $file_size; if ( $is_active_size ) { - $this->statistics['available_uncompressed_sizes']++; + ++$this->statistics['available_uncompressed_sizes']; } } else { $this->statistics['compressed_total_size'] += $output_size; - $this->statistics['image_sizes_compressed']++; + ++$this->statistics['image_sizes_compressed']; } } else { $this->statistics['compressed_total_size'] += $input_size; } } elseif ( $size->exists() ) { - $this->statistics['initial_total_size'] += $file_size; + $this->statistics['initial_total_size'] += $file_size; $this->statistics['compressed_total_size'] += $file_size; if ( $is_active_size ) { - $this->statistics['available_uncompressed_sizes']++; + ++$this->statistics['available_uncompressed_sizes']; } } if ( $is_active_size ) { if ( $size->has_been_converted() ) { - $this->statistics['image_sizes_converted']++; + ++$this->statistics['image_sizes_converted']; } else { - $this->statistics['available_unconverted_sizes']++; + ++$this->statistics['available_unconverted_sizes']; } } }// End foreach(). @@ -522,7 +532,6 @@ private function convert_to() { } return $convert_settings['convert_to']; - } /** @@ -544,7 +553,7 @@ public function mark_as_compressed() { if ( $this->settings->get_conversion_enabled() ) { $uncompressed_sizes = $this->filter_image_sizes( 'uncompressed', $active_tinify_sizes ); - $unconverted_sizes = $this->filter_image_sizes( 'unconverted', $active_tinify_sizes ); + $unconverted_sizes = $this->filter_image_sizes( 'unconverted', $active_tinify_sizes ); $unprocessed_sizes = $uncompressed_sizes + $unconverted_sizes; } else { diff --git a/src/class-tiny-notices.php b/src/class-tiny-notices.php index 854d9e3c..fce29796 100644 --- a/src/class-tiny-notices.php +++ b/src/class-tiny-notices.php @@ -23,13 +23,13 @@ class Tiny_Notices extends Tiny_WP_Base { private $dismissals; protected static $incompatible_plugins = array( - 'CheetahO Image Optimizer' => 'cheetaho-image-optimizer/cheetaho.php', - 'EWWW Image Optimizer' => 'ewww-image-optimizer/ewww-image-optimizer.php', - 'Imagify' => 'imagify/imagify.php', - 'Kraken Image Optimizer' => 'kraken-image-optimizer/kraken.php', + 'CheetahO Image Optimizer' => 'cheetaho-image-optimizer/cheetaho.php', + 'EWWW Image Optimizer' => 'ewww-image-optimizer/ewww-image-optimizer.php', + 'Imagify' => 'imagify/imagify.php', + 'Kraken Image Optimizer' => 'kraken-image-optimizer/kraken.php', 'ShortPixel Image Optimizer' => 'shortpixel-image-optimiser/wp-shortpixel.php', - 'WP Smush' => 'wp-smushit/wp-smush.php', - 'WP Smush Pro' => 'wp-smush-pro/wp-smush.php', + 'WP Smush' => 'wp-smushit/wp-smush.php', + 'WP Smush Pro' => 'wp-smush-pro/wp-smush.php', ); private static function get_option_key() { @@ -55,7 +55,7 @@ private function load_notices() { if ( is_array( $this->notices ) ) { return; } - $option = get_option( self::get_option_key() ); + $option = get_option( self::get_option_key() ); $this->notices = is_array( $option ) ? $option : array(); } @@ -139,21 +139,22 @@ public function show( $name, $message, $klass = 'error', $dismissible = true ) { if ( ! $dismissible ) { $add = '

'; } elseif ( self::check_wp_version( 4.2 ) ) { - $add = '

'; + $add = '

'; $css[] = 'is-dismissible'; } else { $add = ' ' . esc_html__( 'Dismiss', 'tiny-compress-images' ) . '

'; } - $css = implode( ' ', $css ); + $css = implode( ' ', $css ); $plugin_name = esc_html__( 'TinyPNG - JPEG, PNG & WebP image compression', 'tiny-compress-images' ); - add_action( 'admin_notices', - function() use ( $css, $name, $plugin_name, $message, $add ) { + add_action( + 'admin_notices', + function () use ( $css, $name, $plugin_name, $message, $add ) { echo '

' . $plugin_name . ': ' . $message . $add . '

'; } @@ -162,35 +163,38 @@ function() use ( $css, $name, $plugin_name, $message, $add ) { public function api_key_missing_notice() { $notice_class = 'error'; - $notice = esc_html__( + $notice = esc_html__( 'Please register or provide an API key to start compressing images.', 'tiny-compress-images' ); - $link = sprintf( - '%s', $notice + $link = sprintf( + '%s', + $notice ); $this->show( 'setting', $link, $notice_class, false ); } public function get_api_key_pending_notice() { $notice_class = 'notice-warning'; - $notice = esc_html__( + $notice = esc_html__( 'Please activate your account to start compressing images.', 'tiny-compress-images' ); - $link = sprintf( - '%s', $notice + $link = sprintf( + '%s', + $notice ); $this->show( 'setting', $link, $notice_class, false ); } public function add_limit_reached_notice( $email ) { $encoded_email = str_replace( '%20', '%2B', rawurlencode( $email ) ); - $url = 'https://tinypng.com/dashboard/api?type=upgrade&mail=' . $encoded_email; - $link = '' . + $url = 'https://tinypng.com/dashboard/api?type=upgrade&mail=' . $encoded_email; + $link = '' . esc_html__( 'TinyPNG API account', 'tiny-compress-images' ) . ''; - $this->add('limit-reached', + $this->add( + 'limit-reached', esc_html__( 'You have reached your free limit this month.', 'tiny-compress-images' @@ -214,7 +218,8 @@ public function outdated_platform_notice() { $curlinfo = curl_version(); $details .= ' ' . sprintf( /* translators: %s: curl version */ - esc_html__( 'with curl %s', 'tiny-compress-images' ), $curlinfo['version'] + esc_html__( 'with curl %s', 'tiny-compress-images' ), + $curlinfo['version'] ); } else { $details .= ' ' . esc_html__( 'without curl', 'tiny-compress-images' ); @@ -228,16 +233,19 @@ public function outdated_platform_notice() { esc_html__( 'You are using an outdated platform (%s).', 'tiny-compress-images' - ), $details + ), + $details ); } elseif ( ! Tiny_PHP::curl_available() ) { $message = esc_html__( - 'We noticed that cURL is not available. For the best experience we recommend to make sure cURL is available.', // WPCS: Needed for proper translation. + // phpcs:ignore Generic.Files.LineLength + 'We noticed that cURL is not available. For the best experience we recommend to make sure cURL is available.', 'tiny-compress-images' ); } elseif ( Tiny_PHP::curl_exec_disabled() ) { $message = esc_html__( - 'We noticed that curl_exec is disabled in your PHP configuration. Please update this setting for the best experience.', // WPCS: Needed for proper translation. + // phpcs:ignore Generic.Files.LineLength + 'We noticed that curl_exec is disabled in your PHP configuration. Please update this setting for the best experience.', 'tiny-compress-images' ); } @@ -253,18 +261,19 @@ public function incompatible_plugins_notice() { } private function show_incompatible_plugins( $incompatible_plugins ) { - $notice = '
'; - $notice .= '

'; - $notice .= esc_html__( + $notice = '
'; + $notice .= '

'; + $notice .= esc_html__( 'TinyPNG - JPEG, PNG & WebP image compression', 'tiny-compress-images' ); - $notice .= '

'; - $notice .= '

'; - $notice .= esc_html__( - 'You have activated multiple image optimization plugins. This may lead to unexpected results. The following plugins were detected:', // WPCS: Needed for proper translation. - 'tiny-compress-images' - ); + $notice .= '

'; + $notice .= '

'; + $notice .= esc_html__( + // phpcs:ignore Generic.Files.LineLength + 'You have activated multiple image optimization plugins. This may lead to unexpected results. The following plugins were detected:', + 'tiny-compress-images' + ); $notice .= '

'; $notice .= ''; $notice .= ''; foreach ( $incompatible_plugins as $name => $file ) { - $notice .= ''; + $url = admin_url( 'plugins.php?' . $query_string ); + $notice .= ''; + $notice .= esc_html__( 'Deactivate', 'tiny-compress-images' ); + $notice .= ''; } $notice .= '
•'; @@ -274,21 +283,22 @@ private function show_incompatible_plugins( $incompatible_plugins ) { ); $notice .= '
•'; - $notice .= $name; - $notice .= ''; - $nonce = wp_create_nonce( 'deactivate-plugin_' . $file ); + $notice .= '
•'; + $notice .= $name; + $notice .= ''; + $nonce = wp_create_nonce( 'deactivate-plugin_' . $file ); $query_string = 'action=deactivate&plugin=' . $file . '&_wpnonce=' . $nonce; - $url = admin_url( 'plugins.php?' . $query_string ); - $notice .= ''; - $notice .= esc_html__( 'Deactivate', 'tiny-compress-images' ); - $notice .= '
'; $notice .= '
'; - add_action( 'admin_notices', - function() use ( $notice ) { + add_action( + 'admin_notices', + function () use ( $notice ) { echo $notice; } ); diff --git a/src/class-tiny-php.php b/src/class-tiny-php.php index 2348f3c1..91071da0 100644 --- a/src/class-tiny-php.php +++ b/src/class-tiny-php.php @@ -33,11 +33,11 @@ public static function fopen_available() { public static function curl_exec_disabled() { $disabled_functions = explode( ',', ini_get( 'disable_functions' ) ); - return in_array( 'curl_exec', $disabled_functions ); + return in_array( 'curl_exec', $disabled_functions, true ); } public static function client_supported() { - return Tiny_PHP::has_fully_supported_php() && + return Tiny_PHP::has_fully_supported_php() && Tiny_PHP::curl_available() && ! Tiny_PHP::curl_exec_disabled(); } diff --git a/src/class-tiny-picture.php b/src/class-tiny-picture.php index 35440964..a8d54cda 100644 --- a/src/class-tiny-picture.php +++ b/src/class-tiny-picture.php @@ -19,6 +19,10 @@ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +require_once __DIR__ . '/class-tiny-source-base.php'; +require_once __DIR__ . '/class-tiny-source-image.php'; +require_once __DIR__ . '/class-tiny-source-picture.php'; + /** * Class responsible for parsing and modifying html to insert picture elements. * @@ -29,8 +33,6 @@ */ class Tiny_Picture extends Tiny_WP_Base { - - /** @var string */ private $base_dir; @@ -43,7 +45,7 @@ class Tiny_Picture extends Tiny_WP_Base { * @param string $base_dir Absolute path (e.g. ABSPATH) * @param array $domains List of allowed domain URLs */ - function __construct( $base_dir = ABSPATH, $domains = array() ) { + public function __construct( $base_dir = ABSPATH, $domains = array() ) { $this->base_dir = $base_dir; $this->allowed_domains = $domains; @@ -59,9 +61,12 @@ function __construct( $base_dir = ABSPATH, $domains = array() ) { return; } - add_action('template_redirect', function () { - ob_start( array( $this, 'replace_sources' ), 1000 ); - }); + add_action( + 'template_redirect', + function () { + ob_start( array( $this, 'replace_sources' ), 1000 ); + } + ); } public function replace_sources( $content ) { @@ -97,7 +102,7 @@ private function replace_img_sources( $content ) { * Will search for all picture elements within the given source html * * @param string $content - * @return array an array of picture element sources + * @return array an array of picture element sources */ private function filter_pictures( $content ) { $matches = array(); @@ -111,7 +116,7 @@ private function filter_pictures( $content ) { $pictures = array(); foreach ( $matches[0] as $raw_picture ) { - $pictures[] = new Tiny_Picture_Source( + $pictures[] = new Tiny_Source_Picture( $raw_picture, $this->base_dir, $this->allowed_domains @@ -125,7 +130,7 @@ private function filter_pictures( $content ) { * Will add additional sourcesets to picture elements. * * @param string $content the full page content - * @param Tiny_Picture_Source $source the picture element + * @param Tiny_Source_Picture $source the picture element * * @return string the updated content including augmented picture elements */ @@ -139,7 +144,7 @@ private function replace_picture( $content, $source ) { * Will replace img elements with picture elements that (possibly) have additional formats. * * @param string $content the full page content - * @param Tiny_Image_Source $source the picture element + * @param Tiny_Source_Image $source the picture element * * @return string the updated content including augmented picture elements */ @@ -172,10 +177,9 @@ private function filter_images( $content ) { if ( ! preg_match_all( '/]*>/is', $content, $matches ) ) { return array(); } - $images = array(); foreach ( $matches[0] as $img ) { - $images[] = new Tiny_Image_Source( + $images[] = new Tiny_Source_Image( $img, $this->base_dir, $this->allowed_domains @@ -185,353 +189,3 @@ private function filter_images( $content ) { return $images; } } - -abstract class Tiny_Source_Base { - - - public $raw_html; - protected $base_dir; - protected $allowed_domains; - protected $valid_mimetypes; - - public function __construct( $html, $base_dir, $domains ) { - $this->raw_html = $html; - $this->base_dir = $base_dir; - $this->allowed_domains = $domains; - $this->valid_mimetypes = array( 'image/avif', 'image/webp' ); - } - - protected static function get_attribute_value( $element, $name ) { - // Match the exact attribute name (not part of data-media, mediaType, etc.) - // and capture a single- or double-quoted value. - $delim = '~'; - $attr = preg_quote( $name, $delim ); - $regex = $delim . '(?, ,
) - if ( preg_match_all( - '~<' . preg_quote( $tagname, '~' ) . '\b(?:[^>"\']+|"[^"]*"|\'[^\']*\')*/?>~i', - $html, - $matches - ) ) { - $results = array_merge( $results, $matches[0] ); - } - - // Normal paired tags (e.g.
…
) - $regex_tag = preg_quote( $tagname, '~' ); - if ( preg_match_all( - '~<' . $regex_tag . - '\b(?:[^>"\']+|"[^"]*"|\'[^\']*\')*>.*?~is', - $html, - $matches - ) ) { - $results = array_merge( $results, $matches[0] ); - } - - return $results; - } - - protected function get_local_path( $url ) { - if ( strpos( $url, 'http' ) === 0 ) { - $matched_domain = null; - - foreach ( $this->allowed_domains as $domain ) { - if ( strpos( $url, $domain ) === 0 ) { - $matched_domain = $domain; - break; - } - } - - if ( null === $matched_domain ) { - return ''; - } - - $url = substr( $url, strlen( $matched_domain ) ); - } - $url = $this->base_dir . $url; - - return $url; - } - - protected function get_formatted_source( $image_source_data, $mimetype ) { - $format_url = Tiny_Helpers::replace_file_extension( $mimetype, $image_source_data['path'] ); - $local_path = $this->get_local_path( $format_url ); - if ( empty( $local_path ) ) { - return null; - } - - $exists_local = file_exists( $local_path ); - if ( $exists_local ) { - return array( - 'src' => $format_url, - 'size' => $image_source_data['size'], - 'type' => $mimetype, - ); - } - return null; - } - - /** - * Retrieves the sources from the or element - * - * @return array{path: string, size: string}[] The image sources - */ - protected function get_image_srcsets( $html ) { - $result = array(); - $srcset = $this::get_attribute_value( $html, 'srcset' ); - - if ( $srcset ) { - // Split the srcset to get individual entries - $srcset_entries = explode( ',', $srcset ); - - foreach ( $srcset_entries as $entry ) { - // Trim whitespace - $entry = trim( $entry ); - - // Split by whitespace to separate path and size/density descriptor - $parts = preg_split( '/\s+/', $entry, 2 ); - - if ( count( $parts ) === 2 ) { - // We have both path and size - $result[] = array( - 'path' => $parts[0], - 'size' => $parts[1], - ); - } elseif ( count( $parts ) === 1 ) { - // We only have a path, will be interpreted as pixel - // density 1x (unusual in srcset) - $result[] = array( - 'path' => $parts[0], - 'size' => '', - ); - } - } - } - return $result; - } - - /** - * Retrieves the sources from the or element - * - * @return array{path: string, size: string}[] The image sources - */ - private function get_image_src( $html ) { - $source = $this::get_attribute_value( $html, 'src' ); - if ( ! empty( $source ) ) { - // No srcset, but we have a src attribute - return array( - 'path' => $source, - 'size' => '', - ); - } - return array(); - } - - - /** - * Creates one or more elements if alternative formats - * are available. - * - * @param string $original_source_html, either or - * @return array{string} array of html - */ - protected function create_alternative_sources( $original_source_html ) { - $srcsets = $this->get_image_srcsets( $original_source_html ); - if ( empty( $srcsets ) ) { - // no srcset, try src attribute - $srcsets[] = $this->get_image_src( $original_source_html ); - } - - if ( empty( $srcsets ) ) { - return array(); - } - - $is_source_tag = (bool) preg_match( '#get_largest_width_descriptor( $srcsets ); - - foreach ( $this->valid_mimetypes as $mimetype ) { - $srcset_parts = array(); - - foreach ( $srcsets as $srcset ) { - $alt_source = $this->get_formatted_source( $srcset, $mimetype ); - if ( $alt_source ) { - $srcset_parts[] = trim( $alt_source['src'] . ' ' . $alt_source['size'] ); - } - } - - if ( $width_descriptor && - ! self::srcset_contains_width_descriptor( - $srcset_parts, - $width_descriptor - ) ) { - continue; - } - - if ( empty( $srcset_parts ) ) { - continue; - } - - $source_attr_parts = array(); - - $srcset_attr = implode( ', ', $srcset_parts ); - $source_attr_parts['srcset'] = $srcset_attr; - - if ( $is_source_tag ) { - foreach ( array( 'sizes', 'media', 'width', 'height' ) as $attr ) { - $attr_value = $this->get_attribute_value( $original_source_html, $attr ); - if ( $attr_value ) { - $source_attr_parts[ $attr ] = $attr_value; - } - } - } - - $source_attr_parts['type'] = $mimetype; - $source_parts = array( ' $source_attr_val ) { - $source_parts[] = $source_attr_name . '="' . $source_attr_val . '"'; - } - $source_parts[] = '/>'; - $sources[] = implode( ' ', $source_parts ); - }// End foreach(). - - return $sources; - } - - /** - * Returns the largest numeric width descriptor - * (e.g. 2000 from "2000w") found in the srcset data. - * - * @param array $srcsets - * @return int - */ - public static function get_largest_width_descriptor( $srcsets ) { - $largest = 0; - - foreach ( $srcsets as $srcset ) { - if ( empty( $srcset['size'] ) ) { - continue; - } - - if ( preg_match( '/(\d+)w/', $srcset['size'], $matches ) ) { - $width = (int) $matches[1]; - if ( $width > $largest ) { - $largest = $width; - } - } - } - - return $largest; - } - - /** - * Determines whether a srcset list contains the provided width descriptor. - * - * @param string[] $srcset_parts - * @param int $width_descriptor - * @return bool true if width is in srcset - */ - public static function srcset_contains_width_descriptor( $srcset_parts, $width_descriptor ) { - if ( empty( $srcset_parts ) || $width_descriptor <= 0 ) { - return false; - } - - $suffix = ' ' . $width_descriptor . 'w'; - $suffix_length = strlen( $suffix ); - - foreach ( $srcset_parts as $srcset_part ) { - if ( substr( $srcset_part, -$suffix_length ) === $suffix ) { - return true; - } - } - - return false; - } -} - -class Tiny_Picture_Source extends Tiny_Source_Base { - - - - /** - * Adds alternative format sources (e.g., image/webp, image/avif) to an existing - * element based on locally available converted files. - * - * @return string The augmented HTML or the original if no additions. - */ - public function augment_picture_element() { - $modified_sources = array(); - - foreach ( $this->get_element_by_tag( $this->raw_html, 'source' ) as $source_tag_html ) { - $type_attr = self::get_attribute_value( $source_tag_html, 'type' ); - $type_attr = null !== $type_attr ? strtolower( trim( $type_attr ) ) : ''; - - // Skip if already optimized. - if ( '' !== $type_attr && in_array( $type_attr, $this->valid_mimetypes, true ) ) { - continue; - } - - $alternative_sources = $this->create_alternative_sources( $source_tag_html ); - if ( is_array( $alternative_sources ) && $alternative_sources ) { - foreach ( $alternative_sources as $alt ) { - $modified_sources[] = $alt; // no array_merge in the loop - } - } - } - - // handle inner image - foreach ( $this->get_element_by_tag( $this->raw_html, 'img' ) as $img_tag_html ) { - $alt_image_source = $this->create_alternative_sources( $img_tag_html ); - $modified_sources = array_merge( $modified_sources, $alt_image_source ); - } - - $modified_source = implode( '', $modified_sources ); - - // Insert newly built elements immediately before the first - return preg_replace( '#(raw_html, 1 ); - } -} - -class Tiny_Image_Source extends Tiny_Source_Base { - - /** - * Generates a formatted image source array if the corresponding local file exists. - * - * Attempts to replace the file extension of the provided image path with the - * specified MIME type, resolves the local path of the resulting file, and returns - * the `srcset` and `type` if the file exists. - * - * @return string a element contain additional sources - */ - public function create_picture_elements() { - $sources = $this->create_alternative_sources( $this->raw_html ); - if ( empty( $sources ) ) { - return $this->raw_html; - } - $picture_element = array( '' ); - $picture_element[] = implode( '', $sources ); - $picture_element[] = $this->raw_html; - $picture_element[] = ''; - - return implode( '', $picture_element ); - } -} diff --git a/src/class-tiny-plugin.php b/src/class-tiny-plugin.php index 7895b276..0c624007 100644 --- a/src/class-tiny-plugin.php +++ b/src/class-tiny-plugin.php @@ -18,8 +18,8 @@ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ class Tiny_Plugin extends Tiny_WP_Base { - const VERSION = '3.6.4'; - const MEDIA_COLUMN = self::NAME; + const VERSION = '3.6.4'; + const MEDIA_COLUMN = self::NAME; const DATETIME_FORMAT = 'Y-m-d G:i:s'; private static $version; @@ -33,7 +33,7 @@ public static function jpeg_quality() { public static function version() { /* Avoid using get_plugin_data() because it is not loaded early enough - in xmlrpc.php. */ + in xmlrpc.php. */ return self::VERSION; } @@ -47,22 +47,28 @@ public function set_compressor( $compressor ) { } public function init() { - add_filter( 'jpeg_quality', + add_filter( + 'jpeg_quality', $this->get_static_method( 'jpeg_quality' ) ); - add_filter( 'wp_editor_set_quality', + add_filter( + 'wp_editor_set_quality', $this->get_static_method( 'jpeg_quality' ) ); - add_filter( 'wp_generate_attachment_metadata', + add_filter( + 'wp_generate_attachment_metadata', $this->get_method( 'process_attachment' ), - 10, 2 + 10, + 2 ); add_action( 'delete_attachment', $this->get_method( 'clean_attachment' ), 10, 2 ); - load_plugin_textdomain( self::NAME, false, + load_plugin_textdomain( + self::NAME, + false, dirname( plugin_basename( __FILE__ ) ) . '/languages' ); @@ -85,93 +91,116 @@ public function cli_init() { } public function ajax_init() { - add_filter( 'wp_ajax_tiny_async_optimize_upload_new_media', + add_filter( + 'wp_ajax_tiny_async_optimize_upload_new_media', $this->get_method( 'compress_on_upload' ) ); - add_action( 'wp_ajax_tiny_compress_image_from_library', + add_action( + 'wp_ajax_tiny_compress_image_from_library', $this->get_method( 'compress_image_from_library' ) ); - add_action( 'wp_ajax_tiny_compress_image_for_bulk', + add_action( + 'wp_ajax_tiny_compress_image_for_bulk', $this->get_method( 'compress_image_for_bulk' ) ); - add_action( 'wp_ajax_tiny_get_optimization_statistics', + add_action( + 'wp_ajax_tiny_get_optimization_statistics', $this->get_method( 'ajax_optimization_statistics' ) ); - add_action( 'wp_ajax_tiny_get_compression_status', + add_action( + 'wp_ajax_tiny_get_compression_status', $this->get_method( 'ajax_compression_status' ) ); - add_action( 'wp_ajax_tiny_mark_image_as_compressed', + add_action( + 'wp_ajax_tiny_mark_image_as_compressed', $this->get_method( 'mark_image_as_compressed' ) ); /* When touching any functionality linked to image compressions when - uploading images make sure it also works with XML-RPC. See README. */ - add_filter( 'wp_ajax_nopriv_tiny_rpc', + uploading images make sure it also works with XML-RPC. See README. */ + add_filter( + 'wp_ajax_nopriv_tiny_rpc', $this->get_method( 'process_rpc_request' ) ); if ( $this->settings->compress_wr2x_images() ) { - add_action( 'wr2x_upload_retina', + add_action( + 'wr2x_upload_retina', $this->get_method( 'compress_original_retina_image' ), - 10, 2 + 10, + 2 ); - add_action( 'wr2x_retina_file_added', + add_action( + 'wr2x_retina_file_added', $this->get_method( 'compress_retina_image' ), - 10, 3 + 10, + 3 ); - add_action( 'wr2x_retina_file_removed', + add_action( + 'wr2x_retina_file_removed', $this->get_method( 'remove_retina_image' ), - 10, 2 + 10, + 2 ); } } public function admin_init() { - add_action('wp_dashboard_setup', + add_action( + 'wp_dashboard_setup', $this->get_method( 'add_dashboard_widget' ) ); - add_action( 'admin_enqueue_scripts', + add_action( + 'admin_enqueue_scripts', $this->get_method( 'enqueue_scripts' ) ); - add_action( 'admin_action_tiny_bulk_action', + add_action( + 'admin_action_tiny_bulk_action', $this->get_method( 'media_library_bulk_action' ) ); - add_action( 'admin_action_-1', + add_action( + 'admin_action_-1', $this->get_method( 'media_library_bulk_action' ) ); - add_action( 'admin_action_tiny_bulk_mark_compressed', + add_action( + 'admin_action_tiny_bulk_mark_compressed', $this->get_method( 'media_library_bulk_action' ) ); - add_filter( 'manage_media_columns', + add_filter( + 'manage_media_columns', $this->get_method( 'add_media_columns' ) ); - add_action( 'manage_media_custom_column', + add_action( + 'manage_media_custom_column', $this->get_method( 'render_media_column' ), - 10, 2 + 10, + 2 ); - add_action( 'attachment_submitbox_misc_actions', + add_action( + 'attachment_submitbox_misc_actions', $this->get_method( 'show_media_info' ) ); $plugin = plugin_basename( - dirname( dirname( __FILE__ ) ) . '/tiny-compress-images.php' + dirname( __DIR__ ) . '/tiny-compress-images.php' ); - add_filter( "plugin_action_links_$plugin", + add_filter( + "plugin_action_links_$plugin", $this->get_method( 'add_plugin_links' ) ); @@ -196,7 +225,7 @@ public function add_plugin_links( $current_links ) { '%s', esc_html__( 'Settings', 'tiny-compress-images' ) ), - 'bulk' => sprintf( + 'bulk' => sprintf( '%s', esc_html__( 'Bulk TinyPNG', 'tiny-compress-images' ) ), @@ -230,48 +259,77 @@ public function remove_retina_image( $attachment_id, $path ) { } public function enqueue_scripts( $hook ) { - wp_enqueue_style( self::NAME . '_admin', + wp_enqueue_style( + self::NAME . '_admin', plugins_url( '/css/admin.css', __FILE__ ), - array(), self::version() + array(), + self::version() ); - wp_enqueue_style( self::NAME . '_chart', + wp_enqueue_style( + self::NAME . '_chart', plugins_url( '/css/optimization-chart.css', __FILE__ ), - array(), self::version() + array(), + self::version() ); - wp_register_script( self::NAME . '_admin', + wp_register_script( + self::NAME . '_admin', plugins_url( '/js/admin.js', __FILE__ ), - array(), self::version(), true + array(), + self::version(), + true ); // WordPress < 3.3 does not handle multidimensional arrays - wp_localize_script( self::NAME . '_admin', 'tinyCompress', array( - 'nonce' => wp_create_nonce( 'tiny-compress' ), - 'wpVersion' => self::wp_version(), - 'pluginVersion' => self::version(), - 'L10nAllDone' => __( 'All images are processed', 'tiny-compress-images' ), - 'L10nNoActionTaken' => __( 'No action taken', 'tiny-compress-images' ), - 'L10nDuplicate' => __( 'Image was already processed', 'tiny-compress-images' ), - 'L10nBulkAction' => __( 'Compress Images', 'tiny-compress-images' ), - 'L10nBulkMarkCompressed' => __( 'Mark as Compressed', 'tiny-compress-images' ), - 'L10nCancelled' => __( 'Cancelled', 'tiny-compress-images' ), - 'L10nCompressing' => __( 'Compressing', 'tiny-compress-images' ), - 'L10nCompressed' => __( 'compressed', 'tiny-compress-images' ), - 'L10nConverted' => __( 'converted', 'tiny-compress-images' ), - 'L10nFile' => __( 'File', 'tiny-compress-images' ), - 'L10nSizesOptimized' => __( 'Sizes optimized', 'tiny-compress-images' ), - 'L10nInitialSize' => __( 'Initial size', 'tiny-compress-images' ), - 'L10nCurrentSize' => __( 'Current size', 'tiny-compress-images' ), - 'L10nSavings' => __( 'Savings', 'tiny-compress-images' ), - 'L10nStatus' => __( 'Status', 'tiny-compress-images' ), - 'L10nShowMoreDetails' => __( 'Show more details', 'tiny-compress-images' ), - 'L10nError' => __( 'Error', 'tiny-compress-images' ), - 'L10nLatestError' => __( 'Latest error', 'tiny-compress-images' ), - 'L10nInternalError' => __( 'Internal error', 'tiny-compress-images' ), - 'L10nOutOf' => __( 'out of', 'tiny-compress-images' ), - 'L10nWaiting' => __( 'Waiting', 'tiny-compress-images' ), - )); + wp_localize_script( + self::NAME . '_admin', + 'tinyCompress', + array( + 'nonce' => wp_create_nonce( 'tiny-compress' ), + 'wpVersion' => self::wp_version(), + 'pluginVersion' => self::version(), + 'L10nAllDone' => __( + 'All images are processed', + 'tiny-compress-images' + ), + 'L10nNoActionTaken' => __( + 'No action taken', + 'tiny-compress-images' + ), + 'L10nDuplicate' => __( + 'Image was already processed', + 'tiny-compress-images' + ), + 'L10nBulkAction' => __( 'Compress Images', 'tiny-compress-images' ), + 'L10nBulkMarkCompressed' => __( + 'Mark as Compressed', + 'tiny-compress-images' + ), + 'L10nCancelled' => __( 'Cancelled', 'tiny-compress-images' ), + 'L10nCompressing' => __( 'Compressing', 'tiny-compress-images' ), + 'L10nCompressed' => __( 'compressed', 'tiny-compress-images' ), + 'L10nConverted' => __( 'converted', 'tiny-compress-images' ), + 'L10nFile' => __( 'File', 'tiny-compress-images' ), + 'L10nSizesOptimized' => __( + 'Sizes optimized', + 'tiny-compress-images' + ), + 'L10nInitialSize' => __( 'Initial size', 'tiny-compress-images' ), + 'L10nCurrentSize' => __( 'Current size', 'tiny-compress-images' ), + 'L10nSavings' => __( 'Savings', 'tiny-compress-images' ), + 'L10nStatus' => __( 'Status', 'tiny-compress-images' ), + 'L10nShowMoreDetails' => __( + 'Show more details', + 'tiny-compress-images' + ), + 'L10nError' => __( 'Error', 'tiny-compress-images' ), + 'L10nLatestError' => __( 'Latest error', 'tiny-compress-images' ), + 'L10nInternalError' => __( 'Internal error', 'tiny-compress-images' ), + 'L10nOutOf' => __( 'out of', 'tiny-compress-images' ), + 'L10nWaiting' => __( 'Waiting', 'tiny-compress-images' ), + ) + ); wp_enqueue_script( self::NAME . '_admin' ); @@ -279,18 +337,23 @@ public function enqueue_scripts( $hook ) { wp_enqueue_style( self::NAME . '_tiny_bulk_optimization', plugins_url( '/css/bulk-optimization.css', __FILE__ ), - array(), self::version() + array(), + self::version() ); - wp_enqueue_style( self::NAME . '_chart', + wp_enqueue_style( + self::NAME . '_chart', plugins_url( '/css/optimization-chart.css', __FILE__ ), - array(), self::version() + array(), + self::version() ); wp_register_script( self::NAME . '_tiny_bulk_optimization', plugins_url( '/js/bulk-optimization.js', __FILE__ ), - array(), self::version(), true + array(), + self::version(), + true ); wp_enqueue_script( self::NAME . '_tiny_bulk_optimization' ); @@ -314,7 +377,7 @@ public function process_attachment( $metadata, $attachment_id ) { public function blocking_compress_on_upload( $metadata, $attachment_id ) { if ( ! empty( $metadata ) ) { $tiny_image = new Tiny_Image( $this->settings, $attachment_id, $metadata ); - $result = $tiny_image->compress(); + $result = $tiny_image->compress(); return $tiny_image->get_wp_metadata(); } else { return $metadata; @@ -325,7 +388,7 @@ public function async_compress_on_upload( $metadata, $attachment_id ) { $context = 'wp'; $action = 'tiny_async_optimize_upload_new_media'; $_ajax_nonce = wp_create_nonce( 'new_media-' . $attachment_id ); - $body = compact( 'action', '_ajax_nonce', 'metadata', 'attachment_id', 'context' ); + $body = compact( 'action', '_ajax_nonce', 'metadata', 'attachment_id', 'context' ); $args = array( 'timeout' => 0.01, @@ -341,9 +404,9 @@ public function async_compress_on_upload( $metadata, $attachment_id ) { $args['body']['tiny_rpc_action'] = $args['body']['action']; /* We set a different action to make sure that all RPC requests are first validated. */ - $args['body']['action'] = 'tiny_rpc'; - $args['body']['tiny_rpc_hash'] = $rpc_hash; - $args['body']['tiny_rpc_nonce'] = wp_create_nonce( 'tiny_rpc_' . $rpc_hash ); + $args['body']['action'] = 'tiny_rpc'; + $args['body']['tiny_rpc_hash'] = $rpc_hash; + $args['body']['tiny_rpc_nonce'] = wp_create_nonce( 'tiny_rpc_' . $rpc_hash ); /* We can't use cookies here, so we save the user id in a transient @@ -371,8 +434,8 @@ public function process_rpc_request() { } $rpc_hash = sanitize_key( $_POST['tiny_rpc_hash'] ); - $user_id = absint( get_transient( 'tiny_rpc_' . $rpc_hash ) ); - $user = $user_id ? get_userdata( $user_id ) : false; + $user_id = absint( get_transient( 'tiny_rpc_' . $rpc_hash ) ); + $user = $user_id ? get_userdata( $user_id ) : false; /* We no longer need the transient. */ delete_transient( 'tiny_rpc_' . $rpc_hash ); @@ -403,10 +466,10 @@ public function compress_on_upload() { } if ( current_user_can( 'upload_files' ) ) { $attachment_id = intval( $_POST['attachment_id'] ); - $metadata = $_POST['metadata']; + $metadata = $_POST['metadata']; if ( is_array( $metadata ) ) { $tiny_image = new Tiny_Image( $this->settings, $attachment_id, $metadata ); - $result = $tiny_image->compress(); + $result = $tiny_image->compress(); // The wp_update_attachment_metadata call is thrown because the // dimensions of the original image can change. This will then // trigger other plugins and can result in unexpected behaviour and @@ -425,7 +488,7 @@ public function compress_on_upload() { * @since 3.0.0 * * @return array Either error array ['error' => 'message'] - * or success array ['data' => [$id, $metadata]] + * or success array ['data' => [$id, $metadata]] */ private function validate_ajax_attachment_request() { if ( ! $this->check_ajax_referer() ) { @@ -447,7 +510,7 @@ private function validate_ajax_attachment_request() { ), ); } - $id = intval( $_POST['id'] ); + $id = intval( $_POST['id'] ); $metadata = wp_get_attachment_metadata( $id ); if ( ! is_array( $metadata ) ) { return array( @@ -471,8 +534,8 @@ public function compress_image_from_library() { } list($id, $metadata) = $response['data']; - $tiny_image = new Tiny_Image( $this->settings, $id, $metadata ); - $result = $tiny_image->compress(); + $tiny_image = new Tiny_Image( $this->settings, $id, $metadata ); + $result = $tiny_image->compress(); // The wp_update_attachment_metadata call is thrown because the // dimensions of the original image can change. This will then @@ -494,16 +557,16 @@ public function compress_image_for_bulk() { exit(); } - list($id, $metadata) = $response['data']; - $tiny_image_before = new Tiny_Image( $this->settings, $id, $metadata ); + list($id, $metadata) = $response['data']; + $tiny_image_before = new Tiny_Image( $this->settings, $id, $metadata ); $image_statistics_before = $tiny_image_before->get_statistics( $this->settings->get_sizes(), $this->settings->get_active_tinify_sizes() ); - $size_before = $image_statistics_before['compressed_total_size']; + $size_before = $image_statistics_before['compressed_total_size']; - $tiny_image = new Tiny_Image( $this->settings, $id, $metadata ); - $result = $tiny_image->compress(); + $tiny_image = new Tiny_Image( $this->settings, $id, $metadata ); + $result = $tiny_image->compress(); $image_statistics = $tiny_image->get_statistics( $this->settings->get_sizes(), $this->settings->get_active_tinify_sizes() @@ -511,31 +574,36 @@ public function compress_image_for_bulk() { wp_update_attachment_metadata( $id, $tiny_image->get_wp_metadata() ); $current_library_size = intval( $_POST['current_size'] ); - $size_after = $image_statistics['compressed_total_size']; - $new_library_size = $current_library_size + $size_after - $size_before; + $size_after = $image_statistics['compressed_total_size']; + $new_library_size = $current_library_size + $size_after - $size_before; - $result['message'] = $tiny_image->get_latest_error(); + $result['message'] = $tiny_image->get_latest_error(); $result['image_sizes_compressed'] = $image_statistics['image_sizes_compressed']; - $result['image_sizes_converted'] = $image_statistics['image_sizes_converted']; - $result['image_sizes_optimized'] = $image_statistics['image_sizes_compressed']; + $result['image_sizes_converted'] = $image_statistics['image_sizes_converted']; + $result['image_sizes_optimized'] = $image_statistics['image_sizes_compressed']; $result['initial_total_size'] = size_format( - $image_statistics['initial_total_size'], 1 + $image_statistics['initial_total_size'], + 1 ); $result['optimized_total_size'] = size_format( - $image_statistics['compressed_total_size'], 1 + $image_statistics['compressed_total_size'], + 1 ); - $result['savings'] = $tiny_image->get_savings( $image_statistics ); - $result['status'] = $this->settings->get_status(); - $result['thumbnail'] = wp_get_attachment_image( - $id, array( '30', '30' ), true, array( + $result['savings'] = $tiny_image->get_savings( $image_statistics ); + $result['status'] = $this->settings->get_status(); + $result['thumbnail'] = wp_get_attachment_image( + $id, + array( '30', '30' ), + true, + array( 'class' => 'pinkynail', - 'alt' => '', + 'alt' => '', ) ); - $result['size_change'] = $size_after - $size_before; + $result['size_change'] = $size_after - $size_before; $result['human_readable_library_size'] = size_format( $new_library_size, 2 ); echo json_encode( $result ); @@ -569,8 +637,8 @@ public function ajax_compression_status() { public function media_library_bulk_action() { $valid_actions = array( 'tiny_bulk_action', 'tiny_bulk_mark_compressed' ); - $action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : ''; - $action2 = isset( $_REQUEST['action2'] ) ? $_REQUEST['action2'] : ''; + $action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : ''; + $action2 = isset( $_REQUEST['action2'] ) ? $_REQUEST['action2'] : ''; if ( ! in_array( $action, $valid_actions, true ) && @@ -583,7 +651,7 @@ public function media_library_bulk_action() { return; } check_admin_referer( 'bulk-media' ); - $ids = implode( '-', array_map( 'intval', $_REQUEST['media'] ) ); + $ids = implode( '-', array_map( 'intval', $_REQUEST['media'] ) ); $location = 'upload.php?mode=list&ids=' . $ids; $location = add_query_arg( 'action', $_REQUEST['action'], $location ); @@ -636,9 +704,9 @@ public function show_media_info() { private function render_compress_details( $tiny_image ) { $in_progress = $tiny_image->filter_image_sizes( 'in_progress' ); if ( count( $in_progress ) > 0 ) { - include( dirname( __FILE__ ) . '/views/compress-details-processing.php' ); + include __DIR__ . '/views/compress-details-processing.php'; } else { - include( dirname( __FILE__ ) . '/views/compress-details.php' ); + include __DIR__ . '/views/compress-details.php'; } } @@ -653,41 +721,52 @@ public function render_bulk_optimization_page() { $stats = Tiny_Bulk_Optimization::get_optimization_statistics( $this->settings ); $estimated_costs = $this->get_estimated_bulk_cost( $stats['estimated_credit_use'] ); - $admin_colors = self::retrieve_admin_colors(); + $admin_colors = self::retrieve_admin_colors(); /* This makes sure that up to date information is retrieved from the API. */ $this->settings->get_compressor()->get_status(); $active_tinify_sizes = $this->settings->get_active_tinify_sizes(); - $remaining_credits = $this->settings->get_remaining_credits(); - $is_on_free_plan = $this->settings->is_on_free_plan(); - $email_address = $this->settings->get_email_address(); + $remaining_credits = $this->settings->get_remaining_credits(); + $is_on_free_plan = $this->settings->is_on_free_plan(); + $email_address = $this->settings->get_email_address(); - include( dirname( __FILE__ ) . '/views/bulk-optimization.php' ); + include __DIR__ . '/views/bulk-optimization.php'; } public function add_dashboard_widget() { - wp_enqueue_style( self::NAME . '_chart', + wp_enqueue_style( + self::NAME . '_chart', plugins_url( '/css/optimization-chart.css', __FILE__ ), - array(), self::version() + array(), + self::version() ); - wp_enqueue_style( self::NAME . '_dashboard_widget', + wp_enqueue_style( + self::NAME . '_dashboard_widget', plugins_url( '/css/dashboard-widget.css', __FILE__ ), - array(), self::version() + array(), + self::version() ); - wp_register_script( self::NAME . '_dashboard_widget', + wp_register_script( + self::NAME . '_dashboard_widget', plugins_url( '/js/dashboard-widget.js', __FILE__ ), - array(), self::version(), true + array(), + self::version(), + true ); /* This might be deduplicated with the admin script localization, but - the order of including scripts is sometimes different. So in that - case we need to make sure that the order of inclusion is correc.t */ - wp_localize_script( self::NAME . '_dashboard_widget', 'tinyCompressDashboard', array( - 'nonce' => wp_create_nonce( 'tiny-compress' ), - )); + the order of including scripts is sometimes different. So in that + case we need to make sure that the order of inclusion is correc.t */ + wp_localize_script( + self::NAME . '_dashboard_widget', + 'tinyCompressDashboard', + array( + 'nonce' => wp_create_nonce( 'tiny-compress' ), + ) + ); wp_enqueue_script( self::NAME . '_dashboard_widget' ); @@ -698,15 +777,15 @@ public function add_dashboard_widget() { ); } - function add_widget_view() { + public function add_widget_view() { $admin_colors = self::retrieve_admin_colors(); - include( dirname( __FILE__ ) . '/views/dashboard-widget.php' ); + include __DIR__ . '/views/dashboard-widget.php'; } private static function retrieve_admin_colors() { global $_wp_admin_css_colors; $admin_colour_scheme = get_user_option( 'admin_color', get_current_user_id() ); - $admin_colors = array( '#0074aa', '#1685b5', '#78ca44', '#0086ba' ); // default + $admin_colors = array( '#0074aa', '#1685b5', '#78ca44', '#0086ba' ); // default if ( isset( $_wp_admin_css_colors[ $admin_colour_scheme ] ) ) { if ( isset( $_wp_admin_css_colors[ $admin_colour_scheme ]->colors ) ) { $admin_colors = $_wp_admin_css_colors[ $admin_colour_scheme ]->colors; @@ -730,7 +809,7 @@ private static function retrieve_admin_colors() { return $admin_colors; } - function friendly_user_name() { + public function friendly_user_name() { $user = wp_get_current_user(); $name = ucfirst( empty( $user->first_name ) ? $user->display_name : $user->first_name ); return $name; @@ -746,14 +825,15 @@ function friendly_user_name() { * * @return void */ - function clean_attachment( $post_id ) { + public function clean_attachment( $post_id ) { $tiny_image = new Tiny_Image( $this->settings, $post_id ); $tiny_image->delete_converted_image(); } - static function request_review() { - $review_url = 'https://wordpress.org/support/plugin/tiny-compress-images/reviews/#new-post'; - $review_block = esc_html__( 'Enjoying TinyPNG?', 'tiny-compress-images' ); + public static function request_review() { + $review_url = + 'https://wordpress.org/support/plugin/tiny-compress-images/reviews/#new-post'; + $review_block = esc_html__( 'Enjoying TinyPNG?', 'tiny-compress-images' ); $review_block .= ' '; $review_block .= sprintf( '%s', @@ -763,7 +843,7 @@ static function request_review() { return $review_block; } - function mark_image_as_compressed() { + public function mark_image_as_compressed() { $response = $this->validate_ajax_attachment_request(); if ( isset( $response['error'] ) ) { echo $response['error']; @@ -771,7 +851,7 @@ function mark_image_as_compressed() { } list($id, $metadata) = $response['data']; - $tiny_image = new Tiny_Image( $this->settings, $id, $metadata ); + $tiny_image = new Tiny_Image( $this->settings, $id, $metadata ); $tiny_image->mark_as_compressed(); echo $this->render_compress_details( $tiny_image ); diff --git a/src/class-tiny-settings.php b/src/class-tiny-settings.php index 83bfa4e5..e1632459 100644 --- a/src/class-tiny-settings.php +++ b/src/class-tiny-settings.php @@ -148,7 +148,7 @@ public function admin_menu() { } public function add_options_to_page() { - include( dirname( __FILE__ ) . '/views/settings.php' ); + include __DIR__ . '/views/settings.php'; } public function image_sizes_notice() { @@ -183,12 +183,12 @@ public function get_status() { } public function disabled_required_functions() { - $required_functions = array( 'curl_exec' ); + $required_functions = array( 'curl_exec' ); $disabled_required_functions = array(); - $disabled_functions = explode( ',', ini_get( 'disable_functions' ) ); + $disabled_functions = explode( ',', ini_get( 'disable_functions' ) ); foreach ( $required_functions as $required_function ) { - if ( in_array( $required_function, $disabled_functions ) ) { + if ( in_array( $required_function, $disabled_functions, true ) ) { array_push( $disabled_required_functions, $required_function ); } } @@ -252,13 +252,13 @@ public function get_sizes() { $setting = get_option( self::get_prefixed_name( 'sizes' ) ); - $size = Tiny_Image::ORIGINAL; + $size = Tiny_Image::ORIGINAL; $this->sizes = array( $size => array( - 'width' => null, + 'width' => null, 'height' => null, 'tinify' => ! is_array( $setting ) || - (isset( $setting[ $size ] ) && 'on' === $setting[ $size ]), + ( isset( $setting[ $size ] ) && 'on' === $setting[ $size ] ), ), ); @@ -270,10 +270,10 @@ public function get_sizes() { list($width, $height) = self::get_intermediate_size( $size ); if ( $width || $height ) { $this->sizes[ $size ] = array( - 'width' => $width, + 'width' => $width, 'height' => $height, 'tinify' => ! is_array( $setting ) || - (isset( $setting[ $size ] ) && 'on' === $setting[ $size ]), + ( isset( $setting[ $size ] ) && 'on' === $setting[ $size ] ), ); } } @@ -326,7 +326,7 @@ public function get_compression_timing() { } public function auto_compress_enabled() { - return $this->get_compression_timing() === 'auto' || + return $this->get_compression_timing() === 'auto' || $this->get_compression_timing() === 'background'; } @@ -343,7 +343,7 @@ public function get_preserve_options( $size_name ) { if ( ! Tiny_Image::is_original( $size_name ) ) { return false; } - $options = array(); + $options = array(); $settings = get_option( self::get_prefixed_name( 'preserve_data' ) ); if ( $settings ) { $keys = array_keys( $settings ); @@ -363,10 +363,10 @@ public function get_resize_options( $size_name ) { if ( ! $this->get_resize_enabled() ) { return false; } - $setting = get_option( self::get_prefixed_name( 'resize_original' ) ); - $width = intval( $setting['width'] ); - $height = intval( $setting['height'] ); - $method = $width > 0 && $height > 0 ? 'fit' : 'scale'; + $setting = get_option( self::get_prefixed_name( 'resize_original' ) ); + $width = intval( $setting['width'] ); + $height = intval( $setting['height'] ); + $method = $width > 0 && $height > 0 ? 'fit' : 'scale'; $options['method'] = $method; if ( $width > 0 ) { $options['width'] = $width; @@ -384,7 +384,7 @@ public function get_resize_options( $size_name ) { */ public function get_conversion_options() { return array( - 'convert' => $this->get_conversion_enabled(), + 'convert' => $this->get_conversion_enabled(), 'convert_to' => $this->get_convertto_mimetype(), ); } @@ -428,8 +428,8 @@ public function render_settings_moved() { echo '

'; esc_html_e( 'TinyPNG - JPEG, PNG & WebP image compression', 'tiny-compress-images' ); echo '

'; - $url = admin_url( 'options-general.php?page=tinify' ); - $link = ""; + $url = admin_url( 'options-general.php?page=tinify' ); + $link = ""; $link .= esc_html__( 'settings', 'tiny-compress-images' ); $link .= ''; printf( @@ -455,13 +455,13 @@ public function render_compression_timing_settings() { echo '

' . $heading . '

'; echo '
'; - $name = self::get_prefixed_name( 'compression_timing' ); + $name = self::get_prefixed_name( 'compression_timing' ); $compression_timing = $this->get_compression_timing(); - $id = self::get_prefixed_name( 'background_compress_enabled' ); - $checked = ('background' === $compression_timing ? ' checked="checked"' : ''); + $id = self::get_prefixed_name( 'background_compress_enabled' ); + $checked = ( 'background' === $compression_timing ? ' checked="checked"' : '' ); - $label = esc_html__( + $label = esc_html__( 'Compress new images in the background (Recommended)', 'tiny-compress-images' ); @@ -479,10 +479,10 @@ public function render_compression_timing_settings() { false ); - $id = self::get_prefixed_name( 'auto_compress_enabled' ); - $checked = ('auto' === $compression_timing ? ' checked="checked"' : ''); + $id = self::get_prefixed_name( 'auto_compress_enabled' ); + $checked = ( 'auto' === $compression_timing ? ' checked="checked"' : '' ); - $label = esc_html__( + $label = esc_html__( 'Compress new images during upload', 'tiny-compress-images' ); @@ -500,10 +500,10 @@ public function render_compression_timing_settings() { false ); - $id = self::get_prefixed_name( 'auto_compress_disabled' ); - $checked = ('manual' === $compression_timing ? ' checked="checked"' : ''); + $id = self::get_prefixed_name( 'auto_compress_disabled' ); + $checked = ( 'manual' === $compression_timing ? ' checked="checked"' : '' ); - $label = esc_html__( + $label = esc_html__( 'Do not compress new images automatically', 'tiny-compress-images' ); @@ -548,9 +548,9 @@ public function render_sizes() { } private function render_size_checkboxes( $size, $option ) { - $id = self::get_prefixed_name( "sizes_$size" ); - $name = self::get_prefixed_name( 'sizes[' . $size . ']' ); - $checked = ($option['tinify'] ? ' checked="checked"' : ''); + $id = self::get_prefixed_name( "sizes_$size" ); + $name = self::get_prefixed_name( 'sizes[' . $size . ']' ); + $checked = ( $option['tinify'] ? ' checked="checked"' : '' ); if ( Tiny_Image::is_original( $size ) ) { $label = esc_html__( 'Original image', 'tiny-compress-images' ) . ' (' . esc_html__( @@ -594,7 +594,7 @@ public function render_size_checkboxes_description( echo '

'; echo '

'; if ( $resize_original_enabled ) { - $active_sizes_count++; + ++$active_sizes_count; } if ( $compress_wr2x ) { $active_sizes_count *= 2; @@ -618,11 +618,18 @@ public function render_size_checkboxes_description( 'strong' => array(), ); - /* translators: %1$s: number of images */ - printf(wp_kses(__( - 'With these settings you can compress at least %1$s images for free each month.', // WPCS: Needed for proper translation. - 'tiny-compress-images' - ), $strong), $free_images_per_month); + printf( + wp_kses( + /* translators: %1$s: number of images */ + __( + // phpcs:ignore Generic.Files.LineLength + 'With these settings you can compress at least %1$s images for free each month.', + 'tiny-compress-images' + ), + $strong + ), + $free_images_per_month + ); if ( self::wr2x_active() ) { echo '

'; @@ -653,9 +660,9 @@ public function render_resize() { ); echo '
'; - $id = self::get_prefixed_name( 'resize_original_enabled' ); - $name = self::get_prefixed_name( 'resize_original[enabled]' ); - $checked = ($this->get_resize_enabled() ? ' checked="checked"' : ''); + $id = self::get_prefixed_name( 'resize_original_enabled' ); + $name = self::get_prefixed_name( 'resize_original[enabled]' ); + $checked = ( $this->get_resize_enabled() ? ' checked="checked"' : '' ); $label = esc_html__( 'Resize the original image', @@ -667,11 +674,25 @@ public function render_resize() { '" value="on" ' . $checked . '/>'; echo '
'; - echo '
'; + echo '
'; echo ''; - echo wp_kses( __( 'Save space by setting a maximum width and height for all images uploaded.', 'tiny-compress-images' ), $strong ); // WPCS: Needed for proper translation. + echo wp_kses( + __( + // phpcs:ignore Generic.Files.LineLength + 'Save space by setting a maximum width and height for all images uploaded.', + 'tiny-compress-images' + ), + $strong + ); echo '
'; - echo wp_kses( __( 'Resizing takes 1 additional compression for each image that is larger.', 'tiny-compress-images' ), $strong ); // WPCS: Needed for proper translation. + echo wp_kses( + __( + // phpcs:ignore Generic.Files.LineLength + 'Resizing takes 1 additional compression for each image that is larger.', + 'tiny-compress-images' + ), + $strong + ); echo '
'; echo '
'; printf( '%s: ', esc_html__( 'Max Width', 'tiny-compress-images' ) ); @@ -719,7 +740,8 @@ public function render_compression_timing_radiobutton( echo '

'; echo '' . esc_html__( 'Warning', 'tiny-compress-images' ) . ' — '; $message = esc_html_e( - 'For compression to work you will need to configure WP Offload S3 to keep a copy of the images on the server.', // WPCS: Needed for proper translation. + // phpcs:ignore Generic.Files.LineLength + 'For compression to work you will need to configure WP Offload S3 to keep a copy of the images on the server.', 'tiny-compress-images' ); echo $message; @@ -729,9 +751,9 @@ public function render_compression_timing_radiobutton( echo '

'; } - $id = sprintf( self::get_prefixed_name( 'compression_timing_%s' ), $value ); + $id = sprintf( self::get_prefixed_name( 'compression_timing_%s' ), $value ); $label = esc_html( $label, 'tiny-compress-images' ); - $desc = esc_html( $desc, 'tiny-compress-images' ); + $desc = esc_html( $desc, 'tiny-compress-images' ); echo ''; echo ''; @@ -742,10 +764,10 @@ public function render_compression_timing_radiobutton( public function render_preserve_input( $name, $description ) { echo '

'; - $id = sprintf( self::get_prefixed_name( 'preserve_data_%s' ), $name ); - $field = sprintf( self::get_prefixed_name( 'preserve_data[%s]' ), $name ); - $checked = ($this->get_preserve_enabled( $name ) ? ' checked="checked"' : ''); - $label = esc_html( $description, 'tiny-compress-images' ); + $id = sprintf( self::get_prefixed_name( 'preserve_data_%s' ), $name ); + $field = sprintf( self::get_prefixed_name( 'preserve_data[%s]' ), $name ); + $checked = ( $this->get_preserve_enabled( $name ) ? ' checked="checked"' : '' ); + $label = esc_html( $description, 'tiny-compress-images' ); echo ''; echo ''; @@ -754,10 +776,10 @@ public function render_preserve_input( $name, $description ) { } public function render_resize_input( $name ) { - $id = sprintf( self::get_prefixed_name( 'resize_original_%s' ), $name ); - $field = sprintf( self::get_prefixed_name( 'resize_original[%s]' ), $name ); + $id = sprintf( self::get_prefixed_name( 'resize_original_%s' ), $name ); + $field = sprintf( self::get_prefixed_name( 'resize_original[%s]' ), $name ); $settings = get_option( self::get_prefixed_name( 'resize_original' ) ); - $value = isset( $settings[ $name ] ) ? $settings[ $name ] : '2048'; + $value = isset( $settings[ $name ] ) ? $settings[ $name ] : '2048'; echo ''; } @@ -824,12 +846,12 @@ public function render_account_status() { if ( empty( $key ) ) { $compressor = $this->get_compressor(); if ( $compressor->can_create_key() ) { - include( dirname( __FILE__ ) . '/views/account-status-create-advanced.php' ); + include __DIR__ . '/views/account-status-create-advanced.php'; } else { - include( dirname( __FILE__ ) . '/views/account-status-create-simple.php' ); + include __DIR__ . '/views/account-status-create-simple.php'; } } else { - $status = $this->compressor->get_status(); + $status = $this->compressor->get_status(); $status->pending = false; if ( $status->ok ) { if ( $this->get_api_key_pending() ) { @@ -837,14 +859,14 @@ public function render_account_status() { } } else { if ( $this->get_api_key_pending() ) { - $status->ok = true; + $status->ok = true; $status->pending = true; $status->message = ( 'An email has been sent to activate your account' ); } } - include( dirname( __FILE__ ) . '/views/account-status-connected.php' ); + include __DIR__ . '/views/account-status-connected.php'; } } @@ -853,12 +875,12 @@ public function render_pending_status() { if ( empty( $key ) ) { $compressor = $this->get_compressor(); if ( $compressor->can_create_key() ) { - include( dirname( __FILE__ ) . '/views/account-status-create-advanced.php' ); + include __DIR__ . '/views/account-status-create-advanced.php'; } else { - include( dirname( __FILE__ ) . '/views/account-status-create-simple.php' ); + include __DIR__ . '/views/account-status-create-simple.php'; } } else { - include( dirname( __FILE__ ) . '/views/account-status-loading.php' ); + include __DIR__ . '/views/account-status-loading.php'; } } @@ -869,13 +891,13 @@ public function create_api_key() { $compressor = $this->get_compressor(); if ( ! current_user_can( 'manage_options' ) ) { $status = (object) array( - 'ok' => false, + 'ok' => false, 'message' => 'This feature requires certain user capabilities', ); } elseif ( $compressor->can_create_key() ) { if ( ! isset( $_POST['name'] ) || ! $_POST['name'] ) { $status = (object) array( - 'ok' => false, + 'ok' => false, 'message' => __( 'Please enter your name', 'tiny-compress-images' @@ -887,7 +909,7 @@ public function create_api_key() { if ( ! isset( $_POST['email'] ) || ! $_POST['email'] ) { $status = (object) array( - 'ok' => false, + 'ok' => false, 'message' => __( 'Please enter your email address', 'tiny-compress-images' @@ -898,33 +920,40 @@ public function create_api_key() { } try { - $site = str_replace( array( 'http://', 'https://' ), '', get_bloginfo( 'url' ) ); + $site = str_replace( + array( 'http://', 'https://' ), + '', + get_bloginfo( 'url' ) + ); $identifier = 'WordPress plugin for ' . $site; - $link = $this->get_absolute_url(); - $compressor->create_key($_POST['email'], array( - 'name' => $_POST['name'], - 'identifier' => $identifier, - 'link' => $link, - )); + $link = $this->get_absolute_url(); + $compressor->create_key( + $_POST['email'], + array( + 'name' => $_POST['name'], + 'identifier' => $identifier, + 'link' => $link, + ) + ); update_option( self::get_prefixed_name( 'api_key_pending' ), true ); update_option( self::get_prefixed_name( 'api_key' ), $compressor->get_key() ); update_option( self::get_prefixed_name( 'status' ), 0 ); $status = (object) array( - 'ok' => true, + 'ok' => true, 'message' => null, ); } catch ( Tiny_Exception $err ) { list($message) = explode( ' (HTTP', $err->getMessage(), 2 ); - $status = (object) array( - 'ok' => false, + $status = (object) array( + 'ok' => false, 'message' => $message, ); } } else { $status = (object) array( - 'ok' => false, + 'ok' => false, 'message' => 'This feature is not available on your platform', ); } // End if(). @@ -940,13 +969,13 @@ public function update_api_key() { } if ( ! current_user_can( 'manage_options' ) ) { $status = (object) array( - 'ok' => false, + 'ok' => false, 'message' => 'This feature requires certain user capabilities', ); } elseif ( empty( $key ) ) { /* Always save if key is blank, so the key can be deleted. */ $status = (object) array( - 'ok' => true, + 'ok' => true, 'message' => null, ); } else { @@ -967,9 +996,9 @@ public static function wr2x_active() { public function get_wr2x_option() { $setting = get_option( self::get_prefixed_name( 'sizes' ) ); return array( - 'width' => null, + 'width' => null, 'height' => null, - 'tinify' => (isset( $setting['wr2x'] ) && 'on' === $setting['wr2x']), + 'tinify' => ( isset( $setting['wr2x'] ) && 'on' === $setting['wr2x'] ), ); } @@ -982,8 +1011,8 @@ public function compress_wr2x_images() { public function render_format_conversion() { echo '

'; - $convertopts_convert = self::get_prefixed_name( 'convert_format[convert]' ); - $convertopts_convert_id = self::get_prefixed_name( 'conversion_convert' ); + $convertopts_convert = self::get_prefixed_name( 'convert_format[convert]' ); + $convertopts_convert_id = self::get_prefixed_name( 'conversion_convert' ); $convertopts_convert_checked = $this->get_conversion_enabled() ? ' checked="checked"' : ''; @@ -996,11 +1025,14 @@ public function render_format_conversion() { ''; echo '

'; - $convertopts_convert_to_name = self::get_prefixed_name( 'convert_format[convert_to]' ); - $convertopts_convert_subfields_classname = self::get_prefixed_name( 'convert_fields' ); - $convertopts_convert_to_id = self::get_prefixed_name( 'convert_convert_to' ); - $convertopts_convert_value = self::get_convert_format_option( 'convert_to', 'smallest' ); - $convertopts_convert_disabled = + $convertopts_convert_to_name = + self::get_prefixed_name( 'convert_format[convert_to]' ); + $convertopts_convert_subfields_classname = + self::get_prefixed_name( 'convert_fields' ); + $convertopts_convert_to_id = self::get_prefixed_name( 'convert_convert_to' ); + $convertopts_convert_value = + self::get_convert_format_option( 'convert_to', 'smallest' ); + $convertopts_convert_disabled = self::get_conversion_enabled() ? '' : ' disabled="disabled"'; echo sprintf( '
', @@ -1038,8 +1070,11 @@ public function render_format_conversion() { 'avif', $convertopts_convert_value, __( 'Convert to AVIF', 'tiny-compress-images' ), - __( 'AVIF delivers even better compression and image quality than WebP. - Browser support is not as good as WebP.', 'tiny-compress-images' ) + __( + 'AVIF delivers even better compression and image quality than WebP. + Browser support is not as good as WebP.', + 'tiny-compress-images' + ) ); echo '
'; echo '
'; @@ -1053,7 +1088,7 @@ private static function render_convert_to_radiobutton( $label, $descr ) { - $checked = ($current === $value ? ' checked="checked"' : ''); + $checked = ( $current === $value ? ' checked="checked"' : '' ); echo '

'; echo ''; diff --git a/src/class-tiny-source-base.php b/src/class-tiny-source-base.php new file mode 100644 index 00000000..a83b21cb --- /dev/null +++ b/src/class-tiny-source-base.php @@ -0,0 +1,303 @@ +raw_html = $html; + $this->base_dir = $base_dir; + $this->allowed_domains = $domains; + $this->valid_mimetypes = array( 'image/avif', 'image/webp' ); + } + + protected static function get_attribute_value( $element, $name ) { + // Match the exact attribute name (not part of data-media, mediaType, etc.) + // and capture a single- or double-quoted value. + $delim = '~'; + $attr = preg_quote( $name, $delim ); + $regex = $delim . '(?, ,
) + if ( preg_match_all( + '~<' . preg_quote( $tagname, '~' ) . '\b(?:[^>"\']+|"[^"]*"|\'[^\']*\')*/?>~i', + $html, + $matches + ) ) { + $results = array_merge( $results, $matches[0] ); + } + + // Normal paired tags (e.g.

…
) + $regex_tag = preg_quote( $tagname, '~' ); + if ( preg_match_all( + '~<' . $regex_tag . + '\b(?:[^>"\']+|"[^"]*"|\'[^\']*\')*>.*?~is', + $html, + $matches + ) ) { + $results = array_merge( $results, $matches[0] ); + } + + return $results; + } + + protected function get_local_path( $url ) { + if ( strpos( $url, 'http' ) === 0 ) { + $matched_domain = null; + + foreach ( $this->allowed_domains as $domain ) { + if ( strpos( $url, $domain ) === 0 ) { + $matched_domain = $domain; + break; + } + } + + if ( null === $matched_domain ) { + return ''; + } + + $url = substr( $url, strlen( $matched_domain ) ); + } + $url = $this->base_dir . $url; + + return $url; + } + + protected function get_formatted_source( $image_source_data, $mimetype ) { + $format_url = Tiny_Helpers::replace_file_extension( $mimetype, $image_source_data['path'] ); + $local_path = $this->get_local_path( $format_url ); + if ( empty( $local_path ) ) { + return null; + } + + $exists_local = file_exists( $local_path ); + if ( $exists_local ) { + return array( + 'src' => $format_url, + 'size' => $image_source_data['size'], + 'type' => $mimetype, + ); + } + return null; + } + + /** + * Retrieves the sources from the or element + * + * @return array{path: string, size: string}[] The image sources + */ + protected function get_image_srcsets( $html ) { + $result = array(); + $srcset = $this::get_attribute_value( $html, 'srcset' ); + + if ( $srcset ) { + // Split the srcset to get individual entries + $srcset_entries = explode( ',', $srcset ); + + foreach ( $srcset_entries as $entry ) { + // Trim whitespace + $entry = trim( $entry ); + + // Split by whitespace to separate path and size/density descriptor + $parts = preg_split( '/\s+/', $entry, 2 ); + + if ( count( $parts ) === 2 ) { + // We have both path and size + $result[] = array( + 'path' => $parts[0], + 'size' => $parts[1], + ); + } elseif ( count( $parts ) === 1 ) { + // We only have a path, will be interpreted as pixel + // density 1x (unusual in srcset) + $result[] = array( + 'path' => $parts[0], + 'size' => '', + ); + } + } + } + return $result; + } + + /** + * Retrieves the sources from the or element + * + * @return array{path: string, size: string}[] The image sources + */ + private function get_image_src( $html ) { + $source = $this::get_attribute_value( $html, 'src' ); + if ( ! empty( $source ) ) { + // No srcset, but we have a src attribute + return array( + 'path' => $source, + 'size' => '', + ); + } + return array(); + } + + + /** + * Creates one or more elements if alternative formats + * are available. + * + * @param string $original_source_html, either or + * @return array{string} array of html + */ + protected function create_alternative_sources( $original_source_html ) { + $srcsets = $this->get_image_srcsets( $original_source_html ); + if ( empty( $srcsets ) ) { + // no srcset, try src attribute + $srcsets[] = $this->get_image_src( $original_source_html ); + } + + if ( empty( $srcsets ) ) { + return array(); + } + + $is_source_tag = (bool) preg_match( '#get_largest_width_descriptor( $srcsets ); + + foreach ( $this->valid_mimetypes as $mimetype ) { + $srcset_parts = array(); + + foreach ( $srcsets as $srcset ) { + $alt_source = $this->get_formatted_source( $srcset, $mimetype ); + if ( $alt_source ) { + $srcset_parts[] = trim( $alt_source['src'] . ' ' . $alt_source['size'] ); + } + } + + if ( + $width_descriptor && + ! self::srcset_contains_width_descriptor( + $srcset_parts, + $width_descriptor + ) + ) { + continue; + } + + if ( empty( $srcset_parts ) ) { + continue; + } + + $source_attr_parts = array(); + + $srcset_attr = implode( ', ', $srcset_parts ); + $source_attr_parts['srcset'] = $srcset_attr; + + if ( $is_source_tag ) { + foreach ( array( 'sizes', 'media', 'width', 'height' ) as $attr ) { + $attr_value = $this->get_attribute_value( $original_source_html, $attr ); + if ( $attr_value ) { + $source_attr_parts[ $attr ] = $attr_value; + } + } + } + + $source_attr_parts['type'] = $mimetype; + $source_parts = array( ' $source_attr_val ) { + $source_parts[] = $source_attr_name . '="' . $source_attr_val . '"'; + } + $source_parts[] = '/>'; + $sources[] = implode( ' ', $source_parts ); + } // End foreach(). + + return $sources; + } + + /** + * Returns the largest numeric width descriptor + * (e.g. 2000 from "2000w") found in the srcset data. + * + * @param array $srcsets + * @return int + */ + public static function get_largest_width_descriptor( $srcsets ) { + $largest = 0; + + foreach ( $srcsets as $srcset ) { + if ( empty( $srcset['size'] ) ) { + continue; + } + + if ( preg_match( '/(\d+)w/', $srcset['size'], $matches ) ) { + $width = (int) $matches[1]; + if ( $width > $largest ) { + $largest = $width; + } + } + } + + return $largest; + } + + /** + * Determines whether a srcset list contains the provided width descriptor. + * + * @param string[] $srcset_parts + * @param int $width_descriptor + * @return bool true if width is in srcset + */ + public static function srcset_contains_width_descriptor( $srcset_parts, $width_descriptor ) { + if ( empty( $srcset_parts ) || $width_descriptor <= 0 ) { + return false; + } + + $suffix = ' ' . $width_descriptor . 'w'; + $suffix_length = strlen( $suffix ); + + foreach ( $srcset_parts as $srcset_part ) { + if ( substr( $srcset_part, -$suffix_length ) === $suffix ) { + return true; + } + } + + return false; + } +} diff --git a/src/class-tiny-source-image.php b/src/class-tiny-source-image.php new file mode 100644 index 00000000..2858b014 --- /dev/null +++ b/src/class-tiny-source-image.php @@ -0,0 +1,45 @@ + element contain additional sources + */ + public function create_picture_elements() { + $sources = $this->create_alternative_sources( $this->raw_html ); + if ( empty( $sources ) ) { + return $this->raw_html; + } + $picture_element = array( '' ); + $picture_element[] = implode( '', $sources ); + $picture_element[] = $this->raw_html; + $picture_element[] = ''; + + return implode( '', $picture_element ); + } +} diff --git a/src/class-tiny-source-picture.php b/src/class-tiny-source-picture.php new file mode 100644 index 00000000..3bcfa1a5 --- /dev/null +++ b/src/class-tiny-source-picture.php @@ -0,0 +1,60 @@ + element based on locally available converted files. + * + * @return string The augmented HTML or the original if no additions. + */ + public function augment_picture_element() { + $modified_sources = array(); + + foreach ( $this->get_element_by_tag( $this->raw_html, 'source' ) as $source_tag_html ) { + $type_attr = self::get_attribute_value( $source_tag_html, 'type' ); + $type_attr = null !== $type_attr ? strtolower( trim( $type_attr ) ) : ''; + + // Skip if already optimized. + if ( '' !== $type_attr && in_array( $type_attr, $this->valid_mimetypes, true ) ) { + continue; + } + + $alternative_sources = $this->create_alternative_sources( $source_tag_html ); + if ( is_array( $alternative_sources ) && $alternative_sources ) { + foreach ( $alternative_sources as $alt ) { + $modified_sources[] = $alt; // no array_merge in the loop + } + } + } + + // handle inner image + foreach ( $this->get_element_by_tag( $this->raw_html, 'img' ) as $img_tag_html ) { + $alt_image_source = $this->create_alternative_sources( $img_tag_html ); + $modified_sources = array_merge( $modified_sources, $alt_image_source ); + } + + $modified_source = implode( '', $modified_sources ); + + // Insert newly built elements immediately before the first + return preg_replace( '#(raw_html, 1 ); + } +} diff --git a/src/class-tiny-wp-base.php b/src/class-tiny-wp-base.php index f19ec6cf..fd08fb34 100644 --- a/src/class-tiny-wp-base.php +++ b/src/class-tiny-wp-base.php @@ -19,7 +19,7 @@ */ abstract class Tiny_WP_Base { - const NAME = 'tiny-compress-images'; + const NAME = 'tiny-compress-images'; const PREFIX = 'tinypng_'; private static $wp_version; @@ -27,7 +27,7 @@ abstract class Tiny_WP_Base { public static function wp_version() { if ( is_null( self::$wp_version ) ) { // Try to use unmodified version - include( ABSPATH . WPINC . '/version.php' ); + include ABSPATH . WPINC . '/version.php'; if ( isset( $wp_version ) ) { self::$wp_version = $wp_version; } else { diff --git a/src/compatibility/as3cf/class-tiny-as3cf.php b/src/compatibility/as3cf/class-tiny-as3cf.php index 45e63e29..6ad7ca26 100644 --- a/src/compatibility/as3cf/class-tiny-as3cf.php +++ b/src/compatibility/as3cf/class-tiny-as3cf.php @@ -85,6 +85,6 @@ public function as3cf_before_offload( $as3cf_item, $args ) { } $tiny_image = new Tiny_Image( $this->tiny_settings, $as3cf_item->source_id() ); - $result = $tiny_image->compress(); + $result = $tiny_image->compress(); } } diff --git a/src/compatibility/wpml/class-tiny-wpml.php b/src/compatibility/wpml/class-tiny-wpml.php index ed725348..ece7ce37 100644 --- a/src/compatibility/wpml/class-tiny-wpml.php +++ b/src/compatibility/wpml/class-tiny-wpml.php @@ -26,14 +26,20 @@ public function __construct() { private function add_hooks() { // When WPML duplicates an attachment in other languages. - add_action( 'wpml_after_duplicate_attachment', - array( $this, 'copy_tiny_postmeta' ), 10, 2 + add_action( + 'wpml_after_duplicate_attachment', + array( $this, 'copy_tiny_postmeta' ), + 10, + 2 ); // When you add a missing translation text or restore an image // on the WPML media tranlation popup. - add_action( 'wpml_after_copy_attached_file_postmeta', - array( $this, 'after_copy_attached_file' ), 10, 2 + add_action( + 'wpml_after_copy_attached_file_postmeta', + array( $this, 'after_copy_attached_file' ), + 10, + 2 ); // When adding an alternative image on the WPML media translation popup. diff --git a/src/config/class-tiny-config.php b/src/config/class-tiny-config.php index b58fc922..dfab8f81 100644 --- a/src/config/class-tiny-config.php +++ b/src/config/class-tiny-config.php @@ -6,8 +6,8 @@ class Tiny_Config { /* URL is only used by fopen driver. */ - const SHRINK_URL = 'https://api.tinify.com/shrink'; - const KEYS_URL = 'https://api.tinify.com/keys'; + const SHRINK_URL = 'https://api.tinify.com/shrink'; + const KEYS_URL = 'https://api.tinify.com/keys'; const MONTHLY_FREE_COMPRESSIONS = 500; - const META_KEY = 'tiny_compress_images'; + const META_KEY = 'tiny_compress_images'; } diff --git a/src/views/account-status-connected.php b/src/views/account-status-connected.php index f9f8155d..4f8b1bff 100644 --- a/src/views/account-status-connected.php +++ b/src/views/account-status-connected.php @@ -1,6 +1,7 @@

- + ); + ?>

diff --git a/src/views/account-status-create-advanced.php b/src/views/account-status-create-advanced.php index 9a74a560..eccea9d5 100644 --- a/src/views/account-status-create-advanced.php +++ b/src/views/account-status-create-advanced.php @@ -1,21 +1,25 @@ user_firstname . ' ' . $user->user_lastname ); +$user = wp_get_current_user(); +$name = trim( $user->user_firstname . ' ' . $user->user_lastname ); $email = trim( $user->user_email ); ?>