Make emogrifier works with PHP 5.2, closes #7179
This commit is contained in:
parent
586025b17e
commit
ea908283a3
|
@ -113,6 +113,8 @@ class Emogrifier {
|
||||||
*/
|
*/
|
||||||
public $preserveEncoding = FALSE;
|
public $preserveEncoding = FALSE;
|
||||||
|
|
||||||
|
public static $_media = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The constructor.
|
* The constructor.
|
||||||
*
|
*
|
||||||
|
@ -172,12 +174,12 @@ class Emogrifier {
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
private function clearCache($key) {
|
private function clearCache($key) {
|
||||||
$allowedCacheKeys = array(self::CACHE_KEY_CSS, self::CACHE_KEY_SELECTOR, self::CACHE_KEY_XPATH, self::CACHE_KEY_CSS_DECLARATION_BLOCK);
|
$allowedCacheKeys = array(self::CACHE_KEY_CSS, self::CACHE_KEY_SELECTOR, self::CACHE_KEY_XPATH, self::CACHE_KEY_CSS_DECLARATION_BLOCK);
|
||||||
if (!in_array($key, $allowedCacheKeys, TRUE)) {
|
if (!in_array($key, $allowedCacheKeys, TRUE)) {
|
||||||
throw new \InvalidArgumentException('Invalid cache key: ' . $key, 1391822035);
|
throw new InvalidArgumentException('Invalid cache key: ' . $key, 1391822035);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->caches[$key] = array();
|
$this->caches[$key] = array();
|
||||||
|
@ -230,15 +232,15 @@ class Emogrifier {
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*
|
*
|
||||||
* @throws \BadMethodCallException
|
* @throws BadMethodCallException
|
||||||
*/
|
*/
|
||||||
public function emogrify() {
|
public function emogrify() {
|
||||||
if ($this->html === '') {
|
if ($this->html === '') {
|
||||||
throw new \BadMethodCallException('Please set some HTML first before calling emogrify.', 1390393096);
|
throw new BadMethodCallException('Please set some HTML first before calling emogrify.', 1390393096);
|
||||||
}
|
}
|
||||||
|
|
||||||
$xmlDocument = $this->createXmlDocument();
|
$xmlDocument = $this->createXmlDocument();
|
||||||
$xpath = new \DOMXPath($xmlDocument);
|
$xpath = new DOMXPath($xmlDocument);
|
||||||
$this->clearAllCaches();
|
$this->clearAllCaches();
|
||||||
|
|
||||||
// before be begin processing the CSS file, parse the document and normalize all existing CSS attributes (changes 'DISPLAY: none' to 'display: none');
|
// before be begin processing the CSS file, parse the document and normalize all existing CSS attributes (changes 'DISPLAY: none' to 'display: none');
|
||||||
|
@ -248,15 +250,9 @@ class Emogrifier {
|
||||||
|
|
||||||
$nodesWithStyleAttributes = $xpath->query('//*[@style]');
|
$nodesWithStyleAttributes = $xpath->query('//*[@style]');
|
||||||
if ($nodesWithStyleAttributes !== FALSE) {
|
if ($nodesWithStyleAttributes !== FALSE) {
|
||||||
/** @var $nodeWithStyleAttribute \DOMNode */
|
/** @var $nodeWithStyleAttribute DOMNode */
|
||||||
foreach ($nodesWithStyleAttributes as $node) {
|
foreach ($nodesWithStyleAttributes as $node) {
|
||||||
$normalizedOriginalStyle = preg_replace_callback(
|
$normalizedOriginalStyle = preg_replace_callback( '/[A-z\\-]+(?=\\:)/S', array( $this, 'strtolower' ), $node->getAttribute('style') );
|
||||||
'/[A-z\\-]+(?=\\:)/S',
|
|
||||||
function (array $m) {
|
|
||||||
return strtolower($m[0]);
|
|
||||||
},
|
|
||||||
$node->getAttribute('style')
|
|
||||||
);
|
|
||||||
|
|
||||||
// in order to not overwrite existing style attributes in the HTML, we have to save the original HTML styles
|
// in order to not overwrite existing style attributes in the HTML, we have to save the original HTML styles
|
||||||
$nodePath = $node->getNodePath();
|
$nodePath = $node->getNodePath();
|
||||||
|
@ -361,6 +357,10 @@ class Emogrifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function strtolower(array $m) {
|
||||||
|
return strtolower($m[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method merges old or existing name/value array with new name/value array
|
* This method merges old or existing name/value array with new name/value array
|
||||||
|
@ -385,10 +385,10 @@ class Emogrifier {
|
||||||
* Copies the media part from CSS array parts to $xmlDocument.
|
* Copies the media part from CSS array parts to $xmlDocument.
|
||||||
*
|
*
|
||||||
* @param array $cssParts
|
* @param array $cssParts
|
||||||
* @param \DOMDocument $xmlDocument
|
* @param DOMDocument $xmlDocument
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function copyCssWithMediaToStyleNode(array $cssParts, \DOMDocument $xmlDocument) {
|
public function copyCssWithMediaToStyleNode(array $cssParts, DOMDocument $xmlDocument) {
|
||||||
if (isset($cssParts['media']) && $cssParts['media'] !== '') {
|
if (isset($cssParts['media']) && $cssParts['media'] !== '') {
|
||||||
$this->addStyleElementToDocument($xmlDocument, $cssParts['media']);
|
$this->addStyleElementToDocument($xmlDocument, $cssParts['media']);
|
||||||
}
|
}
|
||||||
|
@ -397,10 +397,10 @@ class Emogrifier {
|
||||||
/**
|
/**
|
||||||
* Returns CSS content.
|
* Returns CSS content.
|
||||||
*
|
*
|
||||||
* @param \DOMXPath $xpath
|
* @param DOMXPath $xpath
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private function getCssFromAllStyleNodes(\DOMXPath $xpath) {
|
private function getCssFromAllStyleNodes(DOMXPath $xpath) {
|
||||||
$styleNodes = $xpath->query('//style');
|
$styleNodes = $xpath->query('//style');
|
||||||
|
|
||||||
if ($styleNodes === FALSE) {
|
if ($styleNodes === FALSE) {
|
||||||
|
@ -408,7 +408,7 @@ class Emogrifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
$css = '';
|
$css = '';
|
||||||
/** @var $styleNode \DOMNode */
|
/** @var $styleNode DOMNode */
|
||||||
foreach ($styleNodes as $styleNode) {
|
foreach ($styleNodes as $styleNode) {
|
||||||
$css .= "\n\n" . $styleNode->nodeValue;
|
$css .= "\n\n" . $styleNode->nodeValue;
|
||||||
$styleNode->parentNode->removeChild($styleNode);
|
$styleNode->parentNode->removeChild($styleNode);
|
||||||
|
@ -420,11 +420,11 @@ class Emogrifier {
|
||||||
/**
|
/**
|
||||||
* Adds a style element with $css to $document.
|
* Adds a style element with $css to $document.
|
||||||
*
|
*
|
||||||
* @param \DOMDocument $document
|
* @param DOMDocument $document
|
||||||
* @param string $css
|
* @param string $css
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function addStyleElementToDocument(\DOMDocument $document, $css) {
|
private function addStyleElementToDocument(DOMDocument $document, $css) {
|
||||||
$styleElement = $document->createElement('style', $css);
|
$styleElement = $document->createElement('style', $css);
|
||||||
$styleAttribute = $document->createAttribute('type');
|
$styleAttribute = $document->createAttribute('type');
|
||||||
$styleAttribute->value = 'text/css';
|
$styleAttribute->value = 'text/css';
|
||||||
|
@ -437,10 +437,10 @@ class Emogrifier {
|
||||||
/**
|
/**
|
||||||
* Returns the existing or creates a new head element in $document.
|
* Returns the existing or creates a new head element in $document.
|
||||||
*
|
*
|
||||||
* @param \DOMDocument $document
|
* @param DOMDocument $document
|
||||||
* @return \DOMNode the head element
|
* @return DOMNode the head element
|
||||||
*/
|
*/
|
||||||
private function getOrCreateHeadElement(\DOMDocument $document) {
|
private function getOrCreateHeadElement(DOMDocument $document) {
|
||||||
$head = $document->getElementsByTagName('head')->item(0);
|
$head = $document->getElementsByTagName('head')->item(0);
|
||||||
|
|
||||||
if ($head === NULL) {
|
if ($head === NULL) {
|
||||||
|
@ -473,14 +473,7 @@ class Emogrifier {
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
private function splitCssAndMediaQuery($css) {
|
private function splitCssAndMediaQuery($css) {
|
||||||
$media = '';
|
$css = preg_replace_callback( '#@media\\s+(?:only\\s)?(?:[\\s{\(]|screen|all)\\s?[^{]+{.*}\\s*}\\s*#misU', array( $this, '_media_concat' ), $css );
|
||||||
|
|
||||||
$css = preg_replace_callback(
|
|
||||||
'#@media\\s+(?:only\\s)?(?:[\\s{\(]|screen|all)\\s?[^{]+{.*}\\s*}\\s*#misU',
|
|
||||||
function($matches) use (&$media) {
|
|
||||||
$media .= $matches[0];
|
|
||||||
}, $css
|
|
||||||
);
|
|
||||||
|
|
||||||
// filter the CSS
|
// filter the CSS
|
||||||
$search = array(
|
$search = array(
|
||||||
|
@ -501,16 +494,20 @@ class Emogrifier {
|
||||||
// clean CSS before output
|
// clean CSS before output
|
||||||
$css = preg_replace($search, $replace, $css);
|
$css = preg_replace($search, $replace, $css);
|
||||||
|
|
||||||
return array('css' => $css, 'media' => $media);
|
return array('css' => $css, 'media' => self::$_media);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function _media_concat( $matches ) {
|
||||||
|
self::$_media .= $matches[0];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a DOMDocument instance with the current HTML.
|
* Creates a DOMDocument instance with the current HTML.
|
||||||
*
|
*
|
||||||
* @return \DOMDocument
|
* @return DOMDocument
|
||||||
*/
|
*/
|
||||||
private function createXmlDocument() {
|
private function createXmlDocument() {
|
||||||
$xmlDocument = new \DOMDocument;
|
$xmlDocument = new DOMDocument;
|
||||||
$xmlDocument->encoding = self::ENCODING;
|
$xmlDocument->encoding = self::ENCODING;
|
||||||
$xmlDocument->strictErrorChecking = FALSE;
|
$xmlDocument->strictErrorChecking = FALSE;
|
||||||
$xmlDocument->formatOutput = TRUE;
|
$xmlDocument->formatOutput = TRUE;
|
||||||
|
@ -528,7 +525,7 @@ class Emogrifier {
|
||||||
*
|
*
|
||||||
* @return string the unified HTML
|
* @return string the unified HTML
|
||||||
*
|
*
|
||||||
* @throws \BadMethodCallException
|
* @throws BadMethodCallException
|
||||||
*/
|
*/
|
||||||
private function getUnifiedHtml() {
|
private function getUnifiedHtml() {
|
||||||
if (!empty($this->unprocessableHtmlTags)) {
|
if (!empty($this->unprocessableHtmlTags)) {
|
||||||
|
@ -600,12 +597,7 @@ class Emogrifier {
|
||||||
*/
|
*/
|
||||||
private function translateCssToXpath($paramCssSelector) {
|
private function translateCssToXpath($paramCssSelector) {
|
||||||
$cssSelector = ' ' . $paramCssSelector . ' ';
|
$cssSelector = ' ' . $paramCssSelector . ' ';
|
||||||
$cssSelector = preg_replace_callback('/\s+\w+\s+/',
|
$cssSelector = preg_replace_callback( '/\s+\w+\s+/', array( $this, 'strtolower' ), $cssSelector );
|
||||||
function(array $matches) {
|
|
||||||
return strtolower($matches[0]);
|
|
||||||
},
|
|
||||||
$cssSelector
|
|
||||||
);
|
|
||||||
$cssSelector = trim($cssSelector);
|
$cssSelector = trim($cssSelector);
|
||||||
$xpathKey = md5($cssSelector);
|
$xpathKey = md5($cssSelector);
|
||||||
if (!isset($this->caches[self::CACHE_KEY_XPATH][$xpathKey])) {
|
if (!isset($this->caches[self::CACHE_KEY_XPATH][$xpathKey])) {
|
||||||
|
|
Loading…
Reference in New Issue