jobs:
php:
- name: PHP CodeSniffer
+ name: PHP
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- - run: git clone --branch=master --depth=1 --quiet git://github.com/WoltLab/WCF.git WCF
- - uses: chekalsky/phpcs-action@e269c2f264f400adcda7c6b24c8550302350d495
+ - name: phpcs
+ uses: chekalsky/phpcs-action@e269c2f264f400adcda7c6b24c8550302350d495
+ - name: php-cs-fixer
+ uses: docker://oskarstark/php-cs-fixer-ga
+ with:
+ args: --dry-run --diff-format udiff
--- /dev/null
+<?php
+$finder = PhpCsFixer\Finder::create()
+ ->exclude('*/vendor/*')
+ ->in(__DIR__.'/files/');
+
+return (new PhpCsFixer\Config())
+ ->setRiskyAllowed(true)
+ ->setRules([
+ '@PSR1' => true,
+ '@PSR2' => true,
+
+ 'array_push' => true,
+ 'backtick_to_shell_exec' => true,
+ 'no_alias_language_construct_call' => true,
+ 'no_mixed_echo_print' => true,
+ 'pow_to_exponentiation' => true,
+ 'random_api_migration' => true,
+
+ 'array_syntax' => ['syntax' => 'short'],
+ 'no_multiline_whitespace_around_double_arrow' => true,
+ 'no_trailing_comma_in_singleline_array' => true,
+ 'no_whitespace_before_comma_in_array' => true,
+ 'normalize_index_brace' => true,
+ 'trailing_comma_in_multiline_array' => true,
+ 'whitespace_after_comma_in_array' => true,
+
+ 'non_printable_character' => ['use_escape_sequences_in_strings' => true],
+
+ 'lowercase_static_reference' => true,
+ 'magic_constant_casing' => true,
+ 'magic_method_casing' => true,
+ 'native_function_casing' => true,
+ 'native_function_type_declaration_casing' => true,
+
+ 'cast_spaces' => ['space' => 'none'],
+ 'lowercase_cast' => true,
+ 'no_unset_cast' => true,
+ 'short_scalar_cast' => true,
+
+ 'class_attributes_separation' => true,
+ 'no_blank_lines_after_class_opening' => true,
+ 'no_null_property_initialization' => true,
+ 'self_accessor' => true,
+ 'single_class_element_per_statement' => true,
+ 'single_trait_insert_per_statement' => true,
+
+ 'no_empty_comment' => true,
+ 'single_line_comment_style' => ['comment_types' => ['hash']],
+
+ 'native_constant_invocation' => true,
+
+ 'no_alternative_syntax' => true,
+ 'no_trailing_comma_in_list_call' => true,
+ 'no_unneeded_control_parentheses' => ['statements' => ['break', 'clone', 'continue', 'echo_print', 'return', 'switch_case', 'yield', 'yield_from']],
+ 'no_unneeded_curly_braces' => ['namespaces' => true],
+ 'switch_continue_to_break' => true,
+
+ 'function_typehint_space' => true,
+ 'lambda_not_used_import' => true,
+ 'native_function_invocation' => true,
+ 'no_unreachable_default_argument_value' => true,
+ 'nullable_type_declaration_for_default_null_value' => true,
+ 'return_type_declaration' => true,
+ 'static_lambda' => true,
+
+ 'fully_qualified_strict_types' => true,
+ 'no_leading_import_slash' => true,
+ 'no_unused_imports' => true,
+ 'ordered_imports' => true,
+
+ 'declare_equal_normalize' => true,
+ 'dir_constant' => true,
+ 'explicit_indirect_variable' => true,
+ 'function_to_constant' => true,
+ 'is_null' => true,
+ 'no_unset_on_property' => true,
+
+ 'list_syntax' => ['syntax' => 'short'],
+
+ 'clean_namespace' => true,
+ 'no_leading_namespace_whitespace' => true,
+ 'single_blank_line_before_namespace' => true,
+
+ 'no_homoglyph_names' => true,
+
+ 'binary_operator_spaces' => true,
+ 'concat_space' => ['spacing' => 'one'],
+ 'increment_style' => ['style' => 'post'],
+ 'logical_operators' => true,
+ 'object_operator_without_whitespace' => true,
+ 'operator_linebreak' => true,
+ 'standardize_increment' => true,
+ 'standardize_not_equals' => true,
+ 'ternary_operator_spaces' => true,
+ 'ternary_to_elvis_operator' => true,
+ 'ternary_to_null_coalescing' => true,
+ 'unary_operator_spaces' => true,
+
+ 'no_useless_return' => true,
+ 'return_assignment' => true,
+ 'simplified_null_return' => true,
+
+ 'multiline_whitespace_before_semicolons' => true,
+ 'no_empty_statement' => true,
+ 'no_singleline_whitespace_before_semicolons' => true,
+ 'space_after_semicolon' => ['remove_in_empty_for_expressions' => true],
+
+ 'escape_implicit_backslashes' => true,
+ 'explicit_string_variable' => true,
+ 'heredoc_to_nowdoc' => true,
+ 'no_binary_string' => true,
+ 'simple_to_complex_string_variable' => true,
+
+ 'array_indentation' => true,
+ 'blank_line_before_statement' => ['statements' => ['return', 'exit']],
+ 'compact_nullable_typehint' => true,
+ 'method_chaining_indentation' => true,
+ 'no_extra_blank_lines' => ['tokens' => ['case', 'continue', 'curly_brace_block', 'default', 'extra', 'parenthesis_brace_block', 'square_brace_block', 'switch', 'throw', 'use', 'use_trait']],
+ 'no_spaces_around_offset' => true,
+ ])
+ ->setFinder($finder);
<?xml version="1.0"?>
<ruleset>
<file>files/</file>
+ <exclude-pattern>*/vendor/*</exclude-pattern>
<arg name="extensions" value="php" />
<arg value="p"/>
<arg name="basepath" value="."/>
- <rule ref="./WCF/CodeSniff/WCF/ruleset.xml"/>
+ <rule ref="PSR12"/>
</ruleset>
/**
* Defines constants for autocompletion in IDEs. This file is not meant to be actively used anywhere!
*
- * @author Matthias Schmidt
* @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core
+ * @author Matthias Schmidt
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core
*/
// option constants
<?php
-use wcf\data\user\group\UserGroup;
-use wcf\system\WCF;
/**
- * @author Matthias Schmidt
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @author Matthias Schmidt
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
*/
+
+use wcf\data\user\group\UserGroup;
+use wcf\system\WCF;
+
// set default mod permissions
$group = new UserGroup(5);
if ($group->groupID) {
- $sql = "REPLACE INTO wcf".WCF_N."_user_group_option_value
+ $sql = "REPLACE INTO wcf" . WCF_N . "_user_group_option_value
(groupID, optionID, optionValue)
SELECT 5, optionID, 1
- FROM wcf".WCF_N."_user_group_option
+ FROM wcf" . WCF_N . "_user_group_option
WHERE optionName LIKE 'mod.conversation.%'";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute();
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute();
}
$group = new UserGroup(6);
if ($group->groupID) {
- $sql = "REPLACE INTO wcf".WCF_N."_user_group_option_value
+ $sql = "REPLACE INTO wcf" . WCF_N . "_user_group_option_value
(groupID, optionID, optionValue)
SELECT 6, optionID, 1
- FROM wcf".WCF_N."_user_group_option
+ FROM wcf" . WCF_N . "_user_group_option
WHERE optionName LIKE 'mod.conversation.%'";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute();
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute();
}
<?php
-use wcf\system\database\table\column\DefaultFalseBooleanDatabaseTableColumn;
-use wcf\system\database\table\column\DefaultTrueBooleanDatabaseTableColumn;
-use wcf\system\database\table\DatabaseTable;
-use wcf\system\database\table\DatabaseTableChangeProcessor;
-use wcf\system\package\plugin\ScriptPackageInstallationPlugin;
-use wcf\system\WCF;
/**
* @author Alexander Ebert
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
*/
+use wcf\system\database\table\column\DefaultFalseBooleanDatabaseTableColumn;
+use wcf\system\database\table\column\DefaultTrueBooleanDatabaseTableColumn;
+use wcf\system\database\table\DatabaseTable;
+use wcf\system\database\table\DatabaseTableChangeProcessor;
+use wcf\system\package\plugin\ScriptPackageInstallationPlugin;
+use wcf\system\WCF;
+
$tables = [
- DatabaseTable::create('wcf1_conversation_to_user')
- ->columns([
- DefaultTrueBooleanDatabaseTableColumn::create('leftByOwnChoice')
- ]),
-
- DatabaseTable::create('wcf1_user_group')
- ->columns([
- DefaultFalseBooleanDatabaseTableColumn::create('canBeAddedAsConversationParticipant'),
- ]),
+ DatabaseTable::create('wcf1_conversation_to_user')
+ ->columns([
+ DefaultTrueBooleanDatabaseTableColumn::create('leftByOwnChoice'),
+ ]),
+
+ DatabaseTable::create('wcf1_user_group')
+ ->columns([
+ DefaultFalseBooleanDatabaseTableColumn::create('canBeAddedAsConversationParticipant'),
+ ]),
];
(new DatabaseTableChangeProcessor(
- /** @var ScriptPackageInstallationPlugin $this */
- $this->installation->getPackage(),
- $tables,
- WCF::getDB()->getEditor())
+/** @var ScriptPackageInstallationPlugin $this */
+ $this->installation->getPackage(),
+ $tables,
+ WCF::getDB()->getEditor()
+)
)->process();
<?php
+
namespace wcf\data\conversation;
+
use wcf\data\conversation\message\ConversationMessage;
+use wcf\data\DatabaseObject;
use wcf\data\IPopoverObject;
use wcf\data\user\group\UserGroup;
use wcf\data\user\UserProfile;
-use wcf\data\DatabaseObject;
use wcf\system\cache\runtime\UserProfileRuntimeCache;
use wcf\system\conversation\ConversationHandler;
use wcf\system\database\util\PreparedStatementConditionBuilder;
/**
* Represents a conversation.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
- *
- * @property-read integer $conversationID unique id of the conversation
- * @property-read string $subject subject of the conversation
- * @property-read integer $time timestamp at which the conversation has been started
- * @property-read integer $firstMessageID id of the first conversation message
- * @property-read integer|null $userID id of the user who started the conversation or `null` if the user does not exist anymore
- * @property-read string $username name of the user who started the conversation
- * @property-read integer $lastPostTime timestamp at which the conversation's last message has been written
- * @property-read integer|null $lastPosterID id of the user who wrote the conversation's last message or `null` if the user does not exist anymore
- * @property-read string $lastPoster name of the user who wrote the conversation's last message
- * @property-read integer $replies number of replies on the conversation
- * @property-read integer $attachments total number of attachments in all messages of the conversation
- * @property-read integer $participants number of participants of the conversations
- * @property-read string $participantSummary serialized data of five of the conversation participants (sorted by username)
- * @property-read integer $participantCanInvite is `1` if participants can invite other users to join the conversation, otherwise `0`
- * @property-read integer $isClosed is `1` if the conversation is closed for new messages, otherwise `0`
- * @property-read integer $isDraft is `1` if the conversation is a draft only, thus not sent to any participant, otherwise `0`
- * @property-read string $draftData serialized ids of the participants and invisible participants if conversation is a draft, otherwise `0`
- * @property-read integer|null $participantID id of the user whose conversations are fetched via `UserConversationList`, otherwise `null`
- * @property-read integer|null $hideConversation is `1` if the user has hidden conversation, otherwise `0`; is `null` if the conversation has not been fetched via `UserConversationList`
- * @property-read integer|null $isInvisible is `1` if the user is invisible in conversation, otherwise `0`; is `null` if the conversation has not been fetched via `UserConversationList`
- * @property-read integer|null $lastVisitTime timestamp at which the user last visited the conversation after a new messsage had been written or `0` if they have not visited it at all; is `null` if the conversation has not been fetched via `UserConversationList`
- * @property-read integer|null $joinedAt timestamp at which the user joined the conversation; is `null` if the conversation has not been fetched via `UserConversationList`
- * @property-read integer|null $leftAt timestamp at which the user left the conversation or `0` if they did not leave the conversation; is `null` if the conversation has not been fetched via `UserConversationList`
- * @property-read integer|null $lastMessageID id of the last message written before the user left the conversation or `0` if they did not leave the conversation; is `null` if the conversation has not been fetched via `UserConversationList`
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation
+ *
+ * @property-read integer $conversationID unique id of the conversation
+ * @property-read string $subject subject of the conversation
+ * @property-read integer $time timestamp at which the conversation has been started
+ * @property-read integer $firstMessageID id of the first conversation message
+ * @property-read integer|null $userID id of the user who started the conversation or `null` if the user does not exist anymore
+ * @property-read string $username name of the user who started the conversation
+ * @property-read integer $lastPostTime timestamp at which the conversation's last message has been written
+ * @property-read integer|null $lastPosterID id of the user who wrote the conversation's last message or `null` if the user does not exist anymore
+ * @property-read string $lastPoster name of the user who wrote the conversation's last message
+ * @property-read integer $replies number of replies on the conversation
+ * @property-read integer $attachments total number of attachments in all messages of the conversation
+ * @property-read integer $participants number of participants of the conversations
+ * @property-read string $participantSummary serialized data of five of the conversation participants (sorted by username)
+ * @property-read integer $participantCanInvite is `1` if participants can invite other users to join the conversation, otherwise `0`
+ * @property-read integer $isClosed is `1` if the conversation is closed for new messages, otherwise `0`
+ * @property-read integer $isDraft is `1` if the conversation is a draft only, thus not sent to any participant, otherwise `0`
+ * @property-read string $draftData serialized ids of the participants and invisible participants if conversation is a draft, otherwise `0`
+ * @property-read integer|null $participantID id of the user whose conversations are fetched via `UserConversationList`, otherwise `null`
+ * @property-read integer|null $hideConversation is `1` if the user has hidden conversation, otherwise `0`; is `null` if the conversation has not been fetched via `UserConversationList`
+ * @property-read integer|null $isInvisible is `1` if the user is invisible in conversation, otherwise `0`; is `null` if the conversation has not been fetched via `UserConversationList`
+ * @property-read integer|null $lastVisitTime timestamp at which the user last visited the conversation after a new messsage had been written or `0` if they have not visited it at all; is `null` if the conversation has not been fetched via `UserConversationList`
+ * @property-read integer|null $joinedAt timestamp at which the user joined the conversation; is `null` if the conversation has not been fetched via `UserConversationList`
+ * @property-read integer|null $leftAt timestamp at which the user left the conversation or `0` if they did not leave the conversation; is `null` if the conversation has not been fetched via `UserConversationList`
+ * @property-read integer|null $lastMessageID id of the last message written before the user left the conversation or `0` if they did not leave the conversation; is `null` if the conversation has not been fetched via `UserConversationList`
*/
-class Conversation extends DatabaseObject implements IPopoverObject, IRouteController {
- /**
- * default participation state
- * @var integer
- */
- const STATE_DEFAULT = 0;
-
- /**
- * conversation is hidden but returns visible upon new message
- * @var integer
- */
- const STATE_HIDDEN = 1;
-
- /**
- * conversation was left permanently
- * @var integer
- */
- const STATE_LEFT/*4DEAD*/ = 2;
-
- /**
- * true if the current user can add users without limitations
- * @var boolean
- */
- protected $canAddUnrestricted;
-
- /**
- * first message object
- * @var ConversationMessage
- */
- protected $firstMessage;
-
- /**
- * true if the current user is an active participant of this conversation
- * @var boolean
- */
- protected $isActiveParticipant;
-
- /**
- * @inheritDoc
- */
- public function getTitle() {
- return $this->subject;
- }
-
- /**
- * @inheritDoc
- */
- public function getLink() {
- return LinkHandler::getInstance()->getLink('Conversation', [
- 'object' => $this,
- 'forceFrontend' => true
- ]);
- }
-
- /**
- * Returns true if this conversation is new for the active user.
- *
- * @return boolean
- */
- public function isNew() {
- if (!$this->isDraft && $this->lastPostTime > $this->lastVisitTime) {
- return true;
- }
-
- return false;
- }
-
- /**
- * Returns true if the active user doesn't have read the given message.
- *
- * @param ConversationMessage $message
- * @return boolean
- */
- public function isNewMessage(ConversationMessage $message) {
- if (!$this->isDraft && $message->time > $this->lastVisitTime) {
- return true;
- }
-
- return false;
- }
-
- /**
- * Returns true if the conversation is not closed or the user was not removed.
- *
- * @return boolean
- */
- public function canReply() {
- return !$this->isClosed && !$this->leftAt && WCF::getSession()->getPermission('user.conversation.canReplyToConversation');
- }
-
- /**
- * Overrides the last message data, used when `leftAt < lastPostTime`.
- *
- * @param integer $userID
- * @param string $username
- * @param integer $time
- */
- public function setLastMessage($userID, $username, $time) {
- $this->data['lastPostTime'] = $time;
- $this->data['lastPosterID'] = $userID;
- $this->data['lastPoster'] = $username;
- }
-
- /**
- * Loads participation data for given user id (default: current user) on runtime.
- * You should use Conversation::getUserConversation() instead if possible.
- *
- * @param integer $userID
- */
- public function loadUserParticipation($userID = null) {
- if ($userID === null) {
- $userID = WCF::getUser()->userID;
- }
-
- $sql = "SELECT *
- FROM wcf".WCF_N."_conversation_to_user
+class Conversation extends DatabaseObject implements IPopoverObject, IRouteController
+{
+ /**
+ * default participation state
+ * @var integer
+ */
+ const STATE_DEFAULT = 0;
+
+ /**
+ * conversation is hidden but returns visible upon new message
+ * @var integer
+ */
+ const STATE_HIDDEN = 1;
+
+ /**
+ * conversation was left permanently
+ * @var integer
+ */
+ const STATE_LEFT/*4DEAD*/ = 2;
+
+ /**
+ * true if the current user can add users without limitations
+ * @var boolean
+ */
+ protected $canAddUnrestricted;
+
+ /**
+ * first message object
+ * @var ConversationMessage
+ */
+ protected $firstMessage;
+
+ /**
+ * true if the current user is an active participant of this conversation
+ * @var boolean
+ */
+ protected $isActiveParticipant;
+
+ /**
+ * @inheritDoc
+ */
+ public function getTitle()
+ {
+ return $this->subject;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getLink()
+ {
+ return LinkHandler::getInstance()->getLink('Conversation', [
+ 'object' => $this,
+ 'forceFrontend' => true,
+ ]);
+ }
+
+ /**
+ * Returns true if this conversation is new for the active user.
+ *
+ * @return boolean
+ */
+ public function isNew()
+ {
+ if (!$this->isDraft && $this->lastPostTime > $this->lastVisitTime) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns true if the active user doesn't have read the given message.
+ *
+ * @param ConversationMessage $message
+ * @return boolean
+ */
+ public function isNewMessage(ConversationMessage $message)
+ {
+ if (!$this->isDraft && $message->time > $this->lastVisitTime) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns true if the conversation is not closed or the user was not removed.
+ *
+ * @return boolean
+ */
+ public function canReply()
+ {
+ return !$this->isClosed && !$this->leftAt && WCF::getSession()->getPermission('user.conversation.canReplyToConversation');
+ }
+
+ /**
+ * Overrides the last message data, used when `leftAt < lastPostTime`.
+ *
+ * @param integer $userID
+ * @param string $username
+ * @param integer $time
+ */
+ public function setLastMessage($userID, $username, $time)
+ {
+ $this->data['lastPostTime'] = $time;
+ $this->data['lastPosterID'] = $userID;
+ $this->data['lastPoster'] = $username;
+ }
+
+ /**
+ * Loads participation data for given user id (default: current user) on runtime.
+ * You should use Conversation::getUserConversation() instead if possible.
+ *
+ * @param integer $userID
+ */
+ public function loadUserParticipation($userID = null)
+ {
+ if ($userID === null) {
+ $userID = WCF::getUser()->userID;
+ }
+
+ $sql = "SELECT *
+ FROM wcf" . WCF_N . "_conversation_to_user
WHERE participantID = ?
AND conversationID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute([$userID, $this->conversationID]);
- $row = $statement->fetchArray();
- if ($row !== false) {
- $this->data = array_merge($this->data, $row);
- }
- }
-
- /**
- * Returns a specific user conversation.
- *
- * @param integer $conversationID
- * @param integer $userID
- * @return Conversation
- */
- public static function getUserConversation($conversationID, $userID) {
- $sql = "SELECT conversation_to_user.*, conversation.*
- FROM wcf".WCF_N."_conversation conversation
- LEFT JOIN wcf".WCF_N."_conversation_to_user conversation_to_user
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([$userID, $this->conversationID]);
+ $row = $statement->fetchArray();
+ if ($row !== false) {
+ $this->data = \array_merge($this->data, $row);
+ }
+ }
+
+ /**
+ * Returns a specific user conversation.
+ *
+ * @param integer $conversationID
+ * @param integer $userID
+ * @return Conversation
+ */
+ public static function getUserConversation($conversationID, $userID)
+ {
+ $sql = "SELECT conversation_to_user.*, conversation.*
+ FROM wcf" . WCF_N . "_conversation conversation
+ LEFT JOIN wcf" . WCF_N . "_conversation_to_user conversation_to_user
ON (conversation_to_user.participantID = ? AND conversation_to_user.conversationID = conversation.conversationID)
WHERE conversation.conversationID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute([$userID, $conversationID]);
- $row = $statement->fetchArray();
- if ($row !== false) {
- return new Conversation(null, $row);
- }
-
- return null;
- }
-
- /**
- * Returns a list of user conversations.
- *
- * @param integer[] $conversationIDs
- * @param integer $userID
- * @return Conversation[]
- */
- public static function getUserConversations(array $conversationIDs, $userID) {
- $conditionBuilder = new PreparedStatementConditionBuilder();
- $conditionBuilder->add('conversation.conversationID IN (?)', [$conversationIDs]);
- $sql = "SELECT conversation_to_user.*, conversation.*
- FROM wcf".WCF_N."_conversation conversation
- LEFT JOIN wcf".WCF_N."_conversation_to_user conversation_to_user
- ON (conversation_to_user.participantID = ".$userID." AND conversation_to_user.conversationID = conversation.conversationID)
- ".$conditionBuilder;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditionBuilder->getParameters());
- $conversations = [];
- while ($row = $statement->fetchArray()) {
- $conversations[$row['conversationID']] = new Conversation(null, $row);
- }
-
- return $conversations;
- }
-
- /**
- * Returns true if the active user has the permission to read this conversation.
- *
- * @return boolean
- */
- public function canRead() {
- if (!WCF::getUser()->userID) return false;
-
- if ($this->isDraft && $this->userID == WCF::getUser()->userID) return true;
-
- if ($this->participantID == WCF::getUser()->userID && $this->hideConversation != self::STATE_LEFT) return true;
-
- return false;
- }
-
- /**
- * Returns true if the current user can add new participants to this conversation.
- *
- * @return boolean
- */
- public function canAddParticipants() {
- if ($this->isDraft) {
- return false;
- }
-
- // check permissions
- if (WCF::getUser()->userID != $this->userID) {
- if (!$this->participantCanInvite && !WCF::getSession()->getPermission('mod.conversation.canAlwaysInviteUsers')) {
- return false;
- }
- }
-
- // check for maximum number of participants
- // note: 'participants' does not track invisible participants, this will be checked on the fly!
- if ($this->participants >= WCF::getSession()->getPermission('user.conversation.maxParticipants')) {
- return false;
- }
-
- if (!$this->isActiveParticipant()) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Returns true if the current user can add participants without limitations.
- *
- * @return boolean
- */
- public function canAddParticipantsUnrestricted() {
- if ($this->canAddUnrestricted === null) {
- $this->canAddUnrestricted = false;
- if ($this->isActiveParticipant()) {
- $sql = "SELECT joinedAt
- FROM wcf".WCF_N."_conversation_to_user
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([$userID, $conversationID]);
+ $row = $statement->fetchArray();
+ if ($row !== false) {
+ return new self(null, $row);
+ }
+ }
+
+ /**
+ * Returns a list of user conversations.
+ *
+ * @param integer[] $conversationIDs
+ * @param integer $userID
+ * @return Conversation[]
+ */
+ public static function getUserConversations(array $conversationIDs, $userID)
+ {
+ $conditionBuilder = new PreparedStatementConditionBuilder();
+ $conditionBuilder->add('conversation.conversationID IN (?)', [$conversationIDs]);
+ $sql = "SELECT conversation_to_user.*, conversation.*
+ FROM wcf" . WCF_N . "_conversation conversation
+ LEFT JOIN wcf" . WCF_N . "_conversation_to_user conversation_to_user
+ ON (conversation_to_user.participantID = " . $userID . " AND conversation_to_user.conversationID = conversation.conversationID)
+ " . $conditionBuilder;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditionBuilder->getParameters());
+ $conversations = [];
+ while ($row = $statement->fetchArray()) {
+ $conversations[$row['conversationID']] = new self(null, $row);
+ }
+
+ return $conversations;
+ }
+
+ /**
+ * Returns true if the active user has the permission to read this conversation.
+ *
+ * @return boolean
+ */
+ public function canRead()
+ {
+ if (!WCF::getUser()->userID) {
+ return false;
+ }
+
+ if ($this->isDraft && $this->userID == WCF::getUser()->userID) {
+ return true;
+ }
+
+ if ($this->participantID == WCF::getUser()->userID && $this->hideConversation != self::STATE_LEFT) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns true if the current user can add new participants to this conversation.
+ *
+ * @return boolean
+ */
+ public function canAddParticipants()
+ {
+ if ($this->isDraft) {
+ return false;
+ }
+
+ // check permissions
+ if (WCF::getUser()->userID != $this->userID) {
+ if (
+ !$this->participantCanInvite
+ && !WCF::getSession()->getPermission('mod.conversation.canAlwaysInviteUsers')
+ ) {
+ return false;
+ }
+ }
+
+ // check for maximum number of participants
+ // note: 'participants' does not track invisible participants, this will be checked on the fly!
+ if ($this->participants >= WCF::getSession()->getPermission('user.conversation.maxParticipants')) {
+ return false;
+ }
+
+ if (!$this->isActiveParticipant()) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns true if the current user can add participants without limitations.
+ *
+ * @return boolean
+ */
+ public function canAddParticipantsUnrestricted()
+ {
+ if ($this->canAddUnrestricted === null) {
+ $this->canAddUnrestricted = false;
+ if ($this->isActiveParticipant()) {
+ $sql = "SELECT joinedAt
+ FROM wcf" . WCF_N . "_conversation_to_user
WHERE conversationID = ?
AND participantID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute([
- $this->conversationID,
- WCF::getUser()->userID
- ]);
- $joinedAt = $statement->fetchSingleColumn();
-
- if ($joinedAt !== false && $joinedAt == 0) {
- $this->canAddUnrestricted = true;
- }
- }
- }
-
- return $this->canAddUnrestricted;
- }
-
- /**
- * Returns the first message in this conversation.
- *
- * @return ConversationMessage
- */
- public function getFirstMessage() {
- if ($this->firstMessage === null) {
- $this->firstMessage = new ConversationMessage($this->firstMessageID);
- }
-
- return $this->firstMessage;
- }
-
- /**
- * Sets the first message.
- *
- * @param ConversationMessage $message
- */
- public function setFirstMessage(ConversationMessage $message) {
- $this->firstMessage = $message;
- }
-
- /**
- * Returns a list of the ids of all participants.
- *
- * @param boolean $excludeLeftParticipants
- * @return integer[]
- */
- public function getParticipantIDs($excludeLeftParticipants = false) {
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID = ?", [$this->conversationID]);
- $conditions->add("participantID IS NOT NULL");
- if ($excludeLeftParticipants) $conditions->add("(hideConversation <> ? AND leftAt = ?)", [self::STATE_LEFT, 0]);
-
- $sql = "SELECT participantID
- FROM wcf".WCF_N."_conversation_to_user
- ".$conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditions->getParameters());
-
- return $statement->fetchAll(\PDO::FETCH_COLUMN);
- }
-
- /**
- * Returns a list of the usernames of all participants.
- *
- * @param boolean $excludeSelf
- * @param boolean $leftByOwnChoice
- * @return string[]
- */
- public function getParticipantNames($excludeSelf = false, $leftByOwnChoice = false) {
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID = ?", [$this->conversationID]);
- if ($excludeSelf) $conditions->add("conversation_to_user.participantID <> ?", [WCF::getUser()->userID]);
- if ($leftByOwnChoice) $conditions->add("conversation_to_user.leftByOwnChoice = ?", [1]);
-
- $sql = "SELECT user_table.username
- FROM wcf".WCF_N."_conversation_to_user conversation_to_user
- LEFT JOIN wcf".WCF_N."_user user_table
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([
+ $this->conversationID,
+ WCF::getUser()->userID,
+ ]);
+ $joinedAt = $statement->fetchSingleColumn();
+
+ if ($joinedAt !== false && $joinedAt == 0) {
+ $this->canAddUnrestricted = true;
+ }
+ }
+ }
+
+ return $this->canAddUnrestricted;
+ }
+
+ /**
+ * Returns the first message in this conversation.
+ *
+ * @return ConversationMessage
+ */
+ public function getFirstMessage()
+ {
+ if ($this->firstMessage === null) {
+ $this->firstMessage = new ConversationMessage($this->firstMessageID);
+ }
+
+ return $this->firstMessage;
+ }
+
+ /**
+ * Sets the first message.
+ *
+ * @param ConversationMessage $message
+ */
+ public function setFirstMessage(ConversationMessage $message)
+ {
+ $this->firstMessage = $message;
+ }
+
+ /**
+ * Returns a list of the ids of all participants.
+ *
+ * @param boolean $excludeLeftParticipants
+ * @return integer[]
+ */
+ public function getParticipantIDs($excludeLeftParticipants = false)
+ {
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("conversationID = ?", [$this->conversationID]);
+ $conditions->add("participantID IS NOT NULL");
+ if ($excludeLeftParticipants) {
+ $conditions->add("(hideConversation <> ? AND leftAt = ?)", [self::STATE_LEFT, 0]);
+ }
+
+ $sql = "SELECT participantID
+ FROM wcf" . WCF_N . "_conversation_to_user
+ " . $conditions;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditions->getParameters());
+
+ return $statement->fetchAll(\PDO::FETCH_COLUMN);
+ }
+
+ /**
+ * Returns a list of the usernames of all participants.
+ *
+ * @param boolean $excludeSelf
+ * @param boolean $leftByOwnChoice
+ * @return string[]
+ */
+ public function getParticipantNames($excludeSelf = false, $leftByOwnChoice = false)
+ {
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("conversationID = ?", [$this->conversationID]);
+ if ($excludeSelf) {
+ $conditions->add("conversation_to_user.participantID <> ?", [WCF::getUser()->userID]);
+ }
+ if ($leftByOwnChoice) {
+ $conditions->add("conversation_to_user.leftByOwnChoice = ?", [1]);
+ }
+
+ $sql = "SELECT user_table.username
+ FROM wcf" . WCF_N . "_conversation_to_user conversation_to_user
+ LEFT JOIN wcf" . WCF_N . "_user user_table
ON (user_table.userID = conversation_to_user.participantID)
- ".$conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditions->getParameters());
-
- return $statement->fetchAll(\PDO::FETCH_COLUMN);
- }
-
- /**
- * Returns false if the active user is the last participant of this conversation.
- *
- * @return boolean
- */
- public function hasOtherParticipants() {
- if ($this->userID == WCF::getUser()->userID) {
- // author
- if ($this->participants == 0) return false;
- return true;
- }
- else {
- if ($this->participants > 1) return true;
- if ($this->isInvisible && $this->participants > 0) return true;
-
- if ($this->userID) {
- // check if author has left the conversation
- $sql = "SELECT hideConversation
- FROM wcf".WCF_N."_conversation_to_user
+ " . $conditions;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditions->getParameters());
+
+ return $statement->fetchAll(\PDO::FETCH_COLUMN);
+ }
+
+ /**
+ * Returns false if the active user is the last participant of this conversation.
+ *
+ * @return boolean
+ */
+ public function hasOtherParticipants()
+ {
+ if ($this->userID == WCF::getUser()->userID) {
+ // author
+ if ($this->participants == 0) {
+ return false;
+ }
+
+ return true;
+ } else {
+ if ($this->participants > 1) {
+ return true;
+ }
+ if ($this->isInvisible && $this->participants > 0) {
+ return true;
+ }
+
+ if ($this->userID) {
+ // check if author has left the conversation
+ $sql = "SELECT hideConversation
+ FROM wcf" . WCF_N . "_conversation_to_user
WHERE conversationID = ?
AND participantID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute([$this->conversationID, $this->userID]);
- $row = $statement->fetchArray();
- if ($row !== false) {
- if ($row['hideConversation'] != self::STATE_LEFT) return true;
- }
- }
-
- return false;
- }
- }
-
- /**
- * Returns true if the current user is an active participant of this conversation.
- *
- * @return boolean
- */
- public function isActiveParticipant() {
- if ($this->isActiveParticipant === null) {
- $sql = "SELECT leftAt
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([$this->conversationID, $this->userID]);
+ $row = $statement->fetchArray();
+ if ($row !== false) {
+ if ($row['hideConversation'] != self::STATE_LEFT) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+ }
+
+ /**
+ * Returns true if the current user is an active participant of this conversation.
+ *
+ * @return boolean
+ */
+ public function isActiveParticipant()
+ {
+ if ($this->isActiveParticipant === null) {
+ $sql = "SELECT leftAt
FROM wcf" . WCF_N . "_conversation_to_user
WHERE conversationID = ?
AND participantID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute([
- $this->conversationID,
- WCF::getUser()->userID
- ]);
- $leftAt = $statement->fetchSingleColumn();
-
- $this->isActiveParticipant = ($leftAt !== false && $leftAt == 0);
- }
-
- return $this->isActiveParticipant;
- }
-
- /**
- * @inheritDoc
- */
- public function getPopoverLinkClass() {
- return 'conversationLink';
- }
-
- /**
- * Returns true if the given user id (default: current user) is participant
- * of all given conversation ids.
- *
- * @param integer[] $conversationIDs
- * @param integer $userID
- * @return boolean
- */
- public static function isParticipant(array $conversationIDs, $userID = null) {
- if ($userID === null) $userID = WCF::getUser()->userID;
-
- // check if user is the initial author
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID IN (?)", [$conversationIDs]);
- $conditions->add("userID = ?", [$userID]);
-
- $sql = "SELECT conversationID
- FROM wcf".WCF_N."_conversation
- ".$conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditions->getParameters());
- while ($row = $statement->fetchArray()) {
- $index = array_search($row['conversationID'], $conversationIDs);
- unset($conversationIDs[$index]);
- }
-
- // check for participation
- if (!empty($conversationIDs)) {
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID IN (?)", [$conversationIDs]);
- $conditions->add("participantID = ?", [$userID]);
- $conditions->add("hideConversation <> ?", [self::STATE_LEFT]);
-
- $sql = "SELECT conversationID
- FROM wcf".WCF_N."_conversation_to_user
- ".$conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditions->getParameters());
- while ($row = $statement->fetchArray()) {
- $index = array_search($row['conversationID'], $conversationIDs);
- unset($conversationIDs[$index]);
- }
- }
-
- if (!empty($conversationIDs)) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Validates the participants.
- *
- * @param mixed $participants
- * @param string $field
- * @param integer[] $existingParticipants
- * @return array $result
- * @throws UserInputException
- */
- public static function validateParticipants($participants, $field = 'participants', array $existingParticipants = []) {
- $result = [];
- $error = [];
-
- // loop through participants and check their settings
- $participantList = UserProfile::getUserProfilesByUsername((is_array($participants) ? $participants : ArrayUtil::trim(explode(',', $participants))));
-
- // load user storage at once to avoid multiple queries
- $userIDs = [];
- foreach ($participantList as $user) {
- if ($user) {
- $userIDs[] = $user->userID;
- }
- }
- UserStorageHandler::getInstance()->loadStorage($userIDs);
-
- foreach ($participantList as $participant => $user) {
- try {
- if ($user === null) {
- throw new UserInputException($field, 'notFound');
- }
-
- // user is author
- if ($user->userID == WCF::getUser()->userID) {
- throw new UserInputException($field, 'isAuthor');
- }
- else if (in_array($user->userID, $existingParticipants)) {
- throw new UserInputException($field, 'duplicate');
- }
-
- // validate user
- self::validateParticipant($user, $field);
-
- // no error
- $existingParticipants[] = $result[] = $user->userID;
- }
- catch (UserInputException $e) {
- $error[] = ['type' => $e->getType(), 'username' => $participant];
- }
- }
-
- if (!empty($error)) {
- throw new UserInputException($field, $error);
- }
-
- return $result;
- }
-
- /**
- * Validates the group participants.
- *
- * @param mixed $participants
- * @param string $field
- * @param integer[] $existingParticipants
- * @return array $result
- */
- public static function validateGroupParticipants($participants, $field = 'participants', array $existingParticipants = []) {
- $groupIDs = is_array($participants) ? $participants : ArrayUtil::toIntegerArray(explode(',', $participants));
- $validGroupIDs = [];
- $result = [];
-
- foreach ($groupIDs as $groupID) {
- $group = UserGroup::getGroupByID($groupID);
- /** @noinspection PhpUndefinedFieldInspection */
- if ($group !== null && $group->canBeAddedAsConversationParticipant) {
- $validGroupIDs[] = $groupID;
- }
- }
-
- if (!empty($validGroupIDs)) {
- $userIDs = [];
- $conditionBuilder = new PreparedStatementConditionBuilder();
- $conditionBuilder->add('groupID IN (?)', [$validGroupIDs]);
- $sql = "SELECT DISTINCT userID
- FROM wcf".WCF_N."_user_to_group
- ".$conditionBuilder;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditionBuilder->getParameters());
- while ($userID = $statement->fetchColumn()) $userIDs[] = $userID;
-
- if (!empty($userIDs)) {
- $users = UserProfileRuntimeCache::getInstance()->getObjects($userIDs);
- UserStorageHandler::getInstance()->loadStorage($userIDs);
-
- foreach ($users as $user) {
- // user is author
- if ($user->userID == WCF::getUser()->userID) {
- continue;
- }
- else if (in_array($user->userID, $existingParticipants)) {
- continue;
- }
-
- try {
- // validate user
- self::validateParticipant($user, $field);
-
- // no error
- $result[] = $user->userID;
- }
- catch (UserInputException $e) {}
- }
- }
- }
-
- return $result;
- }
-
- /**
- * Validates the given participant.
- *
- * @param UserProfile $user
- * @param string $field
- * @throws UserInputException
- */
- public static function validateParticipant(UserProfile $user, $field = 'participants') {
- // check participant's settings and permissions
- if (!$user->getPermission('user.conversation.canUseConversation')) {
- throw new UserInputException($field, 'canNotUseConversation');
- }
-
- if (!WCF::getSession()->getPermission('user.profile.cannotBeIgnored')) {
- // check if user wants to receive any conversations
- /** @noinspection PhpUndefinedFieldInspection */
- if ($user->canSendConversation == 2) {
- throw new UserInputException($field, 'doesNotAcceptConversation');
- }
-
- // check if user only wants to receive conversations by
- // users they are following and if the active user is followed
- // by the relevant user
- /** @noinspection PhpUndefinedFieldInspection */
- if ($user->canSendConversation == 1 && !$user->isFollowing(WCF::getUser()->userID)) {
- throw new UserInputException($field, 'doesNotAcceptConversation');
- }
-
- // active user is ignored by participant
- if ($user->isIgnoredUser(WCF::getUser()->userID)) {
- throw new UserInputException($field, 'ignoresYou');
- }
-
- // check participant's mailbox quota
- if (ConversationHandler::getInstance()->getConversationCount($user->userID) >= $user->getPermission('user.conversation.maxConversations')) {
- throw new UserInputException($field, 'mailboxIsFull');
- }
- }
- }
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([
+ $this->conversationID,
+ WCF::getUser()->userID,
+ ]);
+ $leftAt = $statement->fetchSingleColumn();
+
+ $this->isActiveParticipant = ($leftAt !== false && $leftAt == 0);
+ }
+
+ return $this->isActiveParticipant;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getPopoverLinkClass()
+ {
+ return 'conversationLink';
+ }
+
+ /**
+ * Returns true if the given user id (default: current user) is participant
+ * of all given conversation ids.
+ *
+ * @param integer[] $conversationIDs
+ * @param integer $userID
+ * @return boolean
+ */
+ public static function isParticipant(array $conversationIDs, $userID = null)
+ {
+ if ($userID === null) {
+ $userID = WCF::getUser()->userID;
+ }
+
+ // check if user is the initial author
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("conversationID IN (?)", [$conversationIDs]);
+ $conditions->add("userID = ?", [$userID]);
+
+ $sql = "SELECT conversationID
+ FROM wcf" . WCF_N . "_conversation
+ " . $conditions;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditions->getParameters());
+ while ($row = $statement->fetchArray()) {
+ $index = \array_search($row['conversationID'], $conversationIDs);
+ unset($conversationIDs[$index]);
+ }
+
+ // check for participation
+ if (!empty($conversationIDs)) {
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("conversationID IN (?)", [$conversationIDs]);
+ $conditions->add("participantID = ?", [$userID]);
+ $conditions->add("hideConversation <> ?", [self::STATE_LEFT]);
+
+ $sql = "SELECT conversationID
+ FROM wcf" . WCF_N . "_conversation_to_user
+ " . $conditions;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditions->getParameters());
+ while ($row = $statement->fetchArray()) {
+ $index = \array_search($row['conversationID'], $conversationIDs);
+ unset($conversationIDs[$index]);
+ }
+ }
+
+ if (!empty($conversationIDs)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Validates the participants.
+ *
+ * @param mixed $participants
+ * @param string $field
+ * @param integer[] $existingParticipants
+ * @return array $result
+ * @throws UserInputException
+ */
+ public static function validateParticipants(
+ $participants,
+ $field = 'participants',
+ array $existingParticipants = []
+ ) {
+ $result = [];
+ $error = [];
+
+ // loop through participants and check their settings
+ $participantList = UserProfile::getUserProfilesByUsername(
+ (\is_array($participants) ? $participants : ArrayUtil::trim(\explode(',', $participants)))
+ );
+
+ // load user storage at once to avoid multiple queries
+ $userIDs = [];
+ foreach ($participantList as $user) {
+ if ($user) {
+ $userIDs[] = $user->userID;
+ }
+ }
+ UserStorageHandler::getInstance()->loadStorage($userIDs);
+
+ foreach ($participantList as $participant => $user) {
+ try {
+ if ($user === null) {
+ throw new UserInputException($field, 'notFound');
+ }
+
+ // user is author
+ if ($user->userID == WCF::getUser()->userID) {
+ throw new UserInputException($field, 'isAuthor');
+ } elseif (\in_array($user->userID, $existingParticipants)) {
+ throw new UserInputException($field, 'duplicate');
+ }
+
+ // validate user
+ self::validateParticipant($user, $field);
+
+ // no error
+ $existingParticipants[] = $result[] = $user->userID;
+ } catch (UserInputException $e) {
+ $error[] = ['type' => $e->getType(), 'username' => $participant];
+ }
+ }
+
+ if (!empty($error)) {
+ throw new UserInputException($field, $error);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Validates the group participants.
+ *
+ * @param mixed $participants
+ * @param string $field
+ * @param integer[] $existingParticipants
+ * @return array $result
+ */
+ public static function validateGroupParticipants(
+ $participants,
+ $field = 'participants',
+ array $existingParticipants = []
+ ) {
+ $groupIDs = \is_array($participants) ? $participants : ArrayUtil::toIntegerArray(\explode(',', $participants));
+ $validGroupIDs = [];
+ $result = [];
+
+ foreach ($groupIDs as $groupID) {
+ $group = UserGroup::getGroupByID($groupID);
+ /** @noinspection PhpUndefinedFieldInspection */
+ if ($group !== null && $group->canBeAddedAsConversationParticipant) {
+ $validGroupIDs[] = $groupID;
+ }
+ }
+
+ if (!empty($validGroupIDs)) {
+ $userIDs = [];
+ $conditionBuilder = new PreparedStatementConditionBuilder();
+ $conditionBuilder->add('groupID IN (?)', [$validGroupIDs]);
+ $sql = "SELECT DISTINCT userID
+ FROM wcf" . WCF_N . "_user_to_group
+ " . $conditionBuilder;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditionBuilder->getParameters());
+ while ($userID = $statement->fetchColumn()) {
+ $userIDs[] = $userID;
+ }
+
+ if (!empty($userIDs)) {
+ $users = UserProfileRuntimeCache::getInstance()->getObjects($userIDs);
+ UserStorageHandler::getInstance()->loadStorage($userIDs);
+
+ foreach ($users as $user) {
+ // user is author
+ if ($user->userID == WCF::getUser()->userID) {
+ continue;
+ } elseif (\in_array($user->userID, $existingParticipants)) {
+ continue;
+ }
+
+ try {
+ // validate user
+ self::validateParticipant($user, $field);
+
+ // no error
+ $result[] = $user->userID;
+ } catch (UserInputException $e) {
+ }
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Validates the given participant.
+ *
+ * @param UserProfile $user
+ * @param string $field
+ * @throws UserInputException
+ */
+ public static function validateParticipant(UserProfile $user, $field = 'participants')
+ {
+ // check participant's settings and permissions
+ if (!$user->getPermission('user.conversation.canUseConversation')) {
+ throw new UserInputException($field, 'canNotUseConversation');
+ }
+
+ if (!WCF::getSession()->getPermission('user.profile.cannotBeIgnored')) {
+ // check if user wants to receive any conversations
+ /** @noinspection PhpUndefinedFieldInspection */
+ if ($user->canSendConversation == 2) {
+ throw new UserInputException($field, 'doesNotAcceptConversation');
+ }
+
+ // check if user only wants to receive conversations by
+ // users they are following and if the active user is followed
+ // by the relevant user
+ /** @noinspection PhpUndefinedFieldInspection */
+ if ($user->canSendConversation == 1 && !$user->isFollowing(WCF::getUser()->userID)) {
+ throw new UserInputException($field, 'doesNotAcceptConversation');
+ }
+
+ // active user is ignored by participant
+ if ($user->isIgnoredUser(WCF::getUser()->userID)) {
+ throw new UserInputException($field, 'ignoresYou');
+ }
+
+ // check participant's mailbox quota
+ if (ConversationHandler::getInstance()->getConversationCount($user->userID) >= $user->getPermission('user.conversation.maxConversations')) {
+ throw new UserInputException($field, 'mailboxIsFull');
+ }
+ }
+ }
}
<?php
+
namespace wcf\data\conversation;
+
+use wcf\data\AbstractDatabaseObjectAction;
use wcf\data\conversation\label\ConversationLabel;
use wcf\data\conversation\message\ConversationMessageAction;
use wcf\data\conversation\message\ConversationMessageList;
use wcf\data\conversation\message\SimplifiedViewableConversationMessageList;
-use wcf\data\AbstractDatabaseObjectAction;
use wcf\data\IClipboardAction;
use wcf\data\IPopoverAction;
use wcf\data\IVisitableObjectAction;
/**
* Executes conversation-related actions.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
- *
- * @method ConversationEditor[] getObjects()
- * @method ConversationEditor getSingleObject()
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation
+ *
+ * @method ConversationEditor[] getObjects()
+ * @method ConversationEditor getSingleObject()
*/
-class ConversationAction extends AbstractDatabaseObjectAction implements IClipboardAction, IPopoverAction, IVisitableObjectAction {
- /**
- * @inheritDoc
- */
- protected $className = ConversationEditor::class;
-
- /**
- * conversation object
- * @var ConversationEditor
- */
- public $conversation;
-
- /**
- * list of conversation data modifications
- * @var mixed[][]
- */
- protected $conversationData = [];
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- * @return Conversation
- */
- public function create() {
- // create conversation
- $data = $this->parameters['data'];
- $data['lastPosterID'] = $data['userID'];
- $data['lastPoster'] = $data['username'];
- $data['lastPostTime'] = $data['time'];
- // count participants
- if (!empty($this->parameters['participants'])) {
- $data['participants'] = count($this->parameters['participants']);
- }
- // count attachments
- if (isset($this->parameters['attachmentHandler']) && $this->parameters['attachmentHandler'] !== null) {
- $data['attachments'] = count($this->parameters['attachmentHandler']);
- }
- $conversation = call_user_func([$this->className, 'create'], $data);
- $conversationEditor = new ConversationEditor($conversation);
-
- if (!$conversation->isDraft) {
- // save participants
- $conversationEditor->updateParticipants(
- (!empty($this->parameters['participants']) ? $this->parameters['participants'] : []),
- (!empty($this->parameters['invisibleParticipants']) ? $this->parameters['invisibleParticipants'] : []),
- 'all'
- );
-
- // add author
- if ($data['userID'] !== null) {
- $conversationEditor->updateParticipants([$data['userID']], [], 'all');
- }
-
- // update conversation count
- UserStorageHandler::getInstance()->reset($conversation->getParticipantIDs(), 'conversationCount');
-
- // mark conversation as read for the author
- $sql = "UPDATE wcf".WCF_N."_conversation_to_user
+class ConversationAction extends AbstractDatabaseObjectAction implements
+ IClipboardAction,
+ IPopoverAction,
+ IVisitableObjectAction
+{
+ /**
+ * @inheritDoc
+ */
+ protected $className = ConversationEditor::class;
+
+ /**
+ * conversation object
+ * @var ConversationEditor
+ */
+ public $conversation;
+
+ /**
+ * list of conversation data modifications
+ * @var mixed[][]
+ */
+ protected $conversationData = [];
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ * @return Conversation
+ */
+ public function create()
+ {
+ // create conversation
+ $data = $this->parameters['data'];
+ $data['lastPosterID'] = $data['userID'];
+ $data['lastPoster'] = $data['username'];
+ $data['lastPostTime'] = $data['time'];
+ // count participants
+ if (!empty($this->parameters['participants'])) {
+ $data['participants'] = \count($this->parameters['participants']);
+ }
+ // count attachments
+ if (isset($this->parameters['attachmentHandler']) && $this->parameters['attachmentHandler'] !== null) {
+ $data['attachments'] = \count($this->parameters['attachmentHandler']);
+ }
+ $conversation = \call_user_func([$this->className, 'create'], $data);
+ $conversationEditor = new ConversationEditor($conversation);
+
+ if (!$conversation->isDraft) {
+ // save participants
+ $conversationEditor->updateParticipants(
+ (!empty($this->parameters['participants']) ? $this->parameters['participants'] : []),
+ (!empty($this->parameters['invisibleParticipants']) ? $this->parameters['invisibleParticipants'] : []),
+ 'all'
+ );
+
+ // add author
+ if ($data['userID'] !== null) {
+ $conversationEditor->updateParticipants([$data['userID']], [], 'all');
+ }
+
+ // update conversation count
+ UserStorageHandler::getInstance()->reset($conversation->getParticipantIDs(), 'conversationCount');
+
+ // mark conversation as read for the author
+ $sql = "UPDATE wcf" . WCF_N . "_conversation_to_user
SET lastVisitTime = ?
WHERE participantID = ?
AND conversationID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute([$data['time'], $data['userID'], $conversation->conversationID]);
- }
- else {
- // update conversation count
- UserStorageHandler::getInstance()->reset([$data['userID']], 'conversationCount');
- }
-
- // update participant summary
- $conversationEditor->updateParticipantSummary();
-
- // create message
- $messageData = $this->parameters['messageData'];
- $messageData['conversationID'] = $conversation->conversationID;
- $messageData['time'] = $this->parameters['data']['time'];
- $messageData['userID'] = $this->parameters['data']['userID'];
- $messageData['username'] = $this->parameters['data']['username'];
-
- $messageAction = new ConversationMessageAction([], 'create', [
- 'data' => $messageData,
- 'conversation' => $conversation,
- 'isFirstPost' => true,
- 'attachmentHandler' => isset($this->parameters['attachmentHandler']) ? $this->parameters['attachmentHandler'] : null,
- 'htmlInputProcessor' => isset($this->parameters['htmlInputProcessor']) ? $this->parameters['htmlInputProcessor'] : null
- ]);
- $resultValues = $messageAction->executeAction();
-
- // update first message id
- $conversationEditor->update([
- 'firstMessageID' => $resultValues['returnValues']->messageID
- ]);
-
- $conversation->setFirstMessage($resultValues['returnValues']);
- if (!$conversation->isDraft) {
- // fire notification event
- $notificationRecipients = array_merge((!empty($this->parameters['participants']) ? $this->parameters['participants'] : []), (!empty($this->parameters['invisibleParticipants']) ? $this->parameters['invisibleParticipants'] : []));
- UserNotificationHandler::getInstance()->fireEvent(
- 'conversation',
- 'com.woltlab.wcf.conversation.notification',
- new ConversationUserNotificationObject($conversation),
- $notificationRecipients
- );
- }
-
- return $conversation;
- }
-
- /**
- * @inheritDoc
- */
- public function delete() {
- // deletes messages
- $messageList = new ConversationMessageList();
- $messageList->getConditionBuilder()->add('conversation_message.conversationID IN (?)', [$this->objectIDs]);
- $messageList->readObjectIDs();
- $action = new ConversationMessageAction($messageList->getObjectIDs(), 'delete');
- $action->executeAction();
-
- // get the list of participants in order to reset the 'unread conversation'-counter
- $participantIDs = [];
- if (!empty($this->objectIDs)) {
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID IN (?)", [$this->objectIDs]);
- $sql = "SELECT DISTINCT participantID
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([$data['time'], $data['userID'], $conversation->conversationID]);
+ } else {
+ // update conversation count
+ UserStorageHandler::getInstance()->reset([$data['userID']], 'conversationCount');
+ }
+
+ // update participant summary
+ $conversationEditor->updateParticipantSummary();
+
+ // create message
+ $messageData = $this->parameters['messageData'];
+ $messageData['conversationID'] = $conversation->conversationID;
+ $messageData['time'] = $this->parameters['data']['time'];
+ $messageData['userID'] = $this->parameters['data']['userID'];
+ $messageData['username'] = $this->parameters['data']['username'];
+
+ $messageAction = new ConversationMessageAction([], 'create', [
+ 'data' => $messageData,
+ 'conversation' => $conversation,
+ 'isFirstPost' => true,
+ 'attachmentHandler' => $this->parameters['attachmentHandler'] ?? null,
+ 'htmlInputProcessor' => $this->parameters['htmlInputProcessor'] ?? null,
+ ]);
+ $resultValues = $messageAction->executeAction();
+
+ // update first message id
+ $conversationEditor->update([
+ 'firstMessageID' => $resultValues['returnValues']->messageID,
+ ]);
+
+ $conversation->setFirstMessage($resultValues['returnValues']);
+ if (!$conversation->isDraft) {
+ // fire notification event
+ $notificationRecipients = \array_merge(
+ (!empty($this->parameters['participants']) ? $this->parameters['participants'] : [])(!empty($this->parameters['invisibleParticipants']) ? $this->parameters['invisibleParticipants'] : [])
+ );
+ UserNotificationHandler::getInstance()->fireEvent(
+ 'conversation',
+ 'com.woltlab.wcf.conversation.notification',
+ new ConversationUserNotificationObject($conversation),
+ $notificationRecipients
+ );
+ }
+
+ return $conversation;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function delete()
+ {
+ // deletes messages
+ $messageList = new ConversationMessageList();
+ $messageList->getConditionBuilder()->add('conversation_message.conversationID IN (?)', [$this->objectIDs]);
+ $messageList->readObjectIDs();
+ $action = new ConversationMessageAction($messageList->getObjectIDs(), 'delete');
+ $action->executeAction();
+
+ // get the list of participants in order to reset the 'unread conversation'-counter
+ $participantIDs = [];
+ if (!empty($this->objectIDs)) {
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("conversationID IN (?)", [$this->objectIDs]);
+ $sql = "SELECT DISTINCT participantID
FROM wcf" . WCF_N . "_conversation_to_user
" . $conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditions->getParameters());
-
- while ($participantID = $statement->fetchColumn()) {
- $participantIDs[] = $participantID;
- }
- }
-
- // delete conversations
- parent::delete();
-
- if (!empty($this->objectIDs)) {
- // delete notifications
- UserNotificationHandler::getInstance()->removeNotifications('com.woltlab.wcf.conversation.notification', $this->objectIDs);
-
- // remove modification logs
- ConversationModificationLogHandler::getInstance()->deleteLogs($this->objectIDs);
-
- // reset the number of unread conversations
- if (!empty($participantIDs)) {
- UserStorageHandler::getInstance()->reset($participantIDs, 'unreadConversationCount');
- }
- }
- }
-
- /**
- * @inheritDoc
- */
- public function update() {
- if (!isset($this->parameters['participants'])) $this->parameters['participants'] = [];
- if (!isset($this->parameters['invisibleParticipants'])) $this->parameters['invisibleParticipants'] = [];
-
- // count participants
- if (!empty($this->parameters['participants'])) {
- $this->parameters['data']['participants'] = count($this->parameters['participants']);
- }
-
- parent::update();
-
- foreach ($this->getObjects() as $conversation) {
- // participants
- if (!empty($this->parameters['participants']) || !empty($this->parameters['invisibleParticipants'])) {
- // get current participants
- $participantIDs = $conversation->getParticipantIDs();
-
- $conversation->updateParticipants(
- (!empty($this->parameters['participants']) ? $this->parameters['participants'] : []),
- (!empty($this->parameters['invisibleParticipants']) ? $this->parameters['invisibleParticipants'] : []),
- (!empty($this->parameters['visibility']) ? $this->parameters['visibility'] : 'all')
- );
- $conversation->updateParticipantSummary();
-
- // check if new participants have been added
- $newParticipantIDs = array_diff(array_merge($this->parameters['participants'], $this->parameters['invisibleParticipants']), $participantIDs);
- if (!empty($newParticipantIDs)) {
- // update conversation count
- UserStorageHandler::getInstance()->reset($newParticipantIDs, 'unreadConversationCount');
- UserStorageHandler::getInstance()->reset($newParticipantIDs, 'conversationCount');
-
- // fire notification event
- UserNotificationHandler::getInstance()->fireEvent(
- 'conversation',
- 'com.woltlab.wcf.conversation.notification',
- new ConversationUserNotificationObject($conversation->getDecoratedObject()),
- $newParticipantIDs
- );
- }
- }
-
- // draft status
- if (isset($this->parameters['data']['isDraft'])) {
- if ($conversation->isDraft && !$this->parameters['data']['isDraft']) {
- // add author
- $conversation->updateParticipants([$conversation->userID], [], 'all');
-
- // update conversation count
- UserStorageHandler::getInstance()->reset($conversation->getParticipantIDs(), 'unreadConversationCount');
- UserStorageHandler::getInstance()->reset($conversation->getParticipantIDs(), 'conversationCount');
- }
- }
- }
- }
-
- /**
- * @inheritDoc
- */
- public function markAsRead() {
- if (empty($this->parameters['visitTime'])) {
- $this->parameters['visitTime'] = TIME_NOW;
- }
-
- // in case this is a call via PHP and the userID parameter is missing, set it to the userID of the current user
- if (!isset($this->parameters['userID'])) {
- $this->parameters['userID'] = WCF::getUser()->userID;
- }
-
- if (empty($this->objects)) {
- $this->readObjects();
- }
-
- $conversationIDs = [];
- $sql = "UPDATE wcf".WCF_N."_conversation_to_user
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditions->getParameters());
+
+ while ($participantID = $statement->fetchColumn()) {
+ $participantIDs[] = $participantID;
+ }
+ }
+
+ // delete conversations
+ parent::delete();
+
+ if (!empty($this->objectIDs)) {
+ // delete notifications
+ UserNotificationHandler::getInstance()
+ ->removeNotifications('com.woltlab.wcf.conversation.notification', $this->objectIDs);
+
+ // remove modification logs
+ ConversationModificationLogHandler::getInstance()->deleteLogs($this->objectIDs);
+
+ // reset the number of unread conversations
+ if (!empty($participantIDs)) {
+ UserStorageHandler::getInstance()->reset($participantIDs, 'unreadConversationCount');
+ }
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function update()
+ {
+ if (!isset($this->parameters['participants'])) {
+ $this->parameters['participants'] = [];
+ }
+ if (!isset($this->parameters['invisibleParticipants'])) {
+ $this->parameters['invisibleParticipants'] = [];
+ }
+
+ // count participants
+ if (!empty($this->parameters['participants'])) {
+ $this->parameters['data']['participants'] = \count($this->parameters['participants']);
+ }
+
+ parent::update();
+
+ foreach ($this->getObjects() as $conversation) {
+ // participants
+ if (!empty($this->parameters['participants']) || !empty($this->parameters['invisibleParticipants'])) {
+ // get current participants
+ $participantIDs = $conversation->getParticipantIDs();
+
+ $conversation->updateParticipants(
+ (!empty($this->parameters['participants']) ? $this->parameters['participants'] : []),
+ (!empty($this->parameters['invisibleParticipants']) ? $this->parameters['invisibleParticipants'] : []),
+ (!empty($this->parameters['visibility']) ? $this->parameters['visibility'] : 'all')
+ );
+ $conversation->updateParticipantSummary();
+
+ // check if new participants have been added
+ $newParticipantIDs = \array_diff(\array_merge(
+ $this->parameters['participants'],
+ $this->parameters['invisibleParticipants']
+ ), $participantIDs);
+ if (!empty($newParticipantIDs)) {
+ // update conversation count
+ UserStorageHandler::getInstance()->reset($newParticipantIDs, 'unreadConversationCount');
+ UserStorageHandler::getInstance()->reset($newParticipantIDs, 'conversationCount');
+
+ // fire notification event
+ UserNotificationHandler::getInstance()->fireEvent(
+ 'conversation',
+ 'com.woltlab.wcf.conversation.notification',
+ new ConversationUserNotificationObject($conversation->getDecoratedObject()),
+ $newParticipantIDs
+ );
+ }
+ }
+
+ // draft status
+ if (isset($this->parameters['data']['isDraft'])) {
+ if ($conversation->isDraft && !$this->parameters['data']['isDraft']) {
+ // add author
+ $conversation->updateParticipants([$conversation->userID], [], 'all');
+
+ // update conversation count
+ UserStorageHandler::getInstance()
+ ->reset($conversation->getParticipantIDs(), 'unreadConversationCount');
+ UserStorageHandler::getInstance()
+ ->reset($conversation->getParticipantIDs(), 'conversationCount');
+ }
+ }
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function markAsRead()
+ {
+ if (empty($this->parameters['visitTime'])) {
+ $this->parameters['visitTime'] = TIME_NOW;
+ }
+
+ // in case this is a call via PHP and the userID parameter is missing, set it to the userID of the current user
+ if (!isset($this->parameters['userID'])) {
+ $this->parameters['userID'] = WCF::getUser()->userID;
+ }
+
+ if (empty($this->objects)) {
+ $this->readObjects();
+ }
+
+ $conversationIDs = [];
+ $sql = "UPDATE wcf" . WCF_N . "_conversation_to_user
SET lastVisitTime = ?
WHERE participantID = ?
AND conversationID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- WCF::getDB()->beginTransaction();
- foreach ($this->getObjects() as $conversation) {
- $statement->execute([
- $this->parameters['visitTime'],
- $this->parameters['userID'],
- $conversation->conversationID
- ]);
- $conversationIDs[] = $conversation->conversationID;
- }
- WCF::getDB()->commitTransaction();
-
- // reset storage
- UserStorageHandler::getInstance()->reset([$this->parameters['userID']], 'unreadConversationCount');
-
- // mark notifications as confirmed
- if (!empty($conversationIDs)) {
- // conversation start notification
- $conditionBuilder = new PreparedStatementConditionBuilder();
- $conditionBuilder->add('notification.eventID = ?', [UserNotificationHandler::getInstance()->getEvent('com.woltlab.wcf.conversation.notification', 'conversation')->eventID]);
- $conditionBuilder->add('notification.objectID = conversation.conversationID');
- $conditionBuilder->add('notification.userID = ?', [$this->parameters['userID']]);
- $conditionBuilder->add('conversation.conversationID IN (?)', [$conversationIDs]);
- $conditionBuilder->add('conversation.time <= ?', [$this->parameters['visitTime']]);
-
- $sql = "SELECT conversation.conversationID
- FROM wcf".WCF_N."_conversation conversation,
- wcf".WCF_N."_user_notification notification
- ".$conditionBuilder;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditionBuilder->getParameters());
- $notificationObjectIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
-
- if (!empty($notificationObjectIDs)) {
- UserNotificationHandler::getInstance()->markAsConfirmed('conversation', 'com.woltlab.wcf.conversation.notification', [$this->parameters['userID']], $notificationObjectIDs);
- }
-
- // conversation reply notification
- $conditionBuilder = new PreparedStatementConditionBuilder();
- $conditionBuilder->add('notification.eventID = ?', [UserNotificationHandler::getInstance()->getEvent('com.woltlab.wcf.conversation.message.notification', 'conversationMessage')->eventID]);
- $conditionBuilder->add('notification.objectID = conversation_message.messageID');
- $conditionBuilder->add('notification.userID = ?', [$this->parameters['userID']]);
- $conditionBuilder->add('conversation_message.conversationID IN (?)', [$conversationIDs]);
- $conditionBuilder->add('conversation_message.time <= ?', [$this->parameters['visitTime']]);
-
- $sql = "SELECT conversation_message.messageID
- FROM wcf".WCF_N."_conversation_message conversation_message,
- wcf".WCF_N."_user_notification notification
- ".$conditionBuilder;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditionBuilder->getParameters());
- $notificationObjectIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
-
- if (!empty($notificationObjectIDs)) {
- UserNotificationHandler::getInstance()->markAsConfirmed('conversationMessage', 'com.woltlab.wcf.conversation.message.notification', [$this->parameters['userID']], $notificationObjectIDs);
- }
- }
-
- if (!empty($conversationIDs)) {
- $this->unmarkItems($conversationIDs);
- }
-
- $returnValues = [
- 'totalCount' => ConversationHandler::getInstance()->getUnreadConversationCount($this->parameters['userID'], true)
- ];
-
- if (count($conversationIDs) == 1) {
- $returnValues['markAsRead'] = reset($conversationIDs);
- }
-
- return $returnValues;
- }
-
- /**
- * @inheritDoc
- */
- public function validateMarkAsRead() {
- // visitTime might not be in the future
- if (isset($this->parameters['visitTime'])) {
- $this->parameters['visitTime'] = intval($this->parameters['visitTime']);
- if ($this->parameters['visitTime'] > TIME_NOW) {
- $this->parameters['visitTime'] = TIME_NOW;
- }
- }
-
- // userID should always be equal to the userID of the current user when called via AJAX
- $this->parameters['userID'] = WCF::getUser()->userID;
-
- if (empty($this->objects)) {
- $this->readObjects();
- }
-
- // check participation
- $conversationIDs = [];
- foreach ($this->getObjects() as $conversation) {
- $conversationIDs[] = $conversation->conversationID;
- }
-
- if (empty($conversationIDs)) {
- throw new UserInputException('objectIDs');
- }
-
- if (!Conversation::isParticipant($conversationIDs)) {
- throw new PermissionDeniedException();
- }
- }
-
- /**
- * Marks all conversations as read.
- */
- public function markAllAsRead() {
- $sql = "UPDATE wcf".WCF_N."_conversation_to_user
+ $statement = WCF::getDB()->prepareStatement($sql);
+ WCF::getDB()->beginTransaction();
+ foreach ($this->getObjects() as $conversation) {
+ $statement->execute([
+ $this->parameters['visitTime'],
+ $this->parameters['userID'],
+ $conversation->conversationID,
+ ]);
+ $conversationIDs[] = $conversation->conversationID;
+ }
+ WCF::getDB()->commitTransaction();
+
+ // reset storage
+ UserStorageHandler::getInstance()->reset([$this->parameters['userID']], 'unreadConversationCount');
+
+ // mark notifications as confirmed
+ if (!empty($conversationIDs)) {
+ // conversation start notification
+ $conditionBuilder = new PreparedStatementConditionBuilder();
+ $conditionBuilder->add('notification.eventID = ?', [
+ UserNotificationHandler::getInstance()
+ ->getEvent('com.woltlab.wcf.conversation.notification', 'conversation')
+ ->eventID,
+ ]);
+ $conditionBuilder->add('notification.objectID = conversation.conversationID');
+ $conditionBuilder->add('notification.userID = ?', [$this->parameters['userID']]);
+ $conditionBuilder->add('conversation.conversationID IN (?)', [$conversationIDs]);
+ $conditionBuilder->add('conversation.time <= ?', [$this->parameters['visitTime']]);
+
+ $sql = "SELECT conversation.conversationID
+ FROM wcf" . WCF_N . "_conversation conversation,
+ wcf" . WCF_N . "_user_notification notification
+ " . $conditionBuilder;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditionBuilder->getParameters());
+ $notificationObjectIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
+
+ if (!empty($notificationObjectIDs)) {
+ UserNotificationHandler::getInstance()->markAsConfirmed(
+ 'conversation',
+ 'com.woltlab.wcf.conversation.notification',
+ [$this->parameters['userID']],
+ $notificationObjectIDs
+ );
+ }
+
+ // conversation reply notification
+ $conditionBuilder = new PreparedStatementConditionBuilder();
+ $conditionBuilder->add('notification.eventID = ?', [
+ UserNotificationHandler::getInstance()
+ ->getEvent('com.woltlab.wcf.conversation.message.notification', 'conversationMessage')
+ ->eventID,
+ ]);
+ $conditionBuilder->add('notification.objectID = conversation_message.messageID');
+ $conditionBuilder->add('notification.userID = ?', [$this->parameters['userID']]);
+ $conditionBuilder->add('conversation_message.conversationID IN (?)', [$conversationIDs]);
+ $conditionBuilder->add('conversation_message.time <= ?', [$this->parameters['visitTime']]);
+
+ $sql = "SELECT conversation_message.messageID
+ FROM wcf" . WCF_N . "_conversation_message conversation_message,
+ wcf" . WCF_N . "_user_notification notification
+ " . $conditionBuilder;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditionBuilder->getParameters());
+ $notificationObjectIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
+
+ if (!empty($notificationObjectIDs)) {
+ UserNotificationHandler::getInstance()->markAsConfirmed(
+ 'conversationMessage',
+ 'com.woltlab.wcf.conversation.message.notification',
+ [$this->parameters['userID']],
+ $notificationObjectIDs
+ );
+ }
+ }
+
+ if (!empty($conversationIDs)) {
+ $this->unmarkItems($conversationIDs);
+ }
+
+ $returnValues = [
+ 'totalCount' => ConversationHandler::getInstance()
+ ->getUnreadConversationCount($this->parameters['userID'], true),
+ ];
+
+ if (\count($conversationIDs) == 1) {
+ $returnValues['markAsRead'] = \reset($conversationIDs);
+ }
+
+ return $returnValues;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function validateMarkAsRead()
+ {
+ // visitTime might not be in the future
+ if (isset($this->parameters['visitTime'])) {
+ $this->parameters['visitTime'] = \intval($this->parameters['visitTime']);
+ if ($this->parameters['visitTime'] > TIME_NOW) {
+ $this->parameters['visitTime'] = TIME_NOW;
+ }
+ }
+
+ // userID should always be equal to the userID of the current user when called via AJAX
+ $this->parameters['userID'] = WCF::getUser()->userID;
+
+ if (empty($this->objects)) {
+ $this->readObjects();
+ }
+
+ // check participation
+ $conversationIDs = [];
+ foreach ($this->getObjects() as $conversation) {
+ $conversationIDs[] = $conversation->conversationID;
+ }
+
+ if (empty($conversationIDs)) {
+ throw new UserInputException('objectIDs');
+ }
+
+ if (!Conversation::isParticipant($conversationIDs)) {
+ throw new PermissionDeniedException();
+ }
+ }
+
+ /**
+ * Marks all conversations as read.
+ */
+ public function markAllAsRead()
+ {
+ $sql = "UPDATE wcf" . WCF_N . "_conversation_to_user
SET lastVisitTime = ?
WHERE participantID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute([
- TIME_NOW,
- WCF::getUser()->userID
- ]);
-
- // reset storage
- UserStorageHandler::getInstance()->reset([WCF::getUser()->userID], 'unreadConversationCount');
-
- // confirm obsolete notifications
- UserNotificationHandler::getInstance()->markAsConfirmed('conversation', 'com.woltlab.wcf.conversation.notification', [WCF::getUser()->userID]);
- UserNotificationHandler::getInstance()->markAsConfirmed('conversationMessage', 'com.woltlab.wcf.conversation.message.notification', [WCF::getUser()->userID]);
-
- return [
- 'markAllAsRead' => true
- ];
- }
-
- /**
- * Validates the markAllAsRead action.
- */
- public function validateMarkAllAsRead() {
- // does nothing
- }
-
- /**
- * Validates user access for label management.
- *
- * @throws PermissionDeniedException
- */
- public function validateGetLabelManagement() {
- if (!WCF::getSession()->getPermission('user.conversation.canUseConversation')) {
- throw new PermissionDeniedException();
- }
- }
-
- /**
- * Returns the conversation label management.
- *
- * @return array
- */
- public function getLabelManagement() {
- WCF::getTPL()->assign([
- 'cssClassNames' => ConversationLabel::getLabelCssClassNames(),
- 'labelList' => ConversationLabel::getLabelsByUser()
- ]);
-
- return [
- 'actionName' => 'getLabelManagement',
- 'template' => WCF::getTPL()->fetch('conversationLabelManagement'),
- 'maxLabels' => WCF::getSession()->getPermission('user.conversation.maxLabels'),
- 'labelCount' => count(ConversationLabel::getLabelsByUser())
- ];
- }
-
- /**
- * @inheritDoc
- */
- public function validateGetPopover() {
- $this->conversation = $this->getSingleObject();
- if (!Conversation::isParticipant([$this->conversation->conversationID])) {
- throw new PermissionDeniedException();
- }
- }
-
- /**
- * @inheritDoc
- */
- public function getPopover() {
- $messageList = new SimplifiedViewableConversationMessageList();
- $messageList->getConditionBuilder()->add("conversation_message.messageID = ?", [$this->conversation->firstMessageID]);
- $messageList->readObjects();
-
- return [
- 'template' => WCF::getTPL()->fetch('conversationMessagePreview', 'wcf', [
- 'message' => $messageList->getSingleObject(),
- ]),
- ];
- }
-
- /**
- * Validates the get message preview action.
- *
- * @throws PermissionDeniedException
- * @deprecated 5.3 Use `validateGetPopover()` instead.
- */
- public function validateGetMessagePreview() {
- $this->validateGetPopover();
- }
-
- /**
- * Returns a preview of a message in a specific conversation.
- *
- * @return string[]
- * @deprecated 5.3 Use `getPopover()` instead.
- */
- public function getMessagePreview() {
- return $this->getPopover();
- }
-
- /**
- * Validates parameters to close conversations.
- *
- * @throws PermissionDeniedException
- * @throws UserInputException
- */
- public function validateClose() {
- // read objects
- if (empty($this->objects)) {
- $this->readObjects();
-
- if (empty($this->objects)) {
- throw new UserInputException('objectIDs');
- }
- }
-
- // validate ownership
- foreach ($this->getObjects() as $conversation) {
- if ($conversation->isClosed || ($conversation->userID != WCF::getUser()->userID)) {
- throw new PermissionDeniedException();
- }
- }
- }
-
- /**
- * Closes conversations.
- *
- * @return mixed[][]
- */
- public function close() {
- foreach ($this->getObjects() as $conversation) {
- $conversation->update(['isClosed' => 1]);
- $this->addConversationData($conversation->getDecoratedObject(), 'isClosed', 1);
-
- ConversationModificationLogHandler::getInstance()->close($conversation->getDecoratedObject());
- }
-
- $this->unmarkItems();
-
- return $this->getConversationData();
- }
-
- /**
- * Validates parameters to open conversations.
- *
- * @throws PermissionDeniedException
- * @throws UserInputException
- */
- public function validateOpen() {
- // read objects
- if (empty($this->objects)) {
- $this->readObjects();
-
- if (empty($this->objects)) {
- throw new UserInputException('objectIDs');
- }
- }
-
- // validate ownership
- foreach ($this->getObjects() as $conversation) {
- if (!$conversation->isClosed || ($conversation->userID != WCF::getUser()->userID)) {
- throw new PermissionDeniedException();
- }
- }
- }
-
- /**
- * Opens conversations.
- *
- * @return mixed[][]
- */
- public function open() {
- foreach ($this->getObjects() as $conversation) {
- $conversation->update(['isClosed' => 0]);
- $this->addConversationData($conversation->getDecoratedObject(), 'isClosed', 0);
-
- ConversationModificationLogHandler::getInstance()->open($conversation->getDecoratedObject());
- }
-
- $this->unmarkItems();
-
- return $this->getConversationData();
- }
-
- /**
- * Validates conversations for leave form.
- *
- * @throws PermissionDeniedException
- * @throws UserInputException
- */
- public function validateGetLeaveForm() {
- if (empty($this->objectIDs)) {
- throw new UserInputException('objectIDs');
- }
-
- // validate participation
- if (!Conversation::isParticipant($this->objectIDs)) {
- throw new PermissionDeniedException();
- }
- }
-
- /**
- * Returns dialog form to leave conversations.
- *
- * @return array
- */
- public function getLeaveForm() {
- // get hidden state from first conversation (all others have the same state)
- $sql = "SELECT hideConversation
- FROM wcf".WCF_N."_conversation_to_user
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([
+ TIME_NOW,
+ WCF::getUser()->userID,
+ ]);
+
+ // reset storage
+ UserStorageHandler::getInstance()->reset([WCF::getUser()->userID], 'unreadConversationCount');
+
+ // confirm obsolete notifications
+ UserNotificationHandler::getInstance()->markAsConfirmed(
+ 'conversation',
+ 'com.woltlab.wcf.conversation.notification',
+ [WCF::getUser()->userID]
+ );
+ UserNotificationHandler::getInstance()->markAsConfirmed(
+ 'conversationMessage',
+ 'com.woltlab.wcf.conversation.message.notification',
+ [WCF::getUser()->userID]
+ );
+
+ return [
+ 'markAllAsRead' => true,
+ ];
+ }
+
+ /**
+ * Validates the markAllAsRead action.
+ */
+ public function validateMarkAllAsRead()
+ {
+ // does nothing
+ }
+
+ /**
+ * Validates user access for label management.
+ *
+ * @throws PermissionDeniedException
+ */
+ public function validateGetLabelManagement()
+ {
+ if (!WCF::getSession()->getPermission('user.conversation.canUseConversation')) {
+ throw new PermissionDeniedException();
+ }
+ }
+
+ /**
+ * Returns the conversation label management.
+ *
+ * @return array
+ */
+ public function getLabelManagement()
+ {
+ WCF::getTPL()->assign([
+ 'cssClassNames' => ConversationLabel::getLabelCssClassNames(),
+ 'labelList' => ConversationLabel::getLabelsByUser(),
+ ]);
+
+ return [
+ 'actionName' => 'getLabelManagement',
+ 'template' => WCF::getTPL()->fetch('conversationLabelManagement'),
+ 'maxLabels' => WCF::getSession()->getPermission('user.conversation.maxLabels'),
+ 'labelCount' => \count(ConversationLabel::getLabelsByUser()),
+ ];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function validateGetPopover()
+ {
+ $this->conversation = $this->getSingleObject();
+ if (!Conversation::isParticipant([$this->conversation->conversationID])) {
+ throw new PermissionDeniedException();
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getPopover()
+ {
+ $messageList = new SimplifiedViewableConversationMessageList();
+ $messageList->getConditionBuilder()
+ ->add("conversation_message.messageID = ?", [$this->conversation->firstMessageID]);
+ $messageList->readObjects();
+
+ return [
+ 'template' => WCF::getTPL()->fetch('conversationMessagePreview', 'wcf', [
+ 'message' => $messageList->getSingleObject(),
+ ]),
+ ];
+ }
+
+ /**
+ * Validates the get message preview action.
+ *
+ * @throws PermissionDeniedException
+ * @deprecated 5.3 Use `validateGetPopover()` instead.
+ */
+ public function validateGetMessagePreview()
+ {
+ $this->validateGetPopover();
+ }
+
+ /**
+ * Returns a preview of a message in a specific conversation.
+ *
+ * @return string[]
+ * @deprecated 5.3 Use `getPopover()` instead.
+ */
+ public function getMessagePreview()
+ {
+ return $this->getPopover();
+ }
+
+ /**
+ * Validates parameters to close conversations.
+ *
+ * @throws PermissionDeniedException
+ * @throws UserInputException
+ */
+ public function validateClose()
+ {
+ // read objects
+ if (empty($this->objects)) {
+ $this->readObjects();
+
+ if (empty($this->objects)) {
+ throw new UserInputException('objectIDs');
+ }
+ }
+
+ // validate ownership
+ foreach ($this->getObjects() as $conversation) {
+ if ($conversation->isClosed || ($conversation->userID != WCF::getUser()->userID)) {
+ throw new PermissionDeniedException();
+ }
+ }
+ }
+
+ /**
+ * Closes conversations.
+ *
+ * @return mixed[][]
+ */
+ public function close()
+ {
+ foreach ($this->getObjects() as $conversation) {
+ $conversation->update(['isClosed' => 1]);
+ $this->addConversationData($conversation->getDecoratedObject(), 'isClosed', 1);
+
+ ConversationModificationLogHandler::getInstance()->close($conversation->getDecoratedObject());
+ }
+
+ $this->unmarkItems();
+
+ return $this->getConversationData();
+ }
+
+ /**
+ * Validates parameters to open conversations.
+ *
+ * @throws PermissionDeniedException
+ * @throws UserInputException
+ */
+ public function validateOpen()
+ {
+ // read objects
+ if (empty($this->objects)) {
+ $this->readObjects();
+
+ if (empty($this->objects)) {
+ throw new UserInputException('objectIDs');
+ }
+ }
+
+ // validate ownership
+ foreach ($this->getObjects() as $conversation) {
+ if (!$conversation->isClosed || ($conversation->userID != WCF::getUser()->userID)) {
+ throw new PermissionDeniedException();
+ }
+ }
+ }
+
+ /**
+ * Opens conversations.
+ *
+ * @return mixed[][]
+ */
+ public function open()
+ {
+ foreach ($this->getObjects() as $conversation) {
+ $conversation->update(['isClosed' => 0]);
+ $this->addConversationData($conversation->getDecoratedObject(), 'isClosed', 0);
+
+ ConversationModificationLogHandler::getInstance()->open($conversation->getDecoratedObject());
+ }
+
+ $this->unmarkItems();
+
+ return $this->getConversationData();
+ }
+
+ /**
+ * Validates conversations for leave form.
+ *
+ * @throws PermissionDeniedException
+ * @throws UserInputException
+ */
+ public function validateGetLeaveForm()
+ {
+ if (empty($this->objectIDs)) {
+ throw new UserInputException('objectIDs');
+ }
+
+ // validate participation
+ if (!Conversation::isParticipant($this->objectIDs)) {
+ throw new PermissionDeniedException();
+ }
+ }
+
+ /**
+ * Returns dialog form to leave conversations.
+ *
+ * @return array
+ */
+ public function getLeaveForm()
+ {
+ // get hidden state from first conversation (all others have the same state)
+ $sql = "SELECT hideConversation
+ FROM wcf" . WCF_N . "_conversation_to_user
WHERE conversationID = ?
AND participantID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute([
- current($this->objectIDs),
- WCF::getUser()->userID
- ]);
- $row = $statement->fetchArray();
-
- WCF::getTPL()->assign('hideConversation', ($row !== false ? $row['hideConversation'] : 0));
-
- return [
- 'actionName' => 'getLeaveForm',
- 'template' => WCF::getTPL()->fetch('conversationLeave')
- ];
- }
-
- /**
- * Validates parameters to hide conversations.
- *
- * @throws PermissionDeniedException
- * @throws UserInputException
- */
- public function validateHideConversation() {
- $this->parameters['hideConversation'] = isset($this->parameters['hideConversation']) ? intval($this->parameters['hideConversation']) : null;
- if ($this->parameters['hideConversation'] === null || !in_array($this->parameters['hideConversation'], [Conversation::STATE_DEFAULT, Conversation::STATE_HIDDEN, Conversation::STATE_LEFT])) {
- throw new UserInputException('hideConversation');
- }
-
- if (empty($this->objectIDs)) {
- throw new UserInputException('objectIDs');
- }
-
- // validate participation
- if (!Conversation::isParticipant($this->objectIDs)) {
- throw new PermissionDeniedException();
- }
- }
-
- /**
- * Hides or restores conversations.
- *
- * @return string[]
- */
- public function hideConversation() {
- $sql = "UPDATE wcf".WCF_N."_conversation_to_user
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([
+ \current($this->objectIDs),
+ WCF::getUser()->userID,
+ ]);
+ $row = $statement->fetchArray();
+
+ WCF::getTPL()->assign('hideConversation', ($row !== false ? $row['hideConversation'] : 0));
+
+ return [
+ 'actionName' => 'getLeaveForm',
+ 'template' => WCF::getTPL()->fetch('conversationLeave'),
+ ];
+ }
+
+ /**
+ * Validates parameters to hide conversations.
+ *
+ * @throws PermissionDeniedException
+ * @throws UserInputException
+ */
+ public function validateHideConversation()
+ {
+ $this->parameters['hideConversation'] = isset($this->parameters['hideConversation']) ? \intval($this->parameters['hideConversation']) : null;
+ if (
+ $this->parameters['hideConversation'] === null
+ || !\in_array(
+ $this->parameters['hideConversation'],
+ [Conversation::STATE_DEFAULT, Conversation::STATE_HIDDEN, Conversation::STATE_LEFT]
+ )
+ ) {
+ throw new UserInputException('hideConversation');
+ }
+
+ if (empty($this->objectIDs)) {
+ throw new UserInputException('objectIDs');
+ }
+
+ // validate participation
+ if (!Conversation::isParticipant($this->objectIDs)) {
+ throw new PermissionDeniedException();
+ }
+ }
+
+ /**
+ * Hides or restores conversations.
+ *
+ * @return string[]
+ */
+ public function hideConversation()
+ {
+ $sql = "UPDATE wcf" . WCF_N . "_conversation_to_user
SET hideConversation = ?
WHERE conversationID = ?
AND participantID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
-
- WCF::getDB()->beginTransaction();
- foreach ($this->objectIDs as $conversationID) {
- $statement->execute([
- $this->parameters['hideConversation'],
- $conversationID,
- WCF::getUser()->userID
- ]);
- }
- WCF::getDB()->commitTransaction();
-
- // reset user's conversation counters if user leaves conversation
- // permanently
- if ($this->parameters['hideConversation'] == Conversation::STATE_LEFT) {
- UserStorageHandler::getInstance()->reset([WCF::getUser()->userID], 'conversationCount');
- UserStorageHandler::getInstance()->reset([WCF::getUser()->userID], 'unreadConversationCount');
- }
-
- // add modification log entry
- if ($this->parameters['hideConversation'] == Conversation::STATE_LEFT) {
- if (empty($this->objects)) $this->readObjects();
-
- foreach ($this->getObjects() as $conversation) {
- ConversationModificationLogHandler::getInstance()->leave($conversation->getDecoratedObject());
- }
- }
-
- // unmark items
- $this->unmarkItems();
-
- if ($this->parameters['hideConversation'] == Conversation::STATE_LEFT) {
- // update participants count and participant summary
- ConversationEditor::updateParticipantCounts($this->objectIDs);
- ConversationEditor::updateParticipantSummaries($this->objectIDs);
-
- // delete conversation if all users have left it
- $conditionBuilder = new PreparedStatementConditionBuilder();
- $conditionBuilder->add('conversation.conversationID IN (?)', [$this->objectIDs]);
- $conditionBuilder->add('conversation_to_user.conversationID IS NULL');
- $sql = "SELECT DISTINCT conversation.conversationID
- FROM wcf".WCF_N."_conversation conversation
- LEFT JOIN wcf".WCF_N."_conversation_to_user conversation_to_user
+ $statement = WCF::getDB()->prepareStatement($sql);
+
+ WCF::getDB()->beginTransaction();
+ foreach ($this->objectIDs as $conversationID) {
+ $statement->execute([
+ $this->parameters['hideConversation'],
+ $conversationID,
+ WCF::getUser()->userID,
+ ]);
+ }
+ WCF::getDB()->commitTransaction();
+
+ // reset user's conversation counters if user leaves conversation
+ // permanently
+ if ($this->parameters['hideConversation'] == Conversation::STATE_LEFT) {
+ UserStorageHandler::getInstance()->reset([WCF::getUser()->userID], 'conversationCount');
+ UserStorageHandler::getInstance()->reset([WCF::getUser()->userID], 'unreadConversationCount');
+ }
+
+ // add modification log entry
+ if ($this->parameters['hideConversation'] == Conversation::STATE_LEFT) {
+ if (empty($this->objects)) {
+ $this->readObjects();
+ }
+
+ foreach ($this->getObjects() as $conversation) {
+ ConversationModificationLogHandler::getInstance()->leave($conversation->getDecoratedObject());
+ }
+ }
+
+ // unmark items
+ $this->unmarkItems();
+
+ if ($this->parameters['hideConversation'] == Conversation::STATE_LEFT) {
+ // update participants count and participant summary
+ ConversationEditor::updateParticipantCounts($this->objectIDs);
+ ConversationEditor::updateParticipantSummaries($this->objectIDs);
+
+ // delete conversation if all users have left it
+ $conditionBuilder = new PreparedStatementConditionBuilder();
+ $conditionBuilder->add('conversation.conversationID IN (?)', [$this->objectIDs]);
+ $conditionBuilder->add('conversation_to_user.conversationID IS NULL');
+ $sql = "SELECT DISTINCT conversation.conversationID
+ FROM wcf" . WCF_N . "_conversation conversation
+ LEFT JOIN wcf" . WCF_N . "_conversation_to_user conversation_to_user
ON ( conversation_to_user.conversationID = conversation.conversationID
- AND conversation_to_user.hideConversation <> ".Conversation::STATE_LEFT."
+ AND conversation_to_user.hideConversation <> " . Conversation::STATE_LEFT . "
AND conversation_to_user.participantID IS NOT NULL)
- ".$conditionBuilder;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditionBuilder->getParameters());
- $conversationIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
-
- if (!empty($conversationIDs)) {
- $action = new ConversationAction($conversationIDs, 'delete');
- $action->executeAction();
- }
- }
-
- return [
- 'actionName' => 'hideConversation',
- 'redirectURL' => LinkHandler::getInstance()->getLink('ConversationList')
- ];
- }
-
- /**
- * Validates parameters to return the mixed conversation list.
- */
- public function validateGetMixedConversationList() {
- // does nothing
- }
-
- /**
- * Returns a mixed conversation list with up to 10 unread conversations.
- *
- * @return mixed[][]
- */
- public function getMixedConversationList() {
- $sqlSelect = ' , (SELECT participantID FROM wcf'.WCF_N.'_conversation_to_user WHERE conversationID = conversation.conversationID AND participantID <> conversation.userID AND isInvisible = 0 ORDER BY username, participantID LIMIT 1) AS otherParticipantID
- , (SELECT username FROM wcf'.WCF_N.'_conversation_to_user WHERE conversationID = conversation.conversationID AND participantID <> conversation.userID AND isInvisible = 0 ORDER BY username, participantID LIMIT 1) AS otherParticipant';
-
- $unreadConversationList = new UserConversationList(WCF::getUser()->userID);
- $unreadConversationList->sqlSelects .= $sqlSelect;
- $unreadConversationList->getConditionBuilder()->add('conversation_to_user.lastVisitTime < lastPostTime');
- $unreadConversationList->sqlLimit = 10;
- $unreadConversationList->sqlOrderBy = 'lastPostTime DESC';
- $unreadConversationList->readObjects();
-
- $conversations = [];
- $count = 0;
- foreach ($unreadConversationList as $conversation) {
- $conversations[] = $conversation;
- $count++;
- }
-
- if ($count < 10) {
- $conversationList = new UserConversationList(WCF::getUser()->userID);
- $conversationList->sqlSelects .= $sqlSelect;
- $conversationList->getConditionBuilder()->add('conversation_to_user.lastVisitTime >= lastPostTime');
- $conversationList->sqlLimit = (10 - $count);
- $conversationList->sqlOrderBy = 'lastPostTime DESC';
- $conversationList->readObjects();
-
- foreach ($conversationList as $conversation) {
- $conversations[] = $conversation;
- }
- }
-
- WCF::getTPL()->assign([
- 'conversations' => $conversations
- ]);
-
- $totalCount = ConversationHandler::getInstance()->getUnreadConversationCount();
- if ($count < 10 && $count < $totalCount) {
- UserStorageHandler::getInstance()->reset([WCF::getUser()->userID], 'unreadConversationCount');
- }
-
- return [
- 'template' => WCF::getTPL()->fetch('conversationListUserPanel'),
- 'totalCount' => $totalCount
- ];
- }
-
- /**
- * Validates the 'unmarkAll' action.
- */
- public function validateUnmarkAll() {
- // does nothing
- }
-
- /**
- * Unmarks all conversations.
- */
- public function unmarkAll() {
- ClipboardHandler::getInstance()->removeItems(ClipboardHandler::getInstance()->getObjectTypeID('com.woltlab.wcf.conversation.conversation'));
- }
-
- /**
- * Validates parameters to display the 'add participants' form.
- *
- * @throws PermissionDeniedException
- */
- public function validateGetAddParticipantsForm() {
- $this->conversation = $this->getSingleObject();
- if (!Conversation::isParticipant([$this->conversation->conversationID]) || !$this->conversation->canAddParticipants()) {
- throw new PermissionDeniedException();
- }
- }
-
- /**
- * Shows the 'add participants' form.
- *
- * @return array
- */
- public function getAddParticipantsForm() {
- $restrictUserGroupIDs = [];
- foreach (UserGroup::getAllGroups() as $group) {
- if ($group->canBeAddedAsConversationParticipant) {
- $restrictUserGroupIDs[] = $group->groupID;
- }
- }
-
- return [
- 'excludedSearchValues' => $this->conversation->getParticipantNames(false, true),
- 'maxItems' => WCF::getSession()->getPermission('user.conversation.maxParticipants') - $this->conversation->participants,
- 'canAddGroupParticipants' => WCF::getSession()->getPermission('user.conversation.canAddGroupParticipants'),
- 'template' => WCF::getTPL()->fetch('conversationAddParticipants', 'wcf', ['conversation' => $this->conversation]),
- 'restrictUserGroupIDs' => $restrictUserGroupIDs,
- ];
- }
-
- /**
- * Validates parameters to add new participants.
- */
- public function validateAddParticipants() {
- $this->validateGetAddParticipantsForm();
-
- // validate participants
- $this->readStringArray('participants', true);
- $this->readIntegerArray('participantsGroupIDs', true);
-
- if (!$this->conversation->getDecoratedObject()->isDraft) {
- $this->readString('visibility');
- if (!in_array($this->parameters['visibility'], ['all', 'new'])) {
- throw new UserInputException('visibility');
- }
-
- if ($this->parameters['visibility'] === 'all' && !$this->conversation->canAddParticipantsUnrestricted()) {
- throw new UserInputException('visibility');
- }
- }
- }
-
- /**
- * Adds new participants.
- *
- * @return array
- */
- public function addParticipants() {
- try {
- $existingParticipants = $this->conversation->getParticipantIDs(true);
- $participantIDs = Conversation::validateParticipants($this->parameters['participants'], 'participants', $existingParticipants);
- if (!empty($this->parameters['participantsGroupIDs']) && WCF::getSession()->getPermission('user.conversation.canAddGroupParticipants')) {
- $validGroupParticipants = Conversation::validateGroupParticipants($this->parameters['participantsGroupIDs'], 'participants', $existingParticipants);
- $validGroupParticipants = array_diff($validGroupParticipants, $participantIDs);
- if (empty($validGroupParticipants)) {
- throw new UserInputException('participants', 'emptyGroup');
- }
- $participantIDs = array_merge($participantIDs, $validGroupParticipants);
- }
-
- $parameters = [
- 'participantIDs' => $participantIDs,
- ];
- EventHandler::getInstance()->fireAction($this, 'addParticipants_validateParticipants', $parameters);
- $participantIDs = $parameters['participantIDs'];
- }
- catch (UserInputException $e) {
- $errorMessage = '';
- $errors = is_array($e->getType()) ? $e->getType() : [['type' => $e->getType()]];
- foreach ($errors as $type) {
- if (!empty($errorMessage)) $errorMessage .= ' ';
- $errorMessage .= WCF::getLanguage()->getDynamicVariable('wcf.conversation.participants.error.'.$type['type'], ['errorData' => $type]);
- }
-
- return [
- 'actionName' => 'addParticipants',
- 'errorMessage' => $errorMessage
- ];
- }
-
- // validate limit
- $newCount = $this->conversation->participants + count($participantIDs);
- if ($newCount > WCF::getSession()->getPermission('user.conversation.maxParticipants')) {
- return [
- 'actionName' => 'addParticipants',
- 'errorMessage' => WCF::getLanguage()->getDynamicVariable('wcf.conversation.participants.error.tooManyParticipants')
- ];
- }
-
- $count = 0;
- $successMessage = '';
- if (!empty($participantIDs)) {
- // check for already added participants
- if ($this->conversation->isDraft) {
- $draftData = unserialize($this->conversation->draftData);
- $draftData['participants'] = array_merge($draftData['participants'], $participantIDs);
- $data = ['data' => ['draftData' => serialize($draftData)]];
- }
- else {
- $data = [
- 'participants' => $participantIDs,
- 'visibility' => (isset($this->parameters['visibility'])) ? $this->parameters['visibility'] : 'all'
- ];
- }
-
- $conversationAction = new ConversationAction([$this->conversation], 'update', $data);
- $conversationAction->executeAction();
-
- $count = count($participantIDs);
- $successMessage = WCF::getLanguage()->getDynamicVariable('wcf.conversation.edit.addParticipants.success', ['count' => $count]);
-
- ConversationModificationLogHandler::getInstance()->addParticipants($this->conversation->getDecoratedObject(), $participantIDs);
-
- if (!$this->conversation->isDraft) {
- // update participant summary
- $this->conversation->updateParticipantSummary();
- }
- }
-
- return [
- 'count' => $count,
- 'successMessage' => $successMessage
- ];
- }
-
- /**
- * Validates parameters to remove a participant from a conversation.
- *
- * @throws PermissionDeniedException
- * @throws UserInputException
- */
- public function validateRemoveParticipant() {
- $this->readInteger('userID');
-
- // validate conversation
- $this->conversation = $this->getSingleObject();
- if (!$this->conversation->conversationID) {
- throw new UserInputException('objectIDs');
- }
-
- // check ownership
- if ($this->conversation->userID != WCF::getUser()->userID) {
- throw new PermissionDeniedException();
- }
-
- // validate participants
- if ($this->parameters['userID'] == WCF::getUser()->userID || !Conversation::isParticipant([$this->conversation->conversationID]) || !Conversation::isParticipant([$this->conversation->conversationID], $this->parameters['userID'])) {
- throw new PermissionDeniedException();
- }
-
- }
-
- /**
- * Removes a participant from a conversation.
- */
- public function removeParticipant() {
- $this->conversation->removeParticipant($this->parameters['userID']);
- $this->conversation->updateParticipantSummary();
-
- ConversationModificationLogHandler::getInstance()->removeParticipant($this->conversation->getDecoratedObject(), $this->parameters['userID']);
-
- // reset storage
- UserStorageHandler::getInstance()->reset([$this->parameters['userID']], 'unreadConversationCount');
-
- return [
- 'userID' => $this->parameters['userID']
- ];
- }
-
- /**
- * Rebuilds the conversation data of the relevant conversations.
- */
- public function rebuild() {
- if (empty($this->objects)) {
- $this->readObjects();
- }
-
- // collect number of messages for each conversation
- $conditionBuilder = new PreparedStatementConditionBuilder();
- $conditionBuilder->add('conversation_message.conversationID IN (?)', [$this->objectIDs]);
- $sql = "SELECT conversationID, COUNT(messageID) AS messages, SUM(attachments) AS attachments
- FROM wcf".WCF_N."_conversation_message conversation_message
- ".$conditionBuilder."
+ " . $conditionBuilder;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditionBuilder->getParameters());
+ $conversationIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
+
+ if (!empty($conversationIDs)) {
+ $action = new self($conversationIDs, 'delete');
+ $action->executeAction();
+ }
+ }
+
+ return [
+ 'actionName' => 'hideConversation',
+ 'redirectURL' => LinkHandler::getInstance()->getLink('ConversationList'),
+ ];
+ }
+
+ /**
+ * Validates parameters to return the mixed conversation list.
+ */
+ public function validateGetMixedConversationList()
+ {
+ // does nothing
+ }
+
+ /**
+ * Returns a mixed conversation list with up to 10 unread conversations.
+ *
+ * @return mixed[][]
+ */
+ public function getMixedConversationList()
+ {
+ $sqlSelect = ' , (SELECT participantID FROM wcf' . WCF_N . '_conversation_to_user WHERE conversationID = conversation.conversationID AND participantID <> conversation.userID AND isInvisible = 0 ORDER BY username, participantID LIMIT 1) AS otherParticipantID
+ , (SELECT username FROM wcf' . WCF_N . '_conversation_to_user WHERE conversationID = conversation.conversationID AND participantID <> conversation.userID AND isInvisible = 0 ORDER BY username, participantID LIMIT 1) AS otherParticipant';
+
+ $unreadConversationList = new UserConversationList(WCF::getUser()->userID);
+ $unreadConversationList->sqlSelects .= $sqlSelect;
+ $unreadConversationList->getConditionBuilder()->add('conversation_to_user.lastVisitTime < lastPostTime');
+ $unreadConversationList->sqlLimit = 10;
+ $unreadConversationList->sqlOrderBy = 'lastPostTime DESC';
+ $unreadConversationList->readObjects();
+
+ $conversations = [];
+ $count = 0;
+ foreach ($unreadConversationList as $conversation) {
+ $conversations[] = $conversation;
+ $count++;
+ }
+
+ if ($count < 10) {
+ $conversationList = new UserConversationList(WCF::getUser()->userID);
+ $conversationList->sqlSelects .= $sqlSelect;
+ $conversationList->getConditionBuilder()->add('conversation_to_user.lastVisitTime >= lastPostTime');
+ $conversationList->sqlLimit = (10 - $count);
+ $conversationList->sqlOrderBy = 'lastPostTime DESC';
+ $conversationList->readObjects();
+
+ foreach ($conversationList as $conversation) {
+ $conversations[] = $conversation;
+ }
+ }
+
+ WCF::getTPL()->assign([
+ 'conversations' => $conversations,
+ ]);
+
+ $totalCount = ConversationHandler::getInstance()->getUnreadConversationCount();
+ if ($count < 10 && $count < $totalCount) {
+ UserStorageHandler::getInstance()->reset([WCF::getUser()->userID], 'unreadConversationCount');
+ }
+
+ return [
+ 'template' => WCF::getTPL()->fetch('conversationListUserPanel'),
+ 'totalCount' => $totalCount,
+ ];
+ }
+
+ /**
+ * Validates the 'unmarkAll' action.
+ */
+ public function validateUnmarkAll()
+ {
+ // does nothing
+ }
+
+ /**
+ * Unmarks all conversations.
+ */
+ public function unmarkAll()
+ {
+ ClipboardHandler::getInstance()->removeItems(
+ ClipboardHandler::getInstance()->getObjectTypeID('com.woltlab.wcf.conversation.conversation')
+ );
+ }
+
+ /**
+ * Validates parameters to display the 'add participants' form.
+ *
+ * @throws PermissionDeniedException
+ */
+ public function validateGetAddParticipantsForm()
+ {
+ $this->conversation = $this->getSingleObject();
+ if (
+ !Conversation::isParticipant([$this->conversation->conversationID])
+ || !$this->conversation->canAddParticipants()
+ ) {
+ throw new PermissionDeniedException();
+ }
+ }
+
+ /**
+ * Shows the 'add participants' form.
+ *
+ * @return array
+ */
+ public function getAddParticipantsForm()
+ {
+ $restrictUserGroupIDs = [];
+ foreach (UserGroup::getAllGroups() as $group) {
+ if ($group->canBeAddedAsConversationParticipant) {
+ $restrictUserGroupIDs[] = $group->groupID;
+ }
+ }
+
+ return [
+ 'excludedSearchValues' => $this->conversation->getParticipantNames(false, true),
+ 'maxItems' => WCF::getSession()->getPermission('user.conversation.maxParticipants') - $this->conversation->participants,
+ 'canAddGroupParticipants' => WCF::getSession()->getPermission('user.conversation.canAddGroupParticipants'),
+ 'template' => WCF::getTPL()->fetch(
+ 'conversationAddParticipants',
+ 'wcf',
+ ['conversation' => $this->conversation]
+ ),
+ 'restrictUserGroupIDs' => $restrictUserGroupIDs,
+ ];
+ }
+
+ /**
+ * Validates parameters to add new participants.
+ */
+ public function validateAddParticipants()
+ {
+ $this->validateGetAddParticipantsForm();
+
+ // validate participants
+ $this->readStringArray('participants', true);
+ $this->readIntegerArray('participantsGroupIDs', true);
+
+ if (!$this->conversation->getDecoratedObject()->isDraft) {
+ $this->readString('visibility');
+ if (!\in_array($this->parameters['visibility'], ['all', 'new'])) {
+ throw new UserInputException('visibility');
+ }
+
+ if ($this->parameters['visibility'] === 'all' && !$this->conversation->canAddParticipantsUnrestricted()) {
+ throw new UserInputException('visibility');
+ }
+ }
+ }
+
+ /**
+ * Adds new participants.
+ *
+ * @return array
+ */
+ public function addParticipants()
+ {
+ try {
+ $existingParticipants = $this->conversation->getParticipantIDs(true);
+ $participantIDs = Conversation::validateParticipants(
+ $this->parameters['participants'],
+ 'participants',
+ $existingParticipants
+ );
+ if (
+ !empty($this->parameters['participantsGroupIDs'])
+ && WCF::getSession()->getPermission('user.conversation.canAddGroupParticipants')
+ ) {
+ $validGroupParticipants = Conversation::validateGroupParticipants(
+ $this->parameters['participantsGroupIDs'],
+ 'participants',
+ $existingParticipants
+ );
+ $validGroupParticipants = \array_diff($validGroupParticipants, $participantIDs);
+ if (empty($validGroupParticipants)) {
+ throw new UserInputException('participants', 'emptyGroup');
+ }
+ $participantIDs = \array_merge($participantIDs, $validGroupParticipants);
+ }
+
+ $parameters = [
+ 'participantIDs' => $participantIDs,
+ ];
+ EventHandler::getInstance()->fireAction($this, 'addParticipants_validateParticipants', $parameters);
+ $participantIDs = $parameters['participantIDs'];
+ } catch (UserInputException $e) {
+ $errorMessage = '';
+ $errors = \is_array($e->getType()) ? $e->getType() : [['type' => $e->getType()]];
+ foreach ($errors as $type) {
+ if (!empty($errorMessage)) {
+ $errorMessage .= ' ';
+ }
+ $errorMessage .= WCF::getLanguage()->getDynamicVariable(
+ 'wcf.conversation.participants.error.' . $type['type'],
+ ['errorData' => $type]
+ );
+ }
+
+ return [
+ 'actionName' => 'addParticipants',
+ 'errorMessage' => $errorMessage,
+ ];
+ }
+
+ // validate limit
+ $newCount = $this->conversation->participants + \count($participantIDs);
+ if ($newCount > WCF::getSession()->getPermission('user.conversation.maxParticipants')) {
+ return [
+ 'actionName' => 'addParticipants',
+ 'errorMessage' => WCF::getLanguage()->getDynamicVariable('wcf.conversation.participants.error.tooManyParticipants'),
+ ];
+ }
+
+ $count = 0;
+ $successMessage = '';
+ if (!empty($participantIDs)) {
+ // check for already added participants
+ if ($this->conversation->isDraft) {
+ $draftData = \unserialize($this->conversation->draftData);
+ $draftData['participants'] = \array_merge($draftData['participants'], $participantIDs);
+ $data = ['data' => ['draftData' => \serialize($draftData)]];
+ } else {
+ $data = [
+ 'participants' => $participantIDs,
+ 'visibility' => (isset($this->parameters['visibility'])) ? $this->parameters['visibility'] : 'all',
+ ];
+ }
+
+ $conversationAction = new self([$this->conversation], 'update', $data);
+ $conversationAction->executeAction();
+
+ $count = \count($participantIDs);
+ $successMessage = WCF::getLanguage()->getDynamicVariable(
+ 'wcf.conversation.edit.addParticipants.success',
+ ['count' => $count]
+ );
+
+ ConversationModificationLogHandler::getInstance()
+ ->addParticipants($this->conversation->getDecoratedObject(), $participantIDs);
+
+ if (!$this->conversation->isDraft) {
+ // update participant summary
+ $this->conversation->updateParticipantSummary();
+ }
+ }
+
+ return [
+ 'count' => $count,
+ 'successMessage' => $successMessage,
+ ];
+ }
+
+ /**
+ * Validates parameters to remove a participant from a conversation.
+ *
+ * @throws PermissionDeniedException
+ * @throws UserInputException
+ */
+ public function validateRemoveParticipant()
+ {
+ $this->readInteger('userID');
+
+ // validate conversation
+ $this->conversation = $this->getSingleObject();
+ if (!$this->conversation->conversationID) {
+ throw new UserInputException('objectIDs');
+ }
+
+ // check ownership
+ if ($this->conversation->userID != WCF::getUser()->userID) {
+ throw new PermissionDeniedException();
+ }
+
+ // validate participants
+ if (
+ $this->parameters['userID'] == WCF::getUser()->userID
+ || !Conversation::isParticipant([$this->conversation->conversationID])
+ || !Conversation::isParticipant([$this->conversation->conversationID], $this->parameters['userID'])
+ ) {
+ throw new PermissionDeniedException();
+ }
+ }
+
+ /**
+ * Removes a participant from a conversation.
+ */
+ public function removeParticipant()
+ {
+ $this->conversation->removeParticipant($this->parameters['userID']);
+ $this->conversation->updateParticipantSummary();
+
+ ConversationModificationLogHandler::getInstance()
+ ->removeParticipant($this->conversation->getDecoratedObject(), $this->parameters['userID']);
+
+ // reset storage
+ UserStorageHandler::getInstance()->reset([$this->parameters['userID']], 'unreadConversationCount');
+
+ return [
+ 'userID' => $this->parameters['userID'],
+ ];
+ }
+
+ /**
+ * Rebuilds the conversation data of the relevant conversations.
+ */
+ public function rebuild()
+ {
+ if (empty($this->objects)) {
+ $this->readObjects();
+ }
+
+ // collect number of messages for each conversation
+ $conditionBuilder = new PreparedStatementConditionBuilder();
+ $conditionBuilder->add('conversation_message.conversationID IN (?)', [$this->objectIDs]);
+ $sql = "SELECT conversationID, COUNT(messageID) AS messages, SUM(attachments) AS attachments
+ FROM wcf" . WCF_N . "_conversation_message conversation_message
+ " . $conditionBuilder . "
GROUP BY conversationID";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditionBuilder->getParameters());
-
- $objectIDs = [];
- while ($row = $statement->fetchArray()) {
- if (!$row['messages']) {
- continue;
- }
- $objectIDs[] = $row['conversationID'];
-
- $conversationEditor = new ConversationEditor(new Conversation(null, [
- 'conversationID' => $row['conversationID']
- ]));
- $conversationEditor->update([
- 'attachments' => $row['attachments'],
- 'replies' => $row['messages'] - 1
- ]);
- $conversationEditor->updateFirstMessage();
- $conversationEditor->updateLastMessage();
- }
-
- // delete conversations without messages
- $deleteConversationIDs = array_diff($this->objectIDs, $objectIDs);
- if (!empty($deleteConversationIDs)) {
- $conversationAction = new ConversationAction($deleteConversationIDs, 'delete');
- $conversationAction->executeAction();
- }
- }
-
- /**
- * Validates the parameters to edit a conversation's subject.
- *
- * @throws PermissionDeniedException
- */
- public function validateEditSubject() {
- $this->readString('subject');
-
- $this->conversation = $this->getSingleObject();
- if ($this->conversation->userID != WCF::getUser()->userID) {
- throw new PermissionDeniedException();
- }
- }
-
- /**
- * Edits a conversation's subject.
- *
- * @return string[]
- */
- public function editSubject() {
- $subject = mb_substr($this->parameters['subject'], 0, 255);
-
- $this->conversation->update([
- 'subject' => $subject
- ]);
-
- $message = $this->conversation->getFirstMessage();
-
- SearchIndexManager::getInstance()->set(
- 'com.woltlab.wcf.conversation.message',
- $message->messageID,
- $message->message,
- $subject,
- $message->time,
- $message->userID,
- $message->username
- );
-
- return [
- 'subject' => $subject
- ];
- }
-
- /**
- * Adds conversation modification data.
- *
- * @param Conversation $conversation
- * @param string $key
- * @param mixed $value
- */
- protected function addConversationData(Conversation $conversation, $key, $value) {
- if (!isset($this->conversationData[$conversation->conversationID])) {
- $this->conversationData[$conversation->conversationID] = [];
- }
-
- $this->conversationData[$conversation->conversationID][$key] = $value;
- }
-
- /**
- * Returns conversation data.
- *
- * @return mixed[][]
- */
- protected function getConversationData() {
- return [
- 'conversationData' => $this->conversationData
- ];
- }
-
- /**
- * Unmarks conversations.
- *
- * @param integer[] $conversationIDs
- */
- protected function unmarkItems(array $conversationIDs = []) {
- if (empty($conversationIDs)) {
- $conversationIDs = $this->objectIDs;
- }
-
- ClipboardHandler::getInstance()->unmark($conversationIDs, ClipboardHandler::getInstance()->getObjectTypeID('com.woltlab.wcf.conversation.conversation'));
- }
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditionBuilder->getParameters());
+
+ $objectIDs = [];
+ while ($row = $statement->fetchArray()) {
+ if (!$row['messages']) {
+ continue;
+ }
+ $objectIDs[] = $row['conversationID'];
+
+ $conversationEditor = new ConversationEditor(new Conversation(null, [
+ 'conversationID' => $row['conversationID'],
+ ]));
+ $conversationEditor->update([
+ 'attachments' => $row['attachments'],
+ 'replies' => $row['messages'] - 1,
+ ]);
+ $conversationEditor->updateFirstMessage();
+ $conversationEditor->updateLastMessage();
+ }
+
+ // delete conversations without messages
+ $deleteConversationIDs = \array_diff($this->objectIDs, $objectIDs);
+ if (!empty($deleteConversationIDs)) {
+ $conversationAction = new self($deleteConversationIDs, 'delete');
+ $conversationAction->executeAction();
+ }
+ }
+
+ /**
+ * Validates the parameters to edit a conversation's subject.
+ *
+ * @throws PermissionDeniedException
+ */
+ public function validateEditSubject()
+ {
+ $this->readString('subject');
+
+ $this->conversation = $this->getSingleObject();
+ if ($this->conversation->userID != WCF::getUser()->userID) {
+ throw new PermissionDeniedException();
+ }
+ }
+
+ /**
+ * Edits a conversation's subject.
+ *
+ * @return string[]
+ */
+ public function editSubject()
+ {
+ $subject = \mb_substr($this->parameters['subject'], 0, 255);
+
+ $this->conversation->update([
+ 'subject' => $subject,
+ ]);
+
+ $message = $this->conversation->getFirstMessage();
+
+ SearchIndexManager::getInstance()->set(
+ 'com.woltlab.wcf.conversation.message',
+ $message->messageID,
+ $message->message,
+ $subject,
+ $message->time,
+ $message->userID,
+ $message->username
+ );
+
+ return [
+ 'subject' => $subject,
+ ];
+ }
+
+ /**
+ * Adds conversation modification data.
+ *
+ * @param Conversation $conversation
+ * @param string $key
+ * @param mixed $value
+ */
+ protected function addConversationData(Conversation $conversation, $key, $value)
+ {
+ if (!isset($this->conversationData[$conversation->conversationID])) {
+ $this->conversationData[$conversation->conversationID] = [];
+ }
+
+ $this->conversationData[$conversation->conversationID][$key] = $value;
+ }
+
+ /**
+ * Returns conversation data.
+ *
+ * @return mixed[][]
+ */
+ protected function getConversationData()
+ {
+ return [
+ 'conversationData' => $this->conversationData,
+ ];
+ }
+
+ /**
+ * Unmarks conversations.
+ *
+ * @param integer[] $conversationIDs
+ */
+ protected function unmarkItems(array $conversationIDs = [])
+ {
+ if (empty($conversationIDs)) {
+ $conversationIDs = $this->objectIDs;
+ }
+
+ ClipboardHandler::getInstance()->unmark(
+ $conversationIDs,
+ ClipboardHandler::getInstance()->getObjectTypeID('com.woltlab.wcf.conversation.conversation')
+ );
+ }
}
<?php
+
namespace wcf\data\conversation;
+
use wcf\data\conversation\message\ConversationMessage;
use wcf\data\DatabaseObjectEditor;
use wcf\system\database\util\PreparedStatementConditionBuilder;
/**
* Extends the conversation object with functions to create, update and delete conversations.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
- *
- * @method static Conversation create(array $parameters = [])
- * @method Conversation getDecoratedObject()
- * @mixin Conversation
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation
+ *
+ * @method static Conversation create(array $parameters = [])
+ * @method Conversation getDecoratedObject()
+ * @mixin Conversation
*/
-class ConversationEditor extends DatabaseObjectEditor {
- /**
- * @inheritDoc
- */
- protected static $baseClass = Conversation::class;
-
- /**
- * Adds a new message to this conversation.
- *
- * @param ConversationMessage $message
- */
- public function addMessage(ConversationMessage $message) {
- $this->update([
- 'lastPoster' => $message->username,
- 'lastPostTime' => $message->time,
- 'lastPosterID' => $message->userID,
- 'replies' => $this->replies + 1,
- 'attachments' => $this->attachments + $message->attachments
- ]);
- }
-
- /**
- * Resets the participants of this conversation.
- */
- public function resetParticipants() {
- $sql = "DELETE FROM wcf".WCF_N."_conversation_to_user
+class ConversationEditor extends DatabaseObjectEditor
+{
+ /**
+ * @inheritDoc
+ */
+ protected static $baseClass = Conversation::class;
+
+ /**
+ * Adds a new message to this conversation.
+ *
+ * @param ConversationMessage $message
+ */
+ public function addMessage(ConversationMessage $message)
+ {
+ $this->update([
+ 'lastPoster' => $message->username,
+ 'lastPostTime' => $message->time,
+ 'lastPosterID' => $message->userID,
+ 'replies' => $this->replies + 1,
+ 'attachments' => $this->attachments + $message->attachments,
+ ]);
+ }
+
+ /**
+ * Resets the participants of this conversation.
+ */
+ public function resetParticipants()
+ {
+ $sql = "DELETE FROM wcf" . WCF_N . "_conversation_to_user
WHERE conversationID = ?
AND participantID <> ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute([$this->conversationID, $this->userID]);
- }
-
- /**
- * Updates the participants of this conversation.
- *
- * @param integer[] $participantIDs
- * @param integer[] $invisibleParticipantIDs
- * @param string $visibility
- */
- public function updateParticipants(array $participantIDs, array $invisibleParticipantIDs = [], $visibility = 'all') {
- $usernames = [];
- if (!empty($participantIDs) || !empty($invisibleParticipantIDs)) {
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add("userID IN (?)", [array_merge($participantIDs, $invisibleParticipantIDs)]);
-
- $sql = "SELECT userID, username
- FROM wcf".WCF_N."_user
- ".$conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditions->getParameters());
- while ($row = $statement->fetchArray()) {
- $usernames[$row['userID']] = $row['username'];
- }
- }
-
- if (!empty($participantIDs)) {
- WCF::getDB()->beginTransaction();
- $sql = "INSERT INTO wcf".WCF_N."_conversation_to_user
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([$this->conversationID, $this->userID]);
+ }
+
+ /**
+ * Updates the participants of this conversation.
+ *
+ * @param integer[] $participantIDs
+ * @param integer[] $invisibleParticipantIDs
+ * @param string $visibility
+ */
+ public function updateParticipants(array $participantIDs, array $invisibleParticipantIDs = [], $visibility = 'all')
+ {
+ $usernames = [];
+ if (!empty($participantIDs) || !empty($invisibleParticipantIDs)) {
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("userID IN (?)", [\array_merge($participantIDs, $invisibleParticipantIDs)]);
+
+ $sql = "SELECT userID, username
+ FROM wcf" . WCF_N . "_user
+ " . $conditions;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditions->getParameters());
+ while ($row = $statement->fetchArray()) {
+ $usernames[$row['userID']] = $row['username'];
+ }
+ }
+
+ if (!empty($participantIDs)) {
+ WCF::getDB()->beginTransaction();
+ $sql = "INSERT INTO wcf" . WCF_N . "_conversation_to_user
(conversationID, participantID, username, isInvisible, joinedAt)
VALUES (?, ?, ?, ?, ?)
ON DUPLICATE KEY
UPDATE hideConversation = 0, leftAt = 0, leftByOwnChoice = 1";
- $statement = WCF::getDB()->prepareStatement($sql);
-
- foreach ($participantIDs as $userID) {
- $statement->execute([
- $this->conversationID,
- $userID,
- $usernames[$userID],
- 0,
- ($visibility === 'all') ? 0 : TIME_NOW
- ]);
- }
- WCF::getDB()->commitTransaction();
- }
-
- if (!empty($invisibleParticipantIDs)) {
- WCF::getDB()->beginTransaction();
- $sql = "INSERT INTO wcf".WCF_N."_conversation_to_user
+ $statement = WCF::getDB()->prepareStatement($sql);
+
+ foreach ($participantIDs as $userID) {
+ $statement->execute([
+ $this->conversationID,
+ $userID,
+ $usernames[$userID],
+ 0,
+ ($visibility === 'all') ? 0 : TIME_NOW,
+ ]);
+ }
+ WCF::getDB()->commitTransaction();
+ }
+
+ if (!empty($invisibleParticipantIDs)) {
+ WCF::getDB()->beginTransaction();
+ $sql = "INSERT INTO wcf" . WCF_N . "_conversation_to_user
(conversationID, participantID, username, isInvisible)
VALUES (?, ?, ?, ?)";
- $statement = WCF::getDB()->prepareStatement($sql);
-
- foreach ($invisibleParticipantIDs as $userID) {
- $statement->execute([
- $this->conversationID,
- $userID,
- $usernames[$userID],
- 1
- ]);
- }
- WCF::getDB()->commitTransaction();
- }
-
- $this->updateParticipantCount();
- }
-
- /**
- * Updates participant count.
- */
- public function updateParticipantCount() {
- $sql = "UPDATE wcf".WCF_N."_conversation conversation
+ $statement = WCF::getDB()->prepareStatement($sql);
+
+ foreach ($invisibleParticipantIDs as $userID) {
+ $statement->execute([
+ $this->conversationID,
+ $userID,
+ $usernames[$userID],
+ 1,
+ ]);
+ }
+ WCF::getDB()->commitTransaction();
+ }
+
+ $this->updateParticipantCount();
+ }
+
+ /**
+ * Updates participant count.
+ */
+ public function updateParticipantCount()
+ {
+ $sql = "UPDATE wcf" . WCF_N . "_conversation conversation
SET participants = (
SELECT COUNT(*) AS count
- FROM wcf".WCF_N."_conversation_to_user conversation_to_user
+ FROM wcf" . WCF_N . "_conversation_to_user conversation_to_user
WHERE conversation_to_user.conversationID = conversation.conversationID
AND conversation_to_user.hideConversation <> ?
AND conversation_to_user.participantID <> ?
AND conversation_to_user.isInvisible = ?
)
WHERE conversation.conversationID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute([
- Conversation::STATE_LEFT,
- $this->userID,
- 0,
- $this->conversationID
- ]);
- }
-
- /**
- * Updates the participant summary of this conversation.
- */
- public function updateParticipantSummary() {
- $sql = "SELECT participantID AS userID, hideConversation, username
- FROM wcf".WCF_N."_conversation_to_user
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([
+ Conversation::STATE_LEFT,
+ $this->userID,
+ 0,
+ $this->conversationID,
+ ]);
+ }
+
+ /**
+ * Updates the participant summary of this conversation.
+ */
+ public function updateParticipantSummary()
+ {
+ $sql = "SELECT participantID AS userID, hideConversation, username
+ FROM wcf" . WCF_N . "_conversation_to_user
WHERE conversationID = ?
AND participantID <> ?
AND isInvisible = 0
ORDER BY username";
- $statement = WCF::getDB()->prepareStatement($sql, 5);
- $statement->execute([$this->conversationID, $this->userID]);
-
- $this->update(['participantSummary' => serialize($statement->fetchAll(\PDO::FETCH_ASSOC))]);
- }
-
- /**
- * Removes a participant from this conversation.
- *
- * @param integer $userID
- */
- public function removeParticipant($userID) {
- $sql = "SELECT joinedAt
- FROM wcf".WCF_N."_conversation_to_user
+ $statement = WCF::getDB()->prepareStatement($sql, 5);
+ $statement->execute([$this->conversationID, $this->userID]);
+
+ $this->update(['participantSummary' => \serialize($statement->fetchAll(\PDO::FETCH_ASSOC))]);
+ }
+
+ /**
+ * Removes a participant from this conversation.
+ *
+ * @param integer $userID
+ */
+ public function removeParticipant($userID)
+ {
+ $sql = "SELECT joinedAt
+ FROM wcf" . WCF_N . "_conversation_to_user
WHERE conversationID = ?
AND participantID = ?";
- $statement = WCF::getDB()->prepareStatement($sql, 1);
- $statement->execute([$this->conversationID, $userID]);
- $joinedAt = $statement->fetchSingleColumn();
-
- $sql = "SELECT messageID
- FROM wcf".WCF_N."_conversation_message
+ $statement = WCF::getDB()->prepareStatement($sql, 1);
+ $statement->execute([$this->conversationID, $userID]);
+ $joinedAt = $statement->fetchSingleColumn();
+
+ $sql = "SELECT messageID
+ FROM wcf" . WCF_N . "_conversation_message
WHERE conversationID = ?
AND time >= ?
AND time <= ?";
- $statement = WCF::getDB()->prepareStatement($sql, 1);
- $statement->execute([
- $this->conversationID,
- $joinedAt,
- TIME_NOW
- ]);
- $lastMessageID = $statement->fetchSingleColumn();
-
- $sql = "UPDATE wcf".WCF_N."_conversation_to_user
+ $statement = WCF::getDB()->prepareStatement($sql, 1);
+ $statement->execute([
+ $this->conversationID,
+ $joinedAt,
+ TIME_NOW,
+ ]);
+ $lastMessageID = $statement->fetchSingleColumn();
+
+ $sql = "UPDATE wcf" . WCF_N . "_conversation_to_user
SET leftAt = ?,
lastMessageID = ?,
leftByOwnChoice = ?
WHERE conversationID = ?
AND participantID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute([
- TIME_NOW,
- $lastMessageID ?: null,
- 0,
- $this->conversationID,
- $userID
- ]);
-
- // decrease participant count unless it is the author
- if ($userID != $this->userID) {
- $this->updateCounters([
- 'participants' => -1
- ]);
- }
- }
-
- /**
- * Updates the first message of this conversation.
- */
- public function updateFirstMessage() {
- $sql = "SELECT messageID
- FROM wcf".WCF_N."_conversation_message
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([
+ TIME_NOW,
+ $lastMessageID ?: null,
+ 0,
+ $this->conversationID,
+ $userID,
+ ]);
+
+ // decrease participant count unless it is the author
+ if ($userID != $this->userID) {
+ $this->updateCounters([
+ 'participants' => -1,
+ ]);
+ }
+ }
+
+ /**
+ * Updates the first message of this conversation.
+ */
+ public function updateFirstMessage()
+ {
+ $sql = "SELECT messageID
+ FROM wcf" . WCF_N . "_conversation_message
WHERE conversationID = ?
ORDER BY time ASC";
- $statement = WCF::getDB()->prepareStatement($sql, 1);
- $statement->execute([
- $this->conversationID
- ]);
-
- $this->update([
- 'firstMessageID' => $statement->fetchColumn()
- ]);
- }
-
- /**
- * Updates the last message of this conversation.
- */
- public function updateLastMessage() {
- $sql = "SELECT time, userID, username
- FROM wcf".WCF_N."_conversation_message
+ $statement = WCF::getDB()->prepareStatement($sql, 1);
+ $statement->execute([
+ $this->conversationID,
+ ]);
+
+ $this->update([
+ 'firstMessageID' => $statement->fetchColumn(),
+ ]);
+ }
+
+ /**
+ * Updates the last message of this conversation.
+ */
+ public function updateLastMessage()
+ {
+ $sql = "SELECT time, userID, username
+ FROM wcf" . WCF_N . "_conversation_message
WHERE conversationID = ?
ORDER BY time DESC";
- $statement = WCF::getDB()->prepareStatement($sql, 1);
- $statement->execute([
- $this->conversationID
- ]);
- $row = $statement->fetchArray();
-
- $this->update([
- 'lastPostTime' => $row['time'],
- 'lastPosterID' => $row['userID'],
- 'lastPoster' => $row['username']
- ]);
- }
-
- /**
- * Updates the participant summary of the given conversations.
- *
- * @param integer[] $conversationIDs
- */
- public static function updateParticipantSummaries(array $conversationIDs) {
- $conversationList = new ConversationList();
- $conversationList->setObjectIDs($conversationIDs);
- $conversationList->readObjects();
-
- foreach ($conversationList as $conversation) {
- $editor = new ConversationEditor($conversation);
- $editor->updateParticipantSummary();
- }
- }
-
- /**
- * Updates the participant counts of the given conversations.
- *
- * @param integer[] $conversationIDs
- */
- public static function updateParticipantCounts(array $conversationIDs) {
- $conversationList = new ConversationList();
- $conversationList->setObjectIDs($conversationIDs);
- $conversationList->readObjects();
-
- foreach ($conversationList as $conversation) {
- $editor = new ConversationEditor($conversation);
- $editor->updateParticipantCount();
- }
- }
+ $statement = WCF::getDB()->prepareStatement($sql, 1);
+ $statement->execute([
+ $this->conversationID,
+ ]);
+ $row = $statement->fetchArray();
+
+ $this->update([
+ 'lastPostTime' => $row['time'],
+ 'lastPosterID' => $row['userID'],
+ 'lastPoster' => $row['username'],
+ ]);
+ }
+
+ /**
+ * Updates the participant summary of the given conversations.
+ *
+ * @param integer[] $conversationIDs
+ */
+ public static function updateParticipantSummaries(array $conversationIDs)
+ {
+ $conversationList = new ConversationList();
+ $conversationList->setObjectIDs($conversationIDs);
+ $conversationList->readObjects();
+
+ foreach ($conversationList as $conversation) {
+ $editor = new self($conversation);
+ $editor->updateParticipantSummary();
+ }
+ }
+
+ /**
+ * Updates the participant counts of the given conversations.
+ *
+ * @param integer[] $conversationIDs
+ */
+ public static function updateParticipantCounts(array $conversationIDs)
+ {
+ $conversationList = new ConversationList();
+ $conversationList->setObjectIDs($conversationIDs);
+ $conversationList->readObjects();
+
+ foreach ($conversationList as $conversation) {
+ $editor = new self($conversation);
+ $editor->updateParticipantCount();
+ }
+ }
}
<?php
+
namespace wcf\data\conversation;
+
use wcf\data\DatabaseObjectList;
/**
* Represents a list of conversations.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
*
- * @method Conversation current()
- * @method Conversation[] getObjects()
- * @method Conversation|null search($objectID)
- * @property Conversation[] $objects
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation
+ *
+ * @method Conversation current()
+ * @method Conversation[] getObjects()
+ * @method Conversation|null search($objectID)
+ * @property Conversation[] $objects
*/
-class ConversationList extends DatabaseObjectList {
- /**
- * @inheritDoc
- */
- public $className = Conversation::class;
+class ConversationList extends DatabaseObjectList
+{
+ /**
+ * @inheritDoc
+ */
+ public $className = Conversation::class;
}
<?php
+
namespace wcf\data\conversation;
+
use wcf\data\user\UserProfile;
use wcf\data\user\UserProfileList;
use wcf\system\WCF;
/**
* Represents a list of conversation participants.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation
*/
-class ConversationParticipantList extends UserProfileList {
- /**
- * conversation id
- * @var integer
- */
- public $conversationID = 0;
-
- /**
- * @inheritDoc
- */
- public $sqlLimit = 0;
-
- /**
- * Creates a new ConversationParticipantList object.
- *
- * @param integer $conversationID
- * @param integer $userID
- * @param boolean $isAuthor true if given user is the author of this conversation
- */
- public function __construct($conversationID, $userID = 0, $isAuthor = false) {
- parent::__construct();
-
- $this->conversationID = $conversationID;
- $this->getConditionBuilder()->add('conversation_to_user.conversationID = ?', [$conversationID]);
- if (!$isAuthor) {
- if ($userID) {
- $this->getConditionBuilder()->add('(conversation_to_user.isInvisible = 0 OR conversation_to_user.participantID = ?)', [$userID]);
- }
- else {
- $this->getConditionBuilder()->add('conversation_to_user.isInvisible = 0');
- }
- }
- $this->sqlConditionJoins .= " LEFT JOIN wcf".WCF_N."_user user_table ON (user_table.userID = conversation_to_user.participantID)";
-
- if (!empty($this->sqlSelects)) $this->sqlSelects .= ',';
- $this->sqlSelects = 'conversation_to_user.*';
- $this->sqlJoins .= " LEFT JOIN wcf".WCF_N."_conversation_to_user conversation_to_user ON (conversation_to_user.participantID = user_table.userID AND conversation_to_user.conversationID = ".$conversationID.")";
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function countObjects() {
- $sql = "SELECT COUNT(*) AS count
- FROM wcf".WCF_N."_conversation_to_user conversation_to_user
- ".$this->sqlConditionJoins."
- ".$this->getConditionBuilder()->__toString();
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($this->getConditionBuilder()->getParameters());
- $row = $statement->fetchArray();
- return $row['count'];
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function readObjectIDs() {
- $this->objectIDs = [];
- $sql = "SELECT conversation_to_user.participantID AS objectID
- FROM wcf".WCF_N."_conversation_to_user conversation_to_user
- ".$this->sqlConditionJoins."
- ".$this->getConditionBuilder()->__toString()."
- ".(!empty($this->sqlOrderBy) ? "ORDER BY ".$this->sqlOrderBy : '');
- $statement = WCF::getDB()->prepareStatement($sql, $this->sqlLimit, $this->sqlOffset);
- $statement->execute($this->getConditionBuilder()->getParameters());
- $this->objectIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
- }
-
- /**
- * @inheritDoc
- */
- public function readObjects() {
- parent::readObjects();
-
- // check for deleted users
- $sql = "SELECT username
- FROM wcf".WCF_N."_conversation_to_user
+class ConversationParticipantList extends UserProfileList
+{
+ /**
+ * conversation id
+ * @var integer
+ */
+ public $conversationID = 0;
+
+ /**
+ * @inheritDoc
+ */
+ public $sqlLimit = 0;
+
+ /**
+ * Creates a new ConversationParticipantList object.
+ *
+ * @param integer $conversationID
+ * @param integer $userID
+ * @param boolean $isAuthor true if given user is the author of this conversation
+ */
+ public function __construct($conversationID, $userID = 0, $isAuthor = false)
+ {
+ parent::__construct();
+
+ $this->conversationID = $conversationID;
+ $this->getConditionBuilder()->add('conversation_to_user.conversationID = ?', [$conversationID]);
+ if (!$isAuthor) {
+ if ($userID) {
+ $this->getConditionBuilder()->add(
+ '(conversation_to_user.isInvisible = 0 OR conversation_to_user.participantID = ?)',
+ [$userID]
+ );
+ } else {
+ $this->getConditionBuilder()->add(
+ 'conversation_to_user.isInvisible = 0'
+ );
+ }
+ }
+ $this->sqlConditionJoins .= " LEFT JOIN wcf" . WCF_N . "_user user_table ON (user_table.userID = conversation_to_user.participantID)";
+
+ if (!empty($this->sqlSelects)) {
+ $this->sqlSelects .= ',';
+ }
+ $this->sqlSelects = 'conversation_to_user.*';
+ $this->sqlJoins .= " LEFT JOIN wcf" . WCF_N . "_conversation_to_user conversation_to_user ON (conversation_to_user.participantID = user_table.userID AND conversation_to_user.conversationID = " . $conversationID . ")";
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function countObjects()
+ {
+ $sql = "SELECT COUNT(*) AS count
+ FROM wcf" . WCF_N . "_conversation_to_user conversation_to_user
+ " . $this->sqlConditionJoins . "
+ " . $this->getConditionBuilder()->__toString();
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($this->getConditionBuilder()->getParameters());
+ $row = $statement->fetchArray();
+
+ return $row['count'];
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function readObjectIDs()
+ {
+ $this->objectIDs = [];
+ $sql = "SELECT conversation_to_user.participantID AS objectID
+ FROM wcf" . WCF_N . "_conversation_to_user conversation_to_user
+ " . $this->sqlConditionJoins . "
+ " . $this->getConditionBuilder()->__toString() . "
+ " . (!empty($this->sqlOrderBy) ? "ORDER BY " . $this->sqlOrderBy : '');
+ $statement = WCF::getDB()->prepareStatement($sql, $this->sqlLimit, $this->sqlOffset);
+ $statement->execute($this->getConditionBuilder()->getParameters());
+ $this->objectIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function readObjects()
+ {
+ parent::readObjects();
+
+ // check for deleted users
+ $sql = "SELECT username
+ FROM wcf" . WCF_N . "_conversation_to_user
WHERE conversationID = ?
AND participantID IS NULL";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute([$this->conversationID]);
- $i = 0;
- while ($row = $statement->fetchArray()) {
- // create fake user profiles
- $this->objects['x'.(++$i)] = UserProfile::getGuestUserProfile($row['username']);
- $this->indexToObject[] = 'x'.$i;
- }
- }
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([$this->conversationID]);
+ $i = 0;
+ while ($row = $statement->fetchArray()) {
+ // create fake user profiles
+ $this->objects['x' . (++$i)] = UserProfile::getGuestUserProfile($row['username']);
+ $this->indexToObject[] = 'x' . $i;
+ }
+ }
}
<?php
+
namespace wcf\data\conversation;
+
use wcf\data\DatabaseObjectDecorator;
use wcf\data\IFeedEntry;
use wcf\system\request\LinkHandler;
/**
* Represents a conversation for RSS feeds.
- *
- * @author Alexander Ebert
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
*
- * @method Conversation getDecoratedObject()
- * @mixin Conversation
+ * @author Alexander Ebert
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation
+ *
+ * @method Conversation getDecoratedObject()
+ * @mixin Conversation
*/
-class FeedConversation extends DatabaseObjectDecorator implements IFeedEntry {
- /**
- * @inheritDoc
- */
- protected static $baseClass = Conversation::class;
-
- /**
- * @inheritDoc
- */
- public function getLink() {
- return LinkHandler::getInstance()->getLink('Conversation', [
- 'object' => $this->getDecoratedObject(),
- 'encodeTitle' => true
- ]);
- }
-
- /**
- * @inheritDoc
- */
- public function getTitle() {
- return $this->getDecoratedObject()->getTitle();
- }
-
- /**
- * @inheritDoc
- */
- public function getFormattedMessage() {
- return '';
- }
-
- /**
- * @inheritDoc
- */
- public function getMessage() {
- return '';
- }
-
- /**
- * @inheritDoc
- */
- public function getExcerpt($maxLength = 255) {
- return '';
- }
-
- /**
- * @inheritDoc
- */
- public function getUserID() {
- return $this->getDecoratedObject()->lastPosterID;
- }
-
- /**
- * @inheritDoc
- */
- public function getUsername() {
- return $this->getDecoratedObject()->lastPoster;
- }
-
- /**
- * @inheritDoc
- */
- public function getTime() {
- return $this->getDecoratedObject()->lastPostTime;
- }
-
- /**
- * @inheritDoc
- */
- public function __toString() {
- return $this->getFormattedMessage();
- }
-
- /**
- * @inheritDoc
- */
- public function getComments() {
- return $this->replies;
- }
-
- /**
- * @inheritDoc
- */
- public function getCategories() {
- return [];
- }
-
- /**
- * @inheritDoc
- */
- public function isVisible() {
- return $this->canRead();
- }
+class FeedConversation extends DatabaseObjectDecorator implements IFeedEntry
+{
+ /**
+ * @inheritDoc
+ */
+ protected static $baseClass = Conversation::class;
+
+ /**
+ * @inheritDoc
+ */
+ public function getLink()
+ {
+ return LinkHandler::getInstance()->getLink('Conversation', [
+ 'object' => $this->getDecoratedObject(),
+ 'encodeTitle' => true,
+ ]);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getTitle()
+ {
+ return $this->getDecoratedObject()->getTitle();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getFormattedMessage()
+ {
+ return '';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getMessage()
+ {
+ return '';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getExcerpt($maxLength = 255)
+ {
+ return '';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getUserID()
+ {
+ return $this->getDecoratedObject()->lastPosterID;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getUsername()
+ {
+ return $this->getDecoratedObject()->lastPoster;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getTime()
+ {
+ return $this->getDecoratedObject()->lastPostTime;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function __toString()
+ {
+ return $this->getFormattedMessage();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getComments()
+ {
+ return $this->replies;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getCategories()
+ {
+ return [];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function isVisible()
+ {
+ return $this->canRead();
+ }
}
<?php
+
namespace wcf\data\conversation;
+
use wcf\system\WCF;
/**
* Represents a list of conversations for RSS feeds.
- *
- * @author Alexander Ebert
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
*
- * @method FeedConversation current()
- * @method FeedConversation[] getObjects()
- * @method FeedConversation|null search($objectID)
- * @property FeedConversation[] $objects
+ * @author Alexander Ebert
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation
+ *
+ * @method FeedConversation current()
+ * @method FeedConversation[] getObjects()
+ * @method FeedConversation|null search($objectID)
+ * @property FeedConversation[] $objects
*/
-class FeedConversationList extends ConversationList {
- /**
- * @inheritDoc
- */
- public $decoratorClassName = FeedConversation::class;
-
- /**
- * @inheritDoc
- */
- public $sqlOrderBy = 'conversation.lastPostTime DESC';
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function readObjectIDs() {
- $sql = "SELECT conversation_to_user.conversationID AS objectID
- FROM wcf".WCF_N."_conversation_to_user conversation_to_user
- ".$this->sqlConditionJoins."
- ".$this->getConditionBuilder()."
- ".(!empty($this->sqlOrderBy) ? "ORDER BY ".$this->sqlOrderBy : '');
- $statement = WCF::getDB()->prepareStatement($sql, $this->sqlLimit, $this->sqlOffset);
- $statement->execute($this->getConditionBuilder()->getParameters());
- $this->objectIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
- }
-
- /**
- * @inheritDoc
- */
- public function readObjects() {
- if ($this->objectIDs === null) {
- $this->readObjectIDs();
- }
-
- parent::readObjects();
- }
+class FeedConversationList extends ConversationList
+{
+ /**
+ * @inheritDoc
+ */
+ public $decoratorClassName = FeedConversation::class;
+
+ /**
+ * @inheritDoc
+ */
+ public $sqlOrderBy = 'conversation.lastPostTime DESC';
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function readObjectIDs()
+ {
+ $sql = "SELECT conversation_to_user.conversationID AS objectID
+ FROM wcf" . WCF_N . "_conversation_to_user conversation_to_user
+ " . $this->sqlConditionJoins . "
+ " . $this->getConditionBuilder() . "
+ " . (!empty($this->sqlOrderBy) ? "ORDER BY " . $this->sqlOrderBy : '');
+ $statement = WCF::getDB()->prepareStatement($sql, $this->sqlLimit, $this->sqlOffset);
+ $statement->execute($this->getConditionBuilder()->getParameters());
+ $this->objectIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function readObjects()
+ {
+ if ($this->objectIDs === null) {
+ $this->readObjectIDs();
+ }
+
+ parent::readObjects();
+ }
}
<?php
+
namespace wcf\data\conversation;
+
use wcf\data\conversation\label\ConversationLabel;
use wcf\data\conversation\label\ConversationLabelList;
use wcf\system\cache\runtime\UserProfileRuntimeCache;
/**
* Represents a list of conversations.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
- *
- * @method ViewableConversation current()
- * @method ViewableConversation[] getObjects()
- * @method ViewableConversation|null search($objectID)
- * @property ViewableConversation[] $objects
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation
+ *
+ * @method ViewableConversation current()
+ * @method ViewableConversation[] getObjects()
+ * @method ViewableConversation|null search($objectID)
+ * @property ViewableConversation[] $objects
*/
-class UserConversationList extends ConversationList {
- /**
- * list of available filters
- * @var string[]
- */
- public static $availableFilters = ['hidden', 'draft', 'outbox'];
-
- /**
- * active filter
- * @var string
- */
- public $filter = '';
-
- /**
- * label list object
- * @var ConversationLabelList
- */
- public $labelList;
-
- /**
- * @inheritDoc
- */
- public $decoratorClassName = ViewableConversation::class;
-
- /**
- * Creates a new UserConversationList
- *
- * @param integer $userID
- * @param string $filter
- * @param integer $labelID
- */
- public function __construct($userID, $filter = '', $labelID = 0) {
- parent::__construct();
-
- $this->filter = $filter;
-
- // apply filter
- if ($this->filter === 'draft') {
- $this->getConditionBuilder()->add('conversation.userID = ?', [$userID]);
- $this->getConditionBuilder()->add('conversation.isDraft = 1');
- }
- else {
- $this->getConditionBuilder()->add('conversation_to_user.participantID = ?', [$userID]);
- $this->getConditionBuilder()->add('conversation_to_user.hideConversation = ?', [$this->filter == 'hidden' ? 1 : 0]);
- $this->sqlConditionJoins = "LEFT JOIN wcf".WCF_N."_conversation conversation ON (conversation.conversationID = conversation_to_user.conversationID)";
- if ($this->filter == 'outbox') $this->getConditionBuilder()->add('conversation.userID = ?', [$userID]);
- }
-
- // filter by label id
- if ($labelID) {
- $this->getConditionBuilder()->add("conversation.conversationID IN (
+class UserConversationList extends ConversationList
+{
+ /**
+ * list of available filters
+ * @var string[]
+ */
+ public static $availableFilters = ['hidden', 'draft', 'outbox'];
+
+ /**
+ * active filter
+ * @var string
+ */
+ public $filter = '';
+
+ /**
+ * label list object
+ * @var ConversationLabelList
+ */
+ public $labelList;
+
+ /**
+ * @inheritDoc
+ */
+ public $decoratorClassName = ViewableConversation::class;
+
+ /**
+ * Creates a new UserConversationList
+ *
+ * @param integer $userID
+ * @param string $filter
+ * @param integer $labelID
+ */
+ public function __construct($userID, $filter = '', $labelID = 0)
+ {
+ parent::__construct();
+
+ $this->filter = $filter;
+
+ // apply filter
+ if ($this->filter === 'draft') {
+ $this->getConditionBuilder()->add('conversation.userID = ?', [$userID]);
+ $this->getConditionBuilder()->add('conversation.isDraft = 1');
+ } else {
+ $this->getConditionBuilder()->add('conversation_to_user.participantID = ?', [$userID]);
+ $this->getConditionBuilder()
+ ->add('conversation_to_user.hideConversation = ?', [$this->filter == 'hidden' ? 1 : 0]);
+ $this->sqlConditionJoins = "LEFT JOIN wcf" . WCF_N . "_conversation conversation ON (conversation.conversationID = conversation_to_user.conversationID)";
+ if ($this->filter == 'outbox') {
+ $this->getConditionBuilder()->add('conversation.userID = ?', [$userID]);
+ }
+ }
+
+ // filter by label id
+ if ($labelID) {
+ $this->getConditionBuilder()->add("conversation.conversationID IN (
SELECT conversationID
- FROM wcf".WCF_N."_conversation_label_to_object
+ FROM wcf" . WCF_N . "_conversation_label_to_object
WHERE labelID = ?
)", [$labelID]);
- }
-
- // own posts
- $this->sqlSelects = "DISTINCT conversation_message.userID AS ownPosts";
- $this->sqlJoins = "LEFT JOIN wcf".WCF_N."_conversation_message conversation_message ON (conversation_message.conversationID = conversation.conversationID AND conversation_message.userID = ".$userID.")";
-
- // user info
- if (!empty($this->sqlSelects)) $this->sqlSelects .= ',';
- $this->sqlSelects .= "conversation_to_user.*";
- $this->sqlJoins .= "LEFT JOIN wcf".WCF_N."_conversation_to_user conversation_to_user ON (conversation_to_user.participantID = ".$userID." AND conversation_to_user.conversationID = conversation.conversationID)";
-
- if ($this->filter !== 'draft') {
- $this->sqlSelects .= ", conversation.*, CASE WHEN conversation_to_user.leftAt <> 0 THEN conversation_to_user.leftAt ELSE conversation.lastPostTime END AS lastPostTime";
- // this avoids appending `conversation.*` to the SELECT list
- $this->useQualifiedShorthand = false;
- }
- }
-
- /**
- * Sets the label list of the user the conversations belong to.
- *
- * @param ConversationLabelList $labelList
- */
- public function setLabelList(ConversationLabelList $labelList) {
- $this->labelList = $labelList;
- }
-
- /**
- * @inheritDoc
- */
- public function countObjects() {
- if ($this->filter == 'draft') return parent::countObjects();
-
- $sql = "SELECT COUNT(*) AS count
- FROM wcf".WCF_N."_conversation_to_user conversation_to_user
- ".$this->sqlConditionJoins."
- ".$this->getConditionBuilder()->__toString();
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($this->getConditionBuilder()->getParameters());
- $row = $statement->fetchArray();
- return $row['count'];
- }
-
- /**
- * @inheritDoc
- */
- public function readObjectIDs() {
- if ($this->filter === 'draft') {
- parent::readObjectIDs();
-
- return;
- }
-
- $sql = "SELECT conversation_to_user.conversationID AS objectID
- FROM wcf".WCF_N."_conversation_to_user conversation_to_user
- ".$this->sqlConditionJoins."
- ".$this->getConditionBuilder()->__toString()."
- ".(!empty($this->sqlOrderBy) ? "ORDER BY ".$this->sqlOrderBy : '');
- $statement = WCF::getDB()->prepareStatement($sql, $this->sqlLimit, $this->sqlOffset);
- $statement->execute($this->getConditionBuilder()->getParameters());
- $this->objectIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
- }
-
- /**
- * @inheritDoc
- */
- public function readObjects() {
- if ($this->objectIDs === null) {
- $this->readObjectIDs();
- }
-
- parent::readObjects();
-
- if (!empty($this->objects)) {
- $messageIDs = [];
- foreach ($this->objects as $conversation) {
- if ($conversation->lastMessageID) {
- $messageIDs[] = $conversation->lastMessageID;
- }
- }
- if (!empty($messageIDs)) {
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add("messageID IN (?)", [$messageIDs]);
- $sql = "SELECT messageID, userID, username, time
- FROM wcf".WCF_N."_conversation_message
- ".$conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditions->getParameters());
- $messageData = [];
- while ($row = $statement->fetchArray()) {
- $messageData[$row['messageID']] = $row;
- }
-
- foreach ($this->objects as $conversation) {
- if ($conversation->lastMessageID) {
- $data = (isset($messageData[$conversation->lastMessageID])) ? $messageData[$conversation->lastMessageID] : null;
- if ($data !== null) {
- $conversation->setLastMessage($data['userID'], $data['username'], $data['time']);
- }
- else {
- $conversation->setLastMessage(null, '', 0);
- }
- }
- }
- }
-
- $labels = $this->loadLabelAssignments();
-
- $userIDs = [];
- foreach ($this->objects as $conversationID => $conversation) {
- if (isset($labels[$conversationID])) {
- foreach ($labels[$conversationID] as $label) {
- $conversation->assignLabel($label);
- }
- }
-
- if ($conversation->userID) {
- $userIDs[] = $conversation->userID;
- }
- if ($conversation->lastPosterID) {
- $userIDs[] = $conversation->lastPosterID;
- }
- }
-
- if (!empty($userIDs)) {
- UserProfileRuntimeCache::getInstance()->cacheObjectIDs($userIDs);
- }
- }
- }
-
- /**
- * Returns a list of conversation labels.
- *
- * @return ConversationLabel[]
- */
- protected function getLabels() {
- if ($this->labelList === null) {
- $this->labelList = ConversationLabel::getLabelsByUser();
- }
-
- return $this->labelList->getObjects();
- }
-
- /**
- * Returns label assignments per conversation.
- *
- * @return ConversationLabel[][]
- */
- protected function loadLabelAssignments() {
- $labels = $this->getLabels();
- if (empty($labels)) {
- return [];
- }
-
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID IN (?)", [array_keys($this->objects)]);
- $conditions->add("labelID IN (?)", [array_keys($labels)]);
-
- $sql = "SELECT labelID, conversationID
- FROM wcf".WCF_N."_conversation_label_to_object
- ".$conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditions->getParameters());
- $data = [];
- while ($row = $statement->fetchArray()) {
- if (!isset($data[$row['conversationID']])) {
- $data[$row['conversationID']] = [];
- }
-
- $data[$row['conversationID']][$row['labelID']] = $labels[$row['labelID']];
- }
-
- return $data;
- }
+ }
+
+ // own posts
+ $this->sqlSelects = "DISTINCT conversation_message.userID AS ownPosts";
+ $this->sqlJoins = "LEFT JOIN wcf" . WCF_N . "_conversation_message conversation_message ON (conversation_message.conversationID = conversation.conversationID AND conversation_message.userID = " . $userID . ")";
+
+ // user info
+ if (!empty($this->sqlSelects)) {
+ $this->sqlSelects .= ',';
+ }
+ $this->sqlSelects .= "conversation_to_user.*";
+ $this->sqlJoins .= "LEFT JOIN wcf" . WCF_N . "_conversation_to_user conversation_to_user ON (conversation_to_user.participantID = " . $userID . " AND conversation_to_user.conversationID = conversation.conversationID)";
+
+ if ($this->filter !== 'draft') {
+ $this->sqlSelects .= ", conversation.*, CASE WHEN conversation_to_user.leftAt <> 0 THEN conversation_to_user.leftAt ELSE conversation.lastPostTime END AS lastPostTime";
+ // this avoids appending `conversation.*` to the SELECT list
+ $this->useQualifiedShorthand = false;
+ }
+ }
+
+ /**
+ * Sets the label list of the user the conversations belong to.
+ *
+ * @param ConversationLabelList $labelList
+ */
+ public function setLabelList(ConversationLabelList $labelList)
+ {
+ $this->labelList = $labelList;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function countObjects()
+ {
+ if ($this->filter == 'draft') {
+ return parent::countObjects();
+ }
+
+ $sql = "SELECT COUNT(*) AS count
+ FROM wcf" . WCF_N . "_conversation_to_user conversation_to_user
+ " . $this->sqlConditionJoins . "
+ " . $this->getConditionBuilder()->__toString();
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($this->getConditionBuilder()->getParameters());
+ $row = $statement->fetchArray();
+
+ return $row['count'];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function readObjectIDs()
+ {
+ if ($this->filter === 'draft') {
+ parent::readObjectIDs();
+
+ return;
+ }
+
+ $sql = "SELECT conversation_to_user.conversationID AS objectID
+ FROM wcf" . WCF_N . "_conversation_to_user conversation_to_user
+ " . $this->sqlConditionJoins . "
+ " . $this->getConditionBuilder()->__toString() . "
+ " . (!empty($this->sqlOrderBy) ? "ORDER BY " . $this->sqlOrderBy : '');
+ $statement = WCF::getDB()->prepareStatement($sql, $this->sqlLimit, $this->sqlOffset);
+ $statement->execute($this->getConditionBuilder()->getParameters());
+ $this->objectIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function readObjects()
+ {
+ if ($this->objectIDs === null) {
+ $this->readObjectIDs();
+ }
+
+ parent::readObjects();
+
+ if (!empty($this->objects)) {
+ $messageIDs = [];
+ foreach ($this->objects as $conversation) {
+ if ($conversation->lastMessageID) {
+ $messageIDs[] = $conversation->lastMessageID;
+ }
+ }
+ if (!empty($messageIDs)) {
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("messageID IN (?)", [$messageIDs]);
+ $sql = "SELECT messageID, userID, username, time
+ FROM wcf" . WCF_N . "_conversation_message
+ " . $conditions;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditions->getParameters());
+ $messageData = [];
+ while ($row = $statement->fetchArray()) {
+ $messageData[$row['messageID']] = $row;
+ }
+
+ foreach ($this->objects as $conversation) {
+ if ($conversation->lastMessageID) {
+ $data = (isset($messageData[$conversation->lastMessageID])) ? $messageData[$conversation->lastMessageID] : null;
+ if ($data !== null) {
+ $conversation->setLastMessage($data['userID'], $data['username'], $data['time']);
+ } else {
+ $conversation->setLastMessage(null, '', 0);
+ }
+ }
+ }
+ }
+
+ $labels = $this->loadLabelAssignments();
+
+ $userIDs = [];
+ foreach ($this->objects as $conversationID => $conversation) {
+ if (isset($labels[$conversationID])) {
+ foreach ($labels[$conversationID] as $label) {
+ $conversation->assignLabel($label);
+ }
+ }
+
+ if ($conversation->userID) {
+ $userIDs[] = $conversation->userID;
+ }
+ if ($conversation->lastPosterID) {
+ $userIDs[] = $conversation->lastPosterID;
+ }
+ }
+
+ if (!empty($userIDs)) {
+ UserProfileRuntimeCache::getInstance()->cacheObjectIDs($userIDs);
+ }
+ }
+ }
+
+ /**
+ * Returns a list of conversation labels.
+ *
+ * @return ConversationLabel[]
+ */
+ protected function getLabels()
+ {
+ if ($this->labelList === null) {
+ $this->labelList = ConversationLabel::getLabelsByUser();
+ }
+
+ return $this->labelList->getObjects();
+ }
+
+ /**
+ * Returns label assignments per conversation.
+ *
+ * @return ConversationLabel[][]
+ */
+ protected function loadLabelAssignments()
+ {
+ $labels = $this->getLabels();
+ if (empty($labels)) {
+ return [];
+ }
+
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("conversationID IN (?)", [\array_keys($this->objects)]);
+ $conditions->add("labelID IN (?)", [\array_keys($labels)]);
+
+ $sql = "SELECT labelID, conversationID
+ FROM wcf" . WCF_N . "_conversation_label_to_object
+ " . $conditions;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditions->getParameters());
+ $data = [];
+ while ($row = $statement->fetchArray()) {
+ if (!isset($data[$row['conversationID']])) {
+ $data[$row['conversationID']] = [];
+ }
+
+ $data[$row['conversationID']][$row['labelID']] = $labels[$row['labelID']];
+ }
+
+ return $data;
+ }
}
<?php
+
namespace wcf\data\conversation;
+
use wcf\data\conversation\label\ConversationLabel;
use wcf\data\conversation\label\ConversationLabelList;
-use wcf\data\user\User;
-use wcf\data\user\UserProfile;
use wcf\data\DatabaseObjectDecorator;
use wcf\data\TLegacyUserPropertyAccess;
+use wcf\data\user\User;
+use wcf\data\user\UserProfile;
use wcf\system\cache\runtime\UserProfileRuntimeCache;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\WCF;
/**
* Represents a viewable conversation.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation
- *
- * @method Conversation getDecoratedObject()
- * @mixin Conversation
- * @property-read integer|null $otherParticipantID
- * @property-read string|null $otherParticipant
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation
+ *
+ * @method Conversation getDecoratedObject()
+ * @mixin Conversation
+ * @property-read integer|null $otherParticipantID
+ * @property-read string|null $otherParticipant
*/
-class ViewableConversation extends DatabaseObjectDecorator {
- use TLegacyUserPropertyAccess;
-
- /**
- * participant summary
- * @var string
- */
- protected $__participantSummary;
-
- /**
- * user profile object
- * @var UserProfile
- */
- protected $userProfile;
-
- /**
- * last poster's profile
- * @var UserProfile
- */
- protected $lastPosterProfile;
-
- /**
- * other participant's profile
- * @var UserProfile
- */
- protected $otherParticipantProfile;
-
- /**
- * list of assigned labels
- * @var ConversationLabel[]
- */
- protected $labels = [];
-
- /**
- * @inheritDoc
- */
- protected static $baseClass = Conversation::class;
-
- /**
- * maps legacy direct access to last poster's user profile data to the real
- * user profile property names
- * @var string[]
- * @deprecated
- */
- protected static $__lastUserAvatarPropertyMapping = [
- 'lastPosterAvatarID' => 'avatarID',
- 'lastPosterAvatarName' => 'avatarName',
- 'lastPosterAvatarExtension' => 'avatarExtension',
- 'lastPosterAvatarWidth' => 'width',
- 'lastPosterAvatarHeight' => 'height',
- 'lastPosterEmail' => 'email',
- 'lastPosterDisableAvatar' => 'disableAvatar',
- 'lastPosterEnableGravatar' => 'enableGravatar',
- 'lastPosterGravatarFileExtension' => 'gravatarFileExtension',
- 'lastPosterAvatarFileHash' => 'fileHash'
- ];
-
- /**
- * @inheritDoc
- * @deprecated
- */
- public function __get($name) {
- $value = parent::__get($name);
- if ($value !== null) {
- return $value;
- }
- else if (array_key_exists($name, $this->object->data)) {
- return null;
- }
-
- /** @noinspection PhpVariableVariableInspection */
- $value = $this->getUserProfile()->$name;
- if ($value !== null) {
- return $value;
- }
-
- if (isset(static::$__lastUserAvatarPropertyMapping[$name])) {
- return $this->getLastPosterProfile()->getAvatar()->{static::$__lastUserAvatarPropertyMapping[$name]};
- }
-
- return null;
- }
-
- /**
- * Returns the user profile object.
- *
- * @return UserProfile
- */
- public function getUserProfile() {
- if ($this->userProfile === null) {
- if ($this->userID) {
- $this->userProfile = UserProfileRuntimeCache::getInstance()->getObject($this->userID);
- }
- else {
- $this->userProfile = UserProfile::getGuestUserProfile($this->username);
- }
- }
-
- return $this->userProfile;
- }
-
- /**
- * Returns the last poster's profile object.
- *
- * @return UserProfile
- */
- public function getLastPosterProfile() {
- if ($this->lastPosterProfile === null) {
- if ($this->lastPosterID) {
- $this->lastPosterProfile = UserProfileRuntimeCache::getInstance()->getObject($this->lastPosterID);
- }
- else {
- $this->lastPosterProfile = UserProfile::getGuestUserProfile($this->lastPoster);
- }
- }
-
- return $this->lastPosterProfile;
- }
-
- /**
- * Returns the number of pages in this conversation.
- *
- * @return integer
- */
- public function getPages() {
- /** @noinspection PhpUndefinedFieldInspection */
- if (WCF::getUser()->conversationMessagesPerPage) {
- /** @noinspection PhpUndefinedFieldInspection */
- $messagesPerPage = WCF::getUser()->conversationMessagesPerPage;
- }
- else {
- $messagesPerPage = CONVERSATION_MESSAGES_PER_PAGE;
- }
-
- return intval(ceil(($this->replies + 1) / $messagesPerPage));
- }
-
- /**
- * Returns a summary of the participants.
- *
- * @return User[]
- */
- public function getParticipantSummary() {
- if ($this->__participantSummary === null) {
- $this->__participantSummary = [];
-
- if ($this->participantSummary) {
- $data = unserialize($this->participantSummary);
- if ($data !== false) {
- foreach ($data as $userData) {
- $this->__participantSummary[] = new User(null, [
- 'userID' => $userData['userID'],
- 'username' => $userData['username'],
- 'hideConversation' => $userData['hideConversation']
- ]);
- }
- }
- }
- }
-
- return $this->__participantSummary;
- }
-
- /**
- * Returns the other participant's profile object.
- *
- * @return UserProfile
- */
- public function getOtherParticipantProfile() {
- if ($this->otherParticipantProfile === null) {
- if ($this->otherParticipantID) {
- $this->otherParticipantProfile = UserProfileRuntimeCache::getInstance()->getObject($this->otherParticipantID);
- }
- else {
- $this->otherParticipantProfile = UserProfile::getGuestUserProfile($this->otherParticipant);
- }
- }
-
- return $this->otherParticipantProfile;
- }
-
- /**
- * Assigns a label.
- *
- * @param ConversationLabel $label
- */
- public function assignLabel(ConversationLabel $label) {
- $this->labels[$label->labelID] = $label;
- }
-
- /**
- * Returns a list of assigned labels.
- *
- * @return ConversationLabel[]
- */
- public function getAssignedLabels() {
- return $this->labels;
- }
-
- /**
- * Converts a conversation into a viewable conversation.
- *
- * @param Conversation $conversation
- * @param ConversationLabelList $labelList
- * @return ViewableConversation
- */
- public static function getViewableConversation(Conversation $conversation, ConversationLabelList $labelList = null) {
- $conversation = new ViewableConversation($conversation);
-
- if ($labelList === null) {
- $labelList = ConversationLabel::getLabelsByUser();
- }
-
- $labels = $labelList->getObjects();
- if (!empty($labels)) {
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID = ?", [$conversation->conversationID]);
- $conditions->add("labelID IN (?)", [array_keys($labels)]);
-
- $sql = "SELECT labelID
- FROM wcf".WCF_N."_conversation_label_to_object
- ".$conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditions->getParameters());
- while ($row = $statement->fetchArray()) {
- $conversation->assignLabel($labels[$row['labelID']]);
- }
- }
-
- return $conversation;
- }
+class ViewableConversation extends DatabaseObjectDecorator
+{
+ use TLegacyUserPropertyAccess;
+
+ /**
+ * participant summary
+ * @var string
+ */
+ protected $__participantSummary;
+
+ /**
+ * user profile object
+ * @var UserProfile
+ */
+ protected $userProfile;
+
+ /**
+ * last poster's profile
+ * @var UserProfile
+ */
+ protected $lastPosterProfile;
+
+ /**
+ * other participant's profile
+ * @var UserProfile
+ */
+ protected $otherParticipantProfile;
+
+ /**
+ * list of assigned labels
+ * @var ConversationLabel[]
+ */
+ protected $labels = [];
+
+ /**
+ * @inheritDoc
+ */
+ protected static $baseClass = Conversation::class;
+
+ /**
+ * maps legacy direct access to last poster's user profile data to the real
+ * user profile property names
+ * @var string[]
+ * @deprecated
+ */
+ protected static $__lastUserAvatarPropertyMapping = [
+ 'lastPosterAvatarID' => 'avatarID',
+ 'lastPosterAvatarName' => 'avatarName',
+ 'lastPosterAvatarExtension' => 'avatarExtension',
+ 'lastPosterAvatarWidth' => 'width',
+ 'lastPosterAvatarHeight' => 'height',
+ 'lastPosterEmail' => 'email',
+ 'lastPosterDisableAvatar' => 'disableAvatar',
+ 'lastPosterEnableGravatar' => 'enableGravatar',
+ 'lastPosterGravatarFileExtension' => 'gravatarFileExtension',
+ 'lastPosterAvatarFileHash' => 'fileHash',
+ ];
+
+ /**
+ * @inheritDoc
+ * @deprecated
+ */
+ public function __get($name)
+ {
+ $value = parent::__get($name);
+ if ($value !== null) {
+ return $value;
+ } elseif (\array_key_exists($name, $this->object->data)) {
+ return;
+ }
+
+ /** @noinspection PhpVariableVariableInspection */
+ $value = $this->getUserProfile()->{$name};
+ if ($value !== null) {
+ return $value;
+ }
+
+ if (isset(static::$__lastUserAvatarPropertyMapping[$name])) {
+ return $this->getLastPosterProfile()->getAvatar()->{static::$__lastUserAvatarPropertyMapping[$name]};
+ }
+ }
+
+ /**
+ * Returns the user profile object.
+ *
+ * @return UserProfile
+ */
+ public function getUserProfile()
+ {
+ if ($this->userProfile === null) {
+ if ($this->userID) {
+ $this->userProfile = UserProfileRuntimeCache::getInstance()->getObject($this->userID);
+ } else {
+ $this->userProfile = UserProfile::getGuestUserProfile($this->username);
+ }
+ }
+
+ return $this->userProfile;
+ }
+
+ /**
+ * Returns the last poster's profile object.
+ *
+ * @return UserProfile
+ */
+ public function getLastPosterProfile()
+ {
+ if ($this->lastPosterProfile === null) {
+ if ($this->lastPosterID) {
+ $this->lastPosterProfile = UserProfileRuntimeCache::getInstance()->getObject($this->lastPosterID);
+ } else {
+ $this->lastPosterProfile = UserProfile::getGuestUserProfile($this->lastPoster);
+ }
+ }
+
+ return $this->lastPosterProfile;
+ }
+
+ /**
+ * Returns the number of pages in this conversation.
+ *
+ * @return integer
+ */
+ public function getPages()
+ {
+ /** @noinspection PhpUndefinedFieldInspection */
+ if (WCF::getUser()->conversationMessagesPerPage) {
+ /** @noinspection PhpUndefinedFieldInspection */
+ $messagesPerPage = WCF::getUser()->conversationMessagesPerPage;
+ } else {
+ $messagesPerPage = CONVERSATION_MESSAGES_PER_PAGE;
+ }
+
+ return \intval(\ceil(($this->replies + 1) / $messagesPerPage));
+ }
+
+ /**
+ * Returns a summary of the participants.
+ *
+ * @return User[]
+ */
+ public function getParticipantSummary()
+ {
+ if ($this->__participantSummary === null) {
+ $this->__participantSummary = [];
+
+ if ($this->participantSummary) {
+ $data = \unserialize($this->participantSummary);
+ if ($data !== false) {
+ foreach ($data as $userData) {
+ $this->__participantSummary[] = new User(null, [
+ 'userID' => $userData['userID'],
+ 'username' => $userData['username'],
+ 'hideConversation' => $userData['hideConversation'],
+ ]);
+ }
+ }
+ }
+ }
+
+ return $this->__participantSummary;
+ }
+
+ /**
+ * Returns the other participant's profile object.
+ *
+ * @return UserProfile
+ */
+ public function getOtherParticipantProfile()
+ {
+ if ($this->otherParticipantProfile === null) {
+ if ($this->otherParticipantID) {
+ $this->otherParticipantProfile = UserProfileRuntimeCache::getInstance()
+ ->getObject($this->otherParticipantID);
+ } else {
+ $this->otherParticipantProfile = UserProfile::getGuestUserProfile($this->otherParticipant);
+ }
+ }
+
+ return $this->otherParticipantProfile;
+ }
+
+ /**
+ * Assigns a label.
+ *
+ * @param ConversationLabel $label
+ */
+ public function assignLabel(ConversationLabel $label)
+ {
+ $this->labels[$label->labelID] = $label;
+ }
+
+ /**
+ * Returns a list of assigned labels.
+ *
+ * @return ConversationLabel[]
+ */
+ public function getAssignedLabels()
+ {
+ return $this->labels;
+ }
+
+ /**
+ * Converts a conversation into a viewable conversation.
+ *
+ * @param Conversation $conversation
+ * @param ConversationLabelList $labelList
+ * @return ViewableConversation
+ */
+ public static function getViewableConversation(Conversation $conversation, ?ConversationLabelList $labelList = null)
+ {
+ $conversation = new self($conversation);
+
+ if ($labelList === null) {
+ $labelList = ConversationLabel::getLabelsByUser();
+ }
+
+ $labels = $labelList->getObjects();
+ if (!empty($labels)) {
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("conversationID = ?", [$conversation->conversationID]);
+ $conditions->add("labelID IN (?)", [\array_keys($labels)]);
+
+ $sql = "SELECT labelID
+ FROM wcf" . WCF_N . "_conversation_label_to_object
+ " . $conditions;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditions->getParameters());
+ while ($row = $statement->fetchArray()) {
+ $conversation->assignLabel($labels[$row['labelID']]);
+ }
+ }
+
+ return $conversation;
+ }
}
<?php
+
namespace wcf\data\conversation\label;
+
use wcf\data\DatabaseObject;
use wcf\system\WCF;
/**
* Represents a conversation label.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Label
- *
- * @property-read integer $labelID unique id of the conversation label
- * @property-read integer $userID id of the user who created the conversation label
- * @property-read string $label name of the conversation label
- * @property-read string $cssClassName CSS class name of the conversation label handeling its appearance (color)
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation\Label
+ *
+ * @property-read integer $labelID unique id of the conversation label
+ * @property-read integer $userID id of the user who created the conversation label
+ * @property-read string $label name of the conversation label
+ * @property-read string $cssClassName CSS class name of the conversation label handeling its appearance (color)
*/
-class ConversationLabel extends DatabaseObject {
- /**
- * list of pre-defined css class names
- * @var string[]
- */
- public static $availableCssClassNames = [
- 'yellow',
- 'orange',
- 'brown',
- 'red',
- 'pink',
- 'purple',
- 'blue',
- 'green',
- 'black',
-
- 'none' /* not a real value */
- ];
-
- /**
- * Returns a list of conversation labels for given user id.
- *
- * @param integer $userID
- * @return ConversationLabelList
- */
- public static function getLabelsByUser($userID = null) {
- if ($userID === null) $userID = WCF::getUser()->userID;
-
- $labelList = new ConversationLabelList();
- $labelList->getConditionBuilder()->add("conversation_label.userID = ?", [$userID]);
- $labelList->readObjects();
-
- return $labelList;
- }
-
- /**
- * Returns a list of available CSS class names.
- *
- * @return string[]
- */
- public static function getLabelCssClassNames() {
- return self::$availableCssClassNames;
- }
+class ConversationLabel extends DatabaseObject
+{
+ /**
+ * list of pre-defined css class names
+ * @var string[]
+ */
+ public static $availableCssClassNames = [
+ 'yellow',
+ 'orange',
+ 'brown',
+ 'red',
+ 'pink',
+ 'purple',
+ 'blue',
+ 'green',
+ 'black',
+
+ 'none', /* not a real value */
+ ];
+
+ /**
+ * Returns a list of conversation labels for given user id.
+ *
+ * @param integer $userID
+ * @return ConversationLabelList
+ */
+ public static function getLabelsByUser($userID = null)
+ {
+ if ($userID === null) {
+ $userID = WCF::getUser()->userID;
+ }
+
+ $labelList = new ConversationLabelList();
+ $labelList->getConditionBuilder()->add("conversation_label.userID = ?", [$userID]);
+ $labelList->readObjects();
+
+ return $labelList;
+ }
+
+ /**
+ * Returns a list of available CSS class names.
+ *
+ * @return string[]
+ */
+ public static function getLabelCssClassNames()
+ {
+ return self::$availableCssClassNames;
+ }
}
<?php
+
namespace wcf\data\conversation\label;
-use wcf\data\conversation\Conversation;
+
use wcf\data\AbstractDatabaseObjectAction;
+use wcf\data\conversation\Conversation;
use wcf\system\clipboard\ClipboardHandler;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\exception\IllegalLinkException;
/**
* Executes label-related actions.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Label
- *
- * @method ConversationLabel create()
- * @method ConversationLabelEditor[] getObjects()
- * @method ConversationLabelEditor getSingleObject()
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation\Label
+ *
+ * @method ConversationLabel create()
+ * @method ConversationLabelEditor[] getObjects()
+ * @method ConversationLabelEditor getSingleObject()
*/
-class ConversationLabelAction extends AbstractDatabaseObjectAction {
- /**
- * @inheritDoc
- */
- protected $className = ConversationLabelEditor::class;
-
- /**
- * @inheritDoc
- */
- protected $permissionsDelete = ['user.conversation.canUseConversation'];
-
- /**
- * @inheritDoc
- */
- protected $permissionsUpdate = ['user.conversation.canUseConversation'];
-
- /**
- * conversation object
- * @var Conversation
- */
- public $conversation;
-
- /**
- * conversation label list object
- * @var ConversationLabelList
- */
- public $labelList;
-
- /**
- * @inheritDoc
- */
- public function validateUpdate() {
- parent::validateUpdate();
-
- if (count($this->objects) != 1) {
- throw new UserInputException('objectID');
- }
-
- $label = current($this->objects);
- if ($label->userID != WCF::getUser()->userID) {
- throw new PermissionDeniedException();
- }
- }
-
- /**
- * @inheritDoc
- */
- public function validateDelete() {
- parent::validateDelete();
-
- if (count($this->objects) != 1) {
- throw new UserInputException('objectID');
- }
-
- $label = current($this->objects);
- if ($label->userID != WCF::getUser()->userID) {
- throw new PermissionDeniedException();
- }
- }
-
- /**
- * Validates parameters to add a new label.
- *
- * @throws PermissionDeniedException
- * @throws UserInputException
- */
- public function validateAdd() {
- if (!WCF::getSession()->getPermission('user.conversation.canUseConversation')) {
- throw new PermissionDeniedException();
- }
-
- // check if user has already created maximum number of labels
- if (count(ConversationLabel::getLabelsByUser()) >= WCF::getSession()->getPermission('user.conversation.maxLabels')) {
- throw new PermissionDeniedException();
- }
-
- $this->readString('labelName', false, 'data');
- $this->readString('cssClassName', false, 'data');
- if (!in_array($this->parameters['data']['cssClassName'], ConversationLabel::getLabelCssClassNames())) {
- throw new UserInputException('cssClassName');
- }
-
- // 'none' is a pseudo value
- if ($this->parameters['data']['cssClassName'] == 'none') $this->parameters['data']['cssClassName'] = '';
- }
-
- /**
- * Adds a new user-specific label.
- *
- * @return array
- */
- public function add() {
- $label = ConversationLabelEditor::create([
- 'userID' => WCF::getUser()->userID,
- 'label' => $this->parameters['data']['labelName'],
- 'cssClassName' => $this->parameters['data']['cssClassName']
- ]);
-
- return [
- 'actionName' => 'add',
- 'cssClassName' => $label->cssClassName,
- 'label' => StringUtil::encodeHTML($label->label),
- 'labelID' => $label->labelID
- ];
- }
-
- /**
- * Validates parameters for label assignment form.
- *
- * @throws IllegalLinkException
- * @throws PermissionDeniedException
- * @throws UserInputException
- */
- public function validateGetLabelForm() {
- if (!WCF::getSession()->getPermission('user.conversation.canUseConversation')) {
- throw new PermissionDeniedException();
- }
-
- // validate conversation id
- $this->parameters['conversationIDs'] = isset($this->parameters['conversationIDs']) ? ArrayUtil::toIntegerArray($this->parameters['conversationIDs']) : [];
- if (empty($this->parameters['conversationIDs'])) {
- throw new UserInputException('conversationID');
- }
-
- if (!Conversation::isParticipant($this->parameters['conversationIDs'])) {
- throw new PermissionDeniedException();
- }
-
- // validate available labels
- $this->labelList = ConversationLabel::getLabelsByUser();
- if (!count($this->labelList)) {
- throw new IllegalLinkException();
- }
- }
-
- /**
- * Returns the label assignment form.
- *
- * @return array
- */
- public function getLabelForm() {
- // read assigned labels
- $labelIDs = [];
- foreach ($this->labelList as $label) {
- $labelIDs[] = $label->labelID;
- }
-
- $assignedLabels = [];
- // read assigned labels if editing single conversation
- if (count($this->parameters['conversationIDs']) == 1) {
- $conversationID = current($this->parameters['conversationIDs']);
-
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID = ?", [$conversationID]);
- $conditions->add("labelID IN (?)", [$labelIDs]);
-
- $sql = "SELECT labelID
- FROM wcf".WCF_N."_conversation_label_to_object
- ".$conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditions->getParameters());
- $assignedLabels = $statement->fetchAll(\PDO::FETCH_COLUMN);
- }
-
- WCF::getTPL()->assign([
- 'assignedLabels' => $assignedLabels,
- 'conversation' => $this->conversation,
- 'labelList' => $this->labelList
- ]);
-
- return [
- 'actionName' => 'getLabelForm',
- 'template' => WCF::getTPL()->fetch('conversationLabelAssignment')
- ];
- }
-
- /**
- * Validates parameters to assign labels for a conversation.
- *
- * @throws UserInputException
- */
- public function validateAssignLabel() {
- $this->validateGetLabelForm();
-
- // validate given labels
- $this->parameters['labelIDs'] = (isset($this->parameters['labelIDs']) && is_array($this->parameters['labelIDs'])) ? ArrayUtil::toIntegerArray($this->parameters['labelIDs']) : [];
- if (!empty($this->parameters['labelIDs'])) {
- foreach ($this->parameters['labelIDs'] as $labelID) {
- $isValid = false;
-
- foreach ($this->labelList as $label) {
- if ($labelID == $label->labelID) {
- $isValid = true;
- break;
- }
- }
-
- if (!$isValid) {
- throw new UserInputException('labelIDs');
- }
- }
- }
- }
-
- /**
- * Assigns labels to a conversation.
- *
- * @return array
- */
- public function assignLabel() {
- // remove previous labels (if any)
- $labelIDs = [];
- foreach ($this->labelList as $label) {
- $labelIDs[] = $label->labelID;
- }
-
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID IN (?)", [$this->parameters['conversationIDs']]);
- $conditions->add("labelID IN (?)", [$labelIDs]);
-
- $sql = "DELETE FROM wcf".WCF_N."_conversation_label_to_object
- ".$conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditions->getParameters());
-
- // assign label ids
- if (!empty($this->parameters['labelIDs'])) {
- $sql = "INSERT INTO wcf".WCF_N."_conversation_label_to_object
+class ConversationLabelAction extends AbstractDatabaseObjectAction
+{
+ /**
+ * @inheritDoc
+ */
+ protected $className = ConversationLabelEditor::class;
+
+ /**
+ * @inheritDoc
+ */
+ protected $permissionsDelete = ['user.conversation.canUseConversation'];
+
+ /**
+ * @inheritDoc
+ */
+ protected $permissionsUpdate = ['user.conversation.canUseConversation'];
+
+ /**
+ * conversation object
+ * @var Conversation
+ */
+ public $conversation;
+
+ /**
+ * conversation label list object
+ * @var ConversationLabelList
+ */
+ public $labelList;
+
+ /**
+ * @inheritDoc
+ */
+ public function validateUpdate()
+ {
+ parent::validateUpdate();
+
+ if (\count($this->objects) != 1) {
+ throw new UserInputException('objectID');
+ }
+
+ $label = \current($this->objects);
+ if ($label->userID != WCF::getUser()->userID) {
+ throw new PermissionDeniedException();
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function validateDelete()
+ {
+ parent::validateDelete();
+
+ if (\count($this->objects) != 1) {
+ throw new UserInputException('objectID');
+ }
+
+ $label = \current($this->objects);
+ if ($label->userID != WCF::getUser()->userID) {
+ throw new PermissionDeniedException();
+ }
+ }
+
+ /**
+ * Validates parameters to add a new label.
+ *
+ * @throws PermissionDeniedException
+ * @throws UserInputException
+ */
+ public function validateAdd()
+ {
+ if (!WCF::getSession()->getPermission('user.conversation.canUseConversation')) {
+ throw new PermissionDeniedException();
+ }
+
+ // check if user has already created maximum number of labels
+ if (\count(ConversationLabel::getLabelsByUser()) >= WCF::getSession()->getPermission('user.conversation.maxLabels')) {
+ throw new PermissionDeniedException();
+ }
+
+ $this->readString('labelName', false, 'data');
+ $this->readString('cssClassName', false, 'data');
+ if (!\in_array($this->parameters['data']['cssClassName'], ConversationLabel::getLabelCssClassNames())) {
+ throw new UserInputException('cssClassName');
+ }
+
+ // 'none' is a pseudo value
+ if ($this->parameters['data']['cssClassName'] == 'none') {
+ $this->parameters['data']['cssClassName'] = '';
+ }
+ }
+
+ /**
+ * Adds a new user-specific label.
+ *
+ * @return array
+ */
+ public function add()
+ {
+ $label = ConversationLabelEditor::create([
+ 'userID' => WCF::getUser()->userID,
+ 'label' => $this->parameters['data']['labelName'],
+ 'cssClassName' => $this->parameters['data']['cssClassName'],
+ ]);
+
+ return [
+ 'actionName' => 'add',
+ 'cssClassName' => $label->cssClassName,
+ 'label' => StringUtil::encodeHTML($label->label),
+ 'labelID' => $label->labelID,
+ ];
+ }
+
+ /**
+ * Validates parameters for label assignment form.
+ *
+ * @throws IllegalLinkException
+ * @throws PermissionDeniedException
+ * @throws UserInputException
+ */
+ public function validateGetLabelForm()
+ {
+ if (!WCF::getSession()->getPermission('user.conversation.canUseConversation')) {
+ throw new PermissionDeniedException();
+ }
+
+ // validate conversation id
+ $this->parameters['conversationIDs'] = isset($this->parameters['conversationIDs']) ? ArrayUtil::toIntegerArray($this->parameters['conversationIDs']) : [];
+ if (empty($this->parameters['conversationIDs'])) {
+ throw new UserInputException('conversationID');
+ }
+
+ if (!Conversation::isParticipant($this->parameters['conversationIDs'])) {
+ throw new PermissionDeniedException();
+ }
+
+ // validate available labels
+ $this->labelList = ConversationLabel::getLabelsByUser();
+ if (!\count($this->labelList)) {
+ throw new IllegalLinkException();
+ }
+ }
+
+ /**
+ * Returns the label assignment form.
+ *
+ * @return array
+ */
+ public function getLabelForm()
+ {
+ // read assigned labels
+ $labelIDs = [];
+ foreach ($this->labelList as $label) {
+ $labelIDs[] = $label->labelID;
+ }
+
+ $assignedLabels = [];
+ // read assigned labels if editing single conversation
+ if (\count($this->parameters['conversationIDs']) == 1) {
+ $conversationID = \current($this->parameters['conversationIDs']);
+
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("conversationID = ?", [$conversationID]);
+ $conditions->add("labelID IN (?)", [$labelIDs]);
+
+ $sql = "SELECT labelID
+ FROM wcf" . WCF_N . "_conversation_label_to_object
+ " . $conditions;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditions->getParameters());
+ $assignedLabels = $statement->fetchAll(\PDO::FETCH_COLUMN);
+ }
+
+ WCF::getTPL()->assign([
+ 'assignedLabels' => $assignedLabels,
+ 'conversation' => $this->conversation,
+ 'labelList' => $this->labelList,
+ ]);
+
+ return [
+ 'actionName' => 'getLabelForm',
+ 'template' => WCF::getTPL()->fetch('conversationLabelAssignment'),
+ ];
+ }
+
+ /**
+ * Validates parameters to assign labels for a conversation.
+ *
+ * @throws UserInputException
+ */
+ public function validateAssignLabel()
+ {
+ $this->validateGetLabelForm();
+
+ // validate given labels
+ $this->parameters['labelIDs'] = (isset($this->parameters['labelIDs']) && \is_array($this->parameters['labelIDs'])) ? ArrayUtil::toIntegerArray($this->parameters['labelIDs']) : [];
+ if (!empty($this->parameters['labelIDs'])) {
+ foreach ($this->parameters['labelIDs'] as $labelID) {
+ $isValid = false;
+
+ foreach ($this->labelList as $label) {
+ if ($labelID == $label->labelID) {
+ $isValid = true;
+ break;
+ }
+ }
+
+ if (!$isValid) {
+ throw new UserInputException('labelIDs');
+ }
+ }
+ }
+ }
+
+ /**
+ * Assigns labels to a conversation.
+ *
+ * @return array
+ */
+ public function assignLabel()
+ {
+ // remove previous labels (if any)
+ $labelIDs = [];
+ foreach ($this->labelList as $label) {
+ $labelIDs[] = $label->labelID;
+ }
+
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("conversationID IN (?)", [$this->parameters['conversationIDs']]);
+ $conditions->add("labelID IN (?)", [$labelIDs]);
+
+ $sql = "DELETE FROM wcf" . WCF_N . "_conversation_label_to_object
+ " . $conditions;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditions->getParameters());
+
+ // assign label ids
+ if (!empty($this->parameters['labelIDs'])) {
+ $sql = "INSERT INTO wcf" . WCF_N . "_conversation_label_to_object
(labelID, conversationID)
VALUES (?, ?)";
- $statement = WCF::getDB()->prepareStatement($sql);
-
- WCF::getDB()->beginTransaction();
- foreach ($this->parameters['labelIDs'] as $labelID) {
- foreach ($this->parameters['conversationIDs'] as $conversationID) {
- $statement->execute([
- $labelID,
- $conversationID
- ]);
- }
- }
- WCF::getDB()->commitTransaction();
-
- if (!empty($this->parameters['conversationIDs'])) {
- ClipboardHandler::getInstance()->unmark($this->parameters['conversationIDs'], ClipboardHandler::getInstance()->getObjectTypeID('com.woltlab.wcf.conversation.conversation'));
- }
- }
-
- return [
- 'actionName' => 'assignLabel',
- 'labelIDs' => $this->parameters['labelIDs']
- ];
- }
+ $statement = WCF::getDB()->prepareStatement($sql);
+
+ WCF::getDB()->beginTransaction();
+ foreach ($this->parameters['labelIDs'] as $labelID) {
+ foreach ($this->parameters['conversationIDs'] as $conversationID) {
+ $statement->execute([
+ $labelID,
+ $conversationID,
+ ]);
+ }
+ }
+ WCF::getDB()->commitTransaction();
+
+ if (!empty($this->parameters['conversationIDs'])) {
+ ClipboardHandler::getInstance()->unmark(
+ $this->parameters['conversationIDs'],
+ ClipboardHandler::getInstance()->getObjectTypeID('com.woltlab.wcf.conversation.conversation')
+ );
+ }
+ }
+
+ return [
+ 'actionName' => 'assignLabel',
+ 'labelIDs' => $this->parameters['labelIDs'],
+ ];
+ }
}
<?php
+
namespace wcf\data\conversation\label;
+
use wcf\data\DatabaseObjectEditor;
/**
* Extends the label object with functions to create, update and delete labels.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Label
- *
- * @method static ConversationLabel create(array $parameters = [])
- * @method ConversationLabel getDecoratedObject()
- * @mixin ConversationLabel
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation\Label
+ *
+ * @method static ConversationLabel create(array $parameters = [])
+ * @method ConversationLabel getDecoratedObject()
+ * @mixin ConversationLabel
*/
-class ConversationLabelEditor extends DatabaseObjectEditor {
- /**
- * @inheritDoc
- */
- protected static $baseClass = ConversationLabel::class;
+class ConversationLabelEditor extends DatabaseObjectEditor
+{
+ /**
+ * @inheritDoc
+ */
+ protected static $baseClass = ConversationLabel::class;
}
<?php
+
namespace wcf\data\conversation\label;
+
use wcf\data\DatabaseObjectList;
/**
* Represents a list of conversation labels.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Label
- *
- * @method ConversationLabel current()
- * @method ConversationLabel[] getObjects()
- * @method ConversationLabel|null search($objectID)
- * @property ConversationLabel[] $objects
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation\Label
+ *
+ * @method ConversationLabel current()
+ * @method ConversationLabel[] getObjects()
+ * @method ConversationLabel|null search($objectID)
+ * @property ConversationLabel[] $objects
*/
-class ConversationLabelList extends DatabaseObjectList {
- /**
- * @inheritDoc
- */
- public $className = ConversationLabel::class;
+class ConversationLabelList extends DatabaseObjectList
+{
+ /**
+ * @inheritDoc
+ */
+ public $className = ConversationLabel::class;
}
<?php
+
namespace wcf\data\conversation\message;
+
use wcf\data\attachment\GroupedAttachmentList;
use wcf\data\conversation\Conversation;
use wcf\data\DatabaseObject;
/**
* Represents a conversation message.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
*
- * @property-read integer $messageID unique id of the conversation message
- * @property-read integer $conversationID id of the conversation the conversation message belongs to
- * @property-read integer|null $userID id of the user who wrote the conversation message or `null` if the user does not exist anymore
- * @property-read string $username name of the user who wrote the conversation message
- * @property-read string $message text of the conversation message
- * @property-read integer $time timestamp at which the conversation message has been written
- * @property-read integer $attachments number of attachments
- * @property-read integer $enableHtml is `1` if the conversation message's format has been converted to html, otherwise `0`
- * @property-read string $ipAddress ip address of the user who wrote the conversation message at time of writing or empty if no ip addresses are logged
- * @property-read integer $lastEditTime timestamp at which the conversation message has been edited the last time
- * @property-read integer $editCount number of times the conversation message has been edited
- * @property-read integer $hasEmbeddedObjects number of embedded objects in the conversation message
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation\Message
+ *
+ * @property-read integer $messageID unique id of the conversation message
+ * @property-read integer $conversationID id of the conversation the conversation message belongs to
+ * @property-read integer|null $userID id of the user who wrote the conversation message or `null` if the user does not exist anymore
+ * @property-read string $username name of the user who wrote the conversation message
+ * @property-read string $message text of the conversation message
+ * @property-read integer $time timestamp at which the conversation message has been written
+ * @property-read integer $attachments number of attachments
+ * @property-read integer $enableHtml is `1` if the conversation message's format has been converted to html, otherwise `0`
+ * @property-read string $ipAddress ip address of the user who wrote the conversation message at time of writing or empty if no ip addresses are logged
+ * @property-read integer $lastEditTime timestamp at which the conversation message has been edited the last time
+ * @property-read integer $editCount number of times the conversation message has been edited
+ * @property-read integer $hasEmbeddedObjects number of embedded objects in the conversation message
*/
-class ConversationMessage extends DatabaseObject implements IMessage {
- use TUserContent;
-
- /**
- * conversation object
- * @var Conversation
- */
- protected $conversation;
-
- /**
- * @inheritDoc
- */
- public function getFormattedMessage() {
- $processor = new HtmlOutputProcessor();
- $processor->process($this->message, 'com.woltlab.wcf.conversation.message', $this->messageID);
-
- return $processor->getHtml();
- }
-
- /**
- * Returns a simplified version of the formatted message.
- *
- * @return string
- */
- public function getSimplifiedFormattedMessage() {
- $processor = new HtmlOutputProcessor();
- $processor->setOutputType('text/simplified-html');
- $processor->process($this->message, 'com.woltlab.wcf.conversation.message', $this->messageID);
-
- return $processor->getHtml();
- }
-
- /**
- * Assigns and returns the embedded attachments.
- *
- * @param boolean $ignoreCache
- * @return GroupedAttachmentList
- */
- public function getAttachments($ignoreCache = false) {
- if ($this->attachments || $ignoreCache) {
- $attachmentList = new GroupedAttachmentList('com.woltlab.wcf.conversation.message');
- $attachmentList->getConditionBuilder()->add('attachment.objectID IN (?)', [$this->messageID]);
- $attachmentList->readObjects();
- $attachmentList->setPermissions([
- 'canDownload' => true,
- 'canViewPreview' => true
- ]);
-
- if ($ignoreCache && !count($attachmentList)) {
- return null;
- }
-
- return $attachmentList;
- }
-
- return null;
- }
-
- /**
- * @inheritDoc
- */
- public function getExcerpt($maxLength = 255) {
- return StringUtil::truncateHTML($this->getSimplifiedFormattedMessage(), $maxLength);
- }
-
- /**
- * Returns a version of this message optimized for use in emails.
- *
- * @param string $mimeType Either 'text/plain' or 'text/html'
- * @return string
- */
- public function getMailText($mimeType = 'text/plain') {
- switch ($mimeType) {
- case 'text/plain':
- $processor = new HtmlOutputProcessor();
- $processor->setOutputType('text/plain');
- $processor->process($this->message, 'com.woltlab.wcf.conversation.message', $this->messageID);
-
- return $processor->getHtml();
- case 'text/html':
- return $this->getSimplifiedFormattedMessage();
- }
-
- throw new \LogicException('Unreachable');
- }
-
- /**
- * Returns the conversation of this message.
- *
- * @return Conversation
- */
- public function getConversation() {
- if ($this->conversation === null) {
- $this->conversation = Conversation::getUserConversation($this->conversationID, WCF::getUser()->userID);
- }
-
- return $this->conversation;
- }
-
- /**
- * Sets the conversation of this message.
- *
- * @param Conversation $conversation
- */
- public function setConversation(Conversation $conversation) {
- if ($this->conversationID == $conversation->conversationID) {
- $this->conversation = $conversation;
- }
- }
-
- /**
- * Returns true if current user may edit this message.
- *
- * @return boolean
- */
- public function canEdit() {
- return WCF::getUser()->userID == $this->userID
- && ($this->getConversation()->isDraft || WCF::getSession()->getPermission('user.conversation.canEditMessage'))
- && $this->getConversation()->canReply();
- }
-
- /**
- * @inheritDoc
- */
- public function getMessage() {
- return $this->message;
- }
-
- /**
- * @inheritDoc
- */
- public function getLink() {
- return LinkHandler::getInstance()->getLink('Conversation', [
- 'object' => $this->getConversation(),
- 'messageID' => $this->messageID,
- 'forceFrontend' => true
- ], '#message'.$this->messageID);
- }
-
- /**
- * @inheritDoc
- */
- public function getTitle() {
- if ($this->messageID == $this->getConversation()->firstMessageID) {
- return $this->getConversation()->subject;
- }
-
- return 'RE: '.$this->getConversation()->subject;
- }
-
- /**
- * @inheritDoc
- */
- public function isVisible() {
- return true;
- }
-
- /**
- * @inheritDoc
- */
- public function __toString() {
- return $this->getFormattedMessage();
- }
+class ConversationMessage extends DatabaseObject implements IMessage
+{
+ use TUserContent;
+
+ /**
+ * conversation object
+ * @var Conversation
+ */
+ protected $conversation;
+
+ /**
+ * @inheritDoc
+ */
+ public function getFormattedMessage()
+ {
+ $processor = new HtmlOutputProcessor();
+ $processor->process($this->message, 'com.woltlab.wcf.conversation.message', $this->messageID);
+
+ return $processor->getHtml();
+ }
+
+ /**
+ * Returns a simplified version of the formatted message.
+ *
+ * @return string
+ */
+ public function getSimplifiedFormattedMessage()
+ {
+ $processor = new HtmlOutputProcessor();
+ $processor->setOutputType('text/simplified-html');
+ $processor->process($this->message, 'com.woltlab.wcf.conversation.message', $this->messageID);
+
+ return $processor->getHtml();
+ }
+
+ /**
+ * Assigns and returns the embedded attachments.
+ *
+ * @param boolean $ignoreCache
+ * @return GroupedAttachmentList
+ */
+ public function getAttachments($ignoreCache = false)
+ {
+ if ($this->attachments || $ignoreCache) {
+ $attachmentList = new GroupedAttachmentList('com.woltlab.wcf.conversation.message');
+ $attachmentList->getConditionBuilder()->add('attachment.objectID IN (?)', [$this->messageID]);
+ $attachmentList->readObjects();
+ $attachmentList->setPermissions([
+ 'canDownload' => true,
+ 'canViewPreview' => true,
+ ]);
+
+ if ($ignoreCache && !\count($attachmentList)) {
+ return;
+ }
+
+ return $attachmentList;
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getExcerpt($maxLength = 255)
+ {
+ return StringUtil::truncateHTML($this->getSimplifiedFormattedMessage(), $maxLength);
+ }
+
+ /**
+ * Returns a version of this message optimized for use in emails.
+ *
+ * @param string $mimeType Either 'text/plain' or 'text/html'
+ * @return string
+ */
+ public function getMailText($mimeType = 'text/plain')
+ {
+ switch ($mimeType) {
+ case 'text/plain':
+ $processor = new HtmlOutputProcessor();
+ $processor->setOutputType('text/plain');
+ $processor->process($this->message, 'com.woltlab.wcf.conversation.message', $this->messageID);
+
+ return $processor->getHtml();
+ case 'text/html':
+ return $this->getSimplifiedFormattedMessage();
+ }
+
+ throw new \LogicException('Unreachable');
+ }
+
+ /**
+ * Returns the conversation of this message.
+ *
+ * @return Conversation
+ */
+ public function getConversation()
+ {
+ if ($this->conversation === null) {
+ $this->conversation = Conversation::getUserConversation($this->conversationID, WCF::getUser()->userID);
+ }
+
+ return $this->conversation;
+ }
+
+ /**
+ * Sets the conversation of this message.
+ *
+ * @param Conversation $conversation
+ */
+ public function setConversation(Conversation $conversation)
+ {
+ if ($this->conversationID == $conversation->conversationID) {
+ $this->conversation = $conversation;
+ }
+ }
+
+ /**
+ * Returns true if current user may edit this message.
+ *
+ * @return boolean
+ */
+ public function canEdit()
+ {
+ return WCF::getUser()->userID == $this->userID
+ && (
+ $this->getConversation()->isDraft
+ || WCF::getSession()->getPermission('user.conversation.canEditMessage')
+ )
+ && $this->getConversation()->canReply();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getMessage()
+ {
+ return $this->message;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getLink()
+ {
+ return LinkHandler::getInstance()->getLink('Conversation', [
+ 'object' => $this->getConversation(),
+ 'messageID' => $this->messageID,
+ 'forceFrontend' => true,
+ ], '#message' . $this->messageID);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getTitle()
+ {
+ if ($this->messageID == $this->getConversation()->firstMessageID) {
+ return $this->getConversation()->subject;
+ }
+
+ return 'RE: ' . $this->getConversation()->subject;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function isVisible()
+ {
+ return true;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function __toString()
+ {
+ return $this->getFormattedMessage();
+ }
}
<?php
+
namespace wcf\data\conversation\message;
+
+use wcf\data\AbstractDatabaseObjectAction;
use wcf\data\conversation\Conversation;
use wcf\data\conversation\ConversationAction;
use wcf\data\conversation\ConversationEditor;
-use wcf\data\smiley\SmileyCache;
-use wcf\data\AbstractDatabaseObjectAction;
use wcf\data\DatabaseObject;
use wcf\data\IAttachmentMessageQuickReplyAction;
use wcf\data\IMessageInlineEditorAction;
use wcf\data\IMessageQuoteAction;
+use wcf\data\smiley\SmileyCache;
use wcf\system\attachment\AttachmentHandler;
use wcf\system\bbcode\BBCodeHandler;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\html\input\HtmlInputProcessor;
use wcf\system\message\censorship\Censorship;
use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
-use wcf\system\message\quote\MessageQuoteManager;
use wcf\system\message\QuickReplyManager;
+use wcf\system\message\quote\MessageQuoteManager;
use wcf\system\moderation\queue\ModerationQueueManager;
use wcf\system\request\LinkHandler;
use wcf\system\search\SearchIndexManager;
/**
* Executes conversation message-related actions.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
- *
- * @method ConversationMessageEditor[] getObjects()
- * @method ConversationMessageEditor getSingleObject()
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation\Message
+ *
+ * @method ConversationMessageEditor[] getObjects()
+ * @method ConversationMessageEditor getSingleObject()
*/
-class ConversationMessageAction extends AbstractDatabaseObjectAction implements IAttachmentMessageQuickReplyAction, IMessageInlineEditorAction, IMessageQuoteAction {
- /**
- * @inheritDoc
- */
- protected $className = ConversationMessageEditor::class;
-
- /**
- * conversation object
- * @var Conversation
- */
- public $conversation;
-
- /**
- * @var HtmlInputProcessor
- */
- public $htmlInputProcessor;
-
- /**
- * conversation message object
- * @var ConversationMessage
- */
- public $message;
-
- /**
- * @inheritDoc
- * @return ConversationMessage
- */
- public function create() {
- if (!isset($this->parameters['data']['enableHtml'])) $this->parameters['data']['enableHtml'] = 1;
-
- // count attachments
- if (isset($this->parameters['attachmentHandler']) && $this->parameters['attachmentHandler'] !== null) {
- $this->parameters['data']['attachments'] = count($this->parameters['attachmentHandler']);
- }
-
- if (LOG_IP_ADDRESS) {
- // add ip address
- if (!isset($this->parameters['data']['ipAddress'])) {
- $this->parameters['data']['ipAddress'] = WCF::getSession()->ipAddress;
- }
- }
- else {
- // do not track ip address
- if (isset($this->parameters['data']['ipAddress'])) {
- unset($this->parameters['data']['ipAddress']);
- }
- }
-
- if (!empty($this->parameters['htmlInputProcessor'])) {
- /** @noinspection PhpUndefinedMethodInspection */
- $this->parameters['data']['message'] = $this->parameters['htmlInputProcessor']->getHtml();
- }
-
- // create message
- /** @var ConversationMessage $message */
- $message = parent::create();
- $messageEditor = new ConversationMessageEditor($message);
-
- // get conversation
- $conversation = (isset($this->parameters['conversation']) ? $this->parameters['conversation'] : new Conversation($message->conversationID));
- $conversationEditor = new ConversationEditor($conversation);
-
- if (empty($this->parameters['isFirstPost'])) {
- // update last message
- $conversationEditor->addMessage($message);
-
- // fire notification event
- if (!$conversation->isDraft) {
- $notificationRecipients = array_diff($conversation->getParticipantIDs(true), [$message->userID]); // don't notify message author
- if (!empty($notificationRecipients)) {
- UserNotificationHandler::getInstance()->fireEvent(
- 'conversationMessage',
- 'com.woltlab.wcf.conversation.message.notification',
- new ConversationMessageUserNotificationObject($message),
- $notificationRecipients
- );
- }
- }
-
- $userConversation = Conversation::getUserConversation($conversation->conversationID, $message->userID);
- if ($userConversation !== null && $userConversation->isInvisible) {
- // make invisible participant visible
- $sql = "UPDATE wcf".WCF_N."_conversation_to_user
+class ConversationMessageAction extends AbstractDatabaseObjectAction implements
+ IAttachmentMessageQuickReplyAction,
+ IMessageInlineEditorAction,
+ IMessageQuoteAction
+{
+ /**
+ * @inheritDoc
+ */
+ protected $className = ConversationMessageEditor::class;
+
+ /**
+ * conversation object
+ * @var Conversation
+ */
+ public $conversation;
+
+ /**
+ * @var HtmlInputProcessor
+ */
+ public $htmlInputProcessor;
+
+ /**
+ * conversation message object
+ * @var ConversationMessage
+ */
+ public $message;
+
+ /**
+ * @inheritDoc
+ * @return ConversationMessage
+ */
+ public function create()
+ {
+ if (!isset($this->parameters['data']['enableHtml'])) {
+ $this->parameters['data']['enableHtml'] = 1;
+ }
+
+ // count attachments
+ if (isset($this->parameters['attachmentHandler']) && $this->parameters['attachmentHandler'] !== null) {
+ $this->parameters['data']['attachments'] = \count($this->parameters['attachmentHandler']);
+ }
+
+ if (LOG_IP_ADDRESS) {
+ // add ip address
+ if (!isset($this->parameters['data']['ipAddress'])) {
+ $this->parameters['data']['ipAddress'] = WCF::getSession()->ipAddress;
+ }
+ } else {
+ // do not track ip address
+ if (isset($this->parameters['data']['ipAddress'])) {
+ unset($this->parameters['data']['ipAddress']);
+ }
+ }
+
+ if (!empty($this->parameters['htmlInputProcessor'])) {
+ /** @noinspection PhpUndefinedMethodInspection */
+ $this->parameters['data']['message'] = $this->parameters['htmlInputProcessor']->getHtml();
+ }
+
+ // create message
+ /** @var ConversationMessage $message */
+ $message = parent::create();
+ $messageEditor = new ConversationMessageEditor($message);
+
+ // get conversation
+ $conversation = ($this->parameters['conversation'] ?? new Conversation($message->conversationID));
+ $conversationEditor = new ConversationEditor($conversation);
+
+ if (empty($this->parameters['isFirstPost'])) {
+ // update last message
+ $conversationEditor->addMessage($message);
+
+ // fire notification event
+ if (!$conversation->isDraft) {
+ // don't notify message author
+ $notificationRecipients = \array_diff($conversation->getParticipantIDs(true), [$message->userID]);
+ if (!empty($notificationRecipients)) {
+ UserNotificationHandler::getInstance()->fireEvent(
+ 'conversationMessage',
+ 'com.woltlab.wcf.conversation.message.notification',
+ new ConversationMessageUserNotificationObject($message),
+ $notificationRecipients
+ );
+ }
+ }
+
+ $userConversation = Conversation::getUserConversation($conversation->conversationID, $message->userID);
+ if ($userConversation !== null && $userConversation->isInvisible) {
+ // make invisible participant visible
+ $sql = "UPDATE wcf" . WCF_N . "_conversation_to_user
SET isInvisible = 0
WHERE participantID = ?
AND conversationID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute([$message->userID, $conversation->conversationID]);
-
- $conversationEditor->updateParticipantSummary();
- $conversationEditor->updateParticipantCount();
- }
-
- // reset visibility if it was hidden but not left
- $sql = "UPDATE wcf".WCF_N."_conversation_to_user
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([$message->userID, $conversation->conversationID]);
+
+ $conversationEditor->updateParticipantSummary();
+ $conversationEditor->updateParticipantCount();
+ }
+
+ // reset visibility if it was hidden but not left
+ $sql = "UPDATE wcf" . WCF_N . "_conversation_to_user
SET hideConversation = ?
WHERE conversationID = ?
AND hideConversation = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute([
- Conversation::STATE_DEFAULT,
- $conversation->conversationID,
- Conversation::STATE_HIDDEN
- ]);
- }
-
- // reset storage
- UserStorageHandler::getInstance()->reset($conversation->getParticipantIDs(), 'unreadConversationCount');
-
- // update search index
- SearchIndexManager::getInstance()->set(
- 'com.woltlab.wcf.conversation.message',
- $message->messageID,
- $message->message,
- !empty($this->parameters['isFirstPost']) ? $conversation->subject : '',
- $message->time,
- $message->userID,
- $message->username
- );
-
- // update attachments
- if (isset($this->parameters['attachmentHandler']) && $this->parameters['attachmentHandler'] !== null) {
- /** @noinspection PhpUndefinedMethodInspection */
- $this->parameters['attachmentHandler']->updateObjectID($message->messageID);
- }
-
- // save embedded objects
- if (!empty($this->parameters['htmlInputProcessor'])) {
- /** @noinspection PhpUndefinedMethodInspection */
- $this->parameters['htmlInputProcessor']->setObjectID($message->messageID);
-
- if (MessageEmbeddedObjectManager::getInstance()->registerObjects($this->parameters['htmlInputProcessor'])) {
- $messageEditor->update(['hasEmbeddedObjects' => 1]);
- }
- }
-
- // clear quotes
- if (isset($this->parameters['removeQuoteIDs']) && !empty($this->parameters['removeQuoteIDs'])) {
- MessageQuoteManager::getInstance()->markQuotesForRemoval($this->parameters['removeQuoteIDs']);
- }
- MessageQuoteManager::getInstance()->removeMarkedQuotes();
-
- // return new message
- return $message;
- }
-
- /**
- * @inheritDoc
- */
- public function update() {
- // count attachments
- if (isset($this->parameters['attachmentHandler']) && $this->parameters['attachmentHandler'] !== null) {
- $this->parameters['data']['attachments'] = count($this->parameters['attachmentHandler']);
- }
-
- if (!empty($this->parameters['htmlInputProcessor'])) {
- /** @noinspection PhpUndefinedMethodInspection */
- $this->parameters['data']['message'] = $this->parameters['htmlInputProcessor']->getHtml();
- }
-
- parent::update();
-
- // update search index / embedded objects
- if (isset($this->parameters['data']) && isset($this->parameters['data']['message'])) {
- foreach ($this->getObjects() as $message) {
- $conversation = $message->getConversation();
- SearchIndexManager::getInstance()->set(
- 'com.woltlab.wcf.conversation.message',
- $message->messageID,
- $this->parameters['data']['message'],
- $conversation->firstMessageID == $message->messageID ? $conversation->subject : '',
- $message->time,
- $message->userID,
- $message->username
- );
-
- if (!empty($this->parameters['htmlInputProcessor'])) {
- /** @noinspection PhpUndefinedMethodInspection */
- $this->parameters['htmlInputProcessor']->setObjectID($message->messageID);
-
- if ($message->hasEmbeddedObjects != MessageEmbeddedObjectManager::getInstance()->registerObjects($this->parameters['htmlInputProcessor'])) {
- $message->update(['hasEmbeddedObjects' => $message->hasEmbeddedObjects ? 0 : 1]);
- }
- }
- }
- }
- }
-
- /**
- * @inheritDoc
- */
- public function delete() {
- $count = parent::delete();
-
- $attachmentMessageIDs = $conversationIDs = [];
- foreach ($this->getObjects() as $message) {
- if (!in_array($message->conversationID, $conversationIDs)) {
- $conversationIDs[] = $message->conversationID;
- }
-
- if ($message->attachments) {
- $attachmentMessageIDs[] = $message->messageID;
- }
- }
-
- // rebuild conversations
- if (!empty($conversationIDs)) {
- $conversationAction = new ConversationAction($conversationIDs, 'rebuild');
- $conversationAction->executeAction();
- }
-
- if (!empty($this->objectIDs)) {
- // delete notifications
- UserNotificationHandler::getInstance()->removeNotifications('com.woltlab.wcf.conversation.message.notification', $this->objectIDs);
-
- // update search index
- SearchIndexManager::getInstance()->delete('com.woltlab.wcf.conversation.message', $this->objectIDs);
-
- // update embedded objects
- MessageEmbeddedObjectManager::getInstance()->removeObjects('com.woltlab.wcf.conversation.message', $this->objectIDs);
-
- // remove moderation queues
- ModerationQueueManager::getInstance()->removeQueues('com.woltlab.wcf.conversation.message', $this->objectIDs);
- }
-
- // remove attachments
- if (!empty($attachmentMessageIDs)) {
- AttachmentHandler::removeAttachments('com.woltlab.wcf.conversation.message', $attachmentMessageIDs);
- }
-
- return $count;
- }
-
- /**
- * @inheritDoc
- */
- public function validateQuickReply() {
- QuickReplyManager::getInstance()->setDisallowedBBCodes(explode(',', WCF::getSession()->getPermission('user.message.disallowedBBCodes')));
- QuickReplyManager::getInstance()->validateParameters($this, $this->parameters, Conversation::class);
- }
-
- /**
- * @inheritDoc
- */
- public function quickReply() {
- return QuickReplyManager::getInstance()->createMessage(
- $this,
- $this->parameters,
- ConversationAction::class,
- CONVERSATION_LIST_DEFAULT_SORT_ORDER,
- 'conversationMessageList'
- );
- }
-
- /**
- * @inheritDoc
- */
- public function validateJumpToExtended() {
- $this->readInteger('containerID');
- $this->readString('message', true);
- $this->readString('tmpHash', true);
-
- $this->conversation = new Conversation($this->parameters['containerID']);
- if (!$this->conversation->conversationID) {
- throw new UserInputException('containerID');
- }
- else if ($this->conversation->isClosed || !Conversation::isParticipant([$this->conversation->conversationID])) {
- throw new PermissionDeniedException();
- }
-
- // editing existing message
- if (isset($this->parameters['messageID'])) {
- $this->message = new ConversationMessage(intval($this->parameters['messageID']));
- if (!$this->message->messageID || ($this->message->conversationID != $this->conversation->conversationID)) {
- throw new UserInputException('messageID');
- }
-
- if (!$this->message->canEdit()) {
- throw new PermissionDeniedException();
- }
- }
- }
-
- /**
- * @inheritDoc
- */
- public function jumpToExtended() {
- // quick reply
- if ($this->message === null) {
- QuickReplyManager::getInstance()->setMessage('conversation', $this->conversation->conversationID, $this->parameters['message']);
- $url = LinkHandler::getInstance()->getLink('ConversationMessageAdd', ['id' => $this->conversation->conversationID]);
- }
- else {
- // editing message
- QuickReplyManager::getInstance()->setMessage('conversationMessage', $this->message->messageID, $this->parameters['message']);
- $url = LinkHandler::getInstance()->getLink('ConversationMessageEdit', ['id' => $this->message->messageID]);
- }
-
- if (!empty($this->parameters['tmpHash'])) {
- QuickReplyManager::getInstance()->setTmpHash($this->parameters['tmpHash']);
- }
-
- // redirect
- return [
- 'url' => $url
- ];
- }
-
- /**
- * @inheritDoc
- */
- public function validateBeginEdit() {
- $this->readInteger('containerID');
- $this->readInteger('objectID');
-
- $this->conversation = new Conversation($this->parameters['containerID']);
- if (!$this->conversation->conversationID) {
- throw new UserInputException('containerID');
- }
-
- if ($this->conversation->isClosed || !Conversation::isParticipant([$this->conversation->conversationID])) {
- throw new PermissionDeniedException();
- }
-
- $this->message = new ConversationMessage($this->parameters['objectID']);
- if (!$this->message->messageID) {
- throw new UserInputException('objectID');
- }
-
- if (!$this->message->canEdit()) {
- throw new PermissionDeniedException();
- }
-
- BBCodeHandler::getInstance()->setDisallowedBBCodes(explode(',', WCF::getSession()->getPermission('user.message.disallowedBBCodes')));
- }
-
- /**
- * @inheritDoc
- */
- public function beginEdit() {
- WCF::getTPL()->assign([
- 'defaultSmilies' => SmileyCache::getInstance()->getCategorySmilies(),
- 'message' => $this->message,
- 'permissionCanUseSmilies' => 'user.message.canUseSmilies',
- 'wysiwygSelector' => 'messageEditor'.$this->message->messageID,
- ]);
-
- $tmpHash = StringUtil::getRandomID();
- $attachmentHandler = new AttachmentHandler('com.woltlab.wcf.conversation.message', $this->message->messageID, $tmpHash);
- $attachmentList = $attachmentHandler->getAttachmentList();
-
- WCF::getTPL()->assign([
- 'attachmentHandler' => $attachmentHandler,
- 'attachmentList' => $attachmentList->getObjects(),
- 'attachmentObjectID' => $this->message->messageID,
- 'attachmentObjectType' => 'com.woltlab.wcf.conversation.message',
- 'attachmentParentObjectID' => 0,
- 'tmpHash' => $tmpHash,
- ]);
-
- return [
- 'actionName' => 'beginEdit',
- 'template' => WCF::getTPL()->fetch('conversationMessageInlineEditor'),
- ];
- }
-
- /**
- * @inheritDoc
- */
- public function validateSave() {
- $this->readString('message', true, 'data');
-
- if (empty($this->parameters['data']['message'])) {
- throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('wcf.global.form.error.empty'));
- }
-
- $this->validateBeginEdit();
-
- $this->validateMessage($this->conversation, $this->getHtmlInputProcessor($this->parameters['data']['message'], $this->message->messageID));
- }
-
- /**
- * @inheritDoc
- */
- public function save() {
- $data = [];
-
- if (!$this->message->getConversation()->isDraft) {
- $data['lastEditTime'] = TIME_NOW;
- $data['editCount'] = $this->message->editCount + 1;
- }
- // execute update action
- $action = new ConversationMessageAction([$this->message], 'update', [
- 'data' => $data,
- 'htmlInputProcessor' => $this->getHtmlInputProcessor()
- ]);
- $action->executeAction();
-
- // load new message
- $this->message = new ConversationMessage($this->message->messageID);
- $this->message->getAttachments();
-
- $attachmentList = $this->message->getAttachments(true);
- $count = 0;
- if ($attachmentList !== null) {
- // set permissions
- $attachmentList->setPermissions([
- 'canDownload' => true,
- 'canViewPreview' => true,
- ]);
-
- $count = count($attachmentList);
- }
-
- // update count to reflect number of attachments after edit
- if ($count != $this->message->attachments) {
- $messageEditor = new ConversationMessageEditor($this->message);
- $messageEditor->update(['attachments' => $count]);
- }
-
- // load embedded objects
- MessageEmbeddedObjectManager::getInstance()->loadObjects('com.woltlab.wcf.conversation.message', [$this->message->messageID]);
-
- $data = [
- 'actionName' => 'save',
- 'message' => $this->message->getFormattedMessage()
- ];
-
- WCF::getTPL()->assign([
- 'attachmentList' => $attachmentList,
- 'objectID' => $this->message->messageID
- ]);
- $data['attachmentList'] = WCF::getTPL()->fetch('attachments');
-
- return $data;
- }
-
- /**
- * @inheritDoc
- */
- public function validateContainer(DatabaseObject $conversation) {
- /** @var Conversation $conversation */
-
- if (!$conversation->conversationID) {
- throw new UserInputException('objectID');
- }
- if ($conversation->isClosed) {
- throw new PermissionDeniedException();
- }
- $conversation->loadUserParticipation();
- if (!$conversation->canRead() || !$conversation->canReply()) {
- throw new PermissionDeniedException();
- }
- }
-
- /**
- * @inheritDoc
- */
- public function validateMessage(DatabaseObject $container, HtmlInputProcessor $htmlInputProcessor) {
- $message = $htmlInputProcessor->getTextContent();
- if (mb_strlen($message) > WCF::getSession()->getPermission('user.conversation.maxLength')) {
- throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('wcf.message.error.tooLong', ['maxTextLength' => WCF::getSession()->getPermission('user.conversation.maxLength')]));
- }
-
- // search for disallowed bbcodes
- $disallowedBBCodes = $htmlInputProcessor->validate();
- if (!empty($disallowedBBCodes)) {
- throw new UserInputException('text', WCF::getLanguage()->getDynamicVariable('wcf.message.error.disallowedBBCodes', ['disallowedBBCodes' => $disallowedBBCodes]));
- }
-
- // search for censored words
- if (ENABLE_CENSORSHIP) {
- $result = Censorship::getInstance()->test($message);
- if ($result) {
- throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('wcf.message.error.censoredWordsFound', ['censoredWords' => $result]));
- }
- }
- }
-
- /**
- * @inheritDoc
- */
- public function getMessageList(DatabaseObject $conversation, $lastMessageTime) {
- /** @var Conversation $conversation */
-
- $messageList = new ViewableConversationMessageList();
- $messageList->setConversation($conversation);
- $messageList->getConditionBuilder()->add("conversation_message.conversationID = ?", [$conversation->conversationID]);
- $messageList->getConditionBuilder()->add("conversation_message.time > ?", [$lastMessageTime]);
- $messageList->sqlOrderBy = "conversation_message.time ".CONVERSATION_LIST_DEFAULT_SORT_ORDER;
- $messageList->readObjects();
-
- return $messageList;
- }
-
- /**
- * @inheritDoc
- */
- public function getPageNo(DatabaseObject $conversation) {
- /** @var Conversation $conversation */
-
- $sql = "SELECT COUNT(*) AS count
- FROM wcf".WCF_N."_conversation_message
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([
+ Conversation::STATE_DEFAULT,
+ $conversation->conversationID,
+ Conversation::STATE_HIDDEN,
+ ]);
+ }
+
+ // reset storage
+ UserStorageHandler::getInstance()->reset($conversation->getParticipantIDs(), 'unreadConversationCount');
+
+ // update search index
+ SearchIndexManager::getInstance()->set(
+ 'com.woltlab.wcf.conversation.message',
+ $message->messageID,
+ $message->message,
+ !empty($this->parameters['isFirstPost']) ? $conversation->subject : '',
+ $message->time,
+ $message->userID,
+ $message->username
+ );
+
+ // update attachments
+ if (isset($this->parameters['attachmentHandler']) && $this->parameters['attachmentHandler'] !== null) {
+ /** @noinspection PhpUndefinedMethodInspection */
+ $this->parameters['attachmentHandler']->updateObjectID($message->messageID);
+ }
+
+ // save embedded objects
+ if (!empty($this->parameters['htmlInputProcessor'])) {
+ /** @noinspection PhpUndefinedMethodInspection */
+ $this->parameters['htmlInputProcessor']->setObjectID($message->messageID);
+
+ if (MessageEmbeddedObjectManager::getInstance()->registerObjects($this->parameters['htmlInputProcessor'])) {
+ $messageEditor->update(['hasEmbeddedObjects' => 1]);
+ }
+ }
+
+ // clear quotes
+ if (isset($this->parameters['removeQuoteIDs']) && !empty($this->parameters['removeQuoteIDs'])) {
+ MessageQuoteManager::getInstance()->markQuotesForRemoval($this->parameters['removeQuoteIDs']);
+ }
+ MessageQuoteManager::getInstance()->removeMarkedQuotes();
+
+ // return new message
+ return $message;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function update()
+ {
+ // count attachments
+ if (isset($this->parameters['attachmentHandler']) && $this->parameters['attachmentHandler'] !== null) {
+ $this->parameters['data']['attachments'] = \count($this->parameters['attachmentHandler']);
+ }
+
+ if (!empty($this->parameters['htmlInputProcessor'])) {
+ /** @noinspection PhpUndefinedMethodInspection */
+ $this->parameters['data']['message'] = $this->parameters['htmlInputProcessor']->getHtml();
+ }
+
+ parent::update();
+
+ // update search index / embedded objects
+ if (isset($this->parameters['data']) && isset($this->parameters['data']['message'])) {
+ foreach ($this->getObjects() as $message) {
+ $conversation = $message->getConversation();
+ SearchIndexManager::getInstance()->set(
+ 'com.woltlab.wcf.conversation.message',
+ $message->messageID,
+ $this->parameters['data']['message'],
+ $conversation->firstMessageID == $message->messageID ? $conversation->subject : '',
+ $message->time,
+ $message->userID,
+ $message->username
+ );
+
+ if (!empty($this->parameters['htmlInputProcessor'])) {
+ /** @noinspection PhpUndefinedMethodInspection */
+ $this->parameters['htmlInputProcessor']->setObjectID($message->messageID);
+
+ if ($message->hasEmbeddedObjects != MessageEmbeddedObjectManager::getInstance()->registerObjects($this->parameters['htmlInputProcessor'])) {
+ $message->update(['hasEmbeddedObjects' => $message->hasEmbeddedObjects ? 0 : 1]);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function delete()
+ {
+ $count = parent::delete();
+
+ $attachmentMessageIDs = $conversationIDs = [];
+ foreach ($this->getObjects() as $message) {
+ if (!\in_array($message->conversationID, $conversationIDs)) {
+ $conversationIDs[] = $message->conversationID;
+ }
+
+ if ($message->attachments) {
+ $attachmentMessageIDs[] = $message->messageID;
+ }
+ }
+
+ // rebuild conversations
+ if (!empty($conversationIDs)) {
+ $conversationAction = new ConversationAction($conversationIDs, 'rebuild');
+ $conversationAction->executeAction();
+ }
+
+ if (!empty($this->objectIDs)) {
+ // delete notifications
+ UserNotificationHandler::getInstance()
+ ->removeNotifications('com.woltlab.wcf.conversation.message.notification', $this->objectIDs);
+
+ // update search index
+ SearchIndexManager::getInstance()->delete('com.woltlab.wcf.conversation.message', $this->objectIDs);
+
+ // update embedded objects
+ MessageEmbeddedObjectManager::getInstance()
+ ->removeObjects('com.woltlab.wcf.conversation.message', $this->objectIDs);
+
+ // remove moderation queues
+ ModerationQueueManager::getInstance()
+ ->removeQueues('com.woltlab.wcf.conversation.message', $this->objectIDs);
+ }
+
+ // remove attachments
+ if (!empty($attachmentMessageIDs)) {
+ AttachmentHandler::removeAttachments('com.woltlab.wcf.conversation.message', $attachmentMessageIDs);
+ }
+
+ return $count;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function validateQuickReply()
+ {
+ QuickReplyManager::getInstance()->setDisallowedBBCodes(\explode(
+ ',',
+ WCF::getSession()->getPermission('user.message.disallowedBBCodes')
+ ));
+ QuickReplyManager::getInstance()->validateParameters($this, $this->parameters, Conversation::class);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function quickReply()
+ {
+ return QuickReplyManager::getInstance()->createMessage(
+ $this,
+ $this->parameters,
+ ConversationAction::class,
+ CONVERSATION_LIST_DEFAULT_SORT_ORDER,
+ 'conversationMessageList'
+ );
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function validateJumpToExtended()
+ {
+ $this->readInteger('containerID');
+ $this->readString('message', true);
+ $this->readString('tmpHash', true);
+
+ $this->conversation = new Conversation($this->parameters['containerID']);
+ if (!$this->conversation->conversationID) {
+ throw new UserInputException('containerID');
+ } elseif (
+ $this->conversation->isClosed
+ || !Conversation::isParticipant([$this->conversation->conversationID])
+ ) {
+ throw new PermissionDeniedException();
+ }
+
+ // editing existing message
+ if (isset($this->parameters['messageID'])) {
+ $this->message = new ConversationMessage(\intval($this->parameters['messageID']));
+ if (!$this->message->messageID || ($this->message->conversationID != $this->conversation->conversationID)) {
+ throw new UserInputException('messageID');
+ }
+
+ if (!$this->message->canEdit()) {
+ throw new PermissionDeniedException();
+ }
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function jumpToExtended()
+ {
+ // quick reply
+ if ($this->message === null) {
+ QuickReplyManager::getInstance()
+ ->setMessage('conversation', $this->conversation->conversationID, $this->parameters['message']);
+ $url = LinkHandler::getInstance()->getLink(
+ 'ConversationMessageAdd',
+ ['id' => $this->conversation->conversationID]
+ );
+ } else {
+ // editing message
+ QuickReplyManager::getInstance()
+ ->setMessage('conversationMessage', $this->message->messageID, $this->parameters['message']);
+ $url = LinkHandler::getInstance()->getLink(
+ 'ConversationMessageEdit',
+ ['id' => $this->message->messageID]
+ );
+ }
+
+ if (!empty($this->parameters['tmpHash'])) {
+ QuickReplyManager::getInstance()->setTmpHash($this->parameters['tmpHash']);
+ }
+
+ // redirect
+ return [
+ 'url' => $url,
+ ];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function validateBeginEdit()
+ {
+ $this->readInteger('containerID');
+ $this->readInteger('objectID');
+
+ $this->conversation = new Conversation($this->parameters['containerID']);
+ if (!$this->conversation->conversationID) {
+ throw new UserInputException('containerID');
+ }
+
+ if ($this->conversation->isClosed || !Conversation::isParticipant([$this->conversation->conversationID])) {
+ throw new PermissionDeniedException();
+ }
+
+ $this->message = new ConversationMessage($this->parameters['objectID']);
+ if (!$this->message->messageID) {
+ throw new UserInputException('objectID');
+ }
+
+ if (!$this->message->canEdit()) {
+ throw new PermissionDeniedException();
+ }
+
+ BBCodeHandler::getInstance()->setDisallowedBBCodes(\explode(
+ ',',
+ WCF::getSession()->getPermission('user.message.disallowedBBCodes')
+ ));
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function beginEdit()
+ {
+ WCF::getTPL()->assign([
+ 'defaultSmilies' => SmileyCache::getInstance()->getCategorySmilies(),
+ 'message' => $this->message,
+ 'permissionCanUseSmilies' => 'user.message.canUseSmilies',
+ 'wysiwygSelector' => 'messageEditor' . $this->message->messageID,
+ ]);
+
+ $tmpHash = StringUtil::getRandomID();
+ $attachmentHandler = new AttachmentHandler(
+ 'com.woltlab.wcf.conversation.message',
+ $this->message->messageID,
+ $tmpHash
+ );
+ $attachmentList = $attachmentHandler->getAttachmentList();
+
+ WCF::getTPL()->assign([
+ 'attachmentHandler' => $attachmentHandler,
+ 'attachmentList' => $attachmentList->getObjects(),
+ 'attachmentObjectID' => $this->message->messageID,
+ 'attachmentObjectType' => 'com.woltlab.wcf.conversation.message',
+ 'attachmentParentObjectID' => 0,
+ 'tmpHash' => $tmpHash,
+ ]);
+
+ return [
+ 'actionName' => 'beginEdit',
+ 'template' => WCF::getTPL()->fetch('conversationMessageInlineEditor'),
+ ];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function validateSave()
+ {
+ $this->readString('message', true, 'data');
+
+ if (empty($this->parameters['data']['message'])) {
+ throw new UserInputException(
+ 'message',
+ WCF::getLanguage()->getDynamicVariable('wcf.global.form.error.empty')
+ );
+ }
+
+ $this->validateBeginEdit();
+
+ $this->validateMessage(
+ $this->conversation,
+ $this->getHtmlInputProcessor($this->parameters['data']['message'], $this->message->messageID)
+ );
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function save()
+ {
+ $data = [];
+
+ if (!$this->message->getConversation()->isDraft) {
+ $data['lastEditTime'] = TIME_NOW;
+ $data['editCount'] = $this->message->editCount + 1;
+ }
+ // execute update action
+ $action = new self([$this->message], 'update', [
+ 'data' => $data,
+ 'htmlInputProcessor' => $this->getHtmlInputProcessor(),
+ ]);
+ $action->executeAction();
+
+ // load new message
+ $this->message = new ConversationMessage($this->message->messageID);
+ $this->message->getAttachments();
+
+ $attachmentList = $this->message->getAttachments(true);
+ $count = 0;
+ if ($attachmentList !== null) {
+ // set permissions
+ $attachmentList->setPermissions([
+ 'canDownload' => true,
+ 'canViewPreview' => true,
+ ]);
+
+ $count = \count($attachmentList);
+ }
+
+ // update count to reflect number of attachments after edit
+ if ($count != $this->message->attachments) {
+ $messageEditor = new ConversationMessageEditor($this->message);
+ $messageEditor->update(['attachments' => $count]);
+ }
+
+ // load embedded objects
+ MessageEmbeddedObjectManager::getInstance()
+ ->loadObjects('com.woltlab.wcf.conversation.message', [$this->message->messageID]);
+
+ $data = [
+ 'actionName' => 'save',
+ 'message' => $this->message->getFormattedMessage(),
+ ];
+
+ WCF::getTPL()->assign([
+ 'attachmentList' => $attachmentList,
+ 'objectID' => $this->message->messageID,
+ ]);
+ $data['attachmentList'] = WCF::getTPL()->fetch('attachments');
+
+ return $data;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function validateContainer(DatabaseObject $conversation)
+ {
+ /** @var Conversation $conversation */
+
+ if (!$conversation->conversationID) {
+ throw new UserInputException('objectID');
+ }
+ if ($conversation->isClosed) {
+ throw new PermissionDeniedException();
+ }
+ $conversation->loadUserParticipation();
+ if (!$conversation->canRead() || !$conversation->canReply()) {
+ throw new PermissionDeniedException();
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function validateMessage(DatabaseObject $container, HtmlInputProcessor $htmlInputProcessor)
+ {
+ $message = $htmlInputProcessor->getTextContent();
+ if (\mb_strlen($message) > WCF::getSession()->getPermission('user.conversation.maxLength')) {
+ throw new UserInputException(
+ 'message',
+ WCF::getLanguage()->getDynamicVariable(
+ 'wcf.message.error.tooLong',
+ ['maxTextLength' => WCF::getSession()->getPermission('user.conversation.maxLength')]
+ )
+ );
+ }
+
+ // search for disallowed bbcodes
+ $disallowedBBCodes = $htmlInputProcessor->validate();
+ if (!empty($disallowedBBCodes)) {
+ throw new UserInputException(
+ 'text',
+ WCF::getLanguage()->getDynamicVariable(
+ 'wcf.message.error.disallowedBBCodes',
+ ['disallowedBBCodes' => $disallowedBBCodes]
+ )
+ );
+ }
+
+ // search for censored words
+ if (ENABLE_CENSORSHIP) {
+ $result = Censorship::getInstance()->test($message);
+ if ($result) {
+ throw new UserInputException(
+ 'message',
+ WCF::getLanguage()->getDynamicVariable(
+ 'wcf.message.error.censoredWordsFound',
+ ['censoredWords' => $result]
+ )
+ );
+ }
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getMessageList(DatabaseObject $conversation, $lastMessageTime)
+ {
+ /** @var Conversation $conversation */
+
+ $messageList = new ViewableConversationMessageList();
+ $messageList->setConversation($conversation);
+ $messageList->getConditionBuilder()
+ ->add("conversation_message.conversationID = ?", [$conversation->conversationID]);
+ $messageList->getConditionBuilder()
+ ->add("conversation_message.time > ?", [$lastMessageTime]);
+ $messageList->sqlOrderBy = "conversation_message.time " . CONVERSATION_LIST_DEFAULT_SORT_ORDER;
+ $messageList->readObjects();
+
+ return $messageList;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getPageNo(DatabaseObject $conversation)
+ {
+ /** @var Conversation $conversation */
+
+ $sql = "SELECT COUNT(*) AS count
+ FROM wcf" . WCF_N . "_conversation_message
WHERE conversationID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute([$conversation->conversationID]);
- $count = $statement->fetchArray();
-
- return [intval(ceil($count['count'] / CONVERSATION_MESSAGES_PER_PAGE)), $count['count']];
- }
-
- /**
- * @inheritDoc
- */
- public function getRedirectUrl(DatabaseObject $conversation, DatabaseObject $message) {
- /** @var ConversationMessage $message */
- return $message->getLink();
- }
-
- /**
- * @inheritDoc
- */
- public function validateSaveFullQuote() {
- $this->message = $this->getSingleObject();
-
- if (!Conversation::isParticipant([$this->message->conversationID])) {
- throw new PermissionDeniedException();
- }
- }
-
- /**
- * @inheritDoc
- */
- public function saveFullQuote() {
- $quoteID = MessageQuoteManager::getInstance()->addQuote(
- 'com.woltlab.wcf.conversation.message',
- $this->message->conversationID,
- $this->message->messageID,
- $this->message->getExcerpt(),
- $this->message->getMessage()
- );
-
- if ($quoteID === false) {
- $removeQuoteID = MessageQuoteManager::getInstance()->getQuoteID(
- 'com.woltlab.wcf.conversation.message',
- $this->message->messageID,
- $this->message->getExcerpt(),
- $this->message->getMessage()
- );
- MessageQuoteManager::getInstance()->removeQuote($removeQuoteID);
- }
-
- $returnValues = [
- 'count' => MessageQuoteManager::getInstance()->countQuotes(),
- 'fullQuoteMessageIDs' => MessageQuoteManager::getInstance()->getFullQuoteObjectIDs(['com.woltlab.wcf.conversation.message'])
- ];
-
- if ($quoteID) {
- $returnValues['renderedQuote'] = MessageQuoteManager::getInstance()->getQuoteComponents($quoteID);
- }
-
- return $returnValues;
- }
-
- /**
- * @inheritDoc
- */
- public function validateSaveQuote() {
- $this->readString('message');
- $this->readBoolean('renderQuote', true);
- $this->message = $this->getSingleObject();
-
- if (!Conversation::isParticipant([$this->message->conversationID])) {
- throw new PermissionDeniedException();
- }
- }
-
- /**
- * @inheritDoc
- */
- public function saveQuote() {
- $quoteID = MessageQuoteManager::getInstance()->addQuote(
- 'com.woltlab.wcf.conversation.message',
- $this->message->conversationID,
- $this->message->messageID,
- $this->parameters['message'],
- false
- );
-
- $returnValues = [
- 'count' => MessageQuoteManager::getInstance()->countQuotes(),
- 'fullQuoteMessageIDs' => MessageQuoteManager::getInstance()->getFullQuoteObjectIDs(['com.woltlab.wcf.conversation.message'])
- ];
-
- if ($this->parameters['renderQuote']) {
- $returnValues['renderedQuote'] = MessageQuoteManager::getInstance()->getQuoteComponents($quoteID);
- }
-
- return $returnValues;
- }
-
- /**
- * @inheritDoc
- */
- public function validateGetRenderedQuotes() {
- $this->readInteger('parentObjectID');
-
- $this->conversation = new Conversation($this->parameters['parentObjectID']);
- if (!$this->conversation->conversationID) {
- throw new UserInputException('parentObjectID');
- }
- }
-
- /**
- * @inheritDoc
- */
- public function getRenderedQuotes() {
- $quotes = MessageQuoteManager::getInstance()->getQuotesByParentObjectID('com.woltlab.wcf.conversation.message', $this->conversation->conversationID);
-
- return [
- 'template' => implode("\n\n", $quotes)
- ];
- }
-
- /**
- * @inheritDoc
- */
- public function getAttachmentHandler(DatabaseObject $conversation) {
- return new AttachmentHandler('com.woltlab.wcf.conversation.message', 0, $this->parameters['tmpHash']);
- }
-
- /**
- * @inheritDoc
- */
- public function getHtmlInputProcessor($message = null, $objectID = 0) {
- if ($message === null) {
- return $this->htmlInputProcessor;
- }
-
- $this->htmlInputProcessor = new HtmlInputProcessor();
- $this->htmlInputProcessor->process($message, 'com.woltlab.wcf.conversation.message', $objectID);
-
- return $this->htmlInputProcessor;
- }
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([$conversation->conversationID]);
+ $count = $statement->fetchArray();
+
+ return [\intval(\ceil($count['count'] / CONVERSATION_MESSAGES_PER_PAGE)), $count['count']];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getRedirectUrl(DatabaseObject $conversation, DatabaseObject $message)
+ {
+ /** @var ConversationMessage $message */
+ return $message->getLink();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function validateSaveFullQuote()
+ {
+ $this->message = $this->getSingleObject();
+
+ if (!Conversation::isParticipant([$this->message->conversationID])) {
+ throw new PermissionDeniedException();
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function saveFullQuote()
+ {
+ $quoteID = MessageQuoteManager::getInstance()->addQuote(
+ 'com.woltlab.wcf.conversation.message',
+ $this->message->conversationID,
+ $this->message->messageID,
+ $this->message->getExcerpt(),
+ $this->message->getMessage()
+ );
+
+ if ($quoteID === false) {
+ $removeQuoteID = MessageQuoteManager::getInstance()->getQuoteID(
+ 'com.woltlab.wcf.conversation.message',
+ $this->message->messageID,
+ $this->message->getExcerpt(),
+ $this->message->getMessage()
+ );
+ MessageQuoteManager::getInstance()->removeQuote($removeQuoteID);
+ }
+
+ $returnValues = [
+ 'count' => MessageQuoteManager::getInstance()->countQuotes(),
+ 'fullQuoteMessageIDs' => MessageQuoteManager::getInstance()->getFullQuoteObjectIDs(
+ ['com.woltlab.wcf.conversation.message']
+ ),
+ ];
+
+ if ($quoteID) {
+ $returnValues['renderedQuote'] = MessageQuoteManager::getInstance()->getQuoteComponents($quoteID);
+ }
+
+ return $returnValues;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function validateSaveQuote()
+ {
+ $this->readString('message');
+ $this->readBoolean('renderQuote', true);
+ $this->message = $this->getSingleObject();
+
+ if (!Conversation::isParticipant([$this->message->conversationID])) {
+ throw new PermissionDeniedException();
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function saveQuote()
+ {
+ $quoteID = MessageQuoteManager::getInstance()->addQuote(
+ 'com.woltlab.wcf.conversation.message',
+ $this->message->conversationID,
+ $this->message->messageID,
+ $this->parameters['message'],
+ false
+ );
+
+ $returnValues = [
+ 'count' => MessageQuoteManager::getInstance()->countQuotes(),
+ 'fullQuoteMessageIDs' => MessageQuoteManager::getInstance()->getFullQuoteObjectIDs(
+ ['com.woltlab.wcf.conversation.message']
+ ),
+ ];
+
+ if ($this->parameters['renderQuote']) {
+ $returnValues['renderedQuote'] = MessageQuoteManager::getInstance()->getQuoteComponents($quoteID);
+ }
+
+ return $returnValues;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function validateGetRenderedQuotes()
+ {
+ $this->readInteger('parentObjectID');
+
+ $this->conversation = new Conversation($this->parameters['parentObjectID']);
+ if (!$this->conversation->conversationID) {
+ throw new UserInputException('parentObjectID');
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getRenderedQuotes()
+ {
+ $quotes = MessageQuoteManager::getInstance()
+ ->getQuotesByParentObjectID('com.woltlab.wcf.conversation.message', $this->conversation->conversationID);
+
+ return [
+ 'template' => \implode("\n\n", $quotes),
+ ];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getAttachmentHandler(DatabaseObject $conversation)
+ {
+ return new AttachmentHandler('com.woltlab.wcf.conversation.message', 0, $this->parameters['tmpHash']);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getHtmlInputProcessor($message = null, $objectID = 0)
+ {
+ if ($message === null) {
+ return $this->htmlInputProcessor;
+ }
+
+ $this->htmlInputProcessor = new HtmlInputProcessor();
+ $this->htmlInputProcessor->process($message, 'com.woltlab.wcf.conversation.message', $objectID);
+
+ return $this->htmlInputProcessor;
+ }
}
<?php
+
namespace wcf\data\conversation\message;
+
use wcf\data\DatabaseObjectEditor;
/**
* Extends the message object with functions to create, update and delete messages.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
- *
- * @method static ConversationMessage create(array $parameters = [])
- * @method ConversationMessage getDecoratedObject()
- * @mixin ConversationMessage
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation\Message
+ *
+ * @method static ConversationMessage create(array $parameters = [])
+ * @method ConversationMessage getDecoratedObject()
+ * @mixin ConversationMessage
*/
-class ConversationMessageEditor extends DatabaseObjectEditor {
- /**
- * @inheritDoc
- */
- protected static $baseClass = ConversationMessage::class;
+class ConversationMessageEditor extends DatabaseObjectEditor
+{
+ /**
+ * @inheritDoc
+ */
+ protected static $baseClass = ConversationMessage::class;
}
<?php
+
namespace wcf\data\conversation\message;
+
use wcf\data\DatabaseObjectList;
/**
* Represents a list of conversation messages.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
*
- * @method ConversationMessage current()
- * @method ConversationMessage[] getObjects()
- * @method ConversationMessage|null search($objectID)
- * @property ConversationMessage[] $objects
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation\Message
+ *
+ * @method ConversationMessage current()
+ * @method ConversationMessage[] getObjects()
+ * @method ConversationMessage|null search($objectID)
+ * @property ConversationMessage[] $objects
*/
-class ConversationMessageList extends DatabaseObjectList {
- /**
- * @inheritDoc
- */
- public $className = ConversationMessage::class;
+class ConversationMessageList extends DatabaseObjectList
+{
+ /**
+ * @inheritDoc
+ */
+ public $className = ConversationMessage::class;
}
<?php
+
namespace wcf\data\conversation\message;
+
use wcf\data\conversation\Conversation;
use wcf\data\search\ISearchResultObject;
use wcf\system\request\LinkHandler;
/**
* Represents a list of search result.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
- *
- * @property-read string|null $subject
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation\Message
+ *
+ * @property-read string|null $subject
*/
-class SearchResultConversationMessage extends ViewableConversationMessage implements ISearchResultObject {
- /**
- * conversation object
- * @var Conversation
- */
- public $conversation;
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * Returns the conversation object.
- *
- * @return Conversation
- */
- public function getConversation() {
- if ($this->conversation === null) {
- $this->conversation = new Conversation(null, [
- 'conversationID' => $this->conversationID,
- 'subject' => $this->subject
- ]);
- }
-
- return $this->conversation;
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function getFormattedMessage() {
- return SearchResultTextParser::getInstance()->parse($this->getDecoratedObject()->getSimplifiedFormattedMessage());
- }
-
- /**
- * @inheritDoc
- */
- public function getSubject() {
- return $this->subject;
- }
-
- /**
- * @inheritDoc
- */
- public function getLink($query = '') {
- if ($query) {
- return LinkHandler::getInstance()->getLink('Conversation', [
- 'object' => $this->getConversation(),
- 'messageID' => $this->messageID,
- 'highlight' => urlencode($query)
- ], '#message'.$this->messageID);
- }
-
- return $this->getDecoratedObject()->getLink();
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function getTime() {
- return $this->time;
- }
-
- /**
- * @inheritDoc
- */
- public function getObjectTypeName() {
- return 'com.woltlab.wcf.conversation.message';
- }
-
- /**
- * @inheritDoc
- */
- public function getContainerTitle() {
- return '';
- }
-
- /**
- * @inheritDoc
- */
- public function getContainerLink() {
- return '';
- }
+class SearchResultConversationMessage extends ViewableConversationMessage implements ISearchResultObject
+{
+ /**
+ * conversation object
+ * @var Conversation
+ */
+ public $conversation;
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * Returns the conversation object.
+ *
+ * @return Conversation
+ */
+ public function getConversation()
+ {
+ if ($this->conversation === null) {
+ $this->conversation = new Conversation(null, [
+ 'conversationID' => $this->conversationID,
+ 'subject' => $this->subject,
+ ]);
+ }
+
+ return $this->conversation;
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function getFormattedMessage()
+ {
+ return SearchResultTextParser::getInstance()->parse(
+ $this->getDecoratedObject()->getSimplifiedFormattedMessage()
+ );
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getSubject()
+ {
+ return $this->subject;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getLink($query = '')
+ {
+ if ($query) {
+ return LinkHandler::getInstance()->getLink('Conversation', [
+ 'object' => $this->getConversation(),
+ 'messageID' => $this->messageID,
+ 'highlight' => \urlencode($query),
+ ], '#message' . $this->messageID);
+ }
+
+ return $this->getDecoratedObject()->getLink();
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function getTime()
+ {
+ return $this->time;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getObjectTypeName()
+ {
+ return 'com.woltlab.wcf.conversation.message';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getContainerTitle()
+ {
+ return '';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getContainerLink()
+ {
+ return '';
+ }
}
<?php
+
namespace wcf\data\conversation\message;
/**
* Represents a list of search results.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
*
- * @method SearchResultConversationMessage current()
- * @method SearchResultConversationMessage[] getObjects()
- * @method SearchResultConversationMessage|null search($objectID)
- * @property SearchResultConversationMessage[] $objects
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation\Message
+ *
+ * @method SearchResultConversationMessage current()
+ * @method SearchResultConversationMessage[] getObjects()
+ * @method SearchResultConversationMessage|null search($objectID)
+ * @property SearchResultConversationMessage[] $objects
*/
-class SearchResultConversationMessageList extends SimplifiedViewableConversationMessageList {
- /**
- * @inheritDoc
- */
- public $decoratorClassName = SearchResultConversationMessage::class;
-
- /**
- * Creates a new SearchResultConversationMessageList object.
- */
- public function __construct() {
- parent::__construct();
-
- if (!empty($this->sqlSelects)) $this->sqlSelects .= ',';
- $this->sqlSelects .= 'conversation.subject';
- $this->sqlJoins .= " LEFT JOIN wcf".WCF_N."_conversation conversation ON (conversation.conversationID = conversation_message.conversationID)";
- }
+class SearchResultConversationMessageList extends SimplifiedViewableConversationMessageList
+{
+ /**
+ * @inheritDoc
+ */
+ public $decoratorClassName = SearchResultConversationMessage::class;
+
+ /**
+ * Creates a new SearchResultConversationMessageList object.
+ */
+ public function __construct()
+ {
+ parent::__construct();
+
+ if (!empty($this->sqlSelects)) {
+ $this->sqlSelects .= ',';
+ }
+ $this->sqlSelects .= 'conversation.subject';
+ $this->sqlJoins .= " LEFT JOIN wcf" . WCF_N . "_conversation conversation ON (conversation.conversationID = conversation_message.conversationID)";
+ }
}
<?php
+
namespace wcf\data\conversation\message;
/**
* Represents a simplified version of ViewableConversationMessageList.
* Disables the loading of attachments and embedded objects by default.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation\Message
*/
-class SimplifiedViewableConversationMessageList extends ViewableConversationMessageList {
- /**
- * @inheritDoc
- */
- protected $attachmentLoading = false;
-
- /**
- * @inheritDoc
- */
- protected $embeddedObjectLoading = false;
+class SimplifiedViewableConversationMessageList extends ViewableConversationMessageList
+{
+ /**
+ * @inheritDoc
+ */
+ protected $attachmentLoading = false;
+
+ /**
+ * @inheritDoc
+ */
+ protected $embeddedObjectLoading = false;
}
<?php
+
namespace wcf\data\conversation\message;
-use wcf\data\user\UserProfile;
+
use wcf\data\DatabaseObjectDecorator;
use wcf\data\TLegacyUserPropertyAccess;
+use wcf\data\user\UserProfile;
use wcf\system\cache\runtime\UserProfileRuntimeCache;
/**
* Represents a viewable conversation message.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
- *
- * @method ConversationMessage getDecoratedObject()
- * @mixin ConversationMessage
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation\Message
+ *
+ * @method ConversationMessage getDecoratedObject()
+ * @mixin ConversationMessage
*/
-class ViewableConversationMessage extends DatabaseObjectDecorator {
- use TLegacyUserPropertyAccess;
-
- /**
- * @inheritDoc
- */
- protected static $baseClass = ConversationMessage::class;
-
- /**
- * user profile object
- * @var UserProfile
- */
- protected $userProfile;
-
- /**
- * Returns the user profile object.
- *
- * @return UserProfile
- */
- public function getUserProfile() {
- if ($this->userProfile === null) {
- if ($this->userID) {
- $this->userProfile = UserProfileRuntimeCache::getInstance()->getObject($this->userID);
- }
- else {
- $this->userProfile = UserProfile::getGuestUserProfile($this->username);
- }
- }
-
- return $this->userProfile;
- }
-
- /**
- * Returns the viewable conversation message with the given id.
- *
- * @param integer $messageID
- * @return ViewableConversationMessage
- */
- public static function getViewableConversationMessage($messageID) {
- $messageList = new ViewableConversationMessageList();
- $messageList->setObjectIDs([$messageID]);
- $messageList->readObjects();
-
- return $messageList->search($messageID);
- }
+class ViewableConversationMessage extends DatabaseObjectDecorator
+{
+ use TLegacyUserPropertyAccess;
+
+ /**
+ * @inheritDoc
+ */
+ protected static $baseClass = ConversationMessage::class;
+
+ /**
+ * user profile object
+ * @var UserProfile
+ */
+ protected $userProfile;
+
+ /**
+ * Returns the user profile object.
+ *
+ * @return UserProfile
+ */
+ public function getUserProfile()
+ {
+ if ($this->userProfile === null) {
+ if ($this->userID) {
+ $this->userProfile = UserProfileRuntimeCache::getInstance()->getObject($this->userID);
+ } else {
+ $this->userProfile = UserProfile::getGuestUserProfile($this->username);
+ }
+ }
+
+ return $this->userProfile;
+ }
+
+ /**
+ * Returns the viewable conversation message with the given id.
+ *
+ * @param integer $messageID
+ * @return ViewableConversationMessage
+ */
+ public static function getViewableConversationMessage($messageID)
+ {
+ $messageList = new ViewableConversationMessageList();
+ $messageList->setObjectIDs([$messageID]);
+ $messageList->readObjects();
+
+ return $messageList->search($messageID);
+ }
}
<?php
+
namespace wcf\data\conversation\message;
+
use wcf\data\attachment\GroupedAttachmentList;
use wcf\data\conversation\Conversation;
use wcf\data\object\type\ObjectTypeCache;
/**
* Represents a list of viewable conversation messages.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Conversation\Message
*
- * @method ViewableConversationMessage current()
- * @method ViewableConversationMessage[] getObjects()
- * @method ViewableConversationMessage|null search($objectID)
- * @property ViewableConversationMessage[] $objects
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Conversation\Message
+ *
+ * @method ViewableConversationMessage current()
+ * @method ViewableConversationMessage[] getObjects()
+ * @method ViewableConversationMessage|null search($objectID)
+ * @property ViewableConversationMessage[] $objects
*/
-class ViewableConversationMessageList extends ConversationMessageList {
- /**
- * @inheritDoc
- */
- public $sqlOrderBy = 'conversation_message.time';
-
- /**
- * @inheritDoc
- */
- public $decoratorClassName = ViewableConversationMessage::class;
-
- /**
- * attachment object ids
- * @var integer[]
- */
- public $attachmentObjectIDs = [];
-
- /**
- * ids of the messages with embedded objects
- * @var integer[]
- */
- public $embeddedObjectMessageIDs = [];
-
- /**
- * attachment list
- * @var GroupedAttachmentList
- */
- protected $attachmentList;
-
- /**
- * max post time
- * @var integer
- */
- protected $maxPostTime = 0;
-
- /**
- * enables/disables the loading of attachments
- * @var boolean
- */
- protected $attachmentLoading = true;
-
- /**
- * enables/disables the loading of embedded objects
- * @var boolean
- */
- protected $embeddedObjectLoading = true;
-
- /**
- * conversation object
- * @var Conversation
- */
- protected $conversation;
-
- /**
- * @inheritDoc
- */
- public function readObjects() {
- if ($this->objectIDs === null) {
- $this->readObjectIDs();
- }
-
- parent::readObjects();
-
- $userIDs = [];
- foreach ($this->objects as $message) {
- if ($message->time > $this->maxPostTime) {
- $this->maxPostTime = $message->time;
- }
- if ($this->conversation !== null) {
- $message->setConversation($this->conversation);
- }
-
- if ($message->attachments) {
- $this->attachmentObjectIDs[] = $message->messageID;
- }
-
- if ($message->hasEmbeddedObjects) {
- $this->embeddedObjectMessageIDs[] = $message->messageID;
- }
- if ($message->userID) {
- $userIDs[] = $message->userID;
- }
- }
-
- if (!empty($userIDs)) {
- UserProfileRuntimeCache::getInstance()->cacheObjectIDs($userIDs);
- }
-
- if ($this->embeddedObjectLoading) {
- $this->readEmbeddedObjects();
- }
- if ($this->attachmentLoading) {
- $this->readAttachments();
- }
- }
-
- /**
- * Reads the embedded objects of the messages in the list.
- */
- public function readEmbeddedObjects() {
- if (!empty($this->embeddedObjectMessageIDs)) {
- // add message objects to attachment object cache to save SQL queries
- ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.attachment.objectType', 'com.woltlab.wcf.conversation.message')->getProcessor()->setCachedObjects($this->objects);
-
- // load embedded objects
- MessageEmbeddedObjectManager::getInstance()->loadObjects('com.woltlab.wcf.conversation.message', $this->embeddedObjectMessageIDs);
- }
- }
-
- /**
- * Reads the list of attachments.
- */
- public function readAttachments() {
- if (!empty($this->attachmentObjectIDs)) {
- $this->attachmentList = new GroupedAttachmentList('com.woltlab.wcf.conversation.message');
- $this->attachmentList->getConditionBuilder()->add('attachment.objectID IN (?)', [$this->attachmentObjectIDs]);
- $this->attachmentList->readObjects();
- }
- }
-
- /**
- * Returns the max post time.
- *
- * @return integer
- */
- public function getMaxPostTime() {
- return $this->maxPostTime;
- }
-
- /**
- * Returns the list of attachments.
- *
- * @return GroupedAttachmentList
- */
- public function getAttachmentList() {
- return $this->attachmentList;
- }
-
- /**
- * Enables/disables the loading of attachments.
- *
- * @param boolean $enable
- */
- public function enableAttachmentLoading($enable = true) {
- $this->attachmentLoading = $enable;
- }
-
- /**
- * Enables/disables the loading of embedded objects.
- *
- * @param boolean $enable
- */
- public function enableEmbeddedObjectLoading($enable = true) {
- $this->embeddedObjectLoading = $enable;
- }
-
- /**
- * Sets active conversation.
- *
- * @param Conversation $conversation
- */
- public function setConversation(Conversation $conversation) {
- $this->conversation = $conversation;
- }
+class ViewableConversationMessageList extends ConversationMessageList
+{
+ /**
+ * @inheritDoc
+ */
+ public $sqlOrderBy = 'conversation_message.time';
+
+ /**
+ * @inheritDoc
+ */
+ public $decoratorClassName = ViewableConversationMessage::class;
+
+ /**
+ * attachment object ids
+ * @var integer[]
+ */
+ public $attachmentObjectIDs = [];
+
+ /**
+ * ids of the messages with embedded objects
+ * @var integer[]
+ */
+ public $embeddedObjectMessageIDs = [];
+
+ /**
+ * attachment list
+ * @var GroupedAttachmentList
+ */
+ protected $attachmentList;
+
+ /**
+ * max post time
+ * @var integer
+ */
+ protected $maxPostTime = 0;
+
+ /**
+ * enables/disables the loading of attachments
+ * @var boolean
+ */
+ protected $attachmentLoading = true;
+
+ /**
+ * enables/disables the loading of embedded objects
+ * @var boolean
+ */
+ protected $embeddedObjectLoading = true;
+
+ /**
+ * conversation object
+ * @var Conversation
+ */
+ protected $conversation;
+
+ /**
+ * @inheritDoc
+ */
+ public function readObjects()
+ {
+ if ($this->objectIDs === null) {
+ $this->readObjectIDs();
+ }
+
+ parent::readObjects();
+
+ $userIDs = [];
+ foreach ($this->objects as $message) {
+ if ($message->time > $this->maxPostTime) {
+ $this->maxPostTime = $message->time;
+ }
+ if ($this->conversation !== null) {
+ $message->setConversation($this->conversation);
+ }
+
+ if ($message->attachments) {
+ $this->attachmentObjectIDs[] = $message->messageID;
+ }
+
+ if ($message->hasEmbeddedObjects) {
+ $this->embeddedObjectMessageIDs[] = $message->messageID;
+ }
+ if ($message->userID) {
+ $userIDs[] = $message->userID;
+ }
+ }
+
+ if (!empty($userIDs)) {
+ UserProfileRuntimeCache::getInstance()->cacheObjectIDs($userIDs);
+ }
+
+ if ($this->embeddedObjectLoading) {
+ $this->readEmbeddedObjects();
+ }
+ if ($this->attachmentLoading) {
+ $this->readAttachments();
+ }
+ }
+
+ /**
+ * Reads the embedded objects of the messages in the list.
+ */
+ public function readEmbeddedObjects()
+ {
+ if (!empty($this->embeddedObjectMessageIDs)) {
+ // add message objects to attachment object cache to save SQL queries
+ ObjectTypeCache::getInstance()
+ ->getObjectTypeByName('com.woltlab.wcf.attachment.objectType', 'com.woltlab.wcf.conversation.message')
+ ->getProcessor()
+ ->setCachedObjects($this->objects);
+
+ // load embedded objects
+ MessageEmbeddedObjectManager::getInstance()
+ ->loadObjects('com.woltlab.wcf.conversation.message', $this->embeddedObjectMessageIDs);
+ }
+ }
+
+ /**
+ * Reads the list of attachments.
+ */
+ public function readAttachments()
+ {
+ if (!empty($this->attachmentObjectIDs)) {
+ $this->attachmentList = new GroupedAttachmentList('com.woltlab.wcf.conversation.message');
+ $this->attachmentList->getConditionBuilder()
+ ->add('attachment.objectID IN (?)', [$this->attachmentObjectIDs]);
+ $this->attachmentList->readObjects();
+ }
+ }
+
+ /**
+ * Returns the max post time.
+ *
+ * @return integer
+ */
+ public function getMaxPostTime()
+ {
+ return $this->maxPostTime;
+ }
+
+ /**
+ * Returns the list of attachments.
+ *
+ * @return GroupedAttachmentList
+ */
+ public function getAttachmentList()
+ {
+ return $this->attachmentList;
+ }
+
+ /**
+ * Enables/disables the loading of attachments.
+ *
+ * @param boolean $enable
+ */
+ public function enableAttachmentLoading($enable = true)
+ {
+ $this->attachmentLoading = $enable;
+ }
+
+ /**
+ * Enables/disables the loading of embedded objects.
+ *
+ * @param boolean $enable
+ */
+ public function enableEmbeddedObjectLoading($enable = true)
+ {
+ $this->embeddedObjectLoading = $enable;
+ }
+
+ /**
+ * Sets active conversation.
+ *
+ * @param Conversation $conversation
+ */
+ public function setConversation(Conversation $conversation)
+ {
+ $this->conversation = $conversation;
+ }
}
<?php
+
namespace wcf\data\modification\log;
+
use wcf\system\cache\runtime\UserProfileRuntimeCache;
use wcf\system\log\modification\ConversationModificationLogHandler;
use wcf\system\WCF;
/**
* Represents a list of modification logs for conversation log page.
- *
- * @author Alexander Ebert
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Modification\Log
*
- * @method ViewableConversationModificationLog current()
- * @method ViewableConversationModificationLog[] getObjects()
- * @method ViewableConversationModificationLog|null search($objectID)
- * @property ViewableConversationModificationLog[] $objects
+ * @author Alexander Ebert
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Modification\Log
+ *
+ * @method ViewableConversationModificationLog current()
+ * @method ViewableConversationModificationLog[] getObjects()
+ * @method ViewableConversationModificationLog|null search($objectID)
+ * @property ViewableConversationModificationLog[] $objects
*/
-class ConversationLogModificationLogList extends ModificationLogList {
- /**
- * @inheritDoc
- */
- public function __construct($conversationID) {
- parent::__construct();
-
- // set conditions
- $this->getConditionBuilder()->add('modification_log.objectTypeID = ?', [ConversationModificationLogHandler::getInstance()->getObjectType('com.woltlab.wcf.conversation.conversation')->objectTypeID]);
- $this->getConditionBuilder()->add('modification_log.objectID = ?', [$conversationID]);
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function readObjects() {
- $sql = "SELECT modification_log.*
- FROM wcf".WCF_N."_modification_log modification_log
- ".$this->getConditionBuilder()."
- ".(!empty($this->sqlOrderBy) ? "ORDER BY ".$this->sqlOrderBy : '');
- $statement = WCF::getDB()->prepareStatement($sql, $this->sqlLimit, $this->sqlOffset);
- $statement->execute($this->getConditionBuilder()->getParameters());
- $this->objects = $statement->fetchObjects(($this->objectClassName ?: $this->className));
-
- // use table index as array index
- $objects = $userIDs = [];
- foreach ($this->objects as $object) {
- $objectID = $object->{$this->getDatabaseTableIndexName()};
- $objects[$objectID] = $object;
-
- $this->indexToObject[] = $objectID;
-
- if ($object->userID) {
- $userIDs[] = $object->userID;
- }
- }
- $this->objectIDs = $this->indexToObject;
- $this->objects = $objects;
-
- if (!empty($userIDs)) {
- UserProfileRuntimeCache::getInstance()->cacheObjectIDs($userIDs);
- }
-
- foreach ($this->objects as &$object) {
- $object = new ViewableConversationModificationLog($object);
- }
- unset($object);
- }
-
- /**
- * Returns all log entries created before given point of time. Applicable entries
- * will be returned and removed from collection.
- *
- * @param integer $time
- * @return ViewableConversationModificationLog[]
- */
- public function getEntriesUntil($time) {
- $entries = [];
- foreach ($this->objects as $index => $entry) {
- if ($entry->time < $time) {
- $entries[] = $entry;
- unset($this->objects[$index]);
- }
- }
-
- if (!empty($entries)) {
- $this->indexToObject = array_keys($this->objects);
- }
-
- return $entries;
- }
+class ConversationLogModificationLogList extends ModificationLogList
+{
+ /**
+ * @inheritDoc
+ */
+ public function __construct($conversationID)
+ {
+ parent::__construct();
+
+ // set conditions
+ $this->getConditionBuilder()->add(
+ 'modification_log.objectTypeID = ?',
+ [ConversationModificationLogHandler::getInstance()->getObjectType('com.woltlab.wcf.conversation.conversation')->objectTypeID]
+ );
+ $this->getConditionBuilder()->add(
+ 'modification_log.objectID = ?',
+ [$conversationID]
+ );
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function readObjects()
+ {
+ $sql = "SELECT modification_log.*
+ FROM wcf" . WCF_N . "_modification_log modification_log
+ " . $this->getConditionBuilder() . "
+ " . (!empty($this->sqlOrderBy) ? "ORDER BY " . $this->sqlOrderBy : '');
+ $statement = WCF::getDB()->prepareStatement($sql, $this->sqlLimit, $this->sqlOffset);
+ $statement->execute($this->getConditionBuilder()->getParameters());
+ $this->objects = $statement->fetchObjects(($this->objectClassName ?: $this->className));
+
+ // use table index as array index
+ $objects = $userIDs = [];
+ foreach ($this->objects as $object) {
+ $objectID = $object->{$this->getDatabaseTableIndexName()};
+ $objects[$objectID] = $object;
+
+ $this->indexToObject[] = $objectID;
+
+ if ($object->userID) {
+ $userIDs[] = $object->userID;
+ }
+ }
+ $this->objectIDs = $this->indexToObject;
+ $this->objects = $objects;
+
+ if (!empty($userIDs)) {
+ UserProfileRuntimeCache::getInstance()->cacheObjectIDs($userIDs);
+ }
+
+ foreach ($this->objects as &$object) {
+ $object = new ViewableConversationModificationLog($object);
+ }
+ unset($object);
+ }
+
+ /**
+ * Returns all log entries created before given point of time. Applicable entries
+ * will be returned and removed from collection.
+ *
+ * @param integer $time
+ * @return ViewableConversationModificationLog[]
+ */
+ public function getEntriesUntil($time)
+ {
+ $entries = [];
+ foreach ($this->objects as $index => $entry) {
+ if ($entry->time < $time) {
+ $entries[] = $entry;
+ unset($this->objects[$index]);
+ }
+ }
+
+ if (!empty($entries)) {
+ $this->indexToObject = \array_keys($this->objects);
+ }
+
+ return $entries;
+ }
}
<?php
+
namespace wcf\data\modification\log;
-use wcf\data\user\UserProfile;
+
use wcf\data\DatabaseObjectDecorator;
use wcf\data\TLegacyUserPropertyAccess;
+use wcf\data\user\UserProfile;
use wcf\system\cache\runtime\UserProfileRuntimeCache;
use wcf\system\WCF;
/**
* Provides a viewable conversation modification log.
- *
- * @author Alexander Ebert
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Data\Modification\Log
*
- * @method ModificationLog getDecoratedObject()
- * @mixin ModificationLog
+ * @author Alexander Ebert
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Modification\Log
+ *
+ * @method ModificationLog getDecoratedObject()
+ * @mixin ModificationLog
*/
-class ViewableConversationModificationLog extends DatabaseObjectDecorator {
- use TLegacyUserPropertyAccess;
-
- /**
- * @inheritDoc
- */
- protected static $baseClass = ModificationLog::class;
-
- /**
- * user profile object
- * @var UserProfile
- */
- protected $userProfile;
-
- /**
- * Returns readable representation of current log entry.
- *
- * @return string
- */
- public function __toString() {
- return WCF::getLanguage()->getDynamicVariable('wcf.conversation.log.conversation.'.$this->action, ['additionalData' => $this->additionalData]);
- }
-
- /**
- * Returns the profile object of the user who created the modification entry.
- *
- * @return UserProfile
- */
- public function getUserProfile() {
- if ($this->userProfile === null) {
- if ($this->userID) {
- $this->userProfile = UserProfileRuntimeCache::getInstance()->getObject($this->userID);
- }
- else {
- $this->userProfile = UserProfile::getGuestUserProfile($this->username);
- }
- }
-
- return $this->userProfile;
- }
+class ViewableConversationModificationLog extends DatabaseObjectDecorator
+{
+ use TLegacyUserPropertyAccess;
+
+ /**
+ * @inheritDoc
+ */
+ protected static $baseClass = ModificationLog::class;
+
+ /**
+ * user profile object
+ * @var UserProfile
+ */
+ protected $userProfile;
+
+ /**
+ * Returns readable representation of current log entry.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return WCF::getLanguage()->getDynamicVariable(
+ 'wcf.conversation.log.conversation.' . $this->action,
+ ['additionalData' => $this->additionalData]
+ );
+ }
+
+ /**
+ * Returns the profile object of the user who created the modification entry.
+ *
+ * @return UserProfile
+ */
+ public function getUserProfile()
+ {
+ if ($this->userProfile === null) {
+ if ($this->userID) {
+ $this->userProfile = UserProfileRuntimeCache::getInstance()->getObject($this->userID);
+ } else {
+ $this->userProfile = UserProfile::getGuestUserProfile($this->username);
+ }
+ }
+
+ return $this->userProfile;
+ }
}
<?php
+
namespace wcf\form;
+
use wcf\data\conversation\Conversation;
use wcf\data\conversation\ConversationAction;
use wcf\data\user\group\UserGroup;
/**
* Shows the conversation form.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Form
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Form
*/
-class ConversationAddForm extends MessageForm {
- /**
- * @inheritDoc
- */
- public $attachmentObjectType = 'com.woltlab.wcf.conversation.message';
-
- /**
- * @inheritDoc
- */
- public $loginRequired = true;
-
- /**
- * @inheritDoc
- */
- public $messageObjectType = 'com.woltlab.wcf.conversation.message';
-
- /**
- * @inheritDoc
- */
- public $neededModules = ['MODULE_CONVERSATION'];
-
- /**
- * @inheritDoc
- */
- public $neededPermissions = ['user.conversation.canUseConversation'];
-
- /**
- * participants (comma separated user names)
- * @var string
- */
- public $participants = '';
-
- /**
- * invisible participants (comma separated user names)
- * @var string
- */
- public $invisibleParticipants = '';
-
- /**
- * user group participants (comma separated ids)
- * @var string
- */
- public $participantsGroupIDs = '';
-
- /**
- * invisible user group participants (comma separated ids)
- * @var string
- */
- public $invisibleParticipantsGroupIDs = '';
-
- /**
- * draft status
- * @var integer
- */
- public $draft = 0;
-
- /**
- * true, if participants can add new participants
- * @var integer
- */
- public $participantCanInvite = 0;
-
- /**
- * participants (user ids)
- * @var integer[]
- */
- public $participantIDs = [];
-
- /**
- * invisible participants (user ids)
- * @var integer[]
- */
- public $invisibleParticipantIDs = [];
-
- /**
- * @inheritDoc
- */
- public function readParameters() {
- parent::readParameters();
-
- if (!WCF::getUser()->userID) return;
-
- // check max pc permission
- if (ConversationHandler::getInstance()->getConversationCount() >= WCF::getSession()->getPermission('user.conversation.maxConversations')) {
- throw new NamedUserException(WCF::getLanguage()->getDynamicVariable('wcf.conversation.error.mailboxIsFull'));
- }
-
- ConversationHandler::getInstance()->enforceFloodControl();
-
- if (isset($_REQUEST['userID'])) {
- $userID = intval($_REQUEST['userID']);
- $user = UserProfileRuntimeCache::getInstance()->getObject($userID);
- if ($user === null || $user->userID == WCF::getUser()->userID) {
- throw new IllegalLinkException();
- }
-
- // validate user
- try {
- Conversation::validateParticipant($user);
- }
- catch (UserInputException $e) {
- throw new NamedUserException(WCF::getLanguage()->getDynamicVariable('wcf.conversation.participants.error.'.$e->getType(), ['errorData' => ['username' => $user->username]]));
- }
-
- $this->participants = $user->username;
- }
-
- // get max text length
- $this->maxTextLength = WCF::getSession()->getPermission('user.conversation.maxLength');
-
- // quotes
- MessageQuoteManager::getInstance()->readParameters();
- }
-
- /**
- * @inheritDoc
- */
- public function readFormParameters() {
- parent::readFormParameters();
-
- if (isset($_POST['draft'])) $this->draft = (bool) $_POST['draft'];
- if (isset($_POST['participantCanInvite'])) $this->participantCanInvite = (bool) $_POST['participantCanInvite'];
- if (isset($_POST['participants'])) $this->participants = StringUtil::trim($_POST['participants']);
- if (isset($_POST['invisibleParticipants'])) $this->invisibleParticipants = StringUtil::trim($_POST['invisibleParticipants']);
- if (WCF::getSession()->getPermission('user.conversation.canAddGroupParticipants')) {
- if (isset($_POST['participantsGroupIDs'])) $this->participantsGroupIDs = StringUtil::trim($_POST['participantsGroupIDs']);
- if (isset($_POST['invisibleParticipantsGroupIDs'])) $this->invisibleParticipantsGroupIDs = StringUtil::trim($_POST['invisibleParticipantsGroupIDs']);
- }
-
- // quotes
- MessageQuoteManager::getInstance()->readFormParameters();
- }
-
- /**
- * @inheritDoc
- */
- public function validate() {
- if (empty($this->participants) && empty($this->invisibleParticipants) && empty($this->participantsGroupIDs) && empty($this->invisibleParticipantsGroupIDs) && !$this->draft) {
- throw new UserInputException('participants');
- }
-
- // check, if user is allowed to set invisible participants
- if (!WCF::getSession()->getPermission('user.conversation.canAddInvisibleParticipants') && (!empty($this->invisibleParticipants) || !empty($this->invisibleParticipantsGroupIDs))) {
- throw new UserInputException('participants', 'invisibleParticipantsNoPermission');
- }
-
- // check, if user is allowed to set participantCanInvite
- if (!WCF::getSession()->getPermission('user.conversation.canSetCanInvite') && $this->participantCanInvite) {
- throw new UserInputException('participantCanInvite', 'participantCanInviteNoPermission');
- }
-
- $this->participantIDs = Conversation::validateParticipants($this->participants);
- $this->invisibleParticipantIDs = Conversation::validateParticipants($this->invisibleParticipants, 'invisibleParticipants');
- if (!empty($this->participantsGroupIDs)) {
- $validGroupParticipants = Conversation::validateGroupParticipants($this->participantsGroupIDs);
- $validGroupParticipants = array_diff($validGroupParticipants, $this->participantIDs);
- if (empty($validGroupParticipants)) {
- throw new UserInputException('participants', 'emptyGroup');
- }
- $this->participantIDs = array_merge($this->participantIDs, $validGroupParticipants);
- }
- if (!empty($this->invisibleParticipantsGroupIDs)) {
- $validGroupParticipants = Conversation::validateGroupParticipants($this->invisibleParticipantsGroupIDs, 'invisibleParticipants');
- $validGroupParticipants = array_diff($validGroupParticipants, $this->invisibleParticipantIDs);
- if (empty($validGroupParticipants)) {
- throw new UserInputException('invisibleParticipants', 'emptyGroup');
- }
- $this->invisibleParticipantIDs = array_merge($this->invisibleParticipantIDs, $validGroupParticipants);
- }
-
- // remove duplicates
- $intersection = array_intersect($this->participantIDs, $this->invisibleParticipantIDs);
- if (!empty($intersection)) {
- $users = UserProfileRuntimeCache::getInstance()->getObjects(array_slice($intersection, 0, 10));
- throw new UserInputException('invisibleParticipants', array_map(function ($user) {
- return [
- 'type' => 'intersects',
- 'username' => $user->username,
- ];
- }, $users));
- }
-
- if (empty($this->participantIDs) && empty($this->invisibleParticipantIDs) && !$this->draft) {
- throw new UserInputException('participants');
- }
-
- // check number of participants
- if (count($this->participantIDs) + count($this->invisibleParticipantIDs) > WCF::getSession()->getPermission('user.conversation.maxParticipants')) {
- throw new UserInputException('participants', 'tooManyParticipants');
- }
-
- parent::validate();
- }
-
- /**
- * @inheritDoc
- */
- public function save() {
- parent::save();
-
- // save conversation
- $data = array_merge($this->additionalFields, [
- 'subject' => $this->subject,
- 'time' => TIME_NOW,
- 'userID' => WCF::getUser()->userID,
- 'username' => WCF::getUser()->username,
- 'isDraft' => $this->draft ? 1 : 0,
- 'participantCanInvite' => $this->participantCanInvite
- ]);
- if ($this->draft) {
- $data['draftData'] = serialize([
- 'participants' => $this->participantIDs,
- 'invisibleParticipants' => $this->invisibleParticipantIDs
- ]);
- }
-
- $conversationData = [
- 'data' => $data,
- 'attachmentHandler' => $this->attachmentHandler,
- 'htmlInputProcessor' => $this->htmlInputProcessor,
- 'messageData' => []
- ];
- if (!$this->draft) {
- $conversationData['participants'] = $this->participantIDs;
- $conversationData['invisibleParticipants'] = $this->invisibleParticipantIDs;
- }
-
- $this->objectAction = new ConversationAction([], 'create', $conversationData);
- /** @var Conversation $conversation */
- $conversation = $this->objectAction->executeAction()['returnValues'];
-
- MessageQuoteManager::getInstance()->saved();
-
- FloodControl::getInstance()->registerContent('com.woltlab.wcf.conversation');
-
- $this->saved();
-
- // forward
- HeaderUtil::redirect($conversation->getLink());
- exit;
- }
-
- /**
- * @inheritDoc
- */
- public function readData() {
- parent::readData();
-
- // add breadcrumbs
- PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.conversation.ConversationList');
- }
-
- /**
- * @inheritDoc
- */
- public function assignVariables() {
- parent::assignVariables();
-
- MessageQuoteManager::getInstance()->assignVariables();
-
- $allowedUserGroupIDs = [];
- foreach (UserGroupCacheBuilder::getInstance()->getData([], 'groups') as $group) {
- if ($group->canBeAddedAsConversationParticipant) $allowedUserGroupIDs[] = $group->groupID;
- }
-
- WCF::getTPL()->assign([
- 'participantCanInvite' => $this->participantCanInvite,
- 'participants' => $this->participants,
- 'participantsData' => $this->getParticipantsData(),
- 'invisibleParticipants' => $this->invisibleParticipants,
- 'invisibleParticipantsData' => $this->getParticipantsData(true),
- 'action' => 'add',
- 'allowedUserGroupIDs' => $allowedUserGroupIDs
- ]);
- }
-
- /**
- * @inheritDoc
- */
- public function show() {
- if (!WCF::getSession()->getPermission('user.conversation.canStartConversation')) {
- throw new PermissionDeniedException();
- }
-
- parent::show();
- }
-
- private function getParticipantsData($invisible = false) {
- $result = [];
- $participants = ArrayUtil::trim(explode(',', ($invisible ? $this->invisibleParticipants : $this->participants)));
- foreach ($participants as $username) {
- $result[] = [
- 'objectId' => 0,
- 'value' => $username,
- 'type' => 'user'
- ];
- }
-
- $participants = ArrayUtil::toIntegerArray(explode(',', ($invisible ? $this->invisibleParticipantsGroupIDs : $this->participantsGroupIDs)));
- foreach ($participants as $groupID) {
- $group = UserGroup::getGroupByID($groupID);
- if (!$group) continue;
- $result[] = [
- 'objectId' => $groupID,
- 'value' => $group->getName(),
- 'type' => 'group'
- ];
- }
-
- return $result;
- }
+class ConversationAddForm extends MessageForm
+{
+ /**
+ * @inheritDoc
+ */
+ public $attachmentObjectType = 'com.woltlab.wcf.conversation.message';
+
+ /**
+ * @inheritDoc
+ */
+ public $loginRequired = true;
+
+ /**
+ * @inheritDoc
+ */
+ public $messageObjectType = 'com.woltlab.wcf.conversation.message';
+
+ /**
+ * @inheritDoc
+ */
+ public $neededModules = ['MODULE_CONVERSATION'];
+
+ /**
+ * @inheritDoc
+ */
+ public $neededPermissions = ['user.conversation.canUseConversation'];
+
+ /**
+ * participants (comma separated user names)
+ * @var string
+ */
+ public $participants = '';
+
+ /**
+ * invisible participants (comma separated user names)
+ * @var string
+ */
+ public $invisibleParticipants = '';
+
+ /**
+ * user group participants (comma separated ids)
+ * @var string
+ */
+ public $participantsGroupIDs = '';
+
+ /**
+ * invisible user group participants (comma separated ids)
+ * @var string
+ */
+ public $invisibleParticipantsGroupIDs = '';
+
+ /**
+ * draft status
+ * @var integer
+ */
+ public $draft = 0;
+
+ /**
+ * true, if participants can add new participants
+ * @var integer
+ */
+ public $participantCanInvite = 0;
+
+ /**
+ * participants (user ids)
+ * @var integer[]
+ */
+ public $participantIDs = [];
+
+ /**
+ * invisible participants (user ids)
+ * @var integer[]
+ */
+ public $invisibleParticipantIDs = [];
+
+ /**
+ * @inheritDoc
+ */
+ public function readParameters()
+ {
+ parent::readParameters();
+
+ if (!WCF::getUser()->userID) {
+ return;
+ }
+
+ // check max pc permission
+ if (ConversationHandler::getInstance()->getConversationCount() >= WCF::getSession()->getPermission('user.conversation.maxConversations')) {
+ throw new NamedUserException(WCF::getLanguage()->getDynamicVariable(
+ 'wcf.conversation.error.mailboxIsFull'
+ ));
+ }
+
+ ConversationHandler::getInstance()->enforceFloodControl();
+
+ if (isset($_REQUEST['userID'])) {
+ $userID = \intval($_REQUEST['userID']);
+ $user = UserProfileRuntimeCache::getInstance()->getObject($userID);
+ if ($user === null || $user->userID == WCF::getUser()->userID) {
+ throw new IllegalLinkException();
+ }
+
+ // validate user
+ try {
+ Conversation::validateParticipant($user);
+ } catch (UserInputException $e) {
+ throw new NamedUserException(WCF::getLanguage()->getDynamicVariable(
+ 'wcf.conversation.participants.error.' . $e->getType(),
+ ['errorData' => ['username' => $user->username]]
+ ));
+ }
+
+ $this->participants = $user->username;
+ }
+
+ // get max text length
+ $this->maxTextLength = WCF::getSession()->getPermission('user.conversation.maxLength');
+
+ // quotes
+ MessageQuoteManager::getInstance()->readParameters();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function readFormParameters()
+ {
+ parent::readFormParameters();
+
+ if (isset($_POST['draft'])) {
+ $this->draft = (bool)$_POST['draft'];
+ }
+ if (isset($_POST['participantCanInvite'])) {
+ $this->participantCanInvite = (bool)$_POST['participantCanInvite'];
+ }
+ if (isset($_POST['participants'])) {
+ $this->participants = StringUtil::trim($_POST['participants']);
+ }
+ if (isset($_POST['invisibleParticipants'])) {
+ $this->invisibleParticipants = StringUtil::trim($_POST['invisibleParticipants']);
+ }
+ if (WCF::getSession()->getPermission('user.conversation.canAddGroupParticipants')) {
+ if (isset($_POST['participantsGroupIDs'])) {
+ $this->participantsGroupIDs = StringUtil::trim($_POST['participantsGroupIDs']);
+ }
+ if (isset($_POST['invisibleParticipantsGroupIDs'])) {
+ $this->invisibleParticipantsGroupIDs = StringUtil::trim($_POST['invisibleParticipantsGroupIDs']);
+ }
+ }
+
+ // quotes
+ MessageQuoteManager::getInstance()->readFormParameters();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function validate()
+ {
+ if (
+ empty($this->participants)
+ && empty($this->invisibleParticipants)
+ && empty($this->participantsGroupIDs)
+ && empty($this->invisibleParticipantsGroupIDs)
+ && !$this->draft
+ ) {
+ throw new UserInputException('participants');
+ }
+
+ // check, if user is allowed to set invisible participants
+ if (
+ !WCF::getSession()->getPermission('user.conversation.canAddInvisibleParticipants')
+ && (!empty($this->invisibleParticipants) || !empty($this->invisibleParticipantsGroupIDs))
+ ) {
+ throw new UserInputException('participants', 'invisibleParticipantsNoPermission');
+ }
+
+ // check, if user is allowed to set participantCanInvite
+ if (!WCF::getSession()->getPermission('user.conversation.canSetCanInvite') && $this->participantCanInvite) {
+ throw new UserInputException('participantCanInvite', 'participantCanInviteNoPermission');
+ }
+
+ $this->participantIDs = Conversation::validateParticipants($this->participants);
+ $this->invisibleParticipantIDs = Conversation::validateParticipants(
+ $this->invisibleParticipants,
+ 'invisibleParticipants'
+ );
+ if (!empty($this->participantsGroupIDs)) {
+ $validGroupParticipants = Conversation::validateGroupParticipants($this->participantsGroupIDs);
+ $validGroupParticipants = \array_diff($validGroupParticipants, $this->participantIDs);
+ if (empty($validGroupParticipants)) {
+ throw new UserInputException('participants', 'emptyGroup');
+ }
+ $this->participantIDs = \array_merge($this->participantIDs, $validGroupParticipants);
+ }
+ if (!empty($this->invisibleParticipantsGroupIDs)) {
+ $validGroupParticipants = Conversation::validateGroupParticipants(
+ $this->invisibleParticipantsGroupIDs,
+ 'invisibleParticipants'
+ );
+ $validGroupParticipants = \array_diff($validGroupParticipants, $this->invisibleParticipantIDs);
+ if (empty($validGroupParticipants)) {
+ throw new UserInputException('invisibleParticipants', 'emptyGroup');
+ }
+ $this->invisibleParticipantIDs = \array_merge($this->invisibleParticipantIDs, $validGroupParticipants);
+ }
+
+ // remove duplicates
+ $intersection = \array_intersect($this->participantIDs, $this->invisibleParticipantIDs);
+ if (!empty($intersection)) {
+ $users = UserProfileRuntimeCache::getInstance()->getObjects(\array_slice($intersection, 0, 10));
+ throw new UserInputException('invisibleParticipants', \array_map(static function ($user) {
+ return [
+ 'type' => 'intersects',
+ 'username' => $user->username,
+ ];
+ }, $users));
+ }
+
+ if (empty($this->participantIDs) && empty($this->invisibleParticipantIDs) && !$this->draft) {
+ throw new UserInputException('participants');
+ }
+
+ // check number of participants
+ if (\count($this->participantIDs) + \count($this->invisibleParticipantIDs) > WCF::getSession()->getPermission('user.conversation.maxParticipants')) {
+ throw new UserInputException('participants', 'tooManyParticipants');
+ }
+
+ parent::validate();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function save()
+ {
+ parent::save();
+
+ // save conversation
+ $data = \array_merge($this->additionalFields, [
+ 'subject' => $this->subject,
+ 'time' => TIME_NOW,
+ 'userID' => WCF::getUser()->userID,
+ 'username' => WCF::getUser()->username,
+ 'isDraft' => $this->draft ? 1 : 0,
+ 'participantCanInvite' => $this->participantCanInvite,
+ ]);
+ if ($this->draft) {
+ $data['draftData'] = \serialize([
+ 'participants' => $this->participantIDs,
+ 'invisibleParticipants' => $this->invisibleParticipantIDs,
+ ]);
+ }
+
+ $conversationData = [
+ 'data' => $data,
+ 'attachmentHandler' => $this->attachmentHandler,
+ 'htmlInputProcessor' => $this->htmlInputProcessor,
+ 'messageData' => [],
+ ];
+ if (!$this->draft) {
+ $conversationData['participants'] = $this->participantIDs;
+ $conversationData['invisibleParticipants'] = $this->invisibleParticipantIDs;
+ }
+
+ $this->objectAction = new ConversationAction([], 'create', $conversationData);
+ /** @var Conversation $conversation */
+ $conversation = $this->objectAction->executeAction()['returnValues'];
+
+ MessageQuoteManager::getInstance()->saved();
+
+ FloodControl::getInstance()->registerContent('com.woltlab.wcf.conversation');
+
+ $this->saved();
+
+ // forward
+ HeaderUtil::redirect($conversation->getLink());
+
+ exit;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function readData()
+ {
+ parent::readData();
+
+ // add breadcrumbs
+ PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.conversation.ConversationList');
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function assignVariables()
+ {
+ parent::assignVariables();
+
+ MessageQuoteManager::getInstance()->assignVariables();
+
+ $allowedUserGroupIDs = [];
+ foreach (UserGroupCacheBuilder::getInstance()->getData([], 'groups') as $group) {
+ if ($group->canBeAddedAsConversationParticipant) {
+ $allowedUserGroupIDs[] = $group->groupID;
+ }
+ }
+
+ WCF::getTPL()->assign([
+ 'participantCanInvite' => $this->participantCanInvite,
+ 'participants' => $this->participants,
+ 'participantsData' => $this->getParticipantsData(),
+ 'invisibleParticipants' => $this->invisibleParticipants,
+ 'invisibleParticipantsData' => $this->getParticipantsData(true),
+ 'action' => 'add',
+ 'allowedUserGroupIDs' => $allowedUserGroupIDs,
+ ]);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function show()
+ {
+ if (!WCF::getSession()->getPermission('user.conversation.canStartConversation')) {
+ throw new PermissionDeniedException();
+ }
+
+ parent::show();
+ }
+
+ private function getParticipantsData($invisible = false)
+ {
+ $result = [];
+ $participants = ArrayUtil::trim(\explode(
+ ',',
+ ($invisible ? $this->invisibleParticipants : $this->participants)
+ ));
+ foreach ($participants as $username) {
+ $result[] = [
+ 'objectId' => 0,
+ 'value' => $username,
+ 'type' => 'user',
+ ];
+ }
+
+ $participants = ArrayUtil::toIntegerArray(\explode(
+ ',',
+ ($invisible ? $this->invisibleParticipantsGroupIDs : $this->participantsGroupIDs)
+ ));
+ foreach ($participants as $groupID) {
+ $group = UserGroup::getGroupByID($groupID);
+ if (!$group) {
+ continue;
+ }
+ $result[] = [
+ 'objectId' => $groupID,
+ 'value' => $group->getName(),
+ 'type' => 'group',
+ ];
+ }
+
+ return $result;
+ }
}
<?php
+
namespace wcf\form;
-use wcf\data\conversation\message\ConversationMessageAction;
+
use wcf\data\conversation\Conversation;
use wcf\data\conversation\ConversationAction;
+use wcf\data\conversation\message\ConversationMessageAction;
use wcf\data\user\UserProfile;
use wcf\system\exception\IllegalLinkException;
use wcf\system\message\quote\MessageQuoteManager;
/**
* Allows the editing of conversation drafts.
*
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Form
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Form
*/
-class ConversationDraftEditForm extends ConversationAddForm {
- /**
- * @inheritDoc
- */
- public $templateName = 'conversationAdd';
-
- /**
- * conversation id
- * @var integer
- */
- public $conversationID = 0;
-
- /**
- * conversation
- * @var Conversation
- */
- public $conversation;
-
- /**
- * @inheritDoc
- */
- public function readParameters() {
- parent::readParameters();
-
- if (isset($_REQUEST['id'])) $this->conversationID = intval($_REQUEST['id']);
- $this->conversation = new Conversation($this->conversationID);
- if ($this->conversation->userID != WCF::getUser()->userID || !$this->conversation->isDraft) {
- throw new IllegalLinkException();
- }
-
- $this->attachmentObjectID = $this->conversation->getFirstMessage()->messageID;
- }
-
- /**
- * @inheritDoc
- */
- public function save() {
- MessageForm::save();
-
- // save message
- $messageData = [
- 'data' => [],
- 'attachmentHandler' => $this->attachmentHandler,
- 'htmlInputProcessor' => $this->htmlInputProcessor,
- ];
- if (!$this->draft) {
- // update timestamp
- $messageData['data']['time'] = TIME_NOW;
- }
- $messageAction = new ConversationMessageAction([$this->conversation->getFirstMessage()], 'update', $messageData);
- $messageAction->executeAction();
-
- // save conversation
- $data = array_merge($this->additionalFields, [
- 'subject' => $this->subject,
- 'isDraft' => $this->draft ? 1 : 0,
- 'participantCanInvite' => $this->participantCanInvite
- ]);
- if ($this->draft) {
- $data['draftData'] = serialize([
- 'participants' => $this->participantIDs,
- 'invisibleParticipants' => $this->invisibleParticipantIDs
- ]);
- }
- $conversationData = [
- 'data' => $data,
- ];
- if (!$this->draft) {
- $conversationData['participants'] = $this->participantIDs;
- $conversationData['invisibleParticipants'] = $this->invisibleParticipantIDs;
- // update timestamp
- $conversationData['data']['time'] = $conversationData['data']['lastPostTime'] = TIME_NOW;
- }
- $this->objectAction = new ConversationAction([$this->conversation], 'update', $conversationData);
- $this->objectAction->executeAction();
-
- MessageQuoteManager::getInstance()->saved();
- $this->saved();
-
- // forward
- HeaderUtil::redirect($this->conversation->getLink());
- exit;
- }
-
- /**
- * @inheritDoc
- */
- public function readData() {
- parent::readData();
-
- if (empty($_POST)) {
- $this->text = $this->conversation->getFirstMessage()->message;
- $this->participantCanInvite = $this->conversation->participantCanInvite;
- $this->subject = $this->conversation->subject;
-
- if ($this->conversation->draftData) {
- $draftData = @unserialize($this->conversation->draftData);
- if (!empty($draftData['participants'])) {
- foreach (UserProfile::getUserProfiles($draftData['participants']) as $user) {
- if (!empty($this->participants)) $this->participants .= ', ';
- $this->participants .= $user->username;
- }
- }
- if (!empty($draftData['invisibleParticipants'])) {
- foreach (UserProfile::getUserProfiles($draftData['invisibleParticipants']) as $user) {
- if (!empty($this->invisibleParticipants)) $this->invisibleParticipants .= ', ';
- $this->invisibleParticipants .= $user->username;
- }
- }
- }
- }
- }
-
- /**
- * @inheritDoc
- */
- public function assignVariables() {
- parent::assignVariables();
-
- WCF::getTPL()->assign([
- 'conversationID' => $this->conversationID,
- 'conversation' => $this->conversation,
- 'action' => 'edit'
- ]);
- }
+class ConversationDraftEditForm extends ConversationAddForm
+{
+ /**
+ * @inheritDoc
+ */
+ public $templateName = 'conversationAdd';
+
+ /**
+ * conversation id
+ * @var integer
+ */
+ public $conversationID = 0;
+
+ /**
+ * conversation
+ * @var Conversation
+ */
+ public $conversation;
+
+ /**
+ * @inheritDoc
+ */
+ public function readParameters()
+ {
+ parent::readParameters();
+
+ if (isset($_REQUEST['id'])) {
+ $this->conversationID = \intval($_REQUEST['id']);
+ }
+ $this->conversation = new Conversation($this->conversationID);
+ if ($this->conversation->userID != WCF::getUser()->userID || !$this->conversation->isDraft) {
+ throw new IllegalLinkException();
+ }
+
+ $this->attachmentObjectID = $this->conversation->getFirstMessage()->messageID;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function save()
+ {
+ MessageForm::save();
+
+ // save message
+ $messageData = [
+ 'data' => [],
+ 'attachmentHandler' => $this->attachmentHandler,
+ 'htmlInputProcessor' => $this->htmlInputProcessor,
+ ];
+ if (!$this->draft) {
+ // update timestamp
+ $messageData['data']['time'] = TIME_NOW;
+ }
+ $messageAction = new ConversationMessageAction(
+ [$this->conversation->getFirstMessage()],
+ 'update',
+ $messageData
+ );
+ $messageAction->executeAction();
+
+ // save conversation
+ $data = \array_merge($this->additionalFields, [
+ 'subject' => $this->subject,
+ 'isDraft' => $this->draft ? 1 : 0,
+ 'participantCanInvite' => $this->participantCanInvite,
+ ]);
+ if ($this->draft) {
+ $data['draftData'] = \serialize([
+ 'participants' => $this->participantIDs,
+ 'invisibleParticipants' => $this->invisibleParticipantIDs,
+ ]);
+ }
+ $conversationData = [
+ 'data' => $data,
+ ];
+ if (!$this->draft) {
+ $conversationData['participants'] = $this->participantIDs;
+ $conversationData['invisibleParticipants'] = $this->invisibleParticipantIDs;
+ // update timestamp
+ $conversationData['data']['time'] = $conversationData['data']['lastPostTime'] = TIME_NOW;
+ }
+ $this->objectAction = new ConversationAction([$this->conversation], 'update', $conversationData);
+ $this->objectAction->executeAction();
+
+ MessageQuoteManager::getInstance()->saved();
+ $this->saved();
+
+ // forward
+ HeaderUtil::redirect($this->conversation->getLink());
+
+ exit;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function readData()
+ {
+ parent::readData();
+
+ if (empty($_POST)) {
+ $this->text = $this->conversation->getFirstMessage()->message;
+ $this->participantCanInvite = $this->conversation->participantCanInvite;
+ $this->subject = $this->conversation->subject;
+
+ if ($this->conversation->draftData) {
+ $draftData = @\unserialize($this->conversation->draftData);
+ if (!empty($draftData['participants'])) {
+ foreach (UserProfile::getUserProfiles($draftData['participants']) as $user) {
+ if (!empty($this->participants)) {
+ $this->participants .= ', ';
+ }
+ $this->participants .= $user->username;
+ }
+ }
+ if (!empty($draftData['invisibleParticipants'])) {
+ foreach (UserProfile::getUserProfiles($draftData['invisibleParticipants']) as $user) {
+ if (!empty($this->invisibleParticipants)) {
+ $this->invisibleParticipants .= ', ';
+ }
+ $this->invisibleParticipants .= $user->username;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function assignVariables()
+ {
+ parent::assignVariables();
+
+ WCF::getTPL()->assign([
+ 'conversationID' => $this->conversationID,
+ 'conversation' => $this->conversation,
+ 'action' => 'edit',
+ ]);
+ }
}
<?php
+
namespace wcf\page;
+
use wcf\data\conversation\FeedConversationList;
use wcf\system\WCF;
/**
* Shows most recent conversations.
- *
- * @author Alexander Ebert
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Page
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Page
*/
-class ConversationFeedPage extends AbstractFeedPage {
- /**
- * @inheritDoc
- */
- public $loginRequired = true;
-
- /**
- * @inheritDoc
- */
- public function readData() {
- parent::readData();
-
- $this->items = new FeedConversationList();
- $this->items->getConditionBuilder()->add('conversation_to_user.participantID = ?', [WCF::getUser()->userID]);
- $this->items->getConditionBuilder()->add('conversation_to_user.hideConversation = ?', [0]);
- $this->items->sqlConditionJoins = "LEFT JOIN wcf".WCF_N."_conversation conversation ON (conversation.conversationID = conversation_to_user.conversationID)";
- $this->items->sqlLimit = 20;
- $this->items->readObjects();
-
- $this->title = WCF::getLanguage()->get('wcf.conversation.conversations');
- }
+class ConversationFeedPage extends AbstractFeedPage
+{
+ /**
+ * @inheritDoc
+ */
+ public $loginRequired = true;
+
+ /**
+ * @inheritDoc
+ */
+ public function readData()
+ {
+ parent::readData();
+
+ $this->items = new FeedConversationList();
+ $this->items->getConditionBuilder()->add('conversation_to_user.participantID = ?', [WCF::getUser()->userID]);
+ $this->items->getConditionBuilder()->add('conversation_to_user.hideConversation = ?', [0]);
+ $this->items->sqlConditionJoins = "LEFT JOIN wcf" . WCF_N . "_conversation conversation ON (conversation.conversationID = conversation_to_user.conversationID)";
+ $this->items->sqlLimit = 20;
+ $this->items->readObjects();
+
+ $this->title = WCF::getLanguage()->get('wcf.conversation.conversations');
+ }
}
<?php
+
namespace wcf\page;
+
use wcf\data\conversation\label\ConversationLabel;
use wcf\data\conversation\label\ConversationLabelList;
use wcf\data\conversation\UserConversationList;
/**
* Shows a list of conversations.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Page
- *
- * @property UserConversationList $objectList
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Page
+ *
+ * @property UserConversationList $objectList
*/
-class ConversationListPage extends SortablePage {
- /**
- * @inheritDoc
- */
- public $defaultSortField = CONVERSATION_LIST_DEFAULT_SORT_FIELD;
-
- /**
- * @inheritDoc
- */
- public $defaultSortOrder = CONVERSATION_LIST_DEFAULT_SORT_ORDER;
-
- /**
- * @inheritDoc
- */
- public $validSortFields = ['subject', 'time', 'username', 'lastPostTime', 'replies', 'participants'];
-
- /**
- * @inheritDoc
- */
- public $itemsPerPage = CONVERSATIONS_PER_PAGE;
-
- /**
- * @inheritDoc
- */
- public $loginRequired = true;
-
- /**
- * @inheritDoc
- */
- public $neededModules = ['MODULE_CONVERSATION'];
-
- /**
- * @inheritDoc
- */
- public $neededPermissions = ['user.conversation.canUseConversation'];
-
- /**
- * list filter
- * @var string
- */
- public $filter = '';
-
- /**
- * label id
- * @var integer
- */
- public $labelID = 0;
-
- /**
- * label list object
- * @var ConversationLabelList
- */
- public $labelList;
-
- /**
- * number of conversations (no filter)
- * @var integer
- */
- public $conversationCount = 0;
-
- /**
- * number of drafts
- * @var integer
- */
- public $draftCount = 0;
-
- /**
- * number of hidden conversations
- * @var integer
- */
- public $hiddenCount = 0;
-
- /**
- * number of sent conversations
- * @var integer
- */
- public $outboxCount = 0;
-
- /**
- * participant that
- * @var string[]
- */
- public $participants = [];
-
- /**
- * @inheritDoc
- */
- public function readParameters() {
- parent::readParameters();
-
- if (isset($_REQUEST['filter'])) $this->filter = $_REQUEST['filter'];
- if (!in_array($this->filter, UserConversationList::$availableFilters)) $this->filter = '';
-
- // user settings
- /** @noinspection PhpUndefinedFieldInspection */
- if (WCF::getUser()->conversationsPerPage) {
- /** @noinspection PhpUndefinedFieldInspection */
- $this->itemsPerPage = WCF::getUser()->conversationsPerPage;
- }
-
- // labels
- $this->labelList = ConversationLabel::getLabelsByUser();
- if (isset($_REQUEST['labelID'])) {
- $this->labelID = intval($_REQUEST['labelID']);
-
- $validLabel = false;
- foreach ($this->labelList as $label) {
- if ($label->labelID == $this->labelID) {
- $validLabel = true;
- break;
- }
- }
-
- if (!$validLabel) {
- throw new IllegalLinkException();
- }
- }
-
- if (isset($_REQUEST['participants'])) $this->participants = array_slice(ArrayUtil::trim(explode(',', $_REQUEST['participants'])), 0, 20);
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- protected function initObjectList() {
- $this->objectList = new UserConversationList(WCF::getUser()->userID, $this->filter, $this->labelID);
- $this->objectList->setLabelList($this->labelList);
-
- if (!empty($this->participants)) {
- // The column `conversation_to_user.username` has no index, causing full table scans when
- // trying to filter by it, therefore we'll read the user ids in advance.
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add('username IN (?)', [$this->participants]);
- $sql = "SELECT userID
- FROM wcf".WCF_N."_user
- ".$conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditions->getParameters());
- $userIDs = [];
- while ($userID = $statement->fetchColumn()) {
- $userIDs[] = $userID;
- }
-
- if (!empty($userIDs)) {
- // The condition is split into two branches in order to account for invisible participants.
- // Invisible participants are only visible to the conversation starter and remain invisible
- // until the write their first message.
- //
- // We need to protect these users from being exposed as participants by including them for
- // any conversation that the current user has started. For all other conversations, users
- // flagged with `isInvisible = 0` must be excluded.
- //
- // See https://github.com/WoltLab/com.woltlab.wcf.conversation/issues/131
- $this->objectList->getConditionBuilder()->add('
+class ConversationListPage extends SortablePage
+{
+ /**
+ * @inheritDoc
+ */
+ public $defaultSortField = CONVERSATION_LIST_DEFAULT_SORT_FIELD;
+
+ /**
+ * @inheritDoc
+ */
+ public $defaultSortOrder = CONVERSATION_LIST_DEFAULT_SORT_ORDER;
+
+ /**
+ * @inheritDoc
+ */
+ public $validSortFields = ['subject', 'time', 'username', 'lastPostTime', 'replies', 'participants'];
+
+ /**
+ * @inheritDoc
+ */
+ public $itemsPerPage = CONVERSATIONS_PER_PAGE;
+
+ /**
+ * @inheritDoc
+ */
+ public $loginRequired = true;
+
+ /**
+ * @inheritDoc
+ */
+ public $neededModules = ['MODULE_CONVERSATION'];
+
+ /**
+ * @inheritDoc
+ */
+ public $neededPermissions = ['user.conversation.canUseConversation'];
+
+ /**
+ * list filter
+ * @var string
+ */
+ public $filter = '';
+
+ /**
+ * label id
+ * @var integer
+ */
+ public $labelID = 0;
+
+ /**
+ * label list object
+ * @var ConversationLabelList
+ */
+ public $labelList;
+
+ /**
+ * number of conversations (no filter)
+ * @var integer
+ */
+ public $conversationCount = 0;
+
+ /**
+ * number of drafts
+ * @var integer
+ */
+ public $draftCount = 0;
+
+ /**
+ * number of hidden conversations
+ * @var integer
+ */
+ public $hiddenCount = 0;
+
+ /**
+ * number of sent conversations
+ * @var integer
+ */
+ public $outboxCount = 0;
+
+ /**
+ * participant that
+ * @var string[]
+ */
+ public $participants = [];
+
+ /**
+ * @inheritDoc
+ */
+ public function readParameters()
+ {
+ parent::readParameters();
+
+ if (isset($_REQUEST['filter'])) {
+ $this->filter = $_REQUEST['filter'];
+ }
+ if (!\in_array($this->filter, UserConversationList::$availableFilters)) {
+ $this->filter = '';
+ }
+
+ // user settings
+ /** @noinspection PhpUndefinedFieldInspection */
+ if (WCF::getUser()->conversationsPerPage) {
+ /** @noinspection PhpUndefinedFieldInspection */
+ $this->itemsPerPage = WCF::getUser()->conversationsPerPage;
+ }
+
+ // labels
+ $this->labelList = ConversationLabel::getLabelsByUser();
+ if (isset($_REQUEST['labelID'])) {
+ $this->labelID = \intval($_REQUEST['labelID']);
+
+ $validLabel = false;
+ foreach ($this->labelList as $label) {
+ if ($label->labelID == $this->labelID) {
+ $validLabel = true;
+ break;
+ }
+ }
+
+ if (!$validLabel) {
+ throw new IllegalLinkException();
+ }
+ }
+
+ if (isset($_REQUEST['participants'])) {
+ $this->participants = \array_slice(ArrayUtil::trim(\explode(',', $_REQUEST['participants'])), 0, 20);
+ }
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ protected function initObjectList()
+ {
+ $this->objectList = new UserConversationList(WCF::getUser()->userID, $this->filter, $this->labelID);
+ $this->objectList->setLabelList($this->labelList);
+
+ if (!empty($this->participants)) {
+ // The column `conversation_to_user.username` has no index, causing full table scans when
+ // trying to filter by it, therefore we'll read the user ids in advance.
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add('username IN (?)', [$this->participants]);
+ $sql = "SELECT userID
+ FROM wcf" . WCF_N . "_user
+ " . $conditions;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditions->getParameters());
+ $userIDs = [];
+ while ($userID = $statement->fetchColumn()) {
+ $userIDs[] = $userID;
+ }
+
+ if (!empty($userIDs)) {
+ // The condition is split into two branches in order to account for invisible participants.
+ // Invisible participants are only visible to the conversation starter and remain invisible
+ // until the write their first message.
+ //
+ // We need to protect these users from being exposed as participants by including them for
+ // any conversation that the current user has started. For all other conversations, users
+ // flagged with `isInvisible = 0` must be excluded.
+ //
+ // See https://github.com/WoltLab/com.woltlab.wcf.conversation/issues/131
+ $this->objectList->getConditionBuilder()->add('
(
(
conversation.userID = ?
AND
conversation.conversationID IN (
SELECT conversationID
- FROM wcf'.WCF_N.'_conversation_to_user
+ FROM wcf' . WCF_N . '_conversation_to_user
WHERE participantID IN (?)
GROUP BY conversationID
HAVING COUNT(conversationID) = ?
AND
conversation.conversationID IN (
SELECT conversationID
- FROM wcf'.WCF_N.'_conversation_to_user
+ FROM wcf' . WCF_N . '_conversation_to_user
WHERE participantID IN (?)
AND isInvisible = ?
GROUP BY conversationID
)
)
)', [
- // Parameters for the first condition.
- WCF::getUser()->userID,
- $userIDs,
- count($userIDs),
-
- // Parameters for the second condition.
- WCF::getUser()->userID,
- $userIDs,
- 0,
- count($userIDs),
- ]);
- }
- }
- }
-
- /**
- * @inheritDoc
- */
- public function readData() {
- // if sort field is `username`, `conversation.` has to prepended because `username`
- // alone is ambiguous
- if ($this->sortField === 'username') {
- $this->sortField = 'conversation.username';
- }
-
- parent::readData();
-
- // change back to old value
- if ($this->sortField === 'conversation.username') {
- $this->sortField = 'username';
- }
-
- if ($this->filter != '') {
- // `-1` = pseudo object id to have to pages with identifier `com.woltlab.wcf.conversation.ConversationList`
- PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.conversation.ConversationList', -1);
- }
-
- // read stats
- if (!$this->labelID && empty($this->participants)) {
- switch ($this->filter) {
- case '':
- $this->conversationCount = $this->items;
- break;
-
- case 'draft':
- $this->draftCount = $this->items;
- break;
-
- case 'hidden':
- $this->hiddenCount = $this->items;
- break;
-
- case 'outbox':
- $this->outboxCount = $this->items;
- break;
- }
- }
-
- if ($this->filter != '' || $this->labelID || !empty($this->participants)) {
- $conversationList = new UserConversationList(WCF::getUser()->userID, '');
- $this->conversationCount = $conversationList->countObjects();
- }
- if ($this->filter != 'draft' || $this->labelID || !empty($this->participants)) {
- $conversationList = new UserConversationList(WCF::getUser()->userID, 'draft');
- $this->draftCount = $conversationList->countObjects();
- }
- if ($this->filter != 'hidden' || $this->labelID || !empty($this->participants)) {
- $conversationList = new UserConversationList(WCF::getUser()->userID, 'hidden');
- $this->hiddenCount = $conversationList->countObjects();
- }
- if ($this->filter != 'outbox' || $this->labelID || !empty($this->participants)) {
- $conversationList = new UserConversationList(WCF::getUser()->userID, 'outbox');
- $this->outboxCount = $conversationList->countObjects();
- }
- }
-
- /**
- * @inheritDoc
- */
- public function assignVariables() {
- parent::assignVariables();
-
- WCF::getTPL()->assign([
- 'filter' => $this->filter,
- 'hasMarkedItems' => ClipboardHandler::getInstance()->hasMarkedItems(ClipboardHandler::getInstance()->getObjectTypeID('com.woltlab.wcf.conversation.conversation')),
- 'labelID' => $this->labelID,
- 'labelList' => $this->labelList,
- 'conversationCount' => $this->conversationCount,
- 'draftCount' => $this->draftCount,
- 'hiddenCount' => $this->hiddenCount,
- 'outboxCount' => $this->outboxCount,
- 'participants' => $this->participants,
- 'validSortFields' => $this->validSortFields,
- ]);
- }
+ // Parameters for the first condition.
+ WCF::getUser()->userID,
+ $userIDs,
+ \count($userIDs),
+
+ // Parameters for the second condition.
+ WCF::getUser()->userID,
+ $userIDs,
+ 0,
+ \count($userIDs),
+ ]);
+ }
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function readData()
+ {
+ // if sort field is `username`, `conversation.` has to prepended because `username`
+ // alone is ambiguous
+ if ($this->sortField === 'username') {
+ $this->sortField = 'conversation.username';
+ }
+
+ parent::readData();
+
+ // change back to old value
+ if ($this->sortField === 'conversation.username') {
+ $this->sortField = 'username';
+ }
+
+ if ($this->filter != '') {
+ // `-1` = pseudo object id to have to pages with identifier `com.woltlab.wcf.conversation.ConversationList`
+ PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.conversation.ConversationList', -1);
+ }
+
+ // read stats
+ if (!$this->labelID && empty($this->participants)) {
+ switch ($this->filter) {
+ case '':
+ $this->conversationCount = $this->items;
+ break;
+
+ case 'draft':
+ $this->draftCount = $this->items;
+ break;
+
+ case 'hidden':
+ $this->hiddenCount = $this->items;
+ break;
+
+ case 'outbox':
+ $this->outboxCount = $this->items;
+ break;
+ }
+ }
+
+ if ($this->filter != '' || $this->labelID || !empty($this->participants)) {
+ $conversationList = new UserConversationList(WCF::getUser()->userID, '');
+ $this->conversationCount = $conversationList->countObjects();
+ }
+ if ($this->filter != 'draft' || $this->labelID || !empty($this->participants)) {
+ $conversationList = new UserConversationList(WCF::getUser()->userID, 'draft');
+ $this->draftCount = $conversationList->countObjects();
+ }
+ if ($this->filter != 'hidden' || $this->labelID || !empty($this->participants)) {
+ $conversationList = new UserConversationList(WCF::getUser()->userID, 'hidden');
+ $this->hiddenCount = $conversationList->countObjects();
+ }
+ if ($this->filter != 'outbox' || $this->labelID || !empty($this->participants)) {
+ $conversationList = new UserConversationList(WCF::getUser()->userID, 'outbox');
+ $this->outboxCount = $conversationList->countObjects();
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function assignVariables()
+ {
+ parent::assignVariables();
+
+ WCF::getTPL()->assign([
+ 'filter' => $this->filter,
+ 'hasMarkedItems' => ClipboardHandler::getInstance()->hasMarkedItems(
+ ClipboardHandler::getInstance()->getObjectTypeID('com.woltlab.wcf.conversation.conversation')
+ ),
+ 'labelID' => $this->labelID,
+ 'labelList' => $this->labelList,
+ 'conversationCount' => $this->conversationCount,
+ 'draftCount' => $this->draftCount,
+ 'hiddenCount' => $this->hiddenCount,
+ 'outboxCount' => $this->outboxCount,
+ 'participants' => $this->participants,
+ 'validSortFields' => $this->validSortFields,
+ ]);
+ }
}
<?php
+
namespace wcf\page;
+
+use wcf\data\conversation\Conversation;
+use wcf\data\conversation\ConversationAction;
+use wcf\data\conversation\ConversationParticipantList;
use wcf\data\conversation\label\ConversationLabel;
use wcf\data\conversation\label\ConversationLabelList;
use wcf\data\conversation\message\ConversationMessage;
use wcf\data\conversation\message\ViewableConversationMessageList;
-use wcf\data\conversation\Conversation;
-use wcf\data\conversation\ConversationAction;
-use wcf\data\conversation\ConversationParticipantList;
use wcf\data\conversation\ViewableConversation;
use wcf\data\modification\log\ConversationLogModificationLogList;
use wcf\data\smiley\SmileyCache;
/**
* Shows a conversation.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\Page
- *
- * @property ViewableConversationMessageList $objectList
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Page
+ *
+ * @property ViewableConversationMessageList $objectList
*/
-class ConversationPage extends MultipleLinkPage {
- /**
- * @inheritDoc
- */
- public $itemsPerPage = CONVERSATION_MESSAGES_PER_PAGE;
-
- /**
- * @inheritDoc
- */
- public $sortOrder = 'ASC';
-
- /**
- * @inheritDoc
- */
- public $objectListClassName = ViewableConversationMessageList::class;
-
- /**
- * @inheritDoc
- */
- public $loginRequired = true;
-
- /**
- * @inheritDoc
- */
- public $neededModules = ['MODULE_CONVERSATION'];
-
- /**
- * @inheritDoc
- */
- public $neededPermissions = ['user.conversation.canUseConversation'];
-
- /**
- * conversation id
- * @var integer
- */
- public $conversationID = 0;
-
- /**
- * viewable conversation object
- * @var ViewableConversation
- */
- public $conversation;
-
- /**
- * conversation label list
- * @var ConversationLabelList
- */
- public $labelList;
-
- /**
- * message id
- * @var integer
- */
- public $messageID = 0;
-
- /**
- * conversation message object
- * @var ConversationMessage
- */
- public $message;
-
- /**
- * modification log list object
- * @var ConversationLogModificationLogList
- */
- public $modificationLogList;
-
- /**
- * list of participants
- * @var ConversationParticipantList
- */
- public $participantList;
-
- /**
- * @inheritDoc
- */
- public function readParameters() {
- parent::readParameters();
-
- if (isset($_REQUEST['id'])) $this->conversationID = intval($_REQUEST['id']);
- if (isset($_REQUEST['messageID'])) $this->messageID = intval($_REQUEST['messageID']);
- if ($this->messageID) {
- $this->message = new ConversationMessage($this->messageID);
- if (!$this->message->messageID) {
- throw new IllegalLinkException();
- }
- $this->conversationID = $this->message->conversationID;
- }
-
- $this->conversation = Conversation::getUserConversation($this->conversationID, WCF::getUser()->userID);
- if ($this->conversation === null) {
- throw new IllegalLinkException();
- }
- if (!$this->conversation->canRead()) {
- throw new PermissionDeniedException();
- }
-
- // load labels
- $this->labelList = ConversationLabel::getLabelsByUser();
- $this->conversation = ViewableConversation::getViewableConversation($this->conversation, $this->labelList);
-
- // messages per page
- /** @noinspection PhpUndefinedFieldInspection */
- if (WCF::getUser()->conversationMessagesPerPage) {
- /** @noinspection PhpUndefinedFieldInspection */
- $this->itemsPerPage = WCF::getUser()->conversationMessagesPerPage;
- }
-
- $this->canonicalURL = LinkHandler::getInstance()->getLink('Conversation', [
- 'object' => $this->conversation
- ], ($this->pageNo ? 'pageNo=' . $this->pageNo : ''));
- }
-
- /**
- * @inheritDoc
- */
- protected function initObjectList() {
- parent::initObjectList();
-
- $this->objectList->getConditionBuilder()->add('conversation_message.conversationID = ?', [$this->conversation->conversationID]);
- $this->objectList->setConversation($this->conversation->getDecoratedObject());
-
- // handle visibility filter
- if ($this->conversation->joinedAt > 0) $this->objectList->getConditionBuilder()->add('conversation_message.time >= ?', [$this->conversation->joinedAt]);
- if ($this->conversation->leftAt > 0) $this->objectList->getConditionBuilder()->add('conversation_message.time <= ?', [$this->conversation->leftAt]);
-
- // handle jump to
- if ($this->action == 'lastPost') $this->goToLastPost();
- if ($this->action == 'firstNew') $this->goToFirstNewPost();
- if ($this->messageID) $this->goToPost();
- }
-
- /**
- * @inheritDoc
- */
- public function readData() {
- parent::readData();
-
- // add breadcrumbs
- if ($this->conversation->isDraft) {
- // `-1` = pseudo object id to have to pages with identifier `com.woltlab.wcf.conversation.ConversationList`
- PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.conversation.ConversationList', -1, new ParentPageLocation(
- WCF::getLanguage()->get('wcf.conversation.folder.draft'),
- LinkHandler::getInstance()->getLink('ConversationList', ['filter' => 'draft'])
- ));
- }
- PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.conversation.ConversationList');
-
- // update last visit time count
- if (
- $this->conversation->isNew()
- && (
- $this->objectList->getMaxPostTime() > $this->conversation->lastVisitTime
- || ($this->conversation->joinedAt && !count($this->objectList))
- )
- ) {
- $visitTime = $this->objectList->getMaxPostTime();
- if ($visitTime == $this->conversation->lastPostTime) $visitTime = TIME_NOW;
- $conversationAction = new ConversationAction([$this->conversation->getDecoratedObject()], 'markAsRead', ['visitTime' => $visitTime]);
- $conversationAction->executeAction();
- }
-
- // get participants
- $this->participantList = new ConversationParticipantList($this->conversationID, WCF::getUser()->userID, $this->conversation->userID == WCF::getUser()->userID);
- $this->participantList->readObjects();
-
- // init quote objects
- $messageIDs = [];
- foreach ($this->objectList as $message) {
- $messageIDs[] = $message->messageID;
- }
- MessageQuoteManager::getInstance()->initObjects('com.woltlab.wcf.conversation.message', $messageIDs);
-
- $userIDs = [];
- foreach ($this->objectList as $message) {
- if ($message->userID) {
- $userIDs[] = $message->userID;
- }
- }
-
- // fetch special trophies
- if (MODULE_TROPHY) {
- if (!empty($userIDs)) {
- UserProfile::prepareSpecialTrophies(array_unique($userIDs));
- }
- }
-
- if (MODULE_USER_SIGNATURE) {
- if (!empty($userIDs)) {
- SignatureCache::getInstance()->cacheUserSignature($userIDs);
- }
- }
-
- // set attachment permissions
- if ($this->objectList->getAttachmentList() !== null) {
- $this->objectList->getAttachmentList()->setPermissions([
- 'canDownload' => true,
- 'canViewPreview' => true
- ]);
- }
-
- // get timeframe for modifications
- $this->objectList->rewind();
- $startTime = ($this->conversation->joinedAt ?: $this->objectList->current()->time);
- $endTime = ($this->conversation->leftAt ?: TIME_NOW);
-
- $count = count($this->objectList);
- if ($count > 1) {
- $this->objectList->seek($count - 1);
- if ($this->objectList->current()->time < $this->conversation->lastPostTime) {
- $sql = "SELECT time
- FROM wcf".WCF_N."_conversation_message
+class ConversationPage extends MultipleLinkPage
+{
+ /**
+ * @inheritDoc
+ */
+ public $itemsPerPage = CONVERSATION_MESSAGES_PER_PAGE;
+
+ /**
+ * @inheritDoc
+ */
+ public $sortOrder = 'ASC';
+
+ /**
+ * @inheritDoc
+ */
+ public $objectListClassName = ViewableConversationMessageList::class;
+
+ /**
+ * @inheritDoc
+ */
+ public $loginRequired = true;
+
+ /**
+ * @inheritDoc
+ */
+ public $neededModules = ['MODULE_CONVERSATION'];
+
+ /**
+ * @inheritDoc
+ */
+ public $neededPermissions = ['user.conversation.canUseConversation'];
+
+ /**
+ * conversation id
+ * @var integer
+ */
+ public $conversationID = 0;
+
+ /**
+ * viewable conversation object
+ * @var ViewableConversation
+ */
+ public $conversation;
+
+ /**
+ * conversation label list
+ * @var ConversationLabelList
+ */
+ public $labelList;
+
+ /**
+ * message id
+ * @var integer
+ */
+ public $messageID = 0;
+
+ /**
+ * conversation message object
+ * @var ConversationMessage
+ */
+ public $message;
+
+ /**
+ * modification log list object
+ * @var ConversationLogModificationLogList
+ */
+ public $modificationLogList;
+
+ /**
+ * list of participants
+ * @var ConversationParticipantList
+ */
+ public $participantList;
+
+ /**
+ * @inheritDoc
+ */
+ public function readParameters()
+ {
+ parent::readParameters();
+
+ if (isset($_REQUEST['id'])) {
+ $this->conversationID = \intval($_REQUEST['id']);
+ }
+ if (isset($_REQUEST['messageID'])) {
+ $this->messageID = \intval($_REQUEST['messageID']);
+ }
+ if ($this->messageID) {
+ $this->message = new ConversationMessage($this->messageID);
+ if (!$this->message->messageID) {
+ throw new IllegalLinkException();
+ }
+ $this->conversationID = $this->message->conversationID;
+ }
+
+ $this->conversation = Conversation::getUserConversation($this->conversationID, WCF::getUser()->userID);
+ if ($this->conversation === null) {
+ throw new IllegalLinkException();
+ }
+ if (!$this->conversation->canRead()) {
+ throw new PermissionDeniedException();
+ }
+
+ // load labels
+ $this->labelList = ConversationLabel::getLabelsByUser();
+ $this->conversation = ViewableConversation::getViewableConversation($this->conversation, $this->labelList);
+
+ // messages per page
+ /** @noinspection PhpUndefinedFieldInspection */
+ if (WCF::getUser()->conversationMessagesPerPage) {
+ /** @noinspection PhpUndefinedFieldInspection */
+ $this->itemsPerPage = WCF::getUser()->conversationMessagesPerPage;
+ }
+
+ $this->canonicalURL = LinkHandler::getInstance()->getLink('Conversation', [
+ 'object' => $this->conversation,
+ ], ($this->pageNo ? 'pageNo=' . $this->pageNo : ''));
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function initObjectList()
+ {
+ parent::initObjectList();
+
+ $this->objectList->getConditionBuilder()
+ ->add('conversation_message.conversationID = ?', [$this->conversation->conversationID]);
+ $this->objectList->setConversation($this->conversation->getDecoratedObject());
+
+ // handle visibility filter
+ if ($this->conversation->joinedAt > 0) {
+ $this->objectList->getConditionBuilder()
+ ->add('conversation_message.time >= ?', [$this->conversation->joinedAt]);
+ }
+ if ($this->conversation->leftAt > 0) {
+ $this->objectList->getConditionBuilder()
+ ->add('conversation_message.time <= ?', [$this->conversation->leftAt]);
+ }
+
+ // handle jump to
+ if ($this->action == 'lastPost') {
+ $this->goToLastPost();
+ }
+ if ($this->action == 'firstNew') {
+ $this->goToFirstNewPost();
+ }
+ if ($this->messageID) {
+ $this->goToPost();
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function readData()
+ {
+ parent::readData();
+
+ // add breadcrumbs
+ if ($this->conversation->isDraft) {
+ // `-1` = pseudo object id to have to pages with identifier `com.woltlab.wcf.conversation.ConversationList`
+ PageLocationManager::getInstance()->addParentLocation(
+ 'com.woltlab.wcf.conversation.ConversationList',
+ -1,
+ new ParentPageLocation(
+ WCF::getLanguage()->get('wcf.conversation.folder.draft'),
+ LinkHandler::getInstance()->getLink('ConversationList', ['filter' => 'draft'])
+ )
+ );
+ }
+ PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.conversation.ConversationList');
+
+ // update last visit time count
+ if (
+ $this->conversation->isNew()
+ && (
+ $this->objectList->getMaxPostTime() > $this->conversation->lastVisitTime
+ || ($this->conversation->joinedAt && !\count($this->objectList))
+ )
+ ) {
+ $visitTime = $this->objectList->getMaxPostTime();
+ if ($visitTime == $this->conversation->lastPostTime) {
+ $visitTime = TIME_NOW;
+ }
+ $conversationAction = new ConversationAction(
+ [$this->conversation->getDecoratedObject()],
+ 'markAsRead',
+ ['visitTime' => $visitTime]
+ );
+ $conversationAction->executeAction();
+ }
+
+ // get participants
+ $this->participantList = new ConversationParticipantList(
+ $this->conversationID,
+ WCF::getUser()->userID,
+ $this->conversation->userID == WCF::getUser()->userID
+ );
+ $this->participantList->readObjects();
+
+ // init quote objects
+ $messageIDs = [];
+ foreach ($this->objectList as $message) {
+ $messageIDs[] = $message->messageID;
+ }
+ MessageQuoteManager::getInstance()->initObjects('com.woltlab.wcf.conversation.message', $messageIDs);
+
+ $userIDs = [];
+ foreach ($this->objectList as $message) {
+ if ($message->userID) {
+ $userIDs[] = $message->userID;
+ }
+ }
+
+ // fetch special trophies
+ if (MODULE_TROPHY) {
+ if (!empty($userIDs)) {
+ UserProfile::prepareSpecialTrophies(\array_unique($userIDs));
+ }
+ }
+
+ if (MODULE_USER_SIGNATURE) {
+ if (!empty($userIDs)) {
+ SignatureCache::getInstance()->cacheUserSignature($userIDs);
+ }
+ }
+
+ // set attachment permissions
+ if ($this->objectList->getAttachmentList() !== null) {
+ $this->objectList->getAttachmentList()->setPermissions([
+ 'canDownload' => true,
+ 'canViewPreview' => true,
+ ]);
+ }
+
+ // get timeframe for modifications
+ $this->objectList->rewind();
+ $startTime = ($this->conversation->joinedAt ?: $this->objectList->current()->time);
+ $endTime = ($this->conversation->leftAt ?: TIME_NOW);
+
+ $count = \count($this->objectList);
+ if ($count > 1) {
+ $this->objectList->seek($count - 1);
+ if ($this->objectList->current()->time < $this->conversation->lastPostTime) {
+ $sql = "SELECT time
+ FROM wcf" . WCF_N . "_conversation_message
WHERE conversationID = ?
AND time > ?
ORDER BY time";
- $statement = WCF::getDB()->prepareStatement($sql, 1);
- $statement->execute([$this->conversationID, $this->objectList->current()->time]);
- $endTime = $statement->fetchSingleColumn() - 1;
- }
- }
- $this->objectList->rewind();
-
- // get invisible participants
- $invisibleParticipantIDs = [];
- if (WCF::getUser()->userID != $this->conversation->userID) {
- foreach ($this->participantList as $participant) {
- if ($participant->isInvisible) {
- $invisibleParticipantIDs[] = $participant->userID;
- }
- }
- }
-
- // load modification log entries
- $this->modificationLogList = new ConversationLogModificationLogList($this->conversation->conversationID);
- $this->modificationLogList->getConditionBuilder()->add("modification_log.time BETWEEN ? AND ?", [$startTime, $endTime]);
-
- if (!empty($invisibleParticipantIDs)) {
- $this->modificationLogList->getConditionBuilder()->add("(modification_log.action <> ? OR modification_log.userID NOT IN (?))", ['leave', $invisibleParticipantIDs]);
- }
-
- $this->modificationLogList->readObjects();
- }
-
- /**
- * @inheritDoc
- */
- public function assignVariables() {
- parent::assignVariables();
-
- MessageQuoteManager::getInstance()->assignVariables();
-
- $tmpHash = StringUtil::getRandomID();
- $attachmentHandler = new AttachmentHandler('com.woltlab.wcf.conversation.message', 0, $tmpHash, 0);
-
- WCF::getTPL()->assign([
- 'attachmentHandler' => $attachmentHandler,
- 'attachmentObjectID' => 0,
- 'attachmentObjectType' => 'com.woltlab.wcf.conversation.message',
- 'attachmentParentObjectID' => 0,
- 'tmpHash' => $tmpHash,
- 'attachmentList' => $this->objectList->getAttachmentList(),
- 'labelList' => $this->labelList,
- 'modificationLogList' => $this->modificationLogList,
- 'sortOrder' => $this->sortOrder,
- 'conversation' => $this->conversation,
- 'conversationID' => $this->conversationID,
- 'participants' => $this->participantList->getObjects(),
- 'defaultSmilies' => SmileyCache::getInstance()->getCategorySmilies()
- ]);
-
- BBCodeHandler::getInstance()->setDisallowedBBCodes(explode(',', WCF::getSession()->getPermission('user.message.disallowedBBCodes')));
- }
-
- /**
- * Calculates the position of a specific post in this conversation.
- */
- protected function goToPost() {
- $conditionBuilder = clone $this->objectList->getConditionBuilder();
- $conditionBuilder->add('time '.($this->sortOrder == 'ASC' ? '<=' : '>=').' ?', [$this->message->time]);
-
- $sql = "SELECT COUNT(*) AS messages
- FROM wcf".WCF_N."_conversation_message conversation_message
- ".$conditionBuilder;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditionBuilder->getParameters());
- $row = $statement->fetchArray();
- $this->pageNo = intval(ceil($row['messages'] / $this->itemsPerPage));
- }
-
- /**
- * Gets the id of the last post in this conversation and forwards the user to this post.
- */
- protected function goToLastPost() {
- $sql = "SELECT conversation_message.messageID
- FROM wcf".WCF_N."_conversation_message conversation_message
- ".$this->objectList->getConditionBuilder()."
- ORDER BY time ".($this->sortOrder == 'ASC' ? 'DESC' : 'ASC');
- $statement = WCF::getDB()->prepareStatement($sql, 1);
- $statement->execute($this->objectList->getConditionBuilder()->getParameters());
- $row = $statement->fetchArray();
- HeaderUtil::redirect(LinkHandler::getInstance()->getLink('Conversation', [
- 'encodeTitle' => true,
- 'object' => $this->conversation,
- 'messageID' => $row['messageID']
- ]).'#message'.$row['messageID']);
- exit;
- }
-
- /**
- * Forwards the user to the first new message in this conversation.
- */
- protected function goToFirstNewPost() {
- $conditionBuilder = clone $this->objectList->getConditionBuilder();
- $conditionBuilder->add('time > ?', [$this->conversation->lastVisitTime]);
-
- $sql = "SELECT conversation_message.messageID
- FROM wcf".WCF_N."_conversation_message conversation_message
- ".$conditionBuilder."
+ $statement = WCF::getDB()->prepareStatement($sql, 1);
+ $statement->execute([$this->conversationID, $this->objectList->current()->time]);
+ $endTime = $statement->fetchSingleColumn() - 1;
+ }
+ }
+ $this->objectList->rewind();
+
+ // get invisible participants
+ $invisibleParticipantIDs = [];
+ if (WCF::getUser()->userID != $this->conversation->userID) {
+ foreach ($this->participantList as $participant) {
+ if ($participant->isInvisible) {
+ $invisibleParticipantIDs[] = $participant->userID;
+ }
+ }
+ }
+
+ // load modification log entries
+ $this->modificationLogList = new ConversationLogModificationLogList($this->conversation->conversationID);
+ $this->modificationLogList->getConditionBuilder()
+ ->add("modification_log.time BETWEEN ? AND ?", [$startTime, $endTime]);
+
+ if (!empty($invisibleParticipantIDs)) {
+ $this->modificationLogList->getConditionBuilder()->add(
+ "(modification_log.action <> ? OR modification_log.userID NOT IN (?))",
+ ['leave', $invisibleParticipantIDs]
+ );
+ }
+
+ $this->modificationLogList->readObjects();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function assignVariables()
+ {
+ parent::assignVariables();
+
+ MessageQuoteManager::getInstance()->assignVariables();
+
+ $tmpHash = StringUtil::getRandomID();
+ $attachmentHandler = new AttachmentHandler('com.woltlab.wcf.conversation.message', 0, $tmpHash, 0);
+
+ WCF::getTPL()->assign([
+ 'attachmentHandler' => $attachmentHandler,
+ 'attachmentObjectID' => 0,
+ 'attachmentObjectType' => 'com.woltlab.wcf.conversation.message',
+ 'attachmentParentObjectID' => 0,
+ 'tmpHash' => $tmpHash,
+ 'attachmentList' => $this->objectList->getAttachmentList(),
+ 'labelList' => $this->labelList,
+ 'modificationLogList' => $this->modificationLogList,
+ 'sortOrder' => $this->sortOrder,
+ 'conversation' => $this->conversation,
+ 'conversationID' => $this->conversationID,
+ 'participants' => $this->participantList->getObjects(),
+ 'defaultSmilies' => SmileyCache::getInstance()->getCategorySmilies(),
+ ]);
+
+ BBCodeHandler::getInstance()->setDisallowedBBCodes(\explode(
+ ',',
+ WCF::getSession()->getPermission('user.message.disallowedBBCodes')
+ ));
+ }
+
+ /**
+ * Calculates the position of a specific post in this conversation.
+ */
+ protected function goToPost()
+ {
+ $conditionBuilder = clone $this->objectList->getConditionBuilder();
+ $conditionBuilder->add('time ' . ($this->sortOrder == 'ASC' ? '<=' : '>=') . ' ?', [$this->message->time]);
+
+ $sql = "SELECT COUNT(*) AS messages
+ FROM wcf" . WCF_N . "_conversation_message conversation_message
+ " . $conditionBuilder;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditionBuilder->getParameters());
+ $row = $statement->fetchArray();
+ $this->pageNo = \intval(\ceil($row['messages'] / $this->itemsPerPage));
+ }
+
+ /**
+ * Gets the id of the last post in this conversation and forwards the user to this post.
+ */
+ protected function goToLastPost()
+ {
+ $sql = "SELECT conversation_message.messageID
+ FROM wcf" . WCF_N . "_conversation_message conversation_message
+ " . $this->objectList->getConditionBuilder() . "
+ ORDER BY time " . ($this->sortOrder == 'ASC' ? 'DESC' : 'ASC');
+ $statement = WCF::getDB()->prepareStatement($sql, 1);
+ $statement->execute($this->objectList->getConditionBuilder()->getParameters());
+ $row = $statement->fetchArray();
+ HeaderUtil::redirect(
+ LinkHandler::getInstance()->getLink(
+ 'Conversation',
+ [
+ 'encodeTitle' => true,
+ 'object' => $this->conversation,
+ 'messageID' => $row['messageID'],
+ ]
+ ) . '#message' . $row['messageID']
+ );
+
+ exit;
+ }
+
+ /**
+ * Forwards the user to the first new message in this conversation.
+ */
+ protected function goToFirstNewPost()
+ {
+ $conditionBuilder = clone $this->objectList->getConditionBuilder();
+ $conditionBuilder->add('time > ?', [$this->conversation->lastVisitTime]);
+
+ $sql = "SELECT conversation_message.messageID
+ FROM wcf" . WCF_N . "_conversation_message conversation_message
+ " . $conditionBuilder . "
ORDER BY time ASC";
- $statement = WCF::getDB()->prepareStatement($sql, 1);
- $statement->execute($conditionBuilder->getParameters());
- $row = $statement->fetchArray();
- if ($row !== false) {
- HeaderUtil::redirect(LinkHandler::getInstance()->getLink('Conversation', [
- 'encodeTitle' => true,
- 'object' => $this->conversation,
- 'messageID' => $row['messageID']
- ]).'#message'.$row['messageID']);
- exit;
- }
- else {
- $this->goToLastPost();
- }
- }
+ $statement = WCF::getDB()->prepareStatement($sql, 1);
+ $statement->execute($conditionBuilder->getParameters());
+ $row = $statement->fetchArray();
+ if ($row !== false) {
+ HeaderUtil::redirect(
+ LinkHandler::getInstance()->getLink(
+ 'Conversation',
+ [
+ 'encodeTitle' => true,
+ 'object' => $this->conversation,
+ 'messageID' => $row['messageID'],
+ ]
+ ) . '#message' . $row['messageID']
+ );
+
+ exit;
+ } else {
+ $this->goToLastPost();
+ }
+ }
}
<?php
+
namespace wcf\system\attachment;
+
+use wcf\data\conversation\Conversation;
use wcf\data\conversation\message\ConversationMessage;
use wcf\data\conversation\message\ConversationMessageList;
-use wcf\data\conversation\Conversation;
use wcf\system\WCF;
use wcf\util\ArrayUtil;
/**
* Attachment object type implementation for conversations.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Attachment
- *
- * @method ConversationMessage getObject($objectID)
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Attachment
+ *
+ * @method ConversationMessage getObject($objectID)
*/
-class ConversationMessageAttachmentObjectType extends AbstractAttachmentObjectType {
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function getMaxSize() {
- return WCF::getSession()->getPermission('user.conversation.maxAttachmentSize');
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function getAllowedExtensions() {
- return ArrayUtil::trim(explode("\n", WCF::getSession()->getPermission('user.conversation.allowedAttachmentExtensions')));
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function getMaxCount() {
- return WCF::getSession()->getPermission('user.conversation.maxAttachmentCount');
- }
-
- /**
- * @inheritDoc
- */
- public function canDownload($objectID) {
- if ($objectID) {
- $message = new ConversationMessage($objectID);
- $conversation = Conversation::getUserConversation($message->conversationID, WCF::getUser()->userID);
- if ($conversation->canRead()) return true;
- }
-
- return false;
- }
-
- /**
- * @inheritDoc
- */
- public function canUpload($objectID, $parentObjectID = 0) {
- if (!WCF::getSession()->getPermission('user.conversation.canUploadAttachment')) {
- return false;
- }
-
- if ($objectID) {
- $message = new ConversationMessage($objectID);
- if ($message->userID == WCF::getUser()->userID) return true;
- return false;
- }
-
- return true;
- }
-
- /**
- * @inheritDoc
- */
- public function canDelete($objectID) {
- if ($objectID) {
- $message = new ConversationMessage($objectID);
- if ($message->userID == WCF::getUser()->userID) return true;
- }
-
- return false;
- }
-
- /**
- * @inheritDoc
- */
- public function cacheObjects(array $objectIDs) {
- $messageList = new ConversationMessageList();
- $messageList->setObjectIDs($objectIDs);
- $messageList->readObjects();
- $conversationIDs = [];
- foreach ($messageList as $message) {
- $conversationIDs[] = $message->conversationID;
- }
- if (!empty($conversationIDs)) {
- $conversations = Conversation::getUserConversations($conversationIDs, WCF::getUser()->userID);
- foreach ($messageList as $message) {
- if (isset($conversations[$message->conversationID])) $message->setConversation($conversations[$message->conversationID]);
- }
- }
-
- foreach ($messageList->getObjects() as $objectID => $object) {
- $this->cachedObjects[$objectID] = $object;
- }
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function setPermissions(array $attachments) {
- $messageIDs = [];
- foreach ($attachments as $attachment) {
- // set default permissions
- $attachment->setPermissions([
- 'canDownload' => false,
- 'canViewPreview' => false
- ]);
-
- if ($this->getObject($attachment->objectID) === null) {
- $messageIDs[] = $attachment->objectID;
- }
- }
-
- if (!empty($messageIDs)) {
- $this->cacheObjects($messageIDs);
- }
-
- foreach ($attachments as $attachment) {
- if (($message = $this->getObject($attachment->objectID)) !== null) {
- if (!$message->getConversation()->canRead()) continue;
-
- $attachment->setPermissions([
- 'canDownload' => true,
- 'canViewPreview' => true
- ]);
- }
- else if ($attachment->tmpHash != '' && $attachment->userID == WCF::getUser()->userID) {
- $attachment->setPermissions([
- 'canDownload' => true,
- 'canViewPreview' => true
- ]);
- }
- }
- }
+class ConversationMessageAttachmentObjectType extends AbstractAttachmentObjectType
+{
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function getMaxSize()
+ {
+ return WCF::getSession()->getPermission('user.conversation.maxAttachmentSize');
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function getAllowedExtensions()
+ {
+ return ArrayUtil::trim(\explode(
+ "\n",
+ WCF::getSession()->getPermission('user.conversation.allowedAttachmentExtensions')
+ ));
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function getMaxCount()
+ {
+ return WCF::getSession()->getPermission('user.conversation.maxAttachmentCount');
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function canDownload($objectID)
+ {
+ if ($objectID) {
+ $message = new ConversationMessage($objectID);
+ $conversation = Conversation::getUserConversation($message->conversationID, WCF::getUser()->userID);
+ if ($conversation->canRead()) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function canUpload($objectID, $parentObjectID = 0)
+ {
+ if (!WCF::getSession()->getPermission('user.conversation.canUploadAttachment')) {
+ return false;
+ }
+
+ if ($objectID) {
+ $message = new ConversationMessage($objectID);
+ if ($message->userID == WCF::getUser()->userID) {
+ return true;
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function canDelete($objectID)
+ {
+ if ($objectID) {
+ $message = new ConversationMessage($objectID);
+ if ($message->userID == WCF::getUser()->userID) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function cacheObjects(array $objectIDs)
+ {
+ $messageList = new ConversationMessageList();
+ $messageList->setObjectIDs($objectIDs);
+ $messageList->readObjects();
+ $conversationIDs = [];
+ foreach ($messageList as $message) {
+ $conversationIDs[] = $message->conversationID;
+ }
+ if (!empty($conversationIDs)) {
+ $conversations = Conversation::getUserConversations($conversationIDs, WCF::getUser()->userID);
+ foreach ($messageList as $message) {
+ if (isset($conversations[$message->conversationID])) {
+ $message->setConversation($conversations[$message->conversationID]);
+ }
+ }
+ }
+
+ foreach ($messageList->getObjects() as $objectID => $object) {
+ $this->cachedObjects[$objectID] = $object;
+ }
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function setPermissions(array $attachments)
+ {
+ $messageIDs = [];
+ foreach ($attachments as $attachment) {
+ // set default permissions
+ $attachment->setPermissions([
+ 'canDownload' => false,
+ 'canViewPreview' => false,
+ ]);
+
+ if ($this->getObject($attachment->objectID) === null) {
+ $messageIDs[] = $attachment->objectID;
+ }
+ }
+
+ if (!empty($messageIDs)) {
+ $this->cacheObjects($messageIDs);
+ }
+
+ foreach ($attachments as $attachment) {
+ if (($message = $this->getObject($attachment->objectID)) !== null) {
+ if (!$message->getConversation()->canRead()) {
+ continue;
+ }
+
+ $attachment->setPermissions([
+ 'canDownload' => true,
+ 'canViewPreview' => true,
+ ]);
+ } elseif ($attachment->tmpHash != '' && $attachment->userID == WCF::getUser()->userID) {
+ $attachment->setPermissions([
+ 'canDownload' => true,
+ 'canViewPreview' => true,
+ ]);
+ }
+ }
+ }
}
<?php
+
namespace wcf\system\cache\runtime;
+
use wcf\data\conversation\Conversation;
use wcf\data\conversation\ConversationList;
/**
* Runtime cache implementation for conversations.
*
- * @author Matthias Schmidt
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Cache\Runtime
- * @since 3.0
- *
- * @method Conversation[] getCachedObjects()
- * @method Conversation getObject($objectID)
- * @method Conversation[] getObjects(array $objectIDs)
+ * @author Matthias Schmidt
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Cache\Runtime
+ * @since 3.0
+ *
+ * @method Conversation[] getCachedObjects()
+ * @method Conversation getObject($objectID)
+ * @method Conversation[] getObjects(array $objectIDs)
*/
-class ConversationRuntimeCache extends AbstractRuntimeCache {
- /**
- * @inheritDoc
- */
- protected $listClassName = ConversationList::class;
+class ConversationRuntimeCache extends AbstractRuntimeCache
+{
+ /**
+ * @inheritDoc
+ */
+ protected $listClassName = ConversationList::class;
}
<?php
+
namespace wcf\system\cache\runtime;
+
use wcf\data\conversation\Conversation;
use wcf\data\conversation\UserConversationList;
use wcf\system\WCF;
/**
* Runtime cache implementation for conversation fetched using UserConversationList.
*
- * @author Matthias Schmidt
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Cache\Runtime
- * @since 3.0
- *
- * @method Conversation[] getCachedObjects()
- * @method Conversation getObject($objectID)
- * @method Conversation[] getObjects(array $objectIDs)
+ * @author Matthias Schmidt
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Cache\Runtime
+ * @since 3.0
+ *
+ * @method Conversation[] getCachedObjects()
+ * @method Conversation getObject($objectID)
+ * @method Conversation[] getObjects(array $objectIDs)
*/
-class UserConversationRuntimeCache extends AbstractRuntimeCache {
- /**
- * @inheritDoc
- */
- protected $listClassName = UserConversationList::class;
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- protected function getObjectList() {
- return new UserConversationList(WCF::getUser()->userID);
- }
+class UserConversationRuntimeCache extends AbstractRuntimeCache
+{
+ /**
+ * @inheritDoc
+ */
+ protected $listClassName = UserConversationList::class;
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ protected function getObjectList()
+ {
+ return new UserConversationList(WCF::getUser()->userID);
+ }
}
<?php
+
namespace wcf\system\clipboard\action;
+
use wcf\data\clipboard\action\ClipboardAction;
use wcf\data\conversation\Conversation;
use wcf\data\conversation\ConversationAction;
/**
* Prepares clipboard editor items for conversations.
- *
- * @author Alexander Ebert
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Clipboard\Action
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Clipboard\Action
*/
-class ConversationClipboardAction extends AbstractClipboardAction {
- /**
- * @inheritDoc
- */
- protected $actionClassActions = ['close', 'markAsRead', 'open'];
-
- /**
- * list of conversations
- * @var Conversation[]
- */
- public $conversations;
-
- /**
- * @inheritDoc
- */
- protected $supportedActions = ['assignLabel', 'close', 'leave', 'leavePermanently', 'markAsRead', 'open', 'restore'];
-
- /**
- * @inheritDoc
- */
- public function execute(array $objects, ClipboardAction $action) {
- if ($this->conversations === null) {
- // validate conversations
- $this->validateParticipation($objects);
- }
-
- // check if no conversation was accessible
- if (empty($this->conversations)) {
- return null;
- }
-
- $item = parent::execute($objects, $action);
-
- if ($item === null) {
- return null;
- }
-
- switch ($action->actionName) {
- case 'assignLabel':
- // check if user has labels
- $sql = "SELECT COUNT(*) AS count
- FROM wcf".WCF_N."_conversation_label
+class ConversationClipboardAction extends AbstractClipboardAction
+{
+ /**
+ * @inheritDoc
+ */
+ protected $actionClassActions = ['close', 'markAsRead', 'open'];
+
+ /**
+ * list of conversations
+ * @var Conversation[]
+ */
+ public $conversations;
+
+ /**
+ * @inheritDoc
+ */
+ protected $supportedActions = [
+ 'assignLabel',
+ 'close',
+ 'leave',
+ 'leavePermanently',
+ 'markAsRead',
+ 'open',
+ 'restore',
+ ];
+
+ /**
+ * @inheritDoc
+ */
+ public function execute(array $objects, ClipboardAction $action)
+ {
+ if ($this->conversations === null) {
+ // validate conversations
+ $this->validateParticipation($objects);
+ }
+
+ // check if no conversation was accessible
+ if (empty($this->conversations)) {
+ return;
+ }
+
+ $item = parent::execute($objects, $action);
+
+ if ($item === null) {
+ return;
+ }
+
+ switch ($action->actionName) {
+ case 'assignLabel':
+ // check if user has labels
+ $sql = "SELECT COUNT(*) AS count
+ FROM wcf" . WCF_N . "_conversation_label
WHERE userID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute([WCF::getUser()->userID]);
- $row = $statement->fetchArray();
- if ($row['count'] == 0) {
- return null;
- }
-
- $item->addParameter('objectIDs', array_keys($this->conversations));
- break;
-
- case 'leave':
- $item->addInternalData('parameters', ['hideConversation' => 1]);
- $item->addParameter('actionName', 'hideConversation');
- $item->addParameter('className', $this->getClassName());
- break;
-
- case 'leavePermanently':
- $item->addParameter('objectIDs', array_keys($this->conversations));
- $item->addInternalData('parameters', ['hideConversation' => 2]);
- $item->addParameter('actionName', 'hideConversation');
- $item->addParameter('className', $this->getClassName());
- break;
-
- case 'markAsRead':
- $item->addParameter('objectIDs', array_keys($this->conversations));
- $item->addParameter('actionName', 'markAsRead');
- $item->addParameter('className', $this->getClassName());
- $item->addInternalData('confirmMessage', WCF::getLanguage()->getDynamicVariable('wcf.clipboard.item.com.woltlab.wcf.conversation.conversation.markAsRead.confirmMessage', [
- 'count' => $item->getCount()
- ]));
- break;
-
- case 'restore':
- $item->addInternalData('parameters', ['hideConversation' => 0]);
- $item->addParameter('actionName', 'hideConversation');
- $item->addParameter('className', $this->getClassName());
- break;
- }
-
- return $item;
- }
-
- /**
- * @inheritDoc
- */
- public function getClassName() {
- return ConversationAction::class;
- }
-
- /**
- * @inheritDoc
- */
- public function getTypeName() {
- return 'com.woltlab.wcf.conversation.conversation';
- }
-
- /**
- * Returns a list of conversations with user participation.
- *
- * @param Conversation[] $conversations
- */
- protected function validateParticipation(array $conversations) {
- $conversationIDs = [];
-
- // validate ownership
- foreach ($conversations as $conversation) {
- if ($conversation->userID != WCF::getUser()->userID) {
- $conversationIDs[] = $conversation->conversationID;
- }
- }
-
- // validate participation as non-owner
- if (!empty($conversationIDs)) {
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID IN (?)", [$conversationIDs]);
- $conditions->add("participantID = ?", [WCF::getUser()->userID]);
-
- $sql = "SELECT conversationID
- FROM wcf".WCF_N."_conversation_to_user
- ".$conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditions->getParameters());
- while ($row = $statement->fetchArray()) {
- $index = array_search($row['conversationID'], $conversationIDs);
- unset($conversationIDs[$index]);
- }
-
- // remove unaccessible conversations
- if (!empty($conversationIDs)) {
- foreach ($conversations as $index => $conversation) {
- if (in_array($conversation->conversationID, $conversationIDs)) {
- unset($conversations[$index]);
- }
- }
- }
- }
-
- foreach ($conversations as $conversation) {
- $this->conversations[$conversation->conversationID] = $conversation;
- }
- }
-
- /**
- * Validates if user may close the given conversations.
- *
- * @return integer[]
- */
- protected function validateClose() {
- $conversationIDs = [];
-
- foreach ($this->conversations as $conversation) {
- if (!$conversation->isClosed && $conversation->userID == WCF::getUser()->userID) {
- $conversationIDs[] = $conversation->conversationID;
- }
- }
-
- return $conversationIDs;
- }
-
- /**
- * Validates conversations available for leaving.
- *
- * @return integer[]
- */
- public function validateLeave() {
- $tmpIDs = [];
- foreach ($this->conversations as $conversation) {
- $tmpIDs[] = $conversation->conversationID;
- }
-
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID IN (?)", [$tmpIDs]);
- $conditions->add("participantID = ?", [WCF::getUser()->userID]);
- $conditions->add("hideConversation <> ?", [1]);
-
- $sql = "SELECT conversationID
- FROM wcf".WCF_N."_conversation_to_user
- ".$conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditions->getParameters());
-
- return $statement->fetchAll(\PDO::FETCH_COLUMN);
- }
-
- /**
- * Validates conversations applicable for mark as read.
- *
- * @return integer[]
- */
- public function validateMarkAsRead() {
- $conversationIDs = [];
-
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID IN (?)", [array_keys($this->conversations)]);
- $conditions->add("participantID = ?", [WCF::getUser()->userID]);
-
- $sql = "SELECT conversationID, lastVisitTime
- FROM wcf".WCF_N."_conversation_to_user
- ".$conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditions->getParameters());
- $lastVisitTime = [];
- while ($row = $statement->fetchArray()) {
- $lastVisitTime[$row['conversationID']] = $row['lastVisitTime'];
- }
-
- foreach ($this->conversations as $conversation) {
- if (isset($lastVisitTime[$conversation->conversationID]) && $lastVisitTime[$conversation->conversationID] < $conversation->lastPostTime) {
- $conversationIDs[] = $conversation->conversationID;
- }
- }
-
- return $conversationIDs;
- }
-
- /**
- * Validates if user may open the given conversations.
- *
- * @return integer[]
- */
- protected function validateOpen() {
- $conversationIDs = [];
-
- foreach ($this->conversations as $conversation) {
- if ($conversation->isClosed && $conversation->userID == WCF::getUser()->userID) {
- $conversationIDs[] = $conversation->conversationID;
- }
- }
-
- return $conversationIDs;
- }
-
- /**
- * Validates conversations available for restore.
- *
- * @return integer[]
- */
- public function validateRestore() {
- $tmpIDs = [];
- foreach ($this->conversations as $conversation) {
- $tmpIDs[] = $conversation->conversationID;
- }
-
- $conditions = new PreparedStatementConditionBuilder();
- $conditions->add("conversationID IN (?)", [$tmpIDs]);
- $conditions->add("participantID = ?", [WCF::getUser()->userID]);
- $conditions->add("hideConversation <> ?", [0]);
-
- $sql = "SELECT conversationID
- FROM wcf".WCF_N."_conversation_to_user
- ".$conditions;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditions->getParameters());
-
- return $statement->fetchAll(\PDO::FETCH_COLUMN);
- }
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([WCF::getUser()->userID]);
+ $row = $statement->fetchArray();
+ if ($row['count'] == 0) {
+ return;
+ }
+
+ $item->addParameter('objectIDs', \array_keys($this->conversations));
+ break;
+
+ case 'leave':
+ $item->addInternalData('parameters', ['hideConversation' => 1]);
+ $item->addParameter('actionName', 'hideConversation');
+ $item->addParameter('className', $this->getClassName());
+ break;
+
+ case 'leavePermanently':
+ $item->addParameter('objectIDs', \array_keys($this->conversations));
+ $item->addInternalData('parameters', ['hideConversation' => 2]);
+ $item->addParameter('actionName', 'hideConversation');
+ $item->addParameter('className', $this->getClassName());
+ break;
+
+ case 'markAsRead':
+ $item->addParameter('objectIDs', \array_keys($this->conversations));
+ $item->addParameter('actionName', 'markAsRead');
+ $item->addParameter('className', $this->getClassName());
+ $item->addInternalData(
+ 'confirmMessage',
+ WCF::getLanguage()->getDynamicVariable(
+ 'wcf.clipboard.item.com.woltlab.wcf.conversation.conversation.markAsRead.confirmMessage',
+ [
+ 'count' => $item->getCount(),
+ ]
+ )
+ );
+ break;
+
+ case 'restore':
+ $item->addInternalData('parameters', ['hideConversation' => 0]);
+ $item->addParameter('actionName', 'hideConversation');
+ $item->addParameter('className', $this->getClassName());
+ break;
+ }
+
+ return $item;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getClassName()
+ {
+ return ConversationAction::class;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getTypeName()
+ {
+ return 'com.woltlab.wcf.conversation.conversation';
+ }
+
+ /**
+ * Returns a list of conversations with user participation.
+ *
+ * @param Conversation[] $conversations
+ */
+ protected function validateParticipation(array $conversations)
+ {
+ $conversationIDs = [];
+
+ // validate ownership
+ foreach ($conversations as $conversation) {
+ if ($conversation->userID != WCF::getUser()->userID) {
+ $conversationIDs[] = $conversation->conversationID;
+ }
+ }
+
+ // validate participation as non-owner
+ if (!empty($conversationIDs)) {
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("conversationID IN (?)", [$conversationIDs]);
+ $conditions->add("participantID = ?", [WCF::getUser()->userID]);
+
+ $sql = "SELECT conversationID
+ FROM wcf" . WCF_N . "_conversation_to_user
+ " . $conditions;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditions->getParameters());
+ while ($row = $statement->fetchArray()) {
+ $index = \array_search($row['conversationID'], $conversationIDs);
+ unset($conversationIDs[$index]);
+ }
+
+ // remove unaccessible conversations
+ if (!empty($conversationIDs)) {
+ foreach ($conversations as $index => $conversation) {
+ if (\in_array($conversation->conversationID, $conversationIDs)) {
+ unset($conversations[$index]);
+ }
+ }
+ }
+ }
+
+ foreach ($conversations as $conversation) {
+ $this->conversations[$conversation->conversationID] = $conversation;
+ }
+ }
+
+ /**
+ * Validates if user may close the given conversations.
+ *
+ * @return integer[]
+ */
+ protected function validateClose()
+ {
+ $conversationIDs = [];
+
+ foreach ($this->conversations as $conversation) {
+ if (!$conversation->isClosed && $conversation->userID == WCF::getUser()->userID) {
+ $conversationIDs[] = $conversation->conversationID;
+ }
+ }
+
+ return $conversationIDs;
+ }
+
+ /**
+ * Validates conversations available for leaving.
+ *
+ * @return integer[]
+ */
+ public function validateLeave()
+ {
+ $tmpIDs = [];
+ foreach ($this->conversations as $conversation) {
+ $tmpIDs[] = $conversation->conversationID;
+ }
+
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("conversationID IN (?)", [$tmpIDs]);
+ $conditions->add("participantID = ?", [WCF::getUser()->userID]);
+ $conditions->add("hideConversation <> ?", [1]);
+
+ $sql = "SELECT conversationID
+ FROM wcf" . WCF_N . "_conversation_to_user
+ " . $conditions;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditions->getParameters());
+
+ return $statement->fetchAll(\PDO::FETCH_COLUMN);
+ }
+
+ /**
+ * Validates conversations applicable for mark as read.
+ *
+ * @return integer[]
+ */
+ public function validateMarkAsRead()
+ {
+ $conversationIDs = [];
+
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("conversationID IN (?)", [\array_keys($this->conversations)]);
+ $conditions->add("participantID = ?", [WCF::getUser()->userID]);
+
+ $sql = "SELECT conversationID, lastVisitTime
+ FROM wcf" . WCF_N . "_conversation_to_user
+ " . $conditions;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditions->getParameters());
+ $lastVisitTime = [];
+ while ($row = $statement->fetchArray()) {
+ $lastVisitTime[$row['conversationID']] = $row['lastVisitTime'];
+ }
+
+ foreach ($this->conversations as $conversation) {
+ if (
+ isset($lastVisitTime[$conversation->conversationID])
+ && $lastVisitTime[$conversation->conversationID] < $conversation->lastPostTime
+ ) {
+ $conversationIDs[] = $conversation->conversationID;
+ }
+ }
+
+ return $conversationIDs;
+ }
+
+ /**
+ * Validates if user may open the given conversations.
+ *
+ * @return integer[]
+ */
+ protected function validateOpen()
+ {
+ $conversationIDs = [];
+
+ foreach ($this->conversations as $conversation) {
+ if ($conversation->isClosed && $conversation->userID == WCF::getUser()->userID) {
+ $conversationIDs[] = $conversation->conversationID;
+ }
+ }
+
+ return $conversationIDs;
+ }
+
+ /**
+ * Validates conversations available for restore.
+ *
+ * @return integer[]
+ */
+ public function validateRestore()
+ {
+ $tmpIDs = [];
+ foreach ($this->conversations as $conversation) {
+ $tmpIDs[] = $conversation->conversationID;
+ }
+
+ $conditions = new PreparedStatementConditionBuilder();
+ $conditions->add("conversationID IN (?)", [$tmpIDs]);
+ $conditions->add("participantID = ?", [WCF::getUser()->userID]);
+ $conditions->add("hideConversation <> ?", [0]);
+
+ $sql = "SELECT conversationID
+ FROM wcf" . WCF_N . "_conversation_to_user
+ " . $conditions;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditions->getParameters());
+
+ return $statement->fetchAll(\PDO::FETCH_COLUMN);
+ }
}
<?php
+
namespace wcf\system\conversation;
+
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\exception\NamedUserException;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\flood\FloodControl;
-use wcf\system\user\storage\UserStorageHandler;
use wcf\system\SingletonFactory;
+use wcf\system\user\storage\UserStorageHandler;
use wcf\system\WCF;
/**
* Handles the number of conversations and unread conversations of the active user.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Conversation
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Conversation
*/
-class ConversationHandler extends SingletonFactory {
- /**
- * number of unread conversations
- * @var integer[]
- */
- protected $unreadConversationCount = [];
-
- /**
- * number of conversations
- * @var integer[]
- */
- protected $conversationCount = [];
-
- /**
- * Returns the number of unread conversations for given user.
- *
- * @param integer $userID
- * @param boolean $skipCache
- * @return integer
- */
- public function getUnreadConversationCount($userID = null, $skipCache = false) {
- if ($userID === null) $userID = WCF::getUser()->userID;
-
- if (!isset($this->unreadConversationCount[$userID]) || $skipCache) {
- $this->unreadConversationCount[$userID] = 0;
-
- // load storage data
- UserStorageHandler::getInstance()->loadStorage([$userID]);
-
- // get ids
- $data = UserStorageHandler::getInstance()->getStorage([$userID], 'unreadConversationCount');
-
- // cache does not exist or is outdated
- if ($data[$userID] === null || $skipCache) {
- $conditionBuilder = new PreparedStatementConditionBuilder();
- $conditionBuilder->add('conversation.conversationID = conversation_to_user.conversationID');
- $conditionBuilder->add('conversation_to_user.participantID = ?', [$userID]);
- $conditionBuilder->add('conversation_to_user.hideConversation = 0');
- $conditionBuilder->add('conversation_to_user.lastVisitTime < conversation.lastPostTime');
- $conditionBuilder->add('conversation_to_user.leftAt = 0');
-
- $sql = "SELECT COUNT(*) AS count
- FROM wcf".WCF_N."_conversation_to_user conversation_to_user,
- wcf".WCF_N."_conversation conversation
- ".$conditionBuilder;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditionBuilder->getParameters());
- $row = $statement->fetchArray();
- $this->unreadConversationCount[$userID] = $row['count'];
-
- // update storage data
- UserStorageHandler::getInstance()->update($userID, 'unreadConversationCount', serialize($this->unreadConversationCount[$userID]));
- }
- else {
- $this->unreadConversationCount[$userID] = unserialize($data[$userID]);
- }
- }
-
- return $this->unreadConversationCount[$userID];
- }
-
- /**
- * Returns the number of conversations for given user.
- *
- * @param integer $userID
- * @return integer
- */
- public function getConversationCount($userID = null) {
- if ($userID === null) $userID = WCF::getUser()->userID;
-
- if (!isset($this->conversationCount[$userID])) {
- $this->conversationCount[$userID] = 0;
-
- // load storage data
- UserStorageHandler::getInstance()->loadStorage([$userID]);
-
- // get ids
- $data = UserStorageHandler::getInstance()->getStorage([$userID], 'conversationCount');
-
- // cache does not exist or is outdated
- if ($data[$userID] === null) {
- $conditionBuilder1 = new PreparedStatementConditionBuilder();
- $conditionBuilder1->add('conversation_to_user.participantID = ?', [$userID]);
- $conditionBuilder1->add('conversation_to_user.hideConversation IN (0,1)');
- $conditionBuilder2 = new PreparedStatementConditionBuilder();
- $conditionBuilder2->add('conversation.userID = ?', [$userID]);
- $conditionBuilder2->add('conversation.isDraft = 1');
-
- $sql = "SELECT (SELECT COUNT(*)
- FROM wcf".WCF_N."_conversation_to_user conversation_to_user
- ".$conditionBuilder1->__toString().")
+class ConversationHandler extends SingletonFactory
+{
+ /**
+ * number of unread conversations
+ * @var integer[]
+ */
+ protected $unreadConversationCount = [];
+
+ /**
+ * number of conversations
+ * @var integer[]
+ */
+ protected $conversationCount = [];
+
+ /**
+ * Returns the number of unread conversations for given user.
+ *
+ * @param integer $userID
+ * @param boolean $skipCache
+ * @return integer
+ */
+ public function getUnreadConversationCount($userID = null, $skipCache = false)
+ {
+ if ($userID === null) {
+ $userID = WCF::getUser()->userID;
+ }
+
+ if (!isset($this->unreadConversationCount[$userID]) || $skipCache) {
+ $this->unreadConversationCount[$userID] = 0;
+
+ // load storage data
+ UserStorageHandler::getInstance()->loadStorage([$userID]);
+
+ // get ids
+ $data = UserStorageHandler::getInstance()->getStorage([$userID], 'unreadConversationCount');
+
+ // cache does not exist or is outdated
+ if ($data[$userID] === null || $skipCache) {
+ $conditionBuilder = new PreparedStatementConditionBuilder();
+ $conditionBuilder->add('conversation.conversationID = conversation_to_user.conversationID');
+ $conditionBuilder->add('conversation_to_user.participantID = ?', [$userID]);
+ $conditionBuilder->add('conversation_to_user.hideConversation = 0');
+ $conditionBuilder->add('conversation_to_user.lastVisitTime < conversation.lastPostTime');
+ $conditionBuilder->add('conversation_to_user.leftAt = 0');
+
+ $sql = "SELECT COUNT(*) AS count
+ FROM wcf" . WCF_N . "_conversation_to_user conversation_to_user,
+ wcf" . WCF_N . "_conversation conversation
+ " . $conditionBuilder;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditionBuilder->getParameters());
+ $row = $statement->fetchArray();
+ $this->unreadConversationCount[$userID] = $row['count'];
+
+ // update storage data
+ UserStorageHandler::getInstance()->update(
+ $userID,
+ 'unreadConversationCount',
+ \serialize($this->unreadConversationCount[$userID])
+ );
+ } else {
+ $this->unreadConversationCount[$userID] = \unserialize($data[$userID]);
+ }
+ }
+
+ return $this->unreadConversationCount[$userID];
+ }
+
+ /**
+ * Returns the number of conversations for given user.
+ *
+ * @param integer $userID
+ * @return integer
+ */
+ public function getConversationCount($userID = null)
+ {
+ if ($userID === null) {
+ $userID = WCF::getUser()->userID;
+ }
+
+ if (!isset($this->conversationCount[$userID])) {
+ $this->conversationCount[$userID] = 0;
+
+ // load storage data
+ UserStorageHandler::getInstance()->loadStorage([$userID]);
+
+ // get ids
+ $data = UserStorageHandler::getInstance()->getStorage([$userID], 'conversationCount');
+
+ // cache does not exist or is outdated
+ if ($data[$userID] === null) {
+ $conditionBuilder1 = new PreparedStatementConditionBuilder();
+ $conditionBuilder1->add('conversation_to_user.participantID = ?', [$userID]);
+ $conditionBuilder1->add('conversation_to_user.hideConversation IN (0,1)');
+ $conditionBuilder2 = new PreparedStatementConditionBuilder();
+ $conditionBuilder2->add('conversation.userID = ?', [$userID]);
+ $conditionBuilder2->add('conversation.isDraft = 1');
+
+ $sql = "SELECT (SELECT COUNT(*)
+ FROM wcf" . WCF_N . "_conversation_to_user conversation_to_user
+ " . $conditionBuilder1->__toString() . ")
+
(SELECT COUNT(*)
- FROM wcf".WCF_N."_conversation conversation
- ".$conditionBuilder2->__toString().") AS count";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute(array_merge($conditionBuilder1->getParameters(), $conditionBuilder2->getParameters()));
- $row = $statement->fetchArray();
- $this->conversationCount[$userID] = $row['count'];
-
- // update storage data
- UserStorageHandler::getInstance()->update($userID, 'conversationCount', serialize($this->conversationCount[$userID]));
- }
- else {
- $this->conversationCount[$userID] = unserialize($data[$userID]);
- }
- }
-
- return $this->conversationCount[$userID];
- }
-
- /**
- * Enforces the flood control.
- */
- public function enforceFloodControl() {
- $limit = WCF::getSession()->getPermission('user.conversation.maxStartedConversationsPer24Hours');
- if ($limit == -1) {
- return;
- }
- else if ($limit == 0) {
- // `0` is not a valid value, but the interface logic does not permit and exclusion
- // while also allowing the special value `-1`. Therefore, `0` behaves like the
- // 'canStartConversation' permission added in WoltLab Suite 5.2.
- throw new PermissionDeniedException();
- }
-
- $count = FloodControl::getInstance()->countContent('com.woltlab.wcf.conversation', new \DateInterval('P1D'));
- if ($count['count'] >= $limit) {
- throw new NamedUserException(WCF::getLanguage()->getDynamicVariable('wcf.conversation.error.floodControl', [
- 'limit' => $count['count'],
- 'notBefore' => $count['earliestTime'] + 86400,
- ]));
- }
- }
+ FROM wcf" . WCF_N . "_conversation conversation
+ " . $conditionBuilder2->__toString() . ") AS count";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute(\array_merge(
+ $conditionBuilder1->getParameters(),
+ $conditionBuilder2->getParameters()
+ ));
+ $row = $statement->fetchArray();
+ $this->conversationCount[$userID] = $row['count'];
+
+ // update storage data
+ UserStorageHandler::getInstance()->update(
+ $userID,
+ 'conversationCount',
+ \serialize($this->conversationCount[$userID])
+ );
+ } else {
+ $this->conversationCount[$userID] = \unserialize($data[$userID]);
+ }
+ }
+
+ return $this->conversationCount[$userID];
+ }
+
+ /**
+ * Enforces the flood control.
+ */
+ public function enforceFloodControl()
+ {
+ $limit = WCF::getSession()->getPermission('user.conversation.maxStartedConversationsPer24Hours');
+ if ($limit == -1) {
+ return;
+ } elseif ($limit == 0) {
+ // `0` is not a valid value, but the interface logic does not permit and exclusion
+ // while also allowing the special value `-1`. Therefore, `0` behaves like the
+ // 'canStartConversation' permission added in WoltLab Suite 5.2.
+ throw new PermissionDeniedException();
+ }
+
+ $count = FloodControl::getInstance()->countContent('com.woltlab.wcf.conversation', new \DateInterval('P1D'));
+ if ($count['count'] >= $limit) {
+ throw new NamedUserException(WCF::getLanguage()->getDynamicVariable('wcf.conversation.error.floodControl', [
+ 'limit' => $count['count'],
+ 'notBefore' => $count['earliestTime'] + 86400,
+ ]));
+ }
+ }
}
<?php
+
namespace wcf\system\event\listener;
+
use wcf\system\cronjob\PruneIpAddressesCronjob;
/**
* Prunes the stored ip addresses.
- *
- * @author Alexander Ebert
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Event\Listener
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Event\Listener
* @since 5.2
*/
-class ConversationPruneIpAddressesCronjobListener implements IParameterizedEventListener {
- /**
- * @inheritDoc
- */
- public function execute($eventObj, $className, $eventName, array &$parameters) {
- /** @var PruneIpAddressesCronjob $eventObj */
- $eventObj->columns['wcf'.WCF_N.'_conversation_message']['ipAddress'] = 'time';
- }
+class ConversationPruneIpAddressesCronjobListener implements IParameterizedEventListener
+{
+ /**
+ * @inheritDoc
+ */
+ public function execute($eventObj, $className, $eventName, array &$parameters)
+ {
+ /** @var PruneIpAddressesCronjob $eventObj */
+ $eventObj->columns['wcf' . WCF_N . '_conversation_message']['ipAddress'] = 'time';
+ }
}
<?php
+
namespace wcf\system\event\listener;
/**
* Updates the stored username during user rename.
- *
- * @author Alexander Ebert
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Event\Listener
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Event\Listener
*/
-class ConversationUserActionRenameListener extends AbstractUserActionRenameListener {
- /**
- * @inheritDoc
- */
- protected $databaseTables = [
- 'wcf{WCF_N}_conversation',
- 'wcf{WCF_N}_conversation_message',
- [
- 'name' => 'wcf{WCF_N}_conversation',
- 'userID' => 'lastPosterID',
- 'username' => 'lastPoster'
- ],
- [
- 'name' => 'wcf{WCF_N}_conversation_to_user',
- 'userID' => 'participantID'
- ]
- ];
+class ConversationUserActionRenameListener extends AbstractUserActionRenameListener
+{
+ /**
+ * @inheritDoc
+ */
+ protected $databaseTables = [
+ 'wcf{WCF_N}_conversation',
+ 'wcf{WCF_N}_conversation_message',
+ [
+ 'name' => 'wcf{WCF_N}_conversation',
+ 'userID' => 'lastPosterID',
+ 'username' => 'lastPoster',
+ ],
+ [
+ 'name' => 'wcf{WCF_N}_conversation_to_user',
+ 'userID' => 'participantID',
+ ],
+ ];
}
<?php
+
namespace wcf\system\event\listener;
/**
* Merges user conversations.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Event\Listener
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Event\Listener
*/
-class ConversationUserMergeListener extends AbstractUserMergeListener {
- /**
- * @inheritDoc
- */
- protected $databaseTables = [
- 'wcf{WCF_N}_conversation',
- 'wcf{WCF_N}_conversation_message',
- [
- 'name' => 'wcf{WCF_N}_conversation_label',
- 'username' => null
- ],
- [
- 'name' => 'wcf{WCF_N}_conversation_to_user',
- 'userID' => 'participantID',
- 'ignore' => true
- ]
- ];
+class ConversationUserMergeListener extends AbstractUserMergeListener
+{
+ /**
+ * @inheritDoc
+ */
+ protected $databaseTables = [
+ 'wcf{WCF_N}_conversation',
+ 'wcf{WCF_N}_conversation_message',
+ [
+ 'name' => 'wcf{WCF_N}_conversation_label',
+ 'username' => null,
+ ],
+ [
+ 'name' => 'wcf{WCF_N}_conversation_to_user',
+ 'userID' => 'participantID',
+ 'ignore' => true,
+ ],
+ ];
}
<?php
+
namespace wcf\system\event\listener;
+
use wcf\acp\form\UserGroupAddForm;
use wcf\acp\form\UserGroupEditForm;
use wcf\data\user\group\UserGroup;
/**
* Handles 'canBeAddedAsConversationParticipant' setting.
*
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Event\Listener
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Event\Listener
*/
-class UserGroupAddCanBeAddedAsConversationParticipantListener implements IParameterizedEventListener {
- /**
- * instance of UserGroupAddForm
- * @var UserGroupAddForm|UserGroupEditForm
- */
- protected $eventObj;
-
- /**
- * true if group can be added as participant
- * @var boolean
- */
- protected $canBeAddedAsConversationParticipant = 0;
-
- /**
- * @inheritDoc
- */
- public function execute($eventObj, $className, $eventName, array &$parameters) {
- $this->eventObj = $eventObj;
-
- if ($this->eventObj instanceof UserGroupEditForm && is_object($this->eventObj->group)) {
- switch ($this->eventObj->group->groupType) {
- case UserGroup::EVERYONE:
- case UserGroup::GUESTS:
- case UserGroup::USERS:
- return;
- }
- }
-
- $this->$eventName();
- }
-
- /**
- * Handles the assignVariables event.
- */
- protected function assignVariables() {
- WCF::getTPL()->assign([
- 'canBeAddedAsConversationParticipant' => $this->canBeAddedAsConversationParticipant
- ]);
- }
-
- /**
- * Handles the readData event.
- * This is only called in UserGroupEditForm.
- */
- protected function readData() {
- if (empty($_POST)) {
- $this->canBeAddedAsConversationParticipant = $this->eventObj->group->canBeAddedAsConversationParticipant;
- }
- }
-
- /**
- * Handles the readFormParameters event.
- */
- protected function readFormParameters() {
- if (isset($_POST['canBeAddedAsConversationParticipant'])) $this->canBeAddedAsConversationParticipant = intval($_POST['canBeAddedAsConversationParticipant']);
- }
-
- /**
- * Handles the save event.
- */
- protected function save() {
- $this->eventObj->additionalFields = array_merge($this->eventObj->additionalFields, [
- 'canBeAddedAsConversationParticipant' => $this->canBeAddedAsConversationParticipant
- ]);
- }
+class UserGroupAddCanBeAddedAsConversationParticipantListener implements IParameterizedEventListener
+{
+ /**
+ * instance of UserGroupAddForm
+ * @var UserGroupAddForm|UserGroupEditForm
+ */
+ protected $eventObj;
+
+ /**
+ * true if group can be added as participant
+ * @var boolean
+ */
+ protected $canBeAddedAsConversationParticipant = 0;
+
+ /**
+ * @inheritDoc
+ */
+ public function execute($eventObj, $className, $eventName, array &$parameters)
+ {
+ $this->eventObj = $eventObj;
+
+ if ($this->eventObj instanceof UserGroupEditForm && \is_object($this->eventObj->group)) {
+ switch ($this->eventObj->group->groupType) {
+ case UserGroup::EVERYONE:
+ case UserGroup::GUESTS:
+ case UserGroup::USERS:
+ return;
+ }
+ }
+
+ $this->{$eventName}();
+ }
+
+ /**
+ * Handles the assignVariables event.
+ */
+ protected function assignVariables()
+ {
+ WCF::getTPL()->assign([
+ 'canBeAddedAsConversationParticipant' => $this->canBeAddedAsConversationParticipant,
+ ]);
+ }
+
+ /**
+ * Handles the readData event.
+ * This is only called in UserGroupEditForm.
+ */
+ protected function readData()
+ {
+ if (empty($_POST)) {
+ $this->canBeAddedAsConversationParticipant = $this->eventObj->group->canBeAddedAsConversationParticipant;
+ }
+ }
+
+ /**
+ * Handles the readFormParameters event.
+ */
+ protected function readFormParameters()
+ {
+ if (isset($_POST['canBeAddedAsConversationParticipant'])) {
+ $this->canBeAddedAsConversationParticipant = \intval($_POST['canBeAddedAsConversationParticipant']);
+ }
+ }
+
+ /**
+ * Handles the save event.
+ */
+ protected function save()
+ {
+ $this->eventObj->additionalFields = \array_merge($this->eventObj->additionalFields, [
+ 'canBeAddedAsConversationParticipant' => $this->canBeAddedAsConversationParticipant,
+ ]);
+ }
}
<?php
+
namespace wcf\system\importer;
+
use wcf\data\conversation\message\ConversationMessage;
use wcf\data\conversation\message\ConversationMessageEditor;
use wcf\data\object\type\ObjectTypeCache;
/**
* Imports conversation attachments.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Importer
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Importer
*/
-class ConversationAttachmentImporter extends AbstractAttachmentImporter {
- /**
- * Creates a new ConversationAttachmentImporter object.
- */
- public function __construct() {
- $objectType = ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.attachment.objectType', 'com.woltlab.wcf.conversation.message');
- $this->objectTypeID = $objectType->objectTypeID;
- }
-
- /**
- * @inheritDoc
- */
- public function import($oldID, array $data, array $additionalData = []) {
- $data['objectID'] = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.conversation.message', $data['objectID']);
- if (!$data['objectID']) return 0;
-
- $attachmentID = parent::import($oldID, $data, $additionalData);
- if ($attachmentID && $attachmentID != $oldID) {
- // fix embedded attachments
- $messageObj = new ConversationMessage($data['objectID']);
-
- if (($newMessage = $this->fixEmbeddedAttachments($messageObj->message, $oldID, $attachmentID)) !== false) {
- $editor = new ConversationMessageEditor($messageObj);
- $editor->update([
- 'message' => $newMessage
- ]);
- }
- }
-
- return $attachmentID;
- }
+class ConversationAttachmentImporter extends AbstractAttachmentImporter
+{
+ /**
+ * Creates a new ConversationAttachmentImporter object.
+ */
+ public function __construct()
+ {
+ $objectType = ObjectTypeCache::getInstance()
+ ->getObjectTypeByName('com.woltlab.wcf.attachment.objectType', 'com.woltlab.wcf.conversation.message');
+ $this->objectTypeID = $objectType->objectTypeID;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function import($oldID, array $data, array $additionalData = [])
+ {
+ $data['objectID'] = ImportHandler::getInstance()
+ ->getNewID('com.woltlab.wcf.conversation.message', $data['objectID']);
+ if (!$data['objectID']) {
+ return 0;
+ }
+
+ $attachmentID = parent::import($oldID, $data, $additionalData);
+ if ($attachmentID && $attachmentID != $oldID) {
+ // fix embedded attachments
+ $messageObj = new ConversationMessage($data['objectID']);
+
+ if (($newMessage = $this->fixEmbeddedAttachments($messageObj->message, $oldID, $attachmentID)) !== false) {
+ $editor = new ConversationMessageEditor($messageObj);
+ $editor->update([
+ 'message' => $newMessage,
+ ]);
+ }
+ }
+
+ return $attachmentID;
+ }
}
<?php
+
namespace wcf\system\importer;
+
use wcf\data\conversation\Conversation;
use wcf\data\conversation\ConversationEditor;
/**
* Imports conversations.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Importer
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Importer
*/
-class ConversationImporter extends AbstractImporter {
- /**
- * @inheritDoc
- */
- protected $className = Conversation::class;
-
- /**
- * @inheritDoc
- */
- public function import($oldID, array $data, array $additionalData = []) {
- $oldUserID = $data['userID'];
- $data['userID'] = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.user', $data['userID']);
-
- // check existing conversation
- if (ctype_digit((string)$oldID)) {
- $existingConversation = new Conversation($oldID);
- if (!$existingConversation->conversationID) $data['conversationID'] = $oldID;
- }
-
- $conversation = ConversationEditor::create($data);
-
- ImportHandler::getInstance()->saveNewID('com.woltlab.wcf.conversation', $oldID, $conversation->conversationID);
-
- // add author
- if (empty($data['isDraft'])) {
- ImportHandler::getInstance()->getImporter('com.woltlab.wcf.conversation.user')->import(0, [
- 'conversationID' => $oldID,
- 'participantID' => $oldUserID,
- 'username' => $data['username'],
- 'hideConversation' => 0,
- 'isInvisible' => 0,
- 'lastVisitTime' => $data['time']
- ], ['labelIDs' => []]);
- }
-
- return $conversation->conversationID;
- }
+class ConversationImporter extends AbstractImporter
+{
+ /**
+ * @inheritDoc
+ */
+ protected $className = Conversation::class;
+
+ /**
+ * @inheritDoc
+ */
+ public function import($oldID, array $data, array $additionalData = [])
+ {
+ $oldUserID = $data['userID'];
+ $data['userID'] = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.user', $data['userID']);
+
+ // check existing conversation
+ if (\ctype_digit((string)$oldID)) {
+ $existingConversation = new Conversation($oldID);
+ if (!$existingConversation->conversationID) {
+ $data['conversationID'] = $oldID;
+ }
+ }
+
+ $conversation = ConversationEditor::create($data);
+
+ ImportHandler::getInstance()->saveNewID('com.woltlab.wcf.conversation', $oldID, $conversation->conversationID);
+
+ // add author
+ if (empty($data['isDraft'])) {
+ ImportHandler::getInstance()->getImporter('com.woltlab.wcf.conversation.user')->import(0, [
+ 'conversationID' => $oldID,
+ 'participantID' => $oldUserID,
+ 'username' => $data['username'],
+ 'hideConversation' => 0,
+ 'isInvisible' => 0,
+ 'lastVisitTime' => $data['time'],
+ ], ['labelIDs' => []]);
+ }
+
+ return $conversation->conversationID;
+ }
}
<?php
+
namespace wcf\system\importer;
+
use wcf\data\conversation\label\ConversationLabel;
use wcf\data\conversation\label\ConversationLabelAction;
/**
* Imports conversation labels.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Importer
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Importer
*/
-class ConversationLabelImporter extends AbstractImporter {
- /**
- * @inheritDoc
- */
- protected $className = ConversationLabel::class;
-
- /**
- * @inheritDoc
- */
- public function import($oldID, array $data, array $additionalData = []) {
- $data['userID'] = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.user', $data['userID']);
- if (!$data['userID']) return 0;
-
- $action = new ConversationLabelAction([], 'create', [
- 'data' => $data
- ]);
- $returnValues = $action->executeAction();
- $newID = $returnValues['returnValues']->labelID;
-
- ImportHandler::getInstance()->saveNewID('com.woltlab.wcf.conversation.label', $oldID, $newID);
-
- return $newID;
- }
+class ConversationLabelImporter extends AbstractImporter
+{
+ /**
+ * @inheritDoc
+ */
+ protected $className = ConversationLabel::class;
+
+ /**
+ * @inheritDoc
+ */
+ public function import($oldID, array $data, array $additionalData = [])
+ {
+ $data['userID'] = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.user', $data['userID']);
+ if (!$data['userID']) {
+ return 0;
+ }
+
+ $action = new ConversationLabelAction([], 'create', [
+ 'data' => $data,
+ ]);
+ $returnValues = $action->executeAction();
+ $newID = $returnValues['returnValues']->labelID;
+
+ ImportHandler::getInstance()->saveNewID('com.woltlab.wcf.conversation.label', $oldID, $newID);
+
+ return $newID;
+ }
}
<?php
+
namespace wcf\system\importer;
+
use wcf\data\conversation\message\ConversationMessage;
use wcf\data\conversation\message\ConversationMessageEditor;
/**
* Imports conversation messages.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Importer
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Importer
*/
-class ConversationMessageImporter extends AbstractImporter {
- /**
- * @inheritDoc
- */
- protected $className = ConversationMessage::class;
-
- /**
- * @inheritDoc
- */
- public function import($oldID, array $data, array $additionalData = []) {
- $data['conversationID'] = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.conversation', $data['conversationID']);
- if (!$data['conversationID']) return 0;
- $data['userID'] = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.user', $data['userID']);
-
- // check existing message
- if (ctype_digit((string)$oldID)) {
- $existingMessage = new ConversationMessage($oldID);
- if (!$existingMessage->messageID) $data['messageID'] = $oldID;
- }
-
- $message = ConversationMessageEditor::create($data);
-
- ImportHandler::getInstance()->saveNewID('com.woltlab.wcf.conversation.message', $oldID, $message->messageID);
-
- return $message->messageID;
- }
+class ConversationMessageImporter extends AbstractImporter
+{
+ /**
+ * @inheritDoc
+ */
+ protected $className = ConversationMessage::class;
+
+ /**
+ * @inheritDoc
+ */
+ public function import($oldID, array $data, array $additionalData = [])
+ {
+ $data['conversationID'] = ImportHandler::getInstance()
+ ->getNewID('com.woltlab.wcf.conversation', $data['conversationID']);
+ if (!$data['conversationID']) {
+ return 0;
+ }
+ $data['userID'] = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.user', $data['userID']);
+
+ // check existing message
+ if (\ctype_digit((string)$oldID)) {
+ $existingMessage = new ConversationMessage($oldID);
+ if (!$existingMessage->messageID) {
+ $data['messageID'] = $oldID;
+ }
+ }
+
+ $message = ConversationMessageEditor::create($data);
+
+ ImportHandler::getInstance()->saveNewID('com.woltlab.wcf.conversation.message', $oldID, $message->messageID);
+
+ return $message->messageID;
+ }
}
<?php
+
namespace wcf\system\importer;
+
use wcf\system\WCF;
/**
* Imports conversation users.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Importer
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Importer
*/
-class ConversationUserImporter extends AbstractImporter {
- /**
- * @inheritDoc
- */
- public function import($oldID, array $data, array $additionalData = []) {
- $data['conversationID'] = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.conversation', $data['conversationID']);
- if (!$data['conversationID']) return 0;
- $data['participantID'] = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.user', $data['participantID']);
-
- $sql = "INSERT INTO wcf".WCF_N."_conversation_to_user
+class ConversationUserImporter extends AbstractImporter
+{
+ /**
+ * @inheritDoc
+ */
+ public function import($oldID, array $data, array $additionalData = [])
+ {
+ $data['conversationID'] = ImportHandler::getInstance()
+ ->getNewID('com.woltlab.wcf.conversation', $data['conversationID']);
+ if (!$data['conversationID']) {
+ return 0;
+ }
+ $data['participantID'] = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.user', $data['participantID']);
+
+ $sql = "INSERT INTO wcf" . WCF_N . "_conversation_to_user
(conversationID, participantID, username, hideConversation, isInvisible, lastVisitTime)
VALUES (?, ?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE hideConversation = IF(hideConversation > 0 AND hideConversation = VALUES(hideConversation),hideConversation,0),
isInvisible = IF(isInvisible AND VALUES(isInvisible),1,0),
lastVisitTime = GREATEST(lastVisitTime,VALUES(lastVisitTime))";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute([
- $data['conversationID'],
- $data['participantID'],
- $data['username'],
- $data['hideConversation'],
- $data['isInvisible'],
- $data['lastVisitTime']
- ]);
-
- // save labels
- if ($data['participantID'] && !empty($additionalData['labelIDs'])) {
- $sql = "INSERT IGNORE INTO wcf".WCF_N."_conversation_label_to_object
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute([
+ $data['conversationID'],
+ $data['participantID'],
+ $data['username'],
+ $data['hideConversation'],
+ $data['isInvisible'],
+ $data['lastVisitTime'],
+ ]);
+
+ // save labels
+ if ($data['participantID'] && !empty($additionalData['labelIDs'])) {
+ $sql = "INSERT IGNORE INTO wcf" . WCF_N . "_conversation_label_to_object
(labelID, conversationID)
VALUES (?, ?)";
- $statement = WCF::getDB()->prepareStatement($sql);
- foreach ($additionalData['labelIDs'] as $labelID) {
- $labelID = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.conversation.label', $labelID);
- if ($labelID) $statement->execute([$labelID, $data['conversationID']]);
- }
- }
-
- return 1;
- }
+ $statement = WCF::getDB()->prepareStatement($sql);
+ foreach ($additionalData['labelIDs'] as $labelID) {
+ $labelID = ImportHandler::getInstance()->getNewID('com.woltlab.wcf.conversation.label', $labelID);
+ if ($labelID) {
+ $statement->execute([$labelID, $data['conversationID']]);
+ }
+ }
+ }
+
+ return 1;
+ }
}
<?php
+
namespace wcf\system\log\modification;
+
use wcf\data\conversation\Conversation;
use wcf\data\user\User;
use wcf\data\user\UserList;
/**
* Handles conversation modification logs.
- *
- * @author Alexander Ebert
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Log\Modification
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Log\Modification
*/
-class ConversationModificationLogHandler extends VoidExtendedModificationLogHandler {
- /**
- * @inheritDoc
- */
- protected $objectTypeName = 'com.woltlab.wcf.conversation.conversation';
-
- /**
- * Adds a log entry for newly added conversation participants.
- *
- * @param Conversation $conversation
- * @param integer[] $participantIDs
- */
- public function addParticipants(Conversation $conversation, array $participantIDs) {
- $participants = [];
- $userList = new UserList();
- $userList->setObjectIDs($participantIDs);
- $userList->readObjects();
- foreach ($userList as $user) {
- $participants[] = [
- 'userID' => $user->userID,
- 'username' => $user->username
- ];
- }
-
- $this->add($conversation, 'addParticipants', [
- 'participants' => $participants
- ]);
- }
-
- /**
- * Adds a log entry for conversation close.
- *
- * @param Conversation $conversation
- */
- public function close(Conversation $conversation) {
- $this->add($conversation, 'close');
- }
-
- /**
- * Adds a log entry for conversation open.
- *
- * @param Conversation $conversation
- */
- public function open(Conversation $conversation) {
- $this->add($conversation, 'open');
- }
-
- /**
- * Adds a log entry for conversation leave.
- *
- * @param Conversation $conversation
- */
- public function leave(Conversation $conversation) {
- $this->add($conversation, 'leave');
- }
-
- /**
- * Adds a log entry for a removed participant.
- *
- * @param Conversation $conversation
- * @param integer $userID
- */
- public function removeParticipant(Conversation $conversation, $userID) {
- $user = new User($userID);
- $this->add($conversation, 'removeParticipant', [
- 'userID' => $userID,
- 'username' => $user->username
- ]);
- }
-
- /**
- * Adds a conversation modification log entry.
- *
- * @param Conversation $conversation
- * @param string $action
- * @param array $additionalData
- */
- public function add(Conversation $conversation, $action, array $additionalData = []) {
- $this->createLog($action, $conversation->conversationID, null, $additionalData);
- }
-
- /**
- * Removes the conversation log entries of the conversations with the given
- * ids.
- *
- * @param integer[] $objectIDs
- * @deprecated 3.0, use deleteLogs()
- */
- public function remove(array $objectIDs) {
- $this->deleteLogs($objectIDs);
- }
+class ConversationModificationLogHandler extends VoidExtendedModificationLogHandler
+{
+ /**
+ * @inheritDoc
+ */
+ protected $objectTypeName = 'com.woltlab.wcf.conversation.conversation';
+
+ /**
+ * Adds a log entry for newly added conversation participants.
+ *
+ * @param Conversation $conversation
+ * @param integer[] $participantIDs
+ */
+ public function addParticipants(Conversation $conversation, array $participantIDs)
+ {
+ $participants = [];
+ $userList = new UserList();
+ $userList->setObjectIDs($participantIDs);
+ $userList->readObjects();
+ foreach ($userList as $user) {
+ $participants[] = [
+ 'userID' => $user->userID,
+ 'username' => $user->username,
+ ];
+ }
+
+ $this->add($conversation, 'addParticipants', [
+ 'participants' => $participants,
+ ]);
+ }
+
+ /**
+ * Adds a log entry for conversation close.
+ *
+ * @param Conversation $conversation
+ */
+ public function close(Conversation $conversation)
+ {
+ $this->add($conversation, 'close');
+ }
+
+ /**
+ * Adds a log entry for conversation open.
+ *
+ * @param Conversation $conversation
+ */
+ public function open(Conversation $conversation)
+ {
+ $this->add($conversation, 'open');
+ }
+
+ /**
+ * Adds a log entry for conversation leave.
+ *
+ * @param Conversation $conversation
+ */
+ public function leave(Conversation $conversation)
+ {
+ $this->add($conversation, 'leave');
+ }
+
+ /**
+ * Adds a log entry for a removed participant.
+ *
+ * @param Conversation $conversation
+ * @param integer $userID
+ */
+ public function removeParticipant(Conversation $conversation, $userID)
+ {
+ $user = new User($userID);
+ $this->add($conversation, 'removeParticipant', [
+ 'userID' => $userID,
+ 'username' => $user->username,
+ ]);
+ }
+
+ /**
+ * Adds a conversation modification log entry.
+ *
+ * @param Conversation $conversation
+ * @param string $action
+ * @param array $additionalData
+ */
+ public function add(Conversation $conversation, $action, array $additionalData = [])
+ {
+ $this->createLog($action, $conversation->conversationID, null, $additionalData);
+ }
+
+ /**
+ * Removes the conversation log entries of the conversations with the given
+ * ids.
+ *
+ * @param integer[] $objectIDs
+ * @deprecated 3.0, use deleteLogs()
+ */
+ public function remove(array $objectIDs)
+ {
+ $this->deleteLogs($objectIDs);
+ }
}
<?php
+
namespace wcf\system\message\quote;
-use wcf\data\conversation\message\ConversationMessageList;
+
use wcf\data\conversation\ConversationList;
+use wcf\data\conversation\message\ConversationMessageList;
/**
* IMessageQuoteHandler implementation for conversation messages.
- *
- * @author Alexander Ebert
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Message\Quote
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Message\Quote
*/
-class ConversationMessageQuoteHandler extends AbstractMessageQuoteHandler {
- /**
- * @inheritDoc
- */
- protected function getMessages(array $data) {
- // read messages
- $messageList = new ConversationMessageList();
- $messageList->setObjectIDs(array_keys($data));
- $messageList->readObjects();
- $messages = $messageList->getObjects();
-
- // read conversations
- $conversationIDs = $validMessageIDs = [];
- foreach ($messages as $message) {
- $conversationIDs[] = $message->conversationID;
- $validMessageIDs[] = $message->messageID;
- }
-
- $quotedMessages = [];
- if (!empty($conversationIDs)) {
- $conversationList = new ConversationList();
- $conversationList->setObjectIDs($conversationIDs);
- $conversationList->readObjects();
- $conversations = $conversationList->getObjects();
-
- // create QuotedMessage objects
- foreach ($messages as $conversationMessage) {
- $conversationMessage->setConversation($conversations[$conversationMessage->conversationID]);
- $message = new QuotedMessage($conversationMessage);
-
- foreach (array_keys($data[$conversationMessage->messageID]) as $quoteID) {
- $message->addQuote(
- $quoteID,
- MessageQuoteManager::getInstance()->getQuote($quoteID, false), // single quote or excerpt
- MessageQuoteManager::getInstance()->getQuote($quoteID, true) // same as above or full quote
- );
- }
-
- $quotedMessages[] = $message;
- }
- }
-
- // check for orphaned quotes
- if (count($validMessageIDs) != count($data)) {
- $orphanedQuoteIDs = [];
- foreach ($data as $messageID => $quoteIDs) {
- if (!in_array($messageID, $validMessageIDs)) {
- foreach (array_keys($quoteIDs) as $quoteID) {
- $orphanedQuoteIDs[] = $quoteID;
- }
- }
- }
-
- MessageQuoteManager::getInstance()->removeOrphanedQuotes($orphanedQuoteIDs);
- }
-
- return $quotedMessages;
- }
+class ConversationMessageQuoteHandler extends AbstractMessageQuoteHandler
+{
+ /**
+ * @inheritDoc
+ */
+ protected function getMessages(array $data)
+ {
+ // read messages
+ $messageList = new ConversationMessageList();
+ $messageList->setObjectIDs(\array_keys($data));
+ $messageList->readObjects();
+ $messages = $messageList->getObjects();
+
+ // read conversations
+ $conversationIDs = $validMessageIDs = [];
+ foreach ($messages as $message) {
+ $conversationIDs[] = $message->conversationID;
+ $validMessageIDs[] = $message->messageID;
+ }
+
+ $quotedMessages = [];
+ if (!empty($conversationIDs)) {
+ $conversationList = new ConversationList();
+ $conversationList->setObjectIDs($conversationIDs);
+ $conversationList->readObjects();
+ $conversations = $conversationList->getObjects();
+
+ // create QuotedMessage objects
+ foreach ($messages as $conversationMessage) {
+ $conversationMessage->setConversation($conversations[$conversationMessage->conversationID]);
+ $message = new QuotedMessage($conversationMessage);
+
+ foreach (\array_keys($data[$conversationMessage->messageID]) as $quoteID) {
+ $message->addQuote(
+ $quoteID,
+ MessageQuoteManager::getInstance()->getQuote($quoteID, false), // single quote or excerpt
+ MessageQuoteManager::getInstance()->getQuote($quoteID, true) // same as above or full quote
+ );
+ }
+
+ $quotedMessages[] = $message;
+ }
+ }
+
+ // check for orphaned quotes
+ if (\count($validMessageIDs) != \count($data)) {
+ $orphanedQuoteIDs = [];
+ foreach ($data as $messageID => $quoteIDs) {
+ if (!\in_array($messageID, $validMessageIDs)) {
+ foreach (\array_keys($quoteIDs) as $quoteID) {
+ $orphanedQuoteIDs[] = $quoteID;
+ }
+ }
+ }
+
+ MessageQuoteManager::getInstance()->removeOrphanedQuotes($orphanedQuoteIDs);
+ }
+
+ return $quotedMessages;
+ }
}
<?php
+
namespace wcf\system\moderation\queue\report;
+
+use wcf\data\conversation\Conversation;
+use wcf\data\conversation\ConversationList;
use wcf\data\conversation\message\ConversationMessage;
use wcf\data\conversation\message\ConversationMessageAction;
use wcf\data\conversation\message\ConversationMessageList;
use wcf\data\conversation\message\ViewableConversationMessage;
-use wcf\data\conversation\Conversation;
-use wcf\data\conversation\ConversationList;
use wcf\data\moderation\queue\ModerationQueue;
use wcf\data\moderation\queue\ViewableModerationQueue;
use wcf\system\moderation\queue\AbstractModerationQueueHandler;
/**
* An implementation of IModerationQueueReportHandler for conversation messages.
- *
- * @author Alexander Ebert
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Moderation\Queue
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Moderation\Queue
*/
-class ConversationMessageModerationQueueReportHandler extends AbstractModerationQueueHandler implements IModerationQueueReportHandler {
- /**
- * @inheritDoc
- */
- protected $className = ConversationMessage::class;
-
- /**
- * @inheritDoc
- */
- protected $definitionName = 'com.woltlab.wcf.moderation.report';
-
- /**
- * @inheritDoc
- */
- protected $objectType = 'com.woltlab.wcf.conversation.message';
-
- /**
- * list of conversation message
- * @var ConversationMessage[]
- */
- protected static $messages = [];
-
- /**
- * @inheritDoc
- */
- protected $requiredPermission = 'mod.conversation.canModerateConversation';
-
- /**
- * @inheritDoc
- */
- public function assignQueues(array $queues) {
- $assignments = [];
- foreach ($queues as $queue) {
- $assignUser = false;
- if (WCF::getSession()->getPermission('mod.conversation.canModerateConversation')) {
- $assignUser = true;
- }
-
- $assignments[$queue->queueID] = $assignUser;
- }
-
- ModerationQueueManager::getInstance()->setAssignment($assignments);
- }
-
- /**
- * @inheritDoc
- */
- public function canReport($objectID) {
- if (!$this->isValid($objectID)) {
- return false;
- }
-
- if (!Conversation::isParticipant([$this->getMessage($objectID)->conversationID])) {
- return false;
- }
-
- return true;
- }
-
- /**
- * @inheritDoc
- */
- public function getContainerID($objectID) {
- return 0;
- }
-
- /**
- * @inheritDoc
- */
- public function getReportedContent(ViewableModerationQueue $queue) {
- /** @noinspection PhpParamsInspection */
- WCF::getTPL()->assign([
- 'message' => new ViewableConversationMessage($queue->getAffectedObject())
- ]);
-
- return WCF::getTPL()->fetch('moderationConversationMessage');
- }
-
- /**
- * @inheritDoc
- */
- public function getReportedObject($objectID) {
- if ($this->isValid($objectID)) {
- return $this->getMessage($objectID);
- }
-
- return null;
- }
-
- /**
- * @inheritDoc
- */
- public function isValid($objectID) {
- if ($this->getMessage($objectID) === null) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Returns a conversation message object by message id or null if message id is invalid.
- *
- * @param integer $objectID
- * @return ConversationMessage
- */
- protected function getMessage($objectID) {
- if (!array_key_exists($objectID, self::$messages)) {
- self::$messages[$objectID] = new ConversationMessage($objectID);
- if (!self::$messages[$objectID]->messageID) {
- self::$messages[$objectID] = null;
- }
- }
-
- return self::$messages[$objectID];
- }
-
- /**
- * @inheritDoc
- */
- public function populate(array $queues) {
- $objectIDs = [];
- foreach ($queues as $object) {
- $objectIDs[] = $object->objectID;
- }
-
- // fetch messages
- $messageList = new ConversationMessageList();
- $messageList->setObjectIDs($objectIDs);
- $messageList->readObjects();
- $messages = $messageList->getObjects();
-
- // set orphaned queues
- foreach ($queues as $queue) {
- if (!isset($messages[$queue->objectID])) {
- $queue->setIsOrphaned();
- }
- }
-
- // fetch conversations
- $conversationIDs = [];
- foreach ($messages as $message) {
- $conversationIDs[] = $message->conversationID;
- }
-
- if (!empty($conversationIDs)) {
- $conversationList = new ConversationList();
- $conversationList->setObjectIDs($conversationIDs);
- $conversationList->readObjects();
- $conversations = $conversationList->getObjects();
-
- foreach ($queues as $object) {
- if (isset($messages[$object->objectID])) {
- $message = $messages[$object->objectID];
- $message->setConversation($conversations[$message->conversationID]);
-
- $object->setAffectedObject($message);
- }
- }
- }
- }
-
- /**
- * @inheritDoc
- */
- public function removeContent(ModerationQueue $queue, $message) {
- if ($this->isValid($queue->objectID)) {
- $messageAction = new ConversationMessageAction([$this->getMessage($queue->objectID)], 'delete');
- $messageAction->executeAction();
- }
- }
+class ConversationMessageModerationQueueReportHandler extends AbstractModerationQueueHandler implements
+ IModerationQueueReportHandler
+{
+ /**
+ * @inheritDoc
+ */
+ protected $className = ConversationMessage::class;
+
+ /**
+ * @inheritDoc
+ */
+ protected $definitionName = 'com.woltlab.wcf.moderation.report';
+
+ /**
+ * @inheritDoc
+ */
+ protected $objectType = 'com.woltlab.wcf.conversation.message';
+
+ /**
+ * list of conversation message
+ * @var ConversationMessage[]
+ */
+ protected static $messages = [];
+
+ /**
+ * @inheritDoc
+ */
+ protected $requiredPermission = 'mod.conversation.canModerateConversation';
+
+ /**
+ * @inheritDoc
+ */
+ public function assignQueues(array $queues)
+ {
+ $assignments = [];
+ foreach ($queues as $queue) {
+ $assignUser = false;
+ if (WCF::getSession()->getPermission('mod.conversation.canModerateConversation')) {
+ $assignUser = true;
+ }
+
+ $assignments[$queue->queueID] = $assignUser;
+ }
+
+ ModerationQueueManager::getInstance()->setAssignment($assignments);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function canReport($objectID)
+ {
+ if (!$this->isValid($objectID)) {
+ return false;
+ }
+
+ if (!Conversation::isParticipant([$this->getMessage($objectID)->conversationID])) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getContainerID($objectID)
+ {
+ return 0;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getReportedContent(ViewableModerationQueue $queue)
+ {
+ /** @noinspection PhpParamsInspection */
+ WCF::getTPL()->assign([
+ 'message' => new ViewableConversationMessage($queue->getAffectedObject()),
+ ]);
+
+ return WCF::getTPL()->fetch('moderationConversationMessage');
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getReportedObject($objectID)
+ {
+ if ($this->isValid($objectID)) {
+ return $this->getMessage($objectID);
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function isValid($objectID)
+ {
+ if ($this->getMessage($objectID) === null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns a conversation message object by message id or null if message id is invalid.
+ *
+ * @param integer $objectID
+ * @return ConversationMessage
+ */
+ protected function getMessage($objectID)
+ {
+ if (!\array_key_exists($objectID, self::$messages)) {
+ self::$messages[$objectID] = new ConversationMessage($objectID);
+ if (!self::$messages[$objectID]->messageID) {
+ self::$messages[$objectID] = null;
+ }
+ }
+
+ return self::$messages[$objectID];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function populate(array $queues)
+ {
+ $objectIDs = [];
+ foreach ($queues as $object) {
+ $objectIDs[] = $object->objectID;
+ }
+
+ // fetch messages
+ $messageList = new ConversationMessageList();
+ $messageList->setObjectIDs($objectIDs);
+ $messageList->readObjects();
+ $messages = $messageList->getObjects();
+
+ // set orphaned queues
+ foreach ($queues as $queue) {
+ if (!isset($messages[$queue->objectID])) {
+ $queue->setIsOrphaned();
+ }
+ }
+
+ // fetch conversations
+ $conversationIDs = [];
+ foreach ($messages as $message) {
+ $conversationIDs[] = $message->conversationID;
+ }
+
+ if (!empty($conversationIDs)) {
+ $conversationList = new ConversationList();
+ $conversationList->setObjectIDs($conversationIDs);
+ $conversationList->readObjects();
+ $conversations = $conversationList->getObjects();
+
+ foreach ($queues as $object) {
+ if (isset($messages[$object->objectID])) {
+ $message = $messages[$object->objectID];
+ $message->setConversation($conversations[$message->conversationID]);
+
+ $object->setAffectedObject($message);
+ }
+ }
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function removeContent(ModerationQueue $queue, $message)
+ {
+ if ($this->isValid($queue->objectID)) {
+ $messageAction = new ConversationMessageAction([$this->getMessage($queue->objectID)], 'delete');
+ $messageAction->executeAction();
+ }
+ }
}
<?php
+
namespace wcf\system\page\handler;
+
use wcf\system\conversation\ConversationHandler;
use wcf\system\WCF;
/**
* Page handler implementation for the conversation list.
*
- * @author Matthias Schmidt
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Page\Handler
- * @since 3.0
+ * @author Matthias Schmidt
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Page\Handler
+ * @since 3.0
*/
-class ConversationListPageHandler extends AbstractMenuPageHandler {
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function getOutstandingItemCount($objectID = null) {
- return ConversationHandler::getInstance()->getUnreadConversationCount();
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function isVisible($objectID = null) {
- return WCF::getUser()->userID != 0;
- }
+class ConversationListPageHandler extends AbstractMenuPageHandler
+{
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function getOutstandingItemCount($objectID = null)
+ {
+ return ConversationHandler::getInstance()->getUnreadConversationCount();
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function isVisible($objectID = null)
+ {
+ return WCF::getUser()->userID != 0;
+ }
}
<?php
+
namespace wcf\system\page\handler;
/**
* Default implementation of a board-related page handler.
- *
+ *
* Only use this class when you need the online location handling for a board-related page.
*
- * @author Matthias Schmidt
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Page\Handler
- * @since 3.0
+ * @author Matthias Schmidt
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Page\Handler
+ * @since 3.0
*/
-class DefaultConversationRelatedPageHandler extends AbstractMenuPageHandler implements IOnlineLocationPageHandler {
- use TConversationOnlineLocationPageHandler;
+class DefaultConversationRelatedPageHandler extends AbstractMenuPageHandler implements IOnlineLocationPageHandler
+{
+ use TConversationOnlineLocationPageHandler;
}
<?php
+
namespace wcf\system\page\handler;
+
use wcf\data\conversation\Conversation;
use wcf\data\page\Page;
use wcf\data\user\online\UserOnline;
/**
* Implementation of the online location-related page handler methods for conversations.
- *
- * @author Matthias Schmidt
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Page\Handler
- * @since 3.0
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Page\Handler
+ * @since 3.0
*/
-trait TConversationOnlineLocationPageHandler {
- use TOnlineLocationPageHandler;
-
- /**
- * Returns the textual description if a user is currently online viewing this page.
- *
- * @see IOnlineLocationPageHandler::getOnlineLocation()
- *
- * @param Page $page visited page
- * @param UserOnline $user user online object with request data
- * @return string
- */
- public function getOnlineLocation(Page $page, UserOnline $user) {
- if ($user->pageObjectID === null) {
- return '';
- }
-
- $conversation = UserConversationRuntimeCache::getInstance()->getObject($user->pageObjectID);
- if ($conversation === null || !$conversation->canRead()) {
- return '';
- }
-
- if ($conversation->userID != WCF::getUser()->userID && $user->userID != WCF::getUser()->userID) {
- // Make sure that requests from invisible participants are not listed
- // if the active user is not the author of the conversation.
- $userConversation = Conversation::getUserConversation($conversation->conversationID, $user->userID);
- if ($userConversation !== null && $userConversation->isInvisible) {
- return '';
- }
- }
-
- return WCF::getLanguage()->getDynamicVariable('wcf.page.onlineLocation.'.$page->identifier, ['conversation' => $conversation]);
- }
-
- /**
- * Prepares fetching all necessary data for the textual description if a user is currently online
- * viewing this page.
- *
- * @see IOnlineLocationPageHandler::prepareOnlineLocation()
- *
- * @param Page $page visited page
- * @param UserOnline $user user online object with request data
- */
- public function prepareOnlineLocation(/** @noinspection PhpUnusedParameterInspection */Page $page, UserOnline $user) {
- if ($user->pageObjectID !== null) {
- UserConversationRuntimeCache::getInstance()->cacheObjectID($user->pageObjectID);
- }
- }
+trait TConversationOnlineLocationPageHandler
+{
+ use TOnlineLocationPageHandler;
+
+ /**
+ * Returns the textual description if a user is currently online viewing this page.
+ *
+ * @param Page $page visited page
+ * @param UserOnline $user user online object with request data
+ * @return string
+ * @see IOnlineLocationPageHandler::getOnlineLocation()
+ *
+ */
+ public function getOnlineLocation(Page $page, UserOnline $user)
+ {
+ if ($user->pageObjectID === null) {
+ return '';
+ }
+
+ $conversation = UserConversationRuntimeCache::getInstance()->getObject($user->pageObjectID);
+ if ($conversation === null || !$conversation->canRead()) {
+ return '';
+ }
+
+ if ($conversation->userID != WCF::getUser()->userID && $user->userID != WCF::getUser()->userID) {
+ // Make sure that requests from invisible participants are not listed
+ // if the active user is not the author of the conversation.
+ $userConversation = Conversation::getUserConversation($conversation->conversationID, $user->userID);
+ if ($userConversation !== null && $userConversation->isInvisible) {
+ return '';
+ }
+ }
+
+ return WCF::getLanguage()->getDynamicVariable(
+ 'wcf.page.onlineLocation.' . $page->identifier,
+ ['conversation' => $conversation]
+ );
+ }
+
+ /**
+ * Prepares fetching all necessary data for the textual description if a user is currently online
+ * viewing this page.
+ *
+ * @param Page $page visited page
+ * @param UserOnline $user user online object with request data
+ * @see IOnlineLocationPageHandler::prepareOnlineLocation()
+ * @noinspection PhpUnusedParameterInspection
+ */
+ public function prepareOnlineLocation(
+ Page $page,
+ UserOnline $user
+ ) {
+ if ($user->pageObjectID !== null) {
+ UserConversationRuntimeCache::getInstance()->cacheObjectID($user->pageObjectID);
+ }
+ }
}
<?php
+
namespace wcf\system\search;
+
+use wcf\data\conversation\Conversation;
use wcf\data\conversation\message\SearchResultConversationMessage;
use wcf\data\conversation\message\SearchResultConversationMessageList;
-use wcf\data\conversation\Conversation;
use wcf\form\IForm;
use wcf\form\SearchForm;
use wcf\system\database\util\PreparedStatementConditionBuilder;
/**
* An implementation of ISearchableObjectType for searching in conversations.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Search
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Search
*/
-class ConversationMessageSearch extends AbstractSearchableObjectType {
- /**
- * id of the searched conversation
- * @var integer
- */
- public $conversationID = 0;
-
- /**
- * searched conversation
- * @var Conversation
- */
- public $conversation;
-
- /**
- * message data cache
- * @var SearchResultConversationMessage[]
- */
- public $messageCache = [];
-
- /**
- * @inheritDoc
- */
- public function cacheObjects(array $objectIDs, array $additionalData = null) {
- $messageList = new SearchResultConversationMessageList();
- $messageList->setObjectIDs($objectIDs);
- $messageList->readObjects();
- foreach ($messageList->getObjects() as $message) {
- $this->messageCache[$message->messageID] = $message;
- }
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function getAdditionalData() {
- return [
- 'conversationID' => $this->conversationID
- ];
- }
-
- /**
- * @inheritDoc
- */
- public function getObject($objectID) {
- if (isset($this->messageCache[$objectID])) return $this->messageCache[$objectID];
- return null;
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function getJoins() {
- return "JOIN wcf".WCF_N."_conversation_to_user conversation_to_user ON (conversation_to_user.participantID = ".WCF::getUser()->userID." AND conversation_to_user.conversationID = ".$this->getTableName().".conversationID)
- LEFT JOIN wcf".WCF_N."_conversation conversation ON (conversation.conversationID = ".$this->getTableName().".conversationID)";
- }
-
- /**
- * @inheritDoc
- */
- public function getTableName() {
- return 'wcf'.WCF_N.'_conversation_message';
- }
-
- /**
- * @inheritDoc
- */
- public function getIDFieldName() {
- return $this->getTableName().'.messageID';
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function getSubjectFieldName() {
- return 'conversation.subject';
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function getConditions(IForm $form = null) {
- $conditionBuilder = new PreparedStatementConditionBuilder();
- $conditionBuilder->add('conversation_to_user.hideConversation IN (0,1)');
-
- if (isset($_POST['conversationID'])) {
- $this->conversationID = intval($_POST['conversationID']);
-
- $conditionBuilder->add('conversation.conversationID = ?', [$this->conversationID]);
- }
-
- return $conditionBuilder;
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function isAccessible() {
- return (WCF::getUser()->userID ? true : false) && MODULE_CONVERSATION && WCF::getSession()->getPermission('user.conversation.canUseConversation');
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function getFormTemplateName() {
- if ($this->conversation) {
- return 'searchConversationMessage';
- }
-
- return null;
- }
-
- /**
- * @inheritDoc
- */
- public function show(IForm $form = null) {
- /** @var SearchForm $form */
-
- // get existing values
- if ($form !== null && isset($form->searchData['additionalData']['com.woltlab.wcf.conversation.message']['conversationID'])) {
- $this->conversationID = $form->searchData['additionalData']['com.woltlab.wcf.conversation.message']['conversationID'];
-
- if ($this->conversationID) {
- $this->conversation = Conversation::getUserConversation($this->conversationID, WCF::getUser()->userID);
-
- if ($this->conversation === null || !$this->conversation->canRead()) {
- $this->conversationID = 0;
- $this->conversation = null;
- }
- }
- }
-
- WCF::getTPL()->assign('searchedConversation', $this->conversation);
- }
+class ConversationMessageSearch extends AbstractSearchableObjectType
+{
+ /**
+ * id of the searched conversation
+ * @var integer
+ */
+ public $conversationID = 0;
+
+ /**
+ * searched conversation
+ * @var Conversation
+ */
+ public $conversation;
+
+ /**
+ * message data cache
+ * @var SearchResultConversationMessage[]
+ */
+ public $messageCache = [];
+
+ /**
+ * @inheritDoc
+ */
+ public function cacheObjects(array $objectIDs, ?array $additionalData = null)
+ {
+ $messageList = new SearchResultConversationMessageList();
+ $messageList->setObjectIDs($objectIDs);
+ $messageList->readObjects();
+ foreach ($messageList->getObjects() as $message) {
+ $this->messageCache[$message->messageID] = $message;
+ }
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function getAdditionalData()
+ {
+ return [
+ 'conversationID' => $this->conversationID,
+ ];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getObject($objectID)
+ {
+ if (isset($this->messageCache[$objectID])) {
+ return $this->messageCache[$objectID];
+ }
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function getJoins()
+ {
+ return "JOIN wcf" . WCF_N . "_conversation_to_user conversation_to_user ON (conversation_to_user.participantID = " . WCF::getUser()->userID . " AND conversation_to_user.conversationID = " . $this->getTableName() . ".conversationID)
+ LEFT JOIN wcf" . WCF_N . "_conversation conversation ON (conversation.conversationID = " . $this->getTableName() . ".conversationID)";
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getTableName()
+ {
+ return 'wcf' . WCF_N . '_conversation_message';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getIDFieldName()
+ {
+ return $this->getTableName() . '.messageID';
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function getSubjectFieldName()
+ {
+ return 'conversation.subject';
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function getConditions(?IForm $form = null)
+ {
+ $conditionBuilder = new PreparedStatementConditionBuilder();
+ $conditionBuilder->add('conversation_to_user.hideConversation IN (0,1)');
+
+ if (isset($_POST['conversationID'])) {
+ $this->conversationID = \intval($_POST['conversationID']);
+
+ $conditionBuilder->add('conversation.conversationID = ?', [$this->conversationID]);
+ }
+
+ return $conditionBuilder;
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function isAccessible()
+ {
+ if (!WCF::getUser()->userID) {
+ return false;
+ }
+ if (!MODULE_CONVERSATION) {
+ return false;
+ }
+
+ return WCF::getSession()->getPermission('user.conversation.canUseConversation');
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function getFormTemplateName()
+ {
+ if ($this->conversation) {
+ return 'searchConversationMessage';
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function show(?IForm $form = null)
+ {
+ /** @var SearchForm $form */
+
+ // get existing values
+ if (
+ $form !== null
+ && isset($form->searchData['additionalData']['com.woltlab.wcf.conversation.message']['conversationID'])
+ ) {
+ $this->conversationID = $form->searchData['additionalData']['com.woltlab.wcf.conversation.message']['conversationID'];
+
+ if ($this->conversationID) {
+ $this->conversation = Conversation::getUserConversation($this->conversationID, WCF::getUser()->userID);
+
+ if ($this->conversation === null || !$this->conversation->canRead()) {
+ $this->conversationID = 0;
+ $this->conversation = null;
+ }
+ }
+ }
+
+ WCF::getTPL()->assign('searchedConversation', $this->conversation);
+ }
}
<?php
+
namespace wcf\system\stat;
/**
* Stat handler implementation for conversation messages.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Stat
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Stat
*/
-class ConversationMessageStatDailyHandler extends AbstractStatDailyHandler {
- /**
- * @inheritDoc
- */
- public function getData($date) {
- return [
- 'counter' => $this->getCounter($date, 'wcf'.WCF_N.'_conversation_message', 'time'),
- 'total' => $this->getTotal($date, 'wcf'.WCF_N.'_conversation_message', 'time')
- ];
- }
+class ConversationMessageStatDailyHandler extends AbstractStatDailyHandler
+{
+ /**
+ * @inheritDoc
+ */
+ public function getData($date)
+ {
+ return [
+ 'counter' => $this->getCounter($date, 'wcf' . WCF_N . '_conversation_message', 'time'),
+ 'total' => $this->getTotal($date, 'wcf' . WCF_N . '_conversation_message', 'time'),
+ ];
+ }
}
<?php
+
namespace wcf\system\stat;
/**
* Stat handler implementation for conversations.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Stat
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Stat
*/
-class ConversationStatDailyHandler extends AbstractStatDailyHandler {
- /**
- * @inheritDoc
- */
- public function getData($date) {
- return [
- 'counter' => $this->getCounter($date, 'wcf'.WCF_N.'_conversation', 'time'),
- 'total' => $this->getTotal($date, 'wcf'.WCF_N.'_conversation', 'time')
- ];
- }
+class ConversationStatDailyHandler extends AbstractStatDailyHandler
+{
+ /**
+ * @inheritDoc
+ */
+ public function getData($date)
+ {
+ return [
+ 'counter' => $this->getCounter($date, 'wcf' . WCF_N . '_conversation', 'time'),
+ 'total' => $this->getTotal($date, 'wcf' . WCF_N . '_conversation', 'time'),
+ ];
+ }
}
<?php
+
namespace wcf\system\user\content\provider;
+
use wcf\data\conversation\message\ConversationMessage;
/**
* User content provider for conversation messages.
*
- * @author Joshua Ruesweg
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Content\Provider
- * @since 5.2
+ * @author Joshua Ruesweg
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\User\Content\Provider
+ * @since 5.2
*/
-class ConversationMessageUserContentProvider extends AbstractDatabaseUserContentProvider {
- /**
- * @inheritdoc
- */
- public static function getDatabaseObjectClass() {
- return ConversationMessage::class;
- }
+class ConversationMessageUserContentProvider extends AbstractDatabaseUserContentProvider
+{
+ /**
+ * @inheritdoc
+ */
+ public static function getDatabaseObjectClass()
+ {
+ return ConversationMessage::class;
+ }
}
<?php
+
namespace wcf\system\user\content\provider;
+
use wcf\data\conversation\Conversation;
/**
* User content provider for conversations.
*
- * @author Joshua Ruesweg
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Content\Provider
- * @since 5.2
+ * @author Joshua Ruesweg
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\User\Content\Provider
+ * @since 5.2
*/
-class ConversationUserContentProvider extends AbstractDatabaseUserContentProvider {
- /**
- * @inheritdoc
- */
- public static function getDatabaseObjectClass() {
- return Conversation::class;
- }
+class ConversationUserContentProvider extends AbstractDatabaseUserContentProvider
+{
+ /**
+ * @inheritdoc
+ */
+ public static function getDatabaseObjectClass()
+ {
+ return Conversation::class;
+ }
}
<?php
+
namespace wcf\system\user\notification\event;
+
use wcf\data\user\UserProfile;
use wcf\system\email\Email;
use wcf\system\user\notification\object\ConversationMessageUserNotificationObject;
/**
* User notification event for conversation messages.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Notification\Event
- *
- * @method ConversationMessageUserNotificationObject getUserNotificationObject()
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\User\Notification\Event
+ *
+ * @method ConversationMessageUserNotificationObject getUserNotificationObject()
*/
-class ConversationMessageUserNotificationEvent extends AbstractUserNotificationEvent implements ITestableUserNotificationEvent {
- use TTestableConversationRelatedUserNotificationEvent;
- use TTestableUserNotificationEvent;
-
- /**
- * @inheritDoc
- */
- protected $stackable = true;
-
- /**
- * @inheritDoc
- */
- public function getTitle() {
- $count = count($this->getAuthors());
- if ($count > 1) {
- return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.message.title.stacked', ['count' => $count]);
- }
-
- return $this->getLanguage()->get('wcf.user.notification.conversation.message.title');
- }
-
- /**
- * @inheritDoc
- */
- public function getMessage() {
- $authors = array_values($this->getAuthors());
- $count = count($authors);
-
- if ($count > 1) {
- return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.message.message.stacked', [
- 'author' => $this->author,
- 'authors' => $authors,
- 'count' => $count,
- 'message' => $this->userNotificationObject,
- 'others' => $count - 1
- ]);
- }
-
- return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.message.message', [
- 'author' => $this->author,
- 'message' => $this->userNotificationObject
- ]);
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function getEmailMessage($notificationType = 'instant') {
- $messageID = '<com.woltlab.wcf.conversation.notification/'.$this->getUserNotificationObject()->getConversation()->conversationID.'@'.Email::getHost().'>';
-
- return [
- 'template' => 'email_notification_conversationMessage',
- 'application' => 'wcf',
- 'in-reply-to' => [$messageID],
- 'references' => [$messageID]
- ];
- }
-
- /**
- * @inheritDoc
- * @since 5.2
- */
- public function getEmailTitle() {
- if (count($this->getAuthors()) > 1) {
- return parent::getEmailTitle();
- }
-
- return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.message.mail.title', [
- 'author' => $this->author,
- 'message' => $this->userNotificationObject
- ]);
- }
-
- /**
- * @inheritDoc
- */
- public function getLink() {
- return $this->getUserNotificationObject()->getLink();
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function getEventHash() {
- return sha1($this->eventID . '-' . $this->getUserNotificationObject()->conversationID);
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function checkAccess() {
- return $this->getUserNotificationObject()->getConversation()->canRead();
- }
-
- /**
- * @inheritDoc
- */
- public static function getTestObjects(UserProfile $recipient, UserProfile $author) {
- return [new ConversationMessageUserNotificationObject(self::createTestConversationMessage($recipient, $author))];
- }
+class ConversationMessageUserNotificationEvent extends AbstractUserNotificationEvent implements
+ ITestableUserNotificationEvent
+{
+ use TTestableConversationRelatedUserNotificationEvent;
+ use TTestableUserNotificationEvent;
+
+ /**
+ * @inheritDoc
+ */
+ protected $stackable = true;
+
+ /**
+ * @inheritDoc
+ */
+ public function getTitle()
+ {
+ $count = \count($this->getAuthors());
+ if ($count > 1) {
+ return $this->getLanguage()->getDynamicVariable(
+ 'wcf.user.notification.conversation.message.title.stacked',
+ ['count' => $count]
+ );
+ }
+
+ return $this->getLanguage()->get('wcf.user.notification.conversation.message.title');
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getMessage()
+ {
+ $authors = \array_values($this->getAuthors());
+ $count = \count($authors);
+
+ if ($count > 1) {
+ return $this->getLanguage()->getDynamicVariable(
+ 'wcf.user.notification.conversation.message.message.stacked',
+ [
+ 'author' => $this->author,
+ 'authors' => $authors,
+ 'count' => $count,
+ 'message' => $this->userNotificationObject,
+ 'others' => $count - 1,
+ ]
+ );
+ }
+
+ return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.message.message', [
+ 'author' => $this->author,
+ 'message' => $this->userNotificationObject,
+ ]);
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function getEmailMessage($notificationType = 'instant')
+ {
+ $messageID = '<com.woltlab.wcf.conversation.notification/' . $this->getUserNotificationObject()->getConversation()->conversationID . '@' . Email::getHost() . '>';
+
+ return [
+ 'template' => 'email_notification_conversationMessage',
+ 'application' => 'wcf',
+ 'in-reply-to' => [$messageID],
+ 'references' => [$messageID],
+ ];
+ }
+
+ /**
+ * @inheritDoc
+ * @since 5.2
+ */
+ public function getEmailTitle()
+ {
+ if (\count($this->getAuthors()) > 1) {
+ return parent::getEmailTitle();
+ }
+
+ return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.message.mail.title', [
+ 'author' => $this->author,
+ 'message' => $this->userNotificationObject,
+ ]);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getLink()
+ {
+ return $this->getUserNotificationObject()->getLink();
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function getEventHash()
+ {
+ return \sha1($this->eventID . '-' . $this->getUserNotificationObject()->conversationID);
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function checkAccess()
+ {
+ return $this->getUserNotificationObject()->getConversation()->canRead();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public static function getTestObjects(UserProfile $recipient, UserProfile $author)
+ {
+ return [
+ new ConversationMessageUserNotificationObject(self::createTestConversationMessage($recipient, $author)),
+ ];
+ }
}
<?php
+
namespace wcf\system\user\notification\event;
+
use wcf\data\user\UserProfile;
use wcf\system\user\notification\object\ConversationUserNotificationObject;
/**
* User notification event for conversations.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Notification\Event
- *
- * @method ConversationUserNotificationObject getUserNotificationObject()
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\User\Notification\Event
+ *
+ * @method ConversationUserNotificationObject getUserNotificationObject()
*/
-class ConversationUserNotificationEvent extends AbstractUserNotificationEvent implements ITestableUserNotificationEvent {
- use TTestableConversationRelatedUserNotificationEvent;
- use TTestableUserNotificationEvent;
-
- /**
- * @inheritDoc
- */
- public function getTitle() {
- return $this->getLanguage()->get('wcf.user.notification.conversation.title');
- }
-
- /**
- * @inheritDoc
- */
- public function getMessage() {
- return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.message', [
- 'author' => $this->author,
- 'conversation' => $this->userNotificationObject
- ]);
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function getEmailMessage($notificationType = 'instant') {
- return [
- 'message-id' => 'com.woltlab.wcf.conversation.notification/'.$this->getUserNotificationObject()->conversationID,
- 'template' => 'email_notification_conversation',
- 'application' => 'wcf'
- ];
- }
-
- /**
- * @inheritDoc
- * @since 5.2
- */
- public function getEmailTitle() {
- return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.mail.title', [
- 'author' => $this->author,
- 'conversation' => $this->userNotificationObject
- ]);
- }
-
- /**
- * @inheritDoc
- */
- public function getLink() {
- return $this->getUserNotificationObject()->getLink();
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function checkAccess() {
- return $this->getUserNotificationObject()->canRead();
- }
-
- /**
- * @inheritDoc
- */
- public static function getTestObjects(UserProfile $recipient, UserProfile $author) {
- return [new ConversationUserNotificationObject(self::createTestConversation($author, $recipient))];
- }
+class ConversationUserNotificationEvent extends AbstractUserNotificationEvent implements ITestableUserNotificationEvent
+{
+ use TTestableConversationRelatedUserNotificationEvent;
+ use TTestableUserNotificationEvent;
+
+ /**
+ * @inheritDoc
+ */
+ public function getTitle()
+ {
+ return $this->getLanguage()->get('wcf.user.notification.conversation.title');
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getMessage()
+ {
+ return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.message', [
+ 'author' => $this->author,
+ 'conversation' => $this->userNotificationObject,
+ ]);
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function getEmailMessage($notificationType = 'instant')
+ {
+ return [
+ 'message-id' => 'com.woltlab.wcf.conversation.notification/' . $this->getUserNotificationObject()->conversationID,
+ 'template' => 'email_notification_conversation',
+ 'application' => 'wcf',
+ ];
+ }
+
+ /**
+ * @inheritDoc
+ * @since 5.2
+ */
+ public function getEmailTitle()
+ {
+ return $this->getLanguage()->getDynamicVariable('wcf.user.notification.conversation.mail.title', [
+ 'author' => $this->author,
+ 'conversation' => $this->userNotificationObject,
+ ]);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getLink()
+ {
+ return $this->getUserNotificationObject()->getLink();
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function checkAccess()
+ {
+ return $this->getUserNotificationObject()->canRead();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public static function getTestObjects(UserProfile $recipient, UserProfile $author)
+ {
+ return [new ConversationUserNotificationObject(self::createTestConversation($author, $recipient))];
+ }
}
<?php
+
namespace wcf\system\user\notification\event;
-use wcf\data\conversation\message\ConversationMessage;
-use wcf\data\conversation\message\ConversationMessageAction;
+
use wcf\data\conversation\Conversation;
use wcf\data\conversation\ConversationAction;
+use wcf\data\conversation\message\ConversationMessage;
+use wcf\data\conversation\message\ConversationMessageAction;
use wcf\data\user\UserProfile;
/**
* Provides methods to create conversations and conversation messages for testing
* user notification events.
*
- * @author Matthias Schmidt
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Notification\Event
- * @since 3.1
+ * @author Matthias Schmidt
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\User\Notification\Event
+ * @since 3.1
*/
-trait TTestableConversationRelatedUserNotificationEvent {
- /**
- * Creates a conversation for testing.
- *
- * @param UserProfile $conversationAuthor
- * @param UserProfile $participant
- * @return Conversation
- */
- public static function createTestConversation(UserProfile $conversationAuthor, UserProfile $participant) {
- return (new ConversationAction([], 'create', [
- 'data' => [
- 'subject' => 'Test Conversation Subject',
- 'time' => TIME_NOW,
- 'userID' => $conversationAuthor->userID,
- 'username' => $conversationAuthor->username
- ],
- 'messageData' => [
- 'message' => 'Test Conversation Message'
- ],
- 'participants' => [$participant->userID]
- ]))->executeAction()['returnValues'];
- }
-
- /**
- * Creates a conversation message for testing.
- *
- * @param UserProfile $conversationAuthor
- * @param UserProfile $messageAuthor
- * @return ConversationMessage
- */
- public static function createTestConversationMessage(UserProfile $conversationAuthor, UserProfile $messageAuthor) {
- $conversation = self::createTestConversation($conversationAuthor, $messageAuthor);
-
- return (new ConversationMessageAction([], 'create', [
- 'data' => [
- 'conversationID' => $conversation->conversationID,
- 'message' => 'Test Conversation Message Message',
- 'time' => TIME_NOW,
- 'userID' => $messageAuthor->userID,
- 'username' => $messageAuthor->username
- ],
- 'conversation' => $conversation
- ]))->executeAction()['returnValues'];
- }
+trait TTestableConversationRelatedUserNotificationEvent
+{
+ /**
+ * Creates a conversation for testing.
+ *
+ * @param UserProfile $conversationAuthor
+ * @param UserProfile $participant
+ * @return Conversation
+ */
+ public static function createTestConversation(UserProfile $conversationAuthor, UserProfile $participant)
+ {
+ return (new ConversationAction([], 'create', [
+ 'data' => [
+ 'subject' => 'Test Conversation Subject',
+ 'time' => TIME_NOW,
+ 'userID' => $conversationAuthor->userID,
+ 'username' => $conversationAuthor->username,
+ ],
+ 'messageData' => [
+ 'message' => 'Test Conversation Message',
+ ],
+ 'participants' => [$participant->userID],
+ ]))->executeAction()['returnValues'];
+ }
+
+ /**
+ * Creates a conversation message for testing.
+ *
+ * @param UserProfile $conversationAuthor
+ * @param UserProfile $messageAuthor
+ * @return ConversationMessage
+ */
+ public static function createTestConversationMessage(UserProfile $conversationAuthor, UserProfile $messageAuthor)
+ {
+ $conversation = self::createTestConversation($conversationAuthor, $messageAuthor);
+
+ return (new ConversationMessageAction([], 'create', [
+ 'data' => [
+ 'conversationID' => $conversation->conversationID,
+ 'message' => 'Test Conversation Message Message',
+ 'time' => TIME_NOW,
+ 'userID' => $messageAuthor->userID,
+ 'username' => $messageAuthor->username,
+ ],
+ 'conversation' => $conversation,
+ ]))->executeAction()['returnValues'];
+ }
}
<?php
+
namespace wcf\system\user\notification\object;
+
use wcf\data\conversation\message\ConversationMessage;
use wcf\data\DatabaseObjectDecorator;
/**
* Notification object for conversations.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Notification\Object
*
- * @method ConversationMessage getDecoratedObject()
- * @mixin ConversationMessage
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\User\Notification\Object
+ *
+ * @method ConversationMessage getDecoratedObject()
+ * @mixin ConversationMessage
*/
-class ConversationMessageUserNotificationObject extends DatabaseObjectDecorator implements IUserNotificationObject {
- /**
- * @inheritDoc
- */
- protected static $baseClass = ConversationMessage::class;
-
- /**
- * @inheritDoc
- */
- public function getTitle() {
- return $this->getConversation()->subject;
- }
-
- /**
- * @inheritDoc
- */
- public function getURL() {
- return $this->getLink();
- }
-
- /**
- * @inheritDoc
- */
- public function getAuthorID() {
- return $this->userID;
- }
+class ConversationMessageUserNotificationObject extends DatabaseObjectDecorator implements IUserNotificationObject
+{
+ /**
+ * @inheritDoc
+ */
+ protected static $baseClass = ConversationMessage::class;
+
+ /**
+ * @inheritDoc
+ */
+ public function getTitle()
+ {
+ return $this->getConversation()->subject;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getURL()
+ {
+ return $this->getLink();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getAuthorID()
+ {
+ return $this->userID;
+ }
}
<?php
+
namespace wcf\system\user\notification\object;
+
use wcf\data\conversation\Conversation;
use wcf\data\DatabaseObjectDecorator;
/**
* Notification object for conversations.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Notification\Object
- *
- * @method Conversation getDecoratedObject()
- * @mixin Conversation
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\User\Notification\Object
+ *
+ * @method Conversation getDecoratedObject()
+ * @mixin Conversation
*/
-class ConversationUserNotificationObject extends DatabaseObjectDecorator implements IUserNotificationObject {
- /**
- * @inheritDoc
- */
- protected static $baseClass = Conversation::class;
-
- /**
- * @inheritDoc
- */
- public function getTitle() {
- return $this->subject;
- }
-
- /**
- * @inheritDoc
- */
- public function getURL() {
- return $this->getLink();
- }
-
- /**
- * @inheritDoc
- */
- public function getAuthorID() {
- return $this->userID;
- }
+class ConversationUserNotificationObject extends DatabaseObjectDecorator implements IUserNotificationObject
+{
+ /**
+ * @inheritDoc
+ */
+ protected static $baseClass = Conversation::class;
+
+ /**
+ * @inheritDoc
+ */
+ public function getTitle()
+ {
+ return $this->subject;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getURL()
+ {
+ return $this->getLink();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getAuthorID()
+ {
+ return $this->userID;
+ }
}
<?php
+
namespace wcf\system\user\notification\object\type;
+
use wcf\data\conversation\message\ConversationMessage;
use wcf\data\conversation\message\ConversationMessageList;
use wcf\system\user\notification\object\ConversationMessageUserNotificationObject;
/**
* Represents a conversation message notification object type.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Notification\Object\Type
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\User\Notification\Object\Type
*/
-class ConversationMessageNotificationObjectType extends AbstractUserNotificationObjectType {
- /**
- * @inheritDoc
- */
- protected static $decoratorClassName = ConversationMessageUserNotificationObject::class;
-
- /**
- * @inheritDoc
- */
- protected static $objectClassName = ConversationMessage::class;
-
- /**
- * @inheritDoc
- */
- protected static $objectListClassName = ConversationMessageList::class;
+class ConversationMessageNotificationObjectType extends AbstractUserNotificationObjectType
+{
+ /**
+ * @inheritDoc
+ */
+ protected static $decoratorClassName = ConversationMessageUserNotificationObject::class;
+
+ /**
+ * @inheritDoc
+ */
+ protected static $objectClassName = ConversationMessage::class;
+
+ /**
+ * @inheritDoc
+ */
+ protected static $objectListClassName = ConversationMessageList::class;
}
<?php
+
namespace wcf\system\user\notification\object\type;
+
use wcf\data\conversation\Conversation;
use wcf\data\conversation\ConversationList;
use wcf\system\user\notification\object\ConversationUserNotificationObject;
/**
* Represents a conversation notification object type.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\User\Notification\Object\Type
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\User\Notification\Object\Type
*/
-class ConversationNotificationObjectType extends AbstractUserNotificationObjectType {
- /**
- * @inheritDoc
- */
- protected static $decoratorClassName = ConversationUserNotificationObject::class;
-
- /**
- * @inheritDoc
- */
- protected static $objectClassName = Conversation::class;
-
- /**
- * @inheritDoc
- */
- protected static $objectListClassName = ConversationList::class;
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function getObjectsByIDs(array $objectIDs) {
- $objects = Conversation::getUserConversations($objectIDs, WCF::getUser()->userID);
-
- foreach ($objects as $objectID => $conversation) {
- $objects[$objectID] = new static::$decoratorClassName($conversation);
- }
-
- foreach ($objectIDs as $objectID) {
- // append empty objects for unknown ids
- if (!isset($objects[$objectID])) {
- // '__unknownNotificationObject' tells the notification API
- // that the object does not exist anymore so that the related
- // notification can be deleted automatically
- $objects[$objectID] = new static::$decoratorClassName(new static::$objectClassName(null, [
- '__unknownNotificationObject' => true,
- 'conversationID' => $objectID
- ]));
- }
- }
-
- return $objects;
- }
+class ConversationNotificationObjectType extends AbstractUserNotificationObjectType
+{
+ /**
+ * @inheritDoc
+ */
+ protected static $decoratorClassName = ConversationUserNotificationObject::class;
+
+ /**
+ * @inheritDoc
+ */
+ protected static $objectClassName = Conversation::class;
+
+ /**
+ * @inheritDoc
+ */
+ protected static $objectListClassName = ConversationList::class;
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function getObjectsByIDs(array $objectIDs)
+ {
+ $objects = Conversation::getUserConversations($objectIDs, WCF::getUser()->userID);
+
+ foreach ($objects as $objectID => $conversation) {
+ $objects[$objectID] = new static::$decoratorClassName($conversation);
+ }
+
+ foreach ($objectIDs as $objectID) {
+ // append empty objects for unknown ids
+ if (!isset($objects[$objectID])) {
+ // '__unknownNotificationObject' tells the notification API
+ // that the object does not exist anymore so that the related
+ // notification can be deleted automatically
+ $objects[$objectID] = new static::$decoratorClassName(new static::$objectClassName(null, [
+ '__unknownNotificationObject' => true,
+ 'conversationID' => $objectID,
+ ]));
+ }
+ }
+
+ return $objects;
+ }
}
<?php
+
namespace wcf\system\worker;
+
use wcf\data\conversation\message\ConversationMessage;
use wcf\data\conversation\message\ConversationMessageList;
use wcf\data\object\type\ObjectTypeCache;
/**
* Worker implementation for updating conversation messages.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Worker
- *
- * @method ConversationMessageList getObjectList()
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Worker
+ *
+ * @method ConversationMessageList getObjectList()
*/
-class ConversationMessageRebuildDataWorker extends AbstractRebuildDataWorker {
- /**
- * @inheritDoc
- */
- protected $limit = 500;
-
- /**
- * @var HtmlInputProcessor
- */
- protected $htmlInputProcessor;
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function countObjects() {
- if ($this->count === null) {
- $this->count = 0;
- $sql = "SELECT MAX(messageID) AS messageID
- FROM wcf".WCF_N."_conversation_message";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute();
- $row = $statement->fetchArray();
- if ($row !== false) $this->count = $row['messageID'];
- }
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- protected function initObjectList() {
- $this->objectList = new ConversationMessageList();
- $this->objectList->sqlOrderBy = 'conversation_message.messageID';
- $this->objectList->sqlSelects = '(SELECT subject FROM wcf'.WCF_N.'_conversation WHERE conversationID = conversation_message.conversationID) AS subject';
- }
-
- /**
- * @inheritDoc
- */
- public function execute() {
- $this->objectList->getConditionBuilder()->add('conversation_message.messageID BETWEEN ? AND ?', [$this->limit * $this->loopCount + 1, $this->limit * $this->loopCount + $this->limit]);
-
- parent::execute();
-
- if (!$this->loopCount) {
- // reset search index
- SearchIndexManager::getInstance()->reset('com.woltlab.wcf.conversation.message');
- }
-
- if (!count($this->objectList)) {
- return;
- }
-
- // prepare statements
- $attachmentObjectType = ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.attachment.objectType', 'com.woltlab.wcf.conversation.message');
- $sql = "SELECT COUNT(*) AS attachments
- FROM wcf".WCF_N."_attachment
+class ConversationMessageRebuildDataWorker extends AbstractRebuildDataWorker
+{
+ /**
+ * @inheritDoc
+ */
+ protected $limit = 500;
+
+ /**
+ * @var HtmlInputProcessor
+ */
+ protected $htmlInputProcessor;
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function countObjects()
+ {
+ if ($this->count === null) {
+ $this->count = 0;
+ $sql = "SELECT MAX(messageID) AS messageID
+ FROM wcf" . WCF_N . "_conversation_message";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute();
+ $row = $statement->fetchArray();
+ if ($row !== false) {
+ $this->count = $row['messageID'];
+ }
+ }
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ protected function initObjectList()
+ {
+ $this->objectList = new ConversationMessageList();
+ $this->objectList->sqlOrderBy = 'conversation_message.messageID';
+ $this->objectList->sqlSelects = '(SELECT subject FROM wcf' . WCF_N . '_conversation WHERE conversationID = conversation_message.conversationID) AS subject';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function execute()
+ {
+ $this->objectList->getConditionBuilder()->add(
+ 'conversation_message.messageID BETWEEN ? AND ?',
+ [$this->limit * $this->loopCount + 1, $this->limit * $this->loopCount + $this->limit]
+ );
+
+ parent::execute();
+
+ if (!$this->loopCount) {
+ // reset search index
+ SearchIndexManager::getInstance()->reset('com.woltlab.wcf.conversation.message');
+ }
+
+ if (!\count($this->objectList)) {
+ return;
+ }
+
+ // prepare statements
+ $attachmentObjectType = ObjectTypeCache::getInstance()
+ ->getObjectTypeByName('com.woltlab.wcf.attachment.objectType', 'com.woltlab.wcf.conversation.message');
+ $sql = "SELECT COUNT(*) AS attachments
+ FROM wcf" . WCF_N . "_attachment
WHERE objectTypeID = ?
AND objectID = ?";
- $attachmentStatement = WCF::getDB()->prepareStatement($sql);
-
- // retrieve permissions
- $userIDs = [];
- foreach ($this->objectList as $object) {
- // passing `0` is actually valid, because it won't yield any results when querying the group membership
- $userIDs[] = ($object->userID ?: 0);
- }
- $userPermissions = $this->getBulkUserPermissions($userIDs, ['user.message.disallowedBBCodes']);
-
- $updateData = [];
- /** @var ConversationMessage $message */
- foreach ($this->objectList as $message) {
- SearchIndexManager::getInstance()->set(
- 'com.woltlab.wcf.conversation.message',
- $message->messageID,
- $message->message,
- $message->subject ?: '',
- $message->time,
- $message->userID,
- $message->username
- );
-
- $data = [];
-
- // count attachments
- $attachmentStatement->execute([$attachmentObjectType->objectTypeID, $message->messageID]);
- $data['attachments'] = $attachmentStatement->fetchSingleColumn();
-
- BBCodeHandler::getInstance()->setDisallowedBBCodes(explode(',', $this->getBulkUserPermissionValue($userPermissions, $message->userID, 'user.message.disallowedBBCodes')));
-
- // update message
- $data['enableHtml'] = 1;
- if (!$message->enableHtml) {
- $this->getHtmlInputProcessor()->process($message->message, 'com.woltlab.wcf.conversation.message', $message->messageID, true);
- $data['message'] = $this->getHtmlInputProcessor()->getHtml();
- }
- else {
- $this->getHtmlInputProcessor()->reprocess($message->message, 'com.woltlab.wcf.conversation.message', $message->messageID);
- $data['message'] = $this->getHtmlInputProcessor()->getHtml();
- }
-
- if (MessageEmbeddedObjectManager::getInstance()->registerObjects($this->getHtmlInputProcessor(), true)) {
- $data['hasEmbeddedObjects'] = 1;
- }
- else {
- $data['hasEmbeddedObjects'] = 0;
- }
-
- $updateData[$message->messageID] = $data;
- }
-
- $sql = "UPDATE wcf".WCF_N."_conversation_message
+ $attachmentStatement = WCF::getDB()->prepareStatement($sql);
+
+ // retrieve permissions
+ $userIDs = [];
+ foreach ($this->objectList as $object) {
+ // passing `0` is actually valid, because it won't yield any results when querying the group membership
+ $userIDs[] = ($object->userID ?: 0);
+ }
+ $userPermissions = $this->getBulkUserPermissions($userIDs, ['user.message.disallowedBBCodes']);
+
+ $updateData = [];
+ /** @var ConversationMessage $message */
+ foreach ($this->objectList as $message) {
+ SearchIndexManager::getInstance()->set(
+ 'com.woltlab.wcf.conversation.message',
+ $message->messageID,
+ $message->message,
+ $message->subject ?: '',
+ $message->time,
+ $message->userID,
+ $message->username
+ );
+
+ $data = [];
+
+ // count attachments
+ $attachmentStatement->execute([$attachmentObjectType->objectTypeID, $message->messageID]);
+ $data['attachments'] = $attachmentStatement->fetchSingleColumn();
+
+ BBCodeHandler::getInstance()->setDisallowedBBCodes(\explode(
+ ',',
+ $this->getBulkUserPermissionValue($userPermissions, $message->userID, 'user.message.disallowedBBCodes')
+ ));
+
+ // update message
+ $data['enableHtml'] = 1;
+ if (!$message->enableHtml) {
+ $this->getHtmlInputProcessor()->process(
+ $message->message,
+ 'com.woltlab.wcf.conversation.message',
+ $message->messageID,
+ true
+ );
+ $data['message'] = $this->getHtmlInputProcessor()->getHtml();
+ } else {
+ $this->getHtmlInputProcessor()->reprocess(
+ $message->message,
+ 'com.woltlab.wcf.conversation.message',
+ $message->messageID
+ );
+ $data['message'] = $this->getHtmlInputProcessor()->getHtml();
+ }
+
+ if (MessageEmbeddedObjectManager::getInstance()->registerObjects($this->getHtmlInputProcessor(), true)) {
+ $data['hasEmbeddedObjects'] = 1;
+ } else {
+ $data['hasEmbeddedObjects'] = 0;
+ }
+
+ $updateData[$message->messageID] = $data;
+ }
+
+ $sql = "UPDATE wcf" . WCF_N . "_conversation_message
SET attachments = ?,
message = ?,
enableHtml = ?,
hasEmbeddedObjects = ?
WHERE messageID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
-
- WCF::getDB()->beginTransaction();
- foreach ($updateData as $messageID => $data) {
- $statement->execute([
- $data['attachments'],
- $data['message'],
- $data['enableHtml'],
- $data['hasEmbeddedObjects'],
- $messageID
- ]);
- }
- WCF::getDB()->commitTransaction();
-
- MessageEmbeddedObjectManager::getInstance()->commitBulkOperation();
- }
-
- /**
- * @return HtmlInputProcessor
- */
- protected function getHtmlInputProcessor() {
- if ($this->htmlInputProcessor === null) {
- $this->htmlInputProcessor = new HtmlInputProcessor();
- }
-
- return $this->htmlInputProcessor;
- }
+ $statement = WCF::getDB()->prepareStatement($sql);
+
+ WCF::getDB()->beginTransaction();
+ foreach ($updateData as $messageID => $data) {
+ $statement->execute([
+ $data['attachments'],
+ $data['message'],
+ $data['enableHtml'],
+ $data['hasEmbeddedObjects'],
+ $messageID,
+ ]);
+ }
+ WCF::getDB()->commitTransaction();
+
+ MessageEmbeddedObjectManager::getInstance()->commitBulkOperation();
+ }
+
+ /**
+ * @return HtmlInputProcessor
+ */
+ protected function getHtmlInputProcessor()
+ {
+ if ($this->htmlInputProcessor === null) {
+ $this->htmlInputProcessor = new HtmlInputProcessor();
+ }
+
+ return $this->htmlInputProcessor;
+ }
}
<?php
+
namespace wcf\system\worker;
+
use wcf\data\conversation\Conversation;
use wcf\data\conversation\ConversationAction;
use wcf\data\conversation\ConversationEditor;
/**
* Worker implementation for updating conversations.
- *
- * @author Marcel Werk
- * @copyright 2001-2019 WoltLab GmbH
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package WoltLabSuite\Core\System\Worker
- *
- * @method ConversationList getObjectList()
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2019 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Worker
+ *
+ * @method ConversationList getObjectList()
*/
-class ConversationRebuildDataWorker extends AbstractRebuildDataWorker {
- /**
- * @inheritDoc
- */
- protected $limit = 100;
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function countObjects() {
- if ($this->count === null) {
- $this->count = 0;
- $sql = "SELECT MAX(conversationID) AS conversationID
- FROM wcf".WCF_N."_conversation";
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute();
- $row = $statement->fetchArray();
- if ($row !== false) $this->count = $row['conversationID'];
- }
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- protected function initObjectList() {
- $this->objectList = new ConversationList();
- $this->objectList->sqlOrderBy = 'conversation.conversationID';
- }
-
- /**
- * @inheritDoc
- */
- public function execute() {
- $this->objectList->getConditionBuilder()->add('conversation.conversationID BETWEEN ? AND ?', [$this->limit * $this->loopCount + 1, $this->limit * $this->loopCount + $this->limit]);
-
- parent::execute();
-
- // prepare statements
- $sql = "SELECT messageID, time, userID, username
- FROM wcf".WCF_N."_conversation_message
+class ConversationRebuildDataWorker extends AbstractRebuildDataWorker
+{
+ /**
+ * @inheritDoc
+ */
+ protected $limit = 100;
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ public function countObjects()
+ {
+ if ($this->count === null) {
+ $this->count = 0;
+ $sql = "SELECT MAX(conversationID) AS conversationID
+ FROM wcf" . WCF_N . "_conversation";
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute();
+ $row = $statement->fetchArray();
+ if ($row !== false) {
+ $this->count = $row['conversationID'];
+ }
+ }
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+
+ /**
+ * @inheritDoc
+ */
+ protected function initObjectList()
+ {
+ $this->objectList = new ConversationList();
+ $this->objectList->sqlOrderBy = 'conversation.conversationID';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function execute()
+ {
+ $this->objectList->getConditionBuilder()->add(
+ 'conversation.conversationID BETWEEN ? AND ?',
+ [$this->limit * $this->loopCount + 1, $this->limit * $this->loopCount + $this->limit]
+ );
+
+ parent::execute();
+
+ // prepare statements
+ $sql = "SELECT messageID, time, userID, username
+ FROM wcf" . WCF_N . "_conversation_message
WHERE conversationID = ?
ORDER BY time";
- $firstMessageStatement = WCF::getDB()->prepareStatement($sql, 1);
- $sql = "SELECT time, userID, username
- FROM wcf".WCF_N."_conversation_message
+ $firstMessageStatement = WCF::getDB()->prepareStatement($sql, 1);
+ $sql = "SELECT time, userID, username
+ FROM wcf" . WCF_N . "_conversation_message
WHERE conversationID = ?
ORDER BY time DESC";
- $lastMessageStatement = WCF::getDB()->prepareStatement($sql, 1);
- $sql = "SELECT COUNT(*) AS messages,
+ $lastMessageStatement = WCF::getDB()->prepareStatement($sql, 1);
+ $sql = "SELECT COUNT(*) AS messages,
SUM(attachments) AS attachments
- FROM wcf".WCF_N."_conversation_message
+ FROM wcf" . WCF_N . "_conversation_message
WHERE conversationID = ?";
- $statsStatement = WCF::getDB()->prepareStatement($sql);
- $sql = "SELECT COUNT(*) AS participants
- FROM wcf".WCF_N."_conversation_to_user conversation_to_user
+ $statsStatement = WCF::getDB()->prepareStatement($sql);
+ $sql = "SELECT COUNT(*) AS participants
+ FROM wcf" . WCF_N . "_conversation_to_user conversation_to_user
WHERE conversation_to_user.conversationID = ?
AND conversation_to_user.hideConversation <> ?
AND conversation_to_user.participantID <> ?
AND conversation_to_user.isInvisible = ?";
- $participantCounterStatement = WCF::getDB()->prepareStatement($sql);
- $sql = "SELECT conversation_to_user.participantID AS userID, conversation_to_user.hideConversation, user_table.username
- FROM wcf".WCF_N."_conversation_to_user conversation_to_user
- LEFT JOIN wcf".WCF_N."_user user_table
+ $participantCounterStatement = WCF::getDB()->prepareStatement($sql);
+ $sql = "SELECT conversation_to_user.participantID AS userID, conversation_to_user.hideConversation, user_table.username
+ FROM wcf" . WCF_N . "_conversation_to_user conversation_to_user
+ LEFT JOIN wcf" . WCF_N . "_user user_table
ON (user_table.userID = conversation_to_user.participantID)
WHERE conversation_to_user.conversationID = ?
AND conversation_to_user.participantID <> ?
AND conversation_to_user.isInvisible = ?
ORDER BY user_table.username";
- $participantStatement = WCF::getDB()->prepareStatement($sql, 5);
-
- $sql = "SELECT COUNT(*) AS participants
- FROM wcf".WCF_N."_conversation_to_user
+ $participantStatement = WCF::getDB()->prepareStatement($sql, 5);
+
+ $sql = "SELECT COUNT(*) AS participants
+ FROM wcf" . WCF_N . "_conversation_to_user
WHERE conversationID = ?
AND hideConversation <> ?
AND participantID IS NOT NULL";
- $existingParticipantStatement = WCF::getDB()->prepareStatement($sql);
-
- $obsoleteConversations = [];
- $updateData = [];
- /** @var Conversation $conversation */
- foreach ($this->objectList as $conversation) {
- // check for obsolete conversations
- $obsolete = false;
- if ($conversation->isDraft) {
- if (!$conversation->userID) $obsolete = true;
- }
- else {
- $existingParticipantStatement->execute([$conversation->conversationID, Conversation::STATE_LEFT]);
- $row = $existingParticipantStatement->fetchSingleRow();
- if (!$row['participants']) $obsolete = true;
- }
- if ($obsolete) {
- $obsoleteConversations[] = new ConversationEditor($conversation);
- continue;
- }
-
- // update data
- $data = [
- 'firstMessageID' => $conversation->firstMessageID,
- 'lastPostTime' => $conversation->lastPostTime,
- 'lastPosterID' => $conversation->lastPosterID,
- 'lastPoster' => $conversation->lastPoster,
- 'userID' => $conversation->userID,
- 'username' => $conversation->username
- ];
-
- // get first post
- $firstMessageStatement->execute([$conversation->conversationID]);
- if (($row = $firstMessageStatement->fetchSingleRow()) !== false) {
- $data['firstMessageID'] = $row['messageID'];
- $data['lastPostTime'] = $data['time'] = $row['time'];
- $data['userID'] = $row['userID'];
- $data['username'] = $row['username'];
- }
-
- // get last post
- $lastMessageStatement->execute([$conversation->conversationID]);
- if (($row = $lastMessageStatement->fetchSingleRow()) !== false) {
- $data['lastPostTime'] = $row['time'];
- $data['lastPosterID'] = $row['userID'];
- $data['lastPoster'] = $row['username'];
- }
-
- // get stats
- $statsStatement->execute([$conversation->conversationID]);
- $row = $statsStatement->fetchSingleRow();
- $data['replies'] = ($row['messages'] ? $row['messages'] - 1 : 0);
- $data['attachments'] = ($row['attachments'] ?: 0);
-
- // get number of participants
- $participantCounterStatement->execute([$conversation->conversationID, Conversation::STATE_LEFT, $conversation->userID, 0]);
- $data['participants'] = $participantCounterStatement->fetchSingleColumn();
-
- // get participant summary
- $participantStatement->execute([$conversation->conversationID, $conversation->userID, 0]);
- $users = [];
- while ($row = $participantStatement->fetchArray()) {
- $users[] = $row;
- }
- $data['participantSummary'] = serialize($users);
-
- $updateData[$conversation->conversationID] = $data;
- }
-
- $sql = "UPDATE wcf".WCF_N."_conversation
+ $existingParticipantStatement = WCF::getDB()->prepareStatement($sql);
+
+ $obsoleteConversations = [];
+ $updateData = [];
+ /** @var Conversation $conversation */
+ foreach ($this->objectList as $conversation) {
+ // check for obsolete conversations
+ $obsolete = false;
+ if ($conversation->isDraft) {
+ if (!$conversation->userID) {
+ $obsolete = true;
+ }
+ } else {
+ $existingParticipantStatement->execute([$conversation->conversationID, Conversation::STATE_LEFT]);
+ $row = $existingParticipantStatement->fetchSingleRow();
+ if (!$row['participants']) {
+ $obsolete = true;
+ }
+ }
+ if ($obsolete) {
+ $obsoleteConversations[] = new ConversationEditor($conversation);
+ continue;
+ }
+
+ // update data
+ $data = [
+ 'firstMessageID' => $conversation->firstMessageID,
+ 'lastPostTime' => $conversation->lastPostTime,
+ 'lastPosterID' => $conversation->lastPosterID,
+ 'lastPoster' => $conversation->lastPoster,
+ 'userID' => $conversation->userID,
+ 'username' => $conversation->username,
+ ];
+
+ // get first post
+ $firstMessageStatement->execute([$conversation->conversationID]);
+ if (($row = $firstMessageStatement->fetchSingleRow()) !== false) {
+ $data['firstMessageID'] = $row['messageID'];
+ $data['lastPostTime'] = $data['time'] = $row['time'];
+ $data['userID'] = $row['userID'];
+ $data['username'] = $row['username'];
+ }
+
+ // get last post
+ $lastMessageStatement->execute([$conversation->conversationID]);
+ if (($row = $lastMessageStatement->fetchSingleRow()) !== false) {
+ $data['lastPostTime'] = $row['time'];
+ $data['lastPosterID'] = $row['userID'];
+ $data['lastPoster'] = $row['username'];
+ }
+
+ // get stats
+ $statsStatement->execute([$conversation->conversationID]);
+ $row = $statsStatement->fetchSingleRow();
+ $data['replies'] = ($row['messages'] ? $row['messages'] - 1 : 0);
+ $data['attachments'] = ($row['attachments'] ?: 0);
+
+ // get number of participants
+ $participantCounterStatement->execute([
+ $conversation->conversationID,
+ Conversation::STATE_LEFT,
+ $conversation->userID,
+ 0,
+ ]);
+ $data['participants'] = $participantCounterStatement->fetchSingleColumn();
+
+ // get participant summary
+ $participantStatement->execute([$conversation->conversationID, $conversation->userID, 0]);
+ $users = [];
+ while ($row = $participantStatement->fetchArray()) {
+ $users[] = $row;
+ }
+ $data['participantSummary'] = \serialize($users);
+
+ $updateData[$conversation->conversationID] = $data;
+ }
+
+ $sql = "UPDATE wcf" . WCF_N . "_conversation
SET firstMessageID = ?,
lastPostTime = ?,
lastPosterID = ?,
participants = ?,
participantSummary = ?
WHERE conversationID = ?";
- $statement = WCF::getDB()->prepareStatement($sql);
-
- WCF::getDB()->beginTransaction();
- foreach ($updateData as $conversationID => $data) {
- $statement->execute([
- $data['firstMessageID'],
- $data['lastPostTime'],
- $data['lastPosterID'],
- $data['lastPoster'],
- $data['userID'],
- $data['username'],
- $data['replies'],
- $data['attachments'],
- $data['participants'],
- $data['participantSummary'],
- $conversationID
- ]);
- }
- WCF::getDB()->commitTransaction();
-
- // delete obsolete conversations
- if (!empty($obsoleteConversations)) {
- $action = new ConversationAction($obsoleteConversations, 'delete');
- $action->executeAction();
- }
- }
+ $statement = WCF::getDB()->prepareStatement($sql);
+
+ WCF::getDB()->beginTransaction();
+ foreach ($updateData as $conversationID => $data) {
+ $statement->execute([
+ $data['firstMessageID'],
+ $data['lastPostTime'],
+ $data['lastPosterID'],
+ $data['lastPoster'],
+ $data['userID'],
+ $data['username'],
+ $data['replies'],
+ $data['attachments'],
+ $data['participants'],
+ $data['participantSummary'],
+ $conversationID,
+ ]);
+ }
+ WCF::getDB()->commitTransaction();
+
+ // delete obsolete conversations
+ if (!empty($obsoleteConversations)) {
+ $action = new ConversationAction($obsoleteConversations, 'delete');
+ $action->executeAction();
+ }
+ }
}