source: t29-www/lib/ressourceloader.php @ 357

Last change on this file since 357 was 357, checked in by sven, 6 years ago

t29Host-Webroot-System entwickelt.

Damit können Installationen der technikum29-Website ab nun auch in Unterverzeichnissen
(bislang allerdings nur unterhalb des DocumentRoots) installiert werden, was einem
größere Flexibilität beim lokalen Aufsetzen der Seite liefert

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