panels_page.css_filter.inc

Go to the documentation of this file.
00001 <?php
00002 /* $Id: panels_page.css_filter.inc,v 1.1.2.5 2008/08/05 09:35:17 sdboyer Exp $ */
00003 
00004 /*
00005  * @file panels_page/panels_page.css_filter.inc
00006  * CSS filtering functions. Contains a disassembler, filter, compressor, and
00007  * decompressor. Separated out into this file for cleanliness, as it's likely
00008  * that these won't live in panels_page for long.
00009  */
00010 
00011 /**
00012  * Re-assemble a css string and format it nicely.
00013  *
00014  * @param array $css_data
00015  *   An array of css data, as produced by @see panels_page_disassemble_css()
00016  *   disassembler and the @see panels_page_filter_css() filter.
00017  * @return string $css
00018  *   css optimized for human viewing.
00019  */
00020 function panels_page_assemble_css($css_data) {
00021   // Initialize the output.
00022   $css = '';
00023   // Iterate through all the statements.
00024   foreach ($css_data as $selector_str => $declaration) {
00025     // Add the selectors, separating them with commas and line feeds.
00026     $css .= strpos($selector_str, ',') === FALSE ? $selector_str : preg_replace(", ", ",\n", $selector_str);
00027     // Add the opening curly brace.
00028     $css .= " {\n";
00029     // Iterate through all the declarations.
00030     foreach ($declaration as $property => $value) {
00031       $css .= "  " . $property . ": " . $value . ";\n";
00032     }
00033     // Add the closing curly brace.
00034     $css .= "}\n\n";
00035   }
00036   // Return the output.
00037   return $css;
00038 }
00039 
00040 /**
00041  * Compress css data (filter it first!) to optimize for use on view.
00042  *
00043  * @param array $css_data
00044  *   An array of css data, as produced by @see panels_page_disassemble_css()
00045  *   disassembler and the @see panels_page_filter_css() filter.
00046  * @return string $css
00047  *   css optimized for use.
00048  */
00049 function panels_page_compress_css($css_data) {
00050   // Initialize the output.
00051   $css = '';
00052   // Iterate through all the statements.
00053   foreach ($css_data as $selector_str => $declaration) {
00054     if (empty($declaration)) {
00055       // Skip this statement if filtering removed all parts of the declaration.
00056       continue;
00057     }
00058     // Add the selectors, separating them with commas.
00059     $css .= $selector_str;
00060     // And, the opening curly brace.
00061     $css .= "{";
00062     // Iterate through all the statement properties.
00063     foreach ($declaration as $property => $value) {
00064       $css .= $property . ':' . $value . ';';
00065     }
00066     // Add the closing curly brace.
00067     $css .= "}";
00068   }
00069   // Return the output.
00070   return $css;
00071 }
00072 
00073 /**
00074  * Disassemble the css string.
00075  *
00076  * Strip the css of irrelevant characters, invalid/malformed selectors and
00077  * declarations, and otherwise prepare it for processing.
00078  *
00079  * @param string $css
00080  *   A string containing the css to be disassembled.
00081  * @return array $disassembled_css
00082  *   An array of disassembled, slightly cleaned-up/formatted css statements.
00083  */
00084 function panels_page_disassemble_css($css) {
00085   $disassembled_css = array();
00086   // Remove comments.
00087   $css = preg_replace("/\/\*(.*)?\*\//Usi", "", $css);
00088   // Split out each statement
00089   $statements = explode("}", $css);
00090   // If we have any statements, parse them.
00091   if (!empty($statements)) {
00092     // Iterate through all of the statements.
00093     foreach ($statements as $statement) {
00094       // Get the selector(s) and declaration.
00095       list($selector_str, $declaration) = explode('{', $statement);
00096       
00097       // If the selector exists, then disassemble it, check it, and regenerate
00098       // the selector string.
00099       $selector_str = empty($selector_str) ? FALSE : panels_page_disassemble_css_selector($selector_str);
00100       if (empty($selector_str)) {
00101         // No valid selectors. Bomb out and start the next item.
00102         continue;
00103       }
00104       
00105       // Disassemble the declaration, check it and tuck it into an array.
00106       $disassembled_css[$selector_str] = panels_page_disassemble_css_declaration(strtolower($declaration));
00107     }
00108   }
00109   return $disassembled_css;
00110 }
00111 
00112 
00113 function panels_page_disassemble_css_selector($selector_str) {
00114   // Get all selectors individually.
00115   $selectors = explode(",", trim($selector_str));
00116   // Iterate through all the selectors, sanity check them and return if they
00117   // pass. Note that this handles 0, 1, or more valid selectors gracefully.
00118   foreach ($selectors as $key => $selector) {
00119     // Replace un-needed characters and do a little cleanup.
00120     $selector = preg_replace("/[\n|\t|\\|\s]+/", ' ', strtolower(trim($selector)));
00121     // Make sure this is still a real selector after cleanup.
00122     if (!empty($selector)) {
00123       $selectors[$key] = $selector;
00124     }
00125     else {
00126       // Selector is no good, so we scrap it.
00127       unset ($selectors[$key]);
00128     }
00129   }
00130     // Check for malformed selectors; if found, we skip this declaration.
00131   if (empty($selectors)) {
00132     return FALSE;
00133   }
00134   return implode(', ', $selectors);
00135 }
00136 
00137 
00138 function panels_page_disassemble_css_declaration($declaration) {
00139   $formatted_statement = array();
00140   $propval_pairs = explode(";", $declaration);
00141   // Make sure we actually have some properties to work with.
00142   if (!empty($propval_pairs)) {
00143     // Iterate through the remains and parse them.
00144     foreach ($propval_pairs as $key => $propval_pair) {
00145       // Check that we have a ':', otherwise it's an invalid pair.
00146       if (strpos($propval_pair, ':') === FALSE) {
00147         continue;
00148       }
00149       // Clean up the current property-value pair.
00150       $propval_pair =  preg_replace("/[\n|\t|\\|\s]+/", ' ', strtolower(trim($propval_pair)));
00151       // Explode the remaining fragements some more, but clean them up first.
00152       list($property, $value) = explode(':', $propval_pair);
00153       // If the property survived, toss it onto the stack.
00154       if(!empty($property)) {
00155         $formatted_statement[trim($property)] = trim($value);
00156       }
00157     }
00158   }
00159   return $formatted_statement;
00160 }
00161 
00162 /**
00163  *
00164  */
00165 function panels_page_filter_css($css, $allowed_properties = array(), $allowed_values = array(), $allowed_values_regex = '', $disallowed_values_regex = '') {
00166 //  function panels_page_filter_css($css, &$filtered = NULL, $allowed_properties = array(), $allowed_values = array(), $allowed_values_regex = '', $disallowed_values_regex = '') {
00167   // Retrieve the default list of allowed properties if none is provided.
00168   $allowed_properties = !empty($allowed_properties) ? $allowed_properties : panels_page_css_filter_default_allowed_properties();
00169   // Retrieve the default list of allowed values if none is provided.
00170   $allowed_values = !empty($allowed_values) ? $allowed_values : panels_page_css_filter_default_allowed_values();
00171   // Define allowed values regex if none is provided.
00172   $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|%|,|\))?)/';
00173   // Define disallowed url() value contents, if none is provided.
00174   // $disallowed_values_regex = !empty($disallowed_values_regex) ? $disallowed_values_regex : '/[url|expression]\s*\(\s*[^\s)]+?\s*\)\s*/';
00175   $disallowed_values_regex = !empty($disallowed_values_regex) ? $disallowed_values_regex : '/(url|expression)/';
00176   
00177   foreach ($css as $selector_str => $declaration) {
00178     foreach ($declaration as $property => $value) {
00179       if (!in_array($property, $allowed_properties)) {
00180         // $filtered['properties'][$selector_str][$property] = $value;
00181         unset($css[$selector_str][$property]);
00182         continue;
00183       }
00184       $value = str_replace('!important', '', $value);
00185       if (preg_match($disallowed_values_regex, $value) || !(in_array($value, $allowed_values) || preg_match($allowed_values_regex, $value))) {
00186         // $filtered['values'][$selector_str][$property] = $value;
00187         unset($css[$selector_str][$property]);
00188         continue;
00189       }
00190     }
00191   }
00192   return $css;
00193 }
00194 
00195 
00196 function panels_page_css_filter_default_allowed_properties() {
00197   return array(
00198     'azimuth',
00199     'background',
00200     'background-color',
00201     'background-image',
00202     'background-repeat',
00203     'background-attachment',
00204     'background-position',
00205     'border',
00206     'border-top-width',
00207     'border-right-width',
00208     'border-bottom-width',
00209     'border-left-width',
00210     'border-width',
00211     'border-top-color',
00212     'border-right-color',
00213     'border-bottom-color',
00214     'border-left-color',
00215     'border-color',
00216     'border-top-style',
00217     'border-right-style',
00218     'border-bottom-style',
00219     'border-left-style',
00220     'border-style',
00221     'border-top',
00222     'border-right',
00223     'border-bottom',
00224     'border-left',
00225     'clear',
00226     'color',
00227     'cursor',
00228     'direction',
00229     'display',
00230     'elevation',
00231     'float',
00232     'font',
00233     'font-family',
00234     'font-size',
00235     'font-style',
00236     'font-variant',
00237     'font-weight',
00238     'height',
00239     'letter-spacing',
00240     'line-height',
00241     'margin',
00242     'margin-top',
00243     'margin-right',
00244     'margin-bottom',
00245     'margin-left',
00246     'overflow',
00247     'padding',
00248     'padding-top',
00249     'padding-right',
00250     'padding-bottom',
00251     'padding-left',
00252     'pause',
00253     'pause-after',
00254     'pause-before',
00255     'pitch',
00256     'pitch-range',
00257     'richness',
00258     'speak',
00259     'speak-header',
00260     'speak-numeral',
00261     'speak-punctuation',
00262     'speech-rate',
00263     'stress',
00264     'text-align',
00265     'text-decoration',
00266     'text-indent',
00267     'unicode-bidi',
00268     'vertical-align',
00269     'voice-family',
00270     'volume',
00271     'white-space',
00272     'width',
00273     'fill',
00274     'fill-opacity',
00275     'fill-rule',
00276     'stroke',
00277     'stroke-width',
00278     'stroke-linecap',
00279     'stroke-linejoin',
00280     'stroke-opacity',
00281   );
00282 }
00283 
00284 function panels_page_css_filter_default_allowed_values() {
00285   return array(
00286     'auto',
00287     'aqua',
00288     'black',
00289     'block',
00290     'blue',
00291     'bold',
00292     'both',
00293     'bottom',
00294     'brown',
00295     'center',
00296     'collapse',
00297     'dashed',
00298     'dotted',
00299     'fuchsia',
00300     'gray',
00301     'green',
00302     'italic',
00303     'left',
00304     'lime',
00305     'maroon',
00306     'medium',
00307     'navy',
00308     'normal',
00309     'nowrap',
00310     'olive',
00311     'pointer',
00312     'purple',
00313     'red',
00314     'right',
00315     'solid',
00316     'silver',
00317     'teal',
00318     'top',
00319     'transparent',
00320     'underline',
00321     'white',
00322     'yellow',
00323   );
00324 }

Generated on Sun Sep 5 05:00:14 2010 for Panels 2 by  doxygen 1.5.6