diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ab34d2ed3..948211c8f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,7 +40,7 @@ jobs: - name: Build Plugin run: npm run build - name: Decompress plugin - run: unzip wp-job-manager.zip -d wp-job-manager + run: unzip build/wp-job-manager.zip -d wp-job-manager - name: Store Artifact uses: actions/upload-artifact@v2 with: diff --git a/.psalm/psalm-baseline.xml b/.psalm/psalm-baseline.xml index 7eaa926fc..41f2cb722 100644 --- a/.psalm/psalm-baseline.xml +++ b/.psalm/psalm-baseline.xml @@ -402,21 +402,6 @@ - - - - - - - caches[self::CACHE_KEY_CSS][$cssKey]]]> - caches[self::CACHE_KEY_SELECTOR][$selectorKey]]]> - - - parentNode && is_callable([$node->parentNode, 'removeChild'])]]> - - false diff --git a/composer.json b/composer.json index edf7b33ec..23ba0e3eb 100644 --- a/composer.json +++ b/composer.json @@ -17,32 +17,6 @@ "vimeo/psalm": "^5.13", "php-stubs/wordpress-stubs": "^6.4" }, - "archive": { - "exclude": [ - "/*", - "!/assets/dist", - "!/assets/images", - "!/assets/lib", - "/assets/dist/css/*.js", - "!/includes", - "!/languages", - "!/lib", - "!/templates", - "!/changelog.txt", - "!/LICENSE", - "!/readme.txt", - "!/uninstall.php", - "!/wp-job-manager.php", - "!/wp-job-manager-autoload.php", - "!/wp-job-manager-deprecated.php", - "!/wp-job-manager-functions.php", - "!/wp-job-manager-template.php", - "!/wpml-config.xml", - ".DS_Store", - ".*", - "*.test.js" - ] - }, "config": { "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": true @@ -50,5 +24,8 @@ "platform": { "php": "7.4" } + }, + "require": { + "pelago/emogrifier": "^7.2" } } diff --git a/composer.lock b/composer.lock index d54a5e2d9..8ddfabef1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,301 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "33fae2736293dd91fdb47d2118163002", - "packages": [], + "content-hash": "0a4381eadf50310f21920b003fe063c3", + "packages": [ + { + "name": "pelago/emogrifier", + "version": "v7.2.0", + "source": { + "type": "git", + "url": "https://github.com/MyIntervals/emogrifier.git", + "reference": "727bdf7255b51798307f17dec52ff8a91f1c7de3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MyIntervals/emogrifier/zipball/727bdf7255b51798307f17dec52ff8a91f1c7de3", + "reference": "727bdf7255b51798307f17dec52ff8a91f1c7de3", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "php": "~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", + "sabberworm/php-css-parser": "^8.4.0", + "symfony/css-selector": "^4.4.23 || ^5.4.0 || ^6.0.0 || ^7.0.0" + }, + "require-dev": { + "php-parallel-lint/php-parallel-lint": "1.3.2", + "phpunit/phpunit": "9.6.11", + "rawr/cross-data-providers": "2.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "8.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Pelago\\Emogrifier\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Oliver Klee", + "email": "github@oliverklee.de" + }, + { + "name": "Zoli Szabó", + "email": "zoli.szabo+github@gmail.com" + }, + { + "name": "John Reeve", + "email": "jreeve@pelagodesign.com" + }, + { + "name": "Jake Hotson", + "email": "jake@qzdesign.co.uk" + }, + { + "name": "Cameron Brooks" + }, + { + "name": "Jaime Prado" + } + ], + "description": "Converts CSS styles into inline style attributes in your HTML code", + "homepage": "https://www.myintervals.com/emogrifier.php", + "keywords": [ + "css", + "email", + "pre-processing" + ], + "support": { + "issues": "https://github.com/MyIntervals/emogrifier/issues", + "source": "https://github.com/MyIntervals/emogrifier" + }, + "time": "2023-12-06T02:00:20+00:00" + }, + { + "name": "sabberworm/php-css-parser", + "version": "v8.5.1", + "source": { + "type": "git", + "url": "https://github.com/MyIntervals/PHP-CSS-Parser.git", + "reference": "4a3d572b0f8b28bb6fd016ae8bbfc445facef152" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/4a3d572b0f8b28bb6fd016ae8bbfc445facef152", + "reference": "4a3d572b0f8b28bb6fd016ae8bbfc445facef152", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": ">=5.6.20" + }, + "require-dev": { + "phpunit/phpunit": "^5.7.27" + }, + "suggest": { + "ext-mbstring": "for parsing UTF-8 CSS" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "9.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Sabberworm\\CSS\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Raphael Schweikert" + }, + { + "name": "Oliver Klee", + "email": "github@oliverklee.de" + }, + { + "name": "Jake Hotson", + "email": "jake.github@qzdesign.co.uk" + } + ], + "description": "Parser for CSS Files written in PHP", + "homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser", + "keywords": [ + "css", + "parser", + "stylesheet" + ], + "support": { + "issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues", + "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.5.1" + }, + "time": "2024-02-15T16:41:13+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v5.4.35", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "9e615d367e2bed41f633abb383948c96a2dbbfae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/9e615d367e2bed41f633abb383948c96a2dbbfae", + "reference": "9e615d367e2bed41f633abb383948c96a2dbbfae", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Converts CSS selectors to XPath expressions", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/css-selector/tree/v5.4.35" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-01-23T13:51:25+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.28.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-01-26T09:26:14+00:00" + } + ], "packages-dev": [ { "name": "amphp/amp", @@ -3799,89 +4092,6 @@ ], "time": "2023-01-26T09:26:14+00:00" }, - { - "name": "symfony/polyfill-php80", - "version": "v1.28.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", - "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2023-01-26T09:26:14+00:00" - }, { "name": "symfony/service-contracts", "version": "v2.5.2", @@ -4389,5 +4599,5 @@ "platform-overrides": { "php": "7.4" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.3.0" } diff --git a/includes/class-wp-job-manager-email-notifications.php b/includes/class-wp-job-manager-email-notifications.php index 6fced260d..c84b908cb 100644 --- a/includes/class-wp-job-manager-email-notifications.php +++ b/includes/class-wp-job-manager-email-notifications.php @@ -9,6 +9,8 @@ exit; } +use Pelago\Emogrifier\CssInliner; +use Pelago\Emogrifier\HtmlProcessor\CssToAttributeConverter; /** * Base class for WP Job Manager's email notification system. * @@ -164,9 +166,8 @@ public static function lazy_init() { include_once JOB_MANAGER_PLUGIN_DIR . '/includes/emails/class-wp-job-manager-email-employer-expiring-job.php'; include_once JOB_MANAGER_PLUGIN_DIR . '/includes/emails/class-wp-job-manager-email-admin-expiring-job.php'; - if ( ! class_exists( 'Emogrifier' ) && class_exists( 'DOMDocument' ) && version_compare( PHP_VERSION, '5.5', '>=' ) ) { - include_once JOB_MANAGER_PLUGIN_DIR . '/lib/emogrifier/class-emogrifier.php'; - } + // Load Vendor Autoload. + require_once JOB_MANAGER_PLUGIN_DIR . '/vendor/autoload.php'; } /** @@ -933,10 +934,11 @@ private static function get_email_content( $email_notification_key, $args, $is_p * @return string */ private static function inject_styles( $content ) { - if ( class_exists( 'Emogrifier' ) ) { + if ( class_exists( CssInliner::class ) ) { try { - $emogrifier = new Emogrifier( $content, self::get_styles() ); - $content = $emogrifier->emogrify(); + $dom_document = CssInliner::fromHtml( $content )->inlineCss( self::get_styles() )->getDomDocument(); + $content = CssToAttributeConverter::fromDomDocument( $dom_document )->convertCssToVisualAttributes()->render(); + } catch ( Exception $e ) { trigger_error( 'Unable to inject styles into email notification: ' . $e->getMessage() ); // @codingStandardsIgnoreLine } @@ -947,12 +949,12 @@ private static function inject_styles( $content ) { /** * Gets the CSS styles to be used in email notifications. * - * @return bool|string + * @return string */ private static function get_styles() { $email_styles_template = self::locate_template_file( 'email-styles' ); if ( ! file_exists( $email_styles_template ) ) { - return false; + return ''; } ob_start(); include $email_styles_template; diff --git a/lib/emogrifier/class-emogrifier.php b/lib/emogrifier/class-emogrifier.php deleted file mode 100644 index 412dc276a..000000000 --- a/lib/emogrifier/class-emogrifier.php +++ /dev/null @@ -1,1811 +0,0 @@ - - * @author Roman Ožana - * @author Sander Kruger - * @author Zoli Szabó - */ -class Emogrifier -{ - /** - * @var int - */ - const CACHE_KEY_CSS = 0; - - /** - * @var int - */ - const CACHE_KEY_SELECTOR = 1; - - /** - * @var int - */ - const CACHE_KEY_XPATH = 2; - - /** - * @var int - */ - const CACHE_KEY_CSS_DECLARATIONS_BLOCK = 3; - - /** - * @var int - */ - const CACHE_KEY_COMBINED_STYLES = 4; - - /** - * for calculating nth-of-type and nth-child selectors - * - * @var int - */ - const INDEX = 0; - - /** - * for calculating nth-of-type and nth-child selectors - * - * @var int - */ - const MULTIPLIER = 1; - - /** - * @var string - */ - const ID_ATTRIBUTE_MATCHER = '/(\\w+)?\\#([\\w\\-]+)/'; - - /** - * @var string - */ - const CLASS_ATTRIBUTE_MATCHER = '/(\\w+|[\\*\\]])?((\\.[\\w\\-]+)+)/'; - - /** - * @var string - */ - const CONTENT_TYPE_META_TAG = ''; - - /** - * @var string - */ - const DEFAULT_DOCUMENT_TYPE = ''; - - /** - * @var string - */ - private $html = ''; - - /** - * @var string - */ - private $css = ''; - - /** - * @var bool[] - */ - private $excludedSelectors = []; - - /** - * @var string[] - */ - private $unprocessableHtmlTags = ['wbr']; - - /** - * @var bool[] - */ - private $allowedMediaTypes = ['all' => true, 'screen' => true, 'print' => true]; - - /** - * @var mixed[] - */ - private $caches = [ - self::CACHE_KEY_CSS => [], - self::CACHE_KEY_SELECTOR => [], - self::CACHE_KEY_XPATH => [], - self::CACHE_KEY_CSS_DECLARATIONS_BLOCK => [], - self::CACHE_KEY_COMBINED_STYLES => [], - ]; - - /** - * the visited nodes with the XPath paths as array keys - * - * @var \DOMElement[] - */ - private $visitedNodes = []; - - /** - * the styles to apply to the nodes with the XPath paths as array keys for the outer array - * and the attribute names/values as key/value pairs for the inner array - * - * @var string[][] - */ - private $styleAttributesForNodes = []; - - /** - * Determines whether the "style" attributes of tags in the the HTML passed to this class should be preserved. - * If set to false, the value of the style attributes will be discarded. - * - * @var bool - */ - private $isInlineStyleAttributesParsingEnabled = true; - - /** - * Determines whether the