Source for file Simple.php

Documentation is available at Simple.php

  1. <?php
  2. /**
  3.  *  Simple.php
  4.  *
  5.  *  @author     Keisuke SATO <riaf@me.com>
  6.  *  @package    Ethna
  7.  *  @version    $Id: b05bd254b9b40e0c2f998380421e86bf7868467c $
  8.  */
  9.  
  10. /**
  11.  *  URLハンドラクラス
  12.  *
  13.  *  @author     Keisuke SATO <riaf@me.com>
  14.  *  @access     public
  15.  *  @package    Ethna
  16.  */
  17. {
  18.     /** @var    array   アクションマッピング */
  19.     protected $action_map = array(
  20.         // 'index' => '/',
  21.         // 'wozozo_index' => '/wozozo',
  22.         // 'wozozo_message' => '/wozozo/{message}',
  23.         // 'message_show' => array(
  24.         //     'path' => '/message/{id}',
  25.         //     'patterns' => array(
  26.         //         'id' => '\d+',
  27.         //     ),
  28.         //     'defaults' => array(
  29.         //         'id' => 123,
  30.         //     ),
  31.         // ),
  32.     );
  33.  
  34.     /**
  35.      *  アクションをユーザリクエストに変換する
  36.      *
  37.      *  @access public
  38.      */
  39.     public function actionToRequest($action, $param=array())
  40.     {
  41.         $ret = null;
  42.         $action_map = $this->getActionMap();
  43.  
  44.         if (isset($action_map[$action])) {
  45.             $def = $action_map[$action];
  46.  
  47.             $paths = $this->sortPaths($def['path'], SORT_DESC);
  48.  
  49.             foreach ($paths as $path) {
  50.                 if (strpos($path, '{') && preg_match_all('/\{(.*?)\}/', $path, $matches)) {
  51.                     $keys = array_unique($matches[1]);
  52.                     $replaces = array();
  53.  
  54.                     foreach ($keys as $key) {
  55.                         $val = null;
  56.                         if (isset($param[$key])) {
  57.                             $val = $param[$key];
  58.                         } else if (isset($def['defaults']) && isset($def['defaults'][$key])) {
  59.                             $val = $def['defaults'][$key];
  60.                         }
  61.  
  62.                         if (!is_null($val)) {
  63.                             $replaces['{'.$key.'}'] = $val;
  64.                         } else {
  65.                             continue 2;
  66.                         }
  67.                     }
  68.  
  69.                     $ret = array(str_replace(array_keys($replaces), array_values($replaces), $path), $keys);
  70.                     break;
  71.                 } else {
  72.                     $ret = array($path, array());
  73.                     break;
  74.                 }
  75.             }
  76.         }
  77.  
  78.         return $ret;
  79.     }
  80.  
  81.     /**
  82.      * ユーザリクエストをアクションに変換する
  83.      *
  84.      * @param array $http_vars 
  85.      */
  86.     public function requestToAction($http_vars)
  87.     {
  88.         $path = '/';
  89.         $detected_action = null;
  90.  
  91.         if (isset($http_vars['__url_info__'])) {
  92.             $path = $this->normalizePath($http_vars['__url_info__']);
  93.         }
  94.  
  95.         foreach ($this->getActionMap() as $action => $def) {
  96.             foreach ($def['path'] as $pattern) {
  97.                 if (strpos($pattern, '{')) {
  98.                     $action = $this->getActionByRegex($path, $action, $def, $http_vars);
  99.  
  100.                     if (!is_null($action)) {
  101.                         $detected_action = $action;
  102.                         break;
  103.                     }
  104.                 } else {
  105.                     if ($path === $pattern) {
  106.                         $detected_action = $action;
  107.                         break;
  108.                     }
  109.                 }
  110.             }
  111.         }
  112.  
  113.         if (is_null($detected_action)) {
  114.             $http_vars = array();
  115.         } else {
  116.             $http_vars = $this->buildActionParameter($http_vars, $detected_action);
  117.         }
  118.  
  119.         return $http_vars;
  120.     }
  121.  
  122.     /**
  123.      * 正規表現でマッチさせる
  124.      *
  125.      * @param string $path 
  126.      * @param string $action 
  127.      * @param array $def 
  128.      * @param array $http_vars 
  129.      */
  130.     protected function getActionByRegex($path, $action, $def, &$http_vars)
  131.     {
  132.         $ret_action = null;
  133.         $regex_pattern = array();
  134.         $request_keys = array();
  135.  
  136.         foreach ($def['path'] as $pattern) {
  137.             if (preg_match_all('/\{(.*?)\}/', $pattern, $matches)) {
  138.                 $request_keys = $matches[1];
  139.  
  140.                 $replaces = array();
  141.                 foreach ($matches[0] as $i => $from) {
  142.                     $key = $matches[1][$i];
  143.                     $to = '([^\/]+?)';
  144.  
  145.                     if (isset($def['patterns']) && isset($def['patterns'][$key])) {
  146.                         $to = '('.$def['patterns'][$key].')';
  147.                     }
  148.  
  149.                     $replaces[preg_quote($from, '/')] = $to;
  150.                 }
  151.  
  152.                 $regex_pattern = '/^'.str_replace(array_keys($replaces), array_values($replaces), preg_quote($pattern, '/')).'$/';
  153.  
  154.                 if (preg_match($regex_pattern, $path, $match)) {
  155.                     $ret_action = $action;
  156.  
  157.                     foreach ($request_keys as $i => $key) {
  158.                         if (isset($match[$i+1])) {
  159.                             $http_vars[$key] = $match[$i+1];
  160.                         }
  161.                     }
  162.                 }
  163.             }
  164.         }
  165.  
  166.         return $ret_action;
  167.     }
  168.  
  169.     /**
  170.      *  Ethna_UrlHandlerクラスのインスタンスを取得する
  171.      *
  172.      *  $name がクラス名 ('_'を含む) の場合はそのクラスを、
  173.      *  そうでないときはプラグイン名とみなしてインスタンスを返す
  174.      *
  175.      *  @access public
  176.      */
  177.     public static function getInstance($name = null)
  178.     {
  179.         static $instance = array();
  180.         if ($name === null) {
  181.             $name = __CLASS__;
  182.         }
  183.         if (isset($instance[$name])) {
  184.             return $instance[$name];
  185.         }
  186.  
  187.         if (strpos($name, '_') !== false) {
  188.             $instance[$name] = new $name();
  189.         } else {
  190.             // get instance with plugin
  191.             $ctl = Ethna_Controller::getInstance();
  192.             $plugin = $ctl->getPlugin();
  193.             $instance[$name] = $plugin->getPlugin('Urlhandler', $name);
  194.         }
  195.  
  196.         return $instance[$name];
  197.     }
  198.  
  199.     /**
  200.      * get action_map
  201.      * より複雑な定義などを行うときはこれをオーバーライドする
  202.      *
  203.      * @return array 
  204.      */
  205.     protected function getActionMap()
  206.     {
  207.         foreach ($this->action_map as &$def) {
  208.             if (is_string($def)) {
  209.                 $def = array(
  210.                     'path' => array($def),
  211.                 );
  212.             } else if (is_array($def) && isset($def['path']) && is_string($def['path'])) {
  213.                 $def['path'] = array($def['path']);
  214.             }
  215.         }
  216.  
  217.         return $this->action_map;
  218.     }
  219.  
  220.     /**
  221.      *  ゲートウェイパスを正規化する
  222.      *
  223.      *  @access protected
  224.      */
  225.     protected function normalizePath($path)
  226.     {
  227.         if ($path == "") {
  228.             return array($path, false);
  229.         }
  230.  
  231.         $path = preg_replace('|/+|', '/', $path);
  232.         $path = '/'.trim($path, '/');
  233.  
  234.         return $path;
  235.     }
  236.  
  237.     /**
  238.      * 引数順にソートする
  239.      *
  240.      * @access protected
  241.      */
  242.     protected function sortPaths(array $paths, $sort = SORT_ASC)
  243.     {
  244.         $counts = array();
  245.         foreach ($paths as $path) {
  246.             $counts[] = substr_count($path, '{');
  247.         }
  248.  
  249.         array_multisort($paths, $sort, $counts);
  250.  
  251.         return $paths;
  252.     }
  253.  
  254.     /**
  255.      *  アクションをリクエストパラメータに変換する
  256.      *
  257.      *  @access protected
  258.      */
  259.     protected function buildActionParameter($http_vars, $action)
  260.     {
  261.         if ($action == "") {
  262.             return $http_vars;
  263.         }
  264.  
  265.         $key = sprintf('action_%s', $action);
  266.         $http_vars[$key] = 'true';
  267.  
  268.         return $http_vars;
  269.     }
  270. }

Documentation generated on Fri, 11 Nov 2011 03:59:04 +0900 by phpDocumentor 1.4.3