[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 | /** |
---|
[357] | 34 | * expects: type, cache_file, module_dir, page_dir, glob_pattern, content_types, class, modules, debug, host |
---|
[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 | static function create_from_type($type, $baseconf=null) { |
---|
[516] | 51 | global $lib, $webroot, $host; |
---|
| 52 | $conf = $host->get_ressources($type, $webroot, isset($baseconf['debug']) && $baseconf['debug']); |
---|
[273] | 53 | if($conf === null) return null; |
---|
[516] | 54 | |
---|
| 55 | return new $conf['class']($conf); |
---|
[273] | 56 | } |
---|
| 57 | |
---|
[301] | 58 | function get_page_specific_urls($seiten_id) { |
---|
| 59 | global $webroot; |
---|
| 60 | $file = sprintf("%s/%s.%s", $this->conf['page_dir'], $seiten_id, $this->conf['type']); |
---|
| 61 | // TODO: This is hacky. Same in get_urls. |
---|
| 62 | $file_rel2webroot = str_replace($webroot, '', $file); |
---|
| 63 | return file_exists($file) ? array($file_rel2webroot) : array(); |
---|
| 64 | } |
---|
| 65 | |
---|
[357] | 66 | /** |
---|
| 67 | * Return a list of URLs appropriate for being included in a website. In general this |
---|
| 68 | * should be a list with one element, like array("/lib/loader.php?type=js"), which can |
---|
| 69 | * be directly expanded to a <script src="$1"></script> tag. Same applies for CSS. |
---|
| 70 | * In debug mode, the list will contain all base files. |
---|
| 71 | * |
---|
| 72 | * The URLs are relative to the t29 web document root, that is, no host specific web prefix |
---|
| 73 | * handling here. |
---|
| 74 | * |
---|
| 75 | * There is especially an issue with web prefixes and debug mode: Since clean untouched CSS/JS |
---|
| 76 | * files are passed there, there cannot be any rewriting in progress. |
---|
| 77 | * |
---|
| 78 | * @returns array |
---|
| 79 | **/ |
---|
[273] | 80 | function get_urls($debug=null) { |
---|
| 81 | global $webroot; |
---|
| 82 | if(($debug !== null && $debug) || !$this->conf['debug']) { |
---|
| 83 | return array(self::default_include_url . '?type=' . $this->conf['type']); |
---|
| 84 | } else { |
---|
| 85 | $module_dir_rel2webroot = str_replace($webroot, '', $this->conf['module_dir']); |
---|
| 86 | return array_map(function($i)use($module_dir_rel2webroot){ return $module_dir_rel2webroot.$i; }, $this->conf['filenames']); |
---|
| 87 | } |
---|
| 88 | } |
---|
| 89 | |
---|
[271] | 90 | /** |
---|
| 91 | * Print out debug messages, only if debug switch is given. |
---|
| 92 | **/ |
---|
| 93 | protected function print_debug($string) { |
---|
[269] | 94 | if($this->conf['debug']) |
---|
| 95 | echo $string; |
---|
| 96 | } |
---|
[271] | 97 | |
---|
| 98 | /** |
---|
| 99 | * Module hooking: By overwriting this method and looking at $mod_filename, |
---|
| 100 | * you can inject any output before that given file. |
---|
| 101 | * |
---|
| 102 | * Example: |
---|
| 103 | * class YourRessourceLoader extends t29RessourceLoader {[ |
---|
| 104 | * function print_before_file($file, $i) { |
---|
| 105 | * parent::print_before_file($file, $i); |
---|
| 106 | * print "Make a boo boo loading the ${i}. file named ${file}!"; |
---|
| 107 | * } |
---|
| 108 | * } |
---|
| 109 | * This will prepend that string before the output of the file. |
---|
| 110 | * |
---|
| 111 | * Always call the parent function when overwriting so that output is printed, |
---|
| 112 | * too! (See example) |
---|
| 113 | * |
---|
| 114 | * @param $mod_filename Filename of module, like "foo.js". |
---|
| 115 | * @param $dir_index Iteration index while traversing the directory (see run()). Not so important. |
---|
| 116 | * @returns String that |
---|
| 117 | **/ |
---|
[269] | 118 | function print_before_file($mod_filename, $dir_index) { |
---|
| 119 | $this->print_debug("\n\n/*** t29v6-RessourceLoader[$dir_index]: Start of $mod_filename ***/\n\n"); |
---|
| 120 | } |
---|
[271] | 121 | |
---|
| 122 | /** |
---|
| 123 | * Same as print_before_file but will append your content to the file. |
---|
| 124 | * Obey calling parent::print_after_file at first so that corrections in |
---|
| 125 | * the super class can be done! |
---|
| 126 | * |
---|
| 127 | * The implementation in t29RessourceLoader prints some newlines to make sure |
---|
| 128 | * JavaScript oneliner comments at the end of a file won't comment out another |
---|
| 129 | * file's first line. |
---|
| 130 | * |
---|
| 131 | **/ |
---|
[269] | 132 | function print_after_file($mod_filename, $dir_index) { |
---|
| 133 | echo "\n\n"; // JS: for being sure no former "//" comment in last line wipes out code |
---|
| 134 | $this->print_debug("\n\n/*** t29v6-RessourceLoader[$dir_index]: End of $mod_filename ***/\n\n"); |
---|
| 135 | } |
---|
[271] | 136 | |
---|
| 137 | /** |
---|
| 138 | * A generic print_header function which will be called at first. Give out some |
---|
| 139 | * stuff you want to prepend to your overall output. This method provides you a |
---|
| 140 | * generic JS/CSS compilant message where you can give your own $title string |
---|
| 141 | * or use no title (it will use your class name instead). If called with $title != null, |
---|
| 142 | * the C++ style multi line comment won't be closed so you can append your own |
---|
| 143 | * stuff. |
---|
| 144 | **/ |
---|
[269] | 145 | function print_header($title=null) { |
---|
| 146 | if(!$title) $title = __CLASS__; |
---|
| 147 | ?> |
---|
[260] | 148 | /*! |
---|
[269] | 149 | * t29v6 <?=$title; ?> - http://technikum29.de/ |
---|
[260] | 150 | * $Id: ressourceloader.php 1423 2018-01-07 00:31:58Z sven $ |
---|
| 151 | * |
---|
| 152 | * Copyright 2012, Sven Koeppel <sven@te...29.de> |
---|
| 153 | * Licensed under any of Apache, MIT, GPL, LGPL |
---|
| 154 | * |
---|
[269] | 155 | * Packed: <?php echo implode(' ', $this->conf['filenames']); ?> |
---|
[260] | 156 | * Arguments: ?debug=true - skip cache and just cat everything |
---|
| 157 | * ?purge_cache=true - force rebuild of compressed cache file |
---|
[269] | 158 | * Gen Date: <?php echo date('r'), PHP_EOL; |
---|
| 159 | if($title == __CLASS__) print " **/\n"; |
---|
| 160 | } |
---|
| 161 | |
---|
[271] | 162 | /** |
---|
| 163 | * The main run() function will print out the header and concatenate all |
---|
| 164 | * modules contents. Expects OutputBuffering running! |
---|
| 165 | **/ |
---|
[269] | 166 | function run() { |
---|
| 167 | $this->print_header(); |
---|
| 168 | $this->conf['header'] = ob_get_contents(); // for prepending it to minified code |
---|
[260] | 169 | |
---|
[269] | 170 | foreach($this->conf['modules'] as $i => $mod) { |
---|
| 171 | $modfile = $this->conf['filenames'][$i]; |
---|
| 172 | $this->print_before_file($modfile, $i); |
---|
| 173 | readfile($mod); |
---|
| 174 | $this->print_after_file($modfile, $i); |
---|
| 175 | } |
---|
| 176 | } // run |
---|
[264] | 177 | |
---|
[271] | 178 | /** |
---|
| 179 | * Overwrite compression_filter for filtering the whole output made by this |
---|
| 180 | * class. It is used as a shutdown filter in t29Cache, see usage in loader.php. |
---|
| 181 | * @param $output The output string fetched by OutputBuffering |
---|
| 182 | * @returns The filtered String. The default implementation just returns $output. |
---|
| 183 | **/ |
---|
[269] | 184 | function compression_filter($output) { |
---|
| 185 | return $output; |
---|
| 186 | } |
---|
| 187 | } // class t29RessourceLoader |
---|
| 188 | |
---|
[271] | 189 | |
---|
[269] | 190 | class t29JavaScriptRessourceLoader extends t29RessourceLoader { |
---|
| 191 | function print_after_file($mod_filename, $dir_index) { |
---|
| 192 | global $lib; |
---|
| 193 | parent::print_after_file($mod_filename, $dir_index); |
---|
| 194 | if($mod_filename == "msg.js") { |
---|
[271] | 195 | // append system messages to the special msg.js file |
---|
| 196 | // to inject PHP code to JS userspace. |
---|
[269] | 197 | $this->print_debug("\n/*** Auto appended ***/\n"); |
---|
| 198 | require "$lib/messages.php"; |
---|
| 199 | echo "t29.msg.data="; |
---|
[278] | 200 | echo t29Messages::create_json('/^js-/'); |
---|
[269] | 201 | echo ";\n"; |
---|
| 202 | } |
---|
| 203 | } |
---|
[301] | 204 | |
---|
| 205 | function get_page_specific_urls($seiten_id) { |
---|
| 206 | $urls = parent::get_page_specific_urls($seiten_id); |
---|
| 207 | switch($seiten_id) { |
---|
| 208 | case 'impressum': |
---|
| 209 | $urls[] = 'http://maps.google.com/maps?file=api&v=2&sensor=false&key=ABQIAAAAraTKZ5cINardZ8ITNVssKhRcOoEBtCgYLJRQznXYEV8m1M3fRRRT9wMSvFwhyo62fD3KyiwQxe5ruw'; |
---|
| 210 | break; |
---|
[1423] | 211 | case 'startseite': |
---|
| 212 | $urls[] = '/shared/js-v6/libs/flickity.pkgd.min.js'; // Caroussel-Slider |
---|
| 213 | break; |
---|
[301] | 214 | } |
---|
| 215 | return $urls; |
---|
| 216 | } |
---|
[269] | 217 | |
---|
[285] | 218 | function print_header($title=null) { |
---|
[269] | 219 | parent::print_header('JavaScript Code'); |
---|
| 220 | echo " * Depends heavily on jQuery\n **/\n"; |
---|
| 221 | } |
---|
[260] | 222 | |
---|
[269] | 223 | function compression_filter($code) { |
---|
| 224 | global $lib; |
---|
| 225 | // reduces code size about 1/2 - before: 23kB, after: 12kB |
---|
| 226 | require "$lib/JavaScriptMinifier.php"; |
---|
| 227 | $minified = JavaScriptMinifier::minify($code); |
---|
| 228 | return $this->conf['header'] . $minified; |
---|
[260] | 229 | } |
---|
[269] | 230 | } // class t29JavaScriptRessourceLoader |
---|
[260] | 231 | |
---|
[269] | 232 | class t29StyleSheetRessourceLoader extends t29RessourceLoader { |
---|
[285] | 233 | function print_header($title=null) { |
---|
[271] | 234 | parent::print_header('StyleSheet'); |
---|
[269] | 235 | echo " **/\n"; |
---|
| 236 | } |
---|
[260] | 237 | |
---|
[269] | 238 | function compression_filter($code) { |
---|
[516] | 239 | global $lib, $host; |
---|
[357] | 240 | if($host->has_web_prefix) |
---|
| 241 | // rewrite CSS image includes |
---|
| 242 | $code = preg_replace('#(url\(["\']?)/#i', '\\1'.$host->web_prefix.'/', $code); |
---|
| 243 | |
---|
| 244 | |
---|
[269] | 245 | require "$lib/CSSMin.php"; |
---|
[270] | 246 | # compression: 40kb to 16kb |
---|
[269] | 247 | $minified = CSSMin::minify($code); |
---|
| 248 | return $this->conf['header'] . $minified; |
---|
| 249 | |
---|
| 250 | } |
---|
[516] | 251 | } // t29StyleSheetRessourceLoader |
---|