RouteModel.php 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkCMF [ WE CAN DO IT MORE SIMPLE ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2013-present http://www.thinkcmf.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: 老猫 <thinkcmf@126.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\admin\model;
  12. use think\Model;
  13. class RouteModel extends Model
  14. {
  15. /**
  16. * 模型名称
  17. * @var string
  18. */
  19. protected $name = 'route';
  20. /**
  21. * 获取所有url美化规则
  22. * @param boolean $refresh 是否强制刷新
  23. * @return array|mixed|string|\think\Collection
  24. * @throws \think\db\exception\DataNotFoundException
  25. * @throws \think\db\exception\ModelNotFoundException
  26. * @throws \think\exception\DbException
  27. */
  28. public function getRoutes($refresh = false)
  29. {
  30. $routes = cache("routes");
  31. $appUrls = $this->getAppUrls();
  32. if ((!empty($routes) || is_array($routes)) && !$refresh) {
  33. return $routes;
  34. }
  35. $routes = $this->where("status", 1)->order("list_order asc")->select();
  36. $allRoutes = [];
  37. $cacheRoutes = [];
  38. foreach ($routes as $er) {
  39. $fullUrl = htmlspecialchars_decode($er['full_url']);
  40. // 解析URL
  41. $info = parse_url($fullUrl);
  42. $vars = [];
  43. // 解析参数
  44. if (isset($info['query'])) { // 解析地址里面参数 合并到vars
  45. parse_str($info['query'], $vars);
  46. ksort($vars);
  47. }
  48. if (isset($info['scheme'])) { //插件
  49. $plugin = cmf_parse_name($info['scheme']);
  50. $controller = cmf_parse_name($info['host']);
  51. $action = trim(strtolower($info['path']), '/');
  52. $pluginParams = [
  53. '_plugin' => $plugin,
  54. '_controller' => $controller,
  55. '_action' => $action,
  56. ];
  57. $path = '\\cmf\\controller\\PluginController@index?' . http_build_query($pluginParams);
  58. $fullUrl = $path . (empty($vars) ? '' : '&') . http_build_query($vars);
  59. } else { // 应用
  60. $path = explode("/", $info['path']);
  61. if (count($path) != 3) {//必须是完整 url
  62. continue;
  63. }
  64. $path = $info['path'];
  65. $fullUrl = $path . (empty($vars) ? "" : "?") . http_build_query($vars);
  66. }
  67. $url = htmlspecialchars_decode($er['url']);
  68. if (isset($cacheRoutes[$path])) {
  69. array_push($cacheRoutes[$path], ['vars' => $vars]);
  70. } else {
  71. $cacheRoutes[$path] = [];
  72. array_push($cacheRoutes[$path], ['vars' => $vars]);
  73. }
  74. //$cacheRoutes[$fullUrl] = true;
  75. // if (strpos($url, ':') === false) {
  76. // $cacheRoutes['static'][$fullUrl] = $url;
  77. // } else {
  78. // $cacheRoutes['dynamic'][$path][] = ["query" => $vars, "url" => $url];
  79. // }
  80. if (empty($appUrls[$path]['pattern'])) {
  81. $allRoutes[$url] = $fullUrl;
  82. } else {
  83. $allRoutes[$url] = [$fullUrl, [], $appUrls[$path]['pattern']];//[routeUrl,options,patterns]
  84. }
  85. }
  86. cache("routes", $cacheRoutes);
  87. if (strpos(cmf_version(), '5.') === 0) {
  88. if (strpos(cmf_version(), '5.0.') === false) {
  89. $routeDir = CMF_DATA . "route/"; // 5.1
  90. } else {
  91. $routeDir = CMF_DATA . "conf/"; // 5.0
  92. }
  93. $content = "<?php\treturn " . var_export($allRoutes, true) . ";";
  94. } else {
  95. $routeDir = CMF_DATA . "route/";
  96. $fileStrs = [
  97. '<?php',
  98. 'use think\facade\Route;',
  99. '',
  100. ];
  101. foreach ($allRoutes as $rule => $route) {
  102. if (is_array($route)) {
  103. $routeUrl = $route[0];
  104. if (!empty($route[2])) {
  105. $pattern = stripslashes(var_export($route[2], true));
  106. }
  107. } else {
  108. $routeUrl = $route;
  109. }
  110. $ruleName = $routeUrl;
  111. $query = [];
  112. if (strpos($routeUrl, '?') > 0) {
  113. $routeUrlArr = parse_url($routeUrl);
  114. $routeUrl = $routeUrlArr['path'];
  115. parse_str($routeUrlArr['query'], $query);
  116. }
  117. $routeCode = "Route::get('$rule', '$ruleName')";
  118. // $routeCode .= "->name('$ruleName')";
  119. if (!empty($query)) {
  120. $query = var_export($query, true);
  121. $query = str_replace(["\n", 'array ( '], ['', 'array('], $query);
  122. $routeCode .= "->append($query)";
  123. }
  124. if (!empty($pattern)) {
  125. $pattern = str_replace(["\n", 'array ( '], ['', 'array('], $pattern);
  126. $routeCode .= "\n->pattern($pattern)";
  127. }
  128. $routeCode .= ";\n";
  129. $fileStrs[] = $routeCode;
  130. }
  131. $content = join("\n", $fileStrs);
  132. }
  133. if (!file_exists($routeDir)) {
  134. mkdir($routeDir);
  135. }
  136. $routeFile = $routeDir . "route.php";
  137. file_put_contents($routeFile, $content . "\n\n");
  138. return $cacheRoutes;
  139. }
  140. /**
  141. * @return array
  142. */
  143. public function getAppUrls()
  144. {
  145. $apps = cmf_scan_dir(app_path() . '*', GLOB_ONLYDIR);
  146. array_push($apps, 'admin', 'user');
  147. $appUrls = [];
  148. foreach ($apps as $app) {
  149. $urlConfigFile = cmf_get_app_config_file($app, 'url');
  150. if (file_exists($urlConfigFile)) {
  151. $urls = include $urlConfigFile;
  152. foreach ($urls as $action => $url) {
  153. $action = $app . '/' . $action;
  154. $appUrls[$action] = $url;
  155. if (!empty($url['vars'])) {
  156. foreach ($url['vars'] as $urlVarName => $urlVar) {
  157. $appUrls[$action]['pattern'][$urlVarName] = $urlVar['pattern'];
  158. }
  159. }
  160. }
  161. }
  162. }
  163. return $appUrls;
  164. }
  165. public function getUrl($action, $vars)
  166. {
  167. $fullUrl = $this->buildFullUrl($action, $vars);
  168. $url = $this->where('full_url', $fullUrl)->value('url');
  169. return empty($url) ? '' : $url;
  170. }
  171. public function getFullUrlByUrl($url)
  172. {
  173. $full_url = $this->where('url', $url)->value('full_url');
  174. return empty($full_url) ? '' : $full_url;
  175. }
  176. public function buildFullUrl($action, $vars)
  177. {
  178. // 解析参数
  179. if (is_string($vars)) {
  180. // aaa=1&bbb=2 转换成数组
  181. parse_str($vars, $vars);
  182. }
  183. if (!empty($vars)) {
  184. ksort($vars);
  185. $fullUrl = $action . '?' . http_build_query($vars);
  186. } else {
  187. $fullUrl = $action;
  188. }
  189. return $fullUrl;
  190. }
  191. public function existsRoute($url, $fullUrl)
  192. {
  193. $findRouteCount = $this->where('url', $url)->whereNotLike('full_url', $fullUrl)->count();
  194. return $findRouteCount > 0 ? true : false;
  195. }
  196. public function setRoute($url, $action, $vars, $type = 2, $listOrder = 10000)
  197. {
  198. $fullUrl = $this->buildFullUrl($action, $vars);
  199. $findRoute = $this->where('full_url', $fullUrl)->find();
  200. if (preg_match("/[()'\";]/", $url)) {
  201. return false;
  202. }
  203. if ($findRoute) {
  204. if (empty($url)) {
  205. $this->where('id', $findRoute['id'])->delete();
  206. } else {
  207. $this->where('id', $findRoute['id'])->update([
  208. 'url' => $url,
  209. 'list_order' => $listOrder,
  210. 'type' => $type
  211. ]);
  212. }
  213. } else {
  214. if (!empty($url)) {
  215. $this->insert([
  216. 'full_url' => $fullUrl,
  217. 'url' => $url,
  218. 'list_order' => $listOrder,
  219. 'type' => $type
  220. ]);
  221. }
  222. }
  223. }
  224. /**
  225. * @param $action
  226. * @param $vars
  227. * @return bool
  228. * @throws \Exception
  229. */
  230. public function deleteRoute($action, $vars)
  231. {
  232. $fullUrl = $this->buildFullUrl($action, $vars);
  233. $this->where('full_url', $fullUrl)->delete();
  234. return true;
  235. }
  236. }