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

Last change on this file since 516 was 516, checked in by sven, 5 years ago

Bug #51 gefixt (http://labs.technikum29.de/ticket/51).
Jetzt sollten neue Pagestyles gleich beim Erstellen erkannt werden.

  • Property svn:keywords set to Id
File size: 8.4 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        static function create_from_type($type, $baseconf=null) {
51                global $lib, $webroot, $host;
52                $conf = $host->get_ressources($type, $webroot, isset($baseconf['debug']) && $baseconf['debug']);
53                if($conf === null) return null;
54       
55                return new $conf['class']($conf);               
56        }
57       
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       
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         **/
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       
90        /**
91         * Print out debug messages, only if debug switch is given.
92         **/
93        protected function print_debug($string) {
94                if($this->conf['debug'])
95                        echo $string;
96        }
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         **/
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        }
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         **/
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        }
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         **/
145        function print_header($title=null) {
146                if(!$title) $title = __CLASS__;
147                ?>
148/*!
149 * t29v6 <?=$title; ?> - http://technikum29.de/
150 * $Id: ressourceloader.php 516 2014-02-19 11:39:35Z sven $
151 *
152 * Copyright 2012, Sven Koeppel <sven@te...29.de>
153 * Licensed under any of Apache, MIT, GPL, LGPL
154 *
155 * Packed: <?php echo implode(' ', $this->conf['filenames']); ?> 
156 * Arguments: ?debug=true - skip cache and just cat everything
157 *            ?purge_cache=true - force rebuild of compressed cache file
158 * Gen Date: <?php echo date('r'), PHP_EOL;
159                if($title == __CLASS__) print " **/\n";
160        }
161       
162        /**
163         * The main run() function will print out the header and concatenate all
164         * modules contents. Expects OutputBuffering running!
165         **/
166        function run() {
167                $this->print_header();
168                $this->conf['header'] = ob_get_contents(); // for prepending it to minified code
169
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
177
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         **/
184        function compression_filter($output) {
185                return $output;
186        }
187} // class t29RessourceLoader
188
189
190class 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") {
195                        // append system messages to the special msg.js file
196                        // to inject PHP code to JS userspace.
197                        $this->print_debug("\n/*** Auto appended ***/\n");
198                        require "$lib/messages.php";
199                        echo "t29.msg.data=";
200                        echo t29Messages::create_json('/^js-/');
201                        echo ";\n";
202                }
203        }
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&amp;v=2&amp;sensor=false&amp;key=ABQIAAAAraTKZ5cINardZ8ITNVssKhRcOoEBtCgYLJRQznXYEV8m1M3fRRRT9wMSvFwhyo62fD3KyiwQxe5ruw';
210                                break;
211                }
212                return $urls;
213        }
214
215        function print_header($title=null) {
216                parent::print_header('JavaScript Code');
217                echo " * Depends heavily on jQuery\n **/\n";
218        }
219       
220        function compression_filter($code) {
221                global $lib;
222                // reduces code size about 1/2 - before: 23kB, after: 12kB
223                require "$lib/JavaScriptMinifier.php";
224                $minified = JavaScriptMinifier::minify($code);
225                return $this->conf['header'] . $minified;
226        }
227} // class t29JavaScriptRessourceLoader
228
229class t29StyleSheetRessourceLoader extends t29RessourceLoader {
230        function print_header($title=null) {
231                parent::print_header('StyleSheet');
232                echo " **/\n";
233        }
234
235        function compression_filter($code) {
236                global $lib, $host;
237                if($host->has_web_prefix)
238                        // rewrite CSS image includes
239                        $code = preg_replace('#(url\(["\']?)/#i', '\\1'.$host->web_prefix.'/', $code);
240               
241               
242                require "$lib/CSSMin.php";
243                # compression: 40kb to 16kb
244                $minified = CSSMin::minify($code);
245                return $this->conf['header'] . $minified;
246               
247        }
248} // 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