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

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