CSSParser

The Contact Form 7 Style CSSParser class.

Defined (1)

The class is defined in the following location(s).

/inc/cssparser.php  
  1. class CSSParser { 
  2. protected static $cssCounter = 0; 
  3. protected static $propCounter = 0; 
  4. protected $cssData; 
  5.  
  6. function __construct() { 
  7. $this->cssData = array(); 
  8.  
  9. public function ParseCSS($css) { 
  10. $index = ++self::$cssCounter; 
  11. $this->cssData[$index] = array('all'=>array(), 'screen'=>array(), 'print'=>array()); 
  12. return $this->ParseCode($index, $css); 
  13.  
  14. public function ParseCSSAppend($index, $css) { 
  15. if(isset($this->cssData[$index])) { 
  16. return $this->ParseCode($index, $css); 
  17. } else { 
  18. return $this->ParseCSS($css); 
  19.  
  20. public function ParseCSSMediaAppend($index, $css, $media) { 
  21. $css = '@'.$media.' {'.PHP_EOL.$css.PHP_EOL.'}'.PHP_EOL; 
  22. if(isset($this->cssData[$index])) { 
  23. return $this->ParseCode($index, $css); 
  24. $index = ++self::$cssCounter; 
  25. $this->cssData[$index] = array('all'=>array(), 'screen'=>array(), 'print'=>array()); 
  26. return $this->ParseCode($index, $css); 
  27.  
  28. protected function ParseCode($index, $css) { 
  29. $currentMedia = 'all'; 
  30. $mediaList = array(); 
  31. $section = false; 
  32. $css = trim($css); 
  33. if(strlen($css) == 0) { 
  34. return $index; 
  35. $css = preg_replace('/\/\*.*\*\//Us', '', $css); 
  36. while(preg_match('/^\s*(\@(media|import|local)([^\{\}]+)(\{)|([^\{\}]+)(\{)|([^\{\}]*)(\}))/Usi', $css, $match)) { 
  37. if(isset($match[8]) && ($match[8] == '}')) { 
  38. if($section !== false) { 
  39. $code = trim($match[7]); 
  40. $idx = 0; 
  41. $inQuote = false; 
  42. $property = false; 
  43. $codeLen = strlen($code); 
  44. $parenthesis = array(); 
  45. while($idx < $codeLen) { 
  46. $c = $code{$idx}; 
  47. $idx++; 
  48. if($inQuote !== false) { 
  49. if($inQuote === $c) { 
  50. $inQuote = false; 
  51. } elseif(($inQuote === false) && ($c == '(')) { 
  52. array_push($parenthesis, '('); 
  53. } elseif(($inQuote === false) && ($c == ')')) { 
  54. array_pop($parenthesis); 
  55. } elseif(($c == '\'') || ($c == '"')) { 
  56. $inQuote = $c; 
  57. } elseif(($property === false) && ($c == ':')) { 
  58. $property = trim(substr($code, 0, $idx - 1)); 
  59. if(preg_match('/^(.*)\[([0-9]*)\]$/Us', $property, $propMatch)) { 
  60. $property = $propMatch[1].'['.static::$propCounter.']'; 
  61. static::$propCounter += 1; 
  62. $code = substr($code, $idx); 
  63. $idx = 0; 
  64. } elseif((count($parenthesis) == 0) && ($c == ';')) { 
  65. $value = trim(substr($code, 0, $idx - 1)); 
  66. $code = substr($code, $idx); 
  67. $idx = 0; 
  68. $this->AddProperty($index, $currentMedia, $section, $property, $value); 
  69. $property = false; 
  70. if(($idx > 0) && ($property !== false)) { 
  71. $value = trim($code); 
  72. $this->AddProperty($index, $currentMedia, $section, $property, $value); 
  73. $section = false; 
  74. } elseif(count($mediaList) > 0) { 
  75. array_pop($mediaList); 
  76. if(count($mediaList) > 0) { 
  77. $currentMedia = end($mediaList); 
  78. } else { 
  79. $currentMedia = 'all'; 
  80. } else { 
  81. // Superfluous } 
  82. } elseif(isset($match[6]) && ($match[6] == '{')) { 
  83. // Section 
  84. $section = trim($match[5]); 
  85. if(!isset($this->cssData[$index][$currentMedia][$section])) { 
  86. $this->cssData[$index][$currentMedia][$section] = array(); 
  87. } elseif(isset($match[4]) && ($match[4] == '{')) { 
  88. if($match[2] == 'media') { 
  89. // New media 
  90. $media = trim($match[3]); 
  91. $mediaList[] = $media; 
  92. $currentMedia = $media; 
  93. if(!isset($this->cssData[$index][$currentMedia])) { 
  94. $this->cssData[$index][$currentMedia] = array(); 
  95. } elseif($match[2] == 'import') { 
  96. // Can't support import (yet!) 
  97. } elseif($match[2] == 'local') { 
  98. // Can't support local import (yet!) 
  99. } else { 
  100. // Shouldn't get here 
  101. $stripCount = strlen($match[0]); 
  102. $css = trim(substr($css, $stripCount)); 
  103. $css = trim($css); 
  104. if(strlen($css) > 0) { 
  105. echo "Potential error in stylesheet:     ".$css; 
  106. return $index; 
  107.  
  108. public function AddProperty($index, $media, $section, $property, $value) { 
  109. if(!isset($this->cssData[$index])) { 
  110. $this->cssData[$index] = array('all'=>array(), 'screen'=>array(), 'print'=>array()); 
  111. $media = trim($media); 
  112. if($media == '') { 
  113. $media = 'all'; 
  114. $section = trim($section); 
  115. $property = trim($property); 
  116. if(strlen($property) > 0) { 
  117. $value = trim($value); 
  118. if($media == 'all') { 
  119. $this->cssData[$index][$media][$section][$property] = $value; 
  120. $keys = array_keys($this->cssData[$index]); 
  121. foreach($keys as $key) { 
  122. if(!isset($this->cssData[$index][$key][$section])) { 
  123. $this->cssData[$index][$key][$section] = array(); 
  124. $this->cssData[$index][$key][$section][$property] = $value; 
  125. } else { 
  126. if(!isset($this->cssData[$index][$media])) { 
  127. $this->cssData[$index][$media] = $this->cssData[$index]['all']; 
  128. if(!isset($this->cssData[$index][$media][$section])) { 
  129. $this->cssData[$index][$media][$section] = array(); 
  130. $this->cssData[$index][$media][$section][$property] = $value; 
  131.  
  132. public function GetMediaList($index) { 
  133. if(isset($this->cssData[$index])) { 
  134. return array_keys($this->cssData[$index]); 
  135. return array(); 
  136.  
  137. public function ExportKeyValues($index, $media, $keys) { 
  138. $result = array(); 
  139. if(is_string($keys)) { 
  140. $keys = array($keys); 
  141. if(!is_array($keys)) { 
  142. return $result; 
  143. if(isset($this->cssData[$index]) && isset($this->cssData[$index][$media])) { 
  144. foreach($this->cssData[$index][$media] as $section => $sectionValues) { 
  145. foreach($sectionValues as $property => $value) { 
  146. if(in_array($property, $keys)) { 
  147. $result[] = $value; 
  148. return $result; 
  149.  
  150. public function ExportMedia($index, $media, $block = false) { 
  151. $result = ''; 
  152. if(isset($this->cssData[$index]) && isset($this->cssData[$index][$media])) { 
  153. foreach($this->cssData[$index][$media] as $section => $sectionValues) { 
  154. $result .= "$section {\n"; 
  155. foreach($sectionValues as $property => $value) { 
  156. $property = preg_replace('/(\[[0-9]*\])$/Usi', '', $property); 
  157. if(is_array($block) && isset($block[$property])) { 
  158. if(preg_match('/^'.static::ConvertWildcards($block[$property]).'$/Usi', $value) == 0) { 
  159. $result .= $indent." $property: $value;\n"; 
  160. } else { 
  161. $result .= " $property: $value;\n"; 
  162. $result .= "}\n\n"; 
  163. return $result; 
  164.  
  165. public function ExportStyle($index, $block = false) { 
  166. $result = ''; 
  167. if(isset($this->cssData[$index])) { 
  168. foreach($this->cssData[$index] as $media => $mediaValues) { 
  169. if($media != 'all') { 
  170. $result .= "@media $media {\n"; 
  171. $indent = ' '; 
  172. } else { 
  173. $indent = ''; 
  174. foreach($mediaValues as $section => $sectionValues) { 
  175. $result .= $indent."$section {\n"; 
  176. foreach($sectionValues as $property => $value) { 
  177. $property = preg_replace('/(\[[0-9]*\])$/Usi', '', $property); 
  178. if(is_array($block) && isset($block[$property])) { 
  179. if(preg_match('/^'.static::ConvertWildcards($block[$property]).'$/Usi', $value) == 0) { 
  180. $result .= $indent." $property: $value;\n"; 
  181. } else { 
  182. $result .= $indent." $property: $value;\n"; 
  183. $result .= $indent."}\n\n"; 
  184. if($media != 'all') { 
  185. $result .= "}\n\n"; 
  186. return $result; 
  187.  
  188.  
  189. public function GetSections($index, $media = 'screen') { 
  190. if(isset($this->cssData[$index])) { 
  191. if(isset($this->cssData[$index][$media])) { 
  192. return array_keys($this->cssData[$index][$media]); 
  193. if(isset($this->cssData[$index]['all'])) { 
  194. return array_keys($this->cssData[$index]['all']); 
  195. return false; 
  196.  
  197. public function GetSectionsFiltered($index, $matchKey, $matchValue, $media = 'screen') { 
  198. if(isset($this->cssData[$index])) { 
  199. if(!isset($this->cssData[$index][$media])) { 
  200. $media = 'all'; 
  201. if(!isset($this->cssData[$index][$media])) { 
  202. return false; 
  203. if(is_array($this->cssData[$index][$media])) { 
  204. $result = array(); 
  205. foreach($this->cssData[$index][$media] as $section => $values) { 
  206. if(isset($values[$matchKey])) { 
  207. if($values[$matchKey] == $matchValue) { 
  208. $result[] = $section; 
  209. return $result; 
  210. return false; 
  211.  
  212. public function GetEditorCSS($index) { 
  213. $forbiddenKeys = array(); 
  214. $forbiddenKeys[] = '^filter$'; 
  215. return $this->GetCSS($index, 'screen', $forbiddenKeys); 
  216.  
  217. public function GetCSS($index, $media = 'screen', $forbiddenKeys = array()) { 
  218. if(isset($this->cssData[$index])) { 
  219. if(!isset($this->cssData[$index][$media])) { 
  220. $media = 'all'; 
  221. if(!isset($this->cssData[$index][$media])) { 
  222. return false; 
  223. if(is_array($this->cssData[$index][$media])) { 
  224. $result = ''; 
  225. foreach($this->cssData[$index][$media] as $section => $values) { 
  226. $result .= $section.' {'; 
  227. $result .= "\n"; 
  228. if(is_array($values)) { 
  229. foreach($values as $key => $value) { 
  230. $skipThis = false; 
  231. foreach($forbiddenKeys as $fKey) { 
  232. if(preg_match('/'.$fKey.'/Usi', $key)) { 
  233. $skipThis = true; 
  234. break; 
  235. if($skipThis) { 
  236. continue; 
  237. $result .= ' '; 
  238. $key = preg_replace('/(\[[0-9]*\])$/Usi', '', $key); 
  239. $result .= $key.': '.$value.';'; 
  240. $result .= "\n"; 
  241. $result .= '}'; 
  242. $result .= "\n"; 
  243. return $result; 
  244. return false; 
  245.  
  246. public function GetCSSFiltered($index, $matchKey, $matchValue, $media = 'screen') { 
  247. if(!isset($this->cssData[$index])) { 
  248. if(!isset($this->cssData[$index][$media])) { 
  249. $media = 'all'; 
  250. if(!isset($this->cssData[$index][$media])) { 
  251. return false; 
  252. $sections = $this->GetSectionsFiltered($index, $matchKey, $matchValue, $media); 
  253. if($sections !== false) { 
  254. if(is_array($sections)) { 
  255. $result = ''; 
  256. foreach($sections as $section) { 
  257. $result .= $section.' {'; 
  258. $temp = $this->cssData[$index][$media]; 
  259. if(is_array($temp)) { 
  260. foreach($temp as $key => $value) { 
  261. $key = preg_replace('/(\[[0-9]*\])$/Usi', '', $key); 
  262. $result .= $key.': '.$value.';'; 
  263. $result .= $section.' }'; 
  264. return $result; 
  265. return false; 
  266.  
  267. public function GetCSSArray($index, $media = 'screen') { 
  268. if(isset($this->cssData[$index])) { 
  269. if(isset($this->cssData[$index][$media])) { 
  270. return $this->cssData[$index][$media]; 
  271. } elseif(isset($this->cssData[$index]['all'])) { 
  272. return $this->cssData[$index][$media]; 
  273. return false; 
  274.  
  275. public static function ConvertWildcards($text) { 
  276. $text = str_replace('.', '\.', $text); 
  277. $text = str_replace('*', '.*', $text); 
  278. $text = str_replace('?', '.', $text); 
  279. return $text;