-
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. As well as eliminating duplicate code/functionality, there are other benefits: - The method can be tested independently, which is duly done; - The results cache is now shared; - The functionality is readily available to other classes, e.g. for the solution to #1276 (as currently proposed). PHPStan errors from the original code have been resolved as follows: - Use `Preg::split` to wrap `preg_split` to handle unexpected errors; - Check the return value from `preg_match` precisely with `!== 1` instead of `!`. 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.
- Loading branch information
1 parent
c05b168
commit 2b34d83
Showing
5 changed files
with
265 additions
and
112 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,73 @@ | ||
<?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 = (new Preg())->split('/;(?!base64|charset)/', $declarationBlock); | ||
|
||
$properties = []; | ||
foreach ($declarations as $declaration) { | ||
$matches = []; | ||
if ( | ||
\preg_match( | ||
'/^([A-Za-z\\-]+)\\s*:\\s*(.+)$/s', | ||
// `$declaration` would only be an array if `PREG_SPLIT_OFFSET_CAPTURE` was used with `preg_split`, | ||
// which isn't the case | ||
\trim($declaration), | ||
$matches | ||
) | ||
!== 1 | ||
) { | ||
continue; | ||
} | ||
|
||
$propertyName = \strtolower($matches[1]); | ||
$propertyValue = $matches[2]; | ||
$properties[$propertyName] = $propertyValue; | ||
} | ||
self::$cache[$declarationBlock] = $properties; | ||
|
||
return $properties; | ||
} | ||
} |
Oops, something went wrong.