ArticleController.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. <?php
  2. /**
  3. * Author: lf
  4. * Blog: https://blog.feehi.com
  5. * Email: job@feehi.com
  6. * Created at: 2016-04-02 22:48
  7. */
  8. namespace frontend\controllers;
  9. use Yii;
  10. use frontend\controllers\helpers\Helper;
  11. use common\services\CommentServiceInterface;
  12. use common\services\AdServiceInterface;
  13. use common\services\ArticleServiceInterface;
  14. use common\libs\Constants;
  15. use frontend\models\form\ArticlePasswordForm;
  16. use yii\filters\VerbFilter;
  17. use yii\helpers\ArrayHelper;
  18. use yii\web\Controller;
  19. use common\models\Article;
  20. use common\models\Category;
  21. use common\models\Comment;
  22. use yii\data\ActiveDataProvider;
  23. use common\models\meta\ArticleMetaLike;
  24. use yii\web\NotFoundHttpException;
  25. use yii\filters\HttpCache;
  26. use yii\helpers\Url;
  27. use yii\web\Response;
  28. use yii\web\XmlResponseFormatter;
  29. class ArticleController extends Controller
  30. {
  31. public function behaviors()
  32. {
  33. return [
  34. [
  35. 'class' =>VerbFilter::className(),
  36. 'actions' => [
  37. 'comment' => ['POST'],
  38. ]
  39. ],
  40. [
  41. 'class' => HttpCache::className(),
  42. 'only' => ['view'],
  43. 'lastModified' => function ($action, $params) {
  44. $id = Yii::$app->getRequest()->get('id');
  45. $model = Article::findOne(['id' => $id, 'type' => Article::ARTICLE, 'status' => Article::ARTICLE_PUBLISHED]);
  46. if( $model === null ) throw new NotFoundHttpException(Yii::t("frontend", "Article id {id} is not exists", ['id' => $id]));
  47. Article::updateAllCounters(['scan_count' => 1], ['id' => $id]);
  48. if($model->visibility == Constants::ARTICLE_VISIBILITY_PUBLIC) return $model->updated_at;
  49. },
  50. ],
  51. ];
  52. }
  53. /**
  54. * article list page
  55. *
  56. * @param string $cat category name
  57. * @return string
  58. * @throws NotFoundHttpException
  59. * @throws yii\base\InvalidConfigException
  60. */
  61. public function actionIndex($cat = '')
  62. {
  63. if ($cat == '') {
  64. $cat = Yii::$app->getRequest()->getPathInfo();
  65. }
  66. $where = ['type' => Article::ARTICLE, 'status' => Article::ARTICLE_PUBLISHED];
  67. if ($cat != '' && $cat != 'index') {
  68. if ($cat == Yii::t('app', 'UnClassified')) {
  69. $where['cid'] = 0;
  70. } else {
  71. if (! $category = Category::findOne(['alias' => $cat])) {
  72. throw new NotFoundHttpException(Yii::t('frontend', 'None category named {name}', ['name' => $cat]));
  73. }
  74. $descendants = $category->getDescendants($category['id']);
  75. if( empty($descendants) ) {
  76. $where['cid'] = $category['id'];
  77. }else{
  78. $cids = ArrayHelper::getColumn($descendants, 'id');
  79. $cids[] = $category['id'];
  80. $where['cid'] = $cids;
  81. }
  82. }
  83. }
  84. $query = Article::find()->with('category')->where($where);
  85. $dataProvider = new ActiveDataProvider([
  86. 'query' => $query,
  87. 'sort' => [
  88. 'defaultOrder' => [
  89. 'sort' => SORT_ASC,
  90. 'created_at' => SORT_DESC,
  91. 'id' => SORT_DESC,
  92. ]
  93. ]
  94. ]);
  95. $template = "index";
  96. isset($category) && $category->template != "" && $template = $category->template;
  97. $data = array_merge([
  98. 'dataProvider' => $dataProvider,
  99. 'type' => ( !empty($cat) ? Yii::t('frontend', 'Category {cat} articles', ['cat'=>$cat]) : Yii::t('frontend', 'Latest Articles') ),
  100. 'category' => isset($category) ? $category->name : "",
  101. ], Helper::getCommonInfos());
  102. return $this->render($template, $data);
  103. }
  104. /**
  105. * article detail page
  106. *
  107. * @param $id
  108. * @return string
  109. * @throws \yii\web\NotFoundHttpException
  110. * @throws \yii\base\InvalidConfigException
  111. */
  112. public function actionView($id)
  113. {
  114. /** @var ArticleServiceInterface $articleService */
  115. $articleService = Yii::$app->get(ArticleServiceInterface::ServiceName);
  116. $model = $articleService->getArticleById($id);
  117. /** @var Article $model */
  118. if( $model === null ) throw new NotFoundHttpException(Yii::t("frontend", "Article id {id} is not exists", ['id' => $id]));
  119. $prev = Article::find()
  120. ->where(['cid' => $model->cid, 'type' => Article::ARTICLE, 'status' => Article::ARTICLE_PUBLISHED])
  121. ->andWhere(['>', 'id', $id])
  122. ->orderBy("sort asc,id asc")
  123. ->limit(1)
  124. ->one();
  125. $next = Article::find()
  126. ->where(['cid' => $model->cid, 'type' => Article::ARTICLE, 'status' => Article::ARTICLE_PUBLISHED])
  127. ->andWhere(['<', 'id', $id])
  128. ->orderBy("sort asc,id desc")
  129. ->limit(1)
  130. ->one();//->createCommand()->getRawSql();
  131. $commentModel = new Comment();
  132. $commentList = $commentModel->getCommentByAid($id);
  133. $recommends = Article::find()
  134. ->where(['type' => Article::ARTICLE, 'status' => Article::ARTICLE_PUBLISHED])
  135. ->andWhere(['<>', 'thumb', ''])
  136. ->orderBy("scan_count")
  137. ->limit(8)
  138. ->with('category')
  139. ->all();
  140. switch ($model->visibility){
  141. case Constants::ARTICLE_VISIBILITY_COMMENT://评论可见
  142. if( Yii::$app->getUser()->getIsGuest() ){
  143. $result = Comment::find()->where(['aid'=>$model->id, 'ip'=>Yii::$app->getRequest()->getUserIP()])->one();
  144. }else{
  145. $result = Comment::find()->where(['aid'=>$model->id, 'uid'=>Yii::$app->getUser()->getId()])->one();
  146. }
  147. if( $result === null ) {
  148. $model->articleContent->content = "<p style='color: red'>" . Yii::t('frontend', "Only commented user can visit this article") . "</p>";
  149. }
  150. break;
  151. case Constants::ARTICLE_VISIBILITY_SECRET://加密文章
  152. $authorized = Yii::$app->getSession()->get("article_password_" . $model->id, null);
  153. if( $authorized === null ) $this->redirect(Url::toRoute(['password', 'id'=>$id]));
  154. break;
  155. case Constants::ARTICLE_VISIBILITY_LOGIN://登录可见
  156. if( Yii::$app->getUser()->getIsGuest() ) {
  157. $model->articleContent->content = "<p style='color: red'>" . Yii::t('frontend', "Only login user can visit this article") . "</p>";
  158. }
  159. break;
  160. }
  161. $template = "view";
  162. isset($model->category) && $model->category->article_template != "" && $template = $model->category->article_template;
  163. $model->template != "" && $template = $model->template;
  164. /** @var AdServiceInterface $adService */
  165. $adService = Yii::$app->get(AdServiceInterface::ServiceName);
  166. return $this->render($template, [
  167. 'model' => $model,
  168. 'prev' => $prev,
  169. 'next' => $next,
  170. 'recommends' => $recommends,
  171. 'commentModel' => $commentModel,
  172. 'commentList' => $commentList,
  173. 'rightAd1' => $adService->getAdByName("sidebar_right_1"),
  174. 'rightAd2' => $adService->getAdByName("sidebar_right_2"),
  175. ]);
  176. }
  177. /**
  178. * article likes, scan, comment count
  179. *
  180. * @param $id
  181. * @return array
  182. * @throws NotFoundHttpException
  183. * @throws \yii\base\InvalidConfigException
  184. */
  185. public function actionViewAjax($id)
  186. {
  187. Yii::$app->getResponse()->format = Response::FORMAT_JSON;
  188. /** @var ArticleServiceInterface $articleService */
  189. $articleService = Yii::$app->get(ArticleServiceInterface::ServiceName);
  190. $model = $articleService->getArticleById($id);
  191. if( $model === null ) throw new NotFoundHttpException("None exists article id");
  192. return [
  193. 'likeCount' => (int)$model->getArticleLikeCount(),
  194. 'scanCount' => $model->scan_count * 100,
  195. 'commentCount' => $model->comment_count,
  196. ];
  197. }
  198. /**
  199. * comment
  200. *
  201. */
  202. public function actionComment()
  203. {
  204. Yii::$app->getResponse()->format = Response::FORMAT_HTML;
  205. /** @var CommentServiceInterface $service */
  206. $service = Yii::$app->get(CommentServiceInterface::ServiceName);
  207. $commentModel = $service->newModel();
  208. if ($commentModel->load(Yii::$app->getRequest()->post()) && $commentModel->save()) {
  209. $avatar = 'https://secure.gravatar.com/avatar?s=50';
  210. if ($commentModel->email != '') {
  211. $avatar = "https://secure.gravatar.com/avatar/" . md5($commentModel->email) . "?s=50";
  212. }
  213. $tips = '';
  214. if (Yii::$app->feehi->website_comment_need_verify) {
  215. $tips = "<span class='c-approved'>" . Yii::t('frontend', 'Comment waiting for approved.') . "</span><br />";
  216. }
  217. $commentModel->afterFind();
  218. return "<li class='comment even thread-even depth-1' id='comment-{$commentModel->id}'>
  219. <div class='c-avatar'><img src='{$avatar}' class='avatar avatar-108' height='50' width='50'>
  220. <div class='c-main' id='div-comment-{$commentModel->id}'><p>{$commentModel->content}</p>
  221. {$tips}
  222. <div class='c-meta'><span class='c-author'><a href='{$commentModel->website_url}' rel='external nofollow' class='url'>{$commentModel->nickname}</a></span> (" . Yii::t('frontend', 'a minutes ago') . ")</div>
  223. </div>
  224. </div>
  225. </li>";
  226. } else {
  227. $temp = $commentModel->getErrors();
  228. $str = '';
  229. foreach ($temp as $v) {
  230. $str .= $v[0] . "<br>";
  231. }
  232. return "<font color='red'>" . $str . "</font>";
  233. }
  234. }
  235. /**
  236. * @param $id
  237. * @return string|\yii\web\Response
  238. * @throws \yii\base\InvalidConfigException
  239. * @throws NotFoundHttpException
  240. */
  241. public function actionPassword($id)
  242. {
  243. /** @var ArticleServiceInterface $articleService */
  244. $articleService = Yii::$app->get(ArticleServiceInterface::ServiceName);
  245. $article = $articleService->getArticleById($id);
  246. if( $article === null ) {
  247. throw new NotFoundHttpException(Yii::t("frontend", "Article id {id} is not exists", ['id' => $id]));
  248. }
  249. if( $article->visibility !== Constants::ARTICLE_VISIBILITY_SECRET ){
  250. return $this->redirect(Url::to(['article/view', 'id'=>$id]));
  251. }
  252. $model = new ArticlePasswordForm();
  253. if ($model->load(Yii::$app->getRequest()->post()) && $model->checkPassword($id)) {
  254. return $this->redirect(Url::toRoute(['view', 'id'=>$id]));
  255. } else {
  256. return $this->render("password", [
  257. 'model' => $model,
  258. 'article' => Article::findOne($id),
  259. ]);
  260. }
  261. }
  262. /**
  263. * like
  264. *
  265. * @return int|string
  266. */
  267. public function actionLike()
  268. {
  269. Yii::$app->getResponse()->format = Response::FORMAT_HTML;
  270. $aid = Yii::$app->getRequest()->post("aid");
  271. $model = new ArticleMetaLike();
  272. $model->setLike($aid);
  273. return $model->getLikeCount($aid);
  274. }
  275. /**
  276. * rss
  277. *
  278. * @return mixed
  279. * @throws \yii\base\InvalidConfigException
  280. */
  281. public function actionRss()
  282. {
  283. $xml['channel']['title'] = Yii::$app->feehi->website_title;
  284. $xml['channel']['description'] = Yii::$app->feehi->seo_description;
  285. $xml['channel']['lin'] = Yii::$app->getUrlManager()->getHostInfo();
  286. $xml['channel']['generator'] = Yii::$app->getUrlManager()->getHostInfo();
  287. $models = Article::find()->limit(10)->where(['status'=>Article::ARTICLE_PUBLISHED, 'type'=>Article::ARTICLE])->orderBy('id desc')->all();
  288. foreach ($models as $model){
  289. $xml['channel']['item'][] = [
  290. 'title' => $model->title,
  291. 'link' => Url::to(['article/view', 'id'=>$model->id]),
  292. 'pubData' => date('Y-m-d H:i:s', $model->created_at),
  293. 'source' => Yii::$app->feehi->website_title,
  294. 'author' => $model->author_name,
  295. 'description' => $model->summary,
  296. ];
  297. }
  298. Yii::configure(Yii::$app->getResponse(), [
  299. 'formatters' => [
  300. Response::FORMAT_XML => [
  301. 'class' => XmlResponseFormatter::className(),
  302. 'rootTag' => 'rss',
  303. 'version' => '1.0',
  304. 'encoding' => 'utf-8'
  305. ]
  306. ]
  307. ]);
  308. Yii::$app->getResponse()->format = Response::FORMAT_XML;
  309. return $xml;
  310. }
  311. }