Файловый менеджер - Редактировать - /var/www/html/libraries/kunena/src/Forum/Message/KunenaMessage.php
Ðазад
<?php /** * Kunena Component * * @package Kunena.Framework * @subpackage Forum.Message * * @copyright Copyright (C) 2008 - @currentyear@ Kunena Team. All rights reserved. * @license https://www.gnu.org/copyleft/gpl.html GNU/GPL * @link https://www.kunena.org **/ namespace Kunena\Forum\Libraries\Forum\Message; \defined('_JEXEC') or die(); use Exception; use InvalidArgumentException; use Joomla\CMS\Factory; use Joomla\Filesystem\File; use Joomla\CMS\Language\Text; use Joomla\CMS\Mail\Mail; use Joomla\CMS\Mail\MailHelper; use Joomla\CMS\Mail\MailerFactoryInterface; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Uri\Uri; use Joomla\CMS\User\UserHelper; use Joomla\Database\DatabaseDriver; use Joomla\Database\Exception\ExecutionFailureException; use Kunena\Forum\Libraries\Access\KunenaAccess; use Kunena\Forum\Libraries\Attachment\KunenaAttachment; use Kunena\Forum\Libraries\Attachment\KunenaAttachmentHelper; use Kunena\Forum\Libraries\Config\KunenaConfig; use Kunena\Forum\Libraries\Database\KunenaDatabaseObject; use Kunena\Forum\Libraries\Date\KunenaDate; use Kunena\Forum\Libraries\Email\KunenaEmail; use Kunena\Forum\Libraries\Error\KunenaError; use Kunena\Forum\Libraries\Exception\KunenaExceptionAuthorise; use Kunena\Forum\Libraries\Factory\KunenaFactory; use Kunena\Forum\Libraries\Forum\Category\KunenaCategory; use Kunena\Forum\Libraries\Forum\Category\KunenaCategoryHelper; use Kunena\Forum\Libraries\Forum\Category\User\KunenaCategoryUserHelper; use Kunena\Forum\Libraries\Forum\KunenaForum; use Kunena\Forum\Libraries\Forum\Message\Thankyou\KunenaMessageThankyouHelper; use Kunena\Forum\Libraries\Forum\Topic\KunenaTopic; use Kunena\Forum\Libraries\Forum\Topic\KunenaTopicHelper; use Kunena\Forum\Libraries\Forum\Topic\User\Read\KunenaTopicUserReadHelper; use Kunena\Forum\Libraries\Html\KunenaParser; use Kunena\Forum\Libraries\Layout\KunenaLayout; use Kunena\Forum\Libraries\Route\KunenaRoute; use Kunena\Forum\Libraries\User\KunenaUser; use Kunena\Forum\Libraries\User\KunenaUserHelper; use StdClass; /** * Class \Kunena\Forum\Libraries\Forum\Message\Message * * @property int $parent * @property int $thread * @property int $catid * @property string $name * @property int $userid * @property string $email * @property string $subject * @property int $time * @property string $ip * @property int $topic_emoticon * @property int $locked * @property int $hold * @property int $ordering * @property int $hits * @property int $moved * @property int $deleted_time * @property int $modified_by * @property string $modified_time * @property string $modified_reason * @property string $message * @since Kunena 6.0 */ class KunenaMessage extends KunenaDatabaseObject { /** * @var array * @since Kunena 6.0 */ protected static $actions = [ 'none' => [], 'read' => ['Read'], 'reply' => ['Read', 'NotHold', 'GuestWrite'], 'edit' => ['Read', 'Own', 'EditTime'], 'move' => ['Read'], 'approve' => ['Read'], 'delete' => ['Read', 'Own', 'Delete'], 'thankyou' => ['Read', 'Thankyou'], 'unthankyou' => ['Read'], 'undelete' => ['Read'], 'permdelete' => ['Read', 'Permdelete'], 'attachment.read' => ['Read'], 'attachment.createimage' => ['Read', 'AttachmentsImage'], 'attachment.createfile' => ['Read', 'AttachmentsFile'], 'attachment.delete' => [], 'attachment.private' => [], ]; /** * @var integer * @since Kunena 6.0 */ public $id = null; public $thankyou = []; public $replynum; /** * @var string * @since Kunena 6.4 */ public $typeAlias; /** * @var string * @since Kunena 6.4 */ public $parent; /** * @var string * @since Kunena 6.4 */ public $thread; /** * @var integer * @since Kunena 6.4 */ public $catid; /** * @var string * @since Kunena 6.4 */ public $name; /** * @var integer * @since Kunena 6.4 */ public $userid; /** * @var string * @since Kunena 6.4 */ public $email; /** * @var string * @since Kunena 6.4 */ public $subject; /** * @var string * @since Kunena 6.4 */ public $time; /** * @var string * @since Kunena 6.4 */ public $ip; /** * @var string * @since Kunena 6.4 */ public $topic_emoticon; /** * @var string * @since Kunena 6.4 */ public $locked; /** * @var integer * @since Kunena 6.4 */ public $hold; /** * @var string * @since Kunena 6.4 */ public $ordering; /** * @var string * @since Kunena 6.4 */ public $hits; /** * @var string * @since Kunena 6.4 */ public $moved; /** * @var integer * @since Kunena 7.0 */ public $deleted_time; /** * @var integer * @since Kunena 6.4 */ public $modified_by; /** * @var string * @since Kunena 6.4 */ public $modified_time; /** * @var string * @since Kunena 6.4 */ public $modified_reason; /** * @var string * @since Kunena 6.4 */ public $params; /** * @var string * @since Kunena 6.4 */ public $message; /** * @var string * @since Kunena 6.4 */ public $pm; /** * @var string * @since Kunena 6.0 */ protected $_table = 'KunenaMessages'; /** * @var DatabaseDriver|null * @since Kunena 6.0 */ protected $_db = null; /** * @var KunenaAttachment[] * @since Kunena 6.0 */ protected $_attachments_add = []; /** * @var KunenaAttachment[] * @since Kunena 6.0 */ protected $_attachments_del = []; /** * @var null * @since Kunena 6.0 */ protected $_topic = null; /** * @var integer * @since Kunena 6.0 */ protected $_hold = 1; /** * @var integer * @since Kunena 6.0 */ protected $_thread = 0; /** * @var array * @since Kunena 6.0 */ protected $_authcache = []; /** * @var boolean * @since Kunena 5.2 */ protected $_approved = false; /** * @var array * @since Kunena 6.0 */ protected $_authtcache = []; /** * @var array * @since Kunena 6.0 */ protected $_authfcache = []; /** * @var string * @since Kunena 6.0 */ protected $urlNotification; /** * @param mixed $properties properties * * @throws Exception * @since Kunena 6.0 * * @internal */ public function __construct($properties = null) { $this->_db = Factory::getContainer()->get('DatabaseDriver'); parent::__construct($properties); } /** * Returns \Kunena\Forum\Libraries\Forum\Message\Message object. * * @param int $identifier The message to load - Can be only an integer. * @param bool $reload reload * * @return KunenaMessage * * @throws Exception * @since Kunena 6.0 */ public static function getInstance($identifier = null, $reload = false): KunenaMessage { return KunenaMessageHelper::get($identifier, $reload); } /** * Destruct * * @since Kunena 6.0 */ public function __destruct() { unset($this->_db); unset($this->_topic); } /** * @param mixed $user user * * @return boolean * * @throws Exception * @since Kunena 6.0 */ public function isNew($user = null): bool { $user = KunenaUserHelper::get($user); if (!KunenaFactory::getConfig()->showNew || !$user->exists()) { return false; } $session = KunenaFactory::getSession(); if ($this->time < $session->getAllReadTime()) { return false; } $allreadtime = KunenaCategoryUserHelper::get($this->getCategory()->id, $user)->allreadtime; if ($allreadtime && $this->time < $allreadtime) { return false; } $read = KunenaTopicUserReadHelper::get($this->getTopic(), $user); if ($this->id == $read->message_id || $this->time < $read->time) { return false; } return true; } /** * @return KunenaCategory * * @throws Exception * @since Kunena 6.0 */ public function getCategory(): KunenaCategory { return KunenaCategoryHelper::get($this->catid); } /** * @return \Kunena\Forum\Libraries\Forum\Topic\KunenaTopic|null * * @since Kunena 6.0 * @throws \Exception */ public function getTopic(): ?KunenaTopic { if (!$this->_topic) { $this->_topic = KunenaTopicHelper::get($this->thread); } return $this->_topic; } /** * @param KunenaTopic $topic topic * * @return void * * @since Kunena 6.0 */ public function setTopic(KunenaTopic $topic): void { $this->_topic = $topic; if ($topic->id) { $this->thread = $topic->id; } } /** * Get published state in text. * * @return string * * @since Kunena 4.0 */ public function getState(): string { switch ($this->hold) { case 0: return 'published'; case 1: return 'unapproved'; case 2: case 3: return 'deleted'; } return 'unknown'; } /** * @param null|KunenaCategory $category Fake category if needed. Used for aliases. * @param bool $xhtml xhtml * @param int $itemid itemid * * @return string * * @throws Exception * @since Kunena 6.0 */ public function getUrl($category = null, $xhtml = true, $itemid = 0): string { return $this->getTopic()->getUrl($category, $xhtml, $this, $itemid); } /** * @param null|KunenaCategory $category Fake category if needed. Used for aliases. * * @return Uri * * @throws null * @throws Exception * @since Kunena 6.0 */ public function getUri($category = null) { return $this->getTopic()->getUri($category, $this); } /** * @param array $fields fields * @param int $useridfromparent * @param null|array $safefields safefields * * @return array * * @throws Exception * @since Kunena 6.0 */ public function newReply($fields = [], $useridfromparent = 0, $safefields = null): array { $user = KunenaUserHelper::get(); $topic = $this->getTopic(); $category = $this->getCategory(); $message = new KunenaMessage(); $message->setTopic($topic); $message->parent = $this->id; $message->thread = $topic->id; $message->catid = $topic->category_id; $message->name = $user->getName(''); $message->userid = $user->userid; $message->subject = $this->subject; $message->ip = KunenaUserHelper::getUserIp(); // Add IP to user. if (KunenaConfig::getInstance()->ipTracking) { if (empty($user->ip)) { $user->ip = KunenaUserHelper::getUserIp(); } } if (KunenaConfig::getInstance()->allowChangeSubject && $topic->first_post_userid == $message->userid || KunenaUserHelper::getMyself()->isModerator()) { if (isset($fields['subject'])) { $topic->subject = $fields['subject']; } } if ($topic->hold) { // If topic was unapproved or deleted, use the same state for the new message $message->hold = $topic->hold; } else { // Otherwise message is either unapproved or published depending if the category is moderated or not $message->hold = $category->review ? (int) !$category->isAuthorised('moderate', $user) : 0; } if ($fields['quote'] === true) { $userfromparent = KunenaUserHelper::get($useridfromparent); $userfromparentname = $userfromparent->getName(); if (empty($userfromparent->getName())) { $userfromparentname = 'anonymous'; } $find = ['/\[confidential\](.*?)\[\/confidential\]/su']; $replace = ''; $text = preg_replace($find, $replace, $this->message); $message->message = "[quote=\"{$userfromparentname} post={$this->id} userid={$useridfromparent}\"]" . $text . "[/quote]"; } else { if (\is_array($safefields)) { $message->bind($safefields); } if (\is_array($fields)) { $message->bind($fields, ['name', 'email', 'subject', 'message'], true); } } return [$topic, $message]; } /** * Send email notifications from the message. * * @param null|string $url url * @param boolean $approved false * * @return boolean|false * * @throws null * @throws Exception * @since Kunena 6.0 */ public function sendNotification($url = null, $approved = false) { $config = KunenaFactory::getConfig(); $db = Factory::getContainer()->get('DatabaseDriver'); if (!$config->sendEmails) { return false; } if ($this->hold > 1) { return false; } elseif ($this->hold == 1) { $mailsubs = 0; $mailmods = $config->mailModerators >= 0; $mailadmins = $config->mailAdministrators >= 0; } else { $mailsubs = (bool) $config->allowSubscriptions; $mailmods = $config->mailModerators >= 1; $mailadmins = $config->mailAdministrators >= 1; } $this->_approved = $approved; $once = false; if ($mailsubs) { if (!$this->parent) { // New topic: Send email only to category subscribers $mailsubs = $config->categorySubscriptions != 'disabled' ? KunenaAccess::CATEGORY_SUBSCRIPTION : 0; $once = $config->categorySubscriptions == 'topic'; } elseif ($config->categorySubscriptions != 'post') { // Existing topic: Send email only to topic subscribers $mailsubs = $config->topicSubscriptions != 'disabled' ? KunenaAccess::TOPIC_SUBSCRIPTION : 0; $once = $config->topicSubscriptions == 'first'; } else { // Existing topic: Send email to both category and topic subscribers $mailsubs = $config->topicSubscriptions == 'disabled' ? KunenaAccess::CATEGORY_SUBSCRIPTION : KunenaAccess::CATEGORY_SUBSCRIPTION | KunenaAccess::TOPIC_SUBSCRIPTION; // FIXME: category subscription can override topic $once = $config->topicSubscriptions == 'first'; } } if (!$url) { $url = Uri::getInstance()->toString(['scheme', 'host', 'port']) . $this->getPermaUrl(); } // Get all subscribers, moderators and admins who should get the email. $emailToList = KunenaAccess::getInstance()->getSubscribers( $this->catid, $this->thread, $mailsubs, $mailmods, $mailadmins, KunenaUserHelper::getMyself()->userid ); if ($emailToList) { if (!$config->email) { KunenaError::warning(Text::_('COM_KUNENA_EMAIL_DISABLED')); return false; } elseif (!MailHelper::isEmailAddress($config->email)) { KunenaError::warning(Text::_('COM_KUNENA_EMAIL_INVALID')); return false; } $topic = $this->getTopic(); // Make a list from all receivers; split the receivers into two distinct groups. $sentusers = []; $receivers = [0 => [], 1 => []]; foreach ($emailToList as $emailTo) { if (!$emailTo->email || !MailHelper::isEmailAddress($emailTo->email)) { continue; } if ( $config->emailVisibleAddress != $emailTo->email || ( \count($emailToList) == 1 && ($emailTo->moderator || $emailTo->subscription) ) ) { $receivers[$emailTo->subscription][] = $emailTo->email; $sentusers[] = $emailTo->id; } } $mailnamesender = !empty($config->emailSenderName) ? MailHelper::cleanAddress($config->emailSenderName) : MailHelper::cleanAddress($config->boardTitle); $mailsubject = MailHelper::cleanSubject($topic->subject . " (" . $this->getCategory()->name . ")"); $subject = $this->subject ? $this->subject : $topic->subject; // Create email. $mail = Factory::getContainer()->get(MailerFactoryInterface::class)->createMailer(); $mail->setSubject($mailsubject); $mail->setSender([$config->email, $mailnamesender]); // Send email to all subscribers. if (!empty($receivers[1])) { $this->attachEmailBody($mail, 1, $subject, $url, $once); KunenaEmail::send($mail, $receivers[1]); } // Send email to all moderators. if (!empty($receivers[0])) { $this->attachEmailBody($mail, 0, $subject, $url, $once); KunenaEmail::send($mail, $receivers[0]); } // Store the mails data for all subscribers in mail queue if (PluginHelper::isEnabled('kunena', 'plg_kunena_mails_queue')) { $columns = array('subject', 'message_id', 'sent_to', 'message_url'); $values = array($db->quote($subject), $this->id, $db->quote(implode(',', $receivers[1])), $db->quote($url)); $query = $db->createQuery() ->insert($db->quoteName('#__kunena_mails_queue')) ->columns($db->quoteName($columns)) ->values(implode(',', $values)); $db->setQuery($query); try { $db->execute(); } catch (ExecutionFailureException $e) { KunenaError::displayDatabaseError($e); } // Store the mails data for all moderators in mail queue $columns = array('subject', 'message_id', 'sent_to', 'message_url'); $values = array($db->quote($subject), $this->id, $db->quote(implode(',', $receivers[0])), $db->quote($url)); $query = $db->createQuery() ->insert($db->quoteName('#__kunena_mails_queue')) ->columns($db->quoteName($columns)) ->values(implode(',', $values)); $db->setQuery($query); try { $db->execute(); } catch (ExecutionFailureException $e) { KunenaError::displayDatabaseError($e); } } // Update subscriptions. if ($once && $sentusers) { $sentusers = implode(',', $sentusers); $query = $db->createQuery() ->update('#__kunena_user_topics') ->set('subscribed=2') ->where("topic_id={$this->thread}") ->where("user_id IN ({$sentusers})") ->where('subscribed=1'); $db->setQuery($query); try { $db->execute(); } catch (ExecutionFailureException $e) { KunenaError::displayDatabaseError($e); } } } return true; } /** * Get permament topic URL without domain. * * If you want to add domain (for email etc), you can prepend the output with this: * Uri::getInstance()->toString(array('scheme', 'host', 'port')) * * @param null|KunenaCategory $category Fake category if needed. Used for aliases. * @param bool $xhtml xhtml * * @return string * * @throws null * @throws Exception * @since Kunena 6.0 */ public function getPermaUrl($category = null, $xhtml = true): string { $uri = $this->getPermaUri($category); return KunenaRoute::_($uri, $xhtml); } /** * @param null|KunenaCategory $category category * * @return Uri|boolean * * @throws Exception * @since Kunena 6.0 */ public function getPermaUri($category = null) { $category = $category ? KunenaCategoryHelper::get($category) : $this->getCategory(); if (!$this->exists() || !$category->exists()) { return false; } return Uri::getInstance("index.php?option=com_kunena&view=topic&catid={$category->id}&id={$this->thread}&mesid={$this->id}"); } /** * @return void * * @throws Exception * @since Kunena 6.0 */ public static function notificationCloseConnection(): void { $app = Factory::getApplication(); $app->setHeader('Connection', 'close'); } /** * @param int $value value * * @return boolean * * @throws Exception * @throws null * @since Kunena */ public function publish($value = KunenaForum::PUBLISHED) { if ($this->hold == $value) { return true; } $this->hold = (int) $value; return $this->save(); } /** * Method to save the \Kunena\Forum\Libraries\Forum\Message\Message object to the database. * * @return bool * * @throws \Exception * @since Kunena 6.0 */ public function save(): bool { $user = KunenaUserHelper::getMyself(); if ($user->userid == 0 && $this->userid) { $user = KunenaUserHelper::get($this->userid); } if ($user->userid == 0 && !KunenaFactory::getConfig()->pubWrite) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_ERROR_ANONYMOUS_FORBITTEN'), 401); } $isNew = !$this->_exists; $topic = $this->getTopic(); $newTopic = !$topic->exists(); if ($newTopic) { // Create topic, but do not cascade changes to category etc.. try { $topic->save(false); } catch (Exception $e) { throw new Exception($e->getMessage()); } $this->_thread = $this->thread = $topic->id; } // Create message if (!parent::save()) { // If we created a new topic, remember to delete it too. if ($newTopic) { $topic->delete(); } return false; } if ($isNew) { $this->_hold = 1; } // Update attachments and message text $update = $this->updateAttachments(); // Did we change anything? if ($update) { if ($isNew && trim($this->message) == '') { // Oops, no attachments remain and the message becomes empty. // Let's delete the new message and fail on save. $this->delete(); // If we created a new topic, remember to delete it too. if ($newTopic) { $topic->delete(); } throw new Exception(Text::_('COM_KUNENA_LIB_TABLE_MESSAGES_ERROR_NO_MESSAGE')); } $table = $this->getTable(); $table->bind($this->getTableProperties()); $table->exists(true); try { $table->store(); } catch (Exception $e) { throw new Exception($e->getMessage()); } } // Cascade changes to other tables $this->update($newTopic); return true; } /** * @return boolean * * @throws null * @since Kunena 6.0 */ protected function updateAttachments(): bool { // Save new attachments and update message text $message = $this->message; $app = Factory::getApplication(); foreach ($this->_attachments_add as $tmpid => $attachment) { if ($attachment->exists() && $attachment->mesid) { try { $attachment->save(); } catch (Exception $e) { $app->enqueueMessage($e->getMessage(), 'error'); } } $attachment->mesid = $this->id; if ($attachment->IsImage()) { try { $attachment->tryAuthorise('createimage', null, false); } catch (Exception $e) { $app->enqueueMessage($e->getMessage(), 'error'); } } else { try { $attachment->tryAuthorise('createfile', null, false); } catch (Exception $e) { $app->enqueueMessage($e->getMessage(), 'error'); } } try { $attachment->save(); } catch (Exception $e) { $app->enqueueMessage($e->getMessage(), 'error'); } // Update attachments count and fix attachment name inside message $this->getTopic()->attachments++; $this->message = preg_replace('/\[attachment\:' . $tmpid . '\].*?\[\/attachment\]/u', "[attachment={$attachment->id}]{$attachment->filename}[/attachment]", $this->message); } // Delete removed attachments and update attachments count and message text foreach ($this->_attachments_del as $attachment) { if ($attachment->mesid && $attachment->mesid != $this->id) { // Attachment doesn't belong to this message => skip it. continue; } $exception = $attachment->tryAuthorise('delete', null, false); if ($exception) { throw new Exception($exception->getMessage()); } try { $attachment->delete(); } catch (Exception $e) { throw new Exception($e->getMessage()); } $this->getTopic()->attachments--; $this->message = preg_replace('/\[attachment\=' . $attachment->id . '\].*?\[\/attachment\]/u', '', $this->message); $this->message = preg_replace('/\[attachment\]' . $attachment->filename . '\[\/attachment\]/u', '', $this->message); } // Remove missing temporary attachments from the message text $this->message = trim(preg_replace('/\[attachment\:\d+\].*?\[\/attachment\]/u', '', $this->message)); // Return true if we changed the message contents return $this->message != $message; } /** * Method to delete the \Kunena\Forum\Libraries\Forum\Message\Message object from the database. * * @return boolean True on success * * @throws null * @throws Exception * @since Kunena 6.0 */ public function delete(): bool { if (!$this->exists()) { return true; } if (!parent::delete()) { return false; } $this->hold = 1; $attachments = $this->getAttachments(); foreach ($attachments as $attachment) { $file = JPATH_SITE . '/media/kunena/attachments/' . $attachment->userid . '/' . $attachment->filename; File::delete($file); try { $attachment->delete(); } catch (Exception $e) { throw new Exception($e->getMessage()); } } $db = Factory::getContainer()->get('DatabaseDriver'); // Delete thank yous $queries[] = "DELETE FROM #__kunena_thankyou WHERE postid={$db->quote($this->id)}"; // Delete message $queries[] = "DELETE FROM #__kunena_messages_text WHERE mesid={$db->quote($this->id)}"; // Cascade changes into other tables $this->update(); foreach ($queries as $query) { $db->setQuery($query); $db->execute(); try { $db->execute(); } catch (ExecutionFailureException $e) { KunenaError::displayDatabaseError($e); } } KunenaMessageThankyouHelper::recount(); return true; } /** * @param bool|array $ids ids * @param string $action action * * @return KunenaAttachment[] * * @throws Exception * @throws null * @since Kunena */ public function getAttachments($ids = false, $action = 'read'): array { if ($ids === false) { $attachments = KunenaAttachmentHelper::getByMessage($this->id, $action); } else { $attachments = KunenaAttachmentHelper::getById($ids, $action); foreach ($attachments as $id => $attachment) { if ($attachment->mesid && $attachment->mesid != $this->id) { unset($attachments[$id]); } } } return $attachments; } /** * @param bool $newTopic new topic * * @return void * * @throws Exception * @since Kunena 6.0 */ protected function update($newTopic = false): void { // If post was published and then moved, we need to update old topic if (!$this->_hold && $this->_thread && $this->_thread != $this->thread) { $topic = KunenaTopicHelper::get($this->_thread); try { $topic->update($this, -1); } catch (Exception $e) { throw new Exception($e->getMessage()); } } $postDelta = $this->delta(); $topic = $this->getTopic(); // New topic if ($newTopic) { $topic->hold = 0; } // Update topic if (!$this->hold && $topic->hold && $topic->exists()) { // We published message -> publish and recount topic $topic->hold = 0; $topic->recount(); } try { $topic->update($this, $postDelta); } catch (Exception $e) { throw new Exception($e->getMessage()); } // Activity integration // FIXME : load the plugin finder produce a fatal error // Joomla\CMS\Plugin\PluginHelper::importPlugin('finder'); $activity = KunenaFactory::getActivityIntegration(); if ($postDelta < 0) { Factory::getApplication()->triggerEvent('onDeleteKunenaPost', [[$this->id]]); $activity->onAfterDelete($this); } elseif ($postDelta > 0) { $topic->markRead(); if ($this->parent == 0) { $activity->onAfterPost($this); } else { $activity->onAfterReply($this); } } } /** * @return integer * * @since Kunena 6.0 */ protected function delta(): int { if (!$this->hold && ($this->_hold || $this->thread != $this->_thread)) { // Publish message or move it into new topic return 1; } if (!$this->_hold && $this->hold) { // Unpublish message return -1; } return 0; } /** * @param mixed $user user * * @return \Kunena\Forum\Libraries\Forum\Topic\User\KunenaTopicUser * * @throws Exception * @since Kunena 6.0 */ public function getUserTopic($user = null) { return $this->getTopic()->getUserTopic($user); } /** * @return KunenaMessage * * @throws Exception * @since Kunena 6.0 */ public function getParent(): KunenaMessage { return KunenaMessageHelper::get($this->parent); } /** * @return KunenaUser * * @throws Exception * @since Kunena 6.0 */ public function getAuthor(): KunenaUser { return KunenaUserHelper::getAuthor($this->userid, $this->name); } /** * @return KunenaDate * * @since Kunena 6.0 */ public function getTime(): KunenaDate { return new KunenaDate($this->time); } /** * @return KunenaUser * * @throws Exception * @since Kunena 6.0 */ public function getModifier(): KunenaUser { return KunenaUserHelper::get($this->modified_by); } /** * @return KunenaDate * * @since Kunena 6.0 */ public function getModifiedTime(): KunenaDate { return new KunenaDate($this->modified_time); } /** * Display required field from message table * * @param string $field field * @param boolean $html html * @param string $context context * * @return integer|string * * @throws Exception * @since Kunena 6.0 */ public function displayField(string $field, $html = true, $context = '') { switch ($field) { case 'id': return \intval($this->id); case 'subject': return KunenaParser::parseText($this->subject); case 'message': return $html ? KunenaParser::parseBBCode($this->message, $this, 0, $context) : KunenaParser::stripBBCode($this->message, 0, $html); } return ''; } /** * Returns true if user is authorised to do the action. * * @param string $action action * @param KunenaUser|null $user user * * @return boolean * * @throws Exception * @since Kunena 4.0 */ public function isAuthorised(string $action = 'read', ?KunenaUser $user = null) { if (KunenaFactory::getConfig()->readOnly) { // Special case to ignore authorisation. if ($action != 'read') { return false; } } return !$this->tryAuthorise($action, $user, false); } /** * Throws an exception if user isn't authorised to do the action. * * @param string $action action * @param KunenaUser|null $user user * @param bool $throw trow * * @return mixed * * @throws Exception * @since Kunena 4.0 */ public function tryAuthorise($action = 'read', ?KunenaUser $user = null, $throw = true) { // Special case to ignore authorisation. if ($action == 'none') { return false; } // Load user if not given. if ($user === null) { $user = KunenaUserHelper::getMyself(); } if (empty($this->_authcache[$user->userid][$action])) { // Unknown action - throw invalid argument exception. if (!isset(self::$actions[$action])) { throw new InvalidArgumentException(Text::sprintf('COM_KUNENA_LIB_AUTHORISE_INVALID_ACTION', $action), 500); } // Load category authorisation. if (!isset($this->_authtcache[$user->userid][$action])) { $this->_authtcache[$user->userid][$action] = $this->getTopic()->tryAuthorise('post.' . $action, $user, false); } $this->_authcache[$user->userid][$action] = $this->_authtcache[$user->userid][$action]; if (empty($this->_authcache[$user->userid][$action])) { foreach (self::$actions[$action] as $function) { if (!isset($this->_authfcache[$user->userid][$function])) { $authFunction = 'authorise' . $function; $this->_authfcache[$user->userid][$function] = $this->$authFunction($user); } $error = $this->_authfcache[$user->userid][$function]; if ($error) { $this->_authcache[$user->userid][$action] = $error; break; } } } } $exception = $this->_authcache[$user->userid][$action]; // Throw or return the exception. if ($throw && $exception) { throw $exception; } return $exception; } /** * @param array $fields fields * @param mixed $user user * * @return void * * @throws null * @since Kunena 6.0 */ public function edit($fields = [], $user = null): void { $user = KunenaUserHelper::get($user); $this->bind($fields, ['name', 'email', 'subject', 'message', 'modified_reason'], true); // Update rest of the information $category = $this->getCategory(); $this->hold = $category->review && !$category->isAuthorised('moderate', $user) ? 1 : $this->hold; $this->modified_by = $user->userid; $this->modified_time = Factory::getDate()->toUnix(); } /** * @param mixed $user user * * @return void * * @throws Exception * @since Kunena 6.0 */ public function makeAnonymous($user = null): void { $user = KunenaUserHelper::get($user); if ($user->userid == $this->userid && $this->modified_by == $this->userid) { // I am the author and previous modification was made by me => delete modification information to hide my personality $this->modified_by = 0; $this->modified_time = 0; $this->modified_reason = ''; } elseif ($user->userid == $this->userid) { // I am the author, but somebody else has modified the message => leave modification information intact $this->modified_by = null; $this->modified_time = null; $this->modified_reason = null; } // Remove userid, email and ip address $this->userid = 0; $this->ip = ''; $this->email = null; } /** * @param int $tmpid tmpid * @param string $postvar postvar * @param int|null $catid catid * * @return boolean * * @throws Exception * @since Kunena 6.0 */ public function uploadAttachment(int $tmpid, string $postvar, $catid = null): bool { $attachment = new KunenaAttachment(); $attachment->userid = $this->userid; $success = $attachment->upload($postvar, $catid); $this->_attachments_add[$tmpid] = $attachment; return $success; } /** * Add listed attachments to the message. * * If attachment is already pointing to the message, this function has no effect. * Currently only orphan attachments can be added. * * @param array $ids ids * * @return void * * @throws Exception * @throws null * @since Kunena 4.0 */ public function addAttachments(array $ids): void { $this->_attachments_add += $this->getAttachments($ids, 'none'); } /** * Remove listed attachments from the message. * * @param array $ids ids * * @return void * * @throws Exception * @since Kunena 4.0 */ public function removeAttachments(array $ids): void { $this->_attachments_del += $this->getAttachments($ids, 'none'); } /** * Get the number of attachments into a message * * @return StdClass * * @throws Exception * @since Kunena 6.0 */ public function getNbAttachments() { $attachments = KunenaAttachmentHelper::getNumberAttachments($this->id); $attachs = new StdClass(); $attachs->inline = 0; $attachs->image = 0; $attachs->file = 0; $attachs->totalNonProtected = 0; $attachs->readable = 0; $attachs->totalProtected = 0; $attachs->totalPrivate = 0; foreach ($attachments as $attach) { if ($attach->inline) { $attachs->inline = $attachs->inline + 1; } if ($attach->isImage()) { $attachs->image = $attachs->image + 1; } else { $attachs->file = $attachs->file + 1; } if ($attach->protected == 0) { $attachs->totalNonProtected = $attachs->totalNonProtected + 1; } if ($attach->isAuthorised('read')) { if (!$attach->inline) { $attachs->readable = $attachs->readable + 1; } } if ($attach->protected != 32) { $attachs->totalProtected = $attachs->totalProtected + 1; } if ($attach->protected == 32) { $attachs->totalPrivate = $attachs->totalPrivate + 1; } } return $attachs; } /** * Method to load a \Kunena\Forum\Libraries\Forum\Message\Message object by id. * * @param mixed $id The message id to be loaded * * @return boolean True on success * * @throws Exception * @since Kunena 6.0 */ public function load($id = null): bool { $exists = parent::load($id); $this->_hold = $exists ? $this->hold : 1; $this->_thread = $this->thread; return $exists; } /** * @return boolean * * @throws Exception * @throws null * @since Kunena 6.0 */ public function check(): bool { $author = KunenaUserHelper::get($this->userid); // Check username if (!$this->userid) { $this->name = trim($this->name); // Unregistered or anonymous users: Do not allow existing username $nicktaken = UserHelper::getUserId($this->name); if (empty($this->name) || $nicktaken) { $this->name = Text::_('COM_KUNENA_USERNAME_ANONYMOUS'); } } else { $this->name = $author->getName(); } if (!empty($this->email)) { // Check email address $this->email = trim($this->email); // Email address must be valid if (!MailHelper::isEmailAddress($this->email)) { throw new Exception(Text::sprintf('COM_KUNENA_LIB_MESSAGE_ERROR_EMAIL_INVALID')); } } elseif (!KunenaUserHelper::getMyself()->exists() && KunenaFactory::getConfig()->askEmail) { throw new Exception(Text::_('COM_KUNENA_LIB_MESSAGE_ERROR_EMAIL_EMPTY')); } // Do not allow no posting date or dates from the future $now = Factory::getDate()->toUnix(); if (!$this->time || $this->time > $now) { $this->time = $now; } // Do not allow identical posting times inside topic (simplifies logic) $topic = $this->getTopic(); if (!$this->exists() && $topic->exists() && $this->time <= $topic->last_post_time) { $this->time = $topic->last_post_time + 1; } if ($this->modified_time > $now) { $this->modified_time = $now; } if ($this->modified_time && $this->modified_time < $this->time) { $this->modified_time = $this->time; } if ($this->hold < 0 || $this->hold > 3) { throw new Exception(Text::_('COM_KUNENA_LIB_MESSAGE_ERROR_HOLD_INVALID')); } if ($this->modified_by !== null) { if (!$this->modified_by) { $this->modified_time = 0; $this->modified_reason = ''; } elseif (!$this->modified_time) { $this->modified_time = Factory::getDate()->toUnix(); } } // When the message is set to be deleted, set the deleted time to the deleted time if ($this->hold === 2) { $this->deleted_time = Factory::getDate()->toUnix(); } else { $this->deleted_time = 0; } // Flood protection $config = KunenaFactory::getConfig(); if ($config->floodProtection && !$this->getCategory()->isAuthorised('moderate') && !$this->exists()) { $query = $this->_db->createQuery(); $query->select('MAX(time)') ->from($this->_db->quoteName('#__kunena_messages')) ->where($this->_db->quoteName('ip') . ' = ' . $this->_db->quote($this->ip)); $this->_db->setQuery($query); try { $lastPostTime = $this->_db->loadResult(); } catch (ExecutionFailureException $e) { KunenaError::displayDatabaseError($e); return false; } if ($lastPostTime + $config->floodProtection > Factory::getDate()->toUnix()) { throw new Exception(Text::sprintf('COM_KUNENA_LIB_MESSAGE_ERROR_FLOOD', (int) $config->floodProtection)); } } if (!$this->exists() && !$this->getCategory()->isAuthorised('moderate')) { // Ignore identical messages (posted within 5 minutes) $duplicatetimewindow = Factory::getDate()->toUnix() - 5 * 60; $query = $this->_db->createQuery(); $query->select('m.id') ->from($this->_db->quoteName('#__kunena_messages', 'm')) ->innerJoin($this->_db->quoteName('#__kunena_messages_text', 't') . ' ON m.id = t.mesid') ->where($this->_db->quoteName('m.userid') . ' = ' . $this->_db->quote($this->userid)) ->andWhere($this->_db->quoteName('m.ip') . ' = ' . $this->_db->quote($this->ip)) ->andWhere($this->_db->quoteName('t.message') . ' = ' . $this->_db->quote($this->message)) ->andWhere($this->_db->quoteName('m.time') . ' >= ' . $this->_db->quote($duplicatetimewindow)); $this->_db->setQuery($query); try { $id = $this->_db->loadResult(); } catch (ExecutionFailureException $e) { KunenaError::displayDatabaseError($e); return false; } if ($id) { throw new Exception(Text::_('COM_KUNENA_POST_DUPLICATE_IGNORED')); } } return true; } /** * Get the substring * * @param string $string string * @param integer $start start * @param integer $length length * * @return string * * @since Kunena 5.0.2 */ public function getsubstr(string $string, int $start, int $length): string { $mbString = \extension_loaded('mbstring'); if ($mbString) { $title = mb_substr($string, $start, $length); } else { $title2 = substr($string, $start, $length); $title = preg_replace( '/[\x00-\x08\x10\x0B\x0C\x0E-\x19\x7F]' . '|[\x00-\x7F][\x80-\xBF]+' . '|([\xC0\xC1]|[\xF0-\xFF])[\x80-\xBF]*' . '|[\xC2-\xDF]((?![\x80-\xBF])|[\x80-\xBF]{2,})' . '|[\xE0-\xEF](([\x80-\xBF](?![\x80-\xBF]))|(?![\x80-\xBF]{2})|[\x80-\xBF]{3,})/S', '', $title2 ); } return $title; } /** * @param Mail $mail mail * @param int $subscription subscription * @param string $subject subject * @param string $url url * @param bool $once once * * @return void * * @throws Exception * @since Kunena 6.0 */ protected function attachEmailBody(Mail $mail, int $subscription, string $subject, string $url, bool $once): void { $layout = KunenaLayout::factory('Email/Subscription')->debug(false) ->set('mail', $mail) ->set('message', $this) ->set('messageUrl', $url) ->set('once', $once); try { $msg = trim($layout->render($subscription ? ['default'] : ['moderator'])); } catch (Exception $e) { // TODO: throw exception here } $mail->setBody($msg); } /** * @param KunenaUser $user user * * @return KunenaExceptionAuthorise|void * * @throws Exception * @since Kunena 6.0 */ protected function authoriseRead(KunenaUser $user) { if ($this->hold && !$user->exists()) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_NO_ACCESS'), 401); } // Check that user has the right to see the post (user can see his own unapproved posts) if ($this->hold > 1 || ($this->hold == 1 && $this->userid != $user->userid)) { $access = KunenaAccess::getInstance(); $hold = $access->getAllowedHold($user->userid, $this->catid, false); if (!\in_array($this->hold, $hold)) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_NO_ACCESS'), 403); } } return; } /** * @param KunenaUser $user user * * @return KunenaExceptionAuthorise|void * * @since Kunena 6.0 */ protected function authoriseNotHold(KunenaUser $user) { if ($this->hold) { // Nobody can reply to unapproved or deleted post return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_NO_ACCESS'), 403); } return; } /** * @param KunenaUser $user user * * @return KunenaExceptionAuthorise|void * * @throws Exception * @since Kunena 6.0 */ protected function authoriseOwn(KunenaUser $user) { // Guests cannot own posts. if (!$user->exists()) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_EDIT_NOT_ALLOWED'), 401); } // Check that topic owned by the user or user is a moderator // TODO: check #__kunena_user_topics if ($this->userid != $user->userid && !$user->isModerator($this->getCategory())) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_EDIT_NOT_ALLOWED'), 403); } return; } /** * @param KunenaUser $user user * * @return KunenaExceptionAuthorise|void * * @throws Exception * @since Kunena 6.0 */ protected function authoriseThankyou(KunenaUser $user) { // Check that message is not your own if (!KunenaFactory::getConfig()->showThankYou) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_THANKYOU_DISABLED'), 403); } if (!$user->userid) { // TODO: better error message return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_THANKYOU_DISABLED'), 401); } if (!$this->userid || $this->userid == $user->userid) { // TODO: better error message return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_THANKYOU_DISABLED'), 403); } return; } /** * This function check the edit time from the author of the post and return if the user is allowed to edit his post. * * @param KunenaUser $user user * * @return KunenaExceptionAuthorise|boolean|void * * @throws Exception * @since Kunena 6.0 */ protected function authoriseEditTime(KunenaUser $user) { // Do not perform rest of the checks to moderators and admins if ($user->isModerator($this->getCategory())) { return false; } // User is only allowed to edit post within time specified in the configuration $config = KunenaFactory::getConfig(); if (\intval($config->userEdit) != 1) { // Edit never allowed if (\intval($config->userEdit) == 0) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_EDIT_NOT_ALLOWED'), 403); } // Edit allowed if replies if (\intval($config->userEdit) == 2 && $this->getTopic()->getReplies()) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_EDIT_ALLOWED_IF_REPLIES'), 403); } // Edit allowed for the first message of the topic if (\intval($config->userEdit) == 4 && $this->id != $this->getTopic()->first_post_id) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_EDIT_ALLOWED_ONLY_FIRST_MESSAGE_OF_TOPIC'), 403); } // Edit allowed for the last message of the topic if (\intval($config->userEdit) == 3 && $this->id != $this->getTopic()->last_post_id) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_EDIT_ALLOWED_ONLY_LAST_MESSAGE_OF_TOPIC'), 403); } } if (\intval($config->userEditTime) != 0) { // Check whether edit is in time $modtime = $this->modified_time ? $this->modified_time : $this->time; if ($modtime + \intval($config->userEditTime) < Factory::getDate()->toUnix() && \intval($config->userEditTimeGrace) == 0) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_EDIT_NOT_ALLOWED'), 403); } elseif (\intval($config->userEditTimeGrace) != 0 && $modtime + \intval($config->userEditTime) + \intval($config->userEditTimeGrace) < Factory::getDate()->toUnix()) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_EDIT_NOT_ALLOWED'), 403); } } return; } /** * @param KunenaUser $user user * * @return KunenaExceptionAuthorise|void * * @throws Exception * @since Kunena 6.0 */ protected function authoriseDelete(KunenaUser $user) { $config = KunenaFactory::getConfig(); if (!$user->isModerator($this->getCategory()) && $config->userDeleteMessage != '2') { // Never if ($config->userDeleteMessage == '0') { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_ERROR_DELETE_REPLY_AFTER'), 403); } // When no replies if ($config->userDeleteMessage == '1' && ($this->getTopic()->first_post_id != $this->id || $this->getTopic()->getReplies())) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_ERROR_DELETE_REPLY_AFTER'), 403); } // All except the first message of the topic if ($config->userDeleteMessage == '3' && $this->id == $this->getTopic()->first_post_id) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_ERROR_DELETE_ONLY_FIRST_MESSAGE'), 403); } // Only the last message if ($config->userDeleteMessage == '4' && $this->id != $this->getTopic()->last_post_id) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_ERROR_DELETE_ONLY_LAST_MESSAGE'), 403); } } } /** * Check if user has the right to perm delete the message * * @param KunenaUser $user user * * @return KunenaExceptionAuthorise|bool|void * * @throws Exception * @since Kunena 6.0 */ protected function authorisePermdelete(KunenaUser $user) { $config = KunenaFactory::getConfig(); if ($user->isAdmin() || $user->isModerator()) { return false; } if ($user->isModerator($this->getTopic()->getCategory()) && !$config->moderatorPermDelete || !$user->isModerator($this->getTopic()->getCategory())) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_ERROR_DELETE_REPLY_AFTER'), 403); } return; } /** * Check if user has the right to upload image attachment * * @param KunenaUser $user user * * @return KunenaExceptionAuthorise|void * * @throws Exception * @since Kunena 6.0 */ protected function authoriseAttachmentsImage(KunenaUser $user) { if (empty(KunenaFactory::getConfig()->imageUpload)) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_ATTACHMENTS_NOT_ALLOWED'), 403); } if (KunenaFactory::getConfig()->imageUpload == 'admin') { if (!$user->isAdmin()) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_ATTACHMENTS_IMAGE_ONLY_FOR_ADMINISTRATORS'), 403); } } if (KunenaFactory::getConfig()->imageUpload == 'registered') { if (!$user->userid) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_ATTACHMENTS_IMAGE_ONLY_FOR_REGISTERED_USERS'), 403); } } if (KunenaFactory::getConfig()->imageUpload == 'moderator') { $category = $this->getCategory(); if (!$user->isModerator($category)) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_ATTACHMENTS_IMAGE_ONLY_FOR_MODERATORS'), 403); } } return; } /** * Check if user has the right to upload file attachment * * @param KunenaUser $user user * * @return KunenaExceptionAuthorise|void * * @throws Exception * @since Kunena 6.0 */ protected function authoriseAttachmentsFile(KunenaUser $user) { if (empty(KunenaFactory::getConfig()->fileUpload)) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_ATTACHMENTS_NOT_ALLOWED'), 403); } if (KunenaFactory::getConfig()->fileUpload == 'admin') { if (!$user->isAdmin()) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_ATTACHMENTS_FILE_ONLY_FOR_ADMINISTRATORS'), 403); } } if (KunenaFactory::getConfig()->fileUpload == 'registered') { if (!$user->userid) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_ATTACHMENTS_FILE_ONLY_FOR_REGISTERED_USERS'), 403); } } if (KunenaFactory::getConfig()->fileUpload == 'moderator') { $category = $this->getCategory(); if (!$user->isModerator($category)) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_ATTACHMENTS_FILE_ONLY_FOR_MODERATORS'), 403); } } return; } /** * @param KunenaUser $user user * * @return KunenaExceptionAuthorise|void * * @throws Exception * @since Kunena 6.0 */ protected function authoriseGuestWrite(KunenaUser $user) { // Check if user is guest and they can create or reply topics if ($user->userid == 0 && !KunenaFactory::getConfig()->pubWrite) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_ERROR_ANONYMOUS_FORBITTEN'), 401); } return; } /** * Get the table relevant properties. Override for your specific Object * * @return array Assocative array with the propertie values of table * * @since Kunena 6.4 */ protected function getTableProperties(): array { $properties = [ 'id' => $this->id, 'parent' => $this->parent, 'thread' => $this->thread, 'catid' => $this->catid, 'name' => $this->name, 'userid' => $this->userid, 'email' => $this->email, 'subject' => $this->subject, 'time' => $this->time, 'ip' => $this->ip, 'topic_emoticon' => $this->topic_emoticon, 'locked' => $this->locked, 'hold' => $this->hold, 'ordering' => $this->ordering, 'hits' => $this->hits, 'moved' => $this->moved, 'deleted_time' => $this->deleted_time, 'modified_by' => $this->modified_by, 'modified_time' => $this->modified_time, 'modified_reason' => $this->modified_reason, 'message' => $this->message ]; return $properties; } }
| ver. 1.1 | |
.
| PHP 8.4.18 | Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ñтраницы: 0 |
proxy
|
phpinfo
|
ÐаÑтройка