[260] | 1 | <?php |
---|
[269] | 2 | /** |
---|
[270] | 3 | * t29RessourceLoader classes. |
---|
[269] | 4 | * |
---|
[271] | 5 | * The t29 ressource loading system features full caching, directory file input, |
---|
| 6 | * OOP style file type specific functions, pre/post per file injection hooks |
---|
| 7 | * (AOP style) and post output content filtering where compression tools for |
---|
| 8 | * JavaScript and CSS are used. |
---|
[269] | 9 | * |
---|
[271] | 10 | * The architecture and compression technique is highly inspired by the |
---|
| 11 | * RessourceLoader framework of MediaWiki 1.20. |
---|
| 12 | * |
---|
| 13 | * These classes make usage of class inheritance, heavy PHP output buffering, the |
---|
| 14 | * t29v6 caching subsystem and the general t29v6 variable convencience. |
---|
| 15 | * |
---|
| 16 | * This file defines classes t29{,JavaScript,StyleSheet}RessourceLoader. |
---|
| 17 | * Libs JavaScriptMinifier.php and CSSMin.php are included on per-method |
---|
| 18 | * level for minification. |
---|
| 19 | * |
---|
| 20 | * 2012 Sven Koeppel |
---|
| 21 | * |
---|
[269] | 22 | **/ |
---|
[273] | 23 | |
---|
| 24 | /* |
---|
| 25 | // test it: |
---|
| 26 | $lib = dirname(__FILE__); |
---|
| 27 | $webroot = realpath("$lib/../"); |
---|
| 28 | $js = t29RessourceLoader::create_from_type('css'); |
---|
| 29 | $js->run(); |
---|
| 30 | */ |
---|
[260] | 31 | |
---|
[269] | 32 | class t29RessourceLoader { |
---|
[271] | 33 | /** |
---|
[273] | 34 | * expects: type, cache_file, module_dir, glob_pattern, content_types, class, modules, debug |
---|
[271] | 35 | **/ |
---|
[269] | 36 | public $conf; |
---|
| 37 | |
---|
[273] | 38 | const default_include_url = '/lib/loader.php'; // rel to webroot |
---|
| 39 | |
---|
[271] | 40 | /** |
---|
| 41 | * Construct with configuration array. See loader.php for contents of |
---|
| 42 | * that array. See above for minimum elements which must be present. |
---|
[273] | 43 | * @param $conf Configuration array |
---|
[271] | 44 | **/ |
---|
[269] | 45 | function __construct($conf) { |
---|
| 46 | $this->conf = $conf; |
---|
| 47 | $this->conf['filenames'] = array_map('basename', $this->conf['modules']); // filenames like foo.js |
---|
| 48 | } |
---|
| 49 | |
---|
[273] | 50 | private static $conf_for_type; |
---|
| 51 | static function create_from_type($type, $baseconf=null) { |
---|
| 52 | global $lib, $webroot; |
---|
| 53 | if(!self::$conf_for_type) { |
---|
| 54 | define('T29_GRAB_LOADER_DEFS', true); |
---|
| 55 | include "$lib/loader.php"; |
---|
| 56 | self::$conf_for_type = $conf_for_type; |
---|
| 57 | } |
---|
| 58 | |
---|
| 59 | $conf = call_user_func(self::$conf_for_type, $type, isset($baseconf['debug']) && $baseconf['debug']); |
---|
| 60 | if($conf === null) return null; |
---|
| 61 | |
---|
| 62 | return new $conf['class']($conf); |
---|
| 63 | } |
---|
| 64 | |
---|
| 65 | function get_urls($debug=null) { |
---|
| 66 | global $webroot; |
---|
| 67 | if(($debug !== null && $debug) || !$this->conf['debug']) { |
---|
| 68 | return array(self::default_include_url . '?type=' . $this->conf['type']); |
---|
| 69 | } else { |
---|
| 70 | $module_dir_rel2webroot = str_replace($webroot, '', $this->conf['module_dir']); |
---|
| 71 | return array_map(function($i)use($module_dir_rel2webroot){ return $module_dir_rel2webroot.$i; }, $this->conf['filenames']); |
---|
| 72 | } |
---|
| 73 | } |
---|
| 74 | |
---|
[271] | 75 | /** |
---|
| 76 | * Print out debug messages, only if debug switch is given. |
---|
| 77 | **/ |
---|
| 78 | protected function print_debug($string) { |
---|
[269] | 79 | if($this->conf['debug']) |
---|
| 80 | echo $string; |
---|
| 81 | } |
---|
[271] | 82 | |
---|
| 83 | /** |
---|
| 84 | * Module hooking: By overwriting this method and looking at $mod_filename, |
---|
| 85 | * you can inject any output before that given file. |
---|
| 86 | * |
---|
| 87 | * Example: |
---|
| 88 | * class YourRessourceLoader extends t29RessourceLoader {[ |
---|
| 89 | * function print_before_file($file, $i) { |
---|
| 90 | * parent::print_before_file($file, $i); |
---|
| 91 | * print "Make a boo boo loading the ${i}. file named ${file}!"; |
---|
| 92 | * } |
---|
| 93 | * } |
---|
| 94 | * This will prepend that string before the output of the file. |
---|
| 95 | * |
---|
| 96 | * Always call the parent function when overwriting so that output is printed, |
---|
| 97 | * too! (See example) |
---|
| 98 | * |
---|
| 99 | * @param $mod_filename Filename of module, like "foo.js". |
---|
| 100 | * @param $dir_index Iteration index while traversing the directory (see run()). Not so important. |
---|
| 101 | * @returns String that |
---|
| 102 | **/ |
---|
[269] | 103 | function print_before_file($mod_filename, $dir_index) { |
---|
| 104 | $this->print_debug("\n\n/*** t29v6-RessourceLoader[$dir_index]: Start of $mod_filename ***/\n\n"); |
---|
| 105 | } |
---|
[271] | 106 | |
---|
| 107 | /** |
---|
| 108 | * Same as print_before_file but will append your content to the file. |
---|
| 109 | * Obey calling parent::print_after_file at first so that corrections in |
---|
| 110 | * the super class can be done! |
---|
| 111 | * |
---|
| 112 | * The implementation in t29RessourceLoader prints some newlines to make sure |
---|
| 113 | * JavaScript oneliner comments at the end of a file won't comment out another |
---|
| 114 | * file's first line. |
---|
| 115 | * |
---|
| 116 | **/ |
---|
[269] | 117 | function print_after_file($mod_filename, $dir_index) { |
---|
| 118 | echo "\n\n"; // JS: for being sure no former "//" comment in last line wipes out code |
---|
| 119 | $this->print_debug("\n\n/*** t29v6-RessourceLoader[$dir_index]: End of $mod_filename ***/\n\n"); |
---|
| 120 | } |
---|
[271] | 121 | |
---|
| 122 | /** |
---|
| 123 | * A generic print_header function which will be called at first. Give out some |
---|
| 124 | * stuff you want to prepend to your overall output. This method provides you a |
---|
| 125 | * generic JS/CSS compilant message where you can give your own $title string |
---|
| 126 | * or use no title (it will use your class name instead). If called with $title != null, |
---|
| 127 | * the C++ style multi line comment won't be closed so you can append your own |
---|
| 128 | * stuff. |
---|
| 129 | **/ |
---|
[269] | 130 | function print_header($title=null) { |
---|
| 131 | if(!$title) $title = __CLASS__; |
---|
| 132 | ?> |
---|
[260] | 133 | /*! |
---|
[269] | 134 | * t29v6 <?=$title; ?> - http://technikum29.de/ |
---|
[260] | 135 | * $Id: ressourceloader.php 285 2012-08-15 13:24:13Z heribert $ |
---|
| 136 | * |
---|
| 137 | * Copyright 2012, Sven Koeppel <sven@te...29.de> |
---|
| 138 | * Licensed under any of Apache, MIT, GPL, LGPL |
---|
| 139 | * |
---|
[269] | 140 | * Packed: <?php echo implode(' ', $this->conf['filenames']); ?> |
---|
[260] | 141 | * Arguments: ?debug=true - skip cache and just cat everything |
---|
| 142 | * ?purge_cache=true - force rebuild of compressed cache file |
---|
[269] | 143 | * Gen Date: <?php echo date('r'), PHP_EOL; |
---|
| 144 | if($title == __CLASS__) print " **/\n"; |
---|
| 145 | } |
---|
| 146 | |
---|
[271] | 147 | /** |
---|
| 148 | * The main run() function will print out the header and concatenate all |
---|
| 149 | * modules contents. Expects OutputBuffering running! |
---|
| 150 | **/ |
---|
[269] | 151 | function run() { |
---|
| 152 | $this->print_header(); |
---|
| 153 | $this->conf['header'] = ob_get_contents(); // for prepending it to minified code |
---|
[260] | 154 | |
---|
[269] | 155 | foreach($this->conf['modules'] as $i => $mod) { |
---|
| 156 | $modfile = $this->conf['filenames'][$i]; |
---|
| 157 | $this->print_before_file($modfile, $i); |
---|
| 158 | readfile($mod); |
---|
| 159 | $this->print_after_file($modfile, $i); |
---|
| 160 | } |
---|
| 161 | } // run |
---|
[264] | 162 | |
---|
[271] | 163 | /** |
---|
| 164 | * Overwrite compression_filter for filtering the whole output made by this |
---|
| 165 | * class. It is used as a shutdown filter in t29Cache, see usage in loader.php. |
---|
| 166 | * @param $output The output string fetched by OutputBuffering |
---|
| 167 | * @returns The filtered String. The default implementation just returns $output. |
---|
| 168 | **/ |
---|
[269] | 169 | function compression_filter($output) { |
---|
| 170 | return $output; |
---|
| 171 | } |
---|
| 172 | } // class t29RessourceLoader |
---|
| 173 | |
---|
[271] | 174 | |
---|
[269] | 175 | class t29JavaScriptRessourceLoader extends t29RessourceLoader { |
---|
| 176 | function print_after_file($mod_filename, $dir_index) { |
---|
| 177 | global $lib; |
---|
| 178 | parent::print_after_file($mod_filename, $dir_index); |
---|
| 179 | if($mod_filename == "msg.js") { |
---|
[271] | 180 | // append system messages to the special msg.js file |
---|
| 181 | // to inject PHP code to JS userspace. |
---|
[269] | 182 | $this->print_debug("\n/*** Auto appended ***/\n"); |
---|
| 183 | require "$lib/messages.php"; |
---|
| 184 | echo "t29.msg.data="; |
---|
[278] | 185 | echo t29Messages::create_json('/^js-/'); |
---|
[269] | 186 | echo ";\n"; |
---|
| 187 | } |
---|
| 188 | } |
---|
| 189 | |
---|
[285] | 190 | function print_header($title=null) { |
---|
[269] | 191 | parent::print_header('JavaScript Code'); |
---|
| 192 | echo " * Depends heavily on jQuery\n **/\n"; |
---|
| 193 | } |
---|
[260] | 194 | |
---|
[269] | 195 | function compression_filter($code) { |
---|
| 196 | global $lib; |
---|
| 197 | // reduces code size about 1/2 - before: 23kB, after: 12kB |
---|
| 198 | require "$lib/JavaScriptMinifier.php"; |
---|
| 199 | $minified = JavaScriptMinifier::minify($code); |
---|
| 200 | return $this->conf['header'] . $minified; |
---|
[260] | 201 | } |
---|
[269] | 202 | } // class t29JavaScriptRessourceLoader |
---|
[260] | 203 | |
---|
[269] | 204 | class t29StyleSheetRessourceLoader extends t29RessourceLoader { |
---|
[285] | 205 | function print_header($title=null) { |
---|
[271] | 206 | parent::print_header('StyleSheet'); |
---|
[269] | 207 | echo " **/\n"; |
---|
| 208 | } |
---|
[260] | 209 | |
---|
[269] | 210 | function compression_filter($code) { |
---|
| 211 | global $lib; |
---|
| 212 | require "$lib/CSSMin.php"; |
---|
[270] | 213 | # compression: 40kb to 16kb |
---|
[269] | 214 | $minified = CSSMin::minify($code); |
---|
| 215 | return $this->conf['header'] . $minified; |
---|
| 216 | |
---|
| 217 | } |
---|
| 218 | } // t29StyleSheetRessourceLoader |
---|