aboutsummaryrefslogtreecommitdiffstats
path: root/lib/pinq/Controller.php
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pinq/Controller.php')
-rw-r--r--lib/pinq/Controller.php270
1 files changed, 270 insertions, 0 deletions
diff --git a/lib/pinq/Controller.php b/lib/pinq/Controller.php
new file mode 100644
index 000000000..af82c3b0d
--- /dev/null
+++ b/lib/pinq/Controller.php
@@ -0,0 +1,270 @@
+<?php
+/**
+ *
+ * PHP version 5.4
+ *
+ * @category Mageia
+ * @package Mageia\Web\www\Pinq
+ * @author rda <rda@mageia.org>
+ * @link http://www.mageia.org/
+ *
+ * @license http://www.gnu.org/licenses/gpl-2.0.html GNU GPL v2+
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License aspublished by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+*/
+
+/**
+*/
+class Pinq_Controller
+{
+ /**
+ * @param string $dir root application directory
+ * @param array $server $_SERVER array
+ *
+ */
+ public function __construct($dir, $server)
+ {
+ $this->_app_root = $dir;
+ $this->_server = $server;
+ }
+
+ /**
+ */
+ public static function run($app_root, $routes, $_server, $cache)
+ {
+ $pc = new self($app_root, $_server);
+ $pc->init();
+
+ if (isset($cache)
+ && $res = $cache->get($pc->get_cache_key())) {
+
+ } else {
+ $res = $pc->_run($routes);
+
+ if (isset($cache)
+ && isset($res['cache'])
+ && $res['cache'] > 0) {
+
+ $cache->set($res, $pc->cache_key());
+ }
+ }
+
+ $pc->publish($res);
+ unset($pc);
+ }
+
+ /**
+ */
+ public function init()
+ {
+ $this->method = $this->_server['REQUEST_METHOD'];
+ $this->uri = $this->_server['REQUEST_URI'];
+
+ if (strpos('?', $this->uri) !== false) {
+ $uri = explode('?', $this->uri);
+ $this->query = $uri[1];
+ $this->uri = $uri[0];
+ }
+ }
+
+ /**
+ */
+ public function get_cache_key()
+ {
+ return sha1(implode('#', array($this->method, $this->uri)));
+ }
+
+ /**
+ * Prints document headers and contents.
+ * It _expects_ $res to be correctly formatted.
+ *
+ * @param array $res as returned by self::_run()
+ *
+ * @return void
+ */
+ public function publish($res)
+ {
+ //$res['statuts']
+ // Content-Length must match buffer + body
+ foreach ($res['headers'] as $h => $v) {
+ header($h);
+ }
+ echo $res['buffer'];
+ echo $res['body'];
+ }
+
+ /**
+ * @param array $routes
+ *
+ * @return boolean
+ */
+ private function _run($routes = null)
+ {
+ // static, image files are expected to be served directly by the server.
+ $ret = array(
+ 'body' => '',
+ 'buffer' => '',
+ 'cache' => 0,
+ 'headers' => array()
+ );
+
+ // detect path language; if not set, redirect to best fallback language (English for now), end
+ $this->lang = $this->get_request_language($this->uri);
+
+ if (!$this->lang_is_managed($this->lang)) {
+ // TODO - ignore, with a special code or redirect?
+ $this->lang = 'en';
+ }
+
+ // TODO ob_start, etc.?
+
+ if ($app = $this->matches_route($this->uri, $routes)) {
+ // 1.
+ $ret = $this->delegate_to($app);
+ } elseif (false) { // TODO
+ // 2.
+ // delegate to local script
+ // TODO look at local code at $uri, and decide if we can/should load it and decorate it. How?
+ } elseif ($this->fallback_to_previous_mode($this->uri, $this->lang)) {
+ // 3.
+ // finally, act as we used to before
+ } else {
+ // 4.
+ // if nothing matched, well...
+ $ret = $this->delegate_to('error', array('code' => '404'));
+ }
+
+ return $ret;
+ }
+
+ /**
+ * @param string $uri
+ * @param array $routes
+ *
+ * @return string
+ */
+ private function matches_route($uri, $routes)
+ {
+ $re = '
+ /
+ \/(([a-zA-Z\-\_]{2,5})\/)?
+ (.*)
+ /x';
+
+ if (preg_match_all($re, $uri, $matches)) {
+ $this->_lang = $matches[2][0];
+ $this->_path = $matches[3][0];
+ }
+
+ if (is_array($routes) && count($routes) > 0) {
+ foreach ($routes as $r => $app) {
+ $re = '/' . $r . '/';
+ if (preg_match_all($re, $uri, $m)) {
+ return $app;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * @param string $uri
+ *
+ * @return string
+ */
+ function get_request_language($uri)
+ {
+ $tu = explode('/', $uri);
+ $lang = $tu[1];
+ $sl = strlen($lang);
+ if ($this->lang_exists($lang)) {
+ return $lang;
+ }
+
+ return null;
+ }
+
+ /**
+ */
+ function lang_exists($lang)
+ {
+ // is it a valid language code? ll[-cc] or ll[_CC]?
+ return true;
+ }
+
+ /**
+ */
+ function lang_is_managed($lang)
+ {
+ // in managed languages array?
+ return true;
+ }
+
+ /**
+ * @param string $app_name
+ *
+ * @return boolean
+ */
+ private function delegate_to($app_name, $options = null)
+ {
+ $app_cont = realpath(sprintf('%s/apps/%s/%s_app.php', $this->_app_root, $app_name, $app_name));
+ if (!file_exists($app_cont)) {
+ throw new Exception(sprintf('Expected "%s" app, found no definition file.', $app_name));
+ }
+
+ include $app_cont;
+ $a = new $app_name($this, $options);
+
+ return $a->run();
+ }
+
+ /**
+ * @return boolean true if fallback happened
+ */
+ function fallback_to_previous_mode($uri, $lang)
+ {
+ $uri = explode('?', $uri);
+ $qs = count($uri) > 1 ? $uri[1] : null;
+ $uri = $uri[0];
+
+ $alt_uri = sprintf(
+ '/%s/%s',
+ 'en',
+ substr($uri, strlen($lang) + 2)
+ );
+
+ $test_uris = array(
+ $uri,
+ $uri . 'index.php',
+ $uri . 'index.html',
+ $alt_uri,
+ $alt_uri . 'index.php',
+ $alt_uri . 'index.html'
+ );
+
+ $found = false;
+
+ foreach ($test_uris as $inc_uri) {
+
+ $real_file = realpath($this->_app_root . $inc_uri);
+ if (file_exists($real_file) && !is_dir($real_file)) {
+
+ $found = true;
+ break;
+ }
+ }
+
+ if ($found) {
+ chdir(dirname($real_file));
+ require $real_file;
+ return true;
+ }
+
+ return false;
+ }
+
+}