| Current Path : /var/www/html/components/com_jchat/Model/ |
| Current File : /var/www/html/components/com_jchat/Model/LivestreamingModel.php |
<?php
namespace JExtstore\Component\JChat\Site\Model;
/**
* @package JCHAT::LIVESTREAMING::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\Date\Date;
use Joomla\Filesystem\Folder;
use Joomla\Filesystem\File;
use JExtstore\Component\JChat\Administrator\Framework\Model as JChatModel;
use JExtstore\Component\JChat\Administrator\Framework\Exception as JChatException;
use JExtstore\Component\JChat\Administrator\Framework\Helpers\Users as JChatHelpersUsers;
/**
* Group users chat model
*
* @package JCHAT::LIVESTREAMING::components::com_jchat
* @subpackage models
* @since 2.48
*/
class LivestreamingModel extends JChatModel {
/**
* This peer1 session ID
* @access private
* @var int
*/
private $mySessionId;
/**
* Client response
* @access private
* @var array
*/
private $response;
/**
* Retrieve a broadcaster name based on the overrides chain
*
* @access public
* @return string
*/
public function getBroadcasterName() {
$broadcasterSessionId = $this->getState('livestreaming_broadcaster_sessionid');
if(!$broadcasterSessionId) {
return '';
}
$userFieldName = $this->componentParams->get('usefullname', 'username');
$broadcasterName = '';
// End a peers conversation call
$query = "SELECT u.$userFieldName, ccs.override_name" .
"\n FROM " . $this->dbInstance->quoteName('#__session') . " AS sess" .
"\n LEFT JOIN " . $this->dbInstance->quoteName('#__users') . " AS u ON sess.userid = u.id" .
"\n LEFT JOIN " . $this->dbInstance->quoteName('#__jchat_sessionstatus') . " AS ccs ON sess.session_id = ccs.sessionid".
"\n WHERE sess.session_id = " . $this->dbInstance->quote($broadcasterSessionId);
$this->dbInstance->setQuery($query);
$nameOfTheUser = $this->dbInstance->loadAssoc();
// Guest name override: user field name -> override name -> auto generated
if($nameOfTheUser) {
if(!$nameOfTheUser[$userFieldName]) {
if(!$nameOfTheUser['override_name']) {
$broadcasterName = JChatHelpersUsers::generateRandomGuestNameSuffix($broadcasterSessionId, $this->componentParams);
} else {
$broadcasterName = $nameOfTheUser['override_name'];
}
} else {
$broadcasterName = $nameOfTheUser[$userFieldName];
}
}
// Set the model state for a found user based on the sessionid AKA livestreaming ID, if not avoid to display the interface
$this->setState('livestreaming_exists', $broadcasterName);
$this->setState('livestreaming_ismine', ($broadcasterSessionId == $this->mySessionId));
return $broadcasterName;
}
/**
*
* Store the session status for livestreaming role and state
*
* @access public
* @return boolean
*/
public function checkIfStreamingStale() {
$broadcasterSessionId = $this->getState('livestreaming_broadcaster_sessionid');
if(!$broadcasterSessionId) {
return false;
}
// End a peers conversation call
$query = "SELECT " . $this->dbInstance->quoteName('time') .
"\n FROM " . $this->dbInstance->quoteName('#__session') . " AS sess" .
"\n WHERE sess.session_id = " . $this->dbInstance->quote($broadcasterSessionId);
$this->dbInstance->setQuery($query);
$isSessionStillAvailable = $this->dbInstance->loadResult();
return (bool)$isSessionStillAvailable;
}
/**
*
* Check if a live recording is available for the current broadcaster sessionid
*
* @access public
* @return boolean
*/
public function checkIfRecordingAvailable() {
$broadcasterSessionId = $this->getState('livestreaming_broadcaster_sessionid');
if(!$broadcasterSessionId) {
return false;
}
// Check if a recording live session is available for this broadcaster session ID
$folderExists = file_exists(JPATH_ROOT . '/media/com_jchat/livestreaming/archive/' . $broadcasterSessionId);
return $folderExists;
}
/**
*
* Store the session status for livestreaming role and state
*
* @param string $broadcasterSessionId
* @param int $watcherIsWatching
* @access public
* @return boolean
*/
public function updateEntity($broadcasterSessionId = null, $watcherIsWatching = 0) {
$streamingHash = $broadcasterSessionId ? $broadcasterSessionId : $this->mySessionId;
$query = "INSERT INTO #__jchat_sessionstatus" .
"\n (" . $this->dbInstance->quoteName('sessionid') . "," .
$this->dbInstance->quoteName('livestreaming_hash') . "," .
$this->dbInstance->quoteName('livestreaming_watch') . " ) VALUES (" .
"\n " . $this->dbInstance->quote($this->mySessionId) . "," .
$this->dbInstance->quote($streamingHash) . "," .
(int)($watcherIsWatching) . ") " .
"\n ON DUPLICATE KEY UPDATE " .
$this->dbInstance->quoteName('livestreaming_hash') . " = " . $this->dbInstance->quote($streamingHash) . "," .
$this->dbInstance->quoteName('livestreaming_watch') . " = " . (int)($watcherIsWatching);
try {
$this->dbInstance->setQuery($query);
$this->dbInstance->execute ();
} catch (JChatException $e) {
$this->response['storing'] = array('status'=>false, 'exception_message'=>$e->getMessage());
return $this->response;
} catch (\Exception $e) {
$jchatException = new JChatException($e->getMessage(), 'error');
$this->response['storing'] = array('status'=>false, 'exception_message'=>$jchatException->getMessage());
return $this->response;
}
// All went well
$this->response['storing'] = array('status'=>true);
return $this->response;
}
/**
* Store uploaded file to the media recordings folder,
* fully manage error messages and ask for database insert
*
* @access public
* @param bool $updateNulls
* @return Object
*/
public function storeEntity($updateNulls = false) {
// Response JSON object
$response = new \stdClass ();
$this->getComponentParams();
$livestreamingMediaFolder = JPATH_ROOT . '/media/com_jchat/livestreaming';
$livestreamingArchiveFolder = JPATH_ROOT . '/media/com_jchat/livestreaming/archive/' . $this->mySessionId;
// Get uploaded model state
$uploadedMediaFile = $this->getState('blobfile');
$uploadedMediaFileName = $this->getState('blobfilename');
try {
$tmpFile = $uploadedMediaFile['tmp_name'];
if(!$tmpFile) {
throw new \Exception(Text::_('COM_JCHAT_NOFILE_SELECTED'));
}
if(!is_dir($livestreamingMediaFolder)) {
Folder::create($livestreamingMediaFolder);
}
if(!is_writable($livestreamingMediaFolder)) {
if(!chmod($livestreamingMediaFolder, 0775)) {
throw new \Exception( Text::_('COM_JCHAT_MEDIADIR_WRITABLE'));
}
}
// If the recording option is enabled, archive this live streaming for later watchers
if($this->app->getMenu()->getParams($this->getState('propagatedItemid'))->get('record_livestreaming', 0) && file_exists($tmpFile)) {
if(!is_dir($livestreamingArchiveFolder)) {
Folder::create($livestreamingArchiveFolder);
$lastChunkValue = 0;
File::copy($tmpFile, $livestreamingArchiveFolder . '/' . $lastChunkValue . '.webm');
// Add a record to the database table #__jchat_recordings
$this->setState('livestreaming_broadcaster_sessionid', $this->mySessionId);
$recorderTable = $this->getTable('Recorder', 'Administrator');
$recorderTable->title = 'live_streaming_' . $this->getBroadcasterName() . '_' . $this->mySessionId;
$recorderTable->size = '-';
$recorderTable->timerecord = Date::getInstance()->toSql(true);
$recorderTable->peer1 = $this->getBroadcasterName();
$recorderTable->peer2 = 'livestreaming';
$recorderTable->store();
} else {
$currentChunkFiles = Folder::files($livestreamingArchiveFolder);
asort($currentChunkFiles, SORT_NUMERIC);
$lastChunkFileName = array_pop($currentChunkFiles);
$lastChunkValue = str_ireplace('.webm', '', $lastChunkFileName);
$lastChunkValue++;
File::copy($tmpFile, $livestreamingArchiveFolder . '/' . $lastChunkValue . '.webm');
}
}
// Check if file already esists
if(file_exists($livestreamingMediaFolder . '/' . $uploadedMediaFileName)) {
unlink($livestreamingMediaFolder . '/' . $uploadedMediaFileName);
}
if(!move_uploaded_file($tmpFile, $livestreamingMediaFolder . '/' . $uploadedMediaFileName)) {
throw new \Exception( Text::_('COM_JCHAT_MEDIAUPLOAD_ERROR'));
}
} catch ( \Exception $e ) {
$response->result = false;
$response->exception_message = $e->getMessage ();
return $response;
}
// Manage exceptions from DB Model and return to JS domain
$response->result = true;
return $response;
}
/**
* Delete/archive uploaded file to the media recordings folder,
* fully manage error messages and ask for database insert
*
* @access public
* @return Object
*/
public function deleteEntity($ids) {
// Response JSON object
$response = new \stdClass ();
$this->getComponentParams();
$livestreamingMediaFolder = JPATH_ROOT . '/media/com_jchat/livestreaming';
// Get uploaded model state
$uploadedMediaFileName = $this->getState('blobfilename');
try {
// Check if file already esists
if(file_exists($livestreamingMediaFolder . '/' . $uploadedMediaFileName)) {
unlink($livestreamingMediaFolder . '/' . $uploadedMediaFileName);
}
} catch ( \Exception $e ) {
$response->result = false;
$response->exception_message = $e->getMessage ();
return $response;
}
// Manage exceptions from DB Model and return to JS domain
$response->result = true;
return $response;
}
/**
* Class constructor
* @access public
* @param array $config
* @param object $factory
*/
public function __construct($config = array(), ?MVCFactoryInterface $factory = null) {
parent::__construct( $config, $factory );
// Store ssessionID peer1 caller
$this->mySessionId = $config['sessiontable']->session_id;
$this->setState('livestreamingid', $this->mySessionId);
$this->response = array();
}
}