request->isCli()) { echo $msg . PHP_EOL; } else { Log::log($msg); } } /** * 记录错误信息日志 * @param $e \Exception */ public static function errorlog($e) { Log::error("异常信息:" . $e->getMessage()); Log::error('请求数据:' . var_export(Request::instance()->param(), true)); Log::error($e->getTraceAsString()); } /** * 输出错误页面 * @param $basePath * @return string */ public static function errorHtml($basePath) { $basePath = str_replace(Templet::getRootDir(), '', $basePath); return "
" . $basePath . ",此栏目下没有文章,请添加文章后再尝试生成"; } /** * 替换预览内容 * @return array */ public static function getArticlePerViewReplace() { return [ '_UPLOADS_' => '/uploads/q1464674022', '_ROOT_' => '/?path=', ]; } /** * 替换生成内容 * @return array */ public static function getArticleReplace() { return [ '_UPLOADS_' => '', '_ROOT_' => '', ]; } /** * 导出上传目录 */ public function copyUploads() { //创建目录 $destPath = Templet::getRootDir() . 'uploads'; DirHelper::makeDir($destPath); $this->info("导出上传目录" . $destPath); $path = Templet::UPLOAD_PATH . 'admin'; if (file_exists($path)) { DirHelper::copyDir($path, $destPath . DS . 'admin', false);//不覆盖同名文件 } $path = Templet::UPLOAD_PATH . 'ueditor'; if (file_exists($path)) { DirHelper::copyDir($path, $destPath . DS . 'ueditor', false);//不覆盖同名文件 } //导出模板文件 // $path = APP_PATH . 'admin' . DS . 'view' . DS . 'q1464674022'; // if (file_exists($path)) { // copyDir($path, $destPath . DS . 'template'); // } } /** * 执行文件生成 * @param $filePath * @param $content */ public function createFile($filePath, $content) { if (!ifContain($filePath, Templet::getRootDir())) { return;//不允许执行外部路径 } if ($this->request->has('delete')) { if (file_exists($filePath)) { unlink($filePath);//删除 } } elseif ($this->request->has('cover')) { FileHelper::save($filePath, $content);//覆盖 } else { //默认不覆盖,文件不存在或内容修改才覆盖 if (!file_exists($filePath)) { FileHelper::save($filePath, $content); } else { $change = str_replace(file_get_contents($filePath), '', $content); if (!empty($change)) { FileHelper::save($filePath, $content); } } } } /** * 分页url处理 * @param $catalog * @param $tid * @return mixed */ public static function getPaginatePath($catalog, $tid) { $rule = str_replace("{page}", "[PAGE]", $catalog->articlelist_rule); return replaceUrlDS(ArticleCate::getRulePath($catalog->path, $rule, $catalog->id, $tid)); } /** * 栏目预览 * @param $catalog Catalog * @param $cate ArticleCate * @param int $page * @return mixed|string */ public function perviewCatalog($catalog, $cate = null, $page = 1) { $tid = $cate ? $cate->id : 0; if ($catalog) { try { $replace = self::getArticlePerViewReplace(); //先预览静态文件 // $filepath = Templet::getRootDir() . $catalog->getUri(); // if (file_exists($filepath) && ifContain($filepath, '.html')) { // return $this->fetch($filepath, [], $replace); // } //全局对象 $cataLogModel = new Catalog(); $articleModel = new Article(); $articleCateModel = new ArticleCate(); $this->assign([ 'cataLogModel' => $cataLogModel, 'articleCateModel' => $articleCateModel, 'articleModel' => $articleModel, ]); if ($catalog->type == Catalog::TYPE_CATALOG) { return $this->fetch($catalog->getCatalogTemplet()->getRealPath(), ['catalog' => $catalog], $replace); } elseif ($catalog->type == Catalog::TYPE_ARTICLE_LIST) { if ($catalog->article_cate_count > 0) { $where = [ 'article_cate_id' => $tid, 'status' => $articleModel::STATUS_OPEN, ]; } else { $where = [ 'catalog_id' => $catalog->id, 'status' => $articleModel::STATUS_OPEN, ]; } $total = $articleModel->where($where)->where($catalog->articlelist_where)->count(); $listRows = $catalog->articlelist_rows??10;//分页 $orderby = $catalog->articlelist_sort??'create_time desc';//排序 $prefix = isset($replace['_ROOT_']) ? $replace['_ROOT_'] : '_ROOT_'; $articleList = $articleModel->where($where)->where($catalog->articlelist_where)->page($page, $listRows)->order($orderby)->select(); $paginate = new Bootstrap($articleList, $listRows, $page, $total, false, ["path" => $prefix . self::getPaginatePath($catalog, $tid)]); return $this->fetch($catalog->getCatalogTemplet()->getRealPath(), ['catalog' => $catalog, 'articleCate' => $cate, 'paginate' => $paginate], $replace); } return ""; } catch (\Exception $e) { $this->error('预览失败:' . $e->getMessage()); } } abort(404, "预览失败:catelog is null"); } /** * 分类预览 * @param $articleCate ArticleCate * @param int $page * @return mixed|string */ public function perviewArticleCate($articleCate, $page = 1) { if ($articleCate) { try { //先预览静态文件 // $filepath = Templet::getRootDir() . $articleCate->getUri(); // if (file_exists($filepath)) { // return $this->fetch($filepath, [], $replace); // } $catalog = $articleCate->getFirstCatalog(); return $this->perviewCatalog($catalog, $articleCate, $page); } catch (\Exception $e) { $this->error('预览失败:' . $e->getMessage()); } } abort(404, "预览失败:articleCate is null"); } /** * 文章预览 * @param $article Article * @return mixed */ public function perviewArticle($article) { if ($article) { try { $replace = self::getArticlePerViewReplace(); //先预览静态文件 // $filepath = Templet::getRootDir() . $article->getUri(); // if (file_exists($filepath) && ifContain($filepath, '.html')) { // return $this->fetch($filepath, [], $replace); // } //全局对象 $cataLogModel = new Catalog(); $articleModel = new Article(); $articleCateModel = new ArticleCate(); $this->assign([ 'cataLogModel' => $cataLogModel, 'articleCateModel' => $articleCateModel, 'articleModel' => $articleModel, ]); $catalog = $article->catalog_id ? $article->catalog : $article->getFirstCatalog(); $cate = $article->catalog_id ? null : $article->cate; /** @var Catalog $catalog */ return $this->fetch($catalog->getArticleTemplet()->getRealPath(), ['catalog' => $catalog, 'article' => $article, 'articleCate' => $cate], $replace); } catch (\Exception $e) { $this->error('预览失败:' . $e->getMessage()); } } abort(404, "预览失败:article is null"); } /** * 预览网站静态文件 * @return string */ public function perviewHtmlSite() { if ($this->request->has('path')) { $filepath = Templet::getRootDir() . $this->request->get('path'); if (!ifContain($filepath, '.html')) { $filepath .= DS . 'index.html'; } } else { $filepath = Templet::getRootDir() . 'index.html'; } if (file_exists($filepath)) { $replace = self::getArticlePerViewReplace(); $html = $this->fetch($filepath, [], $replace); //todo auto replace assets path exit($html); } else { if ($this->request->has('path')) abort(404); } } /** * 预览网站模板 */ public function perviewSite() { $path = $this->request->get('path', '/index.html'); if (!ifContain($path, '.html')) { $path .= '/index.html'; } $path = str_replace('//', '/', appendStartDS($path, '/')); $catalogModel = new Catalog(); $catalog = $catalogModel->where('path', $path)->find(); if ($catalog) { exit($this->perviewCatalog($catalog)); } $path = deleteStartDS($path, '/'); $catalogs = $catalogModel->field('article_rule,articlelist_rule')->distinct(true)->where('article_rule', '<>', '')->select(); foreach ($catalogs as $catalog) { $matches = $this->matchePath($catalog->article_rule, $path); if ($matches) { if (isset($matches['{aid}'])) { $article = Article::get($matches['{aid}']); exit($this->perviewArticle($article)); } } $matches = $this->matchePath($catalog->articlelist_rule, $path); if ($matches) { if (isset($matches['{tid}'])) { $articlecate = (new ArticleCate())->where('id', $matches['{tid}'])->find(); } elseif (isset($matches['{tpath}'])) { $articlecate = (new ArticleCate())->where('en_name', $matches['{tpath}'])->find(); } else { continue; } $page = $matches['{page}'] ?? 1; exit($this->perviewArticleCate($articlecate, $page)); } } } /** * 解析path * @param $rule * @param $path * @return mixed */ private function matchePath($rule, $path) { $rule_arr = explode('/', $rule); $path_arr = explode('/', $path); if (ifContain($path, 'index.html')) { array_pop($rule_arr); array_pop($path_arr); $rule = implode('/', $rule_arr); $path = implode('/', $path_arr); } $pattern2p = str_replace(['/', '{cpath}', '{tpath}', '{Y}', '{M}', '{D}', '{aid}', '{page}', '{cid}', '{tid}'], ['\/', '(.*?)', '(.*?)', '(\d{4})', '(\d{2})', '(\d{2})', '(\d*?)', '(\d*?)', '(\d*?)', '(\d*?)'], $rule); $pattern2r = str_replace(['/', '{cpath}', '{tpath}', '{Y}', '{M}', '{D}', '{aid}', '{page}', '{cid}', '{tid}'], ['\/', '({cpath})', '({tpath})', '({Y})', '({M})', '({D})', '({aid})', '({page})', '({cid})', '({tid})'], $rule); if (preg_match('/^' . $pattern2p . '$/', $path, $matches2p)) { if (preg_match('/^' . $pattern2r . '$/', $rule, $matches2r)) { $res = []; foreach ($matches2r as $i => $item) { if ($i > 0) $res[$item] = $matches2p[$i]; } return $res; } } } }