From 97d137f3657d6f4cdc70a5670db673845a45a8e5 Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Sun, 25 Sep 2011 13:40:34 -0400 Subject: [PATCH 1/5] Working on Automatic Caching feature for CSS and JS files. Added config options to main Shimmie config. --- core/page.class.php | 214 ++++++++++++++++++++++++++++---------------- core/util.inc.php | 6 +- ext/setup/main.php | 15 ++++ 3 files changed, 156 insertions(+), 79 deletions(-) diff --git a/core/page.class.php b/core/page.class.php index ae801576..ad58430f 100644 --- a/core/page.class.php +++ b/core/page.class.php @@ -150,6 +150,24 @@ class Page { $this->http_headers[$position] = $line; } + /** + * Get all the HTML headers that are currently set and return as a string. + */ + public function get_all_html_headers() { + $data = ''; + foreach ($this->html_headers as $line) { + $data .= $line . "\n"; + } + return $data; + } + + /** + * Removes all currently set HTML headers. (Be careful..) + */ + public function delete_all_html_headers() { + $this->html_headers = array(); + } + /** * Add a Block of data */ @@ -230,99 +248,139 @@ class Page { } } - /* - This function caches the CSS and JavaScript files. - This is done to reduce the number of HTTP requests (recommended by - the Yahoo high-performance guidelines). It combines all of the CSS - and JavaScript files into one for each type, and stores them in - cached files to serve the client. Changes to the CSS or JavaScript - files are caught by taking the md5sum of the concatenated files. - */ + /** + * Automatic caching of CSS and Javascript files + * + * Allows site admins to have Shimmie automatically cache and minify all CSS and JS files. + * This is done to reduce the number of HTTP requests (recommended by the Yahoo high-performance + * guidelines). It combines all of the CSS and JavaScript files into one for each type, and + * stores them in cached files to serve the client. Changes to the CSS or JavaScript files are + * caught by taking the md5sum of the concatenated files. + * + * Note: This can be somewhat problematic, as it edits the links to your CSS files (as well + * as the links to images inside them). + * Also, the directory cache directory needs to be writeable by the php/webserver user. + * PLEASE: Ensure that you test your site out throughly after enabling this module! + * Either that, or don't use this module unless you are sure of what it is doing. + * + * TODO: Before performing the regex's, compute the md5 of the CSS files and store somewhere to check later. (performance reasons.) + * + * @return + * This function returns FALSE if it failed to cache the files, + * and returns TRUE if it was successful. + */ private function add_cached_auto_html_headers() { - $cache_location = 'data/cache/'; - $data_href = get_base_href(); + global $config; + if (!$config->get_bool("autocache_css") || !$config->get_bool("autocache_js")) { + return false; // caching disabled + } + + $cache_location = $config->get_string("autocache_location", 'data/cache'); + // Detect is there is a trailing slash, and add one if not. + $cache_location = ((strrpos($cache_location, '/') + 1) == strlen($cache_location)) ? $cache_location : $cache_location.'/'; + + // Create directory if needed. if(!file_exists($cache_location)) { - if (!mkdir($cache_location, 0750, true)) { + if (is_writeable($cache_location) && !mkdir($cache_location, 0750, true)) { return false; // failed to create directory } } - /* ----- CSS Files ----- */ - // First get all the CSS from the lib directory - $data_1 = ''; - $css_files = glob("lib/*.css"); - if($css_files) { - foreach($css_files as $css_file) { - $data_1 .= file_get_contents($css_file); - } - // Can't directly cache the CSS files, as they might have relative locations to images, etc. in them. - // We have to adjust the URLs accordingly before saving the cached file. - $pattern = '/url[\s]*\([\s]*["\']?([^"\'\)]+)["\']?[\s]*\)/'; - $replace = 'url("../../lib/${1}")'; - $data_1 = preg_replace($pattern, $replace, $data_1); - } - // Next get all the CSS from the extensions - $data_2 = ''; - $css_files = glob("ext/*/style.css"); - if($css_files) { - foreach($css_files as $css_file) { - $data_2 .= file_get_contents($css_file); - } - // Can't directly cache the CSS files, as they might have relative locations to images, etc. in them. - // We have to adjust the URLs accordingly before saving the cached file. - $pattern = '/url[\s]*\([\s]*["\']?([^"\'\)]+)["\']?[\s]*\)/'; - $replace = 'url("../../${1}")'; - $data_2 = preg_replace($pattern, $replace, $data_2); - } - // Combine the two - $data = $data_1 . $data_2; - // compute the MD5 sum of the concatenated CSS files - $md5sum = md5($data); - - if (!file_exists($cache_location.$md5sum.'.css')) { - // remove any old cached CSS files. - $mask = '*.css'; - array_map( 'unlink', glob( $mask ) ); - - // output the combined file - if (file_put_contents($cache_location.$md5sum.'.css', $data, LOCK_EX) === FALSE) { - return false; - } - } - // tell the client where to get the css cache file - $this->add_html_header(''); + $data_href = get_base_href(); + /* ----- CSS Files ----- */ + if ($config->get_bool("autocache_css")) + { + // First get all the CSS from the lib directory + $contents_from_lib = ''; + $css_files = glob("lib/*.css"); + if($css_files) { + foreach($css_files as $css_file) { + $contents_from_lib .= file_get_contents($css_file); + } + // Can't directly cache the CSS files, as they might have relative locations to images, etc. in them. + // We have to adjust the URLs accordingly before saving the cached file. + $pattern = '/url[\s]*\([\s]*["\']?([^"\'\)]+)["\']?[\s]*\)/'; + $replace = 'url("../../lib/${1}")'; + $contents_from_lib = preg_replace($pattern, $replace, $contents_from_lib); + } + // Next get all the CSS from the extensions + $contents_from_extensions = ''; + $css_files = glob("ext/*/style.css"); + if($css_files) { + foreach($css_files as $css_file) { + $contents_from_extensions .= file_get_contents($css_file); + } + // Can't directly cache the CSS files, as they might have relative locations to images, etc. in them. + // We have to adjust the URLs accordingly before saving the cached file. + $pattern = '/url[\s]*\([\s]*["\']?([^"\'\)]+)["\']?[\s]*\)/'; + $replace = 'url("../../${1}")'; + $contents_from_extensions = preg_replace($pattern, $replace, $contents_from_extensions); + } + // Combine the two + $data = $contents_from_lib .' '. $contents_from_extensions; + + // Minify the CSS if enabled. + if ($config->get_bool("autocache_min_css")){ + // not supported yet. + } + + // compute the MD5 sum of the concatenated CSS files + $md5sum = md5($data); + + if (!file_exists($cache_location.$md5sum.'.css')) { + // remove any old cached CSS files. + $mask = '*.css'; + array_map( 'unlink', glob( $mask ) ); + + // output the combined file + if (file_put_contents($cache_location.$md5sum.'.css', $data, LOCK_EX) === FALSE) { + return false; // failed to write the file + } + } + // tell the client where to get the css cache file + $this->add_html_header(''); + } + /* ----- JavaScript Files ----- */ - $data = ''; - $js_files = glob("lib/*.js"); - if($js_files) { - foreach($js_files as $js_file) { - $data .= file_get_contents($js_file); + if ($config->get_bool("autocache_js")) + { + $data = ''; + $js_files = glob("lib/*.js"); + if($js_files) { + foreach($js_files as $js_file) { + $data .= file_get_contents($js_file); + } } - } - $js_files = glob("ext/*/script.js"); - if($js_files) { - foreach($js_files as $js_file) { - $data .= file_get_contents($js_file); + $js_files = glob("ext/*/script.js"); + if($js_files) { + foreach($js_files as $js_file) { + $data .= file_get_contents($js_file); + } } - } - // compute the MD5 sum of the concatenated JavaScript files - $md5sum = md5($data); - - if (!file_exists($cache_location.$md5sum.'.js')) { - // remove any old cached js files. - $mask = '*.js'; - array_map( 'unlink', glob( $mask ) ); - // output the combined file - if (file_put_contents($cache_location.$md5sum.'.js', $data, LOCK_EX) === FALSE) { - return false; + // Minify the JS if enabled. + if ($config->get_bool("autocache_min_js")){ + // not supported yet. } + + // compute the MD5 sum of the concatenated JavaScript files + $md5sum = md5($data); + + if (!file_exists($cache_location.$md5sum.'.js')) { + // remove any old cached js files. + $mask = '*.js'; + array_map( 'unlink', glob( $mask ) ); + // output the combined file + if (file_put_contents($cache_location.$md5sum.'.js', $data, LOCK_EX) === FALSE) { + return false; + } + } + // tell the client where to get the js cache file + $this->add_html_header(''); } - // tell the client where to get the js cache file - $this->add_html_header(''); return true; } diff --git a/core/util.inc.php b/core/util.inc.php index 7b51be91..ce44f378 100644 --- a/core/util.inc.php +++ b/core/util.inc.php @@ -555,11 +555,15 @@ function array_remove($array, $to_remove) { } /** - * Add an item to an array + * Adds an item to an array. + * + * Also removes duplicate values from the array. * * @retval array */ function array_add($array, $element) { + // Could we just use array_push() ? + // http://www.php.net/manual/en/function.array-push.php $array[] = $element; $array = array_unique($array); return $array; diff --git a/ext/setup/main.php b/ext/setup/main.php index efedd1a0..776f1e2d 100644 --- a/ext/setup/main.php +++ b/ext/setup/main.php @@ -173,6 +173,12 @@ class Setup extends SimpleExtension { $config->set_default_bool("word_wrap", true); $config->set_default_bool("use_captchas", false); $config->set_default_string("autodate_format", "F j, Y"); + // Automatic caching is disabled by default + $config->set_default_string("autocache_location", "data/cache"); + $config->set_default_bool("autocache_css", false); + $config->set_default_bool("autocache_jss", false); + $config->set_default_bool("autocache_min_css", false); + $config->set_default_bool("autocache_min_js", false); } public function onPageRequest($event) { @@ -280,6 +286,15 @@ class Setup extends SimpleExtension { $sb->add_text_option("api_recaptcha_privkey", "
Private key: "); $sb->add_text_option("api_recaptcha_pubkey", "
Public key: "); $event->panel->add_block($sb); + + $sb = new SetupBlock("Automatic CSS and JavaScript Caching"); + $sb->add_text_option("autocache_location", "
Location: "); + $sb->add_label("
Needs to be writeable by the webserver"); + $sb->add_bool_option("autocache_css", "
Enable automatic caching of CSS: "); + $sb->add_bool_option("autocache_js", "
Enable automatic caching of JS: "); + $sb->add_bool_option("autocache_min_css", "
Minimize CSS files: "); + $sb->add_bool_option("autocache_min_js", "
Minimize JS files: "); + $event->panel->add_block($sb); } public function onConfigSave($event) { From 944f3bdf3dfd1aebc0fc9007cda4b41d679d2f71 Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Sun, 25 Sep 2011 14:00:56 -0400 Subject: [PATCH 2/5] Fixed caching from not outputing JS if only CSS is enabled. --- core/page.class.php | 26 ++++++++++++++++++++++++-- ext/setup/main.php | 10 +++++----- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/core/page.class.php b/core/page.class.php index ad58430f..f15b31c5 100644 --- a/core/page.class.php +++ b/core/page.class.php @@ -273,7 +273,7 @@ class Page { { global $config; - if (!$config->get_bool("autocache_css") || !$config->get_bool("autocache_js")) { + if (!$config->get_bool("autocache_css") && !$config->get_bool("autocache_js")) { return false; // caching disabled } @@ -283,7 +283,7 @@ class Page { // Create directory if needed. if(!file_exists($cache_location)) { - if (is_writeable($cache_location) && !mkdir($cache_location, 0750, true)) { + if (!mkdir($cache_location, 0750, true)) { return false; // failed to create directory } } @@ -342,6 +342,17 @@ class Page { } // tell the client where to get the css cache file $this->add_html_header(''); + } else { + // Caching of CSS disabled. + foreach(glob("lib/*.css") as $css) { + $this->add_html_header(""); + } + $css_files = glob("ext/*/style.css"); + if($css_files) { + foreach($css_files as $css_file) { + $this->add_html_header(""); + } + } } @@ -380,6 +391,17 @@ class Page { } // tell the client where to get the js cache file $this->add_html_header(''); + } else { + // Caching of Javascript disabled. + foreach(glob("lib/*.js") as $js) { + $this->add_html_header(""); + } + $js_files = glob("ext/*/script.js"); + if($js_files) { + foreach($js_files as $js_file) { + $this->add_html_header(""); + } + } } return true; diff --git a/ext/setup/main.php b/ext/setup/main.php index 776f1e2d..d972ee99 100644 --- a/ext/setup/main.php +++ b/ext/setup/main.php @@ -287,11 +287,11 @@ class Setup extends SimpleExtension { $sb->add_text_option("api_recaptcha_pubkey", "
Public key: "); $event->panel->add_block($sb); - $sb = new SetupBlock("Automatic CSS and JavaScript Caching"); - $sb->add_text_option("autocache_location", "
Location: "); - $sb->add_label("
Needs to be writeable by the webserver"); - $sb->add_bool_option("autocache_css", "
Enable automatic caching of CSS: "); - $sb->add_bool_option("autocache_js", "
Enable automatic caching of JS: "); + $sb = new SetupBlock("Automatic CSS & JS Caching"); + $sb->add_text_option("autocache_location", "Location: "); + $sb->add_label("
Needs to be writeable by the webserver."); + $sb->add_bool_option("autocache_css", "
Automatic caching of CSS: "); + $sb->add_bool_option("autocache_js", "
Automatic caching of JS: "); $sb->add_bool_option("autocache_min_css", "
Minimize CSS files: "); $sb->add_bool_option("autocache_min_js", "
Minimize JS files: "); $event->panel->add_block($sb); From c1df2653a8ad373058aabb5d6e8902ed1a32237e Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Sun, 25 Sep 2011 14:16:20 -0400 Subject: [PATCH 3/5] Cleaned up the comments a bit. --- core/page.class.php | 2 +- ext/setup/main.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/page.class.php b/core/page.class.php index f15b31c5..dde20a97 100644 --- a/core/page.class.php +++ b/core/page.class.php @@ -263,7 +263,7 @@ class Page { * PLEASE: Ensure that you test your site out throughly after enabling this module! * Either that, or don't use this module unless you are sure of what it is doing. * - * TODO: Before performing the regex's, compute the md5 of the CSS files and store somewhere to check later. (performance reasons.) + * TODO: For performance reasons: Before performing the regex's, compute the md5 of the CSS & JS files and store somewhere to check later. * * @return * This function returns FALSE if it failed to cache the files, diff --git a/ext/setup/main.php b/ext/setup/main.php index d972ee99..adf4bb64 100644 --- a/ext/setup/main.php +++ b/ext/setup/main.php @@ -287,9 +287,9 @@ class Setup extends SimpleExtension { $sb->add_text_option("api_recaptcha_pubkey", "
Public key: "); $event->panel->add_block($sb); - $sb = new SetupBlock("Automatic CSS & JS Caching"); + $sb = new SetupBlock("Automatic Caching of CSS & JS"); $sb->add_text_option("autocache_location", "Location: "); - $sb->add_label("
Needs to be writeable by the webserver."); + $sb->add_label("
This location needs to be writeable by the webserver."); $sb->add_bool_option("autocache_css", "
Automatic caching of CSS: "); $sb->add_bool_option("autocache_js", "
Automatic caching of JS: "); $sb->add_bool_option("autocache_min_css", "
Minimize CSS files: "); From bba4301bfa45869fd861095e480a1e05f6460007 Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Thu, 6 Oct 2011 15:23:49 -0400 Subject: [PATCH 4/5] Disabled option for Minifying CSS and JavaScript. (not currently supported) --- core/page.class.php | 5 ++++- ext/setup/main.php | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/core/page.class.php b/core/page.class.php index dde20a97..b2a8d662 100644 --- a/core/page.class.php +++ b/core/page.class.php @@ -263,7 +263,8 @@ class Page { * PLEASE: Ensure that you test your site out throughly after enabling this module! * Either that, or don't use this module unless you are sure of what it is doing. * - * TODO: For performance reasons: Before performing the regex's, compute the md5 of the CSS & JS files and store somewhere to check later. + * TODO: Add support for minify-ing CSS and Javascript files. (similar to Minify. See: http://code.google.com/p/minify/ or https://github.com/mrclay/minify) + * TODO: For performance reasons: Before performing the regex's, compute the md5 of the CSS & JS files and store somewhere to check later. * * @return * This function returns FALSE if it failed to cache the files, @@ -325,6 +326,7 @@ class Page { // Minify the CSS if enabled. if ($config->get_bool("autocache_min_css")){ // not supported yet. + // TODO: add support for Minifying CSS files. } // compute the MD5 sum of the concatenated CSS files @@ -375,6 +377,7 @@ class Page { // Minify the JS if enabled. if ($config->get_bool("autocache_min_js")){ // not supported yet. + // TODO: add support for Minifying CSS files. } // compute the MD5 sum of the concatenated JavaScript files diff --git a/ext/setup/main.php b/ext/setup/main.php index adf4bb64..8b1f0eba 100644 --- a/ext/setup/main.php +++ b/ext/setup/main.php @@ -287,11 +287,27 @@ class Setup extends SimpleExtension { $sb->add_text_option("api_recaptcha_pubkey", "
Public key: "); $event->panel->add_block($sb); + + // Options for Automatic Caching & Minifying + $minifyscript = ""; + $sb = new SetupBlock("Automatic Caching of CSS & JS"); $sb->add_text_option("autocache_location", "Location: "); $sb->add_label("
This location needs to be writeable by the webserver."); $sb->add_bool_option("autocache_css", "
Automatic caching of CSS: "); $sb->add_bool_option("autocache_js", "
Automatic caching of JS: "); + $sb->add_label("Minifying currently not supported.$minifyscript"); $sb->add_bool_option("autocache_min_css", "
Minimize CSS files: "); $sb->add_bool_option("autocache_min_js", "
Minimize JS files: "); $event->panel->add_block($sb); From 589f218d1f3cf4c42cf73df2c993181c757420c8 Mon Sep 17 00:00:00 2001 From: "green-ponies (jgen)" Date: Thu, 6 Oct 2011 15:31:56 -0400 Subject: [PATCH 5/5] Small changes to disable the checkboxes by default. --- ext/setup/main.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ext/setup/main.php b/ext/setup/main.php index 8b1f0eba..e53061b1 100644 --- a/ext/setup/main.php +++ b/ext/setup/main.php @@ -293,12 +293,11 @@ class Setup extends SimpleExtension { checkbox_css = document.getElementById('autocache_min_css'); checkbox_js = document.getElementById('autocache_min_js'); - checkbox_css.disabled = true; - checkbox_js.disabled = true; - $(document).ready(function() { checkbox_css.disabled = true; + checkbox_css.checked = false; checkbox_js.disabled = true; + checkbox_js.checked = false; }); "; @@ -307,9 +306,9 @@ class Setup extends SimpleExtension { $sb->add_label("
This location needs to be writeable by the webserver."); $sb->add_bool_option("autocache_css", "
Automatic caching of CSS: "); $sb->add_bool_option("autocache_js", "
Automatic caching of JS: "); - $sb->add_label("Minifying currently not supported.$minifyscript"); $sb->add_bool_option("autocache_min_css", "
Minimize CSS files: "); - $sb->add_bool_option("autocache_min_js", "
Minimize JS files: "); + $sb->add_bool_option("autocache_min_js", "
Minimize JS files: "); + $sb->add_label("
Minifying currently not supported.$minifyscript"); $event->panel->add_block($sb); }