
remove dependence on jQuery add image delete Admin ui fix for mobile image updates to new style update comments
455 lines
15 KiB
PHP
455 lines
15 KiB
PHP
<?php
|
|
/**
|
|
* app/models/message.php
|
|
*
|
|
* Houses all of the functions for the core messaging system.
|
|
*
|
|
* @version 5.0.1
|
|
* @author Joey Kimsey <Joey@thetempusproject.com>
|
|
* @link https://TheTempusProject.com
|
|
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
|
*/
|
|
namespace TheTempusProject\Models;
|
|
|
|
use TheTempusProject\Classes\DatabaseModel;
|
|
use TheTempusProject\Houdini\Classes\Components;
|
|
use TheTempusProject\Houdini\Classes\Views;
|
|
use TheTempusProject\Canary\Bin\Canary as Debug;
|
|
use TheTempusProject\Bedrock\Functions\Check;
|
|
use TheTempusProject\Bedrock\Functions\Sanitize;
|
|
use TheTempusProject\TheTempusProject as App;
|
|
use TheTempusProject\Canary\Classes\CustomException;
|
|
|
|
class Message extends DatabaseModel {
|
|
public $tableName = 'messages';
|
|
public $databaseMatrix = [
|
|
[ 'userTo', 'int', '11' ],
|
|
[ 'userFrom', 'int', '11' ],
|
|
[ 'parent', 'int', '11' ],
|
|
[ 'sent', 'int', '10' ],
|
|
[ 'lastReply', 'int', '10' ],
|
|
[ 'senderDeleted', 'int', '1' ],
|
|
[ 'recieverDeleted', 'int', '1' ],
|
|
[ 'isRead', 'int', '1' ],
|
|
[ 'message', 'text', '' ],
|
|
[ 'subject', 'text', '' ],
|
|
];
|
|
private $messages;
|
|
private $usernames;
|
|
|
|
/**
|
|
* The model constructor.
|
|
*/
|
|
public function __construct() {
|
|
parent::__construct();
|
|
self::$message = $this;
|
|
}
|
|
|
|
/**
|
|
* Retrieves the most recent relative message in a thread
|
|
*
|
|
* @param int $parent - the id of the parent message
|
|
* @param string $user - the id of the relative user
|
|
* @return object
|
|
*/
|
|
public function getLatestMessage( $parent, $user, $type = null ) {
|
|
if ( !Check::id( $parent ) ) {
|
|
Debug::info( 'Invalid message ID' );
|
|
return false;
|
|
}
|
|
if ( !Check::id( $user ) ) {
|
|
Debug::info( 'Invalid user ID' );
|
|
return false;
|
|
}
|
|
$messageData = self::$db->get( $this->tableName, [ 'ID', '=', $parent ] );
|
|
if ( $messageData->count() == 0 ) {
|
|
Debug::info( 'Message not found.' );
|
|
return false;
|
|
}
|
|
$message = $messageData->first();
|
|
$params = [ 'parent', '=', $parent ];
|
|
if ( $type !== null ) {
|
|
$params = array_merge( $params, [ 'AND', $type, '=', $user ] );
|
|
}
|
|
$messageData = self::$db->get( $this->tableName, $params, 'ID', 'DESC', [ 0, 1 ] );
|
|
if ( $messageData->count() != 0 ) {
|
|
if ( $messageData->first()->recieverDeleted == 0 ) {
|
|
$message = $messageData->first();
|
|
} else {
|
|
$message->recieverDeleted = 1;
|
|
}
|
|
}
|
|
return $message;
|
|
}
|
|
|
|
/**
|
|
* This calls a view of the requested message.
|
|
*
|
|
* @param int $ID - The message ID you are looking for.
|
|
* @return null
|
|
*/
|
|
public function getThread( $id, $markRead = false ) {
|
|
if ( !Check::id( $id ) ) {
|
|
Debug::info( 'Invalid ID' );
|
|
return false;
|
|
}
|
|
$messageData = self::$db->get( $this->tableName, [ 'ID', '=', $id ] );
|
|
if ( $messageData->count() == 0 ) {
|
|
Debug::info( 'Message not found.' );
|
|
return false;
|
|
}
|
|
$message = $messageData->first();
|
|
if ( $message->userTo == App::$activeUser->ID ) {
|
|
$permissionCheck = 1;
|
|
if ( $message->recieverDeleted == 1 ) {
|
|
Debug::info( 'User has already deleted this message.' );
|
|
return false;
|
|
}
|
|
}
|
|
if ( $message->userFrom == App::$activeUser->ID ) {
|
|
$permissionCheck = 1;
|
|
if ( $message->senderDeleted == 1 ) {
|
|
Debug::info( 'User has already deleted this message.' );
|
|
return false;
|
|
}
|
|
}
|
|
if ( empty( $permissionCheck ) ) {
|
|
Debug::info( 'You do not have permission to view this message.' );
|
|
return false;
|
|
}
|
|
if ( $message->parent != 0 ) {
|
|
$find = $message->parent;
|
|
} else {
|
|
$find = $message->ID;
|
|
}
|
|
$messageData = self::$db->get( $this->tableName, [ 'ID', '=', $find, 'OR', 'Parent', '=', $find ], 'ID', 'ASC' )->results();
|
|
Components::set( 'PID', $find );
|
|
|
|
if ( $markRead == true ) {
|
|
foreach ( $messageData as $instance ) {
|
|
$this->markRead( $instance->ID );
|
|
}
|
|
}
|
|
return $this->filter( $messageData );
|
|
}
|
|
|
|
public function getInbox( $limit = null ) {
|
|
if ( empty( $limit ) ) {
|
|
$limit = 10;
|
|
}
|
|
$limit = [ 0, $limit ];
|
|
$messageData = self::$db->get(
|
|
$this->tableName,
|
|
[
|
|
'parent', '=', 0,
|
|
'AND',
|
|
'userFrom', '=', App::$activeUser->ID,
|
|
'OR',
|
|
'parent', '=', 0,
|
|
'AND',
|
|
'userTo', '=', App::$activeUser->ID,
|
|
],
|
|
'ID',
|
|
'DESC',
|
|
$limit
|
|
);
|
|
if ( $messageData->count() == 0 ) {
|
|
Debug::info( 'getInbox: No messages found' );
|
|
return false;
|
|
}
|
|
$filters = [
|
|
'importantUser' => App::$activeUser->ID,
|
|
'deleted' => false,
|
|
'type' => 'userTo',
|
|
];
|
|
return $this->filter( $messageData->results(), $filters );
|
|
}
|
|
|
|
/**
|
|
* This function calls the view for the message outbox.
|
|
*
|
|
* @return null
|
|
*/
|
|
public function getOutbox( $limit = null ) {
|
|
if ( empty( $limit ) ) {
|
|
$limit = 10;
|
|
}
|
|
$limit = [ 0, $limit ];
|
|
$messageData = self::$db->get(
|
|
$this->tableName,
|
|
[
|
|
'parent', '=', 0,
|
|
'AND',
|
|
'userFrom', '=', App::$activeUser->ID,
|
|
],
|
|
'ID',
|
|
'DESC',
|
|
$limit
|
|
);
|
|
if ( $messageData->count() == 0 ) {
|
|
Debug::info( 'getOutbox: No messages found' );
|
|
return false;
|
|
}
|
|
$filters = [
|
|
'importantUser' => App::$activeUser->ID,
|
|
'deleted' => false,
|
|
'type' => 'userFrom',
|
|
];
|
|
return $this->filter( $messageData->results(), $filters );
|
|
}
|
|
|
|
/**
|
|
* This function is to prep our messages for display. An array of raw messages
|
|
* sent through this function will automatically have all the user ID's filter
|
|
* into actual usernames.
|
|
*
|
|
* @param $messageArray - This is an array of messages that need to be processed.
|
|
* @return array - It will return the same message array after being processed.
|
|
* @todo add filtering for BB-code.
|
|
*/
|
|
public function filter( $messageArray, $filters = [] ) {
|
|
$out = [];
|
|
foreach ( $messageArray as $message ) {
|
|
if ( !is_object( $message ) ) {
|
|
$message = $messageArray;
|
|
$end = true;
|
|
}
|
|
if ( isset( $filters['type'] ) && isset( $filters['importantUser'] ) ) {
|
|
$type = $filters['type'];
|
|
} else {
|
|
$type = null;
|
|
}
|
|
if ( isset( $filters['importantUser'] ) ) {
|
|
$user = $filters['importantUser'];
|
|
} else {
|
|
$user = App::$activeUser->ID;
|
|
}
|
|
if ( $message->parent == 0 ) {
|
|
$last = $this->getLatestMessage( $message->ID, $user, $type );
|
|
} else {
|
|
$last = $message;
|
|
}
|
|
if ( $type != null && $message->$type != $user && $last->$type != $user ) {
|
|
continue;
|
|
}
|
|
if ( isset( $filters['deleted'] ) && $filters['deleted'] == false ) {
|
|
if ( $type == 'userFrom' ) {
|
|
if ( $last->senderDeleted == 1 ) {
|
|
continue;
|
|
}
|
|
}
|
|
if ( $type == 'userTo' ) {
|
|
if ( $last->recieverDeleted == 1 ) {
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
$messageOut = (array) $message;
|
|
$short = explode( ' ', Sanitize::contentShort( $message->message ) );
|
|
$summary = implode( ' ', array_splice( $short, 0, 25 ) );
|
|
if ( count( $short, 1 ) >= 25 ) {
|
|
$messageOut['summary'] = $summary . '...';
|
|
} else {
|
|
$messageOut['summary'] = $summary;
|
|
}
|
|
if ( $last->isRead == 0 ) {
|
|
$messageOut['unreadBadge'] = Views::simpleView( 'messages.unreadBadge' );
|
|
} else {
|
|
$messageOut['unreadBadge'] = '';
|
|
}
|
|
$messageOut['fromAvatar'] = self::$user->getAvatar( $message->userFrom );
|
|
$messageOut['userTo'] = self::$user->getUsername( $message->userTo );
|
|
$messageOut['userToPretty'] = \ucfirst( $messageOut['userTo'] );
|
|
$messageOut['userFrom'] = self::$user->getUsername( $message->userFrom );
|
|
$messageOut['userFromPretty'] = \ucfirst( $messageOut['userFrom'] );
|
|
$out[] = (object) $messageOut;
|
|
if ( !empty( $end ) ) {
|
|
$out = $out[0];
|
|
break;
|
|
}
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* Function to check input and save messages to the DB.
|
|
*
|
|
* @param string $data - Username of the person receiving the sent message.
|
|
* @return function
|
|
*/
|
|
public function newThread( $to, $subject, $message ) {
|
|
if ( !self::$user->usernameExists( $to ) ) {
|
|
Debug::info( 'Message->sendMessage: User not found.' );
|
|
return false;
|
|
}
|
|
$fields = [
|
|
'userTo' => self::$user->getID( $to ),
|
|
'userFrom' => App::$activeUser->ID,
|
|
'parent' => 0,
|
|
'sent' => time(),
|
|
'lastReply' => time(),
|
|
'senderDeleted' => 0,
|
|
'recieverDeleted' => 0,
|
|
'isRead' => 0,
|
|
'subject' => $subject,
|
|
'message' => $message,
|
|
];
|
|
if ( !self::$db->insert( $this->tableName, $fields ) ) {
|
|
new CustomException( 'messageSend' );
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public function getUnreadCount( $userId ) {
|
|
$result = self::$db->get(
|
|
$this->tableName,
|
|
[
|
|
'userTo', '=', $userId,
|
|
'AND',
|
|
'isRead', '=', 0,
|
|
'AND',
|
|
'parent', '=', 0,
|
|
'AND',
|
|
'recieverDeleted', '=', 0,
|
|
]
|
|
);
|
|
return $result->count();
|
|
}
|
|
|
|
public function unreadCount() {
|
|
if ( empty( App::$activeUser->ID ) ) {
|
|
return 0;
|
|
}
|
|
return $this->getUnreadCount( App::$activeUser->ID );
|
|
}
|
|
|
|
public function hasPermission( $id ) {
|
|
if ( !Check::id( $id ) ) {
|
|
Debug::info( 'Invalid ID' );
|
|
return false;
|
|
}
|
|
$messageData = self::$db->get( 'messages', [ 'ID', '=', $id ] );
|
|
if ( $messageData->count() == 0 ) {
|
|
Debug::info( 'Message not found.' );
|
|
return false;
|
|
}
|
|
$message = $messageData->first();
|
|
if ( $message->userTo != App::$activeUser->ID && $message->userFrom != App::$activeUser->ID ) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Marks a message as read. This is setup to only work
|
|
* if the message was sent to the active user.
|
|
*
|
|
* @param int - The message ID you are marking as read.
|
|
* @return bool
|
|
*/
|
|
public function markRead( $id ) {
|
|
if ( !Check::id( $id ) ) {
|
|
Debug::info( 'Invalid ID' );
|
|
return false;
|
|
}
|
|
$result = self::$db->get( $this->tableName, [ 'ID', '=', $id, 'AND', 'userTo', '=', App::$activeUser->ID, 'AND', 'isRead', '=', '0' ] );
|
|
if ( $result->count() == 0 ) {
|
|
Debug::info( 'Failed to mark message as read.' );
|
|
return false;
|
|
}
|
|
if ( !self::$db->update( $this->tableName, $id, [ 'isRead' => 1 ] ) ) {
|
|
Debug::error( 'Failed to mark message as read.' );
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public function newMessageReply( $id, $message ) {
|
|
if ( !$this->hasPermission( $id ) ) {
|
|
Debug::info( 'Permission Denied.' );
|
|
return false;
|
|
}
|
|
$messageData = self::$db->get( $this->tableName, [ 'ID', '=', $id ] )->first();
|
|
if ( $messageData->userTo == App::$activeUser->ID ) {
|
|
$recipient = $messageData->userFrom;
|
|
} else {
|
|
$recipient = $messageData->userTo;
|
|
}
|
|
if ( $recipient === App::$activeUser->ID ) {
|
|
Debug::info( 'Cannot send messages to yourself' );
|
|
return false;
|
|
}
|
|
if ( !self::$db->update( $this->tableName, $messageData->ID, [ 'lastReply' => time() ] ) ) {
|
|
new CustomException( 'messagesReplyUpdate' );
|
|
return false;
|
|
}
|
|
$fields = [
|
|
'senderDeleted' => 0,
|
|
'recieverDeleted' => 0,
|
|
'isRead' => 0,
|
|
'userTo' => $recipient,
|
|
'userFrom' => App::$activeUser->ID,
|
|
'message' => $message,
|
|
'subject' => 're: ' . $messageData->subject,
|
|
'sent' => time(),
|
|
'parent' => $messageData->ID,
|
|
'lastReply' => time(),
|
|
];
|
|
if ( !self::$db->insert( $this->tableName, $fields ) ) {
|
|
new CustomException( 'messagesReplySend' );
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public function messageTitle( $id ) {
|
|
if ( !$this->hasPermission( $id ) ) {
|
|
Debug::info( 'Permission Denied.' );
|
|
return false;
|
|
}
|
|
$message = self::$db->get( $this->tableName, [ 'ID', '=', $id ] )->first();
|
|
return $message->subject;
|
|
}
|
|
|
|
/**
|
|
* Function to delete messages from the DB.
|
|
*
|
|
* @param int $data - The ID of the message you are trying to delete.
|
|
* @todo - done at 5 am after no sleep. This can be simplified a lot, i just wanted a working solution ASAP
|
|
* @return bool
|
|
*/
|
|
public function delete( $data ) {
|
|
if ( !is_array( $data ) ) {
|
|
$data = [ $data ];
|
|
}
|
|
foreach ( $data as $instance ) {
|
|
if ( !Check::id( $instance ) ) {
|
|
$error = true;
|
|
}
|
|
if ( !$this->hasPermission( $instance ) ) {
|
|
Debug::info( 'Permission Denied.' );
|
|
return false;
|
|
}
|
|
$message = self::$db->get( $this->tableName, [ 'ID', '=', $instance ] )->first();
|
|
if ( $message->userTo == App::$activeUser->ID ) {
|
|
$fields = [ 'recieverDeleted' => '1' ];
|
|
} else {
|
|
$fields = [ 'senderDeleted' => '1' ];
|
|
}
|
|
if ( !self::$db->update( $this->tableName, $instance, $fields ) ) {
|
|
$error = true;
|
|
}
|
|
Debug::info( "message Deleted: $instance" );
|
|
if ( !empty( $end ) ) {
|
|
break;
|
|
}
|
|
}
|
|
if ( !empty( $error ) ) {
|
|
Debug::info( 'There was an error deleting one or more messages.' );
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|