src/controllers/MessagesController.php
<?php
namespace bizley\podium\controllers;
use bizley\podium\filters\AccessControl;
use bizley\podium\models\Message;
use bizley\podium\models\MessageReceiver;
use bizley\podium\models\MessageSearch;
use bizley\podium\models\User;
use bizley\podium\Podium;
use Yii;
use yii\helpers\Json;
use yii\web\Response;
/**
* Podium Messages controller
* All actions concerning members messages.
*
* @author Paweł Bizley Brzozowski <pawel@positive.codes>
* @since 0.1
*/
class MessagesController extends BaseController
{
/**
* @inheritdoc
*/
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'denyCallback' => function ($rule, $action) {
return $this->redirect(['account/login']);
},
'rules' => [
['class' => 'bizley\podium\filters\InstallRule'],
[
'allow' => true,
'roles' => ['@'],
],
],
],
];
}
/**
* Returns separated messages actions.
* @return array
* @since 0.6
*/
public function actions()
{
return [
'delete-received' => [
'class' => 'bizley\podium\actions\MessageAction',
'redirectRoute' => ['messages/inbox'],
'type' => 'receiver',
],
'delete-sent' => [
'class' => 'bizley\podium\actions\MessageAction',
'redirectRoute' => ['messages/sent'],
'type' => 'sender',
],
];
}
/**
* Listing the messages inbox.
* @return string
*/
public function actionInbox()
{
$searchModel = new MessageReceiver();
return $this->render('inbox', [
'dataProvider' => $searchModel->search(Yii::$app->request->get()),
'searchModel' => $searchModel
]);
}
/**
* Adding a new message.
* @param int $user message receiver's ID
* @return string|Response
*/
public function actionNew($user = null)
{
$podiumUser = User::findMe();
if (Message::tooMany($podiumUser->id)) {
$this->warning(Yii::t('podium/flash', 'You have reached maximum {max_messages, plural, =1{ message} other{ messages}} per {max_minutes, plural, =1{ minute} other{ minutes}} limit. Wait few minutes before sending a new message.', [
'max_messages' => Message::SPAM_MESSAGES,
'max_minutes' => Message::SPAM_WAIT
]));
return $this->redirect(['messages/inbox']);
}
$model = new Message();
$to = null;
if (!empty($user) && (int)$user > 0 && (int)$user != $podiumUser->id) {
$member = User::find()->where(['id' => (int)$user, 'status' => User::STATUS_ACTIVE])->limit(1)->one();
if ($member) {
$model->receiversId = [$member->id];
$to = $member;
}
}
if ($model->load(Yii::$app->request->post())) {
if ($model->validate()) {
$validated = [];
$errors = false;
if (!empty($model->friendsId)) {
$model->receiversId = array_merge(
is_array($model->receiversId) ? $model->receiversId : [],
is_array($model->friendsId) ? $model->friendsId : []
);
}
if (empty($model->receiversId)) {
$model->addError('receiversId', Yii::t('podium/view', 'You have to select at least one message receiver.'));
$errors = true;
} else {
foreach ($model->receiversId as $r) {
if ($r == $podiumUser->id) {
$model->addError('receiversId', Yii::t('podium/view', 'You can not send message to yourself.'));
$errors = true;
} elseif ($podiumUser->isIgnoredBy($r)) {
$model->addError('receiversId', Yii::t('podium/view', 'One of the selected members ignores you and has been removed from message receivers.'));
$errors = true;
} else {
$member = User::find()->where(['id' => (int)$r, 'status' => User::STATUS_ACTIVE])->limit(1)->one();
if ($member) {
$validated[] = $member->id;
if (count($validated) > Message::MAX_RECEIVERS) {
$model->addError('receiversId', Yii::t('podium/view', 'You can send message up to a maximum of 10 receivers at once.'));
$errors = true;
break;
}
}
}
}
$model->receiversId = $validated;
}
if (!$errors) {
if ($model->send()) {
$this->success(Yii::t('podium/flash', 'Message has been sent.'));
return $this->redirect(['messages/inbox']);
}
$this->error(Yii::t('podium/flash', 'Sorry! There was some error while sending your message.'));
}
}
}
return $this->render('new', ['model' => $model, 'to' => $to, 'friends' => User::friendsList()]);
}
/**
* Replying to the message of given ID.
* @param int $id
* @return string|Response
*/
public function actionReply($id = null)
{
$podiumUser = User::findMe();
if (Message::tooMany($podiumUser->id)) {
$this->warning(Yii::t('podium/flash', 'You have reached maximum {max_messages, plural, =1{ message} other{ messages}} per {max_minutes, plural, =1{ minute} other{ minutes}} limit. Wait few minutes before sending a new message.', [
'max_messages' => Message::SPAM_MESSAGES,
'max_minutes' => Message::SPAM_WAIT
]));
return $this->redirect(['messages/inbox']);
}
$reply = Message::find()->where([Message::tableName() . '.id' => $id])->joinWith([
'messageReceivers' => function ($q) use ($podiumUser) {
$q->where(['receiver_id' => $podiumUser->id]);
}])->limit(1)->one();
if (empty($reply)) {
$this->error(Yii::t('podium/flash', 'Sorry! We can not find the message with the given ID.'));
return $this->redirect(['messages/inbox']);
}
$model = new Message();
$model->topic = Message::re() . ' ' . $reply->topic;
if ($model->load(Yii::$app->request->post())) {
if ($model->validate()) {
if (!$podiumUser->isIgnoredBy($model->receiversId[0])) {
$model->replyto = $reply->id;
if ($model->send()) {
$this->success(Yii::t('podium/flash', 'Message has been sent.'));
return $this->redirect(['messages/inbox']);
}
$this->error(Yii::t('podium/flash', 'Sorry! There was some error while sending your message.'));
} else {
$this->error(Yii::t('podium/flash', 'Sorry! This member ignores you so you can not send the message.'));
}
}
}
$model->receiversId = [$reply->sender_id];
return $this->render('reply', ['model' => $model, 'reply' => $reply]);
}
/**
* Listing the sent messages.
* @return string
*/
public function actionSent()
{
$searchModel = new MessageSearch();
return $this->render('sent', [
'dataProvider' => $searchModel->search(Yii::$app->request->get()),
'searchModel' => $searchModel
]);
}
/**
* Viewing the sent message of given ID.
* @param int $id
* @return string|Response
*/
public function actionViewSent($id = null)
{
$model = Message::find()->where([
'and',
['id' => $id, 'sender_id' => User::loggedId()],
['!=', 'sender_status', Message::STATUS_DELETED]
])->limit(1)->one();
if (empty($model)) {
$this->error(Yii::t('podium/flash', 'Sorry! We can not find the message with the given ID.'));
return $this->redirect(['messages/inbox']);
}
$model->markRead();
return $this->render('view', [
'model' => $model,
'type' => 'sent',
'id' => $model->id
]);
}
/**
* Viewing the received message of given ID.
* @param int $id
* @return string|Response
*/
public function actionViewReceived($id = null)
{
$model = MessageReceiver::find()->where([
'and',
['id' => $id, 'receiver_id' => User::loggedId()],
['!=', 'receiver_status', MessageReceiver::STATUS_DELETED]
])->limit(1)->one();
if (empty($model)) {
$this->error(Yii::t('podium/flash', 'Sorry! We can not find the message with the given ID.'));
return $this->redirect(['messages/inbox']);
}
$model->markRead();
return $this->render('view', [
'model' => $model->message,
'type' => 'received',
'id' => $model->id
]);
}
/**
* Loads older messages in thread.
* @return string
*/
public function actionLoad()
{
if (!Yii::$app->request->isAjax) {
return $this->redirect(['forum/index']);
}
$result = ['messages' => '', 'more' => 0];
if (!Podium::getInstance()->user->isGuest) {
$loggedId = User::loggedId();
$id = Yii::$app->request->post('message');
$message = Message::find()->where(['id' => $id])->limit(1)->one();
if ($message && ($message->sender_id == $loggedId || $message->isMessageReceiver($loggedId))) {
$stack = 0;
$reply = clone $message;
while ($reply->reply && $stack < 5) {
$result['more'] = 0;
if ($reply->reply->sender_id == $loggedId && $reply->reply->sender_status == Message::STATUS_DELETED) {
$reply = $reply->reply;
continue;
}
$result['messages'] .= $this->renderPartial('load', ['reply' => $reply]);
$reply = $reply->reply;
if ($reply) {
$result['more'] = $reply->id;
}
$stack++;
}
}
}
return Json::encode($result);
}
}