-
Notifications
You must be signed in to change notification settings - Fork 155
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[CLEANUP] Add DeclarationBlockParser class
This is essentially a refactoring to move the `parseCssDeclarationsBlock` method that was duplicated in both `CssInliner` and `CssToAttributeConverter` to a separate class. Doing so also allows it to be tested independently, which is duly done. Additionally, it allows the results cache to be shared. This is also likely to be used by the solution for #1276 (as currently proposed). Longer-term, we should be able to use functionality from PHP-CSS-Parser for more accurate parsing (e.g. strings containing semicolons), whereupon this class can become a wrapper for that, but currently that functionality is not available in a standalone class. Any PHPStan errors from the original function have been fixed, including handling the failure case of `preg_split` (and using `trigger_error` in that case). There is a false positive from PHPStan for which there is an open ticket: phpstan/phpstan#7799.
- Loading branch information
Showing
5 changed files
with
249 additions
and
113 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Pelago\Emogrifier\Utilities; | ||
|
||
/** | ||
* Provides a common method for parsing CSS declaration blocks. | ||
* These might be from actual CSS, or from the `style` attribute of an HTML DOM element. | ||
* | ||
* Caches results globally. | ||
* | ||
* @internal | ||
*/ | ||
class DeclarationBlockParser | ||
{ | ||
/** | ||
* @var array<string, array<string, string>> | ||
*/ | ||
private static $cache = []; | ||
|
||
/** | ||
* Parses a CSS declaration block into property name/value pairs. | ||
* | ||
* Example: | ||
* | ||
* The declaration block | ||
* | ||
* "color: #000; font-weight: bold;" | ||
* | ||
* will be parsed into the following array: | ||
* | ||
* "color" => "#000" | ||
* "font-weight" => "bold" | ||
* | ||
* @param string $declarationBlock the CSS declarations block without the curly braces, may be empty | ||
* | ||
* @return array<string, string> | ||
* the CSS declarations with the property names as array keys and the property values as array values | ||
*/ | ||
public function parse(string $declarationBlock): array | ||
{ | ||
if (isset(self::$cache[$declarationBlock])) { | ||
return self::$cache[$declarationBlock]; | ||
} | ||
|
||
$declarations = \preg_split('/;(?!base64|charset)/', $declarationBlock); | ||
if ($declarations === false) { | ||
\trigger_error('Regex failure parsing declaration block `' . $declarationBlock . '`', E_USER_ERROR); | ||
return []; | ||
} | ||
|
||
$properties = []; | ||
foreach ($declarations as $declaration) { | ||
$matches = []; | ||
if (!(bool) \preg_match('/^([A-Za-z\\-]+)\\s*:\\s*(.+)$/s', \trim($declaration), $matches)) { | ||
continue; | ||
} | ||
|
||
$propertyName = \strtolower($matches[1]); | ||
$propertyValue = $matches[2]; | ||
$properties[$propertyName] = $propertyValue; | ||
} | ||
self::$cache[$declarationBlock] = $properties; | ||
|
||
return $properties; | ||
} | ||
} |
Oops, something went wrong.