cms-manage/app/model/Route.php

473 lines
14 KiB
PHP

<?php
declare (strict_types=1);
namespace app\model;
use app\exception\ModelEmptyException;
use app\exception\ModelException;
/**
* @mixin \think\Model
*/
class Route extends Model
{
public function category(): \think\model\relation\BelongsTo
{
return $this->belongsTo(Category::class);
}
/**
* @param array $where
* @param int $limit
* @return array
* @throws ModelException
*/
public function getRouteList(array $where = [], int $limit = 10): array
{
try {
$res = $this->where($where)->paginate($limit);
} catch (\Exception $e) {
throw new ModelException($e->getMessage());
}
return dataReturn($this->sucCode, $this->getMsg, $res);
}
/**
* @param array $where
* @param string[] $order
* @return array
* @throws ModelException
*/
public function getAllRoute(array $where, array $order=['id','asc']): array
{
try {
$res = $this->where($where)->order($order[0],$order[1])->select();
} catch (\Exception $e) {
throw new ModelException($e->getMessage());
}
return dataReturn($this->sucCode, $this->getMsg, $res);
}
/**
* @param array $where
* @return array
* @throws ModelEmptyException
* @throws ModelException
*/
public function getRoute(array $where = [],$with=[]): array
{
try {
$res = $this->with($with)->where($where)->find();
if (empty($res)) {
throw new ModelEmptyException();
}
} catch (ModelEmptyException $me) {
throw new ModelEmptyException();
} catch (\Exception $e) {
throw new ModelException($e->getMessage());
}
return dataReturn($this->sucCode, $this->getMsg, $res);
}
/**
* @param array $where
* @return array
* @throws ModelException
*/
public function exitRoute(array $where = []): array
{
try {
$res = $this->where($where)->find();
} catch (\Exception $e) {
throw new ModelException($e->getMessage());
}
return dataReturn($this->sucCode, $this->getMsg, $res);
}
/**
* @param $param
* @return array
* @throws ModelException
*/
public function addRoute($param): array
{
try {
$res = self::create($param);
} catch (\Exception $e) {
throw new ModelException($e->getMessage());
}
return dataReturn($this->sucCode, $this->addMsg, $res);
}
/**
* @param array $where
* @param array $param
* @return array
* @throws ModelException
*/
public function updateRoute(array $where = [], array $param = []): array
{
try {
$res = self::where($where)->update($param);
} catch (\Exception $e) {
throw new ModelException($e->getMessage());
}
return dataReturn($this->sucCode, $this->updateMsg, $res);
}
/**
* @param $where
* @return array
* @throws ModelException
*/
public function softDelRoute($where): array
{
try {
$res = $this->where($where)->update($this->delData);
} catch (\Exception $e) {
throw new ModelException($e->getMessage());
}
return dataReturn($this->sucCode, $this->delMsg, $res);
}
/**
* @param $where
* @return array
* @throws ModelException
*/
public function delRoute($where): array
{
try {
$res = $this->where($where)->delete();
} catch (\Exception $e) {
throw new ModelException($e->getMessage());
}
return dataReturn($this->sucCode, $this->delMsg, $res);
}
/**
* @throws ModelException
* @throws ModelEmptyException
*/
public function getRoutes($siteId, $sellerId, $lang): array
{
$routes = $this->alias('r')
->field('r.*,c.path')
->leftJoin('category c','r.category_id = c.id')
->where('r.seller_id',$sellerId)
->where('r.website_id',$siteId)
->where('r.lang',$lang)
->where('r.status',1)
->where('c.type','in',[1,4])
->select()->toArray();
// dd($routes);
$Website = new Website();
$websiteDomain = $Website->getWebsite(['id'=>$siteId,'seller_id'=>$sellerId])['data']['domain'];
// 如果有子站点,更新子站点
$subSiteList = $Website->where([
['seller_id', '=', $sellerId],
['parent_id', '=', $siteId],
])->select()->toArray();
foreach ($subSiteList as $value) {
$this->getRoutes($value['id'], $sellerId, $lang);
}
$allRoutes = [];
$cacheRoutes = [];
foreach ($routes as $er) {
$fullUrl = htmlspecialchars_decode($er['full_url']);
// 解析URL
$info = parse_url($fullUrl);
$vars = [];
// 解析参数
if (isset($info['query'])) { // 解析地址里面参数 合并到vars
parse_str($info['query'], $vars);
ksort($vars);
}
$path = explode("/", $info['path']);
if (count($path) != 2) {//必须是完整 url
continue;
}
$path = $info['path'];
$fullUrl = $path . (empty($vars) ? "" : "?") . http_build_query($vars);
$url = htmlspecialchars_decode($er['url']);
if (!isset($cacheRoutes[$path])) {
$cacheRoutes[$path] = [];
}
array_push($cacheRoutes[$path], ['vars' => $vars]);
if (empty($er['pattern'])) {
$allRoutes[$url] = $fullUrl;
} else {
$allRoutes[$url] = [$fullUrl, [], json_decode($er['pattern'],true)];//[routeUrl,options,patterns]
}
}
$fileStr = [
'<?php',
'use think\facade\Route;',
'',
"Route::domain('$websiteDomain',function(){",
];
$customerStr = [];
if($lang != config('lang.default_lang')){
array_push($customerStr,"Route::group('$lang',function(){");
}else{
array_push($customerStr,'Route::group(function(){');
}
foreach ($allRoutes as $rule => $route) {
$pattern = '';
if (is_array($route)) {
$routeUrl = $route[0];
if (!empty($route[2])) {
$pattern = stripslashes(var_export($route[2], true));
}
} else {
$routeUrl = $route;
}
$ruleName = $routeUrl;
$query = [];
if (strpos($routeUrl, '?') > 0) {
$routeUrlArr = parse_url($routeUrl);
$routeUrl = $routeUrlArr['path'];
parse_str($routeUrlArr['query'], $query);
}
$this->setRouteFile($rule, $routeUrl, $ruleName, $query, $pattern, $customerStr);
if ($rule == '/') {
$rule = '/index';
$this->setRouteFile($rule, $routeUrl, $ruleName, $query, $pattern, $customerStr);
} elseif ($rule == '/index') {
$rule = '/';
$this->setRouteFile($rule, $routeUrl, $ruleName, $query, $pattern, $customerStr);
}
}
// dd($customerStr);
// 获取前台公共路由
$indexRoute = app()->getRootPath() . 'route' . DIRECTORY_SEPARATOR . 'index.php';
$index_route = file($indexRoute);
foreach ($index_route as $key => $val){
if(trim($val) == "<?php" || trim($val) == "use think\\facade\\Route;" || $val ==PHP_EOL){
unset($index_route[$key]);
}
}
$customerStr = array_merge($customerStr,$index_route);
$customerStr[] = "})->prefix('frontend.');";
$fileStr = array_merge($fileStr,$customerStr);
if( $lang == config('lang.default_lang')){
$adminRoute = app()->getRootPath() . 'route' . DIRECTORY_SEPARATOR . 'admin.php';
$admin_route = file($adminRoute);
foreach ($admin_route as $key => $val){
if(trim($val) == "<?php" || trim($val) == "use think\\facade\\Route;"){
unset($admin_route[$key]);
}
}
$fileStr = array_merge($fileStr,$admin_route);
}
array_push($fileStr,"});");
$content = join("\n", $fileStr);
$path = $this->createRoutePath($siteId,$lang);
// 前台页面路由
$th = fopen($path['frontend'],'w');
file_put_contents($path['frontend'], $content . "\n\n");
fclose($th);
return $cacheRoutes;
}
protected function setRouteFile($rule, $routeUrl, $ruleName, $query, $pattern, &$customerStr)
{
$routeCode = "Route::get('$rule', '$routeUrl')";
$routeCode .= "->name('$ruleName')";
if (!empty($query)) {
$query = var_export($query, true);
$query = str_replace(["\n", 'array ( '], ['', 'array('], $query);
$routeCode .= "->append($query)";
}
if (!empty($pattern)) {
$pattern = str_replace(["\n", 'array ( '], ['', 'array('], $pattern);
$routeCode .= "\n->pattern($pattern)";
}
$routeCode .= ";\n";
$customerStr [] = $routeCode;
}
public function createRoutePath($siteId,$lang): array
{
$routeDir = app()->getRootPath() . "route";
if (!file_exists($routeDir)) {
mkdir($routeDir);
}
$apiRouteFile = $routeDir.DIRECTORY_SEPARATOR .$siteId .'_' .$lang . "_api.php";
$frontendRouteFile = $routeDir .DIRECTORY_SEPARATOR .$siteId.'_' .$lang . "_frontend.php";
return [
'frontend' => $frontendRouteFile,
'api' => $apiRouteFile,
];
}
public function getUrl($action, $vars)
{
$fullUrl = $this->buildFullUrl($action, $vars);
$url = $this->where('full_url', $fullUrl)->value('url');
return empty($url) ? '' : $url;
}
public function getFullUrlByUrl($url)
{
$full_url = $this->where('url', $url)->value('full_url');
return empty($full_url) ? '' : $full_url;
}
public function getFullUrl($where): array
{
$full_url = $this->where($where)->column('full_url');
return empty($full_url)? [] : $full_url;
}
public function buildFullUrl($action, $vars): string
{
// 解析参数
if (is_string($vars)) {
// aaa=1&bbb=2 转换成数组
parse_str($vars, $vars);
}
if (!empty($vars)) {
ksort($vars);
$fullUrl = $action . '?' . http_build_query($vars);
} else {
$fullUrl = $action;
}
return $fullUrl;
}
public function existsRoute($url, $fullUrl): bool
{
$findRouteCount = $this->where('url', $url)->whereNotLike('full_url', $fullUrl)->count();
return $findRouteCount > 0;
}
/**
* @throws ModelException
*/
public function setRoute($url, $action, $vars,$lang, $type, $sort, $seller_id, $category_id,$siteId,$category_title = '',$pattern=''): array
{
if (preg_match("/[()'\";]/", $url)) {
return dataReturn(-1, lang('url格式错误'));
}
$Website = new Website();
// 如果有子站点,更新子站点
$subSiteList = $Website->where([
['seller_id', '=', $seller_id],
['parent_id', '=', $siteId],
])->select()->toArray();
foreach ($subSiteList as $value) {
// 查询子站点的栏目,对应起来
$categoryModel = new Category();
$subCateArr = $categoryModel->where([
['website_id', '=', $value['id']],
['parent_map', '=', $category_id],
])->field('id, title, parent_map')->find();
$subCategoryId = $category_id;
$subCategoryTitle = $category_title;
$subVar = $vars;
if (!empty($subCateArr['id'])) {
$subCategoryId = $subCateArr['id'];
$subCategoryTitle = $subCateArr['title'];
if (isset($subVar['cid'])) {
$subVar['cid'] = $subCategoryId;
$subCategoryTitle .= lang('详情页');
} else {
$subVar['id'] = $subCategoryId;
}
}
$this->setRoute($url, $action, $subVar,$lang, $type, $sort, $seller_id, $subCategoryId,$value['id'],$subCategoryTitle,$pattern);
}
$fullUrl = $this->buildFullUrl($action, $vars);
$findRoute = $this->exitRoute(['seller_id'=>$seller_id,'website_id'=>$siteId,'lang'=>$lang,'full_url'=>$fullUrl,'url'=>$url])['data'];
if (!empty($findRoute)) {
if (empty($url)) {
$data = $this->delRoute(['id' => $findRoute['id'], 'seller_id' => $seller_id]);
} else {
$updateData = [
'url' => $url,
'sort' => $sort,
'type' => $type,
'category_id' => $category_id,
'pattern' => $pattern
];
$data = $this->updateRoute(['id' => $findRoute['id'], 'seller_id' => $seller_id], $updateData);
}
} else {
if (!empty($url)) {
$addData = [
'seller_id' => $seller_id,
'full_url' => $fullUrl,
'website_id' => $siteId,
'url' => $url,
'sort' => $sort,
'type' => $type,
'lang' => $lang,
'category_title' => $category_title,
'category_id' => $category_id,
'pattern' => $pattern
];
$data = $this->addRoute($addData);
} else {
$data = [$this->sucCode, $this->getMsg];
}
}
return $data;
}
/**
* @param $action
* @param $vars
* @return bool
* @throws \Exception
*/
public function deleteRoute($action, $vars): bool
{
$fullUrl = $this->buildFullUrl($action, $vars);
$this->where('full_url', $fullUrl)->delete();
return true;
}
}