| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575 | 
							- <?php
 
- /*
 
-  * @file
 
-  * CSS filtering functions. Contains a disassembler, filter, compressor, and
 
-  * decompressor.
 
-  *
 
-  * The general usage of this tool is:
 
-  *
 
-  * To simply filter CSS:
 
-  * @code
 
-  *   $filtered_css = ctools_css_filter($css, TRUE);
 
-  * @endcode
 
-  *
 
-  * In the above, if the second argument is TRUE, the returned CSS will
 
-  * be compressed. Otherwise it will be returned in a well formatted
 
-  * syntax.
 
-  *
 
-  * To cache unfiltered CSS in a file, which will be filtered:
 
-  *
 
-  * @code
 
-  *   $filename = ctools_css_cache($css, TRUE);
 
-  * @endcode
 
-  *
 
-  * In the above, if the second argument is FALSE, the CSS will not be filtered.
 
-  *
 
-  * This file will be cached within the Drupal files system. This system cannot
 
-  * detect when this file changes, so it is YOUR responsibility to remove and
 
-  * re-cache this file when the CSS is changed. Your system should also contain
 
-  * a backup method of re-generating the CSS cache in case it is removed, so
 
-  * that it is easy to force a re-cache by simply deleting the contents of the
 
-  * directory.
 
-  *
 
-  * Finally, if for some reason your application cannot store the filename
 
-  * (which is true of Panels where the style can't force the display to
 
-  * resave unconditionally) you can use the ctools storage mechanism. You
 
-  * simply have to come up with a unique Id:
 
-  *
 
-  * @code
 
-  *   $filename = ctools_css_store($id, $css, TRUE);
 
-  * @endcode
 
-  *
 
-  * Then later on:
 
-  * @code
 
-  *   $filename = ctools_css_retrieve($id);
 
-  *   drupal_add_css($filename);
 
-  * @endcode
 
-  *
 
-  * The CSS that was generated will be stored in the database, so even if the
 
-  * file was removed the cached CSS will be used. If the CSS cache is
 
-  * cleared you may be required to regenerate your CSS. This will normally
 
-  * only be cleared by an administrator operation, not during normal usage.
 
-  *
 
-  * You may remove your stored CSS this way:
 
-  *
 
-  * @code
 
-  *   ctools_css_clear($id);
 
-  * @endcode
 
-  */
 
- /**
 
-  * Store CSS with a given id and return the filename to use.
 
-  *
 
-  * This function associates a piece of CSS with an id, and stores the
 
-  * cached filename and the actual CSS for later use with
 
-  * ctools_css_retrieve.
 
-  */
 
- function ctools_css_store($id, $css, $filter = TRUE) {
 
-   $filename = db_query('SELECT filename FROM {ctools_css_cache} WHERE cid = :cid', array(':cid' => $id))->fetchField();
 
-   if ($filename && file_exists($filename)) {
 
-     file_unmanaged_delete($filename);
 
-   }
 
-   // Remove any previous records.
 
-   db_delete('ctools_css_cache')
 
-     ->condition('cid', $id)
 
-     ->execute();
 
-   $filename = ctools_css_cache($css, $filter);
 
-   db_merge('ctools_css_cache')
 
-     ->key(array('cid' => $id))
 
-     ->fields(array(
 
-       'filename' => $filename,
 
-       'css' => $css,
 
-       'filter' => intval($filter),
 
-     ))
 
-     ->execute();
 
-   return $filename;
 
- }
 
- /**
 
-  * Retrieve a filename associated with an id of previously cached CSS.
 
-  *
 
-  * This will ensure the file still exists and, if not, create it.
 
-  */
 
- function ctools_css_retrieve($id) {
 
-   $cache = db_query('SELECT * FROM {ctools_css_cache} WHERE cid = :cid', array(':cid' => $id))->fetchObject();
 
-   if (!$cache) {
 
-     return;
 
-   }
 
-   if (!file_exists($cache->filename)) {
 
-     $filename = ctools_css_cache($cache->css, $cache->filter);
 
-     if ($filename != $cache->filename) {
 
-       db_update('ctools_css_cache')
 
-         ->fields(array('filename' => $filename))
 
-         ->condition('cid', $id)
 
-         ->execute();
 
-       $cache->filename = $filename;
 
-     }
 
-   }
 
-   return $cache->filename;
 
- }
 
- /**
 
-  * Remove stored CSS and any associated file.
 
-  */
 
- function ctools_css_clear($id) {
 
-   $cache = db_query('SELECT * FROM {ctools_css_cache} WHERE cid = :cid', array(':cid' => $id))->fetchObject();
 
-   if (!$cache) {
 
-     return;
 
-   }
 
-   if (file_exists($cache->filename)) {
 
-     file_unmanaged_delete($cache->filename);
 
-     // If we remove an existing file, there may be cached pages that refer
 
-     // to it. We must get rid of them: FIXME same format in D7?
 
-     cache_clear_all();
 
-   }
 
-   db_delete('ctools_css_cache')
 
-     ->condition('cid', $id)
 
-     ->execute();
 
- }
 
- /**
 
-  * Write a chunk of CSS to a temporary cache file and return the file name.
 
-  *
 
-  * This function optionally filters the CSS (always compressed, if so) and
 
-  * generates a unique filename based upon md5. It returns that filename that
 
-  * can be used with drupal_add_css(). Note that as a cache file, technically
 
-  * this file is volatile so it should be checked before it is used to ensure
 
-  * that it exists.
 
-  *
 
-  * You can use file_exists() to test for the file and file_delete() to remove
 
-  * it if it needs to be cleared.
 
-  *
 
-  * @param $css
 
-  *   A chunk of well-formed CSS text to cache.
 
-  * @param $filter
 
-  *   If TRUE the css will be filtered. If FALSE the text will be cached
 
-  *   as-is.
 
-  *
 
-  * @return $filename
 
-  *   The filename the CSS will be cached in.
 
-  */
 
- function ctools_css_cache($css, $filter = TRUE) {
 
-   if ($filter) {
 
-     $css = ctools_css_filter($css);
 
-   }
 
-   // Create the css/ within the files folder.
 
-   $path = 'public://ctools/css';
 
-   if (!file_prepare_directory($path, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
 
- //  if (!file_prepare_directory($path, FILE_CREATE_DIRECTORY)) {
 
-     drupal_set_message(t('Unable to create CTools CSS cache directory. Check the permissions on your files directory.'), 'error');
 
-     return;
 
-   }
 
-   // @todo Is this slow? Does it matter if it is?
 
-   $filename = $path . '/' . md5($css) . '.css';
 
-   // Generally md5 is considered unique enough to sign file downloads.
 
-   // So this replaces already existing files based on the assumption that two
 
-   // files with the same hash are identical content wise.
 
-   // If we rename, the cache folder can potentially fill up with thousands of
 
-   // files with the same content.
 
-   $filename = file_unmanaged_save_data($css, $filename, FILE_EXISTS_REPLACE);
 
-   return $filename;
 
- }
 
- /**
 
-  * Filter a chunk of CSS text.
 
-  *
 
-  * This function disassembles the CSS into a raw format that makes it easier
 
-  * for our tool to work, then runs it through the filter and reassembles it.
 
-  * If you find that you want the raw data for some reason or another, you
 
-  * can use the disassemble/assemble functions yourself.
 
-  *
 
-  * @param $css
 
-  *   The CSS text to filter.
 
-  * @param $compressed
 
-  *   If true, generate compressed output; if false, generate pretty output.
 
-  *   Defaults to TRUE.
 
-  */
 
- function ctools_css_filter($css, $compressed = TRUE) {
 
-   $css_data = ctools_css_disassemble($css);
 
-   // Note: By using this function yourself you can control the allowed
 
-   // properties and values list.
 
-   $filtered = ctools_css_filter_css_data($css_data);
 
-   return $compressed ? ctools_css_compress($filtered) : ctools_css_assemble($filtered);
 
- }
 
- /**
 
-  * Re-assemble a css string and format it nicely.
 
-  *
 
-  * @param array $css_data
 
-  *   An array of css data, as produced by @see ctools_css_disassemble()
 
-  *   disassembler and the @see ctools_css_filter_css_data() filter.
 
-  *
 
-  * @return string $css
 
-  *   css optimized for human viewing.
 
-  */
 
- function ctools_css_assemble($css_data) {
 
-   // Initialize the output.
 
-   $css = '';
 
-   // Iterate through all the statements.
 
-   foreach ($css_data as $selector_str => $declaration) {
 
-     // Add the selectors, separating them with commas and line feeds.
 
-     $css .= strpos($selector_str, ',') === FALSE ? $selector_str : str_replace(", ", ",\n", $selector_str);
 
-     // Add the opening curly brace.
 
-     $css .= " {\n";
 
-     // Iterate through all the declarations.
 
-     foreach ($declaration as $property => $value) {
 
-       $css .= "  " . $property . ": " . $value . ";\n";
 
-     }
 
-     // Add the closing curly brace.
 
-     $css .= "}\n\n";
 
-   }
 
-   // Return the output.
 
-   return $css;
 
- }
 
- /**
 
-  * Compress css data (filter it first!) to optimize for use on view.
 
-  *
 
-  * @param array $css_data
 
-  *   An array of css data, as produced by @see ctools_css_disassemble()
 
-  *   disassembler and the @see ctools_css_filter_css_data() filter.
 
-  *
 
-  * @return string $css
 
-  *   css optimized for use.
 
-  */
 
- function ctools_css_compress($css_data) {
 
-   // Initialize the output.
 
-   $css = '';
 
-   // Iterate through all the statements.
 
-   foreach ($css_data as $selector_str => $declaration) {
 
-     if (empty($declaration)) {
 
-       // Skip this statement if filtering removed all parts of the declaration.
 
-       continue;
 
-     }
 
-     // Add the selectors, separating them with commas.
 
-     $css .= $selector_str;
 
-     // And, the opening curly brace.
 
-     $css .= "{";
 
-     // Iterate through all the statement properties.
 
-     foreach ($declaration as $property => $value) {
 
-       $css .= $property . ':' . $value . ';';
 
-     }
 
-     // Add the closing curly brace.
 
-     $css .= "}";
 
-   }
 
-   // Return the output.
 
-   return $css;
 
- }
 
- /**
 
-  * Disassemble the css string.
 
-  *
 
-  * Strip the css of irrelevant characters, invalid/malformed selectors and
 
-  * declarations, and otherwise prepare it for processing.
 
-  *
 
-  * @param string $css
 
-  *   A string containing the css to be disassembled.
 
-  *
 
-  * @return array $disassembled_css
 
-  *   An array of disassembled, slightly cleaned-up/formatted css statements.
 
-  */
 
- function ctools_css_disassemble($css) {
 
-   $disassembled_css = array();
 
-   // Remove comments.
 
-   $css = preg_replace("/\/\*(.*)?\*\//Usi", "", $css);
 
-   // Split out each statement. Match either a right curly brace or a semi-colon
 
-   // that precedes a left curly brace with no right curly brace separating them.
 
-   $statements = preg_split('/}|;(?=[^}]*{)/', $css);
 
-   // If we have any statements, parse them.
 
-   if (!empty($statements)) {
 
-     // Iterate through all of the statements.
 
-     foreach ($statements as $statement) {
 
-       // Get the selector(s) and declaration.
 
-       if (empty($statement) || !strpos($statement, '{')) {
 
-         continue;
 
-       }
 
-       list($selector_str, $declaration) = explode('{', $statement);
 
-       // If the selector exists, then disassemble it, check it, and regenerate
 
-       // the selector string.
 
-       $selector_str = empty($selector_str) ? FALSE : _ctools_css_disassemble_selector($selector_str);
 
-       if (empty($selector_str)) {
 
-         // No valid selectors. Bomb out and start the next item.
 
-         continue;
 
-       }
 
-       // Disassemble the declaration, check it and tuck it into an array.
 
-       if (!isset($disassembled_css[$selector_str])) {
 
-         $disassembled_css[$selector_str] = array();
 
-       }
 
-       $disassembled_css[$selector_str] += _ctools_css_disassemble_declaration($declaration);
 
-     }
 
-   }
 
-   return $disassembled_css;
 
- }
 
- function _ctools_css_disassemble_selector($selector_str) {
 
-   // Get all selectors individually.
 
-   $selectors = explode(",", trim($selector_str));
 
-   // Iterate through all the selectors, sanity check them and return if they
 
-   // pass. Note that this handles 0, 1, or more valid selectors gracefully.
 
-   foreach ($selectors as $key => $selector) {
 
-     // Replace un-needed characters and do a little cleanup.
 
-     $selector = preg_replace("/[\n|\t|\\|\s]+/", ' ', trim($selector));
 
-     // Make sure this is still a real selector after cleanup.
 
-     if (!empty($selector)) {
 
-       $selectors[$key] = $selector;
 
-     }
 
-     else {
 
-       // Selector is no good, so we scrap it.
 
-       unset($selectors[$key]);
 
-     }
 
-   }
 
-   // Check for malformed selectors; if found, we skip this declaration.
 
-   if (empty($selectors)) {
 
-     return FALSE;
 
-   }
 
-   return implode(', ', $selectors);
 
- }
 
- function _ctools_css_disassemble_declaration($declaration) {
 
-   $formatted_statement = array();
 
-   $propval_pairs = explode(";", $declaration);
 
-   // Make sure we actually have some properties to work with.
 
-   if (!empty($propval_pairs)) {
 
-     // Iterate through the remains and parse them.
 
-     foreach ($propval_pairs as $key => $propval_pair) {
 
-       // Check that we have a ':', otherwise it's an invalid pair.
 
-       if (strpos($propval_pair, ':') === FALSE) {
 
-         continue;
 
-       }
 
-       // Clean up the current property-value pair.
 
-       $propval_pair = preg_replace("/[\n|\t|\\|\s]+/", ' ', trim($propval_pair));
 
-       // Explode the remaining fragements some more, but clean them up first.
 
-       list($property, $value) = explode(':', $propval_pair, 2);
 
-       // If the property survived, toss it onto the stack.
 
-       if (!empty($property)) {
 
-         $formatted_statement[trim($property)] = trim($value);
 
-       }
 
-     }
 
-   }
 
-   return $formatted_statement;
 
- }
 
- /**
 
-  * Run disassembled $css through the filter.
 
-  *
 
-  * @param $css
 
-  *   CSS code disassembled by ctools_dss_disassemble().
 
-  * @param $allowed_properties
 
-  *   A list of properties that are allowed by the filter. If empty
 
-  *   ctools_css_filter_default_allowed_properties() will provide the
 
-  *   list.
 
-  * @param $allowed_values
 
-  *   A list of values that are allowed by the filter. If empty
 
-  *   ctools_css_filter_default_allowed_values() will provide the
 
-  *   list.
 
-  *
 
-  * @return
 
-  *   An array of disassembled, filtered CSS.
 
-  */
 
- function ctools_css_filter_css_data($css, $allowed_properties = array(), $allowed_values = array(), $allowed_values_regex = '', $disallowed_values_regex = '') {
 
- //function ctools_css_filter_css_data($css, &$filtered = NULL, $allowed_properties = array(), $allowed_values = array(), $allowed_values_regex = '', $disallowed_values_regex = '') {
 
-   // Retrieve the default list of allowed properties if none is provided.
 
-   $allowed_properties = !empty($allowed_properties) ? $allowed_properties : ctools_css_filter_default_allowed_properties();
 
-   // Retrieve the default list of allowed values if none is provided.
 
-   $allowed_values = !empty($allowed_values) ? $allowed_values : ctools_css_filter_default_allowed_values();
 
-   // Define allowed values regex if none is provided.
 
-   $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|%|,|\))?)/';
 
-   // Define disallowed url() value contents, if none is provided.
 
-   // $disallowed_values_regex = !empty($disallowed_values_regex) ? $disallowed_values_regex : '/[url|expression]\s*\(\s*[^\s)]+?\s*\)\s*/';
 
-   $disallowed_values_regex = !empty($disallowed_values_regex) ? $disallowed_values_regex : '/(url|expression)/';
 
-   foreach ($css as $selector_str => $declaration) {
 
-     foreach ($declaration as $property => $value) {
 
-       if (!in_array($property, $allowed_properties)) {
 
-         // $filtered['properties'][$selector_str][$property] = $value;
 
-         unset($css[$selector_str][$property]);
 
-         continue;
 
-       }
 
-       $value = str_replace('!important', '', $value);
 
-       if (preg_match($disallowed_values_regex, $value) || !(in_array($value, $allowed_values) || preg_match($allowed_values_regex, $value))) {
 
-         // $filtered['values'][$selector_str][$property] = $value;
 
-         unset($css[$selector_str][$property]);
 
-         continue;
 
-       }
 
-     }
 
-   }
 
-   return $css;
 
- }
 
- /**
 
-  * Provide a deafult list of allowed properties by the filter.
 
-  */
 
- function ctools_css_filter_default_allowed_properties() {
 
-   return array(
 
-     'azimuth',
 
-     'background',
 
-     'background-color',
 
-     'background-image',
 
-     'background-repeat',
 
-     'background-attachment',
 
-     'background-position',
 
-     'border',
 
-     'border-top-width',
 
-     'border-right-width',
 
-     'border-bottom-width',
 
-     'border-left-width',
 
-     'border-width',
 
-     'border-top-color',
 
-     'border-right-color',
 
-     'border-bottom-color',
 
-     'border-left-color',
 
-     'border-color',
 
-     'border-top-style',
 
-     'border-right-style',
 
-     'border-bottom-style',
 
-     'border-left-style',
 
-     'border-style',
 
-     'border-top',
 
-     'border-right',
 
-     'border-bottom',
 
-     'border-left',
 
-     'clear',
 
-     'color',
 
-     'cursor',
 
-     'direction',
 
-     'display',
 
-     'elevation',
 
-     'float',
 
-     'font',
 
-     'font-family',
 
-     'font-size',
 
-     'font-style',
 
-     'font-variant',
 
-     'font-weight',
 
-     'height',
 
-     'letter-spacing',
 
-     'line-height',
 
-     'margin',
 
-     'margin-top',
 
-     'margin-right',
 
-     'margin-bottom',
 
-     'margin-left',
 
-     'overflow',
 
-     'padding',
 
-     'padding-top',
 
-     'padding-right',
 
-     'padding-bottom',
 
-     'padding-left',
 
-     'pause',
 
-     'pause-after',
 
-     'pause-before',
 
-     'pitch',
 
-     'pitch-range',
 
-     'richness',
 
-     'speak',
 
-     'speak-header',
 
-     'speak-numeral',
 
-     'speak-punctuation',
 
-     'speech-rate',
 
-     'stress',
 
-     'text-align',
 
-     'text-decoration',
 
-     'text-indent',
 
-     'text-transform',
 
-     'unicode-bidi',
 
-     'vertical-align',
 
-     'voice-family',
 
-     'volume',
 
-     'white-space',
 
-     'width',
 
-     'fill',
 
-     'fill-opacity',
 
-     'fill-rule',
 
-     'stroke',
 
-     'stroke-width',
 
-     'stroke-linecap',
 
-     'stroke-linejoin',
 
-     'stroke-opacity',
 
-   );
 
- }
 
- /**
 
-  * Provide a default list of allowed values by the filter.
 
-  */
 
- function ctools_css_filter_default_allowed_values() {
 
-   return array(
 
-     'auto',
 
-     'aqua',
 
-     'black',
 
-     'block',
 
-     'blue',
 
-     'bold',
 
-     'both',
 
-     'bottom',
 
-     'brown',
 
-     'capitalize',
 
-     'center',
 
-     'collapse',
 
-     'dashed',
 
-     'dotted',
 
-     'fuchsia',
 
-     'gray',
 
-     'green',
 
-     'italic',
 
-     'inherit',
 
-     'left',
 
-     'lime',
 
-     'lowercase',
 
-     'maroon',
 
-     'medium',
 
-     'navy',
 
-     'normal',
 
-     'nowrap',
 
-     'olive',
 
-     'pointer',
 
-     'purple',
 
-     'red',
 
-     'right',
 
-     'solid',
 
-     'silver',
 
-     'teal',
 
-     'top',
 
-     'transparent',
 
-     'underline',
 
-     'uppercase',
 
-     'white',
 
-     'yellow',
 
-   );
 
- }
 
- /**
 
-  * Delegated implementation of hook_flush_caches()
 
-  */
 
- function ctools_css_flush_caches() {
 
-   // Remove all generated files.
 
-   // @see http://drupal.org/node/573292
 
-   // file_unmanaged_delete_recursive('public://render');
 
-   $filedir = file_default_scheme() . '://ctools/css';
 
-   if (drupal_realpath($filedir) && file_exists($filedir)) {
 
-     // We use the @ because it's possible that files created by the webserver
 
-     // cannot be deleted while using drush to clear the cache. We don't really
 
-     // care that much about that, to be honest, so we use the @ to suppress
 
-     // the error message.
 
-     @file_unmanaged_delete_recursive($filedir);
 
-   }
 
-   db_delete('ctools_css_cache')->execute();
 
- }
 
 
  |