|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00003 // This file is part of Moodle - http://moodle.org/ 00004 // 00005 // Moodle is free software: you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation, either version 3 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // Moodle is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00017 00027 // disable moodle specific debug messages and any errors in output, 00028 // comment out when debugging or better look into error log! 00029 define('NO_DEBUG_DISPLAY', true); 00030 00031 // we need just the values from config.php and minlib.php 00032 define('ABORT_AFTER_CONFIG', true); 00033 require('../config.php'); // this stops immediately at the beginning of lib/setup.php 00034 00035 $themename = min_optional_param('theme', 'standard', 'SAFEDIR'); 00036 $type = min_optional_param('type', 'all', 'SAFEDIR'); 00037 $rev = min_optional_param('rev', 0, 'INT'); 00038 00039 if (!in_array($type, array('all', 'ie', 'editor', 'plugins', 'parents', 'theme'))) { 00040 header('HTTP/1.0 404 not found'); 00041 die('Theme was not found, sorry.'); 00042 } 00043 00044 if (file_exists("$CFG->dirroot/theme/$themename/config.php")) { 00045 // exists 00046 } else if (!empty($CFG->themedir) and file_exists("$CFG->themedir/$themename/config.php")) { 00047 // exists 00048 } else { 00049 header('HTTP/1.0 404 not found'); 00050 die('Theme was not found, sorry.'); 00051 } 00052 00053 if ($type === 'ie') { 00054 send_ie_css($themename, $rev); 00055 } 00056 00057 $candidatesheet = "$CFG->cachedir/theme/$themename/css/$type.css"; 00058 00059 if (file_exists($candidatesheet)) { 00060 if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) || !empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { 00061 // we do not actually need to verify the etag value because our files 00062 // never change in cache because we increment the rev parameter 00063 $lifetime = 60*60*24*30; // 30 days 00064 header('HTTP/1.1 304 Not Modified'); 00065 header('Expires: '. gmdate('D, d M Y H:i:s', time() + $lifetime) .' GMT'); 00066 header('Cache-Control: max-age='.$lifetime); 00067 header('Content-Type: text/css; charset=utf-8'); 00068 die; 00069 } 00070 send_cached_css($candidatesheet, $rev); 00071 } 00072 00073 //================================================================================= 00074 // ok, now we need to start normal moodle script, we need to load all libs and $DB 00075 define('ABORT_AFTER_CONFIG_CANCEL', true); 00076 00077 define('NO_MOODLE_COOKIES', true); // Session not used here 00078 define('NO_UPGRADE_CHECK', true); // Ignore upgrade check 00079 00080 require("$CFG->dirroot/lib/setup.php"); 00081 // setup include path 00082 set_include_path($CFG->libdir . '/minify/lib' . PATH_SEPARATOR . get_include_path()); 00083 require_once('Minify.php'); 00084 00085 $theme = theme_config::load($themename); 00086 00087 if ($type === 'editor') { 00088 $files = $theme->editor_css_files(); 00089 store_css($theme, $candidatesheet, $files); 00090 } else { 00091 $css = $theme->css_files(); 00092 $allfiles = array(); 00093 foreach ($css as $key=>$value) { 00094 $cssfiles = array(); 00095 foreach($value as $val) { 00096 if (is_array($val)) { 00097 foreach ($val as $k=>$v) { 00098 $cssfiles[] = $v; 00099 } 00100 } else { 00101 $cssfiles[] = $val; 00102 } 00103 } 00104 $cssfile = "$CFG->cachedir/theme/$themename/css/$key.css"; 00105 store_css($theme, $cssfile, $cssfiles); 00106 $allfiles = array_merge($allfiles, $cssfiles); 00107 } 00108 $cssfile = "$CFG->cachedir/theme/$themename/css/all.css"; 00109 store_css($theme, $cssfile, $allfiles); 00110 } 00111 send_cached_css($candidatesheet, $rev); 00112 00113 //================================================================================= 00114 //=== utility functions == 00115 // we are not using filelib because we need to fine tune all header 00116 // parameters to get the best performance. 00117 00118 function store_css(theme_config $theme, $csspath, $cssfiles) { 00119 $css = $theme->post_process(minify($cssfiles)); 00120 // note: cache reset might have purged our cache dir structure, 00121 // make sure we do not use stale file stat cache in the next check_dir_exists() 00122 clearstatcache(); 00123 check_dir_exists(dirname($csspath)); 00124 $fp = fopen($csspath, 'w'); 00125 fwrite($fp, $css); 00126 fclose($fp); 00127 } 00128 00129 function send_ie_css($themename, $rev) { 00130 $lifetime = 60*60*24*30; // 30 days 00131 00132 $css = <<<EOF 00134 @import url(styles.php?theme=$themename&rev=$rev&type=plugins); 00135 @import url(styles.php?theme=$themename&rev=$rev&type=parents); 00136 @import url(styles.php?theme=$themename&rev=$rev&type=theme); 00137 00138 EOF; 00139 00140 header('Etag: '.md5($rev)); 00141 header('Content-Disposition: inline; filename="styles.php"'); 00142 header('Last-Modified: '. gmdate('D, d M Y H:i:s', time()) .' GMT'); 00143 header('Expires: '. gmdate('D, d M Y H:i:s', time() + $lifetime) .' GMT'); 00144 header('Pragma: '); 00145 header('Cache-Control: max-age='.$lifetime); 00146 header('Accept-Ranges: none'); 00147 header('Content-Type: text/css; charset=utf-8'); 00148 header('Content-Length: '.strlen($css)); 00149 00150 echo $css; 00151 die; 00152 } 00153 00154 function send_cached_css($csspath, $rev) { 00155 $lifetime = 60*60*24*30; // 30 days 00156 00157 header('Content-Disposition: inline; filename="styles.php"'); 00158 header('Last-Modified: '. gmdate('D, d M Y H:i:s', filemtime($csspath)) .' GMT'); 00159 header('Expires: '. gmdate('D, d M Y H:i:s', time() + $lifetime) .' GMT'); 00160 header('Pragma: '); 00161 header('Cache-Control: max-age='.$lifetime); 00162 header('Accept-Ranges: none'); 00163 header('Content-Type: text/css; charset=utf-8'); 00164 if (!min_enable_zlib_compression()) { 00165 header('Content-Length: '.filesize($csspath)); 00166 } 00167 00168 readfile($csspath); 00169 die; 00170 } 00171 00172 function minify($files) { 00173 if (0 === stripos(PHP_OS, 'win')) { 00174 Minify::setDocRoot(); // IIS may need help 00175 } 00176 // disable all caching, we do it in moodle 00177 Minify::setCache(null, false); 00178 00179 $options = array( 00180 'bubbleCssImports' => false, 00181 // Don't gzip content we just want text for storage 00182 'encodeOutput' => false, 00183 // Maximum age to cache, not used but required 00184 'maxAge' => (60*60*24*20), 00185 // The files to minify 00186 'files' => $files, 00187 // Turn orr URI rewriting 00188 'rewriteCssUris' => false, 00189 // This returns the CSS rather than echoing it for display 00190 'quiet' => true 00191 ); 00192 $result = Minify::serve('Files', $options); 00193 return $result['content']; 00194 }