annotate sites/all/modules/ctools/includes/css.inc @ 0:ff03f76ab3fe

initial version
author danieleb <danielebarchiesi@me.com>
date Wed, 21 Aug 2013 18:51:11 +0100
parents
children
rev   line source
danielebarchiesi@0 1 <?php
danielebarchiesi@0 2
danielebarchiesi@0 3 /*
danielebarchiesi@0 4 * @file
danielebarchiesi@0 5 * CSS filtering functions. Contains a disassembler, filter, compressor, and
danielebarchiesi@0 6 * decompressor.
danielebarchiesi@0 7 *
danielebarchiesi@0 8 * The general usage of this tool is:
danielebarchiesi@0 9 *
danielebarchiesi@0 10 * To simply filter CSS:
danielebarchiesi@0 11 * @code
danielebarchiesi@0 12 * $filtered_css = ctools_css_filter($css, TRUE);
danielebarchiesi@0 13 * @endcode
danielebarchiesi@0 14 *
danielebarchiesi@0 15 * In the above, if the second argument is TRUE, the returned CSS will
danielebarchiesi@0 16 * be compressed. Otherwise it will be returned in a well formatted
danielebarchiesi@0 17 * syntax.
danielebarchiesi@0 18 *
danielebarchiesi@0 19 * To cache unfiltered CSS in a file, which will be filtered:
danielebarchiesi@0 20 *
danielebarchiesi@0 21 * @code
danielebarchiesi@0 22 * $filename = ctools_css_cache($css, TRUE);
danielebarchiesi@0 23 * @endcode
danielebarchiesi@0 24 *
danielebarchiesi@0 25 * In the above, if the second argument is FALSE, the CSS will not be filtered.
danielebarchiesi@0 26 *
danielebarchiesi@0 27 * This file will be cached within the Drupal files system. This system cannot
danielebarchiesi@0 28 * detect when this file changes, so it is YOUR responsibility to remove and
danielebarchiesi@0 29 * re-cache this file when the CSS is changed. Your system should also contain
danielebarchiesi@0 30 * a backup method of re-generating the CSS cache in case it is removed, so
danielebarchiesi@0 31 * that it is easy to force a re-cache by simply deleting the contents of the
danielebarchiesi@0 32 * directory.
danielebarchiesi@0 33 *
danielebarchiesi@0 34 * Finally, if for some reason your application cannot store the filename
danielebarchiesi@0 35 * (which is true of Panels where the style can't force the display to
danielebarchiesi@0 36 * resave unconditionally) you can use the ctools storage mechanism. You
danielebarchiesi@0 37 * simply have to come up with a unique Id:
danielebarchiesi@0 38 *
danielebarchiesi@0 39 * @code
danielebarchiesi@0 40 * $filename = ctools_css_store($id, $css, TRUE);
danielebarchiesi@0 41 * @endcode
danielebarchiesi@0 42 *
danielebarchiesi@0 43 * Then later on:
danielebarchiesi@0 44 * @code
danielebarchiesi@0 45 * $filename = ctools_css_retrieve($id);
danielebarchiesi@0 46 * drupal_add_css($filename);
danielebarchiesi@0 47 * @endcode
danielebarchiesi@0 48 *
danielebarchiesi@0 49 * The CSS that was generated will be stored in the database, so even if the
danielebarchiesi@0 50 * file was removed the cached CSS will be used. If the CSS cache is
danielebarchiesi@0 51 * cleared you may be required to regenerate your CSS. This will normally
danielebarchiesi@0 52 * only be cleared by an administrator operation, not during normal usage.
danielebarchiesi@0 53 *
danielebarchiesi@0 54 * You may remove your stored CSS this way:
danielebarchiesi@0 55 *
danielebarchiesi@0 56 * @code
danielebarchiesi@0 57 * ctools_css_clear($id);
danielebarchiesi@0 58 * @endcode
danielebarchiesi@0 59 */
danielebarchiesi@0 60
danielebarchiesi@0 61 /**
danielebarchiesi@0 62 * Store CSS with a given id and return the filename to use.
danielebarchiesi@0 63 *
danielebarchiesi@0 64 * This function associates a piece of CSS with an id, and stores the
danielebarchiesi@0 65 * cached filename and the actual CSS for later use with
danielebarchiesi@0 66 * ctools_css_retrieve.
danielebarchiesi@0 67 */
danielebarchiesi@0 68 function ctools_css_store($id, $css, $filter = TRUE) {
danielebarchiesi@0 69 $filename = db_query('SELECT filename FROM {ctools_css_cache} WHERE cid = :cid', array(':cid' => $id))->fetchField();
danielebarchiesi@0 70 if ($filename && file_exists($filename)) {
danielebarchiesi@0 71 file_unmanaged_delete($filename);
danielebarchiesi@0 72 }
danielebarchiesi@0 73 // Remove any previous records.
danielebarchiesi@0 74 db_delete('ctools_css_cache')
danielebarchiesi@0 75 ->condition('cid', $id)
danielebarchiesi@0 76 ->execute();
danielebarchiesi@0 77
danielebarchiesi@0 78 $filename = ctools_css_cache($css, $filter);
danielebarchiesi@0 79
danielebarchiesi@0 80 db_insert('ctools_css_cache')
danielebarchiesi@0 81 ->fields(array(
danielebarchiesi@0 82 'cid' => $id,
danielebarchiesi@0 83 'filename' => $filename,
danielebarchiesi@0 84 'css' => $css,
danielebarchiesi@0 85 'filter' => intval($filter),
danielebarchiesi@0 86 ))
danielebarchiesi@0 87 ->execute();
danielebarchiesi@0 88
danielebarchiesi@0 89 return $filename;
danielebarchiesi@0 90 }
danielebarchiesi@0 91
danielebarchiesi@0 92 /**
danielebarchiesi@0 93 * Retrieve a filename associated with an id of previously cached CSS.
danielebarchiesi@0 94 *
danielebarchiesi@0 95 * This will ensure the file still exists and, if not, create it.
danielebarchiesi@0 96 */
danielebarchiesi@0 97 function ctools_css_retrieve($id) {
danielebarchiesi@0 98 $cache = db_query('SELECT * FROM {ctools_css_cache} WHERE cid = :cid', array(':cid' => $id))->fetchObject();
danielebarchiesi@0 99 if (!$cache) {
danielebarchiesi@0 100 return;
danielebarchiesi@0 101 }
danielebarchiesi@0 102
danielebarchiesi@0 103 if (!file_exists($cache->filename)) {
danielebarchiesi@0 104 $filename = ctools_css_cache($cache->css, $cache->filter);
danielebarchiesi@0 105 if ($filename != $cache->filename) {
danielebarchiesi@0 106 db_update('ctools_css_cache')
danielebarchiesi@0 107 ->fields(array('filename' => $filename))
danielebarchiesi@0 108 ->condition('cid', $id)
danielebarchiesi@0 109 ->execute();
danielebarchiesi@0 110 $cache->filename = $filename;
danielebarchiesi@0 111 }
danielebarchiesi@0 112 }
danielebarchiesi@0 113
danielebarchiesi@0 114 return $cache->filename;
danielebarchiesi@0 115 }
danielebarchiesi@0 116
danielebarchiesi@0 117 /**
danielebarchiesi@0 118 * Remove stored CSS and any associated file.
danielebarchiesi@0 119 */
danielebarchiesi@0 120 function ctools_css_clear($id) {
danielebarchiesi@0 121 $cache = db_query('SELECT * FROM {ctools_css_cache} WHERE cid = :cid', array(':cid' => $id))->fetchObject();
danielebarchiesi@0 122 if (!$cache) {
danielebarchiesi@0 123 return;
danielebarchiesi@0 124 }
danielebarchiesi@0 125
danielebarchiesi@0 126 if (file_exists($cache->filename)) {
danielebarchiesi@0 127 file_unmanaged_delete($cache->filename);
danielebarchiesi@0 128 // If we remove an existing file, there may be cached pages that refer
danielebarchiesi@0 129 // to it. We must get rid of them: FIXME same format in D7?
danielebarchiesi@0 130 cache_clear_all();
danielebarchiesi@0 131 }
danielebarchiesi@0 132
danielebarchiesi@0 133 db_delete('ctools_css_cache')
danielebarchiesi@0 134 ->condition('cid', $id)
danielebarchiesi@0 135 ->execute();
danielebarchiesi@0 136 }
danielebarchiesi@0 137
danielebarchiesi@0 138 /**
danielebarchiesi@0 139 * Write a chunk of CSS to a temporary cache file and return the file name.
danielebarchiesi@0 140 *
danielebarchiesi@0 141 * This function optionally filters the CSS (always compressed, if so) and
danielebarchiesi@0 142 * generates a unique filename based upon md5. It returns that filename that
danielebarchiesi@0 143 * can be used with drupal_add_css(). Note that as a cache file, technically
danielebarchiesi@0 144 * this file is volatile so it should be checked before it is used to ensure
danielebarchiesi@0 145 * that it exists.
danielebarchiesi@0 146 *
danielebarchiesi@0 147 * You can use file_exists() to test for the file and file_delete() to remove
danielebarchiesi@0 148 * it if it needs to be cleared.
danielebarchiesi@0 149 *
danielebarchiesi@0 150 * @param $css
danielebarchiesi@0 151 * A chunk of well-formed CSS text to cache.
danielebarchiesi@0 152 * @param $filter
danielebarchiesi@0 153 * If TRUE the css will be filtered. If FALSE the text will be cached
danielebarchiesi@0 154 * as-is.
danielebarchiesi@0 155 *
danielebarchiesi@0 156 * @return $filename
danielebarchiesi@0 157 * The filename the CSS will be cached in.
danielebarchiesi@0 158 */
danielebarchiesi@0 159 function ctools_css_cache($css, $filter = TRUE) {
danielebarchiesi@0 160 if ($filter) {
danielebarchiesi@0 161 $css = ctools_css_filter($css);
danielebarchiesi@0 162 }
danielebarchiesi@0 163
danielebarchiesi@0 164 // Create the css/ within the files folder.
danielebarchiesi@0 165 $path = 'public://ctools/css';
danielebarchiesi@0 166 if (!file_prepare_directory($path, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
danielebarchiesi@0 167 // if (!file_prepare_directory($path, FILE_CREATE_DIRECTORY)) {
danielebarchiesi@0 168 drupal_set_message(t('Unable to create CTools CSS cache directory. Check the permissions on your files directory.'), 'error');
danielebarchiesi@0 169 return;
danielebarchiesi@0 170 }
danielebarchiesi@0 171
danielebarchiesi@0 172 // @todo Is this slow? Does it matter if it is?
danielebarchiesi@0 173 $filename = $path . '/' . md5($css) . '.css';
danielebarchiesi@0 174
danielebarchiesi@0 175 // This will do renames if the file already exists, ensuring we don't
danielebarchiesi@0 176 // accidentally overwrite other files who share the same md5. Yes this
danielebarchiesi@0 177 // is a very miniscule chance but it's safe.
danielebarchiesi@0 178 $filename = file_unmanaged_save_data($css, $filename);
danielebarchiesi@0 179
danielebarchiesi@0 180 return $filename;
danielebarchiesi@0 181 }
danielebarchiesi@0 182
danielebarchiesi@0 183 /**
danielebarchiesi@0 184 * Filter a chunk of CSS text.
danielebarchiesi@0 185 *
danielebarchiesi@0 186 * This function disassembles the CSS into a raw format that makes it easier
danielebarchiesi@0 187 * for our tool to work, then runs it through the filter and reassembles it.
danielebarchiesi@0 188 * If you find that you want the raw data for some reason or another, you
danielebarchiesi@0 189 * can use the disassemble/assemble functions yourself.
danielebarchiesi@0 190 *
danielebarchiesi@0 191 * @param $css
danielebarchiesi@0 192 * The CSS text to filter.
danielebarchiesi@0 193 * @param $compressed
danielebarchiesi@0 194 * If true, generate compressed output; if false, generate pretty output.
danielebarchiesi@0 195 * Defaults to TRUE.
danielebarchiesi@0 196 */
danielebarchiesi@0 197 function ctools_css_filter($css, $compressed = TRUE) {
danielebarchiesi@0 198 $css_data = ctools_css_disassemble($css);
danielebarchiesi@0 199
danielebarchiesi@0 200 // Note: By using this function yourself you can control the allowed
danielebarchiesi@0 201 // properties and values list.
danielebarchiesi@0 202 $filtered = ctools_css_filter_css_data($css_data);
danielebarchiesi@0 203
danielebarchiesi@0 204 return $compressed ? ctools_css_compress($filtered) : ctools_css_assemble($filtered);
danielebarchiesi@0 205 }
danielebarchiesi@0 206
danielebarchiesi@0 207 /**
danielebarchiesi@0 208 * Re-assemble a css string and format it nicely.
danielebarchiesi@0 209 *
danielebarchiesi@0 210 * @param array $css_data
danielebarchiesi@0 211 * An array of css data, as produced by @see ctools_css_disassemble()
danielebarchiesi@0 212 * disassembler and the @see ctools_css_filter_css_data() filter.
danielebarchiesi@0 213 *
danielebarchiesi@0 214 * @return string $css
danielebarchiesi@0 215 * css optimized for human viewing.
danielebarchiesi@0 216 */
danielebarchiesi@0 217 function ctools_css_assemble($css_data) {
danielebarchiesi@0 218 // Initialize the output.
danielebarchiesi@0 219 $css = '';
danielebarchiesi@0 220 // Iterate through all the statements.
danielebarchiesi@0 221 foreach ($css_data as $selector_str => $declaration) {
danielebarchiesi@0 222 // Add the selectors, separating them with commas and line feeds.
danielebarchiesi@0 223 $css .= strpos($selector_str, ',') === FALSE ? $selector_str : str_replace(", ", ",\n", $selector_str);
danielebarchiesi@0 224 // Add the opening curly brace.
danielebarchiesi@0 225 $css .= " {\n";
danielebarchiesi@0 226 // Iterate through all the declarations.
danielebarchiesi@0 227 foreach ($declaration as $property => $value) {
danielebarchiesi@0 228 $css .= " " . $property . ": " . $value . ";\n";
danielebarchiesi@0 229 }
danielebarchiesi@0 230 // Add the closing curly brace.
danielebarchiesi@0 231 $css .= "}\n\n";
danielebarchiesi@0 232 }
danielebarchiesi@0 233 // Return the output.
danielebarchiesi@0 234 return $css;
danielebarchiesi@0 235 }
danielebarchiesi@0 236
danielebarchiesi@0 237 /**
danielebarchiesi@0 238 * Compress css data (filter it first!) to optimize for use on view.
danielebarchiesi@0 239 *
danielebarchiesi@0 240 * @param array $css_data
danielebarchiesi@0 241 * An array of css data, as produced by @see ctools_css_disassemble()
danielebarchiesi@0 242 * disassembler and the @see ctools_css_filter_css_data() filter.
danielebarchiesi@0 243 *
danielebarchiesi@0 244 * @return string $css
danielebarchiesi@0 245 * css optimized for use.
danielebarchiesi@0 246 */
danielebarchiesi@0 247 function ctools_css_compress($css_data) {
danielebarchiesi@0 248 // Initialize the output.
danielebarchiesi@0 249 $css = '';
danielebarchiesi@0 250 // Iterate through all the statements.
danielebarchiesi@0 251 foreach ($css_data as $selector_str => $declaration) {
danielebarchiesi@0 252 if (empty($declaration)) {
danielebarchiesi@0 253 // Skip this statement if filtering removed all parts of the declaration.
danielebarchiesi@0 254 continue;
danielebarchiesi@0 255 }
danielebarchiesi@0 256 // Add the selectors, separating them with commas.
danielebarchiesi@0 257 $css .= $selector_str;
danielebarchiesi@0 258 // And, the opening curly brace.
danielebarchiesi@0 259 $css .= "{";
danielebarchiesi@0 260 // Iterate through all the statement properties.
danielebarchiesi@0 261 foreach ($declaration as $property => $value) {
danielebarchiesi@0 262 $css .= $property . ':' . $value . ';';
danielebarchiesi@0 263 }
danielebarchiesi@0 264 // Add the closing curly brace.
danielebarchiesi@0 265 $css .= "}";
danielebarchiesi@0 266 }
danielebarchiesi@0 267 // Return the output.
danielebarchiesi@0 268 return $css;
danielebarchiesi@0 269 }
danielebarchiesi@0 270
danielebarchiesi@0 271 /**
danielebarchiesi@0 272 * Disassemble the css string.
danielebarchiesi@0 273 *
danielebarchiesi@0 274 * Strip the css of irrelevant characters, invalid/malformed selectors and
danielebarchiesi@0 275 * declarations, and otherwise prepare it for processing.
danielebarchiesi@0 276 *
danielebarchiesi@0 277 * @param string $css
danielebarchiesi@0 278 * A string containing the css to be disassembled.
danielebarchiesi@0 279 *
danielebarchiesi@0 280 * @return array $disassembled_css
danielebarchiesi@0 281 * An array of disassembled, slightly cleaned-up/formatted css statements.
danielebarchiesi@0 282 */
danielebarchiesi@0 283 function ctools_css_disassemble($css) {
danielebarchiesi@0 284 $disassembled_css = array();
danielebarchiesi@0 285 // Remove comments.
danielebarchiesi@0 286 $css = preg_replace("/\/\*(.*)?\*\//Usi", "", $css);
danielebarchiesi@0 287 // Split out each statement. Match either a right curly brace or a semi-colon
danielebarchiesi@0 288 // that precedes a left curly brace with no right curly brace separating them.
danielebarchiesi@0 289 $statements = preg_split('/}|;(?=[^}]*{)/', $css);
danielebarchiesi@0 290
danielebarchiesi@0 291 // If we have any statements, parse them.
danielebarchiesi@0 292 if (!empty($statements)) {
danielebarchiesi@0 293 // Iterate through all of the statements.
danielebarchiesi@0 294 foreach ($statements as $statement) {
danielebarchiesi@0 295 // Get the selector(s) and declaration.
danielebarchiesi@0 296 if (empty($statement) || !strpos($statement, '{')) {
danielebarchiesi@0 297 continue;
danielebarchiesi@0 298 }
danielebarchiesi@0 299
danielebarchiesi@0 300 list($selector_str, $declaration) = explode('{', $statement);
danielebarchiesi@0 301
danielebarchiesi@0 302 // If the selector exists, then disassemble it, check it, and regenerate
danielebarchiesi@0 303 // the selector string.
danielebarchiesi@0 304 $selector_str = empty($selector_str) ? FALSE : _ctools_css_disassemble_selector($selector_str);
danielebarchiesi@0 305 if (empty($selector_str)) {
danielebarchiesi@0 306 // No valid selectors. Bomb out and start the next item.
danielebarchiesi@0 307 continue;
danielebarchiesi@0 308 }
danielebarchiesi@0 309
danielebarchiesi@0 310 // Disassemble the declaration, check it and tuck it into an array.
danielebarchiesi@0 311 if (!isset($disassembled_css[$selector_str])) {
danielebarchiesi@0 312 $disassembled_css[$selector_str] = array();
danielebarchiesi@0 313 }
danielebarchiesi@0 314 $disassembled_css[$selector_str] += _ctools_css_disassemble_declaration($declaration);
danielebarchiesi@0 315 }
danielebarchiesi@0 316 }
danielebarchiesi@0 317 return $disassembled_css;
danielebarchiesi@0 318 }
danielebarchiesi@0 319
danielebarchiesi@0 320 function _ctools_css_disassemble_selector($selector_str) {
danielebarchiesi@0 321 // Get all selectors individually.
danielebarchiesi@0 322 $selectors = explode(",", trim($selector_str));
danielebarchiesi@0 323 // Iterate through all the selectors, sanity check them and return if they
danielebarchiesi@0 324 // pass. Note that this handles 0, 1, or more valid selectors gracefully.
danielebarchiesi@0 325 foreach ($selectors as $key => $selector) {
danielebarchiesi@0 326 // Replace un-needed characters and do a little cleanup.
danielebarchiesi@0 327 $selector = preg_replace("/[\n|\t|\\|\s]+/", ' ', trim($selector));
danielebarchiesi@0 328 // Make sure this is still a real selector after cleanup.
danielebarchiesi@0 329 if (!empty($selector)) {
danielebarchiesi@0 330 $selectors[$key] = $selector;
danielebarchiesi@0 331 }
danielebarchiesi@0 332 else {
danielebarchiesi@0 333 // Selector is no good, so we scrap it.
danielebarchiesi@0 334 unset($selectors[$key]);
danielebarchiesi@0 335 }
danielebarchiesi@0 336 }
danielebarchiesi@0 337 // Check for malformed selectors; if found, we skip this declaration.
danielebarchiesi@0 338 if (empty($selectors)) {
danielebarchiesi@0 339 return FALSE;
danielebarchiesi@0 340 }
danielebarchiesi@0 341 return implode(', ', $selectors);
danielebarchiesi@0 342 }
danielebarchiesi@0 343
danielebarchiesi@0 344 function _ctools_css_disassemble_declaration($declaration) {
danielebarchiesi@0 345 $formatted_statement = array();
danielebarchiesi@0 346 $propval_pairs = explode(";", $declaration);
danielebarchiesi@0 347 // Make sure we actually have some properties to work with.
danielebarchiesi@0 348 if (!empty($propval_pairs)) {
danielebarchiesi@0 349 // Iterate through the remains and parse them.
danielebarchiesi@0 350 foreach ($propval_pairs as $key => $propval_pair) {
danielebarchiesi@0 351 // Check that we have a ':', otherwise it's an invalid pair.
danielebarchiesi@0 352 if (strpos($propval_pair, ':') === FALSE) {
danielebarchiesi@0 353 continue;
danielebarchiesi@0 354 }
danielebarchiesi@0 355 // Clean up the current property-value pair.
danielebarchiesi@0 356 $propval_pair = preg_replace("/[\n|\t|\\|\s]+/", ' ', trim($propval_pair));
danielebarchiesi@0 357 // Explode the remaining fragements some more, but clean them up first.
danielebarchiesi@0 358 list($property, $value) = explode(':', $propval_pair, 2);
danielebarchiesi@0 359 // If the property survived, toss it onto the stack.
danielebarchiesi@0 360 if (!empty($property)) {
danielebarchiesi@0 361 $formatted_statement[trim($property)] = trim($value);
danielebarchiesi@0 362 }
danielebarchiesi@0 363 }
danielebarchiesi@0 364 }
danielebarchiesi@0 365 return $formatted_statement;
danielebarchiesi@0 366 }
danielebarchiesi@0 367
danielebarchiesi@0 368 /**
danielebarchiesi@0 369 * Run disassembled $css through the filter.
danielebarchiesi@0 370 *
danielebarchiesi@0 371 * @param $css
danielebarchiesi@0 372 * CSS code disassembled by ctools_dss_disassemble().
danielebarchiesi@0 373 * @param $allowed_properties
danielebarchiesi@0 374 * A list of properties that are allowed by the filter. If empty
danielebarchiesi@0 375 * ctools_css_filter_default_allowed_properties() will provide the
danielebarchiesi@0 376 * list.
danielebarchiesi@0 377 * @param $allowed_values
danielebarchiesi@0 378 * A list of values that are allowed by the filter. If empty
danielebarchiesi@0 379 * ctools_css_filter_default_allowed_values() will provide the
danielebarchiesi@0 380 * list.
danielebarchiesi@0 381 *
danielebarchiesi@0 382 * @return
danielebarchiesi@0 383 * An array of disassembled, filtered CSS.
danielebarchiesi@0 384 */
danielebarchiesi@0 385 function ctools_css_filter_css_data($css, $allowed_properties = array(), $allowed_values = array(), $allowed_values_regex = '', $disallowed_values_regex = '') {
danielebarchiesi@0 386 //function ctools_css_filter_css_data($css, &$filtered = NULL, $allowed_properties = array(), $allowed_values = array(), $allowed_values_regex = '', $disallowed_values_regex = '') {
danielebarchiesi@0 387 // Retrieve the default list of allowed properties if none is provided.
danielebarchiesi@0 388 $allowed_properties = !empty($allowed_properties) ? $allowed_properties : ctools_css_filter_default_allowed_properties();
danielebarchiesi@0 389 // Retrieve the default list of allowed values if none is provided.
danielebarchiesi@0 390 $allowed_values = !empty($allowed_values) ? $allowed_values : ctools_css_filter_default_allowed_values();
danielebarchiesi@0 391 // Define allowed values regex if none is provided.
danielebarchiesi@0 392 $allowed_values_regex = !empty($allowed_values_regex) ? $allowed_values_regex : '/(#[0-9a-f]+|rgb\(\d+%?,\d*%?,?\d*%?\)?|\d{0,2}\.?\d{0,2}(cm|em|ex|in|mm|pc|pt|px|%|,|\))?)/';
danielebarchiesi@0 393 // Define disallowed url() value contents, if none is provided.
danielebarchiesi@0 394 // $disallowed_values_regex = !empty($disallowed_values_regex) ? $disallowed_values_regex : '/[url|expression]\s*\(\s*[^\s)]+?\s*\)\s*/';
danielebarchiesi@0 395 $disallowed_values_regex = !empty($disallowed_values_regex) ? $disallowed_values_regex : '/(url|expression)/';
danielebarchiesi@0 396
danielebarchiesi@0 397 foreach ($css as $selector_str => $declaration) {
danielebarchiesi@0 398 foreach ($declaration as $property => $value) {
danielebarchiesi@0 399 if (!in_array($property, $allowed_properties)) {
danielebarchiesi@0 400 // $filtered['properties'][$selector_str][$property] = $value;
danielebarchiesi@0 401 unset($css[$selector_str][$property]);
danielebarchiesi@0 402 continue;
danielebarchiesi@0 403 }
danielebarchiesi@0 404 $value = str_replace('!important', '', $value);
danielebarchiesi@0 405 if (preg_match($disallowed_values_regex, $value) || !(in_array($value, $allowed_values) || preg_match($allowed_values_regex, $value))) {
danielebarchiesi@0 406 // $filtered['values'][$selector_str][$property] = $value;
danielebarchiesi@0 407 unset($css[$selector_str][$property]);
danielebarchiesi@0 408 continue;
danielebarchiesi@0 409 }
danielebarchiesi@0 410 }
danielebarchiesi@0 411 }
danielebarchiesi@0 412 return $css;
danielebarchiesi@0 413 }
danielebarchiesi@0 414
danielebarchiesi@0 415 /**
danielebarchiesi@0 416 * Provide a deafult list of allowed properties by the filter.
danielebarchiesi@0 417 */
danielebarchiesi@0 418 function ctools_css_filter_default_allowed_properties() {
danielebarchiesi@0 419 return array(
danielebarchiesi@0 420 'azimuth',
danielebarchiesi@0 421 'background',
danielebarchiesi@0 422 'background-color',
danielebarchiesi@0 423 'background-image',
danielebarchiesi@0 424 'background-repeat',
danielebarchiesi@0 425 'background-attachment',
danielebarchiesi@0 426 'background-position',
danielebarchiesi@0 427 'border',
danielebarchiesi@0 428 'border-top-width',
danielebarchiesi@0 429 'border-right-width',
danielebarchiesi@0 430 'border-bottom-width',
danielebarchiesi@0 431 'border-left-width',
danielebarchiesi@0 432 'border-width',
danielebarchiesi@0 433 'border-top-color',
danielebarchiesi@0 434 'border-right-color',
danielebarchiesi@0 435 'border-bottom-color',
danielebarchiesi@0 436 'border-left-color',
danielebarchiesi@0 437 'border-color',
danielebarchiesi@0 438 'border-top-style',
danielebarchiesi@0 439 'border-right-style',
danielebarchiesi@0 440 'border-bottom-style',
danielebarchiesi@0 441 'border-left-style',
danielebarchiesi@0 442 'border-style',
danielebarchiesi@0 443 'border-top',
danielebarchiesi@0 444 'border-right',
danielebarchiesi@0 445 'border-bottom',
danielebarchiesi@0 446 'border-left',
danielebarchiesi@0 447 'clear',
danielebarchiesi@0 448 'color',
danielebarchiesi@0 449 'cursor',
danielebarchiesi@0 450 'direction',
danielebarchiesi@0 451 'display',
danielebarchiesi@0 452 'elevation',
danielebarchiesi@0 453 'float',
danielebarchiesi@0 454 'font',
danielebarchiesi@0 455 'font-family',
danielebarchiesi@0 456 'font-size',
danielebarchiesi@0 457 'font-style',
danielebarchiesi@0 458 'font-variant',
danielebarchiesi@0 459 'font-weight',
danielebarchiesi@0 460 'height',
danielebarchiesi@0 461 'letter-spacing',
danielebarchiesi@0 462 'line-height',
danielebarchiesi@0 463 'margin',
danielebarchiesi@0 464 'margin-top',
danielebarchiesi@0 465 'margin-right',
danielebarchiesi@0 466 'margin-bottom',
danielebarchiesi@0 467 'margin-left',
danielebarchiesi@0 468 'overflow',
danielebarchiesi@0 469 'padding',
danielebarchiesi@0 470 'padding-top',
danielebarchiesi@0 471 'padding-right',
danielebarchiesi@0 472 'padding-bottom',
danielebarchiesi@0 473 'padding-left',
danielebarchiesi@0 474 'pause',
danielebarchiesi@0 475 'pause-after',
danielebarchiesi@0 476 'pause-before',
danielebarchiesi@0 477 'pitch',
danielebarchiesi@0 478 'pitch-range',
danielebarchiesi@0 479 'richness',
danielebarchiesi@0 480 'speak',
danielebarchiesi@0 481 'speak-header',
danielebarchiesi@0 482 'speak-numeral',
danielebarchiesi@0 483 'speak-punctuation',
danielebarchiesi@0 484 'speech-rate',
danielebarchiesi@0 485 'stress',
danielebarchiesi@0 486 'text-align',
danielebarchiesi@0 487 'text-decoration',
danielebarchiesi@0 488 'text-indent',
danielebarchiesi@0 489 'text-transform',
danielebarchiesi@0 490 'unicode-bidi',
danielebarchiesi@0 491 'vertical-align',
danielebarchiesi@0 492 'voice-family',
danielebarchiesi@0 493 'volume',
danielebarchiesi@0 494 'white-space',
danielebarchiesi@0 495 'width',
danielebarchiesi@0 496 'fill',
danielebarchiesi@0 497 'fill-opacity',
danielebarchiesi@0 498 'fill-rule',
danielebarchiesi@0 499 'stroke',
danielebarchiesi@0 500 'stroke-width',
danielebarchiesi@0 501 'stroke-linecap',
danielebarchiesi@0 502 'stroke-linejoin',
danielebarchiesi@0 503 'stroke-opacity',
danielebarchiesi@0 504 );
danielebarchiesi@0 505 }
danielebarchiesi@0 506
danielebarchiesi@0 507 /**
danielebarchiesi@0 508 * Provide a default list of allowed values by the filter.
danielebarchiesi@0 509 */
danielebarchiesi@0 510 function ctools_css_filter_default_allowed_values() {
danielebarchiesi@0 511 return array(
danielebarchiesi@0 512 'auto',
danielebarchiesi@0 513 'aqua',
danielebarchiesi@0 514 'black',
danielebarchiesi@0 515 'block',
danielebarchiesi@0 516 'blue',
danielebarchiesi@0 517 'bold',
danielebarchiesi@0 518 'both',
danielebarchiesi@0 519 'bottom',
danielebarchiesi@0 520 'brown',
danielebarchiesi@0 521 'capitalize',
danielebarchiesi@0 522 'center',
danielebarchiesi@0 523 'collapse',
danielebarchiesi@0 524 'dashed',
danielebarchiesi@0 525 'dotted',
danielebarchiesi@0 526 'fuchsia',
danielebarchiesi@0 527 'gray',
danielebarchiesi@0 528 'green',
danielebarchiesi@0 529 'italic',
danielebarchiesi@0 530 'inherit',
danielebarchiesi@0 531 'left',
danielebarchiesi@0 532 'lime',
danielebarchiesi@0 533 'lowercase',
danielebarchiesi@0 534 'maroon',
danielebarchiesi@0 535 'medium',
danielebarchiesi@0 536 'navy',
danielebarchiesi@0 537 'normal',
danielebarchiesi@0 538 'nowrap',
danielebarchiesi@0 539 'olive',
danielebarchiesi@0 540 'pointer',
danielebarchiesi@0 541 'purple',
danielebarchiesi@0 542 'red',
danielebarchiesi@0 543 'right',
danielebarchiesi@0 544 'solid',
danielebarchiesi@0 545 'silver',
danielebarchiesi@0 546 'teal',
danielebarchiesi@0 547 'top',
danielebarchiesi@0 548 'transparent',
danielebarchiesi@0 549 'underline',
danielebarchiesi@0 550 'uppercase',
danielebarchiesi@0 551 'white',
danielebarchiesi@0 552 'yellow',
danielebarchiesi@0 553 );
danielebarchiesi@0 554 }
danielebarchiesi@0 555
danielebarchiesi@0 556 /**
danielebarchiesi@0 557 * Delegated implementation of hook_flush_caches()
danielebarchiesi@0 558 */
danielebarchiesi@0 559 function ctools_css_flush_caches() {
danielebarchiesi@0 560 // Remove all generated files.
danielebarchiesi@0 561 // @see http://drupal.org/node/573292
danielebarchiesi@0 562 // file_unmanaged_delete_recursive('public://render');
danielebarchiesi@0 563 $filedir = file_default_scheme() . '://ctools/css';
danielebarchiesi@0 564 if (drupal_realpath($filedir) && file_exists($filedir)) {
danielebarchiesi@0 565 // We use the @ because it's possible that files created by the webserver
danielebarchiesi@0 566 // cannot be deleted while using drush to clear the cache. We don't really
danielebarchiesi@0 567 // care that much about that, to be honest, so we use the @ to suppress
danielebarchiesi@0 568 // the error message.
danielebarchiesi@0 569 @file_unmanaged_delete_recursive($filedir);
danielebarchiesi@0 570 }
danielebarchiesi@0 571
danielebarchiesi@0 572 db_delete('ctools_css_cache')->execute();
danielebarchiesi@0 573 }