| Current Path : /var/www/html/components/com_jchat/Model/ |
| Current File : /var/www/html/components/com_jchat/Model/MessagingModel.php |
<?php
namespace JExtstore\Component\JChat\Site\Model;
/**
* @package JCHAT::FORM::components::com_jchat
* @subpackage models
* @author Joomla! Extensions Store
* @copyright (C) 2024 - Joomla! Extensions Store
* @license GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html
*/
defined( '_JEXEC' ) or die( 'Restricted access' );
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Filter\InputFilter;
use JExtstore\Component\JChat\Administrator\Framework\Model as JChatModel;
use JExtstore\Component\JChat\Administrator\Framework\Exception as JChatException;
use JExtstore\Component\JChat\Administrator\Framework\Exception\Exceptions;
/**
* Group users chat model
*
* @package JCHAT::FORM::components::com_jchat
* @subpackage models
* @since 1.0
*/
class MessagingModel extends JChatModel {
use Exceptions;
/**
* Reference to the stream model
*
* @access private
* @var Object &
*/
private $streamModel;
/**
* User Object
* @access private
* @var Object &
*/
private $myUser;
/**
* User field name
* @access private
* @var string
*/
private $userFieldName;
/**
* Restituisce la query string costruita per ottenere il wrapped set richiesto in base
* allo userstate, opzionalmente seleziona i campi richiesti
*
* @access private
* @return string
*/
protected function buildListQuery() {
$queryParts = array();
$selectLastSentMessages = '';
$queryParts['SELECT'] = '';
$queryParts['JOIN'] = '';
$accessLevels['JOIN'] = '';
$myUsersGroups['JOIN'] = '';
$orderByConversations['JOIN'] = '';
$accessLevelsAND = null;
$myUsersGroupsAND = null;
$queryOrder = "\n ORDER BY u.{$this->userFieldName} ASC";
// get current time to evaluate if users are online or offline, AKA no more session refresh after maxinactivitytime seconds = users stripped out from buddylist
$time = time();
// Evaluate ONLY FRIENDS 3PD integration option
if($this->componentParams->get('3pdintegration', null) && $this->componentParams->get('filter_friendship', false)) {
$queryPartsFriends = $this->streamModel->getQueryParts('buddylist');
} else {
$queryPartsFriends['JOIN'] = '';
$queryPartsFriends['WHERE'] = '';
}
// Manage live support mode filtering
list($queryParts['JOIN'], $additionalAND) = $this->streamModel->getQueryLiveSupport ('u.id');
// Manage chat filtering by access levels
list($accessLevels['JOIN'], $accessLevelsAND) = $this->streamModel->getQueryAccessLevels('u.id');
// Manage chat filtering by same users groups of the current user
if($this->componentParams->get('limit_my_users_groups', 0)) {
list($myUsersGroups['JOIN'], $myUsersGroupsAND) = $this->streamModel->getQueryMyUsersGroups('u.id');
}
// Manage ordering of users list
if($this->componentParams->get('pm_order_by_clause', 'alpha') == 'chrono') {
$selectLastSentMessages = ', innerselect.lastsentmessage';
$orderByConversations['JOIN'] = "\n LEFT JOIN (SELECT innerchat.fromuser, MAX(innerchat.sent) AS lastsentmessage" .
"\n FROM #__jchat AS innerchat GROUP BY innerchat.fromuser) innerselect ON u.id = innerselect.fromuser";
$queryOrder = "\n ORDER BY innerselect.lastsentmessage DESC";
}
$queryLimit = '';
$queryLimitValue = (int)$this->componentParams->get('limit_users_number_value', 1000);
if($this->componentParams->get('limit_users_number', 0) && $queryLimitValue) {
$queryLimit = "\n LIMIT 0, " . $queryLimitValue;
}
// Evaluate the shared session option for SQL queries on Joomla 3.7+
$sharedSession = (int)$this->app->get('shared_session', null);
if($sharedSession == 1 && $this->componentParams->get('shared_session_support', 1)) {
$sessClientId = "\n AND (sess.client_id = 0 OR ISNULL(sess.client_id))";
} else {
$sessClientId = "\n AND sess.client_id = 0";
}
$query = "SELECT DISTINCT(u.id), MAX(sess.time)," .
"\n u.{$this->userFieldName} AS " . $this->dbInstance->quoteName('username') . "," .
"\n sess.session_id" .
$selectLastSentMessages .
"\n FROM #__users AS u" .
"\n LEFT JOIN #__session AS sess" .
"\n ON u.id = sess.userid" .
$sessClientId .
$orderByConversations['JOIN'] .
$queryPartsFriends['JOIN'] .
$queryParts['JOIN'] .
$accessLevels['JOIN'] .
$myUsersGroups['JOIN'] .
"\n WHERE u.id <> " . (int)$this->myUser->id .
"\n AND u.block = 0" .
$additionalAND .
$accessLevelsAND .
$myUsersGroupsAND .
$queryPartsFriends['WHERE'] .
"\n GROUP BY u.id" .
$queryOrder .
$queryLimit;
return $query;
}
/**
* Main get data method to retrieve the users list
*
* @access public
* @return Object[]
*/
public function getData(): array {
// Build query
$query = $this->buildListQuery ();
try {
$this->dbInstance->setQuery ( $query );
$result = $this->dbInstance->loadObjectList ();
} catch ( JChatException $e ) {
$this->app->enqueueMessage ( $e->getMessage (), $e->getExceptionLevel () );
$result = array ();
} catch ( \Exception $e ) {
$jchatException = new JChatException ( $e->getMessage (), 'error' );
$this->app->enqueueMessage ( $jchatException->getMessage (), $jchatException->getExceptionLevel () );
$result = array ();
}
return $result;
}
/**
* Main get data method to retrieve the users list
*
* @access public
* @return Object[]
*/
public function getPendingMessages() {
// Build query
$query = "SELECT COUNT(*) AS newmessages, cchat.fromuser" .
"\n FROM #__jchat AS cchat" .
"\n WHERE cchat.touser = " . (int)$this->myUser->id .
"\n AND cchat.read = 0" .
"\n GROUP BY cchat.fromuser";
try {
$this->dbInstance->setQuery ( $query );
$result = $this->dbInstance->loadAssocList ('fromuser');
} catch ( JChatException $e ) {
$this->app->enqueueMessage ( $e->getMessage (), $e->getExceptionLevel () );
$result = array ();
} catch ( \Exception $e ) {
$jchatException = new JChatException ( $e->getMessage (), 'error' );
$this->app->enqueueMessage ( $jchatException->getMessage (), $jchatException->getExceptionLevel () );
$result = array ();
}
return $result;
}
/**
* Load entity from ORM table and manages session data post error redirect
*
* @access public
* @param int $id The target user id in the conversation
* @return Object&
*/
public function loadEntity($id) {
$fromLoggedID = $id->fromLoggedId;
$limitQueryMessages = null;
if(isset($id->oldestMsgId)) {
$oldestMessageID = $id->oldestMsgId;
$limitQueryMessages = $oldestMessageID ? "\n AND cchat.id < " . (int)$oldestMessageID : null;
}
$limitMessages = "\n LIMIT " . (int)$this->componentParams->get('pm_num_loading_msgs', 100);
try {
$sql = "SELECT cchat.id, cchat.from," .
"\n cchat.message, cchat.sent, cchat.read, cchat.type, cchat.status, u.id AS userid, " .
"\n u.{$this->userFieldName} AS " . $this->dbInstance->quoteName('fromusername') .
"\n FROM #__jchat AS cchat" .
"\n INNER JOIN #__users AS u ON cchat.fromuser = u.id" .
"\n WHERE ((cchat.touser = ". $this->dbInstance->quote($this->myUser->id) .
"\n AND cchat.fromuser = " . $this->dbInstance->quote($fromLoggedID) . ")" .
"\n OR (cchat.fromuser = ". $this->dbInstance->quote($this->myUser->id) .
"\n AND cchat.touser = " . $this->dbInstance->quote($fromLoggedID) . "))" .
"\n AND cchat.id NOT IN(SELECT " . $this->dbInstance->quoteName('messageid') .
"\n FROM " . $this->dbInstance->quoteName('#__jchat_messaging_deletedmessages') .
"\n WHERE " . $this->dbInstance->quoteName('userid') . " = " . $this->dbInstance->quote($this->myUser->id) . ")" .
$limitQueryMessages .
"\n ORDER BY cchat.id DESC" .
$limitMessages;
$this->dbInstance->setQuery($sql);
$rows = $this->dbInstance->loadAssocList();
// Now update status of all messages received till the latest new message as read status
$sql = "UPDATE" .
"\n " . $this->dbInstance->quoteName('#__jchat') . " AS cchat" .
"\n SET " . $this->dbInstance->quoteName('read') . " = 1 " .
"\n WHERE " . $this->dbInstance->quoteName('touser') . " = " . (int)($this->myUser->id) .
"\n AND " . $this->dbInstance->quoteName('fromuser') . " = " . (int)($fromLoggedID) .
"\n AND " . $this->dbInstance->quoteName('read') . " = 0" .
$limitQueryMessages .
"\n ORDER BY cchat.id DESC" .
$limitMessages;
$this->dbInstance->setQuery($sql);
$this->dbInstance->execute();
return $rows;
} catch ( JChatException $e ) {
$this->setException ( $e );
return false;
} catch ( \Exception $e ) {
$jchatException = new JChatException ( $e->getMessage (), 'error' );
$this->setException ( $jchatException );
return false;
}
return true;
}
/**
* Delete conversation messages based on messages ids but not deleting records
* It only flags the messages as deleted from the current user on demand to avoid redownload
* The physical deletion must be done in admin
*
* @param int $ids
* @access public
* @return bool
*/
public function deleteEntity($ids): bool {
$chunksQuery = array();
// Now update status of all messages received till latest new message as read status
foreach ($ids as $messageId) {
$chunksQuery[] = "(" .
(int)($messageId) . "," .
(int)($this->myUser->id) . ")";
}
try {
$sql = "INSERT IGNORE INTO #__jchat_messaging_deletedmessages (" .
$this->dbInstance->quoteName('messageid') . ", " .
$this->dbInstance->quoteName('userid') .
") VALUES " . implode(",\n", $chunksQuery);
$this->dbInstance->setQuery($sql);
if(!$this->dbInstance->execute()) {
throw new JChatException(Text::_('COM_JCHAT_ERRORSYNC_INSERT'), 'notice');
}
$this->dbInstance->setQuery($sql);
$this->dbInstance->execute();
} catch ( JChatException $e ) {
$this->setException ( $e );
return false;
} catch ( \Exception $e ) {
$jchatException = new JChatException ( $e->getMessage (), 'error' );
$this->setException ( $jchatException );
return false;
}
return true;
}
/**
* Class constructor
* @access public
* @param Object& $wpdb
* @param Object& $userObject
* @return Object &
*/
public function __construct($config = array(), ?MVCFactoryInterface $factory = null) {
// Parent model construct
parent::__construct( $config, $factory );
$this->getComponentParams();
// Reference to the stream model
$this->streamModel = $config['streamModel'];
// Store the owned user object instance
$this->myUser = $this->app->getIdentity();
$filter = InputFilter::getInstance();
$this->userFieldName = $filter->clean($this->componentParams->get('usefullname', 'username'), 'word');
}
}