// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
- * This file contains CSS related methods and a CSS optimiser
+ * This file contains CSS related class, and function for the CSS optimiser
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * Please see the {@see css_optimiser} class for greater detail.
+ *
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Stores CSS in a file at the given path.
*
+ * This function either succeeds or throws an exception.
+ *
* @param theme_config $theme
* @param string $csspath
* @param array $cssfiles
function css_store_css(theme_config $theme, $csspath, array $cssfiles) {
global $CFG;
- if (!empty($CFG->cssoptimise)) {
+ if (!empty($CFG->enablecssoptimiser)) {
// This is an experimental feature introduced in Moodle 2.2
// The CSS optimiser organises the CSS in order to reduce the overall number
// of rules and styles being sent to the client. It does this by collating
// If cssoptimisestats is set then stats from the optimisation are collected
// and output at the beginning of the CSS
- if (!empty($CFG->cssoptimisestats)) {
+ if (!empty($CFG->cssoptimiserstats)) {
$css = $optimiser->output_stats_css().$css;
}
} else {
$fp = fopen($csspath, 'w');
fwrite($fp, $css);
fclose($fp);
- return true;
}
/**
* Sends IE specific CSS
*
- * @param string $themename
- * @param string $rev
+ * In writing the CSS parser I have a theory that we could optimise the CSS
+ * then split it based upon the number of selectors to ensure we dont' break IE
+ * and that we include only as many sub-stylesheets as we require.
+ * Of course just a theory but may be fun to code.
+ *
+ * @param string $themename The name of the theme we are sending CSS for.
+ * @param string $rev The revision to ensure we utilise the cache.
*/
function css_send_ie_css($themename, $rev) {
$lifetime = 60*60*24*30; // 30 days
/**
* Sends a cached CSS file
*
- * @param string $csspath
- * @param string $rev
+ * This function sends the cached CSS file. Remember it is generate on the first
+ * request, then optimised/minified, and finally cached for serving.
+ *
+ * @param string $csspath The path to the CSS file we want to serve.
+ * @param string $rev The revision to make sure we utilise any caches.
*/
function css_send_cached_css($csspath, $rev) {
$lifetime = 60*60*24*30; // 30 days
/**
* Sends CSS directly without caching it.
*
+ * This function takes a raw CSS string, optimises it if required, and then
+ * serves it.
+ * Turning both themedesignermode and CSS optimiser on at the same time is aweful
+ * for performance because of the optimiser running here. However it was done so
+ * that theme designers could utilise the optimised output during development to
+ * help them optimise their CSS... not that they should write lazy CSS.
+ *
* @param string CSS
*/
function css_send_uncached_css($css) {
$css = implode("\n\n", $css);
}
- if (!empty($CFG->cssoptimise) && !empty($CFG->cssoptimisedebug)) {
+ if (!empty($CFG->enablecssoptimiser)) {
$css = str_replace("\n", "\r\n", $css);
$optimiser = new css_optimiser;
$css = $optimiser->process($css);
- if (!empty($CFG->cssoptimisestats)) {
+ if (!empty($CFG->cssoptimiserstats)) {
$css = $optimiser->output_stats_css().$css;
}
}
/**
* Uses the minify library to compress CSS.
*
- * This is used if $CFG->cssoptimise has been turned off. This was
+ * This is used if $CFG->enablecssoptimiser has been turned off. This was
* the original CSS optimisation library.
+ * It removes whitespace and shrinks things but does no apparent optimisation.
+ * Note the minify library is still being used for JavaScript.
*
* @param array $files An array of files to minify
* @return string The minified CSS
}
/**
- * Given a value determines if it is a valid CSS colour
+ * Given a value determines if it is a valid CSS colour.
+ *
+ * A CSS colour can be one of the following:
+ * - Hex colour: #AA66BB
+ * - RGB colour: rgb(0-255, 0-255, 0-255)
+ * - RGBA colour: rgb(0-255, 0-255, 0-255, 0-1)
+ * - HSL colour: rgb(0-360, 0-100%, 0-100%)
+ * - HSLA colour: rgb(0-360, 0-100%, 0-100%, 0-1)
+ *
+ * Or a regocnised browser colour mapping {@see css_optimiser::$htmlcolours}
*
- * @param string $value
+ * @param string $value The colour value to check
* @return bool
*/
function css_is_colour($value) {
$value = trim($value);
- if (preg_match('/^#([a-fA-F0-9]{1,6})$/', $value)) {
+ if (in_array(strtolower($value), array('inherit'))) {
+ return true;
+ } else if (preg_match('/^#([a-fA-F0-9]{1,6})$/', $value)) {
return true;
} else if (in_array(strtolower($value), array_keys(css_optimiser::$htmlcolours))) {
return true;
- } else if (preg_match('#^(rgb|hsl)\s*\(\s*\d{1,3}\%?\s*,\s*\d{1,3}\%?\s*,\s*\d{1,3}\%?\s*\)$#', $value)) {
+ } else if (preg_match('#^(rgb)\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$#i', $value, $m) && $m[2] < 256 && $m[3] < 256 && $m[4] < 256) {
+ // It is an RGB colour
+ return true;
+ } else if (preg_match('#^(rgba)\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1}(\.\d+)?)\s*\)$#i', $value, $m) && $m[2] < 256 && $m[3] < 256 && $m[4] < 256) {
+ // It is an RGBA colour
+ return true;
+ } else if (preg_match('#^(hsl)\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\%\s*,\s*(\d{1,3})\%\s*\)$#i', $value, $m) && $m[2] <= 360 && $m[3] <= 100 && $m[4] <= 100) {
+ // It is an HSL colour
+ return true;
+ } else if (preg_match('#^(hsla)\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\%\s*,\s*(\d{1,3})\%\s*,\s*(\d{1}(\.\d+)?)\s*\)$#i', $value, $m) && $m[2] <= 360 && $m[3] <= 100 && $m[4] <= 100) {
+ // It is an HSLA colour
+ return true;
+ }
+ // Doesn't look like a colour.
+ return false;
+}
+
+/**
+ * Returns true is the passed value looks like a CSS width.
+ * In order to pass this test the value must be purely numerical or end with a
+ * valid CSS unit term.
+ *
+ * @param string|int $value
+ * @return boolean
+ */
+function css_is_width($value) {
+ $value = trim($value);
+ if (in_array(strtolower($value), array('auto', 'inherit'))) {
return true;
- } else if (preg_match('#^(rgb|hsl)a\s*\(\s*\d{1,3}\%?\s*,\s*\d{1,3}\%?\s*,\s*\d{1,3}\%?\s*,\s*\d(\.\d+)?\s*\)$#', $value)) {
+ }
+ if (preg_match('#^(\-\s*)?(\d*\.)?(\d+)\s*(em|px|pt|%|in|cm|mm|ex|pc)?$#i', $value)) {
return true;
}
return false;
* A basic CSS optimiser that strips out unwanted things and then processing the
* CSS organising styles and moving duplicates and useless CSS.
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * This CSS optimiser works by reading through a CSS string one character at a
+ * time and building an object structure of the CSS.
+ * As part of that processing styles are expanded out as much as they can be to
+ * ensure we collect all mappings, at the end of the processing those styles are
+ * then combined into an optimised form to keep them as short as possible.
+ *
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class css_optimiser {
protected $timecomplete = 0;
/**#@-*/
+ /**
+ * Will be set to any errors that may have occured during processing.
+ * This is updated only at the end of processing NOT during.
+ *
+ * @var array()
+ */
+ protected $errors = array();
+
/**
* Processes incoming CSS optimising it and then returning it.
*
$media->organise_rules_by_selectors();
$this->optimisedrules += $media->count_rules();
$this->optimisedselectors += $media->count_selectors();
+ if ($media->has_errors()) {
+ $this->errors[] = $media->get_errors();
+ }
$css .= $media->out();
}
$this->optimisedstrlen = strlen($css);
return $stats;
}
+ /**
+ * Returns true if any errors have occured during processing
+ *
+ * @return bool
+ */
+ public function has_errors() {
+ return !empty($this->errors);
+ }
+
+ /**
+ * Returns an array of errors that have occured
+ *
+ * @return array
+ */
+ public function get_errors() {
+ return $this->errors;
+ }
+
+ /**
+ * Returns any errors as a string that can be included in CSS.
+ *
+ * @return string
+ */
+ public function output_errors_css() {
+ $computedcss = "/****************************************\n";
+ $computedcss .= " *--- Errors found during processing ----\n";
+ foreach ($this->errors as $error) {
+ $computedcss .= preg_replace('#^#m', '* ', $error);
+ }
+ $computedcss .= " ****************************************/\n\n";
+ return $computedcss;
+ }
+
/**
* Returns a string to display stats about the last generation within CSS output
+ *
* @return string
*/
public function output_stats_css() {
'teal' => '#008080',
'thistle' => '#D8BFD8',
'tomato' => '#FF6347',
+ 'transparent' => 'transparent',
'turquoise' => '#40E0D0',
'violet' => '#EE82EE',
'wheat' => '#F5DEB3',
/**
* Used to prepare CSS strings
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class css_writer {
*/
protected static function is_pretty() {
global $CFG;
- return (!empty($CFG->cssoptimisepretty));
+ return (!empty($CFG->cssoptimiserpretty));
}
/**
}
/**
- * Descreases the current indent
+ * Decreases the current indent
*/
protected static function decrease_indent() {
self::$indent--;
* The selector is the classes, id, elements, and psuedo bits that make up a CSS
* rule.
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class css_selector {
/**
* A structure to represent a CSS rule.
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class css_rule {
}
/**
- * Constructs a new css rule - this can only be called from within the scope of
- * this class or its descendants.
+ * Constructs a new css rule.
*
- * @param type $selector
+ * @param string $selector
* @param array $styles
*/
protected function __construct($selector = null, array $styles = array()) {
}
return $count;
}
+
+ /**
+ * Returns true if there are any errors with this rule.
+ *
+ * @return bool
+ */
+ public function has_errors() {
+ foreach ($this->styles as $style) {
+ if ($style->has_error()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public function get_error_string() {
+ $css = $this->out();
+ $errors = array();
+ foreach ($this->styles as $style) {
+ if ($style->has_error()) {
+ $errors[] = " * ".$style->get_last_error();
+ }
+ }
+ return $css." has the following errors:\n".join("\n", $errors);
+
+ }
}
/**
* A media class to organise rules by the media they apply to.
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class css_media {
/**
* Initalises a new media instance
*
- * @param type $for
+ * @param string $for
*/
public function __construct($for = 'all') {
$types = explode(',', $for);
* Organises rules by gropuing selectors based upon the styles and consolidating
* those selectors into single rules.
*
- * @return array An array of optimised styles
+ * @return bool True if the CSS was optimised by this method
*/
public function organise_rules_by_selectors() {
$optimised = array();
public function get_types() {
return $this->types;
}
+
+ /**
+ * Returns true if the media has any rules that have errors
+ *
+ * @return boolean
+ */
+ public function has_errors() {
+ foreach ($this->rules as $rule) {
+ if ($rule->has_errors()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns any errors that have happened within rules in this media set.
+ *
+ * @return string
+ */
+ public function get_errors() {
+ $errors = array();
+ foreach ($this->rules as $rule) {
+ if ($rule->has_errors()) {
+ $errors[] = $rule->get_error_string();
+ }
+ }
+ return join("\n", $errors);
+ }
}
/**
* An absract class to represent CSS styles
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class css_style {
*/
protected $important = false;
+ /**
+ * Gets set to true if this style has an error
+ * @var bool
+ */
+ protected $error = false;
+
+ /**
+ * The last error message that occured
+ * @var string
+ */
+ protected $errormessage = null;
+
+
/**
* Initialises a new style.
*
* This is the only public way to create a style to ensure they that appropriate
* style class is used if it exists.
*
- * @param type $name
- * @param type $value
+ * @param string $name
+ * @param string $value
* @return css_style_generic
*/
public static function init($name, $value) {
$this->value = $this->clean_value($value);
$this->important = $important;
}
+ if (!$this->is_valid()) {
+ $this->set_error('Invalid value for '.$this->name);
+ }
}
/**
public function consolidate_to() {
return null;
}
+
+ /**
+ * Sets the last error message.
+ *
+ * @param type $message
+ */
+ protected function set_error($message) {
+ $this->error = true;
+ $this->errormessage = $message;
+ }
+
+ /**
+ * Returns true if an error has occured
+ * @return bool
+ */
+ public function has_error() {
+ return $this->error;
+ }
+
+ /**
+ * Returns the last error that occured or null if no errors have happened.
+ *
+ * @return string
+ */
+ public function get_last_error() {
+ return $this->errormessage;
+ }
}
/**
* A generic CSS style class to use when a more specific class does not exist.
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class css_style_generic extends css_style {
/**
* A colour CSS style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class css_style_color extends css_style {
}
}
+/**
+ * A width style
+ *
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class css_style_width extends css_style {
+
+ /**
+ * Checks if the width is valid
+ * @return bool
+ */
+ public function is_valid() {
+ return css_is_width($this->value);
+ }
+
+ /**
+ * Cleans the provided value
+ *
+ * @param mixed $value
+ * @return string
+ */
+ protected function clean_value($value) {
+ if (!css_is_width($value)) {
+ // Note we don't actually change the value to something valid. That
+ // would be bad for futureproofing.
+ $this->set_error('Invalid width specified for '.$this->name);
+ } else if (preg_match('#^0\D+$#', $value)) {
+ $value = 0;
+ }
+ return trim($value);
+ }
+
+ /**
+ * Initialises a new width style
+ *
+ * @param type $value
+ * @return css_style_width
+ */
+ public static function init($value) {
+ return new css_style_width('width', $value);
+ }
+}
+
/**
* A margin style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_margin extends css_style {
+class css_style_margin extends css_style_width {
/**
* Initialises a margin style.
* @return array An array of margin values that can later be consolidated
*/
public static function init($value) {
- $value = preg_replace('#\s+#', ' ', $value);
+ $important = '';
+ if (strpos($value, '!important') !== false) {
+ $important = ' !important';
+ $value = str_replace('!important', '', $value);
+ }
+
+ $value = preg_replace('#\s+#', ' ', trim($value));
$bits = explode(' ', $value, 4);
$top = $right = $bottom = $left = null;
$left = array_shift($bits);
}
return array(
- new css_style_margintop('margin-top', $top),
- new css_style_marginright('margin-right', $right),
- new css_style_marginbottom('margin-bottom', $bottom),
- new css_style_marginleft('margin-left', $left)
+ new css_style_margintop('margin-top', $top.$important),
+ new css_style_marginright('margin-right', $right.$important),
+ new css_style_marginbottom('margin-bottom', $bottom.$important),
+ new css_style_marginleft('margin-left', $left.$important)
);
}
/**
* A margin top style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_margintop extends css_style {
+class css_style_margintop extends css_style_margin {
/**
* A simple init, just a single style
*
/**
* A margin right style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_marginright extends css_style {
+class css_style_marginright extends css_style_margin {
+
/**
* A simple init, just a single style
*
public static function init($value) {
return new css_style_marginright('margin-right', $value);
}
+
/**
* This style can be consolidated into a single margin style
*
/**
* A margin bottom style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_marginbottom extends css_style {
+class css_style_marginbottom extends css_style_margin {
+
/**
* A simple init, just a single style
*
public static function init($value) {
return new css_style_marginbottom('margin-bottom', $value);
}
+
/**
* This style can be consolidated into a single margin style
*
/**
* A margin left style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_marginleft extends css_style {
+class css_style_marginleft extends css_style_margin {
+
/**
* A simple init, just a single style
*
public static function init($value) {
return new css_style_marginleft('margin-left', $value);
}
+
/**
* This style can be consolidated into a single margin style
*
/**
* A border style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class css_style_border extends css_style {
+
/**
* Initalises the border style into an array of individual style compontents
*
$return = array();
if (count($bits) > 0) {
$width = array_shift($bits);
- $return[] = new css_style_borderwidth('border-width-top', $width);
- $return[] = new css_style_borderwidth('border-width-right', $width);
- $return[] = new css_style_borderwidth('border-width-bottom', $width);
- $return[] = new css_style_borderwidth('border-width-left', $width);
+ if (!css_is_width($width)) {
+ $width = '0';
+ }
+ $return[] = new css_style_borderwidth('border-top-width', $width);
+ $return[] = new css_style_borderwidth('border-right-width', $width);
+ $return[] = new css_style_borderwidth('border-bottom-width', $width);
+ $return[] = new css_style_borderwidth('border-left-width', $width);
}
if (count($bits) > 0) {
$style = array_shift($bits);
- $return[] = new css_style_borderstyle('border-style-top', $style);
- $return[] = new css_style_borderstyle('border-style-right', $style);
- $return[] = new css_style_borderstyle('border-style-bottom', $style);
- $return[] = new css_style_borderstyle('border-style-left', $style);
+ $return[] = new css_style_borderstyle('border-top-style', $style);
+ $return[] = new css_style_borderstyle('border-right-style', $style);
+ $return[] = new css_style_borderstyle('border-bottom-style', $style);
+ $return[] = new css_style_borderstyle('border-left-style', $style);
}
if (count($bits) > 0) {
$colour = array_shift($bits);
- $return[] = new css_style_bordercolor('border-color-top', $colour);
- $return[] = new css_style_bordercolor('border-color-right', $colour);
- $return[] = new css_style_bordercolor('border-color-bottom', $colour);
- $return[] = new css_style_bordercolor('border-color-left', $colour);
+ $return[] = new css_style_bordercolor('border-top-color', $colour);
+ $return[] = new css_style_bordercolor('border-right-color', $colour);
+ $return[] = new css_style_bordercolor('border-bottom-color', $colour);
+ $return[] = new css_style_bordercolor('border-left-color', $colour);
}
return $return;
}
+
/**
* Consolidates all border styles into a single style
*
foreach ($styles as $style) {
switch ($style->get_name()) {
- case 'border-width-top': $borderwidths['top'] = $style->get_value(); break;
- case 'border-width-right': $borderwidths['right'] = $style->get_value(); break;
- case 'border-width-bottom': $borderwidths['bottom'] = $style->get_value(); break;
- case 'border-width-left': $borderwidths['left'] = $style->get_value(); break;
-
- case 'border-style-top': $borderstyles['top'] = $style->get_value(); break;
- case 'border-style-right': $borderstyles['right'] = $style->get_value(); break;
- case 'border-style-bottom': $borderstyles['bottom'] = $style->get_value(); break;
- case 'border-style-left': $borderstyles['left'] = $style->get_value(); break;
-
- case 'border-color-top': $bordercolors['top'] = $style->get_value(); break;
- case 'border-color-right': $bordercolors['right'] = $style->get_value(); break;
- case 'border-color-bottom': $bordercolors['bottom'] = $style->get_value(); break;
- case 'border-color-left': $bordercolors['left'] = $style->get_value(); break;
+ case 'border-top-width': $borderwidths['top'] = $style->get_value(); break;
+ case 'border-right-width': $borderwidths['right'] = $style->get_value(); break;
+ case 'border-bottom-width': $borderwidths['bottom'] = $style->get_value(); break;
+ case 'border-left-width': $borderwidths['left'] = $style->get_value(); break;
+
+ case 'border-top-style': $borderstyles['top'] = $style->get_value(); break;
+ case 'border-right-style': $borderstyles['right'] = $style->get_value(); break;
+ case 'border-bottom-style': $borderstyles['bottom'] = $style->get_value(); break;
+ case 'border-left-style': $borderstyles['left'] = $style->get_value(); break;
+
+ case 'border-top-color': $bordercolors['top'] = $style->get_value(); break;
+ case 'border-right-color': $bordercolors['right'] = $style->get_value(); break;
+ case 'border-bottom-color': $bordercolors['bottom'] = $style->get_value(); break;
+ case 'border-left-color': $bordercolors['left'] = $style->get_value(); break;
}
}
$uniquestyles = count(array_unique($borderstyles));
$uniquecolors = count(array_unique($bordercolors));
- $nullwidths = in_array(null, $borderwidths);
- $nullstyles = in_array(null, $borderstyles);
- $nullcolors = in_array(null, $bordercolors);
+ $nullwidths = in_array(null, $borderwidths, true);
+ $nullstyles = in_array(null, $borderstyles, true);
+ $nullcolors = in_array(null, $bordercolors, true);
$allwidthsthesame = ($uniquewidths === 1)?1:0;
$allstylesthesame = ($uniquestyles === 1)?1:0;
}
return $return;
}
+
/**
* Border styles get consolidated to a single border style.
*
public function consolidate_to() {
return 'border';
}
+
/**
*
* @param array $array An array to add styles into during consolidation. Passed by reference.
}
if ($top == $bottom && $left == $right && $top == $left) {
- if ($top == null) {
+ if (is_null($top)) {
$array[] = new $class($style, '');
} else {
$array[] = new $class($style, $top);
}
} else if ($top == null || $right == null || $bottom == null || $left == null) {
if ($top !== null) {
- $array[] = new $class($style.'-top', $top);
+ $array[] = new $class(str_replace('border-', 'border-top-', $style), $top);
}
if ($right !== null) {
- $array[] = new $class($style.'-right', $right);
+ $array[] = new $class(str_replace('border-', 'border-right-', $style), $right);
}
if ($bottom !== null) {
- $array[] = new $class($style.'-bottom', $bottom);
+ $array[] = new $class(str_replace('border-', 'border-bottom-', $style), $bottom);
}
if ($left !== null) {
- $array[] = new $class($style.'-left', $left);
+ $array[] = new $class(str_replace('border-', 'border-left-', $style), $left);
}
} else if ($top == $bottom && $left == $right) {
$array[] = new $class($style, $top.' '.$right);
} else if (!is_null($width) && !is_null($style) && is_null($color)) {
$array[] = new $class($cssstyle, $width.' '.$style);
} else if (!is_null($width) && is_null($style) && is_null($color)) {
- $array[] = new $class($cssstyle.'-width', $width);
+ $array[] = new $class($cssstyle, $width);
} else {
- if (!is_null($width)) $array[] = new $class($cssstyle.'-width', $width);
- if (!is_null($style)) $array[] = new $class($cssstyle.'-style', $style);
- if (!is_null($color)) $array[] = new $class($cssstyle.'-color', $color);
+ if (!is_null($width)) $array[] = new $class($cssstyle, $width);
+ if (!is_null($style)) $array[] = new $class($cssstyle, $style);
+ if (!is_null($color)) $array[] = new $class($cssstyle, $color);
}
return true;
}
/**
* A border colour style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class css_style_bordercolor extends css_style_color {
+
/**
* Creates a new border colour style
*
$left = array_shift($bits);
}
return array(
- css_style_bordercolortop::init($top),
- css_style_bordercolorright::init($right),
- css_style_bordercolorbottom::init($bottom),
- css_style_bordercolorleft::init($left)
+ css_style_bordertopcolor::init($top),
+ css_style_borderrightcolor::init($right),
+ css_style_borderbottomcolor::init($bottom),
+ css_style_borderleftcolor::init($left)
);
}
+
/**
* Consolidate this to a single border style
*
public function consolidate_to() {
return 'border';
}
+
/**
* Cleans the value
*
$values = array_map('parent::clean_value', $values);
return join (' ', $values);
}
+
/**
* Outputs this style
*
/**
* A border left style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class css_style_borderleft extends css_style_generic {
+
/**
* Initialises the border left style into individual components
*
* @param string $value
- * @return css_style_borderwidthleft|css_style_borderstyleleft|css_style_bordercolorleft
+ * @return css_style_borderleftwidth|css_style_borderleftstyle|css_style_borderleftcolor
*/
public static function init($value) {
$value = preg_replace('#\s+#', ' ', $value);
$return = array();
if (count($bits) > 0) {
- $return[] = css_style_borderwidthleft::init(array_shift($bits));
+ $return[] = css_style_borderleftwidth::init(array_shift($bits));
}
if (count($bits) > 0) {
- $return[] = css_style_borderstyleleft::init(array_shift($bits));
+ $return[] = css_style_borderleftstyle::init(array_shift($bits));
}
if (count($bits) > 0) {
- $return[] = css_style_bordercolorleft::init(array_shift($bits));
+ $return[] = css_style_borderleftcolor::init(array_shift($bits));
}
return $return;
}
+
/**
* Consolidate this to a single border style
*
/**
* A border right style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class css_style_borderright extends css_style_generic {
+
/**
* Initialises the border right style into individual components
*
* @param string $value
- * @return css_style_borderwidthright|css_style_borderstyleright|css_style_bordercolorright
+ * @return css_style_borderrightwidth|css_style_borderrightstyle|css_style_borderrightcolor
*/
public static function init($value) {
$value = preg_replace('#\s+#', ' ', $value);
$return = array();
if (count($bits) > 0) {
- $return[] = css_style_borderwidthright::init(array_shift($bits));
+ $return[] = css_style_borderrightwidth::init(array_shift($bits));
}
if (count($bits) > 0) {
- $return[] = css_style_borderstyleright::init(array_shift($bits));
+ $return[] = css_style_borderrightstyle::init(array_shift($bits));
}
if (count($bits) > 0) {
- $return[] = css_style_bordercolorright::init(array_shift($bits));
+ $return[] = css_style_borderrightcolor::init(array_shift($bits));
}
return $return;
}
+
/**
* Consolidate this to a single border style
*
/**
* A border top style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class css_style_bordertop extends css_style_generic {
+
/**
* Initialises the border top style into individual components
*
* @param string $value
- * @return css_style_borderwidthtop|css_style_borderstyletop|css_style_bordercolortop
+ * @return css_style_bordertopwidth|css_style_bordertopstyle|css_style_bordertopcolor
*/
public static function init($value) {
$value = preg_replace('#\s+#', ' ', $value);
$return = array();
if (count($bits) > 0) {
- $return[] = css_style_borderwidthtop::init(array_shift($bits));
+ $return[] = css_style_bordertopwidth::init(array_shift($bits));
}
if (count($bits) > 0) {
- $return[] = css_style_borderstyletop::init(array_shift($bits));
+ $return[] = css_style_bordertopstyle::init(array_shift($bits));
}
if (count($bits) > 0) {
- $return[] = css_style_bordercolortop::init(array_shift($bits));
+ $return[] = css_style_bordertopcolor::init(array_shift($bits));
}
return $return;
}
+
/**
* Consolidate this to a single border style
*
/**
* A border bottom style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class css_style_borderbottom extends css_style_generic {
+
/**
* Initialises the border bottom style into individual components
*
* @param string $value
- * @return css_style_borderwidthbottom|css_style_borderstylebottom|css_style_bordercolorbottom
+ * @return css_style_borderbottomwidth|css_style_borderbottomstyle|css_style_borderbottomcolor
*/
public static function init($value) {
$value = preg_replace('#\s+#', ' ', $value);
$return = array();
if (count($bits) > 0) {
- $return[] = css_style_borderwidthbottom::init(array_shift($bits));
+ $return[] = css_style_borderbottomwidth::init(array_shift($bits));
}
if (count($bits) > 0) {
- $return[] = css_style_borderstylebottom::init(array_shift($bits));
+ $return[] = css_style_borderbottomstyle::init(array_shift($bits));
}
if (count($bits) > 0) {
- $return[] = css_style_bordercolorbottom::init(array_shift($bits));
+ $return[] = css_style_borderbottomcolor::init(array_shift($bits));
}
return $return;
}
+
/**
* Consolidate this to a single border style
*
/**
* A border width style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_borderwidth extends css_style_generic {
+class css_style_borderwidth extends css_style_width {
+
/**
* Creates a new border colour style
*
$left = array_shift($bits);
}
return array(
- css_style_borderwidthtop::init($top),
- css_style_borderwidthright::init($right),
- css_style_borderwidthbottom::init($bottom),
- css_style_borderwidthleft::init($left)
+ css_style_bordertopwidth::init($top),
+ css_style_borderrightwidth::init($right),
+ css_style_borderbottomwidth::init($bottom),
+ css_style_borderleftwidth::init($left)
);
}
+
/**
* Consolidate this to a single border style
*
/**
* A border style style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class css_style_borderstyle extends css_style_generic {
+
/**
* Creates a new border colour style
*
$left = array_shift($bits);
}
return array(
- css_style_borderstyletop::init($top),
- css_style_borderstyleright::init($right),
- css_style_borderstylebottom::init($bottom),
- css_style_borderstyleleft::init($left)
+ css_style_bordertopstyle::init($top),
+ css_style_borderrightstyle::init($right),
+ css_style_borderbottomstyle::init($bottom),
+ css_style_borderleftstyle::init($left)
);
}
+
/**
* Consolidate this to a single border style
*
/**
* A border top colour style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_bordercolortop extends css_style_color {
+class css_style_bordertopcolor extends css_style_bordercolor {
+
/**
* Initialises this style object
*
* @param string $value
- * @return css_style_bordercolortop
+ * @return css_style_bordertopcolor
*/
public static function init($value) {
- return new css_style_bordercolortop('border-color-top', $value);
+ return new css_style_bordertopcolor('border-top-color', $value);
}
+
/**
* Consolidate this to a single border style
*
/**
* A border left colour style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_bordercolorleft extends css_style_color {
+class css_style_borderleftcolor extends css_style_bordercolor {
+
/**
* Initialises this style object
*
* @param string $value
- * @return css_style_bordercolorleft
+ * @return css_style_borderleftcolor
*/
public static function init($value) {
- return new css_style_bordercolorleft('border-color-left', $value);
+ return new css_style_borderleftcolor('border-left-color', $value);
}
+
/**
* Consolidate this to a single border style
*
/**
* A border right colour style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_bordercolorright extends css_style_color {
+class css_style_borderrightcolor extends css_style_bordercolor {
+
/**
* Initialises this style object
*
* @param string $value
- * @return css_style_bordercolorright
+ * @return css_style_borderrightcolor
*/
public static function init($value) {
- return new css_style_bordercolorright('border-color-right', $value);
+ return new css_style_borderrightcolor('border-right-color', $value);
}
+
/**
* Consolidate this to a single border style
*
/**
* A border bottom colour style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_bordercolorbottom extends css_style_color {
+class css_style_borderbottomcolor extends css_style_bordercolor {
+
/**
* Initialises this style object
*
* @param string $value
- * @return css_style_bordercolorbottom
+ * @return css_style_borderbottomcolor
*/
public static function init($value) {
- return new css_style_bordercolorbottom('border-color-bottom', $value);
+ return new css_style_borderbottomcolor('border-bottom-color', $value);
}
+
/**
* Consolidate this to a single border style
*
/**
* A border width top style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_borderwidthtop extends css_style_generic {
+class css_style_bordertopwidth extends css_style_borderwidth {
+
/**
* Initialises this style object
*
* @param string $value
- * @return css_style_borderwidthtop
+ * @return css_style_bordertopwidth
*/
public static function init($value) {
- return new css_style_borderwidthtop('border-width-top', $value);
+ return new css_style_bordertopwidth('border-top-width', $value);
}
+
/**
* Consolidate this to a single border style
*
/**
* A border width left style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_borderwidthleft extends css_style_generic {
+class css_style_borderleftwidth extends css_style_borderwidth {
+
/**
* Initialises this style object
*
* @param string $value
- * @return css_style_borderwidthleft
+ * @return css_style_borderleftwidth
*/
public static function init($value) {
- return new css_style_borderwidthleft('border-width-left', $value);
+ return new css_style_borderleftwidth('border-left-width', $value);
}
+
/**
* Consolidate this to a single border style
*
/**
* A border width right style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_borderwidthright extends css_style_generic {
+class css_style_borderrightwidth extends css_style_borderwidth {
+
/**
* Initialises this style object
*
* @param string $value
- * @return css_style_borderwidthright
+ * @return css_style_borderrightwidth
*/
public static function init($value) {
- return new css_style_borderwidthright('border-width-right', $value);
+ return new css_style_borderrightwidth('border-right-width', $value);
}
+
/**
* Consolidate this to a single border style
*
/**
* A border width bottom style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_borderwidthbottom extends css_style_generic {
+class css_style_borderbottomwidth extends css_style_borderwidth {
+
/**
* Initialises this style object
*
* @param string $value
- * @return css_style_borderwidthbottom
+ * @return css_style_borderbottomwidth
*/
public static function init($value) {
- return new css_style_borderwidthbottom('border-width-bottom', $value);
+ return new css_style_borderbottomwidth('border-bottom-width', $value);
}
+
/**
* Consolidate this to a single border style
*
/**
* A border top style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_borderstyletop extends css_style_generic {
+class css_style_bordertopstyle extends css_style_borderstyle {
+
/**
* Initialises this style object
*
* @param string $value
- * @return css_style_borderstyletop
+ * @return css_style_bordertopstyle
*/
public static function init($value) {
- return new css_style_borderstyletop('border-style-top', $value);
+ return new css_style_bordertopstyle('border-top-style', $value);
}
+
/**
* Consolidate this to a single border style
*
/**
* A border left style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_borderstyleleft extends css_style_generic {
+class css_style_borderleftstyle extends css_style_borderstyle {
+
/**
* Initialises this style object
*
* @param string $value
- * @return css_style_borderstyleleft
+ * @return css_style_borderleftstyle
*/
public static function init($value) {
- return new css_style_borderstyleleft('border-style-left', $value);
+ return new css_style_borderleftstyle('border-left-style', $value);
}
+
/**
* Consolidate this to a single border style
*
/**
* A border right style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_borderstyleright extends css_style_generic {
+class css_style_borderrightstyle extends css_style_borderstyle {
+
/**
* Initialises this style object
*
* @param string $value
- * @return css_style_borderstyleright
+ * @return css_style_borderrightstyle
*/
public static function init($value) {
- return new css_style_borderstyleright('border-style-right', $value);
+ return new css_style_borderrightstyle('border-right-style', $value);
}
+
/**
* Consolidate this to a single border style
*
/**
* A border bottom style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_borderstylebottom extends css_style_generic {
+class css_style_borderbottomstyle extends css_style_borderstyle {
+
/**
* Initialises this style object
*
- * @return css_style_borderstylebottom
+ * @return css_style_borderbottomstyle
*/
public static function init($value) {
- return new css_style_borderstylebottom('border-style-bottom', $value);
+ return new css_style_borderbottomstyle('border-bottom-style', $value);
}
+
/**
* Consolidate this to a single border style
*
/**
* A background style
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class css_style_background extends css_style {
+
+ /**
+ * Initialises a background style
+ *
+ * @param type $value
+ * @return array An array of background component.
+ */
public static function init($value) {
// colour - image - repeat - attachment - position
$attachments = array('scroll' , 'fixed', 'inherit');
$return = array();
+ $unknownbits = array();
+
if (count($bits) > 0 && css_is_colour(reset($bits))) {
$return[] = new css_style_backgroundcolor('background-color', array_shift($bits));
}
$return[] = new css_style_backgroundattachment('background-attachment', array_shift($bits));
}
if (count($bits) > 0) {
- $return[] = new css_style_backgroundposition('background-position', join(' ',$bits));
+ $widthbits = array();
+ foreach ($bits as $bit) {
+ if (in_array($bit, array('top', 'left', 'bottom', 'right', 'center')) || css_is_width($bit)) {
+ $widthbits[] = $bit;
+ } else {
+ $unknownbits[] = $bit;
+ }
+ }
+ $return[] = new css_style_backgroundposition('background-position', join(' ',$widthbits));
+ }
+ if (count($unknownbits)) {
+ foreach ($unknownbits as $bit) {
+ if (css_is_colour($bit)) {
+ $return[] = new css_style_backgroundcolor('background-color', $bit);
+ } else if (in_array($bit, $repeats)) {
+ $return[] = new css_style_backgroundrepeat('background-repeat', $bit);
+ } else if (in_array($bit, $attachments)) {
+ $return[] = new css_style_backgroundattachment('background-attachment', $bit);
+ }
+ }
}
return $return;
}
*
* Based upon the colour style.
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class css_style_backgroundcolor extends css_style_color {
+
/**
* Creates a new background colour style
*
public static function init($value) {
return new css_style_backgroundcolor('background-color', $value);
}
+
+ /**
+ * css_style_backgroundcolor consolidates to css_style_background
+ * @return string
+ */
public function consolidate_to() {
return 'background';
}
/**
* A background image style.
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class css_style_backgroundimage extends css_style_generic {
+
/**
* Creates a new background colour style
*
public static function init($value) {
return new css_style_backgroundimage('background-image', $value);
}
+
/**
* Consolidates this style into a single background style
*
- * @return type
+ * @return string
*/
public function consolidate_to() {
return 'background';
/**
* A background repeat style.
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class css_style_backgroundrepeat extends css_style_generic {
+
/**
* Creates a new background colour style
*
public static function init($value) {
return new css_style_backgroundrepeat('background-repeat', $value);
}
+
/**
* Consolidates this style into a single background style
*
/**
* A background attachment style.
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class css_style_backgroundattachment extends css_style_generic {
+
/**
* Creates a new background colour style
*
public static function init($value) {
return new css_style_backgroundattachment('background-attachment', $value);
}
+
/**
* Consolidates this style into a single background style
*
- * @return type
+ * @return string
*/
public function consolidate_to() {
return 'background';
/**
* A background position style.
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class css_style_backgroundposition extends css_style_generic {
+
/**
* Creates a new background colour style
*
public static function init($value) {
return new css_style_backgroundposition('background-position', $value);
}
+
/**
* Consolidates this style into a single background style
*
- * @return type
+ * @return string
*/
public function consolidate_to() {
return 'background';
/**
* A padding style.
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_padding extends css_style {
+class css_style_padding extends css_style_width {
+
/**
* Initialises this padding style into several individual padding styles
*
* @return array
*/
public static function init($value) {
- $value = preg_replace('#\s+#', ' ', $value);
+ $important = '';
+ if (strpos($value, '!important') !== false) {
+ $important = ' !important';
+ $value = str_replace('!important', '', $value);
+ }
+
+ $value = preg_replace('#\s+#', ' ', trim($value));
$bits = explode(' ', $value, 4);
$top = $right = $bottom = $left = null;
$left = array_shift($bits);
}
return array(
- new css_style_paddingtop('padding-top', $top),
- new css_style_paddingright('padding-right', $right),
- new css_style_paddingbottom('padding-bottom', $bottom),
- new css_style_paddingleft('padding-left', $left)
+ new css_style_paddingtop('padding-top', $top.$important),
+ new css_style_paddingright('padding-right', $right.$important),
+ new css_style_paddingbottom('padding-bottom', $bottom.$important),
+ new css_style_paddingleft('padding-left', $left.$important)
);
}
+
/**
* Consolidates several padding styles into a single style.
*
} else {
return array(new css_style_padding('padding', "{$top} {$right} {$bottom} {$left}"));
}
-
}
}
/**
* A padding top style.
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_paddingtop extends css_style {
+class css_style_paddingtop extends css_style_padding {
+
/**
* Initialises this style
*
public static function init($value) {
return new css_style_paddingtop('padding-top', $value);
}
+
/**
* Consolidates this style into a single padding style
*
/**
* A padding right style.
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_paddingright extends css_style {
+class css_style_paddingright extends css_style_padding {
+
/**
* Initialises this style
*
public static function init($value) {
return new css_style_paddingright('padding-right', $value);
}
+
/**
* Consolidates this style into a single padding style
*
/**
* A padding bottom style.
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_paddingbottom extends css_style {
+class css_style_paddingbottom extends css_style_padding {
+
/**
* Initialises this style
*
public static function init($value) {
return new css_style_paddingbottom('padding-bottom', $value);
}
+
/**
* Consolidates this style into a single padding style
*
/**
* A padding left style.
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class css_style_paddingleft extends css_style {
+class css_style_paddingleft extends css_style_padding {
+
/**
* Initialises this style
*
public static function init($value) {
return new css_style_paddingleft('padding-left', $value);
}
+
/**
* Consolidates this style into a single padding style
*
/**
* This file contains the unittests for the css optimiser in csslib.php
*
- * @package moodlecore
- * @copyright 2011 Sam Hemelryk
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
if (!defined('MOODLE_INTERNAL')) {
}
require_once($CFG->libdir . '/csslib.php');
+
+/**
+ * CSS optimiser test class
+ *
+ * @package core
+ * @subpackage css
+ * @copyright 2012 Sam Hemelryk
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
class css_optimiser_test extends UnitTestCase {
+ /**
+ * Sets up the test class
+ */
public function setUp() {
global $CFG;
parent::setUp();
- $CFG->cssoptimisestats = false;
- $CFG->cssoptimisepretty = false;
+ // We need to disable these if they are enabled to that we can predict
+ // the output.
+ $CFG->cssoptimiserstats = false;
+ $CFG->cssoptimiserpretty = false;
}
+ /**
+ * Test the process method
+ */
public function test_process() {
$optimiser = new css_optimiser;
- /*
- $cssin = '.test {border:1px solid;border-color-top:#111; border-color-bottom: #222;border-color-left: #333;border-color-right:#444;}';
- $cssout = '.test{border:1px solid;border-color:#111 #444 # 222 #333;}';
- $actual = $optimiser->process($cssin);
- debug(compact('cssin', 'cssout', 'actual'));
- $this->assertEqual($cssout, $actual);
- return;
- /**/
-
$this->check_background($optimiser);
$this->check_borders($optimiser);
$this->check_colors($optimiser);
$this->check_margins($optimiser);
$this->check_padding($optimiser);
+ $this->try_broken_css_found_in_moodle($optimiser);
$this->try_invalid_css_handling($optimiser);
$this->try_bulk_processing($optimiser);
-
-
- return;
-
- $cssin = '.one {background-color:color:red}';
- $cssout = '.one{background-color:color:red;}';
- $this->assertEqual($cssout, $optimiser->process($cssin));
+ $this->try_break_things($optimiser);
}
+ /**
+ * Background colour tests
+ * @param css_optimiser $optimiser
+ */
protected function check_background(css_optimiser $optimiser) {
$cssin = '.test {background-color: #123456;}';
$this->assertEqual($cssout, $optimiser->process($cssin));
}
+ /**
+ * Border tests
+ * @param css_optimiser $optimiser
+ */
protected function check_borders(css_optimiser $optimiser) {
- $cssin = '.test {border: 1px solid #654321} .test {border-color-bottom: #123456}';
+ $cssin = '.test {border: 1px solid #654321} .test {border-bottom-color: #123456}';
$cssout = '.test{border:1px solid;border-color:#654321 #654321 #123456;}';
$this->assertEqual($cssout, $optimiser->process($cssin));
$cssout = ".one, .two{border:1px solid #FF0000;}";
$this->assertEqual($cssout, $optimiser->process($cssin));
+ $cssin = '.one, .two {border:0px;}';
+ $cssout = ".one, .two{border-width:0;}";
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
+ $cssin = '.one, .two {border-top: 5px solid white;}';
+ $cssout = ".one, .two{border-top:5px solid #FFFFFF;}";
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
$cssin = '.one {border:1px solid red;} .two {border:1px solid red;}';
$cssout = ".one, .two{border:1px solid #FF0000;}";
$this->assertEqual($cssout, $optimiser->process($cssin));
$cssout = '.test{border:1px solid #123456;}';
$this->assertEqual($cssout, $optimiser->process($cssin));
- $cssin = '.test {border:1px solid;border-color-top:#123456;}';
- $cssout = '.test{border:1px solid;border-color-top:#123456;}';
+ $cssin = '.test {border:1px solid;border-top-color:#123456;}';
+ $cssout = '.test{border:1px solid;border-top-color:#123456;}';
$this->assertEqual($cssout, $optimiser->process($cssin));
- $cssin = '.test {border:1px solid;border-color-top:#111; border-color-bottom: #222;border-color-left: #333;}';
- $cssout = '.test{border:1px solid;border-color-top:#111;border-color-bottom:#222;border-color-left:#333;}';
+ $cssin = '.test {border:1px solid;border-top-color:#111; border-bottom-color: #222;border-left-color: #333;}';
+ $cssout = '.test{border:1px solid;border-top-color:#111;border-bottom-color:#222;border-left-color:#333;}';
$this->assertEqual($cssout, $optimiser->process($cssin));
- $cssin = '.test {border:1px solid;border-color-top:#111; border-color-bottom: #222;border-color-left: #333;border-color-right:#444;}';
+ $cssin = '.test {border:1px solid;border-top-color:#111; border-bottom-color: #222;border-left-color: #333;border-right-color:#444;}';
$cssout = '.test{border:1px solid;border-color:#111 #444 #222 #333;}';
$this->assertEqual($cssout, $optimiser->process($cssin));
+
+ $cssin = '.generaltable .cell {border-color:#EEEEEE;} .generaltable .cell {border-width: 1px;border-style: solid;}';
+ $cssout = '.generaltable .cell{border:1px solid #EEEEEE;}';
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
+ $cssin = '#page-admin-roles-override .rolecap {border:none;border-bottom:1px solid #CECECE;}';
+ $cssout = '#page-admin-roles-override .rolecap{border-top:0;border-right:0;border-bottom:1px solid #CECECE;border-left:0;}';
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
}
+ /**
+ * Test colour styles
+ * @param css_optimiser $optimiser
+ */
protected function check_colors(css_optimiser $optimiser) {
$css = '.css{}';
$this->assertEqual($css, $optimiser->process($css));
$this->assertEqual($cssout, $optimiser->process($cssin));
}
+ /**
+ * Test margin styles
+ * @param css_optimiser $optimiser
+ */
protected function check_margins(css_optimiser $optimiser) {
$cssin = '.one {margin: 1px 2px 3px 4px}';
$cssout = '.one{margin:1px 2px 3px 4px;}';
$this->assertEqual($cssout, $optimiser->process($cssin));
}
+ /**
+ * Test padding styles
+ *
+ * @param css_optimiser $optimiser
+ */
protected function check_padding(css_optimiser $optimiser) {
$cssin = '.one {margin: 1px 2px 3px 4px}';
$cssout = '.one{margin:1px 2px 3px 4px;}';
$cssout = '.one{margin:1px 1px 4px;}';
$this->assertEqual($cssout, $optimiser->process($cssin));
+ $cssin = '.one {margin:0 !important;}';
+ $cssout = '.one{margin:0 !important;}';
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
+ $cssin = '.one {padding:0 !important;}';
+ $cssout = '.one{padding:0 !important;}';
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
$cssin = '.one, .two, .one.two, .one .two {margin:0;} .one.two {margin:0 7px;}';
$cssout = '.one, .two, .one .two{margin:0;} .one.two{margin:0 7px;}';
$this->assertEqual($cssout, $optimiser->process($cssin));
}
+ /**
+ * Test some totally invalid CSS optimisation
+ *
+ * @param css_optimiser $optimiser
+ */
protected function try_invalid_css_handling(css_optimiser $optimiser) {
$cssin = array(
$this->assertEqual($cssout, $optimiser->process($cssin));
}
+ /**
+ * Try to break some things
+ * @param css_optimiser $optimiser
+ */
+ protected function try_break_things(css_optimiser $optimiser) {
+ // Wildcard test
+ $cssin = '* {color: black;}';
+ $cssout = '*{color:#000;}';
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
+ // Wildcard test
+ $cssin = '.one * {color: black;}';
+ $cssout = '.one *{color:#000;}';
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
+ // Wildcard test
+ $cssin = '* .one * {color: black;}';
+ $cssout = '* .one *{color:#000;}';
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
+ // Wildcard test
+ $cssin = '*,* {color: black;}';
+ $cssout = '*{color:#000;}';
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
+ // Wildcard test
+ $cssin = '*, * .one {color: black;}';
+ $cssout = "*,\n* .one{color:#000;}";
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
+ // Wildcard test
+ $cssin = '*, *.one {color: black;}';
+ $cssout = "*,\n*.one{color:#000;}";
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
+ // Psedo test
+ $cssin = '.one:before {color: black;}';
+ $cssout = '.one:before{color:#000;}';
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
+ // Psedo test
+ $cssin = '.one:after {color: black;}';
+ $cssout = '.one:after{color:#000;}';
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
+ // Psedo test
+ $cssin = '.one:onclick {color: black;}';
+ $cssout = '.one:onclick{color:#000;}';
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
+ // Test complex CSS rules that don't really exist but mimic other CSS rules
+ $cssin = '.one {master-of-destruction: explode(\' \', "What madness";}';
+ $cssout = '.one{master-of-destruction:explode(\' \', "What madness";}';
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
+ // Test some complex IE css... I couldn't even think of a more complext solution
+ // than the CSS they came up with.
+ $cssin = 'a { opacity: 0.5; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; filter: alpha(opacity=50); }';
+ $cssout = 'a{opacity:0.5;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";filter:alpha(opacity=50);}';
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+ }
+
+ /**
+ * A bulk processing test
+ * @param css_optimiser $optimiser
+ */
protected function try_bulk_processing(css_optimiser $optimiser) {
global $CFG;
$cssin = <<<CSS
#test .one{color:#654321;}
}
CSS;
- $CFG->cssoptimisepretty = 1;
+ $CFG->cssoptimiserpretty = 1;
$this->assertEqual($optimiser->process($cssin), $cssout);
}
-}
+
+ /**
+ * Test CSS colour matching
+ */
+ public function test_css_is_colour() {
+ // First lets test hex colours
+ $this->assertTrue(css_is_colour('#123456'));
+ $this->assertTrue(css_is_colour('#123'));
+ $this->assertTrue(css_is_colour('#ABCDEF'));
+ $this->assertTrue(css_is_colour('#ABC'));
+ $this->assertTrue(css_is_colour('#abcdef'));
+ $this->assertTrue(css_is_colour('#abc'));
+ $this->assertTrue(css_is_colour('#aBcDeF'));
+ $this->assertTrue(css_is_colour('#aBc'));
+ $this->assertTrue(css_is_colour('#1a2Bc3'));
+ $this->assertTrue(css_is_colour('#1Ac'));
+ // Note the following two colour's arn't really colours but browsers process
+ // them still.
+ $this->assertTrue(css_is_colour('#A'));
+ $this->assertTrue(css_is_colour('#12'));
+
+ $this->assertFalse(css_is_colour('#BCDEFG'));
+ $this->assertFalse(css_is_colour('#'));
+ $this->assertFalse(css_is_colour('#0000000'));
+ $this->assertFalse(css_is_colour('#132-245'));
+ $this->assertFalse(css_is_colour('#13 23 43'));
+ $this->assertFalse(css_is_colour('123456'));
+
+ // Next lets test real browser mapped colours
+ $this->assertTrue(css_is_colour('black'));
+ $this->assertTrue(css_is_colour('blue'));
+ $this->assertTrue(css_is_colour('BLACK'));
+ $this->assertTrue(css_is_colour('Black'));
+ $this->assertTrue(css_is_colour('bLACK'));
+ $this->assertTrue(css_is_colour('mediumaquamarine'));
+ $this->assertTrue(css_is_colour('mediumAquamarine'));
+ $this->assertFalse(css_is_colour('monkey'));
+ $this->assertFalse(css_is_colour(''));
+ $this->assertFalse(css_is_colour('not a colour'));
+
+ // Next lets test rgb(a) colours
+ $this->assertTrue(css_is_colour('rgb(255,255,255)'));
+ $this->assertTrue(css_is_colour('rgb(0, 0, 0)'));
+ $this->assertTrue(css_is_colour('RGB (255, 255 , 255)'));
+ $this->assertTrue(css_is_colour('rgba(0,0,0,0)'));
+ $this->assertTrue(css_is_colour('RGBA(255,255,255,1)'));
+ $this->assertTrue(css_is_colour('rgbA(255,255,255,0.5)'));
+ $this->assertFalse(css_is_colour('rgb(-255,-255,-255)'));
+ $this->assertFalse(css_is_colour('rgb(256,-256,256)'));
+
+ // Now lets test HSL colours
+ $this->assertTrue(css_is_colour('hsl(0,0%,100%)'));
+ $this->assertTrue(css_is_colour('hsl(180, 0%, 10%)'));
+ $this->assertTrue(css_is_colour('hsl (360, 100% , 95%)'));
+
+ // Finally test the special values
+ $this->assertTrue(css_is_colour('inherit'));
+ }
+
+ /**
+ * Test the css_is_width function
+ */
+ public function test_css_is_width() {
+
+ $this->assertTrue(css_is_width('0'));
+ $this->assertTrue(css_is_width('0px'));
+ $this->assertTrue(css_is_width('0em'));
+ $this->assertTrue(css_is_width('199px'));
+ $this->assertTrue(css_is_width('199em'));
+ $this->assertTrue(css_is_width('199%'));
+ $this->assertTrue(css_is_width('-1'));
+ $this->assertTrue(css_is_width('-1px'));
+ $this->assertTrue(css_is_width('auto'));
+ $this->assertTrue(css_is_width('inherit'));
+
+ $this->assertFalse(css_is_width('-'));
+ $this->assertFalse(css_is_width('bananas'));
+ $this->assertFalse(css_is_width(''));
+ $this->assertFalse(css_is_width('top'));
+ }
+
+ /**
+ * This function tests some of the broken crazy CSS we have in Moodle.
+ * For each of these things the value needs to be corrected if we can be 100%
+ * certain what is going wrong, Or it needs to be left as is.
+ *
+ * @param css_optimiser $optimiser
+ */
+ public function try_broken_css_found_in_moodle(css_optimiser $optimiser) {
+ // Notice how things are out of order here but that they get corrected
+ $cssin = '.test {background:url([[pix:theme|pageheaderbgred]]) top center no-repeat}';
+ $cssout = '.test{background:url([[pix:theme|pageheaderbgred]]) no-repeat top center;}';
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
+ // Cursor hand isn't valid
+ $cssin = '.test {cursor: hand;}';
+ $cssout = '.test{cursor:hand;}';
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
+ // Zoom property isn't valid
+ $cssin = '.test {zoom: 1;}';
+ $cssout = '.test{zoom:1;}';
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
+ // Left isn't a valid position property
+ $cssin = '.test {position: left;}';
+ $cssout = '.test{position:left;}';
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
+ // The dark red color isn't a valid HTML color but has a standardised
+ // translation of #8B0000
+ $cssin = '.test {color: darkred;}';
+ $cssout = '.test{color:#8B0000;}';
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
+ // You can't use argb colours as border colors
+ $cssin = '.test {border-bottom: 1px solid rgba(0,0,0,0.25);}';
+ $cssout = '.test{border-bottom:1px solid rgba(0,0,0,0.25);}';
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+
+ // Opacity with annoying IE equivilants....
+ $cssin = '.test {opacity: 0.5; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; filter: alpha(opacity=50);}';
+ $cssout = '.test{opacity:0.5;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";filter:alpha(opacity=50);}';
+ $this->assertEqual($cssout, $optimiser->process($cssin));
+ }
+}
\ No newline at end of file