['except' => ['cate','detail','download'] ],
];
protected $model;
public function __construct(App $app)
{
parent::__construct($app);
$this->model = new \app\common\model\Article();
}
//文章分类
public function cate()
{
$cate = new Cate();
//动态参数
$ename = Request::param('ename');
$type = Request::param('type','all');
$page = Request::param('page',1);
// 分类信息
$cateInfo = $cate->getCateInfo($ename);
//分页url
$url = url('cate_page',['ename'=>$ename,'type'=>$type,'page'=>$page]);
//返回最后/前面的字符串
$path = substr($url,0,strrpos($url,"/"));
//分类列表
$artList = $this->model->getCateList($ename,$type,$page);
// 热议文章
$artHot = $this->model->getArtHot(10);
$assignArr = [
'ename'=>$ename,
'cateinfo'=> $cateInfo,
'type'=>$type,
'artList'=>$artList,
'artHot'=>$artHot,
'path'=>$path,
'jspage'=>'jie'
];
View::assign($assignArr);
$cateView = is_null($cateInfo) ? 'article/cate' : 'article/' . $cateInfo->detpl . '/cate';
return View::fetch($cateView);
}
//文章详情页
public function detail()
{
$id = input('id');
$page = input('page',1);
//输出内容
$artDetail = $this->model->getArtDetail($id);
if(is_null($artDetail)){
throw new \think\exception\HttpException(404, '无内容');
}
//被赞
$zanCount = Db::name('user_zan')->where('user_id', $artDetail['user_id'])->count('id');
//赞列表
$userZanList = [];
$userZan = UserZan::where(['article_id'=>$id,'type'=>1])->select();
if(count($userZan)) {
foreach($userZan as $v){
$userZanList[] = ['userImg'=>$v->user->user_img,'name'=>$v->user->name];
}
}
// 设置内容的tag内链
$artDetail->content = $this->setArtTagLink($artDetail->content);
// 标签
$tags = [];
$relationArticle = [];
$artTags = Db::name('taglist')->where('article_id',$id)->select();
if(count($artTags)) {
foreach($artTags as $v) {
$tag = Db::name('tag')->find($v['tag_id']);
if(!is_null($tag))
$tags[] = ['name'=>$tag['name'],'url'=> (string) url('tag_list',['ename'=>$tag['ename']])];
}
//相关帖子
$relationArticle = $this->model->getRelationTags($artTags[0]['tag_id'],$id,5);
}
$tpl = Db::name('cate')->where('id', $artDetail['cate_id'])->value('detpl');
$download = $artDetail['upzip'] ? download($artDetail['upzip'],'file') : '';
//浏览pv
Db::name('article')->where('id',$id)->inc('pv')->update();
$pv = Db::name('article')->field('pv')->where('id',$id)->value('pv');
$artDetail->pv = $pv;
//上一篇下一篇
$upDownArt = $this->model->getPrevNextArticle($id,$artDetail['cate_id']);
if(empty($upDownArt['previous'][0])) {
$previous = '前面已经没有了!';
} else {
$previous = '' . $upDownArt['previous'][0]['title'] . '';
}
if(empty($upDownArt['next'][0])) {
$next = '已经是最新的内容了!';
} else {
$next = '' . $upDownArt['next'][0]['title'] . '';
}
//评论
$comments = $this->getComments($id, $page);
//最新评论时间
$lrDate_time = Db::name('comment')->where('article_id', $id)->max('update_time',false) ?? time();
// 热议文章
$artHot = $this->model->getArtHot(10);
//push
$push_js = Db::name('push_jscode')->where(['delete_time'=>0,'type'=>1])->cache(true)->select();
View::assign([
'article' => $artDetail,
'pv' => $pv,
'artHot' => $artHot,
'tags' => $tags,
'relationArticle' => $relationArticle,
'previous' => $previous,
'next' => $next,
'page' => $page,
'comments' => $comments,
'push_js' => $push_js,
'cid' => $id,
'lrDate_time' => $lrDate_time,
'userZanList' => $userZanList,
'zanCount' => $zanCount,
'jspage' => 'jie',
'passJieMi' => session('art_pass_'.$id),
$download,
]);
return View::fetch('article/'.$tpl.'/detail');
}
//评论内容
public function getComments($id, $page)
{
$comment = new Comment;
return $comment->getComment($id, $page);
}
//文章评论
public function comment()
{
// 检验发帖是否开放
if(config('taoler.config.is_reply') == 0 ) return json(['code'=>-1,'msg'=>'抱歉,系统维护中,暂时禁止评论!']);
if (Request::isAjax()){
//获取评论
$data = Request::only(['content','article_id','pid','to_user_id']);
$data['user_id'] = $this->uid;
$sendId = $data['user_id'];
// halt($data);
$art = Db::name('article')->field('id,status,is_reply,delete_time')->find($data['article_id']);
if($art['delete_time'] != 0 || $art['status'] != 1 || $art['is_reply'] != 1){
return json(['code'=>-1, 'msg'=>'评论不可用状态']);
}
if(empty($data['content'])){
return json(['code'=>-1, 'msg'=>'评论不能为空!']);
}
$superAdmin = Db::name('user')->where('id',$sendId)->value('auth');
$data['status'] = $superAdmin ? 1 : Config::get('taoler.config.commnets_check');
$msg = $data['status'] ? '留言成功' : '留言成功,请等待审核';
//用户留言存入数据库
if (Comment::create($data)) {
//站内信
$article = Db::name('article')->field('id,title,user_id,cate_id')->where('id',$data['article_id'])->find();
// 获取分类ename,appname
$cateName = Db::name('cate')->field('ename,appname')->find($article['cate_id']);
//$link = (string) url('article_detail',['id'=>$data['article_id']]);
$link = $this->getRouteUrl($data['article_id'], $cateName['ename'], $cateName['appname']);
//评论中回复@user comment
$preg = "/@([^@\s]*)\s/";
preg_match($preg,$data['content'],$username);
if(isset($username[1])){
$receveId = Db::name('user')->whereOr('nickname', $username[1])->whereOr('name', $username[1])->value('id');
} else {
$receveId = $article['user_id'];
}
$data = ['title' => $article['title'], 'content' => '评论通知', 'link' => $link, 'user_id' => $sendId, 'type' => 2]; //type=2为评论留言
Message::sendMsg($sendId, $receveId, $data);
if(Config::get('taoler.config.email_notice')) hook('mailtohook',[$this->showUser(1)['email'],'评论审核通知','Hi亲爱的管理员:用户'.$this->showUser($this->uid)['name'].'刚刚对 ' . $article['title'] . ' 发表了评论,请尽快处理。']);
$res = ['code'=>0, 'msg'=>$msg];
} else {
$res = ['code'=>-1, 'msg'=>'留言失败'];
}
return json($res);
}
}
/**
* 添加帖子文章
* @return string|\think\Response|\think\response\Json|void
*/
public function add()
{
if (Request::isAjax()) {
// 检验发帖是否开放
if(config('taoler.config.is_post') == 0 ) return json(['code'=>-1,'msg'=>'抱歉,系统维护中,暂时禁止发帖!']);
// 数据
$data = Request::only(['cate_id', 'title', 'title_color','read_type','art_pass', 'content', 'upzip', 'keywords', 'description', 'captcha']);
$data['user_id'] = $this->uid;
$tagId = input('tagid');
// 验证码
if(Config::get('taoler.config.post_captcha') == 1) {
if(!captcha_check($data['captcha'])){
return json(['code'=>-1,'msg'=> '验证码失败']);
};
}
// 验证器
$validate = new \app\common\validate\Article;
$result = $validate->scene('Artadd')->check($data);
if (true !== $result) {
return Msgres::error($validate->getError());
}
// 获取内容图片音视频标识
$iva= $this->hasIva($data['content']);
$data = array_merge($data,$iva);
// 处理内容
$data['content'] = $this->downUrlPicsReaplace($data['content']);
// 把中文,转换为英文,并去空格->转为数组->去掉空数组->再转化为带,号的字符串
$data['keywords'] = implode(',',array_filter(explode(',',trim(str_replace(',',',',$data['keywords'])))));
$data['description'] = strip_tags($this->filterEmoji($data['description']));
// 获取分类ename,appname
$cateName = Db::name('cate')->field('ename,appname')->find($data['cate_id']);
$result = $this->model->add($data);
if ($result['code'] == 1) {
// 获取到的最新ID
$aid = $result['data']['id'];
//写入taglist表
$tagArr = [];
if(isset($tagId)) {
$tagIdArr = explode(',',$tagId);
foreach($tagIdArr as $tid) {
$tagArr[] = ['article_id'=>$aid,'tag_id'=>$tid,'create_time'=>time()];
}
}
Db::name('taglist')->insertAll($tagArr);
// 清除文章tag缓存
Cache::tag('tagArtDetail')->clear();
// 发提醒邮件
if(Config::get('taoler.config.email_notice')) hook('mailtohook',[$this->showUser(1)['email'],'发帖审核通知','Hi亲爱的管理员:用户'.$this->showUser($this->uid)['name'].'刚刚发表了 '.$data['title'].' 新的帖子,请尽快处理。']);
$link = $this->getRouteUrl((int)$aid, $cateName['ename']);
hook('SeoBaiduPush', ['link'=>$link]); // 推送给百度收录接口
$url = $result['data']['status'] ? $link : (string)url('index/');
return Msgres::success($result['msg'], $url);
}
return Msgres::error('add_error');
}
// 子模块自定义自适应add.html模板
$cate = Db::name('cate')->field('id,detpl')->where('ename', input('cate'))->find();
// 子模块下有add.html模板
if(!empty($cate)) {
$cid = $cate['id'];
} else {
$cate['detpl'] = '';
$cid = '';
}
// 模板路径
$appName = $this->app->http->getName();
$viewRoot = root_path() . config('view.view_dir_name') . DIRECTORY_SEPARATOR . $appName . DIRECTORY_SEPARATOR;
$view = 'article' . DIRECTORY_SEPARATOR . $cate['detpl'] . DIRECTORY_SEPARATOR . 'add.html';
$vfile = $viewRoot . $view;
//子模块下存在add模板则调用,否则调用article/add.html
$addTpl = is_file($vfile) ? $vfile : 'add';
View::assign(['jspage'=>'jie','cid'=>$cid]);
return View::fetch($addTpl);
}
/**
* 编辑文章
* @param $id
* @return string|\think\Response|\think\response\Json|void
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function edit($id)
{
$article = $this->model->find($id);
if(Request::isAjax()){
$data = Request::only(['id','cate_id','title','title_color','read_type','art_pass','content','upzip','keywords','description','captcha']);
$tagId = input('tagid');
// 验证码
if(Config::get('taoler.config.post_captcha') == 1)
{
if(!captcha_check($data['captcha'])){
return json(['code'=>-1,'msg'=> '验证码失败']);
};
}
//调用验证器
$validate = new \app\common\validate\Article();
$res = $validate->scene('Artadd')->check($data);
if(true !== $res){
return Msgres::error($validate->getError());
} else {
//获取内容图片音视频标识
$iva= $this->hasIva($data['content']);
$data = array_merge($data,$iva);
$data['content'] = $this->downUrlPicsReaplace($data['content']);
// 把,转换为,并去空格->转为数组->去掉空数组->再转化为带,号的字符串
$data['keywords'] = implode(',',array_filter(explode(',',trim(str_replace(',',',',$data['keywords'])))));
$data['description'] = strip_tags($this->filterEmoji($data['description']));
$result = $article->edit($data);
if($result == 1) {
//处理标签
$artTags = Db::name('taglist')->where('article_id',$id)->column('tag_id','id');
if(isset($tagId)) {
$tagIdArr = explode(',',$tagId);
foreach($artTags as $aid => $tid) {
if(!in_array($tid,$tagIdArr)){
//删除被取消的tag
Db::name('taglist')->delete($aid);
}
}
//查询保留的标签
$artTags = Db::name('taglist')->where('article_id',$id)->column('tag_id');
$tagArr = [];
foreach($tagIdArr as $tid) {
if(!in_array($tid, $artTags)){
//新标签
$tagArr[] = ['article_id'=>$data['id'],'tag_id'=>$tid,'create_time'=>time()];
}
}
//更新新标签
Db::name('taglist')->insertAll($tagArr);
}
//删除原有缓存显示编辑后内容
Cache::delete('article_'.$id);
Session::delete('art_pass_'.$id);
$link = $this->getRouteUrl((int) $id, $article->cate->ename);
hook('SeoBaiduPush', ['link'=>$link]); // 推送给百度收录接口
return Msgres::success('edit_success',$link);
}
return Msgres::error($result);
}
}
View::assign(['article'=>$article,'jspage'=>'jie']);
// 编辑多模板支持
$tpl = Db::name('cate')->where('id', $article['cate_id'])->value('detpl');
$appName = $this->app->http->getName();
$viewRoot = root_path() . config('view.view_dir_name') . DIRECTORY_SEPARATOR . $appName . DIRECTORY_SEPARATOR;
$view = 'article' . DIRECTORY_SEPARATOR . $tpl . DIRECTORY_SEPARATOR . 'edit.html';
$vfile = $viewRoot . $view;
$editTpl = is_file($vfile) ? $vfile : 'edit';
return View::fetch($editTpl);
}
/**
* 删除
*
* @return void
*/
public function delete()
{
$article = $this->model->find(input('id'));
$result = $article->together(['comments'])->delete();
if($result) {
return Msgres::success('delete_success');
}
return Msgres::error('delete_error');
}
/**
* 上传接口
*
* @return void
*/
public function uploads()
{
$type = Request::param('type');
return $this->uploadFiles($type);
}
/**
* 附件下载
*
* @param [type] $id
* @return void
*/
public function download($id)
{
$zipdir = Db::name('article')->where('id',$id)->value('upzip');
$zip = substr($zipdir,1);
Db::name('article')->cache(true)->where('id',$id)->inc('downloads')->update();
//删除缓存显示下载后数据
Cache::delete('article_'.$id);
return download($zip,'my');
}
// 文章置顶、加精、评论状态
public function jieset()
{
$data = Request::param();
$article = $this->model->field('id,is_top,is_hot,is_reply')->find($data['id']);
switch ($data['field']){
case 'top':
if($data['rank']==1){
$article->save(['is_top' => 1]);
$res = ['status'=>0,'msg'=>'置顶成功'];
} else {
$article->save(['is_top' => 0]);
$res = ['status'=>0,'msg'=>'置顶已取消'];
}
break;
case 'hot':
if($data['rank']==1){
$article->save(['is_hot' => 1]);
$res = ['status'=>0,'msg'=>'加精成功'];
} else {
$article->save(['is_hot' => 0]);
$res = ['status'=>0,'msg'=>'加精已取消'];
}
break;
case 'reply':
if($data['rank']==1){
$article->save(['is_reply' => 1]);
$res = ['status'=>0,'msg'=>'禁评成功'];
} else {
$article->save(['is_reply' => 0]);
$res = ['status'=>0,'msg'=>'禁评已取消'];
}
}
//删除本贴设置缓存显示编辑后内容
Cache::delete('article_'.$data['id']);
//清除文章tag缓存
Cache::tag('tagArtDetail')->clear();
return json($res);
}
// 改变标题颜色
public function titleColor()
{
$data = Request::param();
$result = $this->model->update($data);
if($result){
//清除文章缓存
Cache::tag(['tagArt','tagArtDetail'])->clear();
$res = ['code'=> 0, 'msg'=>'标题颜色设置成功'];
}else{
$res = ['code'=> -1, 'msg'=>'标题颜色设置失败'];
}
return json($res);
}
/**
* 内容中是否有图片视频音频插入
*
* @param [type] $content
* @return boolean
*/
public function hasIva($content)
{
//判断是否插入图片
$isHasImg = strpos($content,'img[');
$data['has_img'] = is_int($isHasImg) ? 1 : 0;
//判断是否插入视频
$isHasVideo = strpos($content,'video(');
$data['has_video'] = is_int($isHasVideo) ? 1 : 0;
//判断是否插入音频
$isHasAudio = strpos($content,'audio[');
$data['has_audio'] = is_int($isHasAudio) ? 1 : 0;
return $data;
}
//设置文章内容tag
protected function setArtTagLink($content)
{
// tag链接数组
$taglink = new PushJscode();
$tag = $taglink->getAllCodes(2);
if(count($tag)) {
foreach($tag as $key=>$value) {
// 匹配所有
//$content = str_replace("$key", 'a('.$value.')['.$key.']',$content);
// 限定匹配数量 '/'.$key.'/'
// 匹配不包含[和]的内容
// $pats = '/(?)/';
//$pats = '/'.$key.'(?!<\/a>)/';
//1.不匹配 $key已经存在链接的情况
//2.或不匹配 alt="$key等等等" $key后面有"这种情况
$pats = '/' . $value['name'] . '\s?(?!<\/a>|\s?\S*")/is';
preg_match($pats,$content,$arr);
// 开启和关闭编辑器使用不同的链接方式
$rpes = hook('taonystatus') ? '' . $value['name'] . '' : 'a(' . $value['jscode'] . ')[' . $value['name'] . ']';
$content = preg_replace($pats,$rpes,$content,2);
}
}
return $content;
}
//点赞文章
public function userZanArticle()
{
//
if(Request::isPost()) {
$data = Request::post();
$data['user_id'] = $this->uid;
$userZan = Db::name('user_zan')->where(['user_id'=>$this->uid,'article_id'=>$data['article_id']])->find();
if($userZan){
return json(['code'=> -1, 'msg'=>'您已赞过了哦']);
}
$res = Db::name('user_zan')->insert($data);
if($res) {
return json(['code'=> 0, 'msg'=>'点赞成功']);
}
}
}
/**
* 分类树
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getCateTree()
{
$cateList = Cate::field('id,pid,catename,sort')->where(['status' => 1])->select()->toArray();
$list = getTree($cateList);
// 排序
$cmf_arr = array_column($list, 'sort');
array_multisort($cmf_arr, SORT_ASC, $list);
$count = count($list);
$tree = [];
if($count){
$tree = ['code'=>0, 'msg'=>'ok','count'=>$count];
$tree['data'] = $list;
}
return json($tree);
}
public function jiemi()
{
$param = Request::param();
$article = $this->model->find($param['id']);
if($article['art_pass'] == $param['art_pass']) {
session('art_pass_'.$param['id'], $param['art_pass']);
return json(['code' => 0, 'msg' => '解密成功']);
}
return json(['code' => -1, 'msg' => '解密失败']);
}
}