PageRenderTime 81ms CodeModel.GetById 48ms RepoModel.GetById 2ms app.codeStats 0ms

/includes/classes/class.optimize.php

https://github.com/victoralex/gameleon
PHP | 537 lines | 431 code | 84 blank | 22 comment | 71 complexity | e19b03b1abd7823911d0ef18ca3d590b MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. class cssparser
  3. {
  4. var $css;
  5. var $html;
  6. function __construct($html = true) {
  7. // Register "destructor"
  8. register_shutdown_function(array(&$this, "finalize"));
  9. $this->html = ($html != false);
  10. $this->Clear();
  11. }
  12. function finalize() {
  13. unset($this->css);
  14. }
  15. function Clear() {
  16. unset($this->css);
  17. $this->css = array();
  18. if($this->html) {
  19. $this->Add("ADDRESS", "");
  20. $this->Add("APPLET", "");
  21. $this->Add("AREA", "");
  22. $this->Add("A", "text-decoration : underline; color : Blue;");
  23. $this->Add("A:visited", "color : Purple;");
  24. $this->Add("BASE", "");
  25. $this->Add("BASEFONT", "");
  26. $this->Add("BIG", "");
  27. $this->Add("BLOCKQUOTE", "");
  28. $this->Add("BODY", "");
  29. $this->Add("BR", "");
  30. $this->Add("B", "font-weight: bold;");
  31. $this->Add("CAPTION", "");
  32. $this->Add("CENTER", "");
  33. $this->Add("CITE", "");
  34. $this->Add("CODE", "");
  35. $this->Add("DD", "");
  36. $this->Add("DFN", "");
  37. $this->Add("DIR", "");
  38. $this->Add("DIV", "");
  39. $this->Add("DL", "");
  40. $this->Add("DT", "");
  41. $this->Add("EM", "");
  42. $this->Add("FONT", "");
  43. $this->Add("FORM", "");
  44. $this->Add("H1", "");
  45. $this->Add("H2", "");
  46. $this->Add("H3", "");
  47. $this->Add("H4", "");
  48. $this->Add("H5", "");
  49. $this->Add("H6", "");
  50. $this->Add("HEAD", "");
  51. $this->Add("HR", "");
  52. $this->Add("HTML", "");
  53. $this->Add("IMG", "");
  54. $this->Add("INPUT", "");
  55. $this->Add("ISINDEX", "");
  56. $this->Add("I", "font-style: italic;");
  57. $this->Add("KBD", "");
  58. $this->Add("LINK", "");
  59. $this->Add("LI", "");
  60. $this->Add("MAP", "");
  61. $this->Add("MENU", "");
  62. $this->Add("META", "");
  63. $this->Add("OL", "");
  64. $this->Add("OPTION", "");
  65. $this->Add("PARAM", "");
  66. $this->Add("PRE", "");
  67. $this->Add("P", "");
  68. $this->Add("SAMP", "");
  69. $this->Add("SCRIPT", "");
  70. $this->Add("SELECT", "");
  71. $this->Add("SMALL", "");
  72. $this->Add("STRIKE", "");
  73. $this->Add("STRONG", "");
  74. $this->Add("STYLE", "");
  75. $this->Add("SUB", "");
  76. $this->Add("SUP", "");
  77. $this->Add("TABLE", "");
  78. $this->Add("TD", "");
  79. $this->Add("TEXTAREA", "");
  80. $this->Add("TH", "");
  81. $this->Add("TITLE", "");
  82. $this->Add("TR", "");
  83. $this->Add("TT", "");
  84. $this->Add("UL", "");
  85. $this->Add("U", "text-decoration : underline;");
  86. $this->Add("VAR", "");
  87. }
  88. }
  89. function SetHTML($html) {
  90. $this->html = ($html != false);
  91. }
  92. function Add($key, $codestr) {
  93. // $key = strtolower($key);
  94. // $codestr = strtolower($codestr);
  95. if(!isset($this->css[$key])) {
  96. $this->css[$key] = array();
  97. }
  98. $codes = explode(";",$codestr);
  99. if(count($codes) > 0) {
  100. foreach($codes as $code) {
  101. $code = trim($code);
  102. @ list($codekey, $codevalue) = explode(":",$code);
  103. if(strlen($codekey) > 0) {
  104. $this->css[$key][trim($codekey)] = trim($codevalue);
  105. }
  106. }
  107. }
  108. }
  109. function Get($key, $property) {
  110. // $key = strtolower($key);
  111. // $property = strtolower($property);
  112. list($tag, $subtag) = explode(":",$key);
  113. list($tag, $class) = explode(".",$tag);
  114. list($tag, $id) = explode("#",$tag);
  115. $result = "";
  116. foreach($this->css as $_tag => $value) {
  117. list($_tag, $_subtag) = explode(":",$_tag);
  118. list($_tag, $_class) = explode(".",$_tag);
  119. list($_tag, $_id) = explode("#",$_tag);
  120. $tagmatch = (strcmp($tag, $_tag) == 0) | (strlen($_tag) == 0);
  121. $subtagmatch = (strcmp($subtag, $_subtag) == 0) | (strlen($_subtag) == 0);
  122. $classmatch = (strcmp($class, $_class) == 0) | (strlen($_class) == 0);
  123. $idmatch = (strcmp($id, $_id) == 0);
  124. if($tagmatch & $subtagmatch & $classmatch & $idmatch) {
  125. $temp = $_tag;
  126. if((strlen($temp) > 0) & (strlen($_class) > 0)) {
  127. $temp .= ".".$_class;
  128. } elseif(strlen($temp) == 0) {
  129. $temp = ".".$_class;
  130. }
  131. if((strlen($temp) > 0) & (strlen($_subtag) > 0)) {
  132. $temp .= ":".$_subtag;
  133. } elseif(strlen($temp) == 0) {
  134. $temp = ":".$_subtag;
  135. }
  136. if(isset($this->css[$temp][$property])) {
  137. $result = $this->css[$temp][$property];
  138. }
  139. }
  140. }
  141. return $result;
  142. }
  143. function GetSection($key) {
  144. // $key = strtolower($key);
  145. list($tag, $subtag) = explode(":",$key);
  146. list($tag, $class) = explode(".",$tag);
  147. list($tag, $id) = explode("#",$tag);
  148. $result = array();
  149. foreach($this->css as $_tag => $value) {
  150. list($_tag, $_subtag) = explode(":",$_tag);
  151. list($_tag, $_class) = explode(".",$_tag);
  152. list($_tag, $_id) = explode("#",$_tag);
  153. $tagmatch = (strcmp($tag, $_tag) == 0) | (strlen($_tag) == 0);
  154. $subtagmatch = (strcmp($subtag, $_subtag) == 0) | (strlen($_subtag) == 0);
  155. $classmatch = (strcmp($class, $_class) == 0) | (strlen($_class) == 0);
  156. $idmatch = (strcmp($id, $_id) == 0);
  157. if($tagmatch & $subtagmatch & $classmatch & $idmatch) {
  158. $temp = $_tag;
  159. if((strlen($temp) > 0) & (strlen($_class) > 0)) {
  160. $temp .= ".".$_class;
  161. } elseif(strlen($temp) == 0) {
  162. $temp = ".".$_class;
  163. }
  164. if((strlen($temp) > 0) & (strlen($_subtag) > 0)) {
  165. $temp .= ":".$_subtag;
  166. } elseif(strlen($temp) == 0) {
  167. $temp = ":".$_subtag;
  168. }
  169. foreach($this->css[$temp] as $property => $value) {
  170. $result[$property] = $value;
  171. }
  172. }
  173. }
  174. return $result;
  175. }
  176. function ParseStr($str) {
  177. $this->Clear();
  178. // Remove comments
  179. $str = preg_replace("/\/\*(.*)?\*\//Usi", "", $str);
  180. // Parse this damn csscode
  181. $parts = explode("}",$str);
  182. if(count($parts) > 0) {
  183. foreach($parts as $part) {
  184. @ list($keystr,$codestr) = explode("{",$part);
  185. $keys = explode(",",trim($keystr));
  186. if(count($keys) > 0) {
  187. foreach($keys as $key) {
  188. if(strlen($key) > 0) {
  189. $key = str_replace("\n", "", $key);
  190. $key = str_replace("\\", "", $key);
  191. $this->Add($key, trim($codestr));
  192. }
  193. }
  194. }
  195. }
  196. }
  197. //
  198. return (count($this->css) > 0);
  199. }
  200. function Parse($filename) {
  201. $this->Clear();
  202. if(file_exists($filename)) {
  203. return $this->ParseStr(file_get_contents($filename));
  204. } else {
  205. return false;
  206. }
  207. }
  208. function GetCSS() {
  209. $result = "";
  210. foreach($this->css as $key => $values) {
  211. $result .= $key." {\n";
  212. foreach($values as $key => $value) {
  213. $result .= " $key: $value;\n";
  214. }
  215. $result .= "}\n\n";
  216. }
  217. return $result;
  218. }
  219. }
  220. class Optimize
  221. {
  222. const ERR_OK = 0;
  223. const ERR_INVALID_ARGS = 1;
  224. const ERR_INVALID_SOURCE = 2;
  225. public static $ERR_LAST_ERROR = self::ERR_OK;
  226. public function init()
  227. {
  228. }
  229. private function separateCode( $inputContent, $globalContent, $contentType )
  230. {
  231. $css = new cssparser();
  232. $css->ParseStr( $inputContent );
  233. $ie7Code = $css->css;
  234. $ie8Code = $css->css;
  235. $ffCode = $css->css;
  236. foreach($css->css as $selector => $properties)
  237. {
  238. foreach( $properties as $property => $value )
  239. {
  240. if( substr( $property, 0, 2 ) == "##" )
  241. {
  242. unset( $ie7Code[ $selector ][ $property ] );
  243. unset( $ie8Code[ $selector ][ $property ] );
  244. unset( $ffCode[ $selector ][ $property ] );
  245. $ie8Code[ $selector ][ substr( $property, 2 ) ] = $value;
  246. continue;
  247. }
  248. if( substr( $property, 0, 1 ) == "#" )
  249. {
  250. unset( $ie7Code[ $selector ][ $property ] );
  251. unset( $ie8Code[ $selector ][ $property ] );
  252. unset( $ffCode[ $selector ][ $property ] );
  253. $ie7Code[ $selector ][ substr( $property, 1 ) ] = $value;
  254. continue;
  255. }
  256. unset( $ie7Code[ $selector ][ $property ] );
  257. unset( $ie8Code[ $selector ][ $property ] );
  258. }
  259. if( count($ie7Code[ $selector ]) == 0 )
  260. {
  261. unset( $ie7Code[ $selector ] );
  262. }
  263. if( count($ie8Code[ $selector ]) == 0 )
  264. {
  265. unset( $ie8Code[ $selector ] );
  266. }
  267. if( count($ffCode[ $selector ]) == 0 )
  268. {
  269. unset( $ffCode[ $selector ] );
  270. }
  271. }
  272. $css->css = $ie8Code;
  273. $globalContent[ $contentType ][ "ie8" ] .= $css->GetCSS();
  274. $css->css = $ie7Code;
  275. $globalContent[ $contentType ][ "ie7" ] .= $css->GetCSS();
  276. $css->css = $ffCode;
  277. $globalContent[ $contentType ][ "ff" ] .= $css->GetCSS();
  278. return $globalContent;
  279. }
  280. private function setError( $errorID )
  281. {
  282. self::$ERR_LAST_ERROR = $errorID;
  283. return $errorID;
  284. }
  285. private function readJS( $componentName, $rootFolder )
  286. {
  287. $validFiles = array();
  288. $jsBodyFilesContent = "\n\n";
  289. $jsHeadFilesContent = "\n\n";
  290. // Go through all the component's JS files
  291. $files = scandir( $rootFolder, 1 );
  292. foreach( $files as $fileJS )
  293. {
  294. $filePath = $rootFolder . DIRECTORY_SEPARATOR . $fileJS;
  295. if(
  296. is_dir( $filePath )
  297. || pathinfo( $filePath, PATHINFO_EXTENSION ) != "js"
  298. )
  299. {
  300. // not a javascript file
  301. continue;
  302. }
  303. $validFiles[] = $fileJS;
  304. }
  305. // Sort
  306. usort($validFiles, function($a, $b)
  307. {
  308. if($a == $b)
  309. {
  310. return 0;
  311. }
  312. $a = str_replace( ".js", "", $a );
  313. $b = str_replace( ".js", "", $b );
  314. if( strpos( $b, $a ) === 0 )
  315. {
  316. return ( strlen($a) > strlen($b) ) ? 1 : -1;
  317. }
  318. return ($a < $b) ? -1 : 1;
  319. });
  320. foreach($validFiles as $fileJS)
  321. {
  322. $filePath = $rootFolder . DIRECTORY_SEPARATOR . $fileJS;
  323. if(
  324. substr( $fileJS, 0, 8 ) == "imported" ||
  325. $fileJS == "application.js"
  326. )
  327. {
  328. $jsHeadFilesContent .= "\n\n/*\n\tFile: " . $filePath . "\n*/\n\n" . file_get_contents( $filePath );
  329. continue;
  330. }
  331. $jsBodyFilesContent .= "\n\n/*\n\tFile: " . $filePath . "\n*/\n\n" . file_get_contents( $filePath );
  332. }
  333. // recursively read all directories from this point on
  334. $files = scandir( $rootFolder, 1 );
  335. foreach( $files as $fileJS )
  336. {
  337. if($fileJS == '.' || $fileJS == '..' )
  338. {
  339. continue;
  340. }
  341. $filePath = $rootFolder . DIRECTORY_SEPARATOR . $fileJS;
  342. if( !is_dir( $filePath ) )
  343. {
  344. continue;
  345. }
  346. // recursively read directory
  347. $x = self::readJS( $componentName, $filePath );
  348. $jsHeadFilesContent = $jsHeadFilesContent . $x[ "head" ];
  349. $jsBodyFilesContent = $jsBodyFilesContent . $x[ "body" ];
  350. }
  351. return array( "head" => $jsHeadFilesContent, "body" => $jsBodyFilesContent );
  352. }
  353. public function JS( $prefix = "public_web" )
  354. {
  355. require_once( SystemConfig::$installDir . DIRECTORY_SEPARATOR . "includes" . DIRECTORY_SEPARATOR . "classes" . DIRECTORY_SEPARATOR . "class.jsmin.php" );
  356. $jsBodyFilesContent = '"use strict";';
  357. $jsHeadFilesContent = '"use strict";';
  358. $rootFolder = SystemConfig::$installDir . DIRECTORY_SEPARATOR . $prefix . DIRECTORY_SEPARATOR . "components";
  359. // Go through all the components
  360. $filesPointer = opendir( $rootFolder );
  361. while (($file = readdir($filesPointer)) !== false)
  362. {
  363. if($file == '.' || $file == '..' )
  364. {
  365. continue;
  366. }
  367. $x = self::readJS(
  368. $file,
  369. $rootFolder . DIRECTORY_SEPARATOR . $file . DIRECTORY_SEPARATOR . "resources" . DIRECTORY_SEPARATOR . "public"
  370. );
  371. $jsHeadFilesContent = $jsHeadFilesContent . $x[ "head" ];
  372. $jsBodyFilesContent = $jsBodyFilesContent . $x[ "body" ];
  373. }
  374. closedir($filesPointer);
  375. // Save the optimized body content
  376. file_put_contents(
  377. SystemConfig::$installDir . DIRECTORY_SEPARATOR . $prefix . DIRECTORY_SEPARATOR . "appSpecific" . DIRECTORY_SEPARATOR . "js" . DIRECTORY_SEPARATOR . "compiled_body.js",
  378. //JSMin::minify( $jsBodyFilesContent )
  379. $jsBodyFilesContent
  380. );
  381. // Save the optimized head content
  382. file_put_contents(
  383. SystemConfig::$installDir . DIRECTORY_SEPARATOR . $prefix . DIRECTORY_SEPARATOR . "appSpecific" . DIRECTORY_SEPARATOR . "js" . DIRECTORY_SEPARATOR . "compiled_head.js",
  384. //JSMin::minify( $jsHeadFilesContent )
  385. $jsHeadFilesContent
  386. );
  387. return self::setError( self::ERR_OK );
  388. }
  389. public function CSS( $prefix = "public_web" )
  390. {
  391. require_once( SystemConfig::$installDir . DIRECTORY_SEPARATOR . "includes" . DIRECTORY_SEPARATOR . "classes" . DIRECTORY_SEPARATOR . "class.cssmin.php" );
  392. $cssFilesContent = array(
  393. "screen" => array( "ie8" => "", "ie7" => "", "ff" => "" ),
  394. "print" => array( "ie8" => "", "ie7" => "", "ff" => "" )
  395. );
  396. $browsersSeparation = array(
  397. "ie8",
  398. "ie7",
  399. "ff"
  400. );
  401. $cssFiles = array_keys( $cssFilesContent );
  402. $rootFolder = SystemConfig::$installDir . DIRECTORY_SEPARATOR . $prefix . DIRECTORY_SEPARATOR . "components";
  403. // Go through all the components
  404. $filesPointer = opendir( $rootFolder );
  405. while (($file = readdir($filesPointer)) !== false)
  406. {
  407. if($file == '.' || $file == '..' )
  408. {
  409. continue;
  410. }
  411. foreach($cssFiles as $cssFile)
  412. {
  413. $componentPublicResourcesFolder = $rootFolder . DIRECTORY_SEPARATOR . $file . DIRECTORY_SEPARATOR . "resources" . DIRECTORY_SEPARATOR . "public";
  414. $componentPublicResourcesFolderIterator = dir( $componentPublicResourcesFolder );
  415. while( false !== ( $entry = $componentPublicResourcesFolderIterator->read() ) )
  416. {
  417. if( !preg_match( "/^" . $cssFile . "(.*)\.css$/", $entry ) )
  418. {
  419. continue;
  420. }
  421. // file name is $cssFile*.css (e.g. style_vendors.css)
  422. $cssFilesContent = self::separateCode(
  423. file_get_contents( $componentPublicResourcesFolder . DIRECTORY_SEPARATOR . $entry ),
  424. $cssFilesContent,
  425. $cssFile
  426. );
  427. }
  428. }
  429. }
  430. closedir($filesPointer);
  431. // Save the gathered content
  432. foreach($cssFiles as $cssFile)
  433. {
  434. $cssFilesContent = self::separateCode(
  435. file_get_contents( SystemConfig::$installDir . DIRECTORY_SEPARATOR . $prefix . DIRECTORY_SEPARATOR . "appSpecific" . DIRECTORY_SEPARATOR . "css" . DIRECTORY_SEPARATOR . $cssFile . ".css" ),
  436. $cssFilesContent,
  437. $cssFile
  438. );
  439. foreach($browsersSeparation as $browser)
  440. {
  441. file_put_contents(
  442. SystemConfig::$installDir . DIRECTORY_SEPARATOR . $prefix . DIRECTORY_SEPARATOR . "appSpecific" . DIRECTORY_SEPARATOR . "css" . DIRECTORY_SEPARATOR . "compiled_" . $cssFile . "_" . $browser . ".css",
  443. ( str_replace(
  444. "[rootURL]",
  445. SystemConfig::$applicationProtocol . "://" . ( ( ( $prefix == "public_admin" ) ? 'admin.' : '' ) . SystemConfig::$applicationURL ) . ":" . SystemConfig::$applicationPort,
  446. cssmin::minify( $cssFilesContent[ $cssFile ][ $browser ] )
  447. ) )
  448. );
  449. }
  450. }
  451. return self::setError( self::ERR_OK );
  452. }
  453. }