PageRenderTime 47ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/libs/IncludeCssJs.php

https://gitlab.com/fork/hotarucms
PHP | 398 lines | 201 code | 70 blank | 127 comment | 53 complexity | 9cae0ee0361465e1e58821ea9c1b1ccc MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /**
  3. * Functions for including and merging CSS and JavaScript
  4. *
  5. * PHP version 5
  6. *
  7. * LICENSE: Hotaru CMS is free software: you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation, either version 3 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * Hotaru CMS is distributed in the hope that it will be useful, but WITHOUT
  13. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. * FITNESS FOR A PARTICULAR PURPOSE.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with Hotaru CMS. If not, see http://www.gnu.org/licenses/.
  18. *
  19. * @category Content Management System
  20. * @package HotaruCMS
  21. * @author Hotaru CMS Team
  22. * @copyright Copyright (c) 2009 - 2013, Hotaru CMS
  23. * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
  24. * @link http://www.hotarucms.org/
  25. */
  26. class IncludeCssJs
  27. {
  28. protected $cssIncludes = array(); // a list of css files to include
  29. protected $cssIncludesAdmin = array(); // a list of css files to include in Admin
  30. protected $jsIncludes = array(); // a list of js files to include
  31. protected $jsIncludesAdmin = array(); // a list of js files to include in Admin
  32. protected $includeType = ''; // 'css' or 'js'
  33. /**
  34. * Include individual CSS files, not merged into the CSS archive
  35. *
  36. * @param $files- array of files to include (no extensions)
  37. * @param $folder - optional pluin folder
  38. */
  39. public function includeOnceCss($h, $files = array(), $folder = '')
  40. {
  41. if (empty($files)) { return false; }
  42. if (!$folder) { $folder = $h->plugin->folder; }
  43. if (!$folder) { return false; }
  44. foreach ($files as $file) {
  45. if (file_exists(THEMES . THEME . 'css/' . $file . '.css')) {
  46. echo "<link rel='stylesheet' href='" . SITEURL . "content/themes/" . THEME . "css/" . $file . ".css' type='text/css' />\n";
  47. } else {
  48. echo "<link rel='stylesheet' href='" . SITEURL . "content/plugins/" . $folder . "/css/" . $file . ".css' type='text/css' />\n";
  49. }
  50. }
  51. return true;
  52. }
  53. /**
  54. * Include individual JavaScript files, not merged into the JavaScript archive
  55. *
  56. * @param $files- array of files to include (no extensions)
  57. * @param $folder - optional pluin folder
  58. */
  59. public function includeOnceJs($h, $files = array(), $folder = '')
  60. {
  61. if (empty($files)) { return false; }
  62. if (!$folder) { $folder = $h->plugin->folder; }
  63. if (!$folder) { return false; }
  64. foreach ($files as $file) {
  65. if (file_exists(THEMES . THEME . 'javascript/' . $file . '.js')) {
  66. echo "<script src='" . SITEURL . "content/themes/" . THEME . "javascript/" . $file . ".js' type='text/javascript' language='javascript'></script>\n";
  67. } else {
  68. echo "<script src='" . SITEURL . "content/plugins/" . $folder . "/javascript/" . $file . ".js' type='text/javascript' language='javascript'></script>\n";
  69. }
  70. }
  71. return true;
  72. }
  73. /**
  74. * setCssIncludes
  75. *
  76. * @param string $file - full path to the CSS file
  77. */
  78. public function setCssIncludes($file, $admin = false)
  79. {
  80. if ($admin) {
  81. array_push($this->cssIncludesAdmin, $file);
  82. } else {
  83. array_push($this->cssIncludes, $file);
  84. }
  85. }
  86. /**
  87. * getCssIncludes
  88. */
  89. public function getCssIncludes($admin = false)
  90. {
  91. if ($admin) {
  92. return $this->cssIncludesAdmin;
  93. } else {
  94. return $this->cssIncludes;
  95. }
  96. }
  97. /**
  98. * setJsIncludes
  99. *
  100. * @param string $file - full path to the JS file
  101. */
  102. public function setJsIncludes($file, $admin = false)
  103. {
  104. if ($admin) {
  105. array_push($this->jsIncludesAdmin, $file);
  106. } else {
  107. array_push($this->jsIncludes, $file);
  108. }
  109. }
  110. /**
  111. * getJsIncludes
  112. */
  113. public function getJsIncludes($admin = false)
  114. {
  115. if ($admin) {
  116. return $this->jsIncludesAdmin;
  117. } else {
  118. return $this->jsIncludes;
  119. }
  120. }
  121. /**
  122. * Build an array of css files to combine
  123. *
  124. * @param $folder - the folder name of the plugin
  125. * @param $filename - optional css file without an extension
  126. */
  127. public function includeCss($h, $folder = '', $filename = '')
  128. {
  129. if (!$folder) { $folder = $h->plugin->folder; }
  130. // If no filename provided, the filename is assigned the plugin name.
  131. if (!$filename) { $filename = $folder; }
  132. $file_location = $this->findCssFile($folder, $filename);
  133. // Add this css file to the global array of css_files
  134. $this->setCssIncludes($file_location, $h->adminPage);
  135. return $folder; // returned for testing purposes only
  136. }
  137. /**
  138. * Build an array of JavaScript files to combine
  139. *
  140. * @param $folder - the folder name of the plugin
  141. * @param $filename - optional js file without an extension
  142. */
  143. public function includeJs($h, $folder = '', $filename = '')
  144. {
  145. if (!$folder) { $folder = $h->plugin->folder; }
  146. // If no filename provided, the filename is assigned the plugin name.
  147. if (!$filename) { $filename = $folder; }
  148. $file_location = $this->findJsFile($folder, $filename);
  149. // Add this js file to the global array of js_files
  150. $this->setJsIncludes($file_location, $h->adminPage);
  151. return $folder; // returned for testing purposes only
  152. }
  153. /**
  154. * Find CSS file
  155. *
  156. * @param string $folder name of plugin folder
  157. * @param string $filename optional filename without file extension
  158. *
  159. * Note: the css file should be in a folder named 'css' and a file of
  160. * the format plugin_name.css, e.g. rss_show.css
  161. */
  162. public function findCssFile($folder = '', $filename = '')
  163. {
  164. if (!$folder) { return false; }
  165. // If filename not given, make the plugin name the file name
  166. if (!$filename) { $filename = $folder; }
  167. // First look in the theme folder for a css file...
  168. if (file_exists(THEMES . THEME . 'css/' . $filename . '.css')) {
  169. $file_location = THEMES . THEME . 'css/' . $filename . '.css';
  170. // If not found, look in the default theme folder for a css file...
  171. } elseif (file_exists(THEMES . 'default/css/' . $filename . '.css')) {
  172. $file_location = THEMES . 'default/css/' . $filename . '.css';
  173. // If still not found, look in the plugin folder for a css file...
  174. } elseif (file_exists(PLUGINS . $folder . '/css/' . $filename . '.css')) {
  175. $file_location = PLUGINS . $folder . '/css/' . $filename . '.css';
  176. // If still not found, look in the full given folder itself for a js file...
  177. } elseif (file_exists($folder . '/css/' . $filename . '.css')) {
  178. $file_location = $folder . '/css/' . $filename . '.css';
  179. }
  180. if (isset($file_location)) {
  181. return $file_location;
  182. }
  183. }
  184. /**
  185. * Find JavaScript file
  186. *
  187. * @param string $folder name of plugin folder
  188. * @param string $filename optional filename without file extension
  189. *
  190. * Note: the js file should be in a folder named 'javascript' and a file of the format plugin_name.js, e.g. category_manager.js
  191. */
  192. public function findJsFile($folder = '', $filename = '')
  193. {
  194. if (!$folder) { return false; }
  195. // If filename not given, make the plugin name the file name
  196. if (!$filename) { $filename = $folder; }
  197. // First look in the theme folder for a js file...
  198. if (file_exists(THEMES . THEME . 'javascript/' . $filename . '.js')) {
  199. $file_location = THEMES . THEME . 'javascript/' . $filename . '.js';
  200. // If not found, look in the default theme folder for a js file...
  201. } elseif (file_exists(THEMES . 'default/javascript/' . $filename . '.js')) {
  202. $file_location = THEMES . 'default/javascript/' . $filename . '.js';
  203. // If still not found, look in the plugin folder for a js file...
  204. } elseif (file_exists(PLUGINS . $folder . '/javascript/' . $filename . '.js')) {
  205. $file_location = PLUGINS . $folder . '/javascript/' . $filename . '.js';
  206. // If still not found, look in the full given folder itself for a js file...
  207. } elseif (file_exists($folder . $filename . '.js')) {
  208. $file_location = $folder . $filename . '.js';
  209. }
  210. if (isset($file_location)) {
  211. return $file_location;
  212. }
  213. }
  214. /**
  215. * Combine Included CSS & JSS files
  216. *
  217. * @param string $type either 'css' or 'js'
  218. * @return bool
  219. * @link http://www.ejeliot.com/blog/72 Based on work by Ed Eliot
  220. */
  221. public function combineIncludes($h, $type = 'css')
  222. {
  223. // set up cache
  224. $cache_length = 31356000; // about one year
  225. $cache = CACHE . 'css_js_cache/';
  226. // run plugin functions to include css/js files
  227. if ($h->adminPage) {
  228. $h->pluginHook('admin_header_include');
  229. $prefix = 'hotaru_admin_';
  230. } else {
  231. $h->pluginHook('header_include');
  232. $prefix = 'hotaru_';
  233. }
  234. // append css or js to cache filename
  235. $prefix .= ($type == 'css') ? 'css_' : 'js_';
  236. // fill "includes" array with all the files we need to merge
  237. if($type == 'css') {
  238. $content_type = 'text/css';
  239. $includes = $this->getCssIncludes($h->adminPage);
  240. } else {
  241. $type = 'js';
  242. $content_type = 'text/javascript';
  243. //don't forget to get the globals js file as well
  244. $this->includeJs($h, $cache, 'JavascriptConstants') ;
  245. $this->includeJs($h, BASE . 'javascript/' , "hotaru");
  246. if ($h->adminPage) {
  247. $this->includeJs($h, ADMIN_THEMES . ADMIN_THEME. "javascript/" , rtrim(ADMIN_THEME, "/"));
  248. }
  249. $includes = $this->getJsIncludes($h->adminPage);
  250. }
  251. // remove duplicate include files
  252. $includes = array_unique($includes);
  253. if(empty($includes)) { return false; }
  254. // get last modified dates for all files to include
  255. $aLastModifieds = array();
  256. foreach ($includes as $sFile) {
  257. $aLastModifieds[] = filemtime($sFile);
  258. }
  259. // sort dates, newest first
  260. rsort($aLastModifieds);
  261. // the most recently updated include file
  262. $last_modified_include_file = $aLastModifieds[0];
  263. // GET ACTUAL CODE - IF IT'S CACHED, SHOW THE CACHED CODE, OTHERWISE, GET INCLUDE FILES, BUILD AN ARCHIVE AND SHOW IT
  264. // get code from archive folder if it exists, otherwise grab latest files, merge and save in archive folder
  265. if ((CSS_JS_CACHE == "true") && file_exists($cache . $prefix . $last_modified_include_file . '.' . $type))
  266. {
  267. // use the exiting cache file
  268. return $last_modified_include_file;
  269. }
  270. // get and merge code
  271. $sCode = '';
  272. $aLastModifieds = array();
  273. // if not in debug mode, get the Jsmin class
  274. if (!$h->isDebug) {
  275. require_once(EXTENSIONS . 'Jsmin/Jsmin.php');
  276. }
  277. foreach ($includes as $sFile) {
  278. if ($sFile) {
  279. $aLastModifieds[] = filemtime($sFile);
  280. if ($h->isDebug) {
  281. $sCode .= "/* Open: " . $sFile . " */\n\n";
  282. $sCode .= file_get_contents($sFile); // don't minify files when debugging
  283. $sCode .= "\n\n/* Close: " . $sFile . " */\n\n";
  284. } else {
  285. $sCode .= JSMin::minify(file_get_contents($sFile)); // minify files
  286. }
  287. }
  288. }
  289. // sort dates, newest first
  290. rsort($aLastModifieds);
  291. // check for valid file time, we don't want invalid requests to fill up archive folder
  292. if ($last_modified_include_file == $aLastModifieds[0])
  293. {
  294. $oFile = fopen($cache . $prefix . $last_modified_include_file . '.' . $type, 'w');
  295. if (flock($oFile, LOCK_EX)) {
  296. fwrite($oFile, $sCode);
  297. flock($oFile, LOCK_UN);
  298. }
  299. fclose($oFile);
  300. }
  301. else
  302. {
  303. // archive file no longer exists or invalid etag specified
  304. header("{$h->cage->server->getRaw('SERVER_PROTOCOL')} 404 Not Found");
  305. exit;
  306. }
  307. // cache file written, return the time so we can add it within SCRIPT in the header
  308. return $last_modified_include_file;
  309. }
  310. /**
  311. * Included combined files
  312. *
  313. * @param int $version_js
  314. * @param int $version_css
  315. * @param bool $admin
  316. */
  317. public function includeCombined($h, $version_js = 0, $version_css = 0, $admin = false)
  318. {
  319. if ($admin) { $prefix = 'hotaru_admin_'; } else { $prefix = 'hotaru_'; }
  320. if ($version_js > 0) {
  321. echo "<script type='text/javascript' async src='" . SITEURL . "cache/css_js_cache/" . $prefix . "js_" . $version_js . ".js'></script>\n";
  322. }
  323. if ($version_css > 0) {
  324. echo "<link rel='stylesheet' href='" . SITEURL . "cache/css_js_cache/" . $prefix . "css_" . $version_css . ".css' type='text/css' />\n";
  325. }
  326. }
  327. }
  328. ?>