| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601 | 
							- <?php
 
- // +----------------------------------------------------------------------
 
- // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 
- // +----------------------------------------------------------------------
 
- // | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
 
- // +----------------------------------------------------------------------
 
- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 
- // +----------------------------------------------------------------------
 
- // | Author: liu21st <liu21st@gmail.com>
 
- // +----------------------------------------------------------------------
 
- namespace think\route;
 
- use think\Container;
 
- use think\Exception;
 
- use think\Request;
 
- use think\Response;
 
- use think\Route;
 
- use think\route\dispatch\Response as ResponseDispatch;
 
- use think\route\dispatch\Url as UrlDispatch;
 
- class RuleGroup extends Rule
 
- {
 
-     // 分组路由(包括子分组)
 
-     protected $rules = [
 
-         '*'       => [],
 
-         'get'     => [],
 
-         'post'    => [],
 
-         'put'     => [],
 
-         'patch'   => [],
 
-         'delete'  => [],
 
-         'head'    => [],
 
-         'options' => [],
 
-     ];
 
-     // MISS路由
 
-     protected $miss;
 
-     // 自动路由
 
-     protected $auto;
 
-     // 完整名称
 
-     protected $fullName;
 
-     // 所在域名
 
-     protected $domain;
 
-     /**
 
-      * 架构函数
 
-      * @access public
 
-      * @param  Route       $router   路由对象
 
-      * @param  RuleGroup   $parent   上级对象
 
-      * @param  string      $name     分组名称
 
-      * @param  mixed       $rule     分组路由
 
-      * @param  array       $option   路由参数
 
-      * @param  array       $pattern  变量规则
 
-      */
 
-     public function __construct(Route $router, RuleGroup $parent = null, $name = '', $rule = [], $option = [], $pattern = [])
 
-     {
 
-         $this->router  = $router;
 
-         $this->parent  = $parent;
 
-         $this->rule    = $rule;
 
-         $this->name    = trim($name, '/');
 
-         $this->option  = $option;
 
-         $this->pattern = $pattern;
 
-         $this->setFullName();
 
-         if ($this->parent) {
 
-             $this->domain = $this->parent->getDomain();
 
-             $this->parent->addRuleItem($this);
 
-         }
 
-         if (!empty($option['cross_domain'])) {
 
-             $this->router->setCrossDomainRule($this);
 
-         }
 
-         if ($router->isTest()) {
 
-             $this->lazy(false);
 
-         }
 
-     }
 
-     /**
 
-      * 设置分组的路由规则
 
-      * @access public
 
-      * @return void
 
-      */
 
-     protected function setFullName()
 
-     {
 
-         if (false !== strpos($this->name, ':')) {
 
-             $this->name = preg_replace(['/\[\:(\w+)\]/', '/\:(\w+)/'], ['<\1?>', '<\1>'], $this->name);
 
-         }
 
-         if ($this->parent && $this->parent->getFullName()) {
 
-             $this->fullName = $this->parent->getFullName() . ($this->name ? '/' . $this->name : '');
 
-         } else {
 
-             $this->fullName = $this->name;
 
-         }
 
-     }
 
-     /**
 
-      * 获取所属域名
 
-      * @access public
 
-      * @return string
 
-      */
 
-     public function getDomain()
 
-     {
 
-         return $this->domain;
 
-     }
 
-     /**
 
-      * 检测分组路由
 
-      * @access public
 
-      * @param  Request      $request  请求对象
 
-      * @param  string       $url      访问地址
 
-      * @param  bool         $completeMatch   路由是否完全匹配
 
-      * @return Dispatch|false
 
-      */
 
-     public function check($request, $url, $completeMatch = false)
 
-     {
 
-         // 跨域OPTIONS请求
 
-         if ($dispatch = $this->checkCrossDomain($request)) {
 
-             return $dispatch;
 
-         }
 
-         // 检查分组有效性
 
-         if (!$this->checkOption($this->option, $request) || !$this->checkUrl($url)) {
 
-             return false;
 
-         }
 
-         // 检查前置行为
 
-         if (isset($this->option['before'])) {
 
-             if (false === $this->checkBefore($this->option['before'])) {
 
-                 return false;
 
-             }
 
-             unset($this->option['before']);
 
-         }
 
-         // 解析分组路由
 
-         if ($this instanceof Resource) {
 
-             $this->buildResourceRule();
 
-         } elseif ($this->rule) {
 
-             if ($this->rule instanceof Response) {
 
-                 return new ResponseDispatch($request, $this, $this->rule);
 
-             }
 
-             $this->parseGroupRule($this->rule);
 
-         }
 
-         // 获取当前路由规则
 
-         $method = strtolower($request->method());
 
-         $rules  = $this->getMethodRules($method);
 
-         if ($this->parent) {
 
-             // 合并分组参数
 
-             $this->mergeGroupOptions();
 
-             // 合并分组变量规则
 
-             $this->pattern = array_merge($this->parent->getPattern(), $this->pattern);
 
-         }
 
-         if (isset($this->option['complete_match'])) {
 
-             $completeMatch = $this->option['complete_match'];
 
-         }
 
-         if (!empty($this->option['merge_rule_regex'])) {
 
-             // 合并路由正则规则进行路由匹配检查
 
-             $result = $this->checkMergeRuleRegex($request, $rules, $url, $completeMatch);
 
-             if (false !== $result) {
 
-                 return $result;
 
-             }
 
-         }
 
-         // 检查分组路由
 
-         foreach ($rules as $key => $item) {
 
-             $result = $item->check($request, $url, $completeMatch);
 
-             if (false !== $result) {
 
-                 return $result;
 
-             }
 
-         }
 
-         if ($this->auto) {
 
-             // 自动解析URL地址
 
-             $result = new UrlDispatch($request, $this, $this->auto . '/' . $url, ['auto_search' => false]);
 
-         } elseif ($this->miss && in_array($this->miss->getMethod(), ['*', $method])) {
 
-             // 未匹配所有路由的路由规则处理
 
-             $result = $this->miss->parseRule($request, '', $this->miss->getRoute(), $url, $this->miss->mergeGroupOptions());
 
-         } else {
 
-             $result = false;
 
-         }
 
-         return $result;
 
-     }
 
-     /**
 
-      * 获取当前请求的路由规则(包括子分组、资源路由)
 
-      * @access protected
 
-      * @param  string      $method
 
-      * @return array
 
-      */
 
-     protected function getMethodRules($method)
 
-     {
 
-         return array_merge($this->rules[$method], $this->rules['*']);
 
-     }
 
-     /**
 
-      * 分组URL匹配检查
 
-      * @access protected
 
-      * @param  string     $url
 
-      * @return bool
 
-      */
 
-     protected function checkUrl($url)
 
-     {
 
-         if ($this->fullName) {
 
-             $pos = strpos($this->fullName, '<');
 
-             if (false !== $pos) {
 
-                 $str = substr($this->fullName, 0, $pos);
 
-             } else {
 
-                 $str = $this->fullName;
 
-             }
 
-             if ($str && 0 !== stripos(str_replace('|', '/', $url), $str)) {
 
-                 return false;
 
-             }
 
-         }
 
-         return true;
 
-     }
 
-     /**
 
-      * 延迟解析分组的路由规则
 
-      * @access public
 
-      * @param  bool     $lazy   路由是否延迟解析
 
-      * @return $this
 
-      */
 
-     public function lazy($lazy = true)
 
-     {
 
-         if (!$lazy) {
 
-             $this->parseGroupRule($this->rule);
 
-             $this->rule = null;
 
-         }
 
-         return $this;
 
-     }
 
-     /**
 
-      * 解析分组和域名的路由规则及绑定
 
-      * @access public
 
-      * @param  mixed        $rule    路由规则
 
-      * @return void
 
-      */
 
-     public function parseGroupRule($rule)
 
-     {
 
-         $origin = $this->router->getGroup();
 
-         $this->router->setGroup($this);
 
-         if ($rule instanceof \Closure) {
 
-             Container::getInstance()->invokeFunction($rule);
 
-         } elseif (is_array($rule)) {
 
-             $this->addRules($rule);
 
-         } elseif (is_string($rule) && $rule) {
 
-             $this->router->bind($rule, $this->domain);
 
-         }
 
-         $this->router->setGroup($origin);
 
-     }
 
-     /**
 
-      * 检测分组路由
 
-      * @access public
 
-      * @param  Request      $request  请求对象
 
-      * @param  array        $rules    路由规则
 
-      * @param  string       $url      访问地址
 
-      * @param  bool         $completeMatch   路由是否完全匹配
 
-      * @return Dispatch|false
 
-      */
 
-     protected function checkMergeRuleRegex($request, &$rules, $url, $completeMatch)
 
-     {
 
-         $depr = $this->router->config('pathinfo_depr');
 
-         $url  = $depr . str_replace('|', $depr, $url);
 
-         foreach ($rules as $key => $item) {
 
-             if ($item instanceof RuleItem) {
 
-                 $rule = $depr . str_replace('/', $depr, $item->getRule());
 
-                 if ($depr == $rule && $depr != $url) {
 
-                     unset($rules[$key]);
 
-                     continue;
 
-                 }
 
-                 $complete = null !== $item->getOption('complete_match') ? $item->getOption('complete_match') : $completeMatch;
 
-                 if (false === strpos($rule, '<')) {
 
-                     if (0 === strcasecmp($rule, $url) || (!$complete && 0 === strncasecmp($rule, $url, strlen($rule)))) {
 
-                         return $item->checkRule($request, $url, []);
 
-                     }
 
-                     unset($rules[$key]);
 
-                     continue;
 
-                 }
 
-                 $slash = preg_quote('/-' . $depr, '/');
 
-                 if ($matchRule = preg_split('/[' . $slash . ']<\w+\??>/', $rule, 2)) {
 
-                     if ($matchRule[0] && 0 !== strncasecmp($rule, $url, strlen($matchRule[0]))) {
 
-                         unset($rules[$key]);
 
-                         continue;
 
-                     }
 
-                 }
 
-                 if (preg_match_all('/[' . $slash . ']?<?\w+\??>?/', $rule, $matches)) {
 
-                     unset($rules[$key]);
 
-                     $pattern = array_merge($this->getPattern(), $item->getPattern());
 
-                     $option  = array_merge($this->getOption(), $item->getOption());
 
-                     $regex[$key] = $this->buildRuleRegex($rule, $matches[0], $pattern, $option, $complete, '_THINK_' . $key);
 
-                     $items[$key] = $item;
 
-                 }
 
-             }
 
-         }
 
-         if (empty($regex)) {
 
-             return false;
 
-         }
 
-         try {
 
-             $result = preg_match('/^(?:' . implode('|', $regex) . ')/u', $url, $match);
 
-         } catch (\Exception $e) {
 
-             throw new Exception('route pattern error');
 
-         }
 
-         if ($result) {
 
-             $var = [];
 
-             foreach ($match as $key => $val) {
 
-                 if (is_string($key) && '' !== $val) {
 
-                     list($name, $pos) = explode('_THINK_', $key);
 
-                     $var[$name] = $val;
 
-                 }
 
-             }
 
-             if (!isset($pos)) {
 
-                 foreach ($regex as $key => $item) {
 
-                     if (0 === strpos(str_replace(['\/', '\-', '\\' . $depr], ['/', '-', $depr], $item), $match[0])) {
 
-                         $pos = $key;
 
-                         break;
 
-                     }
 
-                 }
 
-             }
 
-             $rule  = $items[$pos]->getRule();
 
-             $array = $this->router->getRule($rule);
 
-             foreach ($array as $item) {
 
-                 if (in_array($item->getMethod(), ['*', strtolower($request->method())])) {
 
-                     $result = $item->checkRule($request, $url, $var);
 
-                     if (false !== $result) {
 
-                         return $result;
 
-                     }
 
-                 }
 
-             }
 
-         }
 
-         return false;
 
-     }
 
-     /**
 
-      * 获取分组的MISS路由
 
-      * @access public
 
-      * @return RuleItem|null
 
-      */
 
-     public function getMissRule()
 
-     {
 
-         return $this->miss;
 
-     }
 
-     /**
 
-      * 获取分组的自动路由
 
-      * @access public
 
-      * @return string
 
-      */
 
-     public function getAutoRule()
 
-     {
 
-         return $this->auto;
 
-     }
 
-     /**
 
-      * 注册自动路由
 
-      * @access public
 
-      * @param  string     $route   路由规则
 
-      * @return void
 
-      */
 
-     public function addAutoRule($route)
 
-     {
 
-         $this->auto = $route;
 
-     }
 
-     /**
 
-      * 注册MISS路由
 
-      * @access public
 
-      * @param  string    $route      路由地址
 
-      * @param  string    $method     请求类型
 
-      * @param  array     $option     路由参数
 
-      * @return RuleItem
 
-      */
 
-     public function addMissRule($route, $method = '*', $option = [])
 
-     {
 
-         // 创建路由规则实例
 
-         $ruleItem = new RuleItem($this->router, $this, null, '', $route, strtolower($method), $option);
 
-         $this->miss = $ruleItem;
 
-         return $ruleItem;
 
-     }
 
-     /**
 
-      * 添加分组下的路由规则或者子分组
 
-      * @access public
 
-      * @param  string    $rule       路由规则
 
-      * @param  string    $route      路由地址
 
-      * @param  string    $method     请求类型
 
-      * @param  array     $option     路由参数
 
-      * @param  array     $pattern    变量规则
 
-      * @return $this
 
-      */
 
-     public function addRule($rule, $route, $method = '*', $option = [], $pattern = [])
 
-     {
 
-         // 读取路由标识
 
-         if (is_array($rule)) {
 
-             $name = $rule[0];
 
-             $rule = $rule[1];
 
-         } elseif (is_string($route)) {
 
-             $name = $route;
 
-         } else {
 
-             $name = null;
 
-         }
 
-         $method = strtolower($method);
 
-         if ('/' === $rule || '' === $rule) {
 
-             // 首页自动完整匹配
 
-             $rule .= '$';
 
-         }
 
-         // 创建路由规则实例
 
-         $ruleItem = new RuleItem($this->router, $this, $name, $rule, $route, $method, $option, $pattern);
 
-         if (!empty($option['cross_domain'])) {
 
-             $this->router->setCrossDomainRule($ruleItem, $method);
 
-         }
 
-         $this->addRuleItem($ruleItem, $method);
 
-         return $ruleItem;
 
-     }
 
-     /**
 
-      * 批量注册路由规则
 
-      * @access public
 
-      * @param  array     $rules      路由规则
 
-      * @param  string    $method     请求类型
 
-      * @param  array     $option     路由参数
 
-      * @param  array     $pattern    变量规则
 
-      * @return void
 
-      */
 
-     public function addRules($rules, $method = '*', $option = [], $pattern = [])
 
-     {
 
-         foreach ($rules as $key => $val) {
 
-             if (is_numeric($key)) {
 
-                 $key = array_shift($val);
 
-             }
 
-             if (is_array($val)) {
 
-                 $route   = array_shift($val);
 
-                 $option  = $val ? array_shift($val) : [];
 
-                 $pattern = $val ? array_shift($val) : [];
 
-             } else {
 
-                 $route = $val;
 
-             }
 
-             $this->addRule($key, $route, $method, $option, $pattern);
 
-         }
 
-     }
 
-     public function addRuleItem($rule, $method = '*')
 
-     {
 
-         if (strpos($method, '|')) {
 
-             $rule->method($method);
 
-             $method = '*';
 
-         }
 
-         $this->rules[$method][] = $rule;
 
-         return $this;
 
-     }
 
-     /**
 
-      * 设置分组的路由前缀
 
-      * @access public
 
-      * @param  string     $prefix
 
-      * @return $this
 
-      */
 
-     public function prefix($prefix)
 
-     {
 
-         if ($this->parent && $this->parent->getOption('prefix')) {
 
-             $prefix = $this->parent->getOption('prefix') . $prefix;
 
-         }
 
-         return $this->option('prefix', $prefix);
 
-     }
 
-     /**
 
-      * 设置资源允许
 
-      * @access public
 
-      * @param  array     $only
 
-      * @return $this
 
-      */
 
-     public function only($only)
 
-     {
 
-         return $this->option('only', $only);
 
-     }
 
-     /**
 
-      * 设置资源排除
 
-      * @access public
 
-      * @param  array     $except
 
-      * @return $this
 
-      */
 
-     public function except($except)
 
-     {
 
-         return $this->option('except', $except);
 
-     }
 
-     /**
 
-      * 设置资源路由的变量
 
-      * @access public
 
-      * @param  array     $vars
 
-      * @return $this
 
-      */
 
-     public function vars($vars)
 
-     {
 
-         return $this->option('var', $vars);
 
-     }
 
-     /**
 
-      * 合并分组的路由规则正则
 
-      * @access public
 
-      * @param  bool     $merge
 
-      * @return $this
 
-      */
 
-     public function mergeRuleRegex($merge = true)
 
-     {
 
-         return $this->option('merge_rule_regex', $merge);
 
-     }
 
-     /**
 
-      * 获取完整分组Name
 
-      * @access public
 
-      * @return string
 
-      */
 
-     public function getFullName()
 
-     {
 
-         return $this->fullName;
 
-     }
 
-     /**
 
-      * 获取分组的路由规则
 
-      * @access public
 
-      * @param  string     $method
 
-      * @return array
 
-      */
 
-     public function getRules($method = '')
 
-     {
 
-         if ('' === $method) {
 
-             return $this->rules;
 
-         }
 
-         return isset($this->rules[strtolower($method)]) ? $this->rules[strtolower($method)] : [];
 
-     }
 
-     /**
 
-      * 清空分组下的路由规则
 
-      * @access public
 
-      * @return void
 
-      */
 
-     public function clear()
 
-     {
 
-         $this->rules = [
 
-             '*'       => [],
 
-             'get'     => [],
 
-             'post'    => [],
 
-             'put'     => [],
 
-             'patch'   => [],
 
-             'delete'  => [],
 
-             'head'    => [],
 
-             'options' => [],
 
-         ];
 
-     }
 
- }
 
 
  |