Файловый менеджер - Редактировать - /var/www/html/libraries/kunena/src/Forum/Topic/KunenaTopic.php
Ðазад
<?php /** * Kunena Component * * @package Kunena.Framework * @subpackage Forum.Topic * * @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\Topic; \defined('_JEXEC') or die(); use DateTime; use DateTimeZone; use Exception; use InvalidArgumentException; use Joomla\CMS\Application\SiteApplication; use Joomla\CMS\Date\Date; use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\Uri\Uri; use Joomla\Database\DatabaseDriver; use Joomla\Database\Exception\ExecutionFailureException; use Kunena\Forum\Libraries\Access\KunenaAccess; use Kunena\Forum\Libraries\Database\KunenaDatabaseObject; use Kunena\Forum\Libraries\Date\KunenaDate; 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\KunenaMessage; use Kunena\Forum\Libraries\Forum\Message\KunenaMessageHelper; use Kunena\Forum\Libraries\Forum\Message\Thankyou\KunenaMessageThankyouHelper; use Kunena\Forum\Libraries\Forum\Topic\Poll\KunenaPoll; use Kunena\Forum\Libraries\Forum\Topic\Poll\KunenaPollHelper; use Kunena\Forum\Libraries\Forum\Topic\Rate\KunenaRateHelper; use Kunena\Forum\Libraries\Forum\Topic\User\KunenaTopicUser; use Kunena\Forum\Libraries\Forum\Topic\User\KunenaTopicUserHelper; use Kunena\Forum\Libraries\Forum\Topic\User\Read\KunenaTopicUserReadHelper; use Kunena\Forum\Libraries\Html\KunenaParser; use Kunena\Forum\Libraries\Pagination\KunenaPagination; use Kunena\Forum\Libraries\Route\KunenaRoute; use Kunena\Forum\Libraries\User\KunenaUser; use Kunena\Forum\Libraries\User\KunenaUserHelper; use RuntimeException; /** * Class \Kunena\Forum\Libraries\Forum\Topic\Topic * * @property int $id * @property int $categoryId * @property string $subject * @property int $icon_id * @property int $locked * @property int $hold * @property int $ordering * @property int $posts * @property int $hits * @property int $attachments * @property int $poll_id * @property int $moved_id * @property int $first_post_id * @property int $first_post_time * @property int $first_post_userid * @property string $first_post_message * @property string $first_post_guest_name * @property int $last_post_id * @property int $last_post_time * @property int $last_post_userid * @property string $last_post_message * @property string $last_post_guest_name * @property string $params * @property int $rating * @property int $count * @since Kunena 6.0 */ class KunenaTopic extends KunenaDatabaseObject { /** * @var array * @since Kunena 6.0 */ protected static $actions = [ 'none' => [], 'read' => ['Read'], 'create' => ['NotExists', 'GuestWrite'], 'reply' => ['Read', 'NotHold', 'GuestWrite', 'NotMoved', 'Unlocked'], 'edit' => ['Read', 'NotMoved', 'Unlocked', 'Own'], 'move' => ['Read'], 'approve' => ['Read', 'NotMoved'], 'delete' => ['Read'], 'undelete' => ['Read'], 'permdelete' => ['Read', 'Permdelete'], 'favorite' => ['Read'], 'subscribe' => ['Read'], 'sticky' => ['Read'], 'lock' => ['Read'], 'rate' => ['Read', 'Unlocked'], 'poll.read' => ['Read', 'Poll'], 'poll.create' => ['Own'], 'poll.edit' => ['Read', 'NoVotes'], 'poll.delete' => ['Read', 'Own', 'Poll'], 'poll.vote' => ['Read', 'Poll', 'Vote'], 'post.read' => ['Read'], 'post.thankyou' => ['Read', 'NotMoved', 'Unlocked'], 'post.unthankyou' => ['Read', 'Unlocked'], 'post.reply' => ['Read', 'NotHold', 'GuestWrite', 'NotMoved', 'Unlocked'], 'post.edit' => ['Read', 'Unlocked'], 'post.move' => ['Read'], 'post.approve' => ['Read'], 'post.delete' => ['Read', 'Unlocked'], 'post.undelete' => ['Read'], 'post.permdelete' => ['Read', 'Permdelete'], 'post.attachment.read' => ['Read'], 'post.attachment.createimage' => ['Unlocked'], 'post.attachment.createfile' => ['Unlocked'], 'post.attachment.delete' => [], 'post.attachment.private' => [], // TODO: In the future we might want to restrict this: array('Read','Unlocked'), ]; /** * @var integer * @since Kunena 6.0 */ public $id = null; /** * @var integer * @since Kunena 6.0 */ public $unread = 0; /** * @var integer * @since Kunena 6.0 */ public $lastread = 0; /** * @var integer * @since Kunena 6.0 */ public $hold = 0; /** * @var integer * @since Kunena 6.0 */ public $posts = 0; /** * @var integer * @since Kunena 6.0 */ public $category_id = 0; /** * @var string * @since Kunena 6.4 */ public $subject; /** * @var string * @since Kunena 6.4 */ public $icon_id; /** * @var string * @since Kunena 6.4 */ public $label_id; /** * @var string * @since Kunena 6.4 */ public $locked; /** * @var string * @since Kunena 6.4 */ public $ordering; /** * @var string * @since Kunena 6.4 */ public $hits; /** * @var string * @since Kunena 6.4 */ public $attachments; /** * @var integer * @since Kunena 6.4 */ public $poll_id; /** * @var integer * @since Kunena 6.4 */ public $moved_id; /** * @var integer * @since Kunena 6.4 */ public $first_post_id; /** * @var string * @since Kunena 6.4 */ public $first_post_time; /** * @var integer * @since Kunena 6.4 */ public $first_post_userid; /** * @var string * @since Kunena 6.4 */ public $first_post_message; /** * @var string * @since Kunena 6.4 */ public $first_post_guest_name; /** * @var integer * @since Kunena 6.4 */ public $last_post_id; /** * @var string * @since Kunena 6.4 */ public $last_post_time; /** * @var integer * @since Kunena 6.4 */ public $last_post_userid; /** * @var string * @since Kunena 6.4 */ public $last_post_message; /** * @var string * @since Kunena 6.4 */ public $last_post_guest_name; /** * @var string * @since Kunena 6.4 */ public $rating; /** * @var string * @since Kunena 6.4 */ public $params; /** * @var string * @since Kunena 6.4 */ public $typeAlias; /** * @var integer * @since Kunena 6.4 */ public $categoryId; /** * @var string * @since Kunena 6.4 */ public $myposts; /** * @var integer * @since Kunena 6.4 */ public $my_last_post_id; /** * @var string * @since Kunena 6.4 */ public $favorite; /** * @var string * @since Kunena 6.4 */ public $title; /** * @var string * @since Kunena 6.4 */ public $titleName; /** * @var string * @since Kunena 6.4 */ public $titleCount; /** * @var string * @since Kunena 6.4 */ public $count; /** * @var string * @since Kunena 6.4 */ public $link; /** * @var string * @since Kunena 6.4 */ public $percent; /** * @var string * @since Kunena 6.4 */ public $avatar; /** * @var string * @since Kunena 6.0 */ protected $_table = 'KunenaTopics'; /** * @var DatabaseDriver|void * @since Kunena 6.0 */ protected $_db = null; /** * @var array * @since Kunena 6.0 */ protected $_authcache = []; /** * @var array * @since Kunena 6.0 */ protected $_authccache = []; /** * @var array * @since Kunena 6.0 */ protected $_authfcache = []; /** * @var integer * @since Kunena 6.0 */ protected $_hold = 1; /** * @var integer * @since Kunena 6.0 */ protected $_posts = 0; /** * @var null * @since Kunena 6.0 */ protected $_pagination = null; /** * @param mixed $properties properties * * @throws Exception * @since Kunena 6.0 * * @internal */ public function __construct($properties = null) { if (!empty($this->id)) { $this->_exists = true; $this->_hold = $this->hold; $this->_posts = $this->posts; } else { parent::__construct($properties); } $this->_db = Factory::getContainer()->get('DatabaseDriver'); } /** * Returns \Kunena\Forum\Libraries\Forum\Topic\Topic object. * * @param int $identifier The topic to load - Can be only an integer. * @param bool $reset reset * * @return KunenaTopic * * @throws Exception * @since Kunena 6.0 */ public static function getInstance($identifier = null, $reset = false): KunenaTopic { return KunenaTopicHelper::get($identifier, $reset); } /** * Subscribe / Unsubscribe user to this topic. * * @param int $value True for subscribe, false for unsubscribe. * @param mixed $user user * * @return boolean * * @throws Exception * @since Kunena 6.0 */ public function subscribe(int $value, $user = null): bool { $usertopic = $this->getUserTopic($user); $usertopic->subscribed = (int) $value; try { $usertopic->save(); } catch (Exception $e) { throw new Exception($e->getMessage()); } return true; } /** * @param mixed $user user * * @return KunenaTopicUser * * @throws Exception * @since Kunena 6.0 */ public function getUserTopic($user = null): KunenaTopicUser { return KunenaTopicUserHelper::get($this, $user); } /** * Favorite / unfavorite user to this topic. * * @param bool $value True for favorite, false for unfavorite. * @param mixed $user user * * @return boolean * * @throws Exception * @since Kunena 6.0 */ public function favorite($value = true, $user = null): bool { $usertopic = $this->getUserTopic($user); $usertopic->favorite = (int) $value; try { $usertopic->save(); } catch (Exception $e) { throw new Exception($e->getMessage()); } return true; } /** * @param int $value values * * @return boolean * * @throws Exception * @since Kunena 6.0 */ public function sticky($value = 1): bool { $this->ordering = (int) $value; return $this->save(); } /** * Method to save the \Kunena\Forum\Libraries\Forum\Topic\Topic object to the database. * * @param bool $cascade cascade * * @return boolean True on success. * * @throws Exception * @since Kunena 6.0 */ public function save($cascade = true): bool { $topicDelta = $this->delta(); $postDelta = $this->posts - $this->_posts; if (!parent::save()) { return false; } $this->_posts = $this->posts; // Clear authentication cache $this->_authfcache = $this->_authccache = $this->_authcache = []; if ($cascade) { $category = $this->getCategory(); try { $category->update($this, $topicDelta, $postDelta); } catch (Exception $e) { throw new Exception($e->getMessage()); } } return true; } /** * @return integer * * @since Kunena 6.0 */ protected function delta(): int { if (!$this->hold && $this->_hold) { // Create or publish topic return 1; } if ($this->hold && !$this->_hold) { // Delete or unpublish topic return -1; } return 0; } /** * @param null|bool $exists exists * * @return boolean * * @since Kunena 6.0 */ public function exists($exists = null): bool { if ($exists !== null) { $this->_hold = $this->hold; $this->_posts = $this->posts; } return parent::exists($exists); } /** * @return KunenaCategory * * @throws Exception * @since Kunena 6.0 */ public function getCategory(): KunenaCategory { return KunenaCategoryHelper::get($this->category_id); } /** * @return string * * @throws Exception * @since Kunena 6.0 */ public function getActions(): string { $txt = ''; if ($this->ordering) { $txt = $this->getCategory()->class_sfx ? $txt . '' : $txt . '-stickymsg'; } if ($this->hold == 1) { $txt .= ' unapproved'; } else { if ($this->hold) { $txt .= ' deleted'; } } if ($this->moved_id > 0) { $txt .= ' moved'; } if ($this->locked) { $txt .= ' locked'; } return $txt; } /** * @param int $value value * * @return boolean * * @throws Exception * @since Kunena 6.0 */ public function lock($value = 1): bool { $this->locked = (int) $value; return $this->save(); } /** * @param mixed $user user * @param bool|string $glue glue * * @return void * * @since Kunena 6.0 */ public function getKeywords($user = null, $glue = false): void {} /** * @param int $value value * * @return boolean * * @throws Exception * @since Kunena 6.0 */ public function publish($value = KunenaForum::PUBLISHED): bool { if ($value < 0 || $value > 3) { $value = 0; } $date = new Date(); $this->hold = (int) $value; if ($this->hold === 3) { $deletedTime = $date->toUnix(); } else { $deletedTime = 0; } $query = $this->_db->createQuery(); $query->update($this->_db->quoteName('#__kunena_messages')) ->set($this->_db->quoteName('hold') . ' = ' . $this->_db->quote($this->hold)) ->set($this->_db->quoteName('deleted_time') . ' = ' . $this->_db->quote($deletedTime)) ->where($this->_db->quoteName('thread') . ' = ' . (int) $this->id . ' AND ' . $this->_db->quoteName('hold') . ' = ' . $this->_db->quote($this->_hold)); $this->_db->setQuery($query); try { $this->_db->execute(); } catch (ExecutionFailureException $e) { KunenaError::displayDatabaseError($e); return false; } return $this->_db->getAffectedRows() ? $this->recount() : $this->save(); } /** * @return boolean * * @throws Exception * @since Kunena 6.0 */ public function recount(): bool { if (!$this->moved_id) { // Recount total posts and attachments $query = $this->_db->createQuery(); $query->select('COUNT(DISTINCT ' . $this->_db->quoteName('m.id') . ') AS ' . $this->_db->quoteName('posts') . ', COUNT(' . $this->_db->quoteName('a.id') . ') AS ' . $this->_db->quoteName('attachments')) ->from($this->_db->quoteName('#__kunena_messages', 'm')) ->leftJoin($this->_db->quoteName('#__kunena_attachments', 'a') . ' ON ' . $this->_db->quoteName('m.id') . ' = ' . $this->_db->quoteName('a.mesid')) ->where($this->_db->quoteName('m.hold') . ' = ' . $this->_db->quote($this->hold) . ' AND ' . $this->_db->quoteName('m.thread') . ' = ' . $this->_db->quote($this->id)) ->group($this->_db->quoteName('m.thread')); $this->_db->setQuery($query); try { $result = $this->_db->loadAssoc(); } catch (ExecutionFailureException $e) { KunenaError::displayDatabaseError($e); return false; } if (!$result) { $this->posts = 0; // Double check if all posts have been removed from the database $query = $this->_db->createQuery(); $query->select('COUNT(' . $this->_db->quoteName('m.id') . ') AS ' . $this->_db->quoteName('posts') . ', MIN(' . $this->_db->quoteName('m.hold') . ') AS ' . $this->_db->quoteName('hold')) ->from($this->_db->quoteName('#__kunena_messages', 'm')) ->where($this->_db->quoteName('m.thread') . ' = ' . $this->_db->quote($this->id)) ->group($this->_db->quoteName('m.thread')); $this->_db->setQuery($query); try { $result = $this->_db->loadAssoc(); } catch (ExecutionFailureException $e) { KunenaError::displayDatabaseError($e); return false; } if ($result) { // Information in the database was wrong, recount topic $this->hold = $result['hold']; $this->recount(); } return true; } $this->bind($result); } return $this->update(); } /** * @param KunenaMessage $message message * @param int $postdelta postdelta * * @return boolean * * @throws Exception * @since Kunena 6.0 */ public function update($message = null, $postdelta = 0): bool { // Update post count $this->posts += $postdelta; $exists = $message && $message->exists(); if (!$this->exists()) { if (!$exists) { throw new Exception(Text::_('COM_KUNENA_LIB_TOPIC_NOT_EXISTS')); } $this->id = $message->id; } if ($exists && $message->thread == $this->id && $message->hold == $this->hold) { // If message belongs into this topic and has same state, we may need to update cache $this->updatePostInfo($message->id, $message->time, $message->userid, $message->message, $message->name); } elseif (!$this->moved_id) { if (!isset($this->hold)) { $this->hold = KunenaForum::TOPIC_DELETED; } // If message isn't visible anymore, check if we need to update cache if (!$exists || $this->first_post_id == $message->id) { // If message got deleted and was cached, we need to find new first post $db = Factory::getContainer()->get('DatabaseDriver'); $query = $this->_db->createQuery(); $query->select('*') ->from($this->_db->quoteName('#__kunena_messages', 'm')) ->innerJoin($this->_db->quoteName('#__kunena_messages_text', 't') . ' ON ' . $this->_db->quoteName('t.mesid') . '=' . $this->_db->quoteName('m.id')) ->where($this->_db->quoteName('m.thread') . ' = ' . $db->quote($this->id) . ' AND ' . $this->_db->quoteName('m.hold') . ' = ' . $this->_db->quote($this->hold)) ->order($this->_db->quoteName('m.time') . ' ASC, ' . $this->_db->quoteName('m.id') . ' ASC'); $query->setLimit(1); $db->setQuery($query); try { $first = $db->loadObject(); } catch (ExecutionFailureException $e) { KunenaError::displayDatabaseError($e); } if ($first) { $this->first_post_time = 0; $this->updatePostInfo($first->id, $first->time, $first->userid, $first->message, $first->name); } else { $this->updatePostInfo(false); } } if (!$exists || $this->last_post_id == $message->id) { // If topic got deleted and was cached, we need to find new last post $db = Factory::getContainer()->get('DatabaseDriver'); $query = $this->_db->createQuery(); $query->select('*') ->from($this->_db->quoteName('#__kunena_messages', 'm')) ->innerJoin($this->_db->quoteName('#__kunena_messages_text', 't') . ' ON ' . $this->_db->quoteName('t.mesid') . ' = ' . $this->_db->quoteName('m.id')) ->where($this->_db->quoteName('m.thread') . ' = ' . $db->quote($this->id) . ' AND ' . $this->_db->quoteName('m.hold') . ' = ' . $this->_db->quote($this->hold)) ->order($this->_db->quoteName('m.time') . ' DESC, ' . $this->_db->quoteName('m.id') . ' DESC'); $query->setLimit(1); $db->setQuery($query); try { $last = $db->loadObject(); } catch (ExecutionFailureException $e) { KunenaError::displayDatabaseError($e); } if ($last) { $this->last_post_time = 0; $this->updatePostInfo($last->id, $last->time, $last->userid, $last->message, $last->name); } else { $this->updatePostInfo(false); } } } if (!$this->first_post_id || !$this->last_post_id) { // If topic has no visible posts, mark it deleted and recount $this->hold = $exists ? $message->hold : KunenaForum::TOPIC_DELETED; $this->recount(); } if (!($message && $message->exists()) && !$this->posts) { return $this->delete(); } if (!$this->save()) { return false; } if ($exists && $message->userid && abs($postdelta) <= 1) { // Update user topic $usertopic = $this->getUserTopic($message->userid); try { $usertopic->update($message, $postdelta); } catch (Exception $e) { throw new Exception($e->getMessage()); } // Update post count from user $user = KunenaUserHelper::get($message->userid); $user->posts += $postdelta; try { $user->save(); } catch (Exception $e) { throw new Exception($e->getMessage()); } } else { KunenaTopicUserHelper::recount($this->id); // FIXME: optimize KunenaUserHelper::recount(); } return true; } /** * @param int $id id * @param int $time time * @param int $userid userid * @param string $message message * @param string $name name * * @return void * * @since Kunena 6.0 */ public function updatePostInfo($id, $time = 0, $userid = 0, $message = '', $name = ''): void { if ($id === false) { $this->first_post_id = 0; $this->first_post_time = 0; $this->first_post_userid = 0; $this->first_post_message = ''; $this->first_post_guest_name = ''; $this->last_post_id = 0; $this->last_post_time = 0; $this->last_post_userid = 0; $this->last_post_message = ''; $this->last_post_guest_name = ''; return; } if (!$this->first_post_time || ($this->first_post_time > $time || ($this->first_post_time == $time && $this->first_post_id >= $id))) { $this->first_post_id = $id; $this->first_post_time = $time; $this->first_post_userid = $userid; $this->first_post_message = $message; $this->first_post_guest_name = $name; } if ($this->last_post_time < $time || ($this->last_post_time == $time && $this->last_post_id <= $id)) { $this->last_post_id = $id; $this->last_post_time = $time; $this->last_post_userid = $userid; $this->last_post_message = $message; $this->last_post_guest_name = $name; } } /** * Method to delete the \Kunena\Forum\Libraries\Forum\Topic\Topic object from the database. * * @param bool $recount recount * * @return boolean True on success. * * @throws Exception * @since Kunena 6.0 */ public function delete($recount = true): bool { if (!$this->exists()) { return true; } if (!parent::delete()) { return false; } // Clear authentication cache $this->_authfcache = $this->_authccache = $this->_authcache = []; // NOTE: shadow topic doesn't exist, DO NOT DELETE OR CHANGE ANY EXTERNAL INFORMATION if ($this->moved_id == 0) { $db = Factory::getContainer()->get('DatabaseDriver'); // Delete user topics $queries[] = "DELETE FROM #__kunena_user_topics WHERE topic_id={$db->quote($this->id)}"; // Delete user read $queries[] = "DELETE FROM #__kunena_user_read WHERE topic_id={$db->quote($this->id)}"; if ($this->poll_id) { // Delete poll (users) $queries[] = "DELETE FROM #__kunena_polls_users WHERE pollid={$db->quote($this->poll_id)}"; // Delete poll (options) $queries[] = "DELETE FROM #__kunena_polls_options WHERE pollid={$db->quote($this->poll_id)}"; // Delete poll $queries[] = "DELETE FROM #__kunena_polls WHERE id={$db->quote($this->poll_id)}"; } // Delete thank yous $queries[] = "DELETE t FROM #__kunena_thankyou AS t INNER JOIN #__kunena_messages AS m ON m.id=t.postid WHERE m.thread={$db->quote($this->id)}"; // Delete all messages $queries[] = "DELETE m, t FROM #__kunena_messages AS m INNER JOIN #__kunena_messages_text AS t ON m.id=t.mesid WHERE m.thread={$db->quote($this->id)}"; // Delete rating $queries[] = "DELETE FROM #__kunena_rate WHERE topic_id={$db->quote($this->id)}"; foreach ($queries as $query) { $db->setQuery($query); try { $db->execute(); } catch (ExecutionFailureException $e) { KunenaError::displayDatabaseError($e); return false; } } // FIXME: add recount statistics if ($recount) { KunenaUserHelper::recount(); KunenaMessageThankyouHelper::recount(); } } return true; } /** * Send email notifications from the first post in the topic. * * @param null|string $url url * @param bool $approved * * @return void * * @throws Exception * @since Kunena 6.0 */ public function sendNotification($url = null, $approved = false): void { // Reload message just in case if it was published by bulk update. KunenaMessageHelper::get($this->first_post_id, true)->sendNotification($url, $approved); } /** * @return KunenaUser * * @throws Exception * @since Kunena 6.0 */ public function getAuthor(): KunenaUser { return KunenaUserHelper::getAuthor($this->first_post_userid, $this->first_post_guest_name); } /** * @return integer * * @since Kunena 6.0 */ public function getHits(): int { return $this->hits; } /** * Increase hit counter for this topic. * * @return void * * @throws Exception * @since Kunena 6.0 */ public function hit(): void { $app = Factory::getApplication(); $lasthit = $app->getUserState('com_kunena.topic.lasthit'); if ($lasthit == $this->id) { return; } // Update only hit - not entire object $table = $this->getTable(); $table->id = $this->id; if ($table->hit()) { $this->hits++; $app->setUserState('com_kunena.topic.lasthit', $this->id); } } /** * @param int $limitstart Null if all pages need to be active. * @param int $limit limit * @param int $display display * @param string $prefix prefix * * @return \Kunena\Forum\Libraries\Pagination\KunenaPagination|null * * @since Kunena 6.0 * @throws \Exception */ public function getPagination($limitstart = 0, $limit = 6, $display = 4, $prefix = ''): ?KunenaPagination { if (!$this->_pagination) { $this->_pagination = new KunenaPagination($this->posts, $limitstart, $limit, $prefix); $this->_pagination ->setUri($this->getUri()) ->setDisplayedPages($display); if ($limitstart == null) { $this->_pagination->pagesCurrent = 0; } } return $this->_pagination; } /** * @param mixed $category category * @param KunenaMessage|string|null $action action * @param int $itemid itemid * * @return \Joomla\CMS\Uri\Uri * * @throws \Exception * @since Kunena 6.0 */ public function getUri($category = null, $action = null, $Itemid = 0): Uri { $category = $category ? KunenaCategoryHelper::get($category) : $this->getCategory(); if ($Itemid == 0) { $Itemid = KunenaRoute::getCategoryItemid($category); } if ($action instanceof KunenaMessage) { $message = $action; $action = 'post' . $message->id; } $uri = Uri::getInstance("index.php?option=com_kunena&view=topic&catid={$category->id}&id={$this->id}&action={$action}&Itemid={$Itemid}"); if ($uri->getVar('action') !== null) { $uri->delVar('action'); $mesid = 0; $limit = max(1, \intval(KunenaFactory::getConfig()->messagesPerPage)); if (isset($message)) { $mesid = $message->id; } elseif ((string) $action === (string) (int) $action) { if ($action > 0) { $uri->setVar('limitstart', $action * $limit); } } else { switch ($action) { case 'first': $mesid = $this->first_post_id; break; case 'last': $mesid = $this->last_post_id; break; case 'unread': // Special case, improves caching $uri->setVar('layout', 'unread'); // $mesid = $this->lastread ? $this->lastread : $this->last_post_id; break; } } if ($mesid) { $uri->setFragment($mesid); $limitstart = \intval($this->getPostLocation($mesid) / $limit) * $limit; if ($limitstart) { $uri->setVar('limitstart', $limitstart); } } } return $uri; } /** * @param int $mesid mesid * @param string|null $direction direction * @param mixed $hold hold * * @return integer * * @throws Exception * @since Kunena 6.0 */ public function getPostLocation(int $mesid, $direction = null, $hold = null): int { if (\is_null($direction)) { $direction = KunenaUserHelper::getMyself()->getMessageOrdering(); } if (!isset($this->lastread)) { $this->lastread = $this->last_post_id; $this->unread = 0; } if ($mesid == 'unread') { $mesid = $this->lastread; } if ($this->moved_id || !KunenaUserHelper::getMyself()->isModerator($this->getCategory())) { if ($mesid == 'first' || $mesid == $this->first_post_id) { return $direction == 'asc' ? 0 : $this->posts - 1; } if ($mesid == 'last' || $mesid == $this->last_post_id) { return $direction == 'asc' ? $this->posts - 1 : 0; } if ($mesid == $this->unread) { return $direction == 'asc' ? $this->posts - max($this->unread, 1) : 0; } } if ($mesid == 'first') { $direction = ($direction == 'asc' ? 0 : 'both'); } if ($mesid == 'last') { $direction = ($direction == 'asc' ? 'both' : 0); } return KunenaMessageHelper::getLocation($mesid, $direction, $hold); } /** * @param mixed $user user * * @return KunenaTopicUser * * @throws Exception * @since Kunena 6.0 */ public function getUserInfo($user = null): KunenaTopicUser { return KunenaTopicUserHelper::get($this->id, $user); } /** * @return KunenaUser * * @throws Exception * @since Kunena 6.0 */ public function getFirstPostAuthor(): KunenaUser { return KunenaUserHelper::getAuthor($this->first_post_userid, $this->first_post_guest_name); } /** * @return KunenaUser * * @throws Exception * @since Kunena 6.0 */ public function getLastPostAuthor(): KunenaUser { return KunenaUserHelper::getAuthor($this->last_post_userid, $this->last_post_guest_name); } /** * @return KunenaDate * * @since Kunena 6.0 */ public function getFirstPostTime(): KunenaDate { return new KunenaDate($this->first_post_time); } /** * @return KunenaDate * * @since Kunena 6.0 */ public function getLastPostTime(): KunenaDate { return new KunenaDate($this->last_post_time); } /** * Resolve/get current topic. * * @return KunenaTopic Returns this topic or move target if this was moved. * * @throws Exception * @since Kunena 4.0 */ public function getTopic(): KunenaTopic { $ids = []; $topic = $this; // If topic has been moved, find the new topic while ($topic->moved_id) { if (isset($ids[$topic->moved_id])) { throw new RuntimeException(Text::_('COM_KUNENA_VIEW_TOPIC_ERROR_LOOP'), 500); } $ids[$topic->moved_id] = 1; $topic = KunenaTopicHelper::get($topic->moved_id); } return $topic; } /** * @param string $field field * * @return integer|string * * @throws Exception * @since Kunena 6.0 */ public function displayField(string $field) { switch ($field) { case 'id': return \intval($this->id); case 'subject': return KunenaParser::parseText($this->subject); } return ''; } /** * @param string $category_icon icon * * @return string * * @throws Exception * @since Kunena 6.0 */ public function getIcon($category_icon = ''): string { return KunenaFactory::getTemplate()->getTopicIcon($this); } /** * @param mixed $hold hold * * @return integer * * @throws Exception * @since Kunena 6.0 */ public function getReplies($hold = null): int { return (int) max($this->getTotal($hold) - 1, 0); } /** * @param mixed $hold hold * * @return integer * * @throws Exception * @since Kunena 6.0 */ public function getTotal($hold = null): int { if ($this->moved_id || !KunenaUserHelper::getMyself()->isModerator($this->getCategory())) { return (int) max($this->posts, 0); } return KunenaMessageHelper::getLocation($this->last_post_id, 'both', $hold) + 1; } /** * 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 KunenaCategory $category category * @param bool $xhtml xhtml * @param string $action action * * @return boolean * * @throws null * @throws Exception * @since Kunena 6.0 */ public function getPermaUrl($category = null, $xhtml = true, $action = null) { return $this->getUrl($category, $xhtml, $action); } /** * @param mixed $category category * @param bool $xhtml xhtml * @param KunenaMessage|null $action action * @param int $itemid itemid * * @return boolean * * @throws null * @throws Exception * @since Kunena 6.0 */ public function getUrl($category = null, $xhtml = true, $action = null, $itemid = 0) { return KunenaRoute::getTopicUrl( $this, $xhtml, $action, $category ? KunenaCategoryHelper::get($category) : $this->getCategory(), $itemid ); } /** * 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 array|bool $fields fields * @param mixed $user user * @param array|void $safefields safefields * * @return KunenaMessage * * @throws null * @since Kunena 6.0 */ public function newReply($fields = [], $user = null, $safefields = null): KunenaMessage { $user = KunenaUserHelper::get($user); $category = $this->getCategory(); $message = new KunenaMessage(); $message->setTopic($this); $message->parent = $this->first_post_id; $message->thread = $this->id; $message->catid = $this->category_id; $message->name = $user->getName(''); $message->userid = $user->userid; $message->subject = $this->subject; $message->ip = !empty(KunenaUserHelper::getUserIp()) ? KunenaUserHelper::getUserIp() : ''; if ($this->hold) { // If topic was unapproved or deleted, use the same state for the new message $message->hold = $this->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 === true) { $user = KunenaUserHelper::get($this->first_post_userid); $text = preg_replace('/\[confidential\](.*?)\[\/confidential\]/su', '', $this->first_post_message); $message->message = "[quote=\"{$user->getName($this->first_post_guest_name)}\" post={$this->first_post_id}]" . $text . "[/quote]"; } else { if ($safefields) { $message->bind($safefields); } if ($fields) { $message->bind($fields, ['name', 'email', 'subject', 'message'], true); } } return $message; } /** * @param mixed $user user * * @return boolean * * @throws Exception * @since Kunena 6.0 */ public function hasNew($user = null): bool { $user = KunenaUserHelper::get($user); if (!KunenaFactory::getConfig()->showNew || !$user->exists()) { return false; } $session = KunenaFactory::getSession(); if ($this->last_post_time <= $session->getAllReadTime()) { return false; } $userinfo = KunenaCategoryUserHelper::get($this->getCategory(), $user); if ($userinfo->allreadtime && $this->last_post_time <= $userinfo->allreadtime) { return false; } $read = KunenaTopicUserReadHelper::get($this, $user); if ($this->last_post_time <= $read->time) { return false; } return true; } /** * @param mixed $user user * * @return boolean * * @throws Exception * @since Kunena 6.0 */ public function markRead($user = null): bool { $user = KunenaUserHelper::get($user); if (!KunenaFactory::getConfig()->showNew || !$user->exists() || Factory::getApplication()->getIdentity()->guest) { return false; } $read = KunenaTopicUserReadHelper::get($this, $user); $read->time = Factory::getDate()->toUnix(); $read->message_id = $this->last_post_id; $read->save(); return true; } /** * 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($action = 'read', ?KunenaUser $user = null): bool { 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 throw * * @return boolean * * @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->_authccache[$user->userid][$action])) { $this->_authccache[$user->userid][$action] = $this->getCategory()->tryAuthorise('topic.' . $action, $user, false); } $this->_authcache[$user->userid][$action] = $this->_authccache[$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; } /** * Method to load a \Kunena\Forum\Libraries\Forum\Topic\Topic object by id. * * @param int|null $id The topic 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 = $this->hold === null ? 1 : $this->hold; $this->_posts = $this->posts; return $exists; } /** * Move topic or parts of it into another category or topic. * * @param object $target Target \Kunena\Forum\Libraries\Forum\Category\Category or * \Kunena\Forum\Libraries\Forum\Topic\Topic * @param mixed $ids false, array of message Ids or Joomla\CMS\Date\Date * @param bool $shadow Leave visible shadow topic. * @param string $subject New subject * @param bool $subjectall Change subject from every message * @param int|null $topic_iconid Define a new topic icon * @param int $keep_poll Define if you want keep the poll to the original topic or to the split topic * * @return boolean|KunenaCategory|KunenaTopic Target \Kunena\Forum\Libraries\Forum\Category\Category or * \Kunena\Forum\Libraries\Forum\Topic\Topic or false on failure * @throws Exception * @since Kunena 6.0 */ public function move(object $target, $ids = false, $shadow = false, $subject = '', $subjectall = false, $topic_iconid = null, $keep_poll = 0) { // Warning: logic in this function is very complicated and even with full understanding its easy to miss some details! // Clear authentication cache $this->_authfcache = $this->_authccache = $this->_authcache = []; // Cleanup input if (!($ids instanceof Date)) { if (!\is_array($ids)) { $ids = explode(',', (string) $ids); } $mesids = []; foreach ($ids as $id) { $mesids[(int) $id] = (int) $id; } unset($mesids[0]); $ids = implode(',', $mesids); } $subject = (string) $subject; // First we need to check if there will be messages left in the old topic if ($ids) { $query = $this->_db->createQuery(); $query->select('COUNT(*)') ->from($this->_db->quoteName('#__kunena_messages')) ->where($this->_db->quoteName('thread') . ' = ' . $this->_db->quote($this->id)); if ($ids instanceof Date) { // All older messages will remain (including unapproved, deleted) $query->where($this->_db->quoteName('time') . ' < ' . $this->_db->quote($ids->toUnix())); } else { // All messages that were not selected will remain $query->where($this->_db->quoteName('id') . ' NOT IN (' . $ids . ')'); } $this->_db->setQuery($query); try { $oldcount = (int) $this->_db->loadResult(); } catch (RuntimeException $e) { $app = Factory::getApplication(); $app->enqueueMessage($e->getMessage(), 'error'); } // So are we moving the whole topic? if (!$oldcount) { $ids = ''; } } $categoryFrom = $this->getCategory(); // Find out where we are moving the messages if (!$target || !$target->exists()) { throw new Exception(Text::sprintf('COM_KUNENA_MODERATION_ERROR_NO_TARGET', $this->id)); } elseif ($target instanceof KunenaTopic) { // Move messages into another topic (original topic will always remain, either as real one or shadow) if ($target == $this) { // We cannot move topic into itself throw new Exception(Text::sprintf('COM_KUNENA_MODERATION_ERROR_SAME_TARGET_THREAD', $this->id, $this->id)); } if ($this->moved_id) { // Moved topic cannot be merged with another topic -- it has no posts to be moved throw new Exception(Text::sprintf('COM_KUNENA_MODERATION_ERROR_ALREADY_SHADOW', $this->id)); } if ($this->poll_id && $target->poll_id) { // We cannot currently have 2 polls in one topic -- fail throw new Exception(Text::_('COM_KUNENA_MODERATION_CANNOT_MOVE_TOPIC_WITH_POLL_INTO_ANOTHER_WITH_POLL')); } if ($subjectall) { $subject = $target->subject; } } elseif ($target instanceof KunenaCategory) { // Move messages into category if ($target->isSection()) { // Section cannot have any topics throw new Exception(Text::_('COM_KUNENA_MODERATION_ERROR_NOT_MOVE_SECTION')); } // Save category information for later use $categoryTarget = $target; if ($this->moved_id) { // Move shadow topic and we are done $this->category_id = $categoryTarget->id; if ($subject) { $this->subject = $subject; } $this->save(false); return $target; } if ($shadow || $ids) { // Create new topic for the moved messages $target = clone $this; $target->exists(false); $target->id = 0; $target->hits = 0; $target->params = ''; } else { // If we just move into another category, we can keep using the old topic $target = $this; } // Did user want to change the subject? if ($subject) { $target->subject = $subject; } // Did user want to change the topic icon? if ($topic_iconid !== null) { $target->icon_id = $topic_iconid; } // Did user want to change category? $target->category_id = $categoryTarget->id; } else { throw new Exception(Text::_('COM_KUNENA_MODERATION_ERROR_WRONG_TARGET')); } // For now on we assume that at least one message will be moved (=authorization check was called on topic/message) // We will soon need target topic id, so save if it doesn't exist if (!$target->exists()) { try { $target->save(false); } catch (Exception $e) { throw new Exception($e->getMessage()); } } // Move messages (set new category and topic) $query = $this->_db->createQuery(); $query->update($this->_db->quoteName('#__kunena_messages')) ->set($this->_db->quoteName('catid') . ' = ' . $this->_db->quote($target->category_id)) ->set($this->_db->quoteName('thread') . ' = ' . $this->_db->quote($target->id)) ->where($this->_db->quoteName('thread') . ' = ' . $this->_db->quote($this->id)); // Did we want to change subject from all the messages? if ($subjectall && !empty($subject)) { $query->set($this->_db->quoteName('subject') . ' = ' . $this->_db->quote($subject)); } if ($ids instanceof Date) { // Move all newer messages (includes unapproved, deleted messages) $query->where($this->_db->quoteName('time') . ' >= ' . $this->_db->quote($ids->toUnix())); } elseif ($ids) { // Move individual messages $query->where($this->_db->quoteName('id') . ' IN (' . $ids . ')'); } $this->_db->setQuery($query); try { $this->_db->execute(); } catch (RuntimeException $e) { $app = Factory::getApplication(); $app->enqueueMessage($query, 'error'); } // Make sure that all messages in topic have unique time (deterministic without ORDER BY time, id) $query = "SET @ktime:=0"; $this->_db->setQuery($query); try { $this->_db->execute(); } catch (RuntimeException $e) { $app = Factory::getApplication(); $app->enqueueMessage($e->getMessage(), 'error'); } $query = 'UPDATE ' . $this->_db->quoteName('#__kunena_messages') . ' SET ' . $this->_db->quoteName('time') . ' = IF(time <= @ktime,@ktime:=@ktime+1,@ktime:=time) WHERE thread=' . $target->id . ' ORDER BY time ASC, id ASC'; $this->_db->setQuery($query); try { $this->_db->execute(); } catch (RuntimeException $e) { $app = Factory::getApplication(); $app->enqueueMessage($e->getMessage(), 'error'); } if ($keep_poll) { $target->poll_id = 0; } else { // If all messages were moved into another topic, we need to move poll as well if ($this->poll_id && !$ids && $target != $this) { // Note: We may already have saved cloned target (having poll_id already in there) $target->poll_id = $this->poll_id; // Note: Do not remove poll from shadow: information could still be used to show icon etc $query = $this->_db->createQuery(); $query->update($this->_db->quoteName('#__kunena_polls')) ->set($this->_db->quoteName('threadid') . ' = ' . $this->_db->quote($target->id)) ->where($this->_db->quoteName('threadid') . ' = ' . $this->_db->quote($this->id)); $this->_db->setQuery($query); try { $this->_db->execute(); } catch (RuntimeException $e) { $app = Factory::getApplication(); $app->enqueueMessage($e->getMessage(), 'error'); } } // When moving only first message keep poll only on target topic if ($this->poll_id && $target != $this && $ids) { if ($ids && $this->first_post_id) { $this->poll_id = 0; } } } if (!$ids && $target != $this) { // Leave shadow from old topic $this->moved_id = $target->id; if (!$shadow) { // Mark shadow topic as deleted $this->hold = 2; } } // Note: We already saved possible target earlier, now save only $this if (!$this->save(false)) { return false; } if (!$ids && !empty($categoryTarget)) { // Move topic into another category // Update user topic information (topic, category) KunenaTopicUserHelper::move($this, $target); // TODO: do we need this? // \Kunena\Forum\Libraries\Forum\Topic\\Kunena\Forum\Libraries\Forum\Topic\User\Read\Helper::move($this, $target); // Remove topic and posts from the old category $categoryFrom->update($this, -1, -$this->posts); // Add topic and posts into the new category $categoryTarget->update($target, 1, $this->posts); } elseif (!$ids) { // Moving topic into another topic // Add new posts, hits and attachments into the target topic $target->posts += $this->posts; $target->hits += $this->hits; $target->attachments += $this->attachments; // Update first and last post information into the target topic $target->updatePostInfo( $this->first_post_id, $this->first_post_time, $this->first_post_userid, $this->first_post_message, $this->first_post_guest_name ); $target->updatePostInfo( $this->last_post_id, $this->last_post_time, $this->last_post_userid, $this->last_post_message, $this->last_post_guest_name ); // Save target topic try { $target->save(false); } catch (Exception $e) { throw new Exception($e->getMessage()); } // Update user topic information (topic, category) KunenaTopicUserHelper::merge($this, $target); // TODO: do we need this? // \Kunena\Forum\Libraries\Forum\Topic\\Kunena\Forum\Libraries\Forum\Topic\User\Read\Helper::merge($this, $target); // Remove topic and posts from the old category $this->getCategory()->update($this, -1, -$this->posts); // Add posts into the new category $target->getCategory()->update($target, 0, $this->posts); } else { // Both topics have changed and we have no idea how much: force full recount // TODO: we can do this faster.. $this->recount(); $target->recount(); } return $target; } /** * Method to put the \Kunena\Forum\Libraries\Forum\Topic\Topic object on trash this is still present in database. * * @return boolean True on success. * * @throws Exception * @since Kunena 6.0 */ public function trash(): bool { if (!$this->exists()) { return true; } // Clear authentication cache $this->_authfcache = $this->_authccache = $this->_authcache = []; $db = Factory::getContainer()->get('DatabaseDriver'); $queries[] = "UPDATE #__kunena_messages SET hold='2' WHERE thread={$db->quote($this->id)}"; $queries[] = "UPDATE #__kunena_topics SET hold='2' WHERE id={$db->quote($this->id)}"; foreach ($queries as $query) { $db->setQuery($query); try { $this->_db->execute(); } catch (ExecutionFailureException $e) { KunenaError::displayDatabaseError($e); return false; } } return true; } /** * @return boolean * * @throws Exception * @since Kunena 6.0 */ public function resetvotes(): bool { if (!$this->poll_id) { return false; } $query = $this->_db->createQuery(); $query->update($this->_db->quoteName('#__kunena_polls_options')) ->set($this->_db->quoteName('votes') . ' = 0') ->where($this->_db->quoteName('pollid') . ' = ' . $this->_db->quote($this->poll_id)); $this->_db->setQuery($query); try { $this->_db->execute(); } catch (ExecutionFailureException $e) { KunenaError::displayDatabaseError($e); return false; } $query = $this->_db->createQuery(); $query->delete($this->_db->quoteName('#__kunena_polls_users')) ->where($this->_db->quoteName('pollid') . ' = ' . $this->_db->quote($this->poll_id)); $this->_db->setQuery($query); try { $this->_db->execute(); } catch (ExecutionFailureException $e) { KunenaError::displayDatabaseError($e); return false; } return true; } /** * Return the number of rating given to the topic * * @return integer * * @since Kunena 5.1.3 */ public function getReviewCount(): int { return KunenaRateHelper::getCount($this->id); } /** * @param KunenaUser $user user * * @return KunenaExceptionAuthorise|void * * @since Kunena 6.0 */ protected function authoriseNotExists(KunenaUser $user) { // Check that topic does not exist if ($this->_exists) { 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 authoriseRead(KunenaUser $user) { // Check that user can read topic if (!$this->exists()) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_NO_ACCESS'), 404); } // TODO: Allow owner to see his posts. if ($this->hold) { if (!$user->exists()) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_NO_ACCESS'), 401); } $access = KunenaAccess::getInstance(); $hold = $access->getAllowedHold($user->userid, $this->category_id, 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) { // Check that topic is not unapproved or deleted if ($this->hold) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_NO_ACCESS'), 403); } return; } /** * @param KunenaUser $user user * * @return KunenaExceptionAuthorise|void * * @since Kunena 6.0 */ protected function authoriseNotMoved(KunenaUser $user) { // Check that topic is not moved if ($this->moved_id) { 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 authoriseUnlocked(KunenaUser $user) { // Check that topic is not locked or user is a moderator if ($this->locked && !$user->isModerator($this->getCategory())) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_ERROR_TOPIC_LOCKED'), 403); } return; } /** * @param KunenaUser $user user * * @return KunenaExceptionAuthorise|void * * @throws Exception * @since Kunena 6.0 */ protected function authoriseOwn(KunenaUser $user) { // Guests cannot own a topic. if (!$user->exists()) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_NOT_MODERATOR'), 401); } // Check that topic owned by the user or user is a moderator $usertopic = $this->getUserTopic($user); if (!$usertopic->owner && !$user->isModerator($this->getCategory())) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_NOT_MODERATOR'), 403); } return; } /** * @param KunenaUser $user user * * @return KunenaExceptionAuthorise|void * * @throws Exception * @since Kunena 6.0 */ protected function authorisePoll(KunenaUser $user) { // Check that user can vote $poll = $this->getPoll(); if (!$poll->exists()) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_LIB_TOPIC_AUTHORISE_FAILED_NO_POLL'), 404); } return; } /** * @return KunenaPoll * * @throws Exception * @since Kunena 6.0 */ public function getPoll() { $poll = KunenaPollHelper::get($this->poll_id); $poll->threadid = $this->id; return $poll; } /** * @param KunenaUser $user user * * @return KunenaExceptionAuthorise|void * * @throws Exception * @since Kunena 6.0 */ protected function authoriseVote(KunenaUser $user) { // Check that user can vote $config = KunenaFactory::getConfig(); $poll = $this->getPoll(); $votes = $poll->getMyVotes($user); if (!$config->pollAllowVoteOne && $votes) { $time_zone = Factory::getContainer()->get(SiteApplication::class)->get('offset'); $objTimeZone = new DateTimeZone($time_zone); // Check the time between two votes $date_a = new DateTime($poll->getMyTime(), $objTimeZone); $date_b = new DateTime('now', $objTimeZone); $interval = date_diff($date_a, $date_b); if ($interval->format('%H:%I:%S') < $config->pollTimeBtVotes) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_TOPIC_VOTE_NEED_TO_WAIT_BEFORE_TO_CHANGE_VOTE'), 403); } } if ($votes && $config->pollAllowVoteOne) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_LIB_TOPIC_AUTHORISE_FAILED_VOTE_ONLY_ONCE'), 403); } if ($votes >= $config->pollNbVotesByUser && $config->pollAllowVoteOne) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_LIB_TOPIC_AUTHORISE_FAILED_VOTE_TOO_MANY_TIMES'), 403); } if ($config->pollTimeBtVotes && (int) $poll->getMyTime($user) + (int) $config->pollTimeBtVotes > Factory::getDate()->toUnix()) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_LIB_TOPIC_AUTHORISE_FAILED_VOTE_TOO_EARLY'), 403); } if ($this->locked) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_LIB_TOPIC_AUTHORISE_FAILED_VOTE_POLL_TOPIC_LOCKED'), 403); } if ($poll->polltimetolive != '1000-01-01 00:00:00' && $poll->getTimeToLive() < Factory::getDate()->toUnix()) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_LIB_TOPIC_AUTHORISE_FAILED_VOTE_POLL_EXPIRED'), 403); } return; } /** * @param KunenaUser $user user * * @return KunenaExceptionAuthorise|void * * @throws Exception * @since Kunena 6.0 */ protected function authoriseNoVotes(KunenaUser $user) { $poll = $this->getPoll(); $config = KunenaFactory::getConfig(); if ($poll->exists() && $poll->getUserCount() && !$config->allowUserEditPoll) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_LIB_TOPIC_AUTHORISE_FAILED_ONGOING_POLL'), 403); } return; } /** * Check if user has the right to perm delete the message * * @param KunenaUser $user user * * @return KunenaExceptionAuthorise|bool * * @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->getCategory()) && !$config->moderatorPermDelete || !$user->isModerator($this->getCategory())) { return new KunenaExceptionAuthorise(Text::_('COM_KUNENA_POST_ERROR_DELETE_REPLY_AFTER'), 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, 'category_id' => $this->category_id, 'subject' => $this->subject, 'icon_id' => $this->icon_id, 'label_id' => $this->label_id, 'locked' => $this->locked, 'hold' => $this->hold, 'ordering' => $this->ordering, 'posts' => $this->posts, 'hits' => $this->hits, 'attachments' => $this->attachments, 'poll_id' => $this->poll_id, 'moved_id' => $this->moved_id, 'first_post_id' => $this->first_post_id, 'first_post_time' => $this->first_post_time, 'first_post_userid' => $this->first_post_userid, 'first_post_message' => $this->first_post_message, 'first_post_guest_name' => $this->first_post_guest_name, 'last_post_id' => $this->last_post_id, 'last_post_time' => $this->last_post_time, 'last_post_userid' => $this->last_post_userid, 'last_post_message' => $this->last_post_message, 'last_post_guest_name' => $this->last_post_guest_name, 'rating' => $this->rating, 'params' => $this->params, ]; return $properties; } }
| ver. 1.1 | |
.
| PHP 8.4.18 | Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ñтраницы: 0 |
proxy
|
phpinfo
|
ÐаÑтройка