1*78a6aeb1SAndreas Gohr<?php 2*78a6aeb1SAndreas Gohr/** 3*78a6aeb1SAndreas Gohr * DokuWiki StyleSheet creator 4*78a6aeb1SAndreas Gohr * 5*78a6aeb1SAndreas Gohr * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6*78a6aeb1SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 7*78a6aeb1SAndreas Gohr */ 8*78a6aeb1SAndreas Gohr 9*78a6aeb1SAndreas Gohrif(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); 10*78a6aeb1SAndreas Gohrdefine('NOSESSION',true); // we do not use a session or authentication here (better caching) 11*78a6aeb1SAndreas Gohrrequire_once(DOKU_INC.'inc/init.php'); 12*78a6aeb1SAndreas Gohrrequire_once(DOKU_INC.'inc/pageutils.php'); 13*78a6aeb1SAndreas Gohrrequire_once(DOKU_INC.'inc/io.php'); 14*78a6aeb1SAndreas Gohr 15*78a6aeb1SAndreas Gohr// Main (don't run when UNIT test) 16*78a6aeb1SAndreas Gohrif(!defined('SIMPLE_TEST')){ 17*78a6aeb1SAndreas Gohr header('Content-Type: text/css; charset=utf-8'); 18*78a6aeb1SAndreas Gohr css_out(); 19*78a6aeb1SAndreas Gohr} 20*78a6aeb1SAndreas Gohr 21*78a6aeb1SAndreas Gohr 22*78a6aeb1SAndreas Gohr// ---------------------- functions ------------------------------ 23*78a6aeb1SAndreas Gohr 24*78a6aeb1SAndreas Gohr/** 25*78a6aeb1SAndreas Gohr * Output all needed Styles 26*78a6aeb1SAndreas Gohr * 27*78a6aeb1SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 28*78a6aeb1SAndreas Gohr */ 29*78a6aeb1SAndreas Gohrfunction css_out(){ 30*78a6aeb1SAndreas Gohr global $conf; 31*78a6aeb1SAndreas Gohr global $lang; 32*78a6aeb1SAndreas Gohr $print = (bool) $_REQUEST['print']; //print mode? 33*78a6aeb1SAndreas Gohr 34*78a6aeb1SAndreas Gohr // The generated script depends on some dynamic options 35*78a6aeb1SAndreas Gohr $cache = getCacheName('styles'.$print,'.css'); 36*78a6aeb1SAndreas Gohr 37*78a6aeb1SAndreas Gohr // Array of needed files and their web locations, the latter ones 38*78a6aeb1SAndreas Gohr // are needed to fix relative paths in the stylesheets 39*78a6aeb1SAndreas Gohr $files = array(); 40*78a6aeb1SAndreas Gohr if($print){ 41*78a6aeb1SAndreas Gohr $files[DOKU_TPLINC.'print.css'] = DOKU_TPL; 42*78a6aeb1SAndreas Gohr // load plugin styles 43*78a6aeb1SAndreas Gohr $files = array_merge($files, css_pluginstyles('print')); 44*78a6aeb1SAndreas Gohr $files[DOKU_CONF.'userprint.css'] = ''; 45*78a6aeb1SAndreas Gohr }else{ 46*78a6aeb1SAndreas Gohr $files[DOKU_INC.'lib/styles/style.css'] = DOKU_BASE.'lib/styles/'; 47*78a6aeb1SAndreas Gohr //fixme spellchecker style 48*78a6aeb1SAndreas Gohr $files[DOKU_TPLINC.'layout.css'] = DOKU_TPL; 49*78a6aeb1SAndreas Gohr $files[DOKU_TPLINC.'design.css'] = DOKU_TPL; 50*78a6aeb1SAndreas Gohr if($lang['direction'] == 'rtl'){ 51*78a6aeb1SAndreas Gohr $files[DOKU_TPLINC.'rtl.css'] = DOKU_TPL; 52*78a6aeb1SAndreas Gohr } 53*78a6aeb1SAndreas Gohr // load plugin styles 54*78a6aeb1SAndreas Gohr $files = array_merge($files, css_pluginstyles('screen')); 55*78a6aeb1SAndreas Gohr $files[DOKU_CONF.'userstyle.css'] = ''; 56*78a6aeb1SAndreas Gohr } 57*78a6aeb1SAndreas Gohr 58*78a6aeb1SAndreas Gohr // check cache age 59*78a6aeb1SAndreas Gohr if(css_cacheok($cache,array_keys($files))){ 60*78a6aeb1SAndreas Gohr readfile($cache); 61*78a6aeb1SAndreas Gohr return; 62*78a6aeb1SAndreas Gohr } 63*78a6aeb1SAndreas Gohr 64*78a6aeb1SAndreas Gohr // start output buffering and build the stylesheet 65*78a6aeb1SAndreas Gohr ob_start(); 66*78a6aeb1SAndreas Gohr 67*78a6aeb1SAndreas Gohr // load files 68*78a6aeb1SAndreas Gohr foreach($files as $file => $location){ 69*78a6aeb1SAndreas Gohr print css_loadfile($file, $location); 70*78a6aeb1SAndreas Gohr } 71*78a6aeb1SAndreas Gohr 72*78a6aeb1SAndreas Gohr // end output buffering and get contents 73*78a6aeb1SAndreas Gohr $css = ob_get_contents(); 74*78a6aeb1SAndreas Gohr ob_end_clean(); 75*78a6aeb1SAndreas Gohr 76*78a6aeb1SAndreas Gohr // compress whitespace and comments 77*78a6aeb1SAndreas Gohr if($conf['compress']){ 78*78a6aeb1SAndreas Gohr $css = css_compress($css); 79*78a6aeb1SAndreas Gohr } 80*78a6aeb1SAndreas Gohr 81*78a6aeb1SAndreas Gohr // save cache file 82*78a6aeb1SAndreas Gohr io_saveFile($cache,$css); 83*78a6aeb1SAndreas Gohr 84*78a6aeb1SAndreas Gohr // finally send output 85*78a6aeb1SAndreas Gohr print $css; 86*78a6aeb1SAndreas Gohr} 87*78a6aeb1SAndreas Gohr 88*78a6aeb1SAndreas Gohr/** 89*78a6aeb1SAndreas Gohr * Checks if a CSS Cache file still is valid 90*78a6aeb1SAndreas Gohr * 91*78a6aeb1SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 92*78a6aeb1SAndreas Gohr */ 93*78a6aeb1SAndreas Gohrfunction css_cacheok($cache,$files){ 94*78a6aeb1SAndreas Gohr $ctime = @filemtime($cache); 95*78a6aeb1SAndreas Gohr if(!$ctime) return false; //There is no cache 96*78a6aeb1SAndreas Gohr 97*78a6aeb1SAndreas Gohr // some additional files to check 98*78a6aeb1SAndreas Gohr $files[] = DOKU_CONF.'dokuwiki.conf'; 99*78a6aeb1SAndreas Gohr $files[] = DOKU_CONF.'local.conf'; 100*78a6aeb1SAndreas Gohr $files[] = __FILE__; 101*78a6aeb1SAndreas Gohr 102*78a6aeb1SAndreas Gohr // now walk the files 103*78a6aeb1SAndreas Gohr foreach($files as $file){ 104*78a6aeb1SAndreas Gohr if(@filemtime($file) > $ctime){ 105*78a6aeb1SAndreas Gohr return false; 106*78a6aeb1SAndreas Gohr } 107*78a6aeb1SAndreas Gohr } 108*78a6aeb1SAndreas Gohr return true; 109*78a6aeb1SAndreas Gohr} 110*78a6aeb1SAndreas Gohr 111*78a6aeb1SAndreas Gohr/** 112*78a6aeb1SAndreas Gohr * Loads a given file and fixes relative URLs with the 113*78a6aeb1SAndreas Gohr * given location prefix 114*78a6aeb1SAndreas Gohr */ 115*78a6aeb1SAndreas Gohrfunction css_loadfile($file,$location=''){ 116*78a6aeb1SAndreas Gohr if(!@file_exists($file)) return ''; 117*78a6aeb1SAndreas Gohr $css = io_readFile($file); 118*78a6aeb1SAndreas Gohr if(!$location) return $css; 119*78a6aeb1SAndreas Gohr 120*78a6aeb1SAndreas Gohr $css = preg_replace('!(url\( *)([^/])!','\\1'.$location.'\\2',$css); 121*78a6aeb1SAndreas Gohr return $css; 122*78a6aeb1SAndreas Gohr} 123*78a6aeb1SAndreas Gohr 124*78a6aeb1SAndreas Gohr/** 125*78a6aeb1SAndreas Gohr * Returns a list of possible Plugin Styles (no existance check here) 126*78a6aeb1SAndreas Gohr * 127*78a6aeb1SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 128*78a6aeb1SAndreas Gohr */ 129*78a6aeb1SAndreas Gohrfunction css_pluginstyles($mode='screen'){ 130*78a6aeb1SAndreas Gohr $list = array(); 131*78a6aeb1SAndreas Gohr $plugins = plugin_list(); 132*78a6aeb1SAndreas Gohr foreach ($plugins as $p){ 133*78a6aeb1SAndreas Gohr if($mode == 'print'){ 134*78a6aeb1SAndreas Gohr $list[DOKU_PLUGIN."$p/print.css"] = DOKU_BASE."lib/plugins/$p/"; 135*78a6aeb1SAndreas Gohr }else{ 136*78a6aeb1SAndreas Gohr $list[DOKU_PLUGIN."$p/style.css"] = DOKU_BASE."lib/plugins/$p/"; 137*78a6aeb1SAndreas Gohr $list[DOKU_PLUGIN."$p/screen.css"] = DOKU_BASE."lib/plugins/$p/"; 138*78a6aeb1SAndreas Gohr } 139*78a6aeb1SAndreas Gohr } 140*78a6aeb1SAndreas Gohr return $list; 141*78a6aeb1SAndreas Gohr} 142*78a6aeb1SAndreas Gohr 143*78a6aeb1SAndreas Gohr/** 144*78a6aeb1SAndreas Gohr * Very simple CSS optimizer 145*78a6aeb1SAndreas Gohr * 146*78a6aeb1SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 147*78a6aeb1SAndreas Gohr */ 148*78a6aeb1SAndreas Gohrfunction css_compress($css){ 149*78a6aeb1SAndreas Gohr // strip whitespaces 150*78a6aeb1SAndreas Gohr $css = preg_replace('![\r\n\t ]+!',' ',$css); 151*78a6aeb1SAndreas Gohr $css = preg_replace('/ ?([:;,{}]) ?/','\\1',$css); 152*78a6aeb1SAndreas Gohr 153*78a6aeb1SAndreas Gohr // strip comments (ungreedy) 154*78a6aeb1SAndreas Gohr // We keep very small comments to maintain typical browser hacks 155*78a6aeb1SAndreas Gohr $css = preg_replace('!(/\*)(.{4,})(\*/)!U','',$css); 156*78a6aeb1SAndreas Gohr 157*78a6aeb1SAndreas Gohr // shorten colors 158*78a6aeb1SAndreas Gohr $css = preg_replace("/#([0-9a-fA-F]{1})\\1([0-9a-fA-F]{1})\\2([0-9a-fA-F]{1})\\3/", "#\\1\\2\\3",$css); 159*78a6aeb1SAndreas Gohr 160*78a6aeb1SAndreas Gohr return $css; 161*78a6aeb1SAndreas Gohr} 162*78a6aeb1SAndreas Gohr 163*78a6aeb1SAndreas Gohr 164*78a6aeb1SAndreas Gohr//Setup VIM: ex: et ts=4 enc=utf-8 : 165*78a6aeb1SAndreas Gohr?> 166