source: t29-www/lib/host.php @ 650

Last change on this file since 650 was 650, checked in by heribert, 10 years ago

Windows-Verzeichnisrechnung korrigiert (Bug behoben)

File size: 13.6 KB
Line 
1<?php
2/**
3 * t29v6 new Hostinfo and Hosthook system.
4 *
5 * Local host.php files in the webroot can hook into t29* php
6 * and js classes without interfering the code. This can be usually
7 * be used for extra svn information.
8 * Hostinfos can also be appended in this file and therefore be
9 * managed centrally.
10 *
11 * webroot/host.php muss have a t29LocalHost extends t29Host class.
12 *
13 **/
14
15abstract class t29Host {
16        const webroot_host_file = '/host.php'; # relative to webroot
17        const webroot_local_host_classname = 't29LocalHost';
18        const env_hidesuffix_name = "T29URLHIDESUFFIX";
19
20        /// $hostname: An identifier like a FQDN. Is only used to identify the t29Host instance and not
21        ///            for constructing any URL.
22        /// This value must be overwritten in child classes!
23        public $hostname = "undefined";
24       
25        /// $document_root := realpath($_SERVER['DOCUMENT_ROOT']), performed by setup().
26        ///                   Can be used to identify the unix file path to the webserver docroot of the
27        ///                   webhost. Independent of the t29 system.
28        public $document_root;
29       
30        /// $webroot: The unix file path to the t29 web installation, actually the parent directory
31        ///           of the lib/ directory. Is widely used by many files and also computed by themselves.
32        public $webroot;
33        /// $lib  := realpath(__FILE__), just for convenience. $lib = "$webroot/lib" always holds.
34        public $lib;
35       
36        /// $web_prefix: The URL path to the webroot. Example:
37        ///              http://example.com/path/to/t29/de/page.php
38        ///                                ^^^^^^^^^^^^
39        ///                            This part is the web prefix, if /de/page.php is the script_filename.
40        /// This value is computed by setup().
41        public $web_prefix = "";
42       
43        /// $has_web_prefix := !empty($web_prefix). If this host is installed in root or not
44        public $has_web_prefix = false;
45       
46        /// $script_filename: The t29-internal identifying url path, like "/de/page.php" or "/en".
47        ///                   While $_SERVER['SCRIPT_FILENAME'] still contains the $web_prefix, this
48        ///                   string is sanitized.
49        /// This value is computed by setup().
50        public $script_filename;
51
52        /// $slash_filename: Cross-platform $script_filename, always starting with a "/".
53        public $slash_filename;
54
55        /// $ressources: CSS and JavaScript file paths ("Assets"), as used by the RessourceLoader,
56        ///              the loader.php and technikum29.php entry points and the Template.
57        private function ressources_array($webroot='') {
58                // this is implemented as method, because of
59                // 1. "$webbroot/..." like strings. This isn't a good idea anyway (e.g. in ressourceloader: $module_dir_rel2webroot
60                // 2. Closures: function($conf){...} doesn't work as class attribute.
61                // This is rather dirty, but anyway the supposed way to access these data is the public get_ressources().
62                $ressources = array(
63                        'cache_file' => array('compressed.js', 'style.css'),
64                        'module_dir' => array("$webroot/shared/js-v6/modules", "$webroot/shared/css-v6/modules"),
65                        'page_dir' => array("$webroot/shared/js-v6/pagescripts", "$webroot/shared/css-v6/pagestyles"),
66                        'glob_pattern' => array('*.js', '*.css'),
67                        'content_types' => array('application/javascript', 'text/css'),
68                        'class' => array('t29JavaScriptRessourceLoader', 't29StyleSheetRessourceLoader'),
69                        'modules' => function($conf){ return glob($conf['module_dir'] . '/' . $conf['glob_pattern']); },
70                );
71                return $ressources;
72        }
73
74        /// $ressources_types: The Ressources array above consists of numeric arrays. This array
75        ///                    maps those positions (numeric keys) to $conf array positions.
76        ///                    Use get_ressources() to resolve this mapping.
77        private $ressources_types = array('js', 'css');
78
79        public function get_ressources($type, $webroot, $debug_flag=false) {
80                $typepos = array_search($type, $this->ressources_types);
81                if($typepos === FALSE) return null;
82                $conf = array_map(function($val) use($typepos) 
83                        { return is_array($val) ? $val[$typepos] : $val; },
84                        $this->ressources_array($webroot));
85                $conf['type'] = $type;
86                // callback functions need the $conf we built.
87                $conf['modules'] = call_user_func($conf['modules'], $conf);
88                $conf['debug'] = $debug_flag; // skip cache and just concat everything
89                return $conf;
90        }
91
92        /**
93         * A special helper class, used by t29Template and technikum29.php entry point.
94         * The general (clean) way would be querying get_ressources().
95         * There is also t29RessourceLoader::get_page_specific_urls() which basically does
96         * the same, just using the global conf array.
97         **/ 
98        public function ressources_get_pagestyle($seiten_id) {
99                $ressources =  $this->ressources_array();
100                // We address the css property directly with the [1] index. Bad!
101                return $ressources['page_dir'][1] . '/' . $seiten_id . '.css';
102        }
103
104        /// Singleton fun for detect()
105        private static $instance;
106        private static function new_singleton($classname) {
107                if(!isset(self::$instance))
108                        self::$instance = new $classname;
109                return self::$instance;
110        }
111
112        /**
113         * Factory for creating a t29Host instance automatically
114         * from the current host. This method will decide which
115         * subclass has to be taken.
116         * This function als implements the Singleton pattern, so
117         * you can call it frequently.
118         **/
119        static function detect() {
120                $instance = null;
121
122                // check if local host file exists
123                $hostfile = dirname(__FILE__) . '/../' . self::webroot_host_file;
124                if(file_exists($hostfile)) {
125                        include $hostfile;
126                        if(class_exists(self::webroot_local_host_classname)) {
127                                $x = self::webroot_local_host_classname;
128                                $host = self::new_singleton($x);
129                                $host->setup();
130                                return $host;
131                        } else {
132                                print "Warning: Hostfile $hostfile does not contain class ".self::webroot_local_host_classname."\n";
133                        }
134                }
135               
136                // Quick and Dirty: Load hostname specific instances
137                switch($_SERVER['SERVER_NAME']) {
138                        case 'heribert':
139                        case 'localhost':
140                                $localhost = self::new_singleton('t29HeribertHost');
141                                $localhost->setup();
142                                return $localhost;
143                }
144               
145                $publichost = self::new_singleton('t29PublicHost');
146                $publichost->setup();
147                return $publichost;
148        }
149
150        /**
151         * "Factory" for creating an instance of $className as a singleton.
152         * You should really use detect() for auto-detection instead of
153         * forcing a host.
154         * Only useful for explicitely calling t29ExternalHost by $external call.
155         **/
156        static function create($className) {
157                return self::new_singleton($className)->setup();
158        }
159       
160        /**
161         * A constructing method which is always called by the t29Host::detect() factory.
162         * It does some general stuff.
163         * Of course you can always write your own setup() class - it's just your __constructor.
164         * The constructor will of course be called before the setup() method.
165         *
166         * This method detects two things:
167         *   1. if this host does Clean URLs (Suffix rewriting)
168         *   2. if this host is *not* installed in its own virtualhost (i.e. on docroot).
169         *
170         * @returns $this for chaining
171         **/
172        private function setup() {
173                $this->is_rewriting_host = isset($_SERVER[self::env_hidesuffix_name]);
174               
175                $this->lib = dirname(__FILE__);
176                $this->webroot = realpath($this->lib . '/../');  # file path to root of t29 web installation
177               
178                /*
179                   calculate the web_prefix. This is kind of a detection.
180                   
181                   Examples for an installation in Document root:
182                      $lib = /var/www/technikum29.de/lib
183                      $webroot = /var/www/technikum29.de
184                      $_SERVER["DOCUMENT_ROOT"] = /var/www/technikum29.de
185                      $this->document_root = /var/www/technikum29.de
186                      $_SERVER["SCRIPT_FILENAME"] = /var/www/technikum29-www/de/index.php
187                      $this->script_filename = /de/index.php
188                      $_SERVER["REQUEST_URI"] = /de
189                      $_SERVER["SCRIPT_NAME"] = /de/index.php
190                      $web_prefix = ""
191                     
192                   Example for an installation in an arbitrary directory below Document Root:
193                     $lib = /var/www/arbitrary/lib
194                     $webroot = /var/www/arbitrary
195                     $_SERVER['DOCUMENT_ROOT'] = /var/www
196                     $this->document_root = /var/www/arbitrary
197                     $_SERVER['SCRIPT_FILENAME'] = /var/www/arbitrary/de/index.php
198                     $this->script_filename = /arbitrary/de/index.php
199                     $_SERVER['REQUEST_URI'] = /arbitrary/de
200                     $_SERVER['SCRIPT_NAME'] = /arbitrary/de/index.php
201                     $web_prefix = "/arbitrary"
202                     
203                   Example for an installation in mod_userdirs homedir out of Docroot:
204                     $lib = /home/sven/public_html/foo/lib
205                     $webroot = /home/sven/public_html/foo
206                     $_SERVER['DOCUMENT_ROOT'] = /var/www   (mind that!)
207                     $this->document_root = /home/sven/public_html/foo
208                     $_SERVER['SCRIPT_FILENAME'] = /~sven/foo/en/index.php
209                     $this->script_filename = /~sven/foo/en/index.php
210                     $_SERVER['REQUEST_URI'] = /~sven/foo/en/
211                     $_SERVER['SCRIPT_NAME'] = /~sven/foo/en/index.php
212                     $web_prefix = "/~sven/foo"
213                */
214
215                // this algorithm is good for detecting paths below the document root.
216                // it is not suitable for paths out of the document root
217                $this->document_root = realpath($_SERVER['DOCUMENT_ROOT']);
218                if($this->webroot == $this->document_root) {
219                        // we are installed in document root
220                        $this->web_prefix = "";
221                } else {
222                        // we are installed in some arbitary directory
223                        $this->web_prefix = substr($this->webroot, strlen($this->document_root));
224                }
225               
226                // TODO: Somehow autodetect paths out of the document root
227               
228                $this->has_web_prefix = !empty($this->web_prefix);
229               
230                //print "Web prefix:<pre>";
231                //var_dump($this); exit;
232                   
233                $this->script_filename = substr(realpath($_SERVER['SCRIPT_FILENAME']), strlen($this->document_root)); # e.g.: "/de/page.php"
234
235                // Windows realpath() converts Unix Paths ($_SERVER) to Windows Paths (like \en\index.php).
236                // We want to use unix paths ($_SERVER like) internally, so do this dummy conversion back, if neccessary
237                $this->script_filename = str_replace('\\', '/', $this->script_filename);
238               
239                # Bug when DOCUMENT_ROOT ends with trailing slash: make sure $file begins with /:
240                $this->slash_filename = $this->script_filename;
241                if($this->slash_filename{0} != '/') $this->slash_filename = '/'.$this->slash_filename;
242       
243                //phpinfo(); exit;
244                return $this; // Chaining
245        }
246       
247        function check_url_rewrite() {
248                if($this->is_rewriting_host) {
249                        $path = $_SERVER['REQUEST_URI'];
250                        $newpath = $this->rewrite_link($path);
251                        if($path != $newpath) {
252                                header('HTTP/1.1 301 Moved Permanently');
253                                header('Location: '.$newpath);
254                                return $newpath;
255                        }
256                }
257                return null;
258        }
259
260        public function __toString() {
261                return 't29v6/'.$this->hostname;
262        }
263       
264        /**
265         * Rewrite Links so they match for this host.
266         * This method acts like a pipeline:
267         *  $new_link = rewrite_link($old_link);
268         * It can perform two conversions:
269         *
270         *   1. Rewriting/Clean URL system: Will strip file suffixes, if appropriate.
271         *      This will be done whenever this is a rewriting host and this is the
272         *      main purpose for this function.
273         *
274         *   2. Prefixing the correct web prefix. This is *only* be done when
275         *      $also_rewrite_prefix = true. The reaseon is that prefix rewriting is
276         *      generally done by a global page rewrite after generation of the whole
277         *      page on a whole-page-level. This is less error prone.
278         *      Anyway you can use this function if you think you need. blubblubb
279         *
280         *
281         **/
282        function rewrite_link($link_target, $also_rewrite_prefix=false) {
283                // rewrite link if neccessary. This function will be called hundreds of times
284                // while rendering a page, rewriting all links found.
285               
286                // pending: prefix setzen.
287                if($this->has_web_prefix && $also_rewrite_prefix) {
288                        $link_target = $this->web_prefix . $link_target;
289                }
290               
291                if($this->is_rewriting_host) {
292                        $new_target = preg_replace('/\.(?:php|shtml?)([#?].+)?$/i', '\\1', $link_target);
293                        return $new_target;
294                } else {
295                        // just the identity function
296                        return $link_target;
297                }
298               
299        }
300       
301        function get_shorthand_link_returner() {
302                $t = $this;
303                return function($link_target)use($t) { return $t->rewrite_link($link_target); };
304        }
305
306        abstract function fillup_template_conf(&$template_conf);
307}
308
309class t29PublicHost extends t29Host {
310        /**
311         * This is actually the default public host which should be loaded
312         * at www.technikum29.de.
313         **/
314        public $hostname = "public";
315        function fillup_template_conf(&$template_conf) {}
316}
317
318/**
319 * Host auf heriberts Rechner; dort wird ein weiterer Metatag mit id eingefuehrt,
320 * mit dem seine Firefox Editthispage-Extension die Seite bearbeiten kann.
321 **/
322class t29HeribertHost extends t29Host {
323        public $hostname = "heribert";
324
325        function fillup_template_conf(&$template_conf) {
326                $template_conf['header_prepend'][] = 
327                        '<meta name="t29.localfile" content="'.$_SERVER['SCRIPT_FILENAME'].'" id="localFileSource">';
328        }
329}
330
331/**
332 * Ein "external" Host, der Links mit voller URL angeben muss, etwa bei der
333 * Einbindung von CSS/JS, aber auch von Links.
334 * Genutzt fuer $external-Einbindung von technikum29.php
335 **/
336class t29ExternalHost extends t29Host {
337        public $hostname = "external";
338        public $target_host = 'http://www.technikum29.de';
339
340        function rewrite_link($link_target, $also_rewrite_prefix=false) {
341                $link_target = parent::rewrite_link($link_target, $also_rewrite_prefix);
342       
343                if($also_rewrite_prefix) {
344                        // check if link has host part
345                        if(!preg_match('#^http:#i', $link_target)) {
346                                $sep = ($link_target{0} == '/') ? '' : '/';
347                                $link_target = $this->target_host . $sep . $link_target;
348                        }
349                }
350
351                return $link_target;
352        }
353
354        function fillup_template_conf(&$template_conf) {
355                $template_conf['header_prepend'][] = 
356                        '<meta name="t29.host.from" content="'.$_SERVER['SERVER_NAME'].'">';
357        }
358}
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