Merge pull request #781 from mailpoet/form_css_fix

Fixes some from CSS styles not being saved [MAILPOET-784]
This commit is contained in:
Tautvidas Sipavičius
2017-01-16 15:28:42 +02:00
committed by GitHub
6 changed files with 391 additions and 402 deletions

View File

@ -14,7 +14,8 @@
"swiftmailer/swiftmailer": "^5.4", "swiftmailer/swiftmailer": "^5.4",
"mtdowling/cron-expression": "^1.1", "mtdowling/cron-expression": "^1.1",
"nesbot/carbon": "^1.21", "nesbot/carbon": "^1.21",
"soundasleep/html2text": "dev-master" "soundasleep/html2text": "dev-master",
"sabberworm/php-css-parser": "^8.1"
}, },
"require-dev": { "require-dev": {
"codeception/codeception": "*", "codeception/codeception": "*",
@ -37,4 +38,4 @@
"post-update-cmd": "rm -rf vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PHPCompatibility; cp -rpd vendor/wimg/php-compatibility vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PHPCompatibility", "post-update-cmd": "rm -rf vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PHPCompatibility; cp -rpd vendor/wimg/php-compatibility vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PHPCompatibility",
"post-install-cmd": "rm -rf vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PHPCompatibility; cp -rpd vendor/wimg/php-compatibility vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PHPCompatibility" "post-install-cmd": "rm -rf vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PHPCompatibility; cp -rpd vendor/wimg/php-compatibility vendor/squizlabs/php_codesniffer/CodeSniffer/Standards/PHPCompatibility"
} }
} }

606
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -35,7 +35,7 @@ class Renderer {
&& strlen(trim($form['styles'])) > 0) { && strlen(trim($form['styles'])) > 0) {
return strip_tags($form['styles']); return strip_tags($form['styles']);
} else { } else {
return Util\Styles::$defaults; return Util\Styles::$default_styles;
} }
} }

View File

@ -1,11 +1,11 @@
<?php <?php
namespace MailPoet\Form\Util; namespace MailPoet\Form\Util;
class Styles { use Sabberworm\CSS\Parser as CSSParser;
private $_stylesheet = null;
private $_styles = array();
static $defaults =<<<EOL class Styles {
public $styles;
static $default_styles = <<<EOL
/* form */ /* form */
.mailpoet_form { .mailpoet_form {
@ -49,130 +49,25 @@ class Styles {
EOL; EOL;
function __construct($stylesheet = null) { function __construct($stylesheet = null) {
// store raw styles $this->stylesheet = $stylesheet;
$this->setStylesheet($stylesheet);
// extract rules/properties
$this->parseStyles();
return $this;
} }
function render($prefix = '') { function render($prefix = '') {
$styles = $this->getStyles(); if(!$this->stylesheet) return;
if(!empty($styles)) { $styles = new CSSParser($this->stylesheet);
$output = array(); $styles = $styles->parse();
$formatted_styles = array();
// add prefix on each selector foreach($styles->getAllDeclarationBlocks() as $style_declaration) {
foreach($styles as $style) { $selectors = array_map(function($selector) use ($prefix) {
// check if selector is an array return sprintf('%s %s', $prefix, $selector->__toString());
if(is_array($style['selector'])) { }, $style_declaration->getSelectors());
$selector = join(",\n", array_map(function($value) use ($prefix) { $selectors = implode(', ', $selectors);
return $prefix.' '.$value; $rules = array_map(function($rule) {
}, $style['selector'])); return $rule->__toString();
} else { }, $style_declaration->getRules());
$selector = $prefix.' '.$style['selector']; $rules = sprintf('{ %s }', implode(' ', $rules));
} $formatted_styles[] = sprintf('%s %s', $selectors, $rules);
// format selector
$output[] = $selector . ' {';
// format rules
if(!empty($style['rules'])) {
$rules = join("\n", array_map(function($rule) {
return "\t".$rule['property'] . ': ' . $rule['value'].';';
}, $style['rules']));
$output[] = $rules;
}
$output[] = '}';
}
return join("\n", $output);
} }
return implode(PHP_EOL, $formatted_styles);
} }
}
private function setStylesheet($stylesheet) {
$this->_stylesheet = $this->stripComments($stylesheet);
return $this;
}
private function stripComments($stylesheet) {
// remove comments
return preg_replace('!/\*.*?\*/!s', '', $stylesheet);
}
private function getStylesheet() {
return $this->_stylesheet;
}
private function setStyles($styles) {
$this->_styles = $styles;
return $this;
}
private function getStyles() {
return $this->_styles;
}
private function parseStyles() {
if($this->getStylesheet() !== null) {
// extract selectors and rules
preg_match_all( '/(?ims)([a-z0-9\s\.\:#_\-@,]+)\{([^\}]*)\}/',
$this->getStylesheet(),
$matches
);
$selectors = $matches[1];
$rules = $matches[2];
// extracted styles
$styles = array();
// loop through each selector
foreach($selectors as $index => $selector) {
// trim selector
$selector = trim($selector);
// get selector rules
$selector_rules = array_filter(array_map(function($value) {
if(strlen(trim($value)) > 0) {
// split property / value
$pair = explode(':', trim($value));
if(isset($pair[0]) && isset($pair[1])) {
return array(
'property' => $pair[0],
'value' => $pair[1]
);
}
}
}, explode(';', trim($rules[$index]))));
// check if we have multiple selectors
if(strpos($selector, ',') !== false) {
$selectors_array = array_filter(array_map(function($value) {
return trim($value);
}, explode(',', $selector)));
// multiple selectors
$styles[$index] = array(
'selector' => $selectors_array,
'rules' => $selector_rules
);
} else {
// it's a single selector
$styles[$index] = array(
'selector' => $selector,
'rules' => $selector_rules
);
}
}
$this->setStyles($styles);
}
}
function __toString() {
$this->stripComments();
return $this->render();
}
}

View File

@ -0,0 +1,28 @@
<?php
use MailPoet\Form\Util\Styles;
class StylesTest extends MailPoetTest {
function testItSetsDefaultCSSStyles() {
expect(property_exists('MailPoet\Form\Util\Styles', 'default_styles'))->true();
expect(Styles::$default_styles)->notEmpty();
}
function testItProcessesAndRendersStyles() {
$stylesheet = '
/* some comment */
input[name=first_name] , input.some_class, .some_class { color: red ; background: blue; } .another_style { fonT-siZe: 20px }
';
$style_processer = new Styles($stylesheet);
$extracted_and_prefixed_styles = $style_processer->render($prefix = 'mailpoet');
// 1. comments should be stripped
// 2. each selector should be refixed
// 3. multiple spaces, missing semicolons should be fixed
// 4. each style should be on a separate line
$expected_result = <<<EOL
mailpoet input[name=first_name], mailpoet input.some_class, mailpoet .some_class { color: red; background: blue; }
mailpoet .another_style { font-size: 20px; }
EOL;
expect($extracted_and_prefixed_styles)->equals($expected_result);
}
}

View File

@ -4,7 +4,8 @@ use MailPoet\Util\License\License;
class LicenseTest extends MailPoetTest { class LicenseTest extends MailPoetTest {
function testItGetsLicense() { function testItGetsLicense() {
expect(License::getLicense())->false(); if(defined('MAILPOET_PREMIUM_LICENSE')) return;
expect(License::getLicense('valid'))->equals('valid'); expect(License::getLicense())->false();
expect(License::getLicense('valid'))->equals('valid');
} }
} }