src/controllers/ForumPostController.php
<?php
namespace bizley\podium\controllers;
use bizley\podium\filters\AccessControl;
use bizley\podium\helpers\Helper;
use bizley\podium\models\Category;
use bizley\podium\models\Forum;
use bizley\podium\models\Message;
use bizley\podium\models\Post;
use bizley\podium\models\Thread;
use bizley\podium\models\User;
use bizley\podium\rbac\Rbac;
use bizley\podium\services\ThreadVerifier;
use Yii;
use yii\helpers\Html;
use yii\helpers\Json;
use yii\web\Response;
/**
* Podium Forum controller
* All actions concerning posts.
* Not accessible directly.
*
* @author Paweł Bizley Brzozowski <pawel@positive.codes>
* @since 0.5
*/
class ForumPostController extends ForumThreadController
{
/**
* @inheritdoc
*/
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [['allow' => false]],
],
];
}
/**
* Deleting the post of given category ID, forum ID, thread ID and ID.
* @param int $cid category ID
* @param int $fid forum ID
* @param int $tid thread ID
* @param int $pid post ID
* @return string|Response
*/
public function actionDeletepost($cid = null, $fid = null, $tid = null, $pid = null)
{
$post = Post::verify($cid, $fid, $tid, $pid);
if (empty($post)) {
$this->error(Yii::t('podium/flash', 'Sorry! We can not find the post you are looking for.'));
return $this->redirect(['forum/index']);
}
if ($post->thread->locked == 1 && !User::can(Rbac::PERM_UPDATE_THREAD, ['item' => $post->thread])) {
$this->info(Yii::t('podium/flash', 'This thread is locked.'));
return $this->redirect([
'forum/thread',
'cid' => $post->forum->category->id,
'fid' => $post->forum->id,
'id' => $post->thread->id,
'slug' => $post->thread->slug
]);
}
if (!User::can(Rbac::PERM_DELETE_OWN_POST, ['post' => $post]) && !User::can(Rbac::PERM_DELETE_POST, ['item' => $post])) {
$this->error(Yii::t('podium/flash', 'Sorry! You do not have the required permission to perform this action.'));
return $this->redirect(['forum/index']);
}
$postData = Yii::$app->request->post('post');
if ($postData) {
if ($postData != $post->id) {
$this->error(Yii::t('podium/flash', 'Sorry! There was an error while deleting the post.'));
} else {
if ($post->podiumDelete()) {
$this->success(Yii::t('podium/flash', 'Post has been deleted.'));
if (Thread::find()->where(['id' => $post->thread->id])->exists()) {
return $this->redirect([
'forum/forum',
'cid' => $post->forum->category->id,
'id' => $post->forum->id,
'slug' => $post->forum->slug
]);
}
return $this->redirect([
'forum/thread',
'cid' => $post->forum->category->id,
'fid' => $post->forum->id,
'id' => $post->thread->id,
'slug' => $post->thread->slug
]);
}
$this->error(Yii::t('podium/flash', 'Sorry! There was an error while deleting the post.'));
}
}
return $this->render('deletepost', ['model' => $post]);
}
/**
* Deleting the posts of given category ID, forum ID, thread ID and slug.
* @param int $cid category ID
* @param int $fid forum ID
* @param int $id thread ID
* @param string $slug thread slug
* @return string|Response
*/
public function actionDeleteposts($cid = null, $fid = null, $id = null, $slug = null)
{
$thread = (new ThreadVerifier([
'categoryId' => $cid,
'forumId' => $fid,
'threadId' => $id,
'threadSlug' => $slug
]))->verify();
if (empty($thread)) {
$this->error(Yii::t('podium/flash', 'Sorry! We can not find the thread you are looking for.'));
return $this->redirect(['forum/index']);
}
if (!User::can(Rbac::PERM_DELETE_POST, ['item' => $thread])) {
$this->error(Yii::t('podium/flash', 'Sorry! You do not have the required permission to perform this action.'));
return $this->redirect(['forum/index']);
}
$posts = Yii::$app->request->post('post');
if ($posts) {
if (!is_array($posts)) {
$this->error(Yii::t('podium/flash', 'You have to select at least one post.'));
} else {
if ($thread->podiumDeletePosts($posts)) {
$this->success(Yii::t('podium/flash', 'Posts have been deleted.'));
if (Thread::find()->where(['id' => $thread->id])->exists()) {
return $this->redirect([
'forum/thread',
'cid' => $thread->forum->category->id,
'fid' => $thread->forum->id,
'id' => $thread->id,
'slug' => $thread->slug
]);
}
return $this->redirect([
'forum',
'cid' => $thread->forum->category->id,
'id' => $thread->forum->id,
'slug' => $thread->forum->slug
]);
}
$this->error(Yii::t('podium/flash', 'Sorry! There was an error while deleting the posts.'));
}
}
return $this->render('deleteposts', [
'model' => $thread,
'dataProvider' => (new Post())->search($thread->forum->id, $thread->id)
]);
}
/**
* Editing the post of given category ID, forum ID, thread ID and own ID.
* If this is the first post in thread user can change the thread name.
* @param int $cid category ID
* @param int $fid forum ID
* @param int $tid thread ID
* @param int $pid post ID
* @return string|Response
*/
public function actionEdit($cid = null, $fid = null, $tid = null, $pid = null)
{
$post = Post::verify($cid, $fid, $tid, $pid);
if (empty($post)) {
$this->error(Yii::t('podium/flash', 'Sorry! We can not find the post you are looking for.'));
return $this->redirect(['forum/index']);
}
if ($post->thread->locked == 1 && !User::can(Rbac::PERM_UPDATE_THREAD, ['item' => $post->thread])) {
$this->info(Yii::t('podium/flash', 'This thread is locked.'));
return $this->redirect([
'forum/thread',
'cid' => $post->forum->category->id,
'fid' => $post->forum->id,
'id' => $post->thread->id,
'slug' => $post->thread->slug
]);
}
if (!User::can(Rbac::PERM_UPDATE_OWN_POST, ['post' => $post]) && !User::can(Rbac::PERM_UPDATE_POST, ['item' => $post])) {
$this->error(Yii::t('podium/flash', 'Sorry! You do not have the required permission to perform this action.'));
return $this->redirect(['forum/index']);
}
$isFirstPost = false;
$firstPost = Post::find()->where([
'thread_id' => $post->thread->id,
'forum_id' => $post->forum->id
])->orderBy(['id' => SORT_ASC])->limit(1)->one();
if ($firstPost->id == $post->id) {
$post->scenario = 'firstPost';
$post->topic = $post->thread->name;
$isFirstPost = true;
}
$postData = Yii::$app->request->post();
$preview = false;
if ($post->load($postData)) {
if ($post->validate()) {
if (isset($postData['preview-button'])) {
$preview = true;
} else {
if ($post->podiumEdit($isFirstPost)) {
$this->success(Yii::t('podium/flash', 'Post has been updated.'));
return $this->redirect(['show', 'id' => $post->id]);
}
$this->error(Yii::t('podium/flash', 'Sorry! There was an error while updating the post. Contact administrator about this problem.'));
}
}
}
return $this->render('edit', [
'preview' => $preview,
'model' => $post,
'isFirstPost' => $isFirstPost
]);
}
/**
* Moving the posts of given category ID, forum ID, thread ID and slug.
* @param int $cid category ID
* @param int $fid forum ID
* @param int $id thread ID
* @param string $slug thread slug
* @return string|Response
*/
public function actionMoveposts($cid = null, $fid = null, $id = null, $slug = null)
{
$thread = (new ThreadVerifier([
'categoryId' => $cid,
'forumId' => $fid,
'threadId' => $id,
'threadSlug' => $slug
]))->verify();
if (empty($thread)) {
$this->error(Yii::t('podium/flash', 'Sorry! We can not find the thread you are looking for.'));
return $this->redirect(['forum/index']);
}
if (!User::can(Rbac::PERM_MOVE_POST, ['item' => $thread])) {
$this->error(Yii::t('podium/flash', 'Sorry! You do not have the required permission to perform this action.'));
return $this->redirect(['forum/index']);
}
if (Yii::$app->request->post()) {
$posts = Yii::$app->request->post('post');
$newthread = Yii::$app->request->post('newthread');
$newname = Yii::$app->request->post('newname');
$newforum = Yii::$app->request->post('newforum');
if (empty($posts) || !is_array($posts)) {
$this->error(Yii::t('podium/flash', 'You have to select at least one post.'));
} else {
if (!is_numeric($newthread) || $newthread < 0) {
$this->error(Yii::t('podium/flash', 'You have to select a thread for this posts to be moved to.'));
} else {
if ($newthread == 0 && (empty($newname) || empty($newforum) || !is_numeric($newforum) || $newforum < 1)) {
$this->error(Yii::t('podium/flash', 'If you want to move posts to a new thread you have to enter its name and select parent forum.'));
} else {
if ($newthread == $thread->id) {
$this->error(Yii::t('podium/flash', 'Are you trying to move posts from this thread to this very same thread?'));
} else {
if ($thread->podiumMovePostsTo($newthread, $posts, $newname, $newforum)) {
$this->success(Yii::t('podium/flash', 'Posts have been moved.'));
if (Thread::find()->where(['id' => $thread->id])->exists()) {
return $this->redirect([
'forum/thread',
'cid' => $thread->forum->category->id,
'fid' => $thread->forum->id,
'id' => $thread->id,
'slug' => $thread->slug
]);
}
return $this->redirect([
'forum/forum',
'cid' => $thread->forum->category->id,
'id' => $thread->forum->id,
'slug' => $thread->forum->slug
]);
}
$this->error(Yii::t('podium/flash', 'Sorry! There was an error while moving the posts.'));
}
}
}
}
}
$categories = Category::find()->orderBy(['name' => SORT_ASC]);
$forums = Forum::find()->orderBy(['name' => SORT_ASC]);
$threads = Thread::find()->orderBy(['name' => SORT_ASC]);
$list = [0 => Yii::t('podium/view', 'Create new thread')];
$listforum = [];
$options = [];
foreach ($categories->each() as $cat) {
$catlist = [];
foreach ($forums->each() as $for) {
$forlist = [];
if ($for->category_id == $cat->id) {
$catlist[$for->id] = (User::can(Rbac::PERM_UPDATE_THREAD, ['item' => $for]) ? '* ' : '')
. Html::encode($cat->name)
. ' » '
. Html::encode($for->name);
foreach ($threads->each() as $thr) {
if ($thr->category_id == $cat->id && $thr->forum_id == $for->id) {
$forlist[$thr->id] = (User::can(Rbac::PERM_UPDATE_THREAD, ['item' => $thr]) ? '* ' : '')
. Html::encode($cat->name)
. ' » '
. Html::encode($for->name)
. ' » '
. Html::encode($thr->name);
if ($thr->id == $thread->id) {
$options[$thr->id] = ['disabled' => true];
}
}
}
$list[Html::encode($cat->name) . ' > ' . Html::encode($for->name)] = $forlist;
}
}
$listforum[Html::encode($cat->name)] = $catlist;
}
return $this->render('moveposts', [
'model' => $thread,
'list' => $list,
'options' => $options,
'listforum' => $listforum,
'dataProvider' => (new Post())->search($thread->forum->id, $thread->id)
]);
}
/**
* Creating the post of given category ID, forum ID and thread ID.
* This can be reply to selected post of given ID.
* @param int $cid category ID
* @param int $fid forum ID
* @param int $tid thread ID
* @param int $pid ID of post to reply to
* @return string|Response
*/
public function actionPost($cid = null, $fid = null, $tid = null, $pid = null)
{
$thread = Thread::find()->where([
'id' => $tid,
'category_id' => $cid,
'forum_id' => $fid
])->limit(1)->one();
if (empty($thread)) {
$this->error(Yii::t('podium/flash', 'Sorry! We can not find the thread you are looking for.'));
return $this->redirect(['forum/index']);
}
if ($thread->locked == 1 && !User::can(Rbac::PERM_UPDATE_THREAD, ['item' => $thread])) {
$this->info(Yii::t('podium/flash', 'This thread is locked.'));
return $this->redirect([
'forum/thread',
'cid' => $thread->forum->category->id,
'fid' => $thread->forum->id,
'id' => $thread->id,
'slug' => $thread->slug
]);
}
if (!User::can(Rbac::PERM_CREATE_POST)) {
$this->error(Yii::t('podium/flash', 'Sorry! You do not have the required permission to perform this action.'));
return $this->redirect(['forum/index']);
}
$model = new Post();
$model->subscribe = 1;
$postData = Yii::$app->request->post();
$replyFor = null;
if (is_numeric($pid) && $pid > 0) {
$replyFor = Post::find()->where(['id' => $pid])->limit(1)->one();
if ($replyFor) {
$model->content = Helper::prepareQuote($replyFor, Yii::$app->request->post('quote'));
}
}
$preview = false;
$previous = Post::find()->where(['thread_id' => $thread->id])->orderBy(['id' => SORT_DESC])->limit(1)->one();
if ($model->load($postData)) {
$model->thread_id = $thread->id;
$model->forum_id = $thread->forum->id;
$model->author_id = User::loggedId();
if ($model->validate()) {
if (isset($postData['preview-button'])) {
$preview = true;
} else {
if ($model->podiumNew($previous)) {
$this->success(Yii::t('podium/flash', 'New reply has been added.'));
if (!empty($previous) && $previous->author_id == User::loggedId() && $this->module->podiumConfig->get('merge_posts')) {
return $this->redirect(['forum/show', 'id' => $previous->id]);
}
return $this->redirect(['forum/show', 'id' => $model->id]);
}
$this->error(Yii::t('podium/flash', 'Sorry! There was an error while adding the reply. Contact administrator about this problem.'));
}
}
}
return $this->render('post', [
'replyFor' => $replyFor,
'preview' => $preview,
'model' => $model,
'thread' => $thread,
'previous' => $previous,
]);
}
/**
* Reporting the post of given category ID, forum ID, thread ID, own ID and slug.
* @param int $cid category ID
* @param int $fid forum ID
* @param int $tid thread ID
* @param int $pid post ID
* @return string|Response
*/
public function actionReport($cid = null, $fid = null, $tid = null, $pid = null)
{
$post = Post::verify($cid, $fid, $tid, $pid);
if (empty($post)) {
$this->error(Yii::t('podium/flash', 'Sorry! We can not find the post you are looking for.'));
return $this->redirect(['forum/index']);
}
if (User::can(Rbac::PERM_UPDATE_POST, ['item' => $post])) {
$this->info(Yii::t('podium/flash', "You don't have to report this post since you are allowed to modify it."));
return $this->redirect([
'forum/edit',
'cid' => $post->forum->category->id,
'fid' => $post->forum->id,
'tid' => $post->thread->id,
'pid' => $post->id
]);
}
if ($post->author_id == User::loggedId()) {
$this->info(Yii::t('podium/flash', 'You can not report your own post. Please contact the administrator or moderators if you have got any concerns regarding your post.'));
return $this->redirect([
'forum/thread',
'cid' => $post->forum->category->id,
'fid' => $post->forum->id,
'id' => $post->thread->id,
'slug' => $post->thread->slug
]);
}
$model = new Message();
$model->scenario = 'report';
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
if ($model->podiumReport($post)) {
$this->success(Yii::t('podium/flash', 'Thank you for your report. The moderation team will take a look at this post.'));
return $this->redirect([
'forum/thread',
'cid' => $post->forum->category->id,
'fid' => $post->forum->id,
'id' => $post->thread->id,
'slug' => $post->thread->slug
]);
}
$this->error(Yii::t('podium/flash', 'Sorry! There was an error while notifying the moderation team. Contact administrator about this problem.'));
}
return $this->render('report', ['model' => $model, 'post' => $post]);
}
/**
* Voting on the post.
* @return string|Response
*/
public function actionThumb()
{
if (!Yii::$app->request->isAjax) {
return $this->redirect(['forum/index']);
}
$data = [
'error' => 1,
'msg' => Html::tag('span',
Html::tag('span', '', ['class' => 'glyphicon glyphicon-warning-sign'])
. ' ' . Yii::t('podium/view', 'Error while voting on this post!'),
['class' => 'text-danger']
),
];
if ($this->module->user->isGuest) {
$data['msg'] = Html::tag('span',
Html::tag('span', '', ['class' => 'glyphicon glyphicon-warning-sign'])
. ' ' . Yii::t('podium/view', 'Please sign in to vote on this post'),
['class' => 'text-info']
);
return Json::encode($data);
}
$postId = Yii::$app->request->post('post');
$thumb = Yii::$app->request->post('thumb');
if (is_numeric($postId) && $postId > 0 && in_array($thumb, ['up', 'down'])) {
$post = Post::find()->where(['id' => $postId])->limit(1)->one();
if ($post) {
if ($post->thread->locked) {
$data['msg'] = Html::tag('span',
Html::tag('span', '', ['class' => 'glyphicon glyphicon-warning-sign'])
. ' ' . Yii::t('podium/view', 'This thread is locked.'),
['class' => 'text-info']
);
return Json::encode($data);
}
if ($post->author_id == User::loggedId()) {
$data['msg'] = Html::tag('span',
Html::tag('span', '', ['class' => 'glyphicon glyphicon-warning-sign'])
. ' ' . Yii::t('podium/view', 'You can not vote on your own post!'),
['class' => 'text-info']
);
return Json::encode($data);
}
$count = 0;
$votes = $this->module->podiumCache->get('user.votes.' . User::loggedId());
if ($votes !== false) {
if ($votes['expire'] < time()) {
$votes = false;
} elseif ($votes['count'] >= 10) {
$data['msg'] = Html::tag('span',
Html::tag('span', '', ['class' => 'glyphicon glyphicon-warning-sign'])
. ' ' . Yii::t('podium/view', '{max} votes per hour limit reached!', ['max' => 10]),
['class' => 'text-danger']
);
return Json::encode($data);
} else {
$count = $votes['count'];
}
}
if ($post->podiumThumb($thumb == 'up', $count)) {
$data = [
'error' => 0,
'likes' => '+' . $post->likes,
'dislikes' => '-' . $post->dislikes,
'summ' => $post->likes - $post->dislikes,
'msg' => Html::tag('span',
Html::tag('span', '', ['class' => 'glyphicon glyphicon-ok-circle'])
. ' ' . Yii::t('podium/view', 'Your vote has been saved!'),
['class' => 'text-success']
),
];
}
}
}
return Json::encode($data);
}
/**
* Marking all unread posts as seen.
* @return Response
*/
public function actionMarkSeen()
{
if (Thread::podiumMarkAllSeen()) {
$this->success(Yii::t('podium/flash', 'All unread threads have been marked as seen.'));
return $this->redirect(['forum/index']);
}
$this->error(Yii::t('podium/flash', 'Sorry! There was an error while marking threads as seen. Contact administrator about this problem.'));
return $this->redirect(['forum/unread-posts']);
}
}