xref: /dokuwiki/lib/exe/css.php (revision 78a6aeb15ad85c8be4a7e39307b7d9aa0512742c)
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