Advertisement
Guest User

Igor Hlina

a guest
Feb 1st, 2009
1,452
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 9.44 KB | None | 0 0
  1. <?php
  2. /**
  3.  * Router.php
  4.  * this file is contains Router class definition
  5.  *
  6.  * @version 0.68
  7.  * @copyright Copyright (c) 2009 Igor Hlina
  8.  * @license read LICENCE.txt
  9.  *
  10.  */
  11.  
  12.  
  13. /**
  14.  * Router class
  15.  * This class analyzes URL, acording to that runs adquate Controller.
  16.  * Also detects clients preffered language
  17.  *
  18.  */
  19. class Router
  20. {
  21.  
  22.     /**
  23.      * Registry object
  24.      *
  25.      * @var object
  26.      */
  27.     private $registry;
  28.  
  29.  
  30.     /**
  31.      * View object
  32.      *
  33.      * @var object
  34.      */
  35.     private $view;
  36.  
  37.  
  38.     /**
  39.      * Path to controllers source files
  40.      *
  41.      * @var string
  42.      */
  43.     private $ctrlPath;
  44.  
  45.  
  46.     /**
  47.      * Asign needed elements to internal variables
  48.      *
  49.      * @param object $registry
  50.      */
  51.     public function __construct($registry)
  52.     {
  53.         $this->registry = $registry;
  54.         $this->view     = $this->registry['view'];
  55.     }
  56.  
  57.  
  58.     /**
  59.      * Set path to controllers
  60.      *
  61.      * @param string $path
  62.      * @return void
  63.      */
  64.     public function setPath($path)
  65.     {
  66.         $path  = rtrim($path, '/\\');
  67.         $path .= DS;
  68.  
  69.         if (!is_dir($path)) {
  70.             throw new Exception ('Invalid controller path: `' . $path . '`');
  71.         }
  72.  
  73.         $this->ctrlPath = $path;
  74.     }
  75.  
  76.  
  77.     /**
  78.      * Parse URL. Find out which controller and action to run
  79.      * Store additional elements in URL to $args.
  80.      * Gained informations return by reference
  81.      *
  82.      * @param string $controller
  83.      * @param string $action
  84.      * @param string $lang
  85.      * @param string $args
  86.      */
  87.     private function parseUrl(&$file, &$controller, &$action, &$lang, &$args)
  88.     {
  89.         $route = (empty($_GET['route'])) ? '' : $_GET['route'];
  90.         if (empty($route)) {
  91.             $route = 'index';
  92.         }
  93.  
  94.         // split route by slashes
  95.         $route = trim($route, '/\\');
  96.         $parts = explode('/', $route);
  97.  
  98.         // test if very first URL part is 2chars langcode
  99.         $langtest = array_shift($parts);  // move first part out of array
  100.  
  101.         if (preg_match('/^[a-z]{2}$/i', $langtest)) {
  102.             $lang = $langtest;
  103.         } else {
  104.             // not a langcode, put URL part back to array
  105.             array_unshift($parts, $langtest);
  106.         }
  107.  
  108.         // Find right controller
  109.         $cmdPath = $this->ctrlPath;
  110.         foreach ($parts as $part) {
  111.             $part     = str_replace('-', '_', $part);
  112.             $fullPath = $cmdPath . $part;
  113.  
  114.             // Check if part is name of a directory
  115.             if (is_dir($fullPath)) {
  116.                 $cmdPath .= $part . DS;
  117.                 array_shift($parts);
  118.                 continue;
  119.  
  120.             } else {
  121.                 // try to find Controller source file
  122.                 $fullPath = $cmdPath . ucfirst($part);  // capitalize first char in filename
  123.                 if (is_file($fullPath . 'Controller.php')) {
  124.                     // gained controller name
  125.                     $controller = ucfirst($part) . 'Controller';    // compose controller name
  126.                     array_shift($parts);
  127.                     break;
  128.  
  129.                 } else {
  130.                     // no Controller of specified name find,
  131.                     // continue with error
  132.                     $controller = 'ErrorController';
  133.                     break;
  134.                 }
  135.             }
  136.         }
  137.  
  138.         // if URL was empty, set default controller
  139.         if (empty($controller)) { $controller = 'IndexController'; };
  140.  
  141.         // compose filename
  142.         $file = $cmdPath . $controller. '.php';
  143.  
  144.         // gain action
  145.         if ($controller == 'ErrorController') {
  146.             $action = 'index';
  147.  
  148.         } else {
  149.             $action = array_shift($parts);
  150.             $action = str_replace('-', '_', $action);
  151.  
  152.             if (empty($action)) {
  153.                 // URL was not containing actionname
  154.                 $action = 'index';
  155.             }
  156.         }
  157.  
  158.         $args = $parts;  // return all other elements of URL in $args
  159.     }
  160.  
  161.  
  162.     /**
  163.      * This method runs the application
  164.      * parses URL, to get controller & action to run
  165.      * if URL is invalid, passes control to ErrorController
  166.      *
  167.      * @return  void
  168.      */
  169.     public function delegate()
  170.     {
  171.         $this->parseUrl($file, $controller, $action, $lang, $args);
  172.         $this->registry['args'] = $args;
  173.  
  174.         // File available?
  175.         if (!file_exists($file)) {
  176.             $controller = "ErrorController";
  177.             $file = $this->ctrlPath . $controller. '.php';
  178.             $action = 'index';
  179.         }
  180.  
  181.         if (is_readable($file) == false) {
  182.             throw new Exception("File '$file' cannot be read from filesystem");
  183.         }
  184.  
  185.         // Include controller definition
  186.         include($file);
  187.  
  188.         // Initiate the controller
  189.         $controllerObj = new $controller($this->registry);
  190.  
  191.         // Action available?
  192.         if (!method_exists($controllerObj, $action)) {
  193.             // gained action name not exist
  194.             unset($controllerObj);           // free uneeded Controller
  195.             $this->registry->remove('args'); // free unneded URL arguments
  196.  
  197.             // pass control to ErrorController
  198.             $controller = 'ErrorController';
  199.             $action     = 'index';
  200.             $file       = $this->ctrlPath . "$controller.php";
  201.             include($file);
  202.  
  203.             // Initiate the class
  204.             $controllerObj = new $controller($this->registry);
  205.         }
  206.  
  207.         // Run Controller::action()
  208.         $controllerObj->$action();
  209.     }
  210.  
  211.  
  212.     /**
  213.      * Get working directory of the application in web_root
  214.      *
  215.      * @return  string
  216.      */
  217.     public function getBaseUrl()
  218.     {
  219.         $dirName = rtrim(dirname($_SERVER['PHP_SELF']), '/\\');
  220.         return("http://$_SERVER[SERVER_NAME]" . $dirName);
  221.     }
  222.  
  223.  
  224.     /**
  225.      * Resolves langcode, which will be used across application
  226.      * Also gains Ctrl and action names for autodetection on indexpage
  227.      *
  228.      * @return string
  229.      */
  230.     public function getClientLang()
  231.     {
  232.         $this->parseUrl($file, $controller, $action, $lang, $args);
  233.  
  234.         // check if is there language identifier in URL
  235.         if (empty($lang)) {
  236.             // recieved URL without lang identifier
  237.             // detect language from UA
  238.             // do this only on index page
  239.  
  240.             // check if request to indexpage
  241.             if ($controller == 'IndexController' && $action == 'index') {
  242.                 // we are on indexpage, resolve lang from UA
  243.                 if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { // test if UA contains langcode
  244.                     // USER_AGENT language identifier present
  245.                     // get language from it
  246.                     $lang = $this->getUAlang();
  247.  
  248.                     // check if gained langcode is supported by application
  249.                     if (!in_array($lang, $this->registry['supportedLangs'])) {
  250.                         // this lang identifier is not supported by application
  251.                         return DEFAULTLANG;
  252.  
  253.                     } else {
  254.                         // rediredt only if resolved is not DEFAULTLANG
  255.                         if ($lang != DEFAULTLANG) {
  256.                             header('Location: ' . $this->getBaseUrl() . "/$lang", true, 303);
  257.                             die;
  258.  
  259.                         } else {
  260.                             return DEFAULTLANG;
  261.                         }
  262.                     }
  263.  
  264.                 } else {
  265.                     // langcode not present in UA (probably validator or robot)
  266.                     // set default lang for enviroment
  267.                     return DEFAULTLANG;
  268.                 }
  269.  
  270.             } else {
  271.                 // not on indexpage, break detection
  272.                 return DEFAULTLANG;
  273.             }
  274.  
  275.         } else {
  276.             // lang identifier was present in URL
  277.             // check if identifier is supported by application
  278.             if (!in_array($lang, $this->registry['supportedLangs'])) {
  279.                 // this lang URL identifier is not supported by application
  280.                 // redirect to indexpage
  281.                 header('Location: ' . $this->getBaseUrl(), true, 303);
  282.                 die;
  283.  
  284.             } else {
  285.                 return $lang;
  286.             }
  287.         }
  288.     }
  289.  
  290.  
  291.     /**
  292.      * Gain langcode from user's browser.
  293.      * Also aling slight diferences in this langcode.
  294.      * If langcode is not recognized, return default value.
  295.      *
  296.      * @return string
  297.      */
  298.     private function getUaLang()
  299.     {
  300.         $ua_langs     = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
  301.         $primary_lang = array_shift($ua_langs);
  302.  
  303.         switch (strtolower($primary_lang)) {
  304.             case 'en':
  305.             case 'en-us':
  306.             case 'en-au':
  307.             case 'en-ca':
  308.             case 'en-ie':
  309.             case 'en-gb':
  310.                 return('en');
  311.  
  312.             /*
  313.             case 'de':
  314.             case 'de-de':
  315.             case 'de-at':
  316.             case 'de-li':
  317.             case 'de-lu':
  318.             case 'de-ch':
  319.                 return('de');
  320.  
  321.             case 'pl':
  322.             case 'pl-pl':
  323.                 return('pl');
  324.  
  325.             case 'cs':
  326.             case 'cs-cz':
  327.                 return('cz');
  328.             //*/
  329.  
  330.             case "sk":
  331.             case "sk-sk":
  332.                 return('sk');
  333.  
  334.             default:
  335.                 return DEFAULTLANG;
  336.         }
  337.     }
  338.  
  339. }
  340.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement