1
0
mirror of https://github.com/wbbaddons/Tims-Chat.git synced 2024-10-31 14:10:08 +00:00

Compare commits

..

No commits in common. "master" and "v4.1.0-rc.7" have entirely different histories.

233 changed files with 8171 additions and 9555 deletions

View File

@ -3,9 +3,9 @@
, "last 2 chromeandroid versions"
, "firefox esr"
, "last 2 firefox versions"
, "last 2 edge versions"
, "safari >= 15"
, "ios >= 15"
, "edge >= 17"
, "safari >= 12"
, "ios >= 12"
]
}
, "debug": true

3
.gitattributes vendored
View File

@ -1,3 +0,0 @@
*.php diff=php
*.css diff=css
*.scss diff=css

View File

@ -1,8 +0,0 @@
{
"editor.rulers": [
{
"column": 120,
"color": "#ff00ff40"
}
]
}

View File

@ -4,13 +4,13 @@ License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.
Parameters
Licensor: Tim Düsterhus
Licensed Work: Tims Chat 4.3
The Licensed Work is (c) 2010-2024 Tim Düsterhus
Licensed Work: Tims Chat 4.1
The Licensed Work is (c) 2010-2021 Tim Düsterhus
Additional Use Grant: You may use the Licensed Work when your application
uses the Licensed Work for a purpose that does neither
directly or indirectly generate revenue.
Change Date: 2028-06-15
Change Date: 2025-03-05
Change License: Version 2 or later of the GNU General Public License as
published by the Free Software Foundation.

View File

@ -16,7 +16,7 @@
<controller>chat\acp\form\RoomAddForm</controller>
<parent>chat.acp.menu.link.room.list</parent>
<permissions>admin.chat.canManageRoom</permissions>
<icon>plus</icon>
<icon>fa-plus</icon>
</acpmenuitem>
<acpmenuitem name="chat.acp.menu.link.command.trigger.list">
@ -29,7 +29,7 @@
<controller>chat\acp\form\CommandTriggerAddForm</controller>
<parent>chat.acp.menu.link.command.trigger.list</parent>
<permissions>admin.chat.canManageTriggers</permissions>
<icon>plus</icon>
<icon>fa-plus</icon>
</acpmenuitem>
<acpmenuitem name="chat.acp.menu.link.suspension.list">

View File

@ -0,0 +1,5 @@
<dl>
<dt>{lang}chat.acp.index.system.software.chatVersion{/lang}</dt>
<dd>{$__chat->getPackage()->packageVersion}</dd>
</dl>

View File

@ -7,14 +7,18 @@
<nav class="contentHeaderNavigation">
<ul>
<li><a href="{link application='chat' controller='CommandTriggerList'}{/link}" class="button">{icon name='list'} <span>{lang}chat.acp.command.trigger.list{/lang}</span></a></li>
<li><a href="{link application='chat' controller='CommandTriggerList'}{/link}" class="button"><span class="icon icon16 fa-list"></span> <span>{lang}chat.acp.command.trigger.list{/lang}</span></a></li>
{event name='contentHeaderNavigation'}
</ul>
</nav>
</header>
{include file='formNotice'}
{include file='formError'}
{if $success|isset}
<p class="success">{lang}wcf.global.success.{$action}{/lang}</p>
{/if}
<form method="post" action="{if $action == 'add'}{link application='chat' controller='CommandTriggerAdd'}{/link}{else}{link application='chat' controller='CommandTriggerEdit' id=$triggerID}{/link}{/if}">
<div class="section">
@ -60,7 +64,7 @@
<div class="formSubmit">
<input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s">
{csrfToken}
{@SECURITY_TOKEN_INPUT_TAG}
</div>
</form>

View File

@ -14,7 +14,7 @@
<nav class="contentHeaderNavigation">
<ul>
<li><a href="{link controller='CommandTriggerAdd' application='chat'}{/link}" class="button">{icon name='plus'} <span>{lang}chat.acp.command.trigger.add{/lang}</span></a></li>
<li><a href="{link controller='CommandTriggerAdd' application='chat'}{/link}" class="button"><span class="icon icon16 fa-plus"></span> <span>{lang}chat.acp.command.trigger.add{/lang}</span></a></li>
{event name='contentHeaderNavigation'}
</ul>
@ -45,8 +45,8 @@
{foreach from=$objects item=trigger}
<tr class="jsTriggerRow">
<td class="columnIcon">
<a href="{link controller='CommandTriggerEdit' object=$trigger application='chat'}{/link}" title="{lang}wcf.global.button.edit{/lang}" class="jsTooltip">{icon name='pencil'}</a>
<span class="jsDeleteButton jsTooltip pointer" title="{lang}wcf.global.button.delete{/lang}" data-object-id="{$trigger->triggerID}" data-confirm-message-html="{lang __encode=true}chat.acp.command.trigger.delete.sure{/lang}">{icon name='xmark'}</span>
<a href="{link controller='CommandTriggerEdit' object=$trigger application='chat'}{/link}" title="{lang}wcf.global.button.edit{/lang}" class="jsTooltip"><span class="icon icon16 fa-pencil"></span></a>
<span class="icon icon16 fa-times jsDeleteButton jsTooltip pointer" title="{lang}wcf.global.button.delete{/lang}" data-object-id="{@$trigger->triggerID}" data-confirm-message-html="{lang __encode=true}chat.acp.command.trigger.delete.sure{/lang}"></span>
{event name='rowButtons'}
</td>
@ -75,7 +75,7 @@
<nav class="contentFooterNavigation">
<ul>
<li><a href="{link controller='CommandTriggerAdd' application='chat'}{/link}" class="button">{icon name='plus'} <span>{lang}chat.acp.command.trigger.add{/lang}</span></a></li>
<li><a href="{link controller='CommandTriggerAdd' application='chat'}{/link}" class="button"><span class="icon icon16 fa-plus"></span> <span>{lang}chat.acp.command.trigger.add{/lang}</span></a></li>
{event name='contentFooterNavigation'}
</ul>

View File

@ -19,14 +19,18 @@
<nav class="contentHeaderNavigation">
<ul>
<li><a href="{link application='chat' controller='RoomList'}{/link}" class="button">{icon name='list'} <span>{lang}chat.acp.room.list{/lang}</span></a></li>
<li><a href="{link application='chat' controller='RoomList'}{/link}" class="button"><span class="icon icon16 fa-list"></span> <span>{lang}chat.acp.room.list{/lang}</span></a></li>
{event name='contentHeaderNavigation'}
</ul>
</nav>
</header>
{include file='formNotice'}
{include file='formError'}
{if $success|isset}
<p class="success">{lang}wcf.global.success.{$action}{/lang}</p>
{/if}
<form method="post" action="{if $action == 'add'}{link application='chat' controller='RoomAdd'}{/link}{else}{link application='chat' controller='RoomEdit' id=$roomID}{/link}{/if}">
<div class="section">
@ -101,7 +105,7 @@
<div class="formSubmit">
<input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s">
{csrfToken}
{@SECURITY_TOKEN_INPUT_TAG}
</div>
</form>

View File

@ -19,7 +19,7 @@
<nav class="contentHeaderNavigation">
<ul>
<li><a href="{link controller='RoomAdd' application='chat'}{/link}" class="button">{icon name='plus'} <span>{lang}chat.acp.room.add{/lang}</span></a></li>
<li><a href="{link controller='RoomAdd' application='chat'}{/link}" class="button"><span class="icon icon16 fa-plus"></span> <span>{lang}chat.acp.room.add{/lang}</span></a></li>
{event name='contentHeaderNavigation'}
</ul>
@ -37,14 +37,14 @@
<ol id="roomContainer0" class="sortableList" data-object-id="0">
{content}
{foreach from=$objects item=room}
<li class="sortableNode sortableNoNesting" data-object-id="{$room->roomID}">
<li class="sortableNode sortableNoNesting" data-object-id="{@$room->roomID}">
<span class="sortableNodeLabel">
<a href="{link controller='RoomEdit' application='chat' object=$room}{/link}">{$room}</a>
<span class="statusDisplay sortableButtonContainer">
<span class="sortableNodeHandle">{icon name='up-down-left-right'}</span>
<a href="{link controller='RoomEdit' application='chat' object=$room}{/link}" title="{lang}wcf.global.button.edit{/lang}" class="jsTooltip">{icon name='pencil'}</a>
<span class="jsDeleteButton jsTooltip pointer" title="{lang}wcf.global.button.delete{/lang}" data-object-id="{$room->roomID}" data-confirm-message-html="{lang __encode=true}chat.acp.room.delete.sure{/lang}">{icon name='xmark'}</span>
<span class="icon icon16 fa-arrows sortableNodeHandle"></span>
<a href="{link controller='RoomEdit' application='chat' object=$room}{/link}" title="{lang}wcf.global.button.edit{/lang}" class="jsTooltip"><span class="icon icon16 fa-pencil"></span></a>
<span class="icon icon16 fa-times jsDeleteButton jsTooltip pointer" title="{lang}wcf.global.button.delete{/lang}" data-object-id="{@$room->roomID}" data-confirm-message-html="{lang __encode=true}chat.acp.room.delete.sure{/lang}"></span>
{event name='itemButtons'}
</span>
</span>
@ -70,7 +70,7 @@
<nav class="contentFooterNavigation">
<ul>
<li><a href="{link controller='RoomAdd' application='chat'}{/link}" class="button">{icon name='plus'} <span>{lang}chat.acp.room.add{/lang}</span></a></li>
<li><a href="{link controller='RoomAdd' application='chat'}{/link}" class="button"><span class="icon icon16 fa-plus"></span> <span>{lang}chat.acp.room.add{/lang}</span></a></li>
{event name='contentFooterNavigation'}
</ul>

View File

@ -99,7 +99,7 @@ require([ 'Bastelstu.be/PromiseWrap/Ajax', 'Bastelstu.be/PromiseWrap/Ui/Confirma
<div class="formSubmit">
<input type="submit" value="{lang}wcf.global.button.submit{/lang}" accesskey="s">
{csrfToken}
{@SECURITY_TOKEN_INPUT_TAG}
</div>
</section>
</form>
@ -141,7 +141,7 @@ require([ 'Bastelstu.be/PromiseWrap/Ajax', 'Bastelstu.be/PromiseWrap/Ui/Confirma
{foreach from=$objects item=suspension}
<tr class="jsSuspensionRow" data-object-id="{$suspension->suspensionID}">
<td class="columnIcon">
<span class="jsRevokeButton{if !$suspension->isActive()} disabled{else} pointer{/if}" title="{lang}chat.acp.suspension.revoke{/lang}" data-confirm-message-html="{lang}chat.acp.suspension.revoke.sure{/lang}">{icon name='arrow-rotate-left'}</span>
<span class="icon icon16 fa-undo{if !$suspension->isActive()} disabled{else} pointer{/if} jsRevokeButton" title="{lang}chat.acp.suspension.revoke{/lang}" data-confirm-message-html="{lang}chat.acp.suspension.revoke.sure{/lang}"></span>
{event name='rowButtons'}
</td>

View File

@ -1,25 +1,21 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
* or later of the General Public License.
*/
use wcf\system\box\BoxHandler;
use \wcf\system\box\BoxHandler;
BoxHandler::getInstance()->createBoxCondition(
'be.bastelstu.chat.roomListDashboard',
'be.bastelstu.chat.box.roomList.condition',
'be.bastelstu.chat.roomFilled',
[
'chatRoomIsFilled' => 1,
]
BoxHandler::getInstance()->createBoxCondition( 'be.bastelstu.chat.roomListDashboard'
, 'be.bastelstu.chat.box.roomList.condition'
, 'be.bastelstu.chat.roomFilled'
, [ 'chatRoomIsFilled' => 1 ]
);

View File

@ -1,44 +1,35 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
* or later of the General Public License.
*/
use chat\data\message\MessageAction;
use wcf\data\object\type\ObjectTypeCache;
use \chat\data\message\MessageAction;
$objectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName(
'be.bastelstu.chat.messageType',
'be.bastelstu.chat.messageType.chatUpdate'
);
$objectTypeID = \wcf\data\object\type\ObjectTypeCache::getInstance()->getObjectTypeIDByName('be.bastelstu.chat.messageType', 'be.bastelstu.chat.messageType.chatUpdate');
if ($objectTypeID) {
(new MessageAction(
[ ],
'create',
[
'data' => [
'roomID' => null,
'userID' => null,
'username' => '',
'time' => TIME_NOW,
'objectTypeID' => $objectTypeID,
'payload' => \serialize([ ]),
],
(new MessageAction([ ], 'create', [ 'data' => [ 'roomID' => null
, 'userID' => null
, 'username' => ''
, 'time' => TIME_NOW
, 'objectTypeID' => $objectTypeID
, 'payload' => serialize([ ])
]
))->executeAction();
]
)
)->executeAction();
}
$CHATCore = \file_get_contents(__DIR__ . '/../lib/system/CHATCore.class.php');
if (\strpos($CHATCore, 'chat.phar.php') === false) {
@\unlink(__DIR__ . '/../chat.phar.php');
$CHATCore = file_get_contents(__DIR__.'/../lib/system/CHATCore.class.php');
if (strpos($CHATCore, 'chat.phar.php') === false) {
@unlink(__DIR__.'/../chat.phar.php');
}

View File

@ -1,41 +0,0 @@
<?php
/**
* Deletes orphaned attachments.
*
* @author Tim Duesterhus
* @copyright 2001-2022 WoltLab GmbH
* @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
* @package WoltLabSuite\Core
* @see https://github.com/WoltLab/com.woltlab.wcf.conversation/blob/f0d4964a0b8042c440d5a3f759078429dc43c5b8/files/acp/update_com.woltlab.wcf.conversation_5.5_cleanup_orphaned_attachments.php
*/
use wcf\data\attachment\AttachmentAction;
use wcf\data\object\type\ObjectTypeCache;
use wcf\system\package\SplitNodeException;
use wcf\system\WCF;
$objectType = ObjectTypeCache::getInstance()
->getObjectTypeByName('com.woltlab.wcf.attachment.objectType', 'be.bastelstu.chat.message');
$sql = "SELECT attachmentID
FROM wcf1_attachment
WHERE objectTypeID = ?
AND objectID NOT IN (
SELECT messageID
FROM chat1_message
)";
$statement = WCF::getDB()->prepare($sql, 100);
$statement->execute([$objectType->objectTypeID]);
$attachmentIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
if (empty($attachmentIDs)) {
return;
}
(new AttachmentAction($attachmentIDs, 'delete'))->executeAction();
// If we reached this location we processed at least one attachment.
// If this was the final attachment the next iteration will abort this
// script early, thus not splitting the node.
throw new SplitNodeException();

View File

@ -1,19 +1,18 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
* or later of the General Public License.
*/
\define('RELATIVE_CHAT_DIR', '../');
define('RELATIVE_CHAT_DIR', '../');
require_once(RELATIVE_CHAT_DIR . '/app.config.inc.php');
require_once(RELATIVE_CHAT_DIR.'/config.inc.php');
require_once(RELATIVE_WCF_DIR.'acp/global.php');

View File

@ -1,20 +1,16 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
* or later of the General Public License.
*/
use wcf\system\request\RequestHandler;
require('./global.php');
RequestHandler::getInstance()->handle('chat', true);
\wcf\system\request\RequestHandler::getInstance()->handle('chat', true);

View File

@ -1,17 +1,16 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
* or later of the General Public License.
*/
require_once(__DIR__ . '/app.config.inc.php');
require_once(dirname(__FILE__).'/config.inc.php');
require_once(RELATIVE_WCF_DIR.'global.php');

View File

@ -1,20 +1,16 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
* or later of the General Public License.
*/
use wcf\system\request\RequestHandler;
require('./global.php');
RequestHandler::getInstance()->handle('chat');
\wcf\system\request\RequestHandler::getInstance()->handle('chat');

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,19 +14,17 @@
namespace chat\acp\form;
use chat\data\command\CommandList;
use chat\data\command\CommandTrigger;
use chat\data\command\CommandTriggerAction;
use wcf\form\AbstractForm;
use wcf\system\exception\UserInputException;
use wcf\system\WCF;
use wcf\util\StringUtil;
use \chat\data\command\CommandCache;
use \chat\data\command\CommandTrigger;
use \chat\data\command\CommandTriggerAction;
use \chat\data\command\CommandTriggerEditor;
use \wcf\system\exception\UserInputException;
use \wcf\system\WCF;
/**
* Shows the command trigger add form.
*/
class CommandTriggerAddForm extends AbstractForm
{
class CommandTriggerAddForm extends \wcf\form\AbstractForm {
/**
* @inheritDoc
*/
@ -36,9 +33,7 @@ class CommandTriggerAddForm extends AbstractForm
/**
* @inheritDoc
*/
public $neededPermissions = [
'admin.chat.canManageTriggers',
];
public $neededPermissions = [ 'admin.chat.canManageTriggers' ];
/**
* The new trigger for the specified command
@ -57,7 +52,7 @@ class CommandTriggerAddForm extends AbstractForm
*
* @param Command
*/
public $command;
public $command = null;
/**
* The fully qualified name of the command
@ -68,9 +63,8 @@ class CommandTriggerAddForm extends AbstractForm
/**
* @inheritDoc
*/
public function readData()
{
$commandList = new CommandList();
public function readData() {
$commandList = new \chat\data\command\CommandList();
$commandList->sqlOrderBy = 'command.className';
$commandList->readObjects();
@ -82,44 +76,35 @@ public function readData()
/**
* @inheritDoc
*/
public function readFormParameters()
{
public function readFormParameters() {
parent::readFormParameters();
if (isset($_POST['commandTrigger'])) {
$this->commandTrigger = StringUtil::trim($_POST['commandTrigger']);
}
if (isset($_POST['className'])) {
$this->className = StringUtil::trim($_POST['className']);
}
if (isset($_POST['commandTrigger'])) $this->commandTrigger = \wcf\util\StringUtil::trim($_POST['commandTrigger']);
if (isset($_POST['className'])) $this->className = \wcf\util\StringUtil::trim($_POST['className']);
}
/**
* @inheritDoc
*/
public function validate()
{
public function validate() {
parent::validate();
if ($this->commandTrigger === '') {
if (empty($this->commandTrigger)) {
throw new UserInputException('commandTrigger', 'empty');
}
// Triggers must not contain whitespace
if (\preg_match('~\s~', $this->commandTrigger)) {
if (preg_match('~\s~', $this->commandTrigger)) {
throw new UserInputException('commandTrigger', 'invalid');
}
// Check for duplicates
$trigger = CommandTrigger::getTriggerByName($this->commandTrigger);
if (
(!isset($this->trigger) && $trigger->triggerID)
|| (isset($this->trigger) && $trigger->triggerID != $this->trigger->triggerID)
) {
if ((!isset($this->trigger) && $trigger->triggerID) || (isset($this->trigger) && $trigger->triggerID != $this->trigger->triggerID)) {
throw new UserInputException('commandTrigger', 'duplicate');
}
if ($this->className === '') {
if (empty($this->className)) {
throw new UserInputException('className', 'empty');
}
@ -139,26 +124,15 @@ public function validate()
/**
* @inheritDoc
*/
public function save()
{
public function save() {
parent::save();
$fields = [
'commandTrigger' => $this->commandTrigger,
'commandID' => $this->command->commandID,
$fields = [ 'commandTrigger' => $this->commandTrigger
, 'commandID' => $this->command->commandID
];
// create room
$this->objectAction = new CommandTriggerAction(
[ ],
'create',
[
'data' => \array_merge(
$this->additionalFields,
$fields
),
]
);
$this->objectAction = new \chat\data\command\CommandTriggerAction([ ], 'create', [ 'data' => array_merge($this->additionalFields, $fields) ]);
$this->objectAction->executeAction();
$this->saved();
@ -173,15 +147,13 @@ public function save()
/**
* @inheritDoc
*/
public function assignVariables()
{
public function assignVariables() {
parent::assignVariables();
WCF::getTPL()->assign([
'action' => 'add',
'commandTrigger' => $this->commandTrigger,
'className' => $this->className,
'availableCommands' => $this->commands,
WCF::getTPL()->assign([ 'action' => 'add'
, 'commandTrigger' => $this->commandTrigger
, 'className' => $this->className
, 'availableCommands' => $this->commands
]);
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,18 +14,17 @@
namespace chat\acp\form;
use chat\data\command\CommandList;
use chat\data\command\CommandTrigger;
use chat\data\command\CommandTriggerAction;
use wcf\form\AbstractForm;
use wcf\system\exception\IllegalLinkException;
use wcf\system\WCF;
use \chat\data\command\CommandTrigger;
use \chat\data\command\CommandTriggerAction;
use \chat\data\command\CommandTriggerEditor;
use \wcf\system\exception\IllegalLinkException;
use \wcf\system\exception\UserInputException;
use \wcf\system\WCF;
/**
* Shows the command trigger edit form.
*/
class CommandTriggerEditForm extends CommandTriggerAddForm
{
class CommandTriggerEditForm extends CommandTriggerAddForm {
/**
* @inheritDoc
*/
@ -44,16 +42,13 @@ class CommandTriggerEditForm extends CommandTriggerAddForm
*
* @param CommandTrigger
*/
public $trigger;
public $trigger = null;
/**
* @inheritDoc
*/
public function readParameters()
{
if (isset($_REQUEST['id'])) {
$this->triggerID = \intval($_REQUEST['id']);
}
public function readParameters() {
if (isset($_REQUEST['id'])) $this->triggerID = intval($_REQUEST['id']);
$this->trigger = new CommandTrigger($this->triggerID);
if (!$this->trigger) {
@ -66,17 +61,16 @@ public function readParameters()
/**
* @inheritDoc
*/
public function readData()
{
public function readData() {
parent::readData();
if (empty($_POST)) {
$commandList = new CommandList();
$commandList = new \chat\data\command\CommandList();
$commandList->getConditionBuilder()->add('command.commandID = ?', [ $this->trigger->commandID ]);
$commandList->readObjects();
$commands = $commandList->getObjects();
if (!\count($commands)) {
if (!count($commands)) {
throw new IllegalLinkException();
}
@ -88,28 +82,15 @@ public function readData()
/**
* @inheritDoc
*/
public function save()
{
AbstractForm::save();
public function save() {
\wcf\form\AbstractForm::save();
$fields = [
'commandTrigger' => $this->commandTrigger,
'commandID' => $this->command->commandID,
$fields = [ 'commandTrigger' => $this->commandTrigger
, 'commandID' => $this->command->commandID
];
// update trigger
$this->objectAction = new CommandTriggerAction(
[
$this->trigger,
],
'update',
[
'data' => \array_merge(
$this->additionalFields,
$fields
),
]
);
$this->objectAction = new CommandTriggerAction([ $this->trigger ], 'update', [ 'data' => array_merge($this->additionalFields, $fields) ]);
$this->objectAction->executeAction();
$this->saved();
@ -121,13 +102,11 @@ public function save()
/**
* @inheritDoc
*/
public function assignVariables()
{
public function assignVariables() {
parent::assignVariables();
WCF::getTPL()->assign([
'action' => 'edit',
'triggerID' => $this->trigger->triggerID,
WCF::getTPL()->assign([ 'action' => 'edit'
, 'triggerID' => $this->trigger->triggerID
]);
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,21 +14,18 @@
namespace chat\acp\form;
use chat\data\room\Room;
use chat\data\room\RoomAction;
use chat\data\room\RoomEditor;
use wcf\data\package\PackageCache;
use wcf\form\AbstractForm;
use wcf\system\acl\ACLHandler;
use wcf\system\exception\UserInputException;
use wcf\system\language\I18nHandler;
use wcf\system\WCF;
use \chat\data\room\Room;
use \chat\data\room\RoomAction;
use \chat\data\room\RoomEditor;
use \wcf\system\acl\ACLHandler;
use \wcf\system\exception\UserInputException;
use \wcf\system\language\I18nHandler;
use \wcf\system\WCF;
/**
* Shows the room add form.
*/
class RoomAddForm extends AbstractForm
{
class RoomAddForm extends \wcf\form\AbstractForm {
/**
* @inheritDoc
*/
@ -38,9 +34,7 @@ class RoomAddForm extends AbstractForm
/**
* @inheritDoc
*/
public $neededPermissions = [
'admin.chat.canManageRoom',
];
public $neededPermissions = [ 'admin.chat.canManageRoom' ];
/**
* Object type ID of the ACL object type for rooms.
@ -75,8 +69,7 @@ class RoomAddForm extends AbstractForm
/**
* @inheritDoc
*/
public function readParameters()
{
public function readParameters() {
parent::readParameters();
I18nHandler::getInstance()->register('title');
@ -88,40 +81,31 @@ public function readParameters()
/**
* @inheritDoc
*/
public function readFormParameters()
{
public function readFormParameters() {
parent::readFormParameters();
// read i18n values
I18nHandler::getInstance()->readValues();
// handle i18n plain input
if (I18nHandler::getInstance()->isPlainValue('title')) {
$this->title = I18nHandler::getInstance()->getValue('title');
}
if (I18nHandler::getInstance()->isPlainValue('topic')) {
$this->topic = I18nHandler::getInstance()->getValue('topic');
}
if (isset($_POST['userLimit'])) {
$this->userLimit = \intval($_POST['userLimit']);
}
if (isset($_POST['topicUseHtml'])) {
$this->topicUseHtml = true;
}
if (I18nHandler::getInstance()->isPlainValue('title')) $this->title = I18nHandler::getInstance()->getValue('title');
if (I18nHandler::getInstance()->isPlainValue('topic')) $this->topic = I18nHandler::getInstance()->getValue('topic');
if (isset($_POST['userLimit'])) $this->userLimit = intval($_POST['userLimit']);
if (isset($_POST['topicUseHtml'])) $this->topicUseHtml = true;
}
/**
* @inheritDoc
*/
public function validate()
{
public function validate() {
parent::validate();
// validate title
if (!I18nHandler::getInstance()->validateValue('title')) {
if (I18nHandler::getInstance()->isPlainValue('title')) {
throw new UserInputException('title');
} else {
}
else {
throw new UserInputException('title', 'multilingual');
}
}
@ -131,7 +115,7 @@ public function validate()
throw new UserInputException('topic');
}
if (\mb_strlen($this->topic) > 10000) {
if (mb_strlen($this->topic) > 10000) {
throw new UserInputException('topic', 'tooLong');
}
@ -143,39 +127,22 @@ public function validate()
/**
* @inheritDoc
*/
public function save()
{
public function save() {
parent::save();
$fields = [
'title' => $this->title,
'topic' => $this->topic,
'topicUseHtml' => (int)$this->topicUseHtml,
'userLimit' => $this->userLimit,
'position' => 0, // TODO
$fields = [ 'title' => $this->title
, 'topic' => $this->topic
, 'topicUseHtml' => (int) $this->topicUseHtml
, 'userLimit' => $this->userLimit
, 'position' => 0 // TODO
];
// create room
$this->objectAction = new RoomAction(
[ ],
'create',
[
'data' => \array_merge(
$this->additionalFields,
$fields
),
]
);
$this->objectAction = new \chat\data\room\RoomAction([], 'create', [ 'data' => array_merge($this->additionalFields, $fields) ]);
$returnValues = $this->objectAction->executeAction();
// save i18n values
$this->saveI18nValue(
$returnValues['returnValues'],
[
'title',
'topic',
]
);
$this->saveI18nValue($returnValues['returnValues'], [ 'title', 'topic' ]);
// save ACL
ACLHandler::getInstance()->save($returnValues['returnValues']->roomID, $this->aclObjectTypeID);
@ -200,32 +167,31 @@ public function save()
* @param Room $room
* @param string[] $columns
*/
public function saveI18nValue(Room $room, $columns)
{
public function saveI18nValue(Room $room, $columns) {
$data = [ ];
foreach ($columns as $columnName) {
$languageItem = 'chat.room.room'.$room->roomID.'.'.$columnName;
if (I18nHandler::getInstance()->isPlainValue($columnName)) {
if ($room->{$columnName} === $languageItem) {
if ($room->$columnName === $languageItem) {
I18nHandler::getInstance()->remove($languageItem);
}
} else {
$packageID = PackageCache::getInstance()->getPackageID('be.bastelstu.chat');
}
else {
$packageID = \wcf\data\package\PackageCache::getInstance()->getPackageID('be.bastelstu.chat');
I18nHandler::getInstance()->save(
$columnName,
$languageItem,
'chat.room',
$packageID
I18nHandler::getInstance()->save( $columnName
, $languageItem
, 'chat.room'
, $packageID
);
$data[$columnName] = $languageItem;
}
}
if ($data !== []) {
if (!empty($data)) {
(new RoomEditor($room))->update($data);
}
}
@ -233,18 +199,17 @@ public function saveI18nValue(Room $room, $columns)
/**
* @inheritDoc
*/
public function assignVariables()
{
public function assignVariables() {
parent::assignVariables();
ACLHandler::getInstance()->assignVariables($this->aclObjectTypeID);
I18nHandler::getInstance()->assignVariables();
WCF::getTPL()->assign([
'action' => 'add',
'aclObjectTypeID' => $this->aclObjectTypeID,
'userLimit' => $this->userLimit,
'topicUseHtml' => $this->topicUseHtml,
WCF::getTPL()->assign([ 'action' => 'add'
, 'aclObjectTypeID' => $this->aclObjectTypeID
, 'userLimit' => $this->userLimit
, 'topicUseHtml' => $this->topicUseHtml
]);
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,20 +14,16 @@
namespace chat\acp\form;
use chat\data\room\Room;
use chat\data\room\RoomAction;
use wcf\data\package\PackageCache;
use wcf\form\AbstractForm;
use wcf\system\acl\ACLHandler;
use wcf\system\exception\IllegalLinkException;
use wcf\system\language\I18nHandler;
use wcf\system\WCF;
use \chat\data\room\Room;
use \chat\data\room\RoomAction;
use \wcf\system\acl\ACLHandler;
use \wcf\system\language\I18nHandler;
use \wcf\system\WCF;
/**
* Shows the room edit form.
*/
class RoomEditForm extends RoomAddForm
{
class RoomEditForm extends RoomAddForm {
/**
* @inheritDoc
*/
@ -46,16 +41,13 @@ class RoomEditForm extends RoomAddForm
*
* @param Room
*/
public $room;
public $room = null;
/**
* @inheritDoc
*/
public function readParameters()
{
if (isset($_REQUEST['id'])) {
$this->roomID = \intval($_REQUEST['id']);
}
public function readParameters() {
if (isset($_REQUEST['id'])) $this->roomID = intval($_REQUEST['id']);
$this->room = new Room($this->roomID);
if (!$this->room) {
@ -68,24 +60,13 @@ public function readParameters()
/**
* @inheritDoc
*/
public function readData()
{
public function readData() {
parent::readData();
if (empty($_POST)) {
$packageID = PackageCache::getInstance()->getPackageID('be.bastelstu.chat');
I18nHandler::getInstance()->setOptions(
'title',
$packageID,
$this->room->title,
'chat.room.room\d+.title'
);
I18nHandler::getInstance()->setOptions(
'topic',
$packageID,
$this->room->topic,
'chat.room.room\d+.topic'
);
$packageID = \wcf\data\package\PackageCache::getInstance()->getPackageID('be.bastelstu.chat');
I18nHandler::getInstance()->setOptions('title', $packageID, $this->room->title, 'chat.room.room\d+.title');
I18nHandler::getInstance()->setOptions('topic', $packageID, $this->room->topic, 'chat.room.room\d+.topic');
$this->userLimit = $this->room->userLimit;
$this->topicUseHtml = $this->room->topicUseHtml;
}
@ -94,45 +75,25 @@ public function readData()
/**
* @inheritDoc
*/
public function save()
{
AbstractForm::save();
public function save() {
\wcf\form\AbstractForm::save();
$fields = [
'title' => $this->title,
'topic' => $this->topic,
'topicUseHtml' => (int)$this->topicUseHtml,
'userLimit' => $this->userLimit,
'position' => 0, // TODO
$fields = [ 'title' => $this->title
, 'topic' => $this->topic
, 'topicUseHtml' => (int) $this->topicUseHtml
, 'userLimit' => $this->userLimit
, 'position' => 0 // TODO
];
// update room
$this->objectAction = new RoomAction(
[ $this->room ],
'update',
[
'data' => \array_merge(
$this->additionalFields,
$fields
),
]
);
$this->objectAction = new RoomAction([ $this->room ], 'update', [ 'data' => array_merge($this->additionalFields, $fields) ]);
$returnValues = $this->objectAction->executeAction();
// save i18n values
$this->saveI18nValue(
$this->room,
[
'title',
'topic',
]
);
$this->saveI18nValue($this->room, [ 'title', 'topic' ]);
// save ACL
ACLHandler::getInstance()->save(
$this->room->roomID,
$this->aclObjectTypeID
);
ACLHandler::getInstance()->save($this->room->roomID, $this->aclObjectTypeID);
$this->saved();
@ -143,16 +104,14 @@ public function save()
/**
* @inheritDoc
*/
public function assignVariables()
{
public function assignVariables() {
parent::assignVariables();
I18nHandler::getInstance()->assignVariables(!empty($_POST));
WCF::getTPL()->assign([
'action' => 'edit',
'roomID' => $this->room->roomID,
'room' => $this->room,
WCF::getTPL()->assign([ 'action' => 'edit'
, 'roomID' => $this->room->roomID
, 'room' => $this->room
]);
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,14 +14,10 @@
namespace chat\acp\page;
use chat\data\command\CommandTriggerList;
use wcf\page\SortablePage;
/**
* Shows the command trigger list.
*/
final class CommandTriggerListPage extends SortablePage
{
class CommandTriggerListPage extends \wcf\page\SortablePage {
/**
* @inheritDoc
*/
@ -31,23 +26,17 @@ final class CommandTriggerListPage extends SortablePage
/**
* @inheritDoc
*/
public $neededPermissions = [
'admin.chat.canManageTriggers',
];
public $neededPermissions = [ 'admin.chat.canManageTriggers' ];
/**
* @inheritDoc
*/
public $objectListClassName = CommandTriggerList::class;
public $objectListClassName = \chat\data\command\CommandTriggerList::class;
/**
* @inheritDoc
*/
public $validSortFields = [
'triggerID',
'commandTrigger',
'className',
];
public $validSortFields = [ 'triggerID', 'commandTrigger', 'className' ];
/**
* @inheritDoc
@ -57,8 +46,7 @@ final class CommandTriggerListPage extends SortablePage
/**
* @inheritDoc
*/
protected function initObjectList()
{
protected function initObjectList() {
parent::initObjectList();
$this->objectList->sqlSelects = 'command.className';

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,14 +14,10 @@
namespace chat\acp\page;
use chat\data\room\RoomList;
use wcf\page\SortablePage;
/**
* Shows the room list.
*/
final class RoomListPage extends SortablePage
{
class RoomListPage extends \wcf\page\SortablePage {
/**
* @inheritDoc
*/
@ -31,22 +26,17 @@ final class RoomListPage extends SortablePage
/**
* @inheritDoc
*/
public $neededPermissions = [
'admin.chat.canManageRoom',
];
public $neededPermissions = [ 'admin.chat.canManageRoom' ];
/**
* @inheritDoc
*/
public $objectListClassName = RoomList::class;
public $objectListClassName = \chat\data\room\RoomList::class;
/**
* @inheritDoc
*/
public $validSortFields = [
'roomID',
'title',
];
public $validSortFields = [ 'roomID', 'title' ];
/**
* @inheritDoc

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,22 +14,16 @@
namespace chat\acp\page;
use chat\data\room\Room;
use chat\data\room\RoomList;
use chat\data\suspension\Suspension;
use chat\data\suspension\SuspensionList;
use wcf\data\object\type\ObjectTypeCache;
use wcf\data\user\User;
use wcf\page\SortablePage;
use wcf\system\cache\runtime\UserRuntimeCache;
use wcf\system\WCF;
use wcf\util\StringUtil;
use \chat\data\room\Room;
use \chat\data\suspension\Suspension;
use \wcf\data\user\User;
use \wcf\system\WCF;
use \wcf\util\StringUtil;
/**
* Shows the suspension list.
*/
final class SuspensionListPage extends SortablePage
{
class SuspensionListPage extends \wcf\page\SortablePage {
/**
* @inheritDoc
*/
@ -39,24 +32,17 @@ final class SuspensionListPage extends SortablePage
/**
* @inheritDoc
*/
public $neededPermissions = [
'admin.chat.canManageSuspensions',
];
public $neededPermissions = [ 'admin.chat.canManageSuspensions' ];
/**
* @inheritDoc
*/
public $objectListClassName = SuspensionList::class;
public $objectListClassName = \chat\data\suspension\SuspensionList::class;
/**
* @inheritDoc
*/
public $validSortFields = [
'suspensionID',
'time',
'expires',
'revoked',
];
public $validSortFields = [ 'suspensionID', 'time', 'expires', 'revoked' ];
/**
* @inheritDoc
@ -72,25 +58,25 @@ final class SuspensionListPage extends SortablePage
* userID filter
* @var int
*/
public $userID;
public $userID = null;
/**
* roomID filter
* @var int
*/
public $roomID;
public $roomID = null;
/**
* objectTypeID filter
* @var int
*/
public $objectTypeID;
public $objectTypeID = null;
/**
* judgeID filter
* @var int
*/
public $judgeID;
public $judgeID = null;
/**
* Whether to show expired entries
@ -102,13 +88,13 @@ final class SuspensionListPage extends SortablePage
* username filter
* @var string
*/
public $searchUsername;
public $searchUsername = null;
/**
* judge's username filter
* @var string
*/
public $searchJudge;
public $searchJudge = null;
/**
* Array of available suspension object types
@ -125,44 +111,35 @@ final class SuspensionListPage extends SortablePage
/**
* @inheritDoc
*/
public function readParameters()
{
public function readParameters() {
parent::readParameters();
if (isset($_REQUEST['roomID']) && $_REQUEST['roomID'] !== '') {
$this->roomID = \intval($_REQUEST['roomID']);
}
if (isset($_REQUEST['userID']) && $_REQUEST['userID'] !== '') {
$this->userID = \intval($_REQUEST['userID']);
}
if (isset($_REQUEST['judgeID']) && $_REQUEST['judgeID'] !== '') {
$this->judgeID = \intval($_REQUEST['judgeID']);
}
if (isset($_REQUEST['objectTypeID']) && $_REQUEST['objectTypeID'] !== '') {
$this->objectTypeID = \intval($_REQUEST['objectTypeID']);
}
if (isset($_REQUEST['roomID']) && $_REQUEST['roomID'] !== '') $this->roomID = intval($_REQUEST['roomID']);
if (isset($_REQUEST['userID']) && $_REQUEST['userID'] !== '') $this->userID = intval($_REQUEST['userID']);
if (isset($_REQUEST['judgeID']) && $_REQUEST['judgeID'] !== '') $this->judgeID = intval($_REQUEST['judgeID']);
if (isset($_REQUEST['objectTypeID']) && $_REQUEST['objectTypeID'] !== '') $this->objectTypeID = intval($_REQUEST['objectTypeID']);
// Checkboxes need special handling
if (!empty($_POST) && !isset($_POST['showExpired'])) {
$this->showExpired = false;
}
if (!empty($_POST) && !isset($_POST['showExpired'])) $this->showExpired = false;
if (isset($_POST['searchUsername'])) {
$this->searchUsername = StringUtil::trim($_POST['searchUsername']);
if ($this->searchUsername !== '') {
if (!empty($this->searchUsername)) {
$this->userID = User::getUserByUsername($this->searchUsername)->userID;
}
} elseif ($this->userID !== null) {
}
else if ($this->userID !== null) {
$this->searchUsername = (new User($this->userID))->username;
}
if (isset($_POST['searchJudge'])) {
$this->searchJudge = StringUtil::trim($_POST['searchJudge']);
if ($this->searchJudge !== '') {
if (!empty($this->searchJudge)) {
$this->judgeID = User::getUserByUsername($this->searchJudge)->userID;
}
} elseif ($this->judgeID !== null) {
}
else if ($this->judgeID !== null) {
$this->searchJudge = (new User($this->judgeID))->username;
}
}
@ -170,18 +147,17 @@ public function readParameters()
/**
* @inheritDoc
*/
public function readData()
{
$this->availableObjectTypes = ObjectTypeCache::getInstance()->getObjectTypes('be.bastelstu.chat.suspension');
public function readData() {
$this->availableObjectTypes = \wcf\data\object\type\ObjectTypeCache::getInstance()->getObjectTypes('be.bastelstu.chat.suspension');
$roomList = new RoomList();
$roomList = new \chat\data\room\RoomList();
$roomList->sqlOrderBy = "room.position";
$roomList->readObjects();
$this->availableRooms = $roomList->getObjects();
parent::readData();
UserRuntimeCache::getInstance()->cacheObjectIDs(\array_map(static function (Suspension $s) {
\wcf\system\cache\runtime\UserRuntimeCache::getInstance()->cacheObjectIDs(array_map(function (Suspension $s) {
return $s->userID;
}, $this->objectList->getObjects()));
}
@ -189,17 +165,17 @@ public function readData()
/**
* @inheritDoc
*/
protected function initObjectList()
{
protected function initObjectList() {
parent::initObjectList();
$this->objectList->sqlSelects .= 'COALESCE(suspension.revoked, suspension.expires, 2147483647) AS expiresSort';
if (!empty($this->availableRooms)) {
$this->objectList->getConditionBuilder()->add('(roomID IN (?) OR roomID IS NULL)', [ \array_map(static function (Room $room) {
$this->objectList->getConditionBuilder()->add('(roomID IN (?) OR roomID IS NULL)', [ array_map(function (Room $room) {
return $room->roomID;
}, $this->availableRooms) ]);
} else {
}
else {
$this->objectList->getConditionBuilder()->add('1 = 0');
}
@ -210,7 +186,8 @@ protected function initObjectList()
if ($this->roomID !== null) {
if ($this->roomID === 0) {
$this->objectList->getConditionBuilder()->add('roomID IS NULL');
} else {
}
else {
$this->objectList->getConditionBuilder()->add('roomID = ?', [ $this->roomID ]);
}
}
@ -231,20 +208,18 @@ protected function initObjectList()
/**
* @inheritDoc
*/
public function assignVariables()
{
public function assignVariables() {
parent::assignVariables();
WCF::getTPL()->assign([
'userID' => $this->userID,
'roomID' => $this->roomID,
'objectTypeID' => $this->objectTypeID,
'judgeID' => $this->judgeID,
'availableRooms' => $this->availableRooms,
'availableObjectTypes' => $this->availableObjectTypes,
'searchUsername' => $this->searchUsername,
'searchJudge' => $this->searchJudge,
'showExpired' => $this->showExpired,
WCF::getTPL()->assign([ 'userID' => $this->userID
, 'roomID' => $this->roomID
, 'objectTypeID' => $this->objectTypeID
, 'judgeID' => $this->judgeID
, 'availableRooms' => $this->availableRooms
, 'availableObjectTypes' => $this->availableObjectTypes
, 'searchUsername' => $this->searchUsername
, 'searchJudge' => $this->searchJudge
, 'showExpired' => $this->showExpired
]);
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,32 +14,27 @@
namespace chat\data\command;
use chat\system\command\ICommand;
use wcf\data\package\PackageCache;
use wcf\data\ProcessibleDatabaseObject;
use wcf\system\WCF;
use \wcf\system\WCF;
/**
* Represents a chat command.
*/
class Command extends ProcessibleDatabaseObject
{
class Command extends \wcf\data\ProcessibleDatabaseObject {
/**
* @inheritDoc
*/
protected static $processorInterface = ICommand::class;
protected static $processorInterface = \chat\system\command\ICommand::class;
/**
* Returns whether this command has at least one trigger assigned.
*
* The default PlainCommand implicitely has one.
*/
public function hasTriggers(): bool
{
public function hasTriggers() {
static $chatPackageID = null;
if ($chatPackageID === null) {
$chatPackageID = PackageCache::getInstance()->getPackageID('be.bastelstu.chat');
$chatPackageID = \wcf\data\package\PackageCache::getInstance()->getPackageID('be.bastelstu.chat');
}
if ($this->packageID === $chatPackageID && $this->identifier === 'plain') {
@ -48,13 +42,10 @@ public function hasTriggers(): bool
}
$sql = "SELECT COUNT(*)
FROM chat1_command_trigger
FROM chat".WCF_N."_command_trigger
WHERE commandID = ?";
$statement = WCF::getDB()->prepare($sql);
$statement->execute([
$this->commandID,
]);
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute([ $this->commandID ]);
return $statement->fetchSingleColumn() > 0;
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,15 +14,10 @@
namespace chat\data\command;
use chat\system\cache\builder\CommandCacheBuilder;
use wcf\data\package\Package;
use wcf\system\SingletonFactory;
/**
* Manages the command cache.
*/
final class CommandCache extends SingletonFactory
{
class CommandCache extends \wcf\system\SingletonFactory {
/**
* list of cached commands
* @var Command[]
@ -45,9 +39,8 @@ final class CommandCache extends SingletonFactory
/**
* @inheritDoc
*/
protected function init()
{
$data = CommandCacheBuilder::getInstance()->getData();
protected function init() {
$data = \chat\system\cache\builder\CommandCacheBuilder::getInstance()->getData();
$this->commands = $data['commands'];
$this->packages = $data['packages'];
@ -56,9 +49,11 @@ protected function init()
/**
* Returns a specific command.
*
* @param integer $commandID
* @return Command
*/
public function getCommand(int $commandID): ?Command
{
public function getCommand($commandID) {
if (isset($this->commands[$commandID])) {
return $this->commands[$commandID];
}
@ -68,9 +63,11 @@ public function getCommand(int $commandID): ?Command
/**
* Returns a specific command defined by a trigger.
*
* @param string $trigger
* @return Command
*/
public function getCommandByTrigger(string $trigger): ?Command
{
public function getCommandByTrigger($trigger) {
if (isset($this->triggers[$trigger])) {
return $this->commands[$this->triggers[$trigger]];
}
@ -80,9 +77,12 @@ public function getCommandByTrigger(string $trigger): ?Command
/**
* Returns the command defined by the given package and identifier.
*
* @param \wcf\data\package\Package $package
* @param string $identifier
* @return Command
*/
public function getCommandByPackageAndIdentifier(Package $package, string $identifier): ?Command
{
public function getCommandByPackageAndIdentifier(\wcf\data\package\Package $package, $identifier) {
if (isset($this->packages[$package->packageID][$identifier])) {
return $this->packages[$package->packageID][$identifier];
}
@ -95,8 +95,7 @@ public function getCommandByPackageAndIdentifier(Package $package, string $ident
*
* @return Command[]
*/
public function getCommands()
{
public function getCommands() {
return $this->commands;
}
@ -105,8 +104,7 @@ public function getCommands()
*
* @return int[]
*/
public function getTriggers()
{
public function getTriggers() {
return $this->triggers;
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,13 +14,10 @@
namespace chat\data\command;
use wcf\data\DatabaseObjectEditor;
/**
* Represents a chat command editor.
*/
class CommandEditor extends DatabaseObjectEditor
{
class CommandEditor extends \wcf\data\DatabaseObjectEditor {
/**
* @inheritDoc
*/

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,17 +14,8 @@
namespace chat\data\command;
use wcf\data\DatabaseObjectList;
/**
* Represents a list of chat commands.
*
* @method Command current()
* @method Command[] getObjects()
* @method Command|null getSingleObject()
* @method Command|null search($objectID)
* @property Command[] $objects
*/
class CommandList extends DatabaseObjectList
{
class CommandList extends \wcf\data\DatabaseObjectList {
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,47 +14,40 @@
namespace chat\data\command;
use wcf\data\DatabaseObject;
use wcf\system\request\IRouteController;
use wcf\system\WCF;
use \wcf\system\WCF;
/**
* Represents a chat command trigger.
* Represents a chat command trugger.
*/
class CommandTrigger extends DatabaseObject implements IRouteController
{
class CommandTrigger extends \wcf\data\DatabaseObject implements \wcf\system\request\IRouteController {
/**
* @inheritDoc
*/
public function getTitle(): string
{
public function getTitle() {
return $this->commandTrigger;
}
/**
* @inheritDoc
*/
public function getObjectID()
{
public function getObjectID() {
return $this->triggerID;
}
/**
* Returns the trigger specified by its commandTrigger value
*
* @param string $name
* @return CommandTrigger
*/
public static function getTriggerByName(string $name)
{
public static function getTriggerByName($name) {
$sql = "SELECT *
FROM chat1_command_trigger
FROM chat".WCF_N."_command_trigger
WHERE commandTrigger = ?";
$statement = WCF::getDB()->prepare($sql);
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute([ $name ]);
$row = $statement->fetchArray();
if (!$row) {
$row = [];
}
if (!$row) $row = [];
return new self(null, $row);
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,24 +14,17 @@
namespace chat\data\command;
use wcf\data\AbstractDatabaseObjectAction;
/**
* Executes command trigger-related actions.
*/
class CommandTriggerAction extends AbstractDatabaseObjectAction
{
class CommandTriggerAction extends \wcf\data\AbstractDatabaseObjectAction {
/**
* @inheritDoc
*/
protected $permissionsDelete = [
'admin.chat.canManageTriggers',
];
protected $permissionsDelete = [ 'admin.chat.canManageTriggers' ];
/**
* @inheritDoc
*/
protected $permissionsUpdate = [
'admin.chat.canManageTriggers',
];
protected $permissionsUpdate = [ 'admin.chat.canManageTriggers' ];
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,15 +14,10 @@
namespace chat\data\command;
use chat\system\cache\builder\CommandCacheBuilder;
use wcf\data\DatabaseObjectEditor;
use wcf\data\IEditableCachedObject;
/**
* Represents a command trigger editor.
*/
class CommandTriggerEditor extends DatabaseObjectEditor implements IEditableCachedObject
{
class CommandTriggerEditor extends \wcf\data\DatabaseObjectEditor implements \wcf\data\IEditableCachedObject {
/**
* @inheritDoc
*/
@ -32,8 +26,7 @@ class CommandTriggerEditor extends DatabaseObjectEditor implements IEditableCach
/**
* @inheritDoc
*/
public static function resetCache()
{
CommandCacheBuilder::getInstance()->reset();
public static function resetCache() {
\chat\system\cache\builder\CommandCacheBuilder::getInstance()->reset();
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,17 +14,7 @@
namespace chat\data\command;
use wcf\data\DatabaseObjectList;
/**
* Represents a list command triggers.
*
* @method CommandTrigger current()
* @method CommandTrigger[] getObjects()
* @method CommandTrigger|null getSingleObject()
* @method CommandTrigger|null search($objectID)
* @property CommandTrigger[] $objects
*/
class CommandTriggerList extends DatabaseObjectList
{
}
class CommandTriggerList extends \wcf\data\DatabaseObjectList { }

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,11 +14,9 @@
namespace chat\data\message;
use chat\data\room\Room;
use chat\data\room\RoomCache;
use wcf\data\DatabaseObject;
use wcf\data\object\type\ObjectType;
use wcf\data\object\type\ObjectTypeCache;
use \chat\data\room\Room;
use \wcf\data\object\type\ObjectType;
use \wcf\data\object\type\ObjectTypeCache;
/**
* Represents a chat message.
@ -34,17 +31,15 @@
* @property-read integer $hasEmbeddedObjects
* @property-read integer $isDeleted
*/
class Message extends DatabaseObject
{
class Message extends \wcf\data\DatabaseObject {
/**
* @inheritDoc
*/
protected function handleData($data)
{
protected function handleData($data) {
parent::handleData($data);
$this->data['payload'] = @\unserialize($this->data['payload']);
if (!\is_array($this->data['payload'])) {
$this->data['payload'] = @unserialize($this->data['payload']);
if (!is_array($this->data['payload'])) {
$this->data['payload'] = [ ];
}
}
@ -52,24 +47,21 @@ protected function handleData($data)
/**
* Returns whether this message already is inside the log.
*/
public function isInLog(): bool
{
public function isInLog(): bool {
return $this->time < (TIME_NOW - CHAT_ARCHIVE_AFTER);
}
/**
* Returns the message type object of this message.
*/
public function getMessageType(): ObjectType
{
public function getMessageType(): ObjectType {
return ObjectTypeCache::getInstance()->getObjectType($this->objectTypeID);
}
/**
* Returns the chat room that contains this message.
*/
public function getRoom(): Room
{
return RoomCache::getInstance()->getRoom($this->roomID);
public function getRoom(): Room {
return \chat\data\room\RoomCache::getInstance()->getRoom($this->roomID);
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,75 +14,45 @@
namespace chat\data\message;
use chat\data\command\CommandCache;
use chat\data\room\RoomCache;
use chat\data\user\User as ChatUser;
use chat\data\user\UserAction as ChatUserAction;
use chat\system\message\type\IDeletableMessageType;
use wcf\data\AbstractDatabaseObjectAction;
use wcf\data\object\type\ObjectTypeCache;
use wcf\system\attachment\AttachmentHandler;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\exception\UserInputException;
use wcf\system\html\input\HtmlInputProcessor;
use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
use wcf\system\push\PushHandler;
use wcf\system\user\activity\point\UserActivityPointHandler;
use wcf\system\WCF;
use \chat\data\command\CommandCache;
use \chat\data\room\RoomCache;
use \wcf\data\object\type\ObjectTypeCache;
use \wcf\system\attachment\AttachmentHandler;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\exception\UserInputException;
use \wcf\system\user\activity\point\UserActivityPointHandler;
use \wcf\system\WCF;
/**
* Executes chat user-related actions.
*/
class MessageAction extends AbstractDatabaseObjectAction
{
class MessageAction extends \wcf\data\AbstractDatabaseObjectAction {
/**
* @inheritDoc
*/
public function create()
{
public function create() {
$message = parent::create();
\assert($message instanceof Message);
if (isset($this->parameters['updateTimestamp']) && $this->parameters['updateTimestamp']) {
$sql = "UPDATE chat1_room_to_user
SET lastPush = ?
WHERE roomID = ?
AND userID = ?";
$statement = WCF::getDB()->prepare($sql);
$statement->execute([
TIME_NOW,
$message->roomID,
$message->userID,
]);
$sql = "UPDATE chat".WCF_N."_room_to_user SET lastPush = ? WHERE roomID = ? AND userID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute([ TIME_NOW, $message->roomID, $message->userID ]);
}
if (isset($this->parameters['grantPoints']) && $this->parameters['grantPoints']) {
UserActivityPointHandler::getInstance()->fireEvent(
'be.bastelstu.chat.activityPointEvent.message',
$message->messageID,
$message->userID
);
UserActivityPointHandler::getInstance()->fireEvent('be.bastelstu.chat.activityPointEvent.message', $message->messageID, $message->userID);
}
$pushHandler = PushHandler::getInstance();
if ($pushHandler->isEnabled() && \in_array('target:channels', $pushHandler->getFeatureFlags())) {
$pushHandler = \wcf\system\push\PushHandler::getInstance();
if ($pushHandler->isEnabled() && in_array('target:channels', $pushHandler->getFeatureFlags())) {
$fastSelect = $message->getMessageType()->getProcessor()->supportsFastSelect();
if ($fastSelect) {
$target = [
'channels' => [
'be.bastelstu.chat.room-' . $message->roomID,
],
];
} else {
$target = [
'channels' => [
'be.bastelstu.chat',
],
];
$target = [ 'channels' => [ 'be.bastelstu.chat.room-'.$message->roomID ] ];
}
$pushHandler->sendMessage([
'message' => 'be.bastelstu.chat.message',
'target' => $target,
else {
$target = [ 'channels' => [ 'be.bastelstu.chat' ] ];
}
$pushHandler->sendMessage([ 'message' => 'be.bastelstu.chat.message'
, 'target' => $target
]);
}
@ -93,8 +62,7 @@ public function create()
/**
* Validates parameters and permissions.
*/
public function validateTrash()
{
public function validateTrash() {
// read objects
if (empty($this->objects)) {
$this->readObjects();
@ -105,15 +73,10 @@ public function validateTrash()
}
foreach ($this->getObjects() as $message) {
if ($message->isDeleted) {
continue;
}
if ($message->isDeleted) continue;
$messageType = $message->getMessageType()->getProcessor();
if (
!($messageType instanceof IDeletableMessageType)
|| !$messageType->canDelete($message->getDecoratedObject())
) {
if (!($messageType instanceof \chat\system\message\type\IDeletableMessageType) || !$messageType->canDelete($message->getDecoratedObject())) {
throw new PermissionDeniedException();
}
}
@ -124,54 +87,35 @@ public function validateTrash()
*
* Note: Contrary to other applications there is no way to undelete a message.
*/
public function trash()
{
public function trash() {
if (empty($this->objects)) {
$this->readObjects();
}
$data = [
'isDeleted' => 1,
$data = [ 'isDeleted' => 1
];
$objectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName(
'be.bastelstu.chat.messageType',
'be.bastelstu.chat.messageType.tombstone'
);
$objectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName('be.bastelstu.chat.messageType', 'be.bastelstu.chat.messageType.tombstone');
if (!$objectTypeID) {
throw new \LogicException('Missing object type');
}
WCF::getDB()->beginTransaction();
$objectAction = new static(
$this->getObjects(),
'update',
[
'data' => $data,
]
);
$objectAction = new static($this->getObjects(), 'update', [ 'data' => $data ]);
$objectAction->executeAction();
foreach ($this->getObjects() as $message) {
if ($message->isDeleted) {
continue;
}
if ($message->isDeleted) continue;
(new self(
[ ],
'create',
[
'data' => [
'roomID' => $message->roomID,
'userID' => null,
'username' => '',
'time' => TIME_NOW,
'objectTypeID' => $objectTypeID,
'payload' => \serialize([
'messageID' => $message->messageID,
]),
],
(new MessageAction([ ], 'create', [ 'data' => [ 'roomID' => $message->roomID
, 'userID' => null
, 'username' => ''
, 'time' => TIME_NOW
, 'objectTypeID' => $objectTypeID
, 'payload' => serialize([ 'messageID' => $message->messageID ])
]
))->executeAction();
]
)
)->executeAction();
}
WCF::getDB()->commitTransaction();
}
@ -179,56 +123,38 @@ public function trash()
/**
* Prunes chat messages older than chat_log_archivetime days.
*/
public function prune()
{
public function prune() {
// Check whether pruning is disabled.
if (!CHAT_LOG_ARCHIVETIME) {
return;
}
if (!CHAT_LOG_ARCHIVETIME) return;
$sql = "SELECT messageID
FROM chat1_message
FROM chat".WCF_N."_message
WHERE time < ?";
$statement = WCF::getDB()->prepare($sql);
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute([ TIME_NOW - CHAT_LOG_ARCHIVETIME * 86400 ]);
$messageIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
return \call_user_func(
[$this->className, 'deleteAll'],
$messageIDs
);
return call_user_func([$this->className, 'deleteAll'], $messageIDs);
}
/**
* Validates parameters and permissions.
*/
public function validatePull()
{
public function validatePull() {
$this->readString('sessionID', true);
if ($this->parameters['sessionID']) {
$this->parameters['sessionID'] = \pack(
'H*',
\str_replace('-', '', $this->parameters['sessionID'])
);
$this->parameters['sessionID'] = pack('H*', str_replace('-', '', $this->parameters['sessionID']));
}
$this->readInteger('roomID');
$this->readBoolean('inLog', true);
$room = RoomCache::getInstance()->getRoom($this->parameters['roomID']);
if ($room === null) {
throw new UserInputException('roomID');
}
if (!$room->canSee($user = null, $reason)) {
throw $reason;
}
$user = new ChatUser(WCF::getUser());
if (!$this->parameters['inLog'] && !$user->isInRoom($room)) {
throw new PermissionDeniedException();
}
if ($this->parameters['inLog'] && !$room->canSeeLog(null, $reason)) {
throw $reason;
}
if ($room === null) throw new UserInputException('roomID');
if (!$room->canSee($user = null, $reason)) throw $reason;
$user = new \chat\data\user\User(WCF::getUser());
if (!$this->parameters['inLog'] && !$user->isInRoom($room)) throw new PermissionDeniedException();
if ($this->parameters['inLog'] && !$room->canSeeLog(null, $reason)) throw $reason;
$this->readInteger('from', true);
$this->readInteger('to', true);
@ -242,56 +168,51 @@ public function validatePull()
/**
* Pulls messages for the given room.
*/
public function pull()
{
public function pull() {
$room = RoomCache::getInstance()->getRoom($this->parameters['roomID']);
if ($room === null) {
throw new UserInputException('roomID');
}
if ($room === null) throw new UserInputException('roomID');
if (($sessionID = $this->parameters['sessionID'])) {
if (\strlen($sessionID) !== 16) {
throw new UserInputException('sessionID');
}
if (strlen($sessionID) !== 16) throw new UserInputException('sessionID');
(new ChatUserAction([], 'clearDeadSessions'))->executeAction();
(new \chat\data\user\UserAction([], 'clearDeadSessions'))->executeAction();
WCF::getDB()->beginTransaction();
// update timestamp
$sql = "UPDATE chat1_room_to_user
$sql = "UPDATE chat".WCF_N."_room_to_user
SET lastPull = ?
WHERE roomID = ?
AND userID = ?";
$statement = WCF::getDB()->prepare($sql);
$statement->execute([ TIME_NOW,
$room->roomID,
WCF::getUser()->userID,
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute([ TIME_NOW
, $room->roomID
, WCF::getUser()->userID
]);
$sql = "UPDATE chat1_session
$sql = "UPDATE chat".WCF_N."_session
SET lastRequest = ?
WHERE roomID = ?
AND userID = ?
AND sessionID = ?";
$statement = WCF::getDB()->prepare($sql);
$statement->execute([ TIME_NOW,
$room->roomID,
WCF::getUser()->userID,
$sessionID,
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute([ TIME_NOW
, $room->roomID
, WCF::getUser()->userID
, $sessionID
]);
WCF::getDB()->commitTransaction();
}
// Determine message types supporting fast select
$objectTypes = ObjectTypeCache::getInstance()->getObjectTypes('be.bastelstu.chat.messageType');
$fastSelect = \array_map(static function ($item) {
$objectTypes = \wcf\data\object\type\ObjectTypeCache::getInstance()->getObjectTypes('be.bastelstu.chat.messageType');
$fastSelect = array_map(function ($item) {
return $item->objectTypeID;
}, \array_filter($objectTypes, static function ($item) {
}, array_filter($objectTypes, function ($item) {
return $item->getProcessor()->supportsFastSelect();
}));
// Build fast select filter
$condition = new PreparedStatementConditionBuilder();
$condition = new \wcf\system\database\util\PreparedStatementConditionBuilder();
$condition->add('((roomID = ? AND objectTypeID IN (?)) OR objectTypeID NOT IN (?))', [ $room->roomID, $fastSelect, $fastSelect ]);
$sortOrder = 'DESC';
@ -305,10 +226,10 @@ public function pull()
}
$sql = "SELECT messageID
FROM chat1_message
FROM chat".WCF_N."_message
".$condition."
ORDER BY messageID ".$sortOrder;
$statement = WCF::getDB()->prepare($sql, 20);
$statement = WCF::getDB()->prepareStatement($sql, 20);
$statement->execute($condition->getParameters());
$messageIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
@ -318,58 +239,49 @@ public function pull()
$objects = $objectList->getObjects();
$canSeeLog = $room->canSeeLog();
$messages = \array_map(static function (Message $item) use ($room) {
$messages = array_map(function (Message $item) use ($room) {
return new ViewableMessage($item, $room);
}, \array_filter($objects, function (Message $message) use ($canSeeLog, $room) {
}, array_filter($objects, function (Message $message) use ($canSeeLog, $room) {
if ($this->parameters['inLog'] || $message->isInLog()) {
return $canSeeLog && $message->getMessageType()->getProcessor()->canSeeInLog($message, $room);
} else {
}
else {
return $message->getMessageType()->getProcessor()->canSee($message, $room);
}
}));
$embeddedObjectMessageIDs = \array_map(static function ($message) {
$embeddedObjectMessageIDs = array_map(function ($message) {
return $message->messageID;
}, \array_filter($messages, static function ($message) {
}, array_filter($messages, function ($message) {
return $message->hasEmbeddedObjects;
}));
if ($embeddedObjectMessageIDs !== []) {
if (!empty($embeddedObjectMessageIDs)) {
// load embedded objects
MessageEmbeddedObjectManager::getInstance()->loadObjects('be.bastelstu.chat.message', $embeddedObjectMessageIDs);
\wcf\system\message\embedded\object\MessageEmbeddedObjectManager::getInstance()->loadObjects('be.bastelstu.chat.message', $embeddedObjectMessageIDs);
}
return [
'messages' => $messages,
'from' => $this->parameters['from'] ?: (!empty($objects) ? \reset($objects)->messageID : $this->parameters['to'] + 1),
'to' => $this->parameters['to'] ?: (!empty($objects) ? \end($objects)->messageID : $this->parameters['from'] - 1),
return [ 'messages' => $messages
, 'from' => $this->parameters['from'] ?: (!empty($objects) ? reset($objects)->messageID : $this->parameters['to'] + 1)
, 'to' => $this->parameters['to'] ?: (!empty($objects) ? end($objects)->messageID : $this->parameters['from'] - 1)
];
}
/**
* Validates parameters and permissions.
*/
public function validatePush()
{
public function validatePush() {
$this->readInteger('roomID');
$room = RoomCache::getInstance()->getRoom($this->parameters['roomID']);
if ($room === null) {
throw new UserInputException('roomID');
}
if (!$room->canSee($user = null, $reason)) {
throw $reason;
}
$user = new ChatUser(WCF::getUser());
if (!$user->isInRoom($room)) {
throw new PermissionDeniedException();
}
if ($room === null) throw new UserInputException('roomID');
if (!$room->canSee($user = null, $reason)) throw $reason;
$user = new \chat\data\user\User(WCF::getUser());
if (!$user->isInRoom($room)) throw new PermissionDeniedException();
$this->readInteger('commandID');
$command = CommandCache::getInstance()->getCommand($this->parameters['commandID']);
if ($command === null) {
throw new UserInputException('commandID');
}
if ($command === null) throw new UserInputException('commandID');
if (!$command->hasTriggers()) {
if (!$command->getProcessor()->allowWithoutTrigger()) {
throw new UserInputException('commandID');
@ -382,17 +294,12 @@ public function validatePush()
/**
* Pushes a new message into the given room.
*/
public function push()
{
public function push() {
$room = RoomCache::getInstance()->getRoom($this->parameters['roomID']);
if ($room === null) {
throw new UserInputException('roomID');
}
if ($room === null) throw new UserInputException('roomID');
$command = CommandCache::getInstance()->getCommand($this->parameters['commandID']);
if ($command === null) {
throw new UserInputException('commandID');
}
if ($command === null) throw new UserInputException('commandID');
$processor = $command->getProcessor();
$processor->validate($this->parameters['parameters'], $room);
@ -402,25 +309,16 @@ public function push()
/**
* Validates parameters and permissions.
*/
public function validatePushAttachment()
{
public function validatePushAttachment() {
$this->readInteger('roomID');
$room = RoomCache::getInstance()->getRoom($this->parameters['roomID']);
if ($room === null) {
throw new UserInputException('roomID');
}
if (!$room->canSee($user = null, $reason)) {
throw $reason;
}
$user = new ChatUser(WCF::getUser());
if (!$user->isInRoom($room)) {
throw new PermissionDeniedException();
}
if ($room === null) throw new UserInputException('roomID');
if (!$room->canSee($user = null, $reason)) throw $reason;
$user = new \chat\data\user\User(WCF::getUser());
if (!$user->isInRoom($room)) throw new PermissionDeniedException();
if (!$room->canWritePublicly(null, $reason)) {
throw $reason;
}
if (!$room->canWritePublicly(null, $reason)) throw $reason;
$this->readString('tmpHash');
}
@ -428,63 +326,45 @@ public function validatePushAttachment()
/**
* Pushes a new attachment into the given room.
*/
public function pushAttachment()
{
$objectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName(
'be.bastelstu.chat.messageType',
'be.bastelstu.chat.messageType.attachment'
);
if (!$objectTypeID) {
throw new \LogicException('Missing object type');
}
public function pushAttachment() {
$objectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName('be.bastelstu.chat.messageType', 'be.bastelstu.chat.messageType.attachment');
if (!$objectTypeID) throw new \LogicException('Missing object type');
$room = RoomCache::getInstance()->getRoom($this->parameters['roomID']);
if ($room === null) {
throw new UserInputException('roomID');
}
if ($room === null) throw new UserInputException('roomID');
$attachmentHandler = new AttachmentHandler(
'be.bastelstu.chat.message',
0,
$this->parameters['tmpHash'],
$room->roomID
);
$attachmentHandler = new AttachmentHandler('be.bastelstu.chat.message', 0, $this->parameters['tmpHash'], $room->roomID);
$attachments = $attachmentHandler->getAttachmentList();
$attachmentIDs = [];
foreach ($attachments as $attachment) {
$attachmentIDs[] = $attachment->attachmentID;
}
$processor = new HtmlInputProcessor();
$processor->process(\implode(' ', \array_map(static function ($attachmentID) {
$processor = new \wcf\system\html\input\HtmlInputProcessor();
$processor->process(implode(' ', array_map(function ($attachmentID) {
return '[attach='.$attachmentID.',none,true][/attach]';
}, $attachmentIDs)), 'be.bastelstu.chat.message', 0);
WCF::getDB()->beginTransaction();
/** @var Message $message */
$message = (new self(
[ ],
'create',
[
'data' => [
'roomID' => $room->roomID,
'userID' => WCF::getUser()->userID,
'username' => WCF::getUser()->username,
'time' => TIME_NOW,
'objectTypeID' => $objectTypeID,
'payload' => \serialize([
'attachmentIDs' => $attachmentIDs,
'message' => $processor->getHtml(),
]),
],
$message = (new MessageAction([ ], 'create', [ 'data' => [ 'roomID' => $room->roomID
, 'userID' => WCF::getUser()->userID
, 'username' => WCF::getUser()->username
, 'time' => TIME_NOW
, 'objectTypeID' => $objectTypeID
, 'payload' => serialize([ 'attachmentIDs' => $attachmentIDs
, 'message' => $processor->getHtml()
])
]
))->executeAction()['returnValues'];
]
)
)->executeAction()['returnValues'];
$attachmentHandler->updateObjectID($message->messageID);
$processor->setObjectID($message->messageID);
if (MessageEmbeddedObjectManager::getInstance()->registerObjects($processor)) {
if (\wcf\system\message\embedded\object\MessageEmbeddedObjectManager::getInstance()->registerObjects($processor)) {
(new MessageEditor($message))->update([
'hasEmbeddedObjects' => 1,
'hasEmbeddedObjects' => 1
]);
}
WCF::getDB()->commitTransaction();

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,15 +14,13 @@
namespace chat\data\message;
use wcf\data\DatabaseObjectEditor;
use wcf\system\attachment\AttachmentHandler;
use wcf\system\WCF;
use \wcf\system\attachment\AttachmentHandler;
use \wcf\system\WCF;
/**
* Represents a chat message editor.
*/
class MessageEditor extends DatabaseObjectEditor
{
class MessageEditor extends \wcf\data\DatabaseObjectEditor {
/**
* @inheritDoc
*/
@ -32,12 +29,11 @@ class MessageEditor extends DatabaseObjectEditor
/**
* @inheritDoc
*/
public static function deleteAll(array $messageIDs = [])
{
public static function deleteAll(array $messageIDs = []) {
WCF::getDB()->beginTransaction();
$result = parent::deleteAll($messageIDs);
if ($messageIDs !== []) {
if (!empty($messageIDs)) {
AttachmentHandler::removeAttachments('be.bastelstu.chat.message', $messageIDs);
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,17 +14,8 @@
namespace chat\data\message;
use wcf\data\DatabaseObjectList;
/**
* Represents a list of chat messages.
*
* @method Message current()
* @method Message[] getObjects()
* @method Message|null getSingleObject()
* @method Message|null search($objectID)
* @property Message[] $objects
*/
class MessageList extends DatabaseObjectList
{
class MessageList extends \wcf\data\DatabaseObjectList {
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,23 +14,18 @@
namespace chat\data\message;
use chat\data\room\Room;
use chat\page\LogPage;
use wcf\data\DatabaseObjectDecorator;
use wcf\system\request\LinkHandler;
use wcf\system\WCF;
use \wcf\system\request\LinkHandler;
use \wcf\system\WCF;
/**
* Represents a chat message.
*/
class ViewableMessage extends DatabaseObjectDecorator implements \JsonSerializable
{
class ViewableMessage extends \wcf\data\DatabaseObjectDecorator implements \JsonSerializable {
protected static $baseClass = Message::class;
protected $room;
protected $room = null;
public function __construct(Message $message, Room $room)
{
public function __construct(Message $message, \chat\data\room\Room $room) {
parent::__construct($message);
$this->room = $room;
@ -40,34 +34,30 @@ public function __construct(Message $message, Room $room)
/**
* @inheritDoc
*/
public function jsonSerialize(): array
{
$link = LinkHandler::getInstance()->getControllerLink(
LogPage::class,
[
'messageid' => $this->messageID,
'object' => $this->room,
]
);
public function jsonSerialize() {
$link = LinkHandler::getInstance()->getLink('Log', [ 'application' => 'chat'
, 'messageid' => $this->messageID
, 'object' => $this->room
]);
if ($this->isDeleted) {
$payload = false;
$objectType = 'be.bastelstu.chat.messageType.tombstone';
} else {
}
else {
$payload = $this->getMessageType()->getProcessor()->getPayload($this->getDecoratedObject());
$objectType = $this->getMessageType()->objectType;
}
return [
'messageID' => $this->messageID,
'userID' => $this->userID,
'username' => $this->username,
'time' => $this->time,
'payload' => $payload,
'objectType' => $objectType,
'link' => $link,
'isIgnored' => WCF::getUserProfileHandler()->isIgnoredUser($this->userID),
'isDeleted' => (bool)$this->isDeleted,
return [ 'messageID' => $this->messageID
, 'userID' => $this->userID
, 'username' => $this->username
, 'time' => $this->time
, 'payload' => $payload
, 'objectType' => $objectType
, 'link' => $link
, 'isIgnored' => WCF::getUserProfileHandler()->isIgnoredUser($this->userID)
, 'isDeleted' => (bool) $this->isDeleted
];
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,18 +14,12 @@
namespace chat\data\room;
use chat\page\RoomPage;
use chat\system\cache\runtime\UserRuntimeCache as ChatUserRuntimeCache;
use chat\system\permission\PermissionHandler;
use wcf\data\DatabaseObject;
use wcf\data\ITitledLinkObject;
use wcf\data\user\UserProfile;
use wcf\system\event\EventHandler;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\request\IRouteController;
use wcf\system\request\LinkHandler;
use wcf\system\WCF;
use wcf\util\StringUtil;
use \chat\system\cache\runtime\UserRuntimeCache;
use \chat\system\permission\PermissionHandler;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\request\LinkHandler;
use \wcf\system\WCF;
use \wcf\util\StringUtil;
/**
* Represents a chat room.
@ -40,21 +33,18 @@
* @property-read integer $ownerID
* @property-read integer $topicUseHtml
*/
final class Room extends DatabaseObject implements
IRouteController,
ITitledLinkObject,
\JsonSerializable
{
final class Room extends \wcf\data\DatabaseObject implements \wcf\system\request\IRouteController
, \wcf\data\ITitledLinkObject
, \JsonSerializable {
/**
* @var ?(integer[])
*/
private static $userToRoom;
private static $userToRoom = null;
/**
* @see Room::getTitle()
*/
public function __toString(): string
{
public function __toString() {
return $this->getTitle();
}
@ -63,13 +53,10 @@ public function __toString(): string
* one chat room. If no user is given the current user
* should be assumed
*/
public static function canSeeAny(?UserProfile $user = null): bool
{
public static function canSeeAny(\wcf\data\user\UserProfile $user = null): bool {
$rooms = RoomCache::getInstance()->getRooms();
foreach ($rooms as $room) {
if ($room->canSee($user)) {
return true;
}
if ($room->canSee($user)) return true;
}
return false;
@ -79,23 +66,17 @@ public static function canSeeAny(?UserProfile $user = null): bool
* Returns whether the given user can see this room.
* If no user is given the current user should be assumed.
*/
public function canSee(?UserProfile $user = null, ?\Exception &$reason = null): bool
{
public function canSee(\wcf\data\user\UserProfile $user = null, \Exception &$reason = null): bool {
static $cache = [ ];
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
if ($user === null) $user = new \wcf\data\user\UserProfile(WCF::getUser());
if (!isset($cache[$this->roomID])) {
$cache[$this->roomID] = [];
}
if (\array_key_exists($user->userID, $cache[$this->roomID])) {
if (!isset($cache[$this->roomID])) $cache[$this->roomID] = [];
if (array_key_exists($user->userID, $cache[$this->roomID])) {
return ($reason = $cache[$this->roomID][$user->userID]) === null;
}
if (!$user->userID) {
$reason = new PermissionDeniedException();
return ($cache[$this->roomID][$user->userID] = $reason) === null;
}
@ -104,14 +85,13 @@ public function canSee(?UserProfile $user = null, ?\Exception &$reason = null):
$result = new PermissionDeniedException();
}
$parameters = [
'user' => $user,
'result' => $result,
$parameters = [ 'user' => $user
, 'result' => $result
];
EventHandler::getInstance()->fireAction($this, 'canSee', $parameters);
\wcf\system\event\EventHandler::getInstance()->fireAction($this, 'canSee', $parameters);
$reason = $parameters['result'];
if (!($reason === null || $reason instanceof \Throwable)) {
if (!($reason === null || $reason instanceof \Exception || $reason instanceof \Throwable)) {
throw new \DomainException('Result of canSee must be a \Throwable or null.');
}
@ -122,17 +102,12 @@ public function canSee(?UserProfile $user = null, ?\Exception &$reason = null):
* Returns whether the given user can see the log of this room.
* If no user is given the current user should be assumed.
*/
public function canSeeLog(?UserProfile $user = null, ?\Exception &$reason = null): bool
{
public function canSeeLog(\wcf\data\user\UserProfile $user = null, \Exception &$reason = null): bool {
static $cache = [ ];
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
if ($user === null) $user = new \wcf\data\user\UserProfile(WCF::getUser());
if (!isset($cache[$this->roomID])) {
$cache[$this->roomID] = [];
}
if (\array_key_exists($user->userID, $cache[$this->roomID])) {
if (!isset($cache[$this->roomID])) $cache[$this->roomID] = [];
if (array_key_exists($user->userID, $cache[$this->roomID])) {
return ($reason = $cache[$this->roomID][$user->userID]) === null;
}
@ -141,14 +116,13 @@ public function canSeeLog(?UserProfile $user = null, ?\Exception &$reason = null
$result = new PermissionDeniedException();
}
$parameters = [
'user' => $user,
'result' => $result,
$parameters = [ 'user' => $user
, 'result' => $result
];
EventHandler::getInstance()->fireAction($this, 'canSeeLog', $parameters);
\wcf\system\event\EventHandler::getInstance()->fireAction($this, 'canSeeLog', $parameters);
$reason = $parameters['result'];
if (!($reason === null || $reason instanceof \Throwable)) {
if (!($reason === null || $reason instanceof \Exception || $reason instanceof \Throwable)) {
throw new \DomainException('Result of canSeeLog must be a \Throwable or null.');
}
@ -159,28 +133,22 @@ public function canSeeLog(?UserProfile $user = null, ?\Exception &$reason = null
* Returns whether the given user can join this room.
* If no user is given the current user should be assumed.
*/
public function canJoin(?UserProfile $user = null, ?\Exception &$reason = null): bool
{
public function canJoin(\wcf\data\user\UserProfile $user = null, \Exception &$reason = null): bool {
static $cache = [ ];
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
if ($user === null) $user = new \wcf\data\user\UserProfile(WCF::getUser());
if (!isset($cache[$this->roomID])) {
$cache[$this->roomID] = [];
}
if (\array_key_exists($user->userID, $cache[$this->roomID])) {
if (!isset($cache[$this->roomID])) $cache[$this->roomID] = [];
if (array_key_exists($user->userID, $cache[$this->roomID])) {
return ($reason = $cache[$this->roomID][$user->userID]) === null;
}
$parameters = [
'user' => $user,
'result' => null,
$parameters = [ 'user' => $user
, 'result' => null
];
EventHandler::getInstance()->fireAction($this, 'canJoin', $parameters);
\wcf\system\event\EventHandler::getInstance()->fireAction($this, 'canJoin', $parameters);
$reason = $parameters['result'];
if (!($reason === null || $reason instanceof \Throwable)) {
if (!($reason === null || $reason instanceof \Exception || $reason instanceof \Throwable)) {
throw new \DomainException('Result of canJoin must be a \Throwable or null.');
}
@ -191,17 +159,12 @@ public function canJoin(?UserProfile $user = null, ?\Exception &$reason = null):
* Returns whether the given user can write public messages in this room.
* If no user is given the current user should be assumed.
*/
public function canWritePublicly(?UserProfile $user = null, ?\Exception &$reason = null): bool
{
public function canWritePublicly(\wcf\data\user\UserProfile $user = null, \Exception &$reason = null): bool {
static $cache = [ ];
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
if ($user === null) $user = new \wcf\data\user\UserProfile(WCF::getUser());
if (!isset($cache[$this->roomID])) {
$cache[$this->roomID] = [];
}
if (\array_key_exists($user->userID, $cache[$this->roomID])) {
if (!isset($cache[$this->roomID])) $cache[$this->roomID] = [];
if (array_key_exists($user->userID, $cache[$this->roomID])) {
return ($reason = $cache[$this->roomID][$user->userID]) === null;
}
@ -210,14 +173,13 @@ public function canWritePublicly(?UserProfile $user = null, ?\Exception &$reason
$result = new PermissionDeniedException();
}
$parameters = [
'user' => $user,
'result' => $result,
$parameters = [ 'user' => $user
, 'result' => $result
];
EventHandler::getInstance()->fireAction($this, 'canWritePublicly', $parameters);
\wcf\system\event\EventHandler::getInstance()->fireAction($this, 'canWritePublicly', $parameters);
$reason = $parameters['result'];
if (!($reason === null || $reason instanceof \Throwable)) {
if (!($reason === null || $reason instanceof \Exception || $reason instanceof \Throwable)) {
throw new \DomainException('Result of canWritePublicly must be a \Throwable or null.');
}
@ -227,16 +189,14 @@ public function canWritePublicly(?UserProfile $user = null, ?\Exception &$reason
/**
* @inheritDoc
*/
public function getTitle(): string
{
public function getTitle() {
return WCF::getLanguage()->get($this->title);
}
/**
* @inheritDoc
*/
public function getTopic(): string
{
public function getTopic() {
$topic = StringUtil::trim(WCF::getLanguage()->get($this->topic));
if (!$this->topicUseHtml) {
@ -248,45 +208,36 @@ public function getTopic(): string
/**
* Returns an array of users in this room.
*
* @return \chat\data\user\User[]
*/
public function getUsers()
{
public function getUsers() {
if (self::$userToRoom === null) {
$sql = "SELECT r2u.userID,
r2u.roomID
FROM chat1_room_to_user r2u
INNER JOIN wcf1_user u
$sql = "SELECT r2u.userID, r2u.roomID
FROM chat".WCF_N."_room_to_user r2u
INNER JOIN wcf".WCF_N."_user u
ON r2u.userID = u.userID
WHERE r2u.active = ?
ORDER BY u.username ASC";
$statement = WCF::getDB()->prepare($sql);
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute([ 1 ]);
self::$userToRoom = $statement->fetchMap('roomID', 'userID', false);
if (!empty(self::$userToRoom)) {
ChatUserRuntimeCache::getInstance()->cacheObjectIDs(\array_merge(...self::$userToRoom));
UserRuntimeCache::getInstance()->cacheObjectIDs(array_merge(...self::$userToRoom));
}
}
if (!isset(self::$userToRoom[$this->roomID])) {
return [ ];
}
if (!isset(self::$userToRoom[$this->roomID])) return [ ];
return ChatUserRuntimeCache::getInstance()->getObjects(self::$userToRoom[$this->roomID]);
return UserRuntimeCache::getInstance()->getObjects(self::$userToRoom[$this->roomID]);
}
/**
* @inheritDoc
*/
public function getLink(): string
{
return LinkHandler::getInstance()->getControllerLink(
RoomPage::class,
[
'object' => $this,
'forceFrontend' => true,
public function getLink() {
return LinkHandler::getInstance()->getLink('Room', [ 'application' => 'chat'
, 'object' => $this
, 'forceFrontend' => true
]
);
}
@ -294,12 +245,10 @@ public function getLink(): string
/**
* @inheritDoc
*/
public function jsonSerialize(): array
{
return [
'title' => $this->getTitle(),
'topic' => $this->getTopic(),
'link' => $this->getLink(),
public function jsonSerialize() {
return [ 'title' => $this->getTitle()
, 'topic' => $this->getTopic()
, 'link' => $this->getLink()
];
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,137 +14,89 @@
namespace chat\data\room;
use chat\data\command\CommandCache;
use chat\data\message\MessageAction;
use chat\data\user\User as ChatUser;
use chat\data\user\UserAction as ChatUserAction;
use chat\system\box\RoomListBoxController;
use wcf\data\AbstractDatabaseObjectAction;
use wcf\data\box\Box;
use wcf\data\ISortableAction;
use wcf\data\object\type\ObjectTypeCache;
use wcf\data\package\PackageCache;
use wcf\data\user\UserProfile;
use wcf\system\cache\runtime\UserProfileRuntimeCache;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\event\EventHandler;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\exception\UserInputException;
use wcf\system\push\PushHandler;
use wcf\system\user\activity\point\UserActivityPointHandler;
use wcf\system\WCF;
use \chat\data\user\User as ChatUser;
use \chat\data\message\MessageAction;
use \wcf\data\object\type\ObjectTypeCache;
use \wcf\system\cache\runtime\UserProfileRuntimeCache;
use \wcf\system\database\util\PreparedStatementConditionBuilder;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\exception\UserInputException;
use \wcf\system\user\activity\point\UserActivityPointHandler;
use \wcf\system\WCF;
/**
* Executes chat room-related actions.
*/
class RoomAction extends AbstractDatabaseObjectAction implements ISortableAction
{
class RoomAction extends \wcf\data\AbstractDatabaseObjectAction implements \wcf\data\ISortableAction {
/**
* @inheritDoc
*/
protected $permissionsDelete = [
'admin.chat.canManageRoom',
];
protected $permissionsDelete = [ 'admin.chat.canManageRoom' ];
/**
* @inheritDoc
*/
protected $permissionsUpdate = [
'admin.chat.canManageRoom',
];
protected $permissionsUpdate = [ 'admin.chat.canManageRoom' ];
/**
* Validates parameters and permissions.
*/
public function validateJoin()
{
public function validateJoin() {
unset($this->parameters['user']);
$this->readString('sessionID');
$this->parameters['sessionID'] = \pack(
'H*',
\str_replace('-', '', $this->parameters['sessionID'])
);
$this->parameters['sessionID'] = pack('H*', str_replace('-', '', $this->parameters['sessionID']));
$this->readInteger('roomID');
$room = RoomCache::getInstance()->getRoom($this->parameters['roomID']);
if ($room === null) {
throw new UserInputException('roomID');
}
if (!$room->canSee($user = null, $reason)) {
throw $reason;
}
if (!$room->canJoin($user = null, $reason)) {
throw $reason;
}
if ($room === null) throw new UserInputException('roomID');
if (!$room->canSee($user = null, $reason)) throw $reason;
if (!$room->canJoin($user = null, $reason)) throw $reason;
}
/**
* Makes the given user join the current chat room.
*/
public function join()
{
$objectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName(
'be.bastelstu.chat.messageType',
'be.bastelstu.chat.messageType.join'
);
if (!$objectTypeID) {
throw new \LogicException('Missing object type');
}
public function join() {
$objectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName('be.bastelstu.chat.messageType', 'be.bastelstu.chat.messageType.join');
if (!$objectTypeID) throw new \LogicException('Missing object type');
// User cannot be set during an AJAX request, but may be set by Tims Chat itself.
if (!isset($this->parameters['user'])) {
$this->parameters['user'] = WCF::getUser();
}
if (!isset($this->parameters['user'])) $this->parameters['user'] = WCF::getUser();
$user = new ChatUser($this->parameters['user']);
// Check parameters
$room = RoomCache::getInstance()->getRoom($this->parameters['roomID']);
if ($room === null) {
throw new UserInputException('roomID');
}
if ($room === null) throw new UserInputException('roomID');
$sessionID = $this->parameters['sessionID'];
if (\strlen($sessionID) !== 16) {
throw new UserInputException('sessionID');
}
if (strlen($sessionID) !== 16) throw new UserInputException('sessionID');
try {
// Create room_to_user mapping.
$sql = "INSERT INTO chat1_room_to_user
(active, roomID, userID)
VALUES (?, ?, ?)";
$statement = WCF::getDB()->prepare($sql);
$sql = "INSERT INTO chat".WCF_N."_room_to_user (active, roomID, userID) VALUES (?, ?, ?)";
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute([ 0, $room->roomID, $user->userID ]);
} catch (\wcf\system\database\exception\DatabaseException $e) {
// Ignore if there already is a mapping.
if ((string)$e->getCode() !== '23000') {
throw $e;
}
catch (\wcf\system\database\exception\DatabaseException $e) {
// Ignore if there already is a mapping.
if ((string) $e->getCode() !== '23000') throw $e;
}
try {
$sql = "INSERT INTO chat1_session
(roomID, userID, sessionID, lastRequest)
VALUES (?, ?, ?, ?)";
$statement = WCF::getDB()->prepare($sql);
$statement->execute([
$room->roomID,
$user->userID,
$sessionID,
TIME_NOW,
]);
} catch (\wcf\system\database\exception\DatabaseException $e) {
if ((string)$e->getCode() !== '23000') {
throw $e;
$sql = "INSERT INTO chat".WCF_N."_session (roomID, userID, sessionID, lastRequest) VALUES (?, ?, ?, ?)";
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute([ $room->roomID, $user->userID, $sessionID, TIME_NOW ]);
}
catch (\wcf\system\database\exception\DatabaseException $e) {
if ((string) $e->getCode() !== '23000') throw $e;
throw new UserInputException('sessionID');
}
$markAsBack = static function () use ($user, $room) {
$userProfile = new UserProfile($user->getDecoratedObject());
$package = PackageCache::getInstance()->getPackageByIdentifier('be.bastelstu.chat');
$command = CommandCache::getInstance()->getCommandByPackageAndIdentifier($package, 'back');
$markAsBack = function () use ($user, $room) {
$userProfile = new \wcf\data\user\UserProfile($user->getDecoratedObject());
$package = \wcf\data\package\PackageCache::getInstance()->getPackageByIdentifier('be.bastelstu.chat');
$command = \chat\data\command\CommandCache::getInstance()->getCommandByPackageAndIdentifier($package, 'back');
$processor = $command->getProcessor();
$processor->execute([ ], $room, $userProfile);
};
@ -155,11 +106,8 @@ public function join()
}
// Attempt to mark the user as active in the room.
$sql = "UPDATE chat1_room_to_user
SET active = ?
WHERE roomID = ?
AND userID = ?";
$statement = WCF::getDB()->prepare($sql);
$sql = "UPDATE chat".WCF_N."_room_to_user SET active = ? WHERE roomID = ? AND userID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute([ 1, $room->roomID, $user->userID ]);
if ($statement->getAffectedRows() === 0) {
// The User already is inside the room: Nothing to do here.
@ -167,58 +115,40 @@ public function join()
}
// Update lastPull. This must not be merged into the above query, because of the 'getAffectedRows' check.
$sql = "UPDATE chat1_room_to_user
SET lastPull = ?
WHERE roomID = ?
AND userID = ?";
$statement = WCF::getDB()->prepare($sql);
$sql = "UPDATE chat".WCF_N."_room_to_user SET lastPull = ? WHERE roomID = ? AND userID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute([ TIME_NOW, $room->roomID, $user->userID ]);
(new MessageAction(
[ ],
'create',
[
'data' => [
'roomID' => $room->roomID,
'userID' => $user->userID,
'username' => $user->username,
'time' => TIME_NOW,
'objectTypeID' => $objectTypeID,
'payload' => \serialize([ ]),
],
(new MessageAction([ ], 'create', [ 'data' => [ 'roomID' => $room->roomID
, 'userID' => $user->userID
, 'username' => $user->username
, 'time' => TIME_NOW
, 'objectTypeID' => $objectTypeID
, 'payload' => serialize([ ])
]
))->executeAction();
]
)
)->executeAction();
UserActivityPointHandler::getInstance()->fireEvent(
'be.bastelstu.chat.activityPointEvent.join',
0,
$user->userID
);
$pushHandler = PushHandler::getInstance();
$pushHandler->sendMessage([
'message' => 'be.bastelstu.chat.join',
'target' => 'registered',
UserActivityPointHandler::getInstance()->fireEvent('be.bastelstu.chat.activityPointEvent.join', 0, $user->userID);
$pushHandler = \wcf\system\push\PushHandler::getInstance();
$pushHandler->sendMessage([ 'message' => 'be.bastelstu.chat.join'
, 'target' => 'registered'
]);
}
/**
* Validates parameters and permissions.
*/
public function validateLeave()
{
public function validateLeave() {
unset($this->parameters['user']);
$this->readString('sessionID');
$this->parameters['sessionID'] = \pack(
'H*',
\str_replace('-', '', $this->parameters['sessionID'])
);
$this->parameters['sessionID'] = pack('H*', str_replace('-', '', $this->parameters['sessionID']));
$this->readInteger('roomID');
$room = RoomCache::getInstance()->getRoom($this->parameters['roomID']);
if ($room === null) {
throw new UserInputException('roomID');
}
if ($room === null) throw new UserInputException('roomID');
// Do not check permissions: If the user is not inside the room nothing happens, if he is it
// may lead to a faster eviction of the user.
}
@ -226,42 +156,32 @@ public function validateLeave()
/**
* Makes the given user leave the current chat room.
*/
public function leave()
{
$objectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName(
'be.bastelstu.chat.messageType',
'be.bastelstu.chat.messageType.leave'
);
public function leave() {
$objectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName('be.bastelstu.chat.messageType', 'be.bastelstu.chat.messageType.leave');
if ($objectTypeID) {
// User cannot be set during an AJAX request, but may be set by Tims Chat itself.
if (!isset($this->parameters['user'])) {
$this->parameters['user'] = WCF::getUser();
}
if (!isset($this->parameters['user'])) $this->parameters['user'] = WCF::getUser();
$user = new ChatUser($this->parameters['user']);
$room = RoomCache::getInstance()->getRoom($this->parameters['roomID']);
if ($room === null) {
throw new UserInputException('roomID');
}
if ($room === null) throw new UserInputException('roomID');
$sessionID = null;
if (isset($this->parameters['sessionID'])) {
$sessionID = $this->parameters['sessionID'];
if (\strlen($sessionID) !== 16) {
throw new UserInputException('sessionID');
}
if (strlen($sessionID) !== 16) throw new UserInputException('sessionID');
}
// Delete session.
$condition = new PreparedStatementConditionBuilder();
$condition = new \wcf\system\database\util\PreparedStatementConditionBuilder();
$condition->add('roomID = ?', [ $room->roomID ]);
$condition->add('userID = ?', [ $user->userID ]);
if ($sessionID !== null) {
$condition->add('sessionID = ?', [ $sessionID ]);
}
$sql = "DELETE FROM chat1_session
{$condition}";
$statement = WCF::getDB()->prepare($sql);
$sql = "DELETE FROM chat".WCF_N."_session
".$condition;
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute($condition->getParameters());
if ($statement->getAffectedRows() === 0) {
throw new UserInputException('sessionID');
@ -273,55 +193,45 @@ public function leave()
// Check whether we deleted the last session.
$sql = "SELECT COUNT(*)
FROM chat1_session
FROM chat".WCF_N."_session
WHERE roomID = ?
AND userID = ?";
$statement = WCF::getDB()->prepare($sql);
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute([ $room->roomID, $user->userID ]);
// We did not: Nothing to do here.
if ($statement->fetchColumn()) {
return;
}
if ($statement->fetchColumn()) return;
// Mark the user as inactive.
$sql = "UPDATE chat1_room_to_user
SET active = ?
WHERE roomID = ?
AND userID = ?";
$statement = WCF::getDB()->prepare($sql);
$sql = "UPDATE chat".WCF_N."_room_to_user SET active = ? WHERE roomID = ? AND userID = ?";
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute([ 0, $room->roomID, $user->userID ]);
\assert($statement->getAffectedRows() > 0);
if ($statement->getAffectedRows() === 0) throw new \LogicException('Unreachable');
WCF::getDB()->commitTransaction();
$commited = true;
} finally {
if (!$commited) {
WCF::getDB()->rollBackTransaction();
}
finally {
if (!$commited) WCF::getDB()->rollBackTransaction();
}
(new MessageAction(
[ ],
'create',
[
'data' => [
'roomID' => $room->roomID,
'userID' => $user->userID,
'username' => $user->username,
'time' => TIME_NOW,
'objectTypeID' => $objectTypeID,
'payload' => \serialize([ ]),
],
(new MessageAction([ ], 'create', [ 'data' => [ 'roomID' => $room->roomID
, 'userID' => $user->userID
, 'username' => $user->username
, 'time' => TIME_NOW
, 'objectTypeID' => $objectTypeID
, 'payload' => serialize([ ])
]
))->executeAction();
]
)
)->executeAction();
$pushHandler = PushHandler::getInstance();
$pushHandler->sendMessage([
'message' => 'be.bastelstu.chat.leave',
'target' => 'registered',
$pushHandler = \wcf\system\push\PushHandler::getInstance();
$pushHandler->sendMessage([ 'message' => 'be.bastelstu.chat.leave'
, 'target' => 'registered'
]);
} else {
}
else {
throw new \LogicException('Missing object type');
}
}
@ -329,56 +239,46 @@ public function leave()
/**
* Validates parameters and permissions.
*/
public function validateGetUsers()
{
public function validateGetUsers() {
if (empty($this->getObjects())) {
$this->readObjects();
}
if (\count($this->getObjects()) !== 1) {
if (count($this->getObjects()) !== 1) {
throw new UserInputException('objectIDs');
}
$room = $this->getObjects()[0];
$user = new ChatUser(WCF::getUser());
if (!$user->isInRoom($room->getDecoratedObject())) {
throw new PermissionDeniedException();
}
if (!$user->isInRoom($room->getDecoratedObject())) throw new PermissionDeniedException();
}
/**
* Returns the userIDs of the users in this room.
*/
public function getUsers()
{
public function getUsers() {
if (empty($this->getObjects())) {
$this->readObjects();
}
if (\count($this->getObjects()) !== 1) {
if (count($this->getObjects()) !== 1) {
throw new UserInputException('objectIDs');
}
$room = $this->getObjects()[0];
$users = (new ChatUserAction(
[ ],
'getUsersByID',
[
'userIDs' => \array_keys($room->getUsers()),
]
))->executeAction()['returnValues'];
$users = (new \chat\data\user\UserAction([ ], 'getUsersByID', [
'userIDs' => array_keys($room->getUsers())
]))->executeAction()['returnValues'];
$users = \array_map(static function (array $user) use ($room) {
$users = array_map(function (array $user) use ($room) {
$userProfile = UserProfileRuntimeCache::getInstance()->getObject($user['userID']);
if (!isset($user['permissions'])) {
$user['permissions'] = [];
}
if (!isset($user['permissions'])) $user['permissions'] = [];
$user['permissions']['canWritePublicly'] = $room->canWritePublicly($userProfile);
return $user;
}, $users);
EventHandler::getInstance()->fireAction($this, 'getUsers', $users);
\wcf\system\event\EventHandler::getInstance()->fireAction($this, 'getUsers', $users);
return $users;
}
@ -386,12 +286,12 @@ public function getUsers()
/**
* @inheritDoc
*/
public function validateUpdatePosition()
{
public function validateUpdatePosition() {
// validate permissions
if (\is_array($this->permissionsUpdate) && !empty($this->permissionsUpdate)) {
if (is_array($this->permissionsUpdate) && !empty($this->permissionsUpdate)) {
WCF::getSession()->checkPermissions($this->permissionsUpdate);
} else {
}
else {
throw new PermissionDeniedException();
}
@ -402,17 +302,14 @@ public function validateUpdatePosition()
foreach ($this->parameters['data']['structure'][0] as $roomID) {
$room = $roomList->search($roomID);
if ($room === null) {
throw new UserInputException('structure');
}
if ($room === null) throw new UserInputException('structure');
}
}
/**
* @inheritDoc
*/
public function updatePosition()
{
public function updatePosition() {
$roomList = new RoomList();
$roomList->readObjects();
@ -420,14 +317,10 @@ public function updatePosition()
WCF::getDB()->beginTransaction();
foreach ($this->parameters['data']['structure'][0] as $roomID) {
$room = $roomList->search($roomID);
if ($room === null) {
continue;
}
if ($room === null) continue;
$editor = new RoomEditor($room);
$editor->update([
'position' => $i++,
]);
$editor->update([ 'position' => $i++ ]);
}
WCF::getDB()->commitTransaction();
}
@ -435,11 +328,8 @@ public function updatePosition()
/**
* Validates permissions.
*/
public function validateGetBoxRoomList()
{
if (!Room::canSeeAny()) {
throw new PermissionDeniedException();
}
public function validateGetBoxRoomList() {
if (!\chat\data\room\Room::canSeeAny()) throw new \wcf\system\exception\PermissionDeniedException();
$this->readBoolean('isSidebar', true);
$this->readBoolean('skipEmptyRooms', true);
@ -448,10 +338,10 @@ public function validateGetBoxRoomList()
unset($this->parameters['boxController']);
$this->readInteger('boxID', true);
if ($this->parameters['boxID']) {
$box = new Box($this->parameters['boxID']);
$box = new \wcf\data\box\Box($this->parameters['boxID']);
if ($box->boxID) {
$this->parameters['boxController'] = $box->getController();
if ($this->parameters['boxController'] instanceof RoomListBoxController) {
if ($this->parameters['boxController'] instanceof \chat\system\box\RoomListBoxController) {
// all checks passed, end validation; otherwise throw the exception below
return;
}
@ -464,14 +354,11 @@ public function validateGetBoxRoomList()
/**
* Returns dashboard roomlist.
*/
public function getBoxRoomList()
{
public function getBoxRoomList() {
if (isset($this->parameters['boxController'])) {
$this->parameters['boxController']->setActiveRoomID($this->parameters['activeRoomID']);
return [
'template' => $this->parameters['boxController']->getContent(),
];
return [ 'template' => $this->parameters['boxController']->getContent() ];
}
// Fetch all rooms, the templates have filtering in place
@ -479,14 +366,11 @@ public function getBoxRoomList()
$template = 'boxRoomList'.($this->parameters['isSidebar'] ? 'Sidebar' : '');
WCF::getTPL()->assign([
'boxRoomList' => $rooms,
'skipEmptyRooms' => $this->parameters['skipEmptyRooms'],
'activeRoomID' => $this->parameters['activeRoomID'],
\wcf\system\WCF::getTPL()->assign([ 'boxRoomList' => $rooms
, 'skipEmptyRooms' => $this->parameters['skipEmptyRooms']
, 'activeRoomID' => $this->parameters['activeRoomID']
]);
return [
'template' => WCF::getTPL()->fetch($template, 'chat'),
];
return [ 'template' => \wcf\system\WCF::getTPL()->fetch($template, 'chat') ];
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,14 +14,12 @@
namespace chat\data\room;
use chat\system\cache\builder\RoomCacheBuilder;
use wcf\system\SingletonFactory;
use \wcf\system\WCF;
/**
* Manages the room cache.
*/
final class RoomCache extends SingletonFactory
{
class RoomCache extends \wcf\system\SingletonFactory {
/**
* List of cached rooms.
*
@ -40,16 +37,17 @@ final class RoomCache extends SingletonFactory
/**
* @inheritDoc
*/
protected function init()
{
$this->rooms = RoomCacheBuilder::getInstance()->getData();
protected function init() {
$this->rooms = \chat\system\cache\builder\RoomCacheBuilder::getInstance()->getData();
}
/**
* Returns a specific room.
*
* @param integer $roomID
* @return Room
*/
public function getRoom(int $roomID): ?Room
{
public function getRoom($roomID) {
if (isset($this->rooms[$roomID])) {
return $this->rooms[$roomID];
}
@ -62,8 +60,7 @@ public function getRoom(int $roomID): ?Room
*
* @return Room[]
*/
public function getRooms()
{
public function getRooms() {
return $this->rooms;
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,16 +14,10 @@
namespace chat\data\room;
use chat\system\cache\builder\RoomCacheBuilder;
use chat\system\permission\PermissionHandler;
use wcf\data\DatabaseObjectEditor;
use wcf\data\IEditableCachedObject;
/**
* Represents a chat room editor.
*/
class RoomEditor extends DatabaseObjectEditor implements IEditableCachedObject
{
class RoomEditor extends \wcf\data\DatabaseObjectEditor implements \wcf\data\IEditableCachedObject {
/**
* @inheritDoc
*/
@ -33,9 +26,8 @@ class RoomEditor extends DatabaseObjectEditor implements IEditableCachedObject
/**
* @inheritDoc
*/
public static function resetCache()
{
RoomCacheBuilder::getInstance()->reset();
PermissionHandler::resetCache();
public static function resetCache() {
\chat\system\cache\builder\RoomCacheBuilder::getInstance()->reset();
\chat\system\permission\PermissionHandler::resetCache();
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,19 +14,10 @@
namespace chat\data\room;
use wcf\data\DatabaseObjectList;
/**
* Represents a list of chat rooms.
*
* @method Room current()
* @method Room[] getObjects()
* @method Room|null getSingleObject()
* @method Room|null search($objectID)
* @property Room[] $objects
*/
class RoomList extends DatabaseObjectList
{
class RoomList extends \wcf\data\DatabaseObjectList {
/**
* @inheritDoc
*/

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 3
@ -15,27 +14,24 @@
namespace chat\data\suspension;
use chat\data\room\Room;
use chat\data\room\RoomCache;
use wcf\data\DatabaseObject;
use wcf\data\object\type\ObjectType;
use wcf\data\object\type\ObjectTypeCache;
use wcf\data\user\User;
use wcf\system\cache\runtime\UserRuntimeCache;
use \chat\data\room\Room;
use \wcf\data\user\User;
use \wcf\system\WCF;
/**
* Represents a chat suspension.
*/
class Suspension extends DatabaseObject implements \JsonSerializable
{
class Suspension extends \wcf\data\DatabaseObject implements \JsonSerializable {
/**
* Returns the active suspensions for the given (objectTypeID, Room, User)
* triple.
*
* @param int $objectTypeID
* @param \wcf\data\user\User $user
* @param \chat\data\room\Room $room
* @return \chat\data\suspension\Suspension[]
*/
public static function getActiveSuspensionsByTriple(int $objectTypeID, User $user, Room $room)
{
public static function getActiveSuspensionsByTriple($objectTypeID, User $user, Room $room) {
$suspensionList = new SuspensionList();
$suspensionList->getConditionBuilder()->add('(expires IS NULL OR expires > ?)', [ TIME_NOW ]);
@ -46,34 +42,30 @@ public static function getActiveSuspensionsByTriple(int $objectTypeID, User $use
$suspensionList->readObjects();
return \array_filter($suspensionList->getObjects(), static function (self $suspension) {
return array_filter($suspensionList->getObjects(), function (Suspension $suspension) {
return $suspension->isActive();
});
}
/**
* Returns the suspension object type of this message.
*
* @return \wcf\data\object\type\ObjectType
*/
public function getSuspensionType(): ObjectType
{
return ObjectTypeCache::getInstance()->getObjectType($this->objectTypeID);
public function getSuspensionType() {
return \wcf\data\object\type\ObjectTypeCache::getInstance()->getObjectType($this->objectTypeID);
}
/**
* Returns whether this suspension still is in effect.
*
* @return boolean
*/
public function isActive(): bool
{
if ($this->revoked !== null) {
return false;
}
if (!$this->getSuspensionType()->getProcessor()->hasEffect($this)) {
return false;
}
public function isActive() {
if ($this->revoked !== null) return false;
if (!$this->getSuspensionType()->getProcessor()->hasEffect($this)) return false;
if ($this->expires === null) {
return true;
}
if ($this->expires === null) return true;
return $this->expires > TIME_NOW;
}
@ -81,39 +73,39 @@ public function isActive(): bool
/**
* Returns the chat room this suspension is in effect.
* Returns null if this is a global suspension.
*
* @return \chat\data\room\Room
*/
public function getRoom(): ?Room
{
public function getRoom() {
if ($this->roomID === null) {
return null;
}
return RoomCache::getInstance()->getRoom($this->roomID);
return \chat\data\room\RoomCache::getInstance()->getRoom($this->roomID);
}
/**
* Returns the user that is affected by this suspension.
*
* @return \wcf\data\user\User
*/
public function getUser(): User
{
return UserRuntimeCache::getInstance()->getObject($this->userID);
public function getUser() {
return \wcf\system\cache\runtime\UserRuntimeCache::getInstance()->getObject($this->userID);
}
/**
* @inheritDoc
*/
public function jsonSerialize(): array
{
return [
'userID' => $this->userID,
'username' => $this->getUser()->username,
'roomID' => $this->roomID,
'time' => $this->time,
'expires' => $this->expires,
'reason' => $this->reason,
'objectType' => $this->getSuspensionType()->objectType,
'judgeID' => $this->judgeID,
'judge' => $this->judge,
public function jsonSerialize() {
return [ 'userID' => $this->userID
, 'username' => $this->getUser()->username
, 'roomID' => $this->roomID
, 'time' => $this->time
, 'expires' => $this->expires
, 'reason' => $this->reason
, 'objectType' => $this->getSuspensionType()->objectType
, 'judgeID' => $this->judgeID
, 'judge' => $this->judge
];
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 3
@ -15,27 +14,21 @@
namespace chat\data\suspension;
use wcf\data\AbstractDatabaseObjectAction;
use wcf\system\exception\UserInputException;
use wcf\system\WCF;
use \wcf\system\WCF;
/**
* Executes suspension-related actions.
*/
class SuspensionAction extends AbstractDatabaseObjectAction
{
class SuspensionAction extends \wcf\data\AbstractDatabaseObjectAction {
/**
* @inheritDoc
*/
protected $requireACP = [
'revoke',
];
protected $requireACP = [ 'revoke' ];
/**
* Validates parameters and permissions.
*/
public function validateRevoke()
{
public function validateRevoke() {
if (empty($this->objects)) {
$this->readObjects();
@ -46,44 +39,30 @@ public function validateRevoke()
unset($this->parameters['revoker']);
WCF::getSession()->checkPermissions([
'admin.chat.canManageSuspensions',
]);
WCF::getSession()->checkPermissions([ 'admin.chat.canManageSuspensions' ]);
foreach ($this->getObjects() as $object) {
if (!$object->isActive()) {
throw new UserInputException('objectIDs', 'nonActive');
}
if (!$object->isActive()) throw new UserInputException('objectIDs', 'nonActive');
}
}
/**
* Revokes the suspensions
*/
public function revoke()
{
public function revoke() {
if (empty($this->objects)) {
$this->readObjects();
}
// User cannot be set during an AJAX request, but may be set by Tims Chat itself.
if (!isset($this->parameters['revoker'])) {
$this->parameters['revoker'] = WCF::getUser();
}
if (!isset($this->parameters['revoker'])) $this->parameters['revoker'] = WCF::getUser();
$data = [
'revoked' => TIME_NOW,
'revokerID' => $this->parameters['revoker']->userID,
'revoker' => $this->parameters['revoker']->username,
$data = [ 'revoked' => TIME_NOW
, 'revokerID' => $this->parameters['revoker']->userID
, 'revoker' => $this->parameters['revoker']->username
];
$objectAction = new static(
$this->getObjects(),
'update',
[
'data' => $data,
]
);
$objectAction = new static($this->getObjects(), 'update', [ 'data' => $data ]);
$objectAction->executeAction();
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 3
@ -15,13 +14,10 @@
namespace chat\data\suspension;
use wcf\data\DatabaseObjectEditor;
/**
* Represents a chat suspension editor.
*/
class SuspensionEditor extends DatabaseObjectEditor
{
class SuspensionEditor extends \wcf\data\DatabaseObjectEditor {
/**
* @inheritDoc
*/

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 3
@ -15,17 +14,9 @@
namespace chat\data\suspension;
use wcf\data\DatabaseObjectList;
/**
* Represents a list of chat suspensions.
*
* @method Suspension current()
* @method Suspension[] getObjects()
* @method Suspension|null getSingleObject()
* @method Suspension|null search($objectID)
* @property Suspension[] $objects
*/
class SuspensionList extends DatabaseObjectList
{
class SuspensionList extends \wcf\data\DatabaseObjectList {
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,16 +14,12 @@
namespace chat\data\user;
use chat\data\room\Room;
use chat\data\room\RoomCache;
use wcf\data\DatabaseObjectDecorator;
use wcf\system\WCF;
use \wcf\system\WCF;
/**
* Decorates the User object to make it useful in context of Tims Chat.
*/
class User extends DatabaseObjectDecorator implements \JsonSerializable
{
class User extends \wcf\data\DatabaseObjectDecorator implements \JsonSerializable {
/**
* @inheritDoc
*/
@ -35,20 +30,19 @@ class User extends DatabaseObjectDecorator implements \JsonSerializable
*
* @var int[][]
*/
protected $roomToUser;
protected $roomToUser = null;
/**
* Returns an array of the room_to_user arrays for this user.
*
* @return mixed[]
*/
public function getRoomAssociations($skipCache = false)
{
public function getRoomAssociations($skipCache = false) {
if ($this->roomToUser === null || $skipCache) {
$sql = "SELECT *
FROM chat1_room_to_user
FROM chat".WCF_N."_room_to_user
WHERE userID = ?";
$statement = WCF::getDB()->prepare($sql);
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute([ $this->userID ]);
$this->roomToUser = [ ];
while (($row = $statement->fetchArray())) {
@ -64,26 +58,24 @@ public function getRoomAssociations($skipCache = false)
*
* @return \chat\data\room\Room[]
*/
public function getRooms($skipCache = false)
{
return \array_map(static function ($assoc) {
return RoomCache::getInstance()->getRoom($assoc['roomID']);
}, \array_filter($this->getRoomAssociations($skipCache), static function ($assoc) {
public function getRooms($skipCache = false) {
return array_map(function ($assoc) {
return \chat\data\room\RoomCache::getInstance()->getRoom($assoc['roomID']);
}, array_filter($this->getRoomAssociations($skipCache), function ($assoc) {
return $assoc['active'] === 1;
}));
}
/**
* Returns whether the user is in the given room.
*
* @param \chat\data\room\Room $room
* @return boolean
*/
public function isInRoom(Room $room, $skipCache = false): bool
{
public function isInRoom(\chat\data\room\Room $room, $skipCache = false) {
$assoc = $this->getRoomAssociations($skipCache);
if (!isset($assoc[$room->roomID])) {
return false;
}
if (!isset($assoc[$room->roomID])) return false;
return $assoc[$room->roomID]['active'] === 1;
}
@ -92,17 +84,12 @@ public function isInRoom(Room $room, $skipCache = false): bool
*
* @return mixed[][]
*/
public static function getDeadSessions()
{
$sql = "SELECT userID,
roomID,
sessionID
FROM chat1_session
public static function getDeadSessions() {
$sql = "SELECT userID, roomID, sessionID
FROM chat".WCF_N."_session
WHERE lastRequest < ?";
$statement = WCF::getDB()->prepare($sql);
$statement->execute([
TIME_NOW - 60 * 3,
]);
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute([ TIME_NOW - 60 * 3 ]);
return $statement->fetchAll(\PDO::FETCH_ASSOC);
}
@ -110,12 +97,10 @@ public static function getDeadSessions()
/**
* @inheritDoc
*/
public function jsonSerialize(): array
{
return [
'userID' => $this->userID,
'username' => $this->username,
'link' => $this->getLink(),
public function jsonSerialize() {
return [ 'userID' => $this->userID
, 'username' => $this->username
, 'link' => $this->getLink()
];
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,20 +14,17 @@
namespace chat\data\user;
use chat\data\room\Room;
use chat\data\room\RoomAction;
use wcf\data\AbstractDatabaseObjectAction;
use wcf\system\cache\runtime\UserProfileRuntimeCache;
use wcf\system\cache\runtime\UserRuntimeCache;
use wcf\system\event\EventHandler;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\exception\UserInputException;
use \chat\data\room\RoomCache;
use \wcf\system\cache\runtime\UserProfileRuntimeCache;
use \wcf\system\cache\runtime\UserRuntimeCache;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\exception\UserInputException;
use \wcf\system\WCF;
/**
* Executes chat user-related actions.
*/
class UserAction extends AbstractDatabaseObjectAction
{
class UserAction extends \wcf\data\AbstractDatabaseObjectAction {
/**
* @inheritDoc
*/
@ -37,11 +33,8 @@ class UserAction extends AbstractDatabaseObjectAction
/**
* Validates parameters and permissions.
*/
public function validateGetUsersByID()
{
if (!Room::canSeeAny()) {
throw new PermissionDeniedException();
}
public function validateGetUsersByID() {
if (!\chat\data\room\Room::canSeeAny()) throw new PermissionDeniedException();
$this->readIntegerArray('userIDs');
}
@ -49,34 +42,30 @@ public function validateGetUsersByID()
/**
* Returns information about the users identified by the given userIDs.
*/
public function getUsersByID()
{
public function getUsersByID() {
$userList = UserProfileRuntimeCache::getInstance()->getObjects($this->parameters['userIDs']);
return \array_map(function ($user) {
if (!$user) {
return null;
}
return array_map(function ($user) {
if (!$user) return null;
$payload = [
'image16' => $user->getAvatar()->getImageTag(16),
'image24' => $user->getAvatar()->getImageTag(24),
'image32' => $user->getAvatar()->getImageTag(32),
'image48' => $user->getAvatar()->getImageTag(48),
'imageUrl' => $user->getAvatar()->getURL(),
'link' => $user->getLink(),
'anchor' => $user->getAnchorTag(),
'userID' => $user->userID,
'username' => $user->username,
'userTitle' => $user->getUserTitle(),
'userRankClass' => $user->getRank() ? $user->getRank()->cssClassName : null,
'formattedUsername' => $user->getFormattedUsername(),
'away' => $user->chatAway,
'color1' => $user->chatColor1,
'color2' => $user->chatColor2,
$payload = [ 'image16' => $user->getAvatar()->getImageTag(16)
, 'image24' => $user->getAvatar()->getImageTag(24)
, 'image32' => $user->getAvatar()->getImageTag(32)
, 'image48' => $user->getAvatar()->getImageTag(48)
, 'imageUrl' => $user->getAvatar()->getURL()
, 'link' => $user->getLink()
, 'anchor' => $user->getAnchorTag()
, 'userID' => $user->userID
, 'username' => $user->username
, 'userTitle' => $user->getUserTitle()
, 'userRankClass' => $user->getRank() ? $user->getRank()->cssClassName : null
, 'formattedUsername' => $user->getFormattedUsername()
, 'away' => $user->chatAway
, 'color1' => $user->chatColor1
, 'color2' => $user->chatColor2
];
EventHandler::getInstance()->fireAction($this, 'getUsersByID', $payload);
\wcf\system\event\EventHandler::getInstance()->fireAction($this, 'getUsersByID', $payload);
return $payload;
}, $userList);
@ -85,30 +74,22 @@ public function getUsersByID()
/**
* Clears dead clients.
*/
public function clearDeadSessions()
{
public function clearDeadSessions() {
$sessions = User::getDeadSessions();
if ($sessions === []) {
return;
}
$userIDs = \array_map(static function ($item) {
if (empty($sessions)) return;
$userIDs = array_map(function ($item) {
return $item['userID'];
}, $sessions);
$users = UserRuntimeCache::getInstance()->getObjects($userIDs);
foreach ($sessions as $session) {
$parameters = [
'user' => $users[$session['userID']],
'roomID' => $session['roomID'],
'sessionID' => $session['sessionID'],
$parameters = [ 'user' => $users[$session['userID']]
, 'roomID' => $session['roomID']
, 'sessionID' => $session['sessionID']
];
try {
(new RoomAction(
[ ],
'leave',
$parameters
))->executeAction();
} catch (UserInputException $e) {
(new \chat\data\room\RoomAction([ ], 'leave', $parameters))->executeAction();
}
catch (UserInputException $e) {
// Probably some other request has been faster to remove this session, ignore
}
}
@ -117,24 +98,21 @@ public function clearDeadSessions()
/**
* @inheritDoc
*/
public function create()
{
public function create() {
throw new \BadMethodCallException();
}
/**
* @inheritDoc
*/
public function update()
{
public function update() {
throw new \BadMethodCallException();
}
/**
* @inheritDoc
*/
public function delete()
{
public function delete() {
throw new \BadMethodCallException();
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -18,8 +17,7 @@
/**
* Represents a list of chat users.
*/
class UserList extends \wcf\data\user\UserList
{
class UserList extends \wcf\data\user\UserList {
/**
* @inheritDoc
*/

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,24 +14,16 @@
namespace chat\page;
use chat\data\message\Message;
use chat\data\message\MessageList;
use chat\data\room\RoomCache;
use wcf\data\object\type\ObjectTypeCache;
use wcf\page\AbstractPage;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\exception\IllegalLinkException;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\page\PageLocationManager;
use wcf\system\request\LinkHandler;
use wcf\system\WCF;
use wcf\util\HeaderUtil;
use \chat\data\message\MessageList;
use \wcf\system\exception\IllegalLinkException;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\page\PageLocationManager;
use \wcf\system\WCF;
/**
* Shows the log of a specific chat room.
*/
final class LogPage extends AbstractPage
{
class LogPage extends \wcf\page\AbstractPage {
use TConfiguredPage;
/**
@ -50,7 +41,7 @@ final class LogPage extends AbstractPage
* The requested chat room.
* @var \chat\data\room\Room
*/
public $room;
public $room = null;
/**
* The requested message ID.
@ -62,7 +53,7 @@ final class LogPage extends AbstractPage
* The requested message.
* @var \chat\data\message\Message
*/
public $message;
public $message = null;
/**
* The requested time.
@ -73,53 +64,39 @@ final class LogPage extends AbstractPage
/**
* @inheritDoc
*/
public function readParameters()
{
public function readParameters() {
parent::readParameters();
if (isset($_GET['id'])) {
$this->roomID = \intval($_GET['id']);
}
$this->room = RoomCache::getInstance()->getRoom($this->roomID);
if (isset($_GET['id'])) $this->roomID = intval($_GET['id']);
$this->room = \chat\data\room\RoomCache::getInstance()->getRoom($this->roomID);
if ($this->room === null) {
throw new IllegalLinkException();
}
if (!$this->room->canSee($user = null, $reason)) {
throw $reason;
}
if (!$this->room->canSeeLog($user = null, $reason)) {
throw $reason;
}
if ($this->room === null) throw new IllegalLinkException();
if (!$this->room->canSee($user = null, $reason)) throw $reason;
if (!$this->room->canSeeLog($user = null, $reason)) throw $reason;
if (isset($_GET['messageid'])) {
$this->messageID = \intval($_GET['messageid']);
}
if (isset($_GET['messageid'])) $this->messageID = intval($_GET['messageid']);
if ($this->messageID) {
$this->message = new Message($this->messageID);
$this->message = new \chat\data\message\Message($this->messageID);
if (!$this->message->getMessageType()->getProcessor()->canSeeInLog($this->message, $this->room)) {
throw new PermissionDeniedException();
}
}
if (isset($_REQUEST['datetime'])) {
$this->datetime = \strtotime($_REQUEST['datetime']);
}
if (isset($_REQUEST['datetime'])) $this->datetime = strtotime($_REQUEST['datetime']);
}
/**
* @inheritDoc
*/
public function readData()
{
public function readData() {
parent::readData();
if ($this->datetime) {
// Determine message types supporting fast select
$objectTypes = ObjectTypeCache::getInstance()->getObjectTypes('be.bastelstu.chat.messageType');
$fastSelect = \array_map(static function ($item) {
$objectTypes = \wcf\data\object\type\ObjectTypeCache::getInstance()->getObjectTypes('be.bastelstu.chat.messageType');
$fastSelect = array_map(function ($item) {
return $item->objectTypeID;
}, \array_filter($objectTypes, static function ($item) {
}, array_filter($objectTypes, function ($item) {
// TODO: Consider a method couldAppearInLog(): bool
return $item->getProcessor()->supportsFastSelect();
}));
@ -128,7 +105,7 @@ public function readData()
$loops = 0;
do {
// Build fast select filter
$condition = new PreparedStatementConditionBuilder();
$condition = new \wcf\system\database\util\PreparedStatementConditionBuilder();
$condition->add('((roomID = ? AND objectTypeID IN (?)) OR objectTypeID NOT IN (?))', [ $this->room->roomID, $fastSelect, $fastSelect ]);
$condition->add('time >= ?', [ $this->datetime ]);
if ($minimum) {
@ -136,10 +113,10 @@ public function readData()
}
$sql = "SELECT messageID
FROM chat1_message
{$condition}
FROM chat".WCF_N."_message
".$condition."
ORDER BY messageID ASC";
$statement = WCF::getDB()->prepare($sql, 20);
$statement = WCF::getDB()->prepareStatement($sql, 20);
$statement->execute($condition->getParameters());
$messageIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
@ -154,26 +131,24 @@ public function readData()
foreach ($objects as $message) {
if ($message->getMessageType()->getProcessor()->canSeeInLog($message, $this->room)) {
$parameters = [
'messageid' => $message->messageID,
'object' => $this->room,
$parameters = [ 'application' => 'chat'
, 'messageid' => $message->messageID
, 'object' => $this->room
];
HeaderUtil::redirect(LinkHandler::getInstance()->getControllerLink(self::class, $parameters));
\wcf\util\HeaderUtil::redirect(\wcf\system\request\LinkHandler::getInstance()->getLink('Log', $parameters));
exit;
}
$minimum = $message->messageID;
}
} while (++$loops <= 3);
}
while (++$loops <= 3);
// Do a best guess redirect to an ID that is as near as possible
$parameters = [
'application' => 'chat',
'messageid' => $minimum,
'object' => $this->room,
$parameters = [ 'application' => 'chat'
, 'messageid' => $minimum
, 'object' => $this->room
];
HeaderUtil::redirect(LinkHandler::getInstance()->getControllerLink(self::class, $parameters));
\wcf\util\HeaderUtil::redirect(\wcf\system\request\LinkHandler::getInstance()->getLink('Log', $parameters));
exit;
}
}
@ -181,21 +156,15 @@ public function readData()
/**
* @inheritDoc
*/
public function assignVariables()
{
public function assignVariables() {
parent::assignVariables();
PageLocationManager::getInstance()->addParentLocation(
'be.bastelstu.chat.Room',
$this->room->roomID,
$this->room
);
WCF::getTPL()->assign([
'room' => $this->room,
'roomList' => RoomCache::getInstance()->getRooms(),
'messageID' => $this->messageID,
'message' => $this->message,
'config' => $this->getConfig(),
PageLocationManager::getInstance()->addParentLocation('be.bastelstu.chat.Room', $this->room->roomID, $this->room);
WCF::getTPL()->assign([ 'room' => $this->room
, 'roomList' => \chat\data\room\RoomCache::getInstance()->getRooms()
, 'messageID' => $this->messageID
, 'message' => $this->message
, 'config' => $this->getConfig()
]);
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,17 +14,12 @@
namespace chat\page;
use chat\data\room\Room;
use chat\data\room\RoomCache;
use wcf\page\AbstractPage;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\WCF;
use \wcf\system\WCF;
/**
* Shows the list of available chat rooms.
*/
final class RoomListPage extends AbstractPage
{
class RoomListPage extends \wcf\page\AbstractPage {
/**
* @inheritDoc
*/
@ -41,34 +35,27 @@ final class RoomListPage extends AbstractPage
/**
* @inheritDoc
*/
public function checkPermissions()
{
public function checkPermissions() {
parent::checkPermissions();
if (!Room::canSeeAny()) {
throw new PermissionDeniedException();
}
if (!\chat\data\room\Room::canSeeAny()) throw new \wcf\system\exception\PermissionDeniedException();
}
/**
* @inheritDoc
*/
public function readData()
{
public function readData() {
parent::readData();
$this->rooms = RoomCache::getInstance()->getRooms();
$this->rooms = \chat\data\room\RoomCache::getInstance()->getRooms();
}
/**
* @inheritDoc
*/
public function assignVariables()
{
public function assignVariables() {
parent::assignVariables();
WCF::getTPL()->assign([
'rooms' => $this->rooms,
]);
WCF::getTPL()->assign([ 'rooms' => $this->rooms ]);
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,21 +14,15 @@
namespace chat\page;
use chat\data\room\RoomCache;
use wcf\data\package\PackageCache;
use wcf\page\AbstractPage;
use wcf\system\attachment\AttachmentHandler;
use wcf\system\exception\IllegalLinkException;
use wcf\system\exception\NamedUserException;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\push\PushHandler;
use wcf\system\WCF;
use \wcf\system\exception\IllegalLinkException;
use \wcf\system\exception\NamedUserException;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\WCF;
/**
* Shows a specific chat room.
*/
final class RoomPage extends AbstractPage
{
class RoomPage extends \wcf\page\AbstractPage {
use TConfiguredPage;
/**
@ -47,38 +40,29 @@ final class RoomPage extends AbstractPage
/**
* The requested chat room ID.
*
* @var int
* @param int
*/
public $roomID = 0;
/**
* The requested chat room.
*
* @var \chat\data\room\Room
* @param \chat\data\room\Room
*/
public $room;
public $room = null;
/**
* @inheritDoc
*/
public function readParameters()
{
public function readParameters() {
parent::readParameters();
if (isset($_GET['id'])) {
$this->roomID = \intval($_GET['id']);
}
$this->room = RoomCache::getInstance()->getRoom($this->roomID);
if (isset($_GET['id'])) $this->roomID = intval($_GET['id']);
$this->room = \chat\data\room\RoomCache::getInstance()->getRoom($this->roomID);
if ($this->room === null) {
throw new IllegalLinkException();
}
if (!$this->room->canSee($user = null, $reason)) {
throw $reason;
}
if (!$this->room->canJoin($user = null, $reason)) {
throw $reason;
}
if ($this->room === null) throw new IllegalLinkException();
if (!$this->room->canSee($user = null, $reason)) throw $reason;
if (!$this->room->canJoin($user = null, $reason)) throw $reason;
$this->canonicalURL = $this->room->getLink();
}
@ -86,17 +70,16 @@ public function readParameters()
/**
* @inheritDoc
*/
public function checkPermissions()
{
public function checkPermissions() {
parent::checkPermissions();
$package = PackageCache::getInstance()->getPackageByIdentifier('be.bastelstu.chat');
if (\stripos($package->packageVersion, 'Alpha') !== false) {
$sql = "SELECT COUNT(*) FROM wcf1_user";
$statement = WCF::getDB()->prepare($sql);
$package = \wcf\data\package\PackageCache::getInstance()->getPackageByIdentifier('be.bastelstu.chat');
if (stripos($package->packageVersion, 'Alpha') !== false) {
$sql = "SELECT COUNT(*) FROM wcf".WCF_N."_user";
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute();
$userCount = $statement->fetchSingleColumn();
if ((($userCount > 5 && !OFFLINE) || ($userCount > 30 && OFFLINE)) && \sha1(WCF_UUID) !== '643a6b3af2a6ea3d393c4d8371e75d7d1b66e0d0') {
if ((($userCount > 5 && !OFFLINE) || ($userCount > 30 && OFFLINE)) && sha1(WCF_UUID) !== '643a6b3af2a6ea3d393c4d8371e75d7d1b66e0d0') {
throw new PermissionDeniedException("Do not use alpha versions of Tims Chat in production communities!");
}
}
@ -105,10 +88,9 @@ public function checkPermissions()
/**
* @inheritDoc
*/
public function readData()
{
public function readData() {
$sql = "SELECT 1";
$statement = WCF::getDB()->prepare($sql);
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute();
if ($statement->fetchSingleColumn() !== 1) {
throw new NamedUserException('PHP must be configured to use the MySQLnd driver, instead of libmysqlclient.');
@ -117,14 +99,9 @@ public function readData()
parent::readData();
// This attachment handler gets only used for the language variable `wcf.attachment.upload.limits`!
$this->attachmentHandler = new AttachmentHandler(
'be.bastelstu.chat.message',
0,
'DEADC0DE00000000DEADC0DE00000000DEADC0DE',
$this->room->roomID
);
$this->attachmentHandler = new \wcf\system\attachment\AttachmentHandler('be.bastelstu.chat.message', 0, 'DEADC0DE00000000DEADC0DE00000000DEADC0DE', $this->room->roomID);
$pushHandler = PushHandler::getInstance();
$pushHandler = \wcf\system\push\PushHandler::getInstance();
$pushHandler->joinChannel('be.bastelstu.chat');
$pushHandler->joinChannel('be.bastelstu.chat.room-'.$this->room->roomID);
}
@ -132,14 +109,12 @@ public function readData()
/**
* @inheritDoc
*/
public function assignVariables()
{
public function assignVariables() {
parent::assignVariables();
WCF::getTPL()->assign([
'room' => $this->room,
'config' => $this->getConfig(),
'attachmentHandler' => $this->attachmentHandler,
WCF::getTPL()->assign([ 'room' => $this->room
, 'config' => $this->getConfig()
, 'attachmentHandler' => $this->attachmentHandler
]);
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,55 +14,47 @@
namespace chat\page;
use chat\data\command\Command;
use chat\data\command\CommandCache;
use wcf\data\object\type\ObjectTypeCache;
use wcf\data\package\PackageCache;
use wcf\system\event\EventHandler;
use wcf\util\JSON;
use \chat\data\command\Command;
use \chat\data\command\CommandCache;
use \wcf\data\object\type\ObjectTypeCache;
use \wcf\data\package\PackageCache;
/**
* Provides a getConfig() method, returning the JSON configuration
* for the chat's JavaSCript.
*/
trait TConfiguredPage
{
trait TConfiguredPage {
/**
* Returns the configuration for the chat's JavaScript.
*/
public function getConfig()
{
public function getConfig() {
$triggers = CommandCache::getInstance()->getTriggers();
$commands = \array_map(function (Command $item) {
$commands = array_map(function (Command $item) {
$package = PackageCache::getInstance()->getPackage($item->packageID)->package;
return [
'package' => $package,
'identifier' => $item->identifier,
'commandID' => $item->commandID,
'module' => $item->getProcessor()->getJavaScriptModuleName(),
'isAvailable' => $item->getProcessor()->isAvailable($this->room) && ($item->hasTriggers() || $item->getProcessor()->allowWithoutTrigger()),
return [ 'package' => $package
, 'identifier' => $item->identifier
, 'commandID' => $item->commandID
, 'module' => $item->getProcessor()->getJavaScriptModuleName()
, 'isAvailable' => $item->getProcessor()->isAvailable($this->room) && ($item->hasTriggers() || $item->getProcessor()->allowWithoutTrigger())
];
}, CommandCache::getInstance()->getCommands());
$messageTypes = \array_map(static function ($item) {
return [
'module' => $item->getProcessor()->getJavaScriptModuleName(),
$messageTypes = array_map(function ($item) {
return [ 'module' => $item->getProcessor()->getJavaScriptModuleName()
];
}, ObjectTypeCache::getInstance()->getObjectTypes('be.bastelstu.chat.messageType'));
$config = [
'clientVersion' => 1,
'reloadTime' => (int)CHAT_RELOADTIME,
'autoAwayTime' => (int)CHAT_AUTOAWAYTIME,
'commands' => $commands,
'triggers' => $triggers,
'messageTypes' => $messageTypes,
$config = [ 'clientVersion' => 1
, 'reloadTime' => (int) CHAT_RELOADTIME
, 'autoAwayTime' => (int) CHAT_AUTOAWAYTIME
, 'commands' => $commands
, 'triggers' => $triggers
, 'messageTypes' => $messageTypes
];
EventHandler::getInstance()->fireAction($this, 'config', $config);
\wcf\system\event\EventHandler::getInstance()->fireAction($this, 'config', $config);
return JSON::encode($config);
return \wcf\util\JSON::encode($config);
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,33 +14,25 @@
namespace chat\system;
use chat\page\RoomListPage;
use wcf\system\application\AbstractApplication;
use wcf\system\request\route\StaticRequestRoute;
use wcf\system\request\RouteHandler;
final class CHATCore extends AbstractApplication
{
class CHATCore extends \wcf\system\application\AbstractApplication {
/**
* @inheritDoc
*/
protected $primaryController = RoomListPage::class;
protected $primaryController = \chat\page\RoomListPage::class;
/**
* @inheritDoc
*/
public function __run()
{
$route = new StaticRequestRoute();
public function __run() {
$route = new \wcf\system\request\route\StaticRequestRoute();
$route->setStaticController('chat', 'Log');
$route->setBuildSchema('/{controller}/{id}-{title}/{messageid}');
$route->setPattern('~^/?(?P<controller>[^/]+)/(?P<id>\d+)(?:-(?P<title>[^/]+))?/(?P<messageid>\d+)~x');
$route->setRequiredComponents([
'id' => '~^\d+$~',
'messageid' => '~^\d+$~',
$route->setRequiredComponents([ 'id' => '~^\d+$~'
, 'messageid' => '~^\d+$~'
]);
$route->setMatchController(true);
RouteHandler::getInstance()->addRoute($route);
\wcf\system\request\RouteHandler::getInstance()->addRoute($route);
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,31 +14,25 @@
namespace chat\system\attachment;
use chat\data\message\Message;
use chat\data\message\MessageList;
use chat\data\room\RoomCache;
use wcf\system\attachment\AbstractAttachmentObjectType;
use wcf\system\WCF;
use wcf\util\ArrayUtil;
use \chat\data\message\Message;
use \chat\data\message\MessageList;
use \chat\data\room\RoomCache;
use \wcf\system\WCF;
/**
* Attachment object type implementation for messages.
*/
final class MessageAttachmentObjectType extends AbstractAttachmentObjectType
{
class MessageAttachmentObjectType extends \wcf\system\attachment\AbstractAttachmentObjectType {
/**
* @inheritDoc
*/
public function canDownload($objectID): bool
{
public function canDownload($objectID) {
if ($objectID) {
$message = new Message($objectID);
if (!$message->messageID) {
return false;
if ($message->getMessageType()->objectType !== 'be.bastelstu.chat.messageType.attachment') {
throw new \LogicException('Unreachable');
}
\assert($message->getMessageType()->objectType === 'be.bastelstu.chat.messageType.attachment');
$room = $message->getRoom();
return $room->canSee();
@ -51,8 +44,7 @@ public function canDownload($objectID): bool
/**
* @inheritDoc
*/
public function canUpload($objectID, $parentObjectID = 0): bool
{
public function canUpload($objectID, $parentObjectID = 0) {
if ($objectID) {
return false;
}
@ -76,43 +68,35 @@ public function canUpload($objectID, $parentObjectID = 0): bool
/**
* @inheritDoc
*/
public function canDelete($objectID): bool
{
public function canDelete($objectID) {
return false;
}
/**
* @inheritDoc
*/
public function getMaxCount(): int
{
public function getMaxCount() {
return 1;
}
/**
* @inheritDoc
*/
public function getMaxSize(): int
{
return (int)WCF::getSession()->getPermission('user.chat.attachment.maxSize');
public function getMaxSize() {
return WCF::getSession()->getPermission('user.chat.attachment.maxSize');
}
/**
* @inheritDoc
*/
public function getAllowedExtensions()
{
return ArrayUtil::trim(\explode(
"\n",
WCF::getSession()->getPermission('user.chat.attachment.allowedExtensions')
));
public function getAllowedExtensions() {
return \wcf\util\ArrayUtil::trim(\explode("\n", WCF::getSession()->getPermission('user.chat.attachment.allowedExtensions')));
}
/**
* @inheritDoc
*/
public function cacheObjects(array $objectIDs)
{
public function cacheObjects(array $objectIDs) {
$messageList = new MessageList();
$messageList->setObjectIDs($objectIDs);
$messageList->readObjects();

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,29 +14,17 @@
namespace chat\system\box;
use chat\data\room\Room;
use chat\data\room\RoomList;
use chat\page\RoomListPage;
use chat\page\RoomPage;
use wcf\system\box\AbstractDatabaseObjectListBoxController;
use wcf\system\request\LinkHandler;
use wcf\system\request\RequestHandler;
use wcf\system\WCF;
use \wcf\system\request\RequestHandler;
use \wcf\system\WCF;
/**
* Dynamic box controller implementation for a list of rooms.
*/
final class RoomListBoxController extends AbstractDatabaseObjectListBoxController
{
class RoomListBoxController extends \wcf\system\box\AbstractDatabaseObjectListBoxController {
/**
* @inheritDoc
*/
protected static $supportedPositions = [
'contentBottom',
'contentTop',
'sidebarLeft',
'sidebarRight',
];
protected static $supportedPositions = [ 'contentBottom', 'contentTop', 'sidebarLeft', 'sidebarRight' ];
/**
* @inheritDoc
@ -47,17 +34,16 @@ final class RoomListBoxController extends AbstractDatabaseObjectListBoxControlle
/**
* @var int
*/
protected $activeRoomID;
protected $activeRoomID = null;
/**
* @inheritDoc
*/
public function __construct()
{
public function __construct() {
parent::__construct();
$activeRequest = RequestHandler::getInstance()->getActiveRequest();
if ($activeRequest && $activeRequest->getRequestObject() instanceof RoomPage) {
if ($activeRequest && $activeRequest->getRequestObject() instanceof \chat\page\RoomPage) {
$this->activeRoomID = $activeRequest->getRequestObject()->room->roomID;
}
}
@ -65,8 +51,7 @@ public function __construct()
/**
* Sets the active room ID.
*/
public function setActiveRoomID($activeRoomID)
{
public function setActiveRoomID($activeRoomID) {
$this->activeRoomID = $activeRoomID;
}
@ -75,69 +60,61 @@ public function setActiveRoomID($activeRoomID)
*
* @return int
*/
public function getActiveRoomID()
{
public function getActiveRoomID() {
return $this->activeRoomID;
}
/**
* @inheritDoc
*/
public function hasLink()
{
public function hasLink() {
return true;
}
/**
* @inheritDoc
*/
public function getLink(): string
{
return LinkHandler::getInstance()->getControllerLink(RoomListPage::class);
public function getLink() {
return \wcf\system\request\LinkHandler::getInstance()->getLink('RoomList', [ 'application' => 'chat' ]);
}
/**
* @inheritDoc
*/
protected function getObjectList()
{
return new RoomList();
protected function getObjectList() {
return new \chat\data\room\RoomList();
}
/**
* @inheritDoc
*/
protected function getTemplate()
{
protected function getTemplate() {
$templateName = 'boxRoomList';
if ($this->box->position === 'sidebarLeft' || $this->box->position === 'sidebarRight') {
$templateName = 'boxRoomListSidebar';
}
return WCF::getTPL()->fetch($templateName, 'chat', [
'boxRoomList' => $this->objectList,
'boxID' => $this->getBox()->boxID,
'activeRoomID' => $this->activeRoomID ?: 0,
return WCF::getTPL()->fetch($templateName, 'chat', [ 'boxRoomList' => $this->objectList
, 'boxID' => $this->getBox()->boxID
, 'activeRoomID' => $this->activeRoomID ?: 0
], true);
}
/**
* @inheritDoc
*/
public function hasContent()
{
public function hasContent() {
if ($this->box->position === 'sidebarLeft' || $this->box->position === 'sidebarRight') {
parent::hasContent();
foreach ($this->objectList as $room) {
if ($room->canSee()) {
return true;
}
if ($room->canSee()) return true;
}
return false;
} else {
return Room::canSeeAny();
}
else {
return \chat\data\room\Room::canSeeAny();
}
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,42 +14,35 @@
namespace chat\system\cache\builder;
use chat\data\command\CommandList;
use wcf\system\cache\builder\AbstractCacheBuilder;
use wcf\system\WCF;
use \wcf\system\WCF;
/**
* Caches all chat commands.
*/
final class CommandCacheBuilder extends AbstractCacheBuilder
{
class CommandCacheBuilder extends \wcf\system\cache\builder\AbstractCacheBuilder {
/**
* @inheritDoc
* @see \wcf\system\cache\AbstractCacheBuilder::rebuild()
*/
public function rebuild(array $parameters)
{
$data = [
'commands' => [ ],
'triggers' => [ ],
'packages' => [ ],
public function rebuild(array $parameters) {
$data = [ 'commands' => [ ]
, 'triggers' => [ ]
, 'packages' => [ ]
];
$commandList = new CommandList();
$commandList = new \chat\data\command\CommandList();
$commandList->sqlOrderBy = 'command.commandID';
$commandList->readObjects();
$data['commands'] = $commandList->getObjects();
foreach ($data['commands'] as $command) {
if (!isset($data['packages'][$command->packageID])) {
$data['packages'][$command->packageID] = [ ];
}
if (!isset($data['packages'][$command->packageID])) $data['packages'][$command->packageID] = [ ];
$data['packages'][$command->packageID][$command->identifier] = $command;
}
$sql = "SELECT *
FROM chat1_command_trigger";
$statement = WCF::getDB()->prepare($sql);
FROM chat".WCF_N."_command_trigger";
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute();
$data['triggers'] = $statement->fetchMap('commandTrigger', 'commandID');

View File

@ -1,8 +1,7 @@
<?php
/**
* Copyright (C) 2010-2024 Tim Düsterhus
* Copyright (C) 2010-2024 Woltlab GmbH
* Copyright (C) 2010-2021 Tim Düsterhus
* Copyright (C) 2010-2021 Woltlab GmbH
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -21,40 +20,37 @@
namespace chat\system\cache\builder;
use wcf\system\acl\ACLHandler;
use wcf\system\cache\builder\AbstractCacheBuilder;
use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\WCF;
use \wcf\system\acl\ACLHandler;
use \wcf\system\WCF;
/**
* Caches the chat permissions for a combination of user groups.
*/
final class PermissionCacheBuilder extends AbstractCacheBuilder
{
class PermissionCacheBuilder extends \wcf\system\cache\builder\AbstractCacheBuilder {
/**
* @inheritDoc
*/
public function rebuild(array $parameters)
{
public function rebuild(array $parameters) {
$data = [ ];
if (!empty($parameters)) {
$conditionBuilder = new PreparedStatementConditionBuilder();
$conditionBuilder = new \wcf\system\database\util\PreparedStatementConditionBuilder();
$conditionBuilder->add('acl_option.objectTypeID = ?', [ ACLHandler::getInstance()->getObjectTypeID('be.bastelstu.chat.room') ]);
$conditionBuilder->add('option_to_group.groupID IN (?)', [ $parameters ]);
$sql = "SELECT option_to_group.objectID AS roomID,
option_to_group.optionValue,
acl_option.optionName AS permission
FROM wcf1_acl_option acl_option
INNER JOIN wcf1_acl_option_to_group option_to_group
FROM wcf".WCF_N."_acl_option acl_option
INNER JOIN wcf".WCF_N."_acl_option_to_group option_to_group
ON option_to_group.optionID = acl_option.optionID
{$conditionBuilder}";
$statement = WCF::getDB()->prepare($sql);
".$conditionBuilder;
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute($conditionBuilder->getParameters());
while (($row = $statement->fetchArray())) {
if (!isset($data[$row['roomID']][$row['permission']])) {
$data[$row['roomID']][$row['permission']] = $row['optionValue'];
} else {
}
else {
$data[$row['roomID']][$row['permission']] = $row['optionValue'] || $data[$row['roomID']][$row['permission']];
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,20 +14,15 @@
namespace chat\system\cache\builder;
use chat\data\room\RoomList;
use wcf\system\cache\builder\AbstractCacheBuilder;
/**
* Caches all chat rooms.
*/
final class RoomCacheBuilder extends AbstractCacheBuilder
{
class RoomCacheBuilder extends \wcf\system\cache\builder\AbstractCacheBuilder {
/**
* @inheritDoc
*/
public function rebuild(array $parameters)
{
$roomList = new RoomList();
public function rebuild(array $parameters) {
$roomList = new \chat\data\room\RoomList();
$roomList->sqlOrderBy = "room.position";
$roomList->readObjects();

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,16 +14,12 @@
namespace chat\system\cache\runtime;
use chat\data\user\UserList as ChatUserList;
use wcf\system\cache\runtime\AbstractRuntimeCache;
/**
* Runtime cache implementation for chat users.
*/
class UserRuntimeCache extends AbstractRuntimeCache
{
class UserRuntimeCache extends \wcf\system\cache\runtime\AbstractRuntimeCache {
/**
* @inheritDoc
*/
protected $listClassName = ChatUserList::class;
protected $listClassName = \chat\data\user\UserList::class;
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,39 +14,32 @@
namespace chat\system\command;
use chat\data\command\Command;
use chat\data\room\Room;
use wcf\data\DatabaseObjectDecorator;
use wcf\data\IDatabaseObjectProcessor;
use wcf\data\object\type\ObjectTypeCache;
use wcf\data\user\UserProfile;
use wcf\system\exception\UserInputException;
use \chat\data\room\Room;
use \wcf\data\object\type\ObjectTypeCache;
use \wcf\data\user\UserProfile;
use \wcf\system\exception\UserInputException;
/**
* Default implemention for command processors.
*/
abstract class AbstractCommand extends DatabaseObjectDecorator implements
ICommand,
IDatabaseObjectProcessor
{
abstract class AbstractCommand extends \wcf\data\DatabaseObjectDecorator implements ICommand
, \wcf\data\IDatabaseObjectProcessor {
/**
* @inheritDoc
*/
protected static $baseClass = Command::class;
protected static $baseClass = \chat\data\command\Command::class;
/**
* @inheritDoc
*/
public function isAvailable(Room $room, ?UserProfile $user = null)
{
public function isAvailable(Room $room, UserProfile $user = null) {
return true;
}
/**
* @inheritDoc
*/
public function allowWithoutTrigger()
{
public function allowWithoutTrigger() {
return false;
}
@ -57,12 +49,8 @@ public function allowWithoutTrigger()
* @param string
* @return int
*/
public function getMessageObjectTypeID($objectType)
{
$objectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName(
'be.bastelstu.chat.messageType',
$objectType
);
public function getMessageObjectTypeID($objectType) {
$objectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName('be.bastelstu.chat.messageType', $objectType);
if (!$objectType) {
throw new \LogicException('Missing object type');
@ -79,9 +67,8 @@ public function getMessageObjectTypeID($objectType)
* @param string $key
* @return mixed The value.
*/
public function assertParameter($parameters, $key)
{
if (\array_key_exists($key, $parameters)) {
public function assertParameter($parameters, $key) {
if (array_key_exists($key, $parameters)) {
return $parameters[$key];
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,113 +14,70 @@
namespace chat\system\command;
use wcf\data\DatabaseObject;
use wcf\system\bbcode\BBCodeHandler;
use wcf\system\exception\UserInputException;
use wcf\system\html\input\HtmlInputProcessor;
use wcf\system\message\censorship\Censorship;
use wcf\system\WCF;
use \wcf\system\exception\UserInputException;
use \wcf\system\bbcode\BBCodeHandler;
use \wcf\system\message\censorship\Censorship;
use \wcf\system\WCF;
/**
* Represents a command that processes the input using HtmlInputProcessor.
*/
abstract class AbstractInputProcessedCommand extends AbstractCommand
{
abstract class AbstractInputProcessedCommand extends AbstractCommand {
/**
* HtmlInputProcessor to use.
* @var \wcf\system\html\input\HtmlInputProcessor
*/
protected $processor;
protected $processor = null;
/**
* The text processed last.
* @var string
*/
private $text;
private $text = null;
public function __construct(DatabaseObject $object)
{
public function __construct(\wcf\data\DatabaseObject $object) {
parent::__construct($object);
$this->processor = new HtmlInputProcessor();
$this->processor = new \wcf\system\html\input\HtmlInputProcessor();
$this->setDisallowedBBCodes();
}
private function setDisallowedBBCodes()
{
BBCodeHandler::getInstance()->setDisallowedBBCodes(\explode(
',',
WCF::getSession()->getPermission('user.chat.disallowedBBCodes')
));
private function setDisallowedBBCodes() {
BBCodeHandler::getInstance()->setDisallowedBBCodes(explode(',', WCF::getSession()->getPermission('user.chat.disallowedBBCodes')));
}
public function setText($text)
{
if ($this->text === $text) {
return;
}
public function setText($text) {
if ($this->text === $text) return;
$this->text = $text;
$this->setDisallowedBBCodes();
$this->processor->process(
$text,
'be.bastelstu.chat.message',
0
);
$this->processor->process($text, 'be.bastelstu.chat.message', 0);
}
public function validateText()
{
public function validateText() {
if ($this->processor->appearsToBeEmpty()) {
throw new UserInputException(
'message',
WCF::getLanguage()->getDynamicVariable('wcf.global.form.error.empty')
);
throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('wcf.global.form.error.empty'));
}
$message = $this->processor->getTextContent();
// validate message length
if (\mb_strlen($message) > CHAT_MAX_LENGTH) {
throw new UserInputException(
'message',
WCF::getLanguage()->getDynamicVariable(
'wcf.message.error.tooLong',
[
'maxTextLength' => CHAT_MAX_LENGTH,
]
)
);
if (mb_strlen($message) > CHAT_MAX_LENGTH) {
throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('wcf.message.error.tooLong', [ 'maxTextLength' => CHAT_MAX_LENGTH ]));
}
// search for disallowed bbcodes
$this->setDisallowedBBCodes();
$disallowedBBCodes = $this->processor->validate();
if (!empty($disallowedBBCodes)) {
throw new UserInputException(
'message',
WCF::getLanguage()->getDynamicVariable(
'wcf.message.error.disallowedBBCodes',
[
'disallowedBBCodes' => $disallowedBBCodes,
]
)
);
throw new UserInputException('message', 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,
]
)
);
throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('wcf.message.error.censoredWordsFound', [ 'censoredWords' => $result ]));
}
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 3
@ -15,21 +14,19 @@
namespace chat\system\command;
use chat\data\message\MessageAction;
use chat\data\room\Room;
use chat\data\suspension\Suspension;
use chat\data\suspension\SuspensionAction;
use chat\data\user\User as ChatUser;
use wcf\data\object\type\ObjectTypeCache;
use wcf\data\user\UserProfile;
use wcf\system\exception\UserInputException;
use wcf\system\WCF;
use \chat\data\message\MessageAction;
use \chat\data\room\Room;
use \chat\data\suspension\Suspension;
use \chat\data\suspension\SuspensionAction;
use \wcf\data\object\type\ObjectTypeCache;
use \wcf\data\user\UserProfile;
use \wcf\system\exception\UserInputException;
use \wcf\system\WCF;
/**
* Represents a command that creates suspensions
*/
abstract class AbstractSuspensionCommand extends AbstractCommand
{
abstract class AbstractSuspensionCommand extends AbstractCommand {
use TNeedsUser;
/**
@ -50,11 +47,8 @@ abstract protected function checkPermissions($parameters, Room $room, UserProfil
/**
* @inheritDoc
*/
public function validate($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function validate($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
$this->assertParameter($parameters, 'username');
$this->assertParameter($parameters, 'globally');
@ -63,41 +57,24 @@ public function validate($parameters, Room $room, ?UserProfile $user = null)
$this->assertUser($parameters['username']);
if ($parameters['duration'] !== null && $parameters['duration'] < TIME_NOW) {
throw new UserInputException(
'message',
WCF::getLanguage()->getDynamicVariable('chat.error.datePast')
);
throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('chat.error.datePast'));
}
if (!empty($parameters['reason']) && \mb_strlen($parameters['reason']) > 100) {
throw new UserInputException(
'message',
WCF::getLanguage()->getDynamicVariable(
'wcf.message.error.tooLong',
[
'maxTextLength' => 250,
]
)
);
if (!empty($parameters['reason']) && mb_strlen($parameters['reason']) > 100) {
throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('wcf.message.error.tooLong', [ 'maxTextLength' => 250 ]));
}
$this->checkPermissions($parameters, $room, $user);
$test = new Suspension(null, $this->getSuspensionData($parameters, $room, $user));
if (!$test->isActive()) {
throw new UserInputException(
'message',
WCF::getLanguage()->getDynamicVariable('chat.error.suspension.noEffect')
);
throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('chat.error.suspension.noEffect'));
}
}
/**
* @inheritDoc
*/
public function execute($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function execute($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
$data = $this->getSuspensionData($parameters, $room, $user);
$test = new Suspension(null, $data);
@ -106,13 +83,7 @@ public function execute($parameters, Room $room, ?UserProfile $user = null)
}
WCF::getDB()->beginTransaction();
$suspension = (new SuspensionAction(
[ ],
'create',
[
'data' => $data,
]
))->executeAction()['returnValues'];
$suspension = (new SuspensionAction([ ], 'create', [ 'data' => $data ]))->executeAction()['returnValues'];
$this->afterCreate($suspension, $parameters, $room, $user);
WCF::getDB()->commitTransaction();
@ -121,75 +92,69 @@ public function execute($parameters, Room $room, ?UserProfile $user = null)
/**
* Creates chat messages informing about the suspension.
*
* @param \chat\data\suspension\Suspension $suspension
* @param mixed[] $parameters
* @param \chat\data\room\Room $room
* @param \wcf\data\user\UserProfile $user
*/
protected function afterCreate(Suspension $suspension, $parameters, Room $room, UserProfile $user)
{
protected function afterCreate(Suspension $suspension, $parameters, Room $room, UserProfile $user) {
$objectTypeID = $this->getMessageObjectTypeID('be.bastelstu.chat.messageType.suspend');
$target = $suspension->getUser();
if ($suspension->getRoom() === null) {
$roomIDs = \array_map(static function (Room $room) {
$roomIDs = array_map(function (Room $room) use ($user) {
return $room->roomID;
}, (new ChatUser($target))->getRooms());
}, (new \chat\data\user\User($target))->getRooms());
$roomIDs[] = $room->roomID;
} else {
}
else {
$roomIDs = [ $suspension->getRoom()->roomID ];
}
(new MessageAction(
[ ],
'create',
[
'data' => [
'roomID' => $room->roomID,
'userID' => $user->userID,
'username' => $user->username,
'time' => TIME_NOW,
'objectTypeID' => $objectTypeID,
'payload' => \serialize([
'suspension' => $suspension,
'roomIDs' => $roomIDs,
'globally' => $this->isGlobally($parameters),
'target' => [
'userID' => $target->userID,
'username' => $target->username,
],
]),
],
'updateTimestamp' => true,
(new MessageAction([ ], 'create', [ 'data' => [ 'roomID' => $room->roomID
, 'userID' => $user->userID
, 'username' => $user->username
, 'time' => TIME_NOW
, 'objectTypeID' => $objectTypeID
, 'payload' => serialize([ 'suspension' => $suspension
, 'roomIDs' => $roomIDs
, 'globally' => $this->isGlobally($parameters)
, 'target' => [ 'userID' => $target->userID
, 'username' => $target->username
]
))->executeAction();
])
]
, 'updateTimestamp' => true
]
)
)->executeAction();
}
/**
* Returns the database fields.
*
* @param mixed[] $parameters
* @param \chat\data\room\Room $room
* @param \wcf\data\user\UserProfile $user
* @return mixed[]
*/
protected function getSuspensionData($parameters, Room $room, ?UserProfile $user = null)
{
protected function getSuspensionData($parameters, Room $room, UserProfile $user = null) {
$target = $this->getUser($parameters['username']);
$globally = $this->isGlobally($parameters);
$expires = $parameters['duration'];
$reason = $parameters['reason'] ?: '';
$roomID = $globally ? null : $room->roomID;
$objectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName(
'be.bastelstu.chat.suspension',
$this->getObjectTypeName()
);
$objectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName('be.bastelstu.chat.suspension', $this->getObjectTypeName());
return [
'time' => TIME_NOW,
'expires' => $expires,
'roomID' => $roomID,
'userID' => $target->userID,
'objectTypeID' => $objectTypeID,
'reason' => $reason,
'judgeID' => $user->userID,
'judge' => $user->username,
return [ 'time' => TIME_NOW
, 'expires' => $expires
, 'roomID' => $roomID
, 'userID' => $target->userID
, 'objectTypeID' => $objectTypeID
, 'reason' => $reason
, 'judgeID' => $user->userID
, 'judge' => $user->username
];
}
@ -199,8 +164,7 @@ protected function getSuspensionData($parameters, Room $room, ?UserProfile $user
* @param mixed[] $parameters
* @return boolean
*/
protected function isGlobally($parameters)
{
protected function isGlobally($parameters) {
return $parameters['globally'] === true;
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 3
@ -15,22 +14,20 @@
namespace chat\system\command;
use chat\data\message\MessageAction;
use chat\data\room\Room;
use chat\data\suspension\Suspension;
use chat\data\suspension\SuspensionAction;
use chat\data\suspension\SuspensionList;
use chat\data\user\User as ChatUser;
use wcf\data\object\type\ObjectTypeCache;
use wcf\data\user\UserProfile;
use wcf\system\exception\UserInputException;
use wcf\system\WCF;
use \chat\data\message\MessageAction;
use \chat\data\room\Room;
use \chat\data\suspension\Suspension;
use \chat\data\suspension\SuspensionAction;
use \chat\data\suspension\SuspensionList;
use \wcf\data\object\type\ObjectTypeCache;
use \wcf\data\user\UserProfile;
use \wcf\system\exception\UserInputException;
use \wcf\system\WCF;
/**
* Represents a command that revokes suspensions
*/
abstract class AbstractUnsuspensionCommand extends AbstractCommand
{
abstract class AbstractUnsuspensionCommand extends AbstractCommand {
use TNeedsUser;
/**
@ -51,11 +48,8 @@ abstract protected function checkPermissions($parameters, Room $room, UserProfil
/**
* @inheritDoc
*/
public function validate($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function validate($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
$this->assertParameter($parameters, 'username');
$this->assertParameter($parameters, 'globally');
@ -64,30 +58,20 @@ public function validate($parameters, Room $room, ?UserProfile $user = null)
$suspensions = $this->getSuspensionData($parameters, $room, $user);
if (empty($suspensions)) {
throw new UserInputException(
'message',
WCF::getLanguage()->getDynamicVariable('chat.error.suspension.remove.empty')
);
throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('chat.error.suspension.remove.empty'));
}
}
/**
* @inheritDoc
*/
public function execute($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function execute($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
$suspensions = $this->getSuspensionData($parameters, $room, $user);
WCF::getDB()->beginTransaction();
(new SuspensionAction(
$suspensions,
'revoke',
[ ]
))->executeAction();
(new SuspensionAction($suspensions, 'revoke', [ ]))->executeAction();
$this->afterCreate($suspensions, $parameters, $room, $user);
WCF::getDB()->commitTransaction();
}
@ -97,62 +81,54 @@ public function execute($parameters, Room $room, ?UserProfile $user = null)
*
* @param \chat\data\suspension\Suspension[] $suspension
* @param mixed[] $parameters
* @param \chat\data\room\Room $room
* @param \wcf\data\user\UserProfile $user
*/
protected function afterCreate($suspensions, $parameters, Room $room, UserProfile $user)
{
protected function afterCreate($suspensions, $parameters, Room $room, UserProfile $user) {
$objectTypeID = $this->getMessageObjectTypeID('be.bastelstu.chat.messageType.unsuspend');
$target = $this->getUser($parameters['username']);
if ($this->isGlobally($parameters)) {
$roomIDs = \array_map(static function (Room $room) {
$roomIDs = array_map(function (Room $room) use ($user) {
return $room->roomID;
}, (new ChatUser($target))->getRooms());
}, (new \chat\data\user\User($target))->getRooms());
$roomIDs[] = $room->roomID;
} else {
$roomIDs = [
$room->roomID,
];
}
else {
$roomIDs = [ $room->roomID ];
}
(new MessageAction(
[ ],
'create',
[
'data' => [
'roomID' => $room->roomID,
'userID' => $user->userID,
'username' => $user->username,
'time' => TIME_NOW,
'objectTypeID' => $objectTypeID,
'payload' => \serialize([
'objectType' => $this->getObjectTypeName(),
'roomIDs' => $roomIDs,
'globally' => $this->isGlobally($parameters),
'target' => [
'userID' => $target->userID,
'username' => $target->username,
],
]),
],
'updateTimestamp' => true,
(new MessageAction([ ], 'create', [ 'data' => [ 'roomID' => $room->roomID
, 'userID' => $user->userID
, 'username' => $user->username
, 'time' => TIME_NOW
, 'objectTypeID' => $objectTypeID
, 'payload' => serialize([ 'objectType' => $this->getObjectTypeName()
, 'roomIDs' => $roomIDs
, 'globally' => $this->isGlobally($parameters)
, 'target' => [ 'userID' => $target->userID
, 'username' => $target->username
]
))->executeAction();
])
]
, 'updateTimestamp' => true
]
)
)->executeAction();
}
/**
* Returns the active suspensions.
*
* @param mixed[] $parameters
* @param \chat\data\room\Room $room
* @param \wcf\data\user\UserProfile $user
* @return mixed[]
*/
protected function getSuspensionData($parameters, Room $room, ?UserProfile $user = null)
{
protected function getSuspensionData($parameters, Room $room, UserProfile $user = null) {
$target = $this->getUser($parameters['username']);
$roomID = $this->isGlobally($parameters) ? null : $room->roomID;
$objectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName(
'be.bastelstu.chat.suspension',
$this->getObjectTypeName()
);
$objectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName('be.bastelstu.chat.suspension', $this->getObjectTypeName());
$suspensionList = new SuspensionList();
@ -162,13 +138,14 @@ protected function getSuspensionData($parameters, Room $room, ?UserProfile $user
$suspensionList->getConditionBuilder()->add('objectTypeID = ?', [ $objectTypeID ]);
if ($roomID === null) {
$suspensionList->getConditionBuilder()->add('roomID IS NULL');
} else {
}
else {
$suspensionList->getConditionBuilder()->add('roomID = ?', [ $room->roomID ]);
}
$suspensionList->readObjects();
return \array_filter($suspensionList->getObjects(), static function (Suspension $suspension) {
return array_filter($suspensionList->getObjects(), function (Suspension $suspension) {
return $suspension->isActive();
});
}
@ -179,8 +156,7 @@ protected function getSuspensionData($parameters, Room $room, ?UserProfile $user
* @param mixed[] $parameters
* @return boolean
*/
protected function isGlobally($parameters)
{
protected function isGlobally($parameters) {
return $parameters['globally'] === true;
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,36 +14,30 @@
namespace chat\system\command;
use chat\data\message\MessageAction;
use chat\data\room\Room;
use chat\data\user\User as ChatUser;
use wcf\data\user\UserEditor;
use wcf\data\user\UserProfile;
use wcf\system\exception\UserInputException;
use wcf\system\message\censorship\Censorship;
use wcf\system\WCF;
use \chat\data\message\MessageAction;
use \chat\data\room\Room;
use \wcf\data\user\UserProfile;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\exception\UserInputException;
use \wcf\system\message\censorship\Censorship;
use \wcf\system\WCF;
/**
* The away command marks the user as being away.
*/
final class AwayCommand extends AbstractCommand implements ICommand
{
class AwayCommand extends AbstractCommand implements ICommand {
/**
* @inheritDoc
*/
public function getJavaScriptModuleName()
{
public function getJavaScriptModuleName() {
return 'Bastelstu.be/Chat/Command/Away';
}
/**
* @inheritDoc
*/
public function validate($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function validate($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(WCF::getUser());
$reason = $this->assertParameter($parameters, 'reason');
@ -52,15 +45,7 @@ public function validate($parameters, Room $room, ?UserProfile $user = null)
if (ENABLE_CENSORSHIP) {
$result = Censorship::getInstance()->test($reason);
if ($result) {
throw new UserInputException(
'message',
WCF::getLanguage()->getDynamicVariable(
'wcf.message.error.censoredWordsFound',
[
'censoredWords' => $result,
]
)
);
throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('wcf.message.error.censoredWordsFound', [ 'censoredWords' => $result ]));
}
}
}
@ -68,46 +53,35 @@ public function validate($parameters, Room $room, ?UserProfile $user = null)
/**
* @inheritDoc
*/
public function execute($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function execute($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(WCF::getUser());
$reason = $this->assertParameter($parameters, 'reason');
$objectTypeID = $this->getMessageObjectTypeID('be.bastelstu.chat.messageType.away');
$rooms = \array_map(static function (Room $room) use ($user) {
return [
'roomID' => $room->roomID,
'isSilent' => !$room->canWritePublicly($user),
$rooms = array_map(function (Room $room) use ($user) {
return [ 'roomID' => $room->roomID
, 'isSilent' => !$room->canWritePublicly($user)
];
}, (new ChatUser($user->getDecoratedObject()))->getRooms());
}, (new \chat\data\user\User($user->getDecoratedObject()))->getRooms());
WCF::getDB()->beginTransaction();
$editor = new UserEditor($user->getDecoratedObject());
$editor->update([
'chatAway' => $reason,
]);
$editor = new \wcf\data\user\UserEditor($user->getDecoratedObject());
$editor->update([ 'chatAway' => $reason ]);
(new MessageAction(
[ ],
'create',
[
'data' => [
'roomID' => $room->roomID,
'userID' => $user->userID,
'username' => $user->username,
'time' => TIME_NOW,
'objectTypeID' => $objectTypeID,
'payload' => \serialize([
'message' => $reason,
'rooms' => \array_values($rooms),
]),
],
'updateTimestamp' => true,
(new MessageAction([ ], 'create', [ 'data' => [ 'roomID' => $room->roomID
, 'userID' => $user->userID
, 'username' => $user->username
, 'time' => TIME_NOW
, 'objectTypeID' => $objectTypeID
, 'payload' => serialize([ 'message' => $reason
, 'rooms' => array_values($rooms)
])
]
))->executeAction();
, 'updateTimestamp' => true
]
)
)->executeAction();
WCF::getDB()->commitTransaction();
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,89 +14,67 @@
namespace chat\system\command;
use chat\data\message\MessageAction;
use chat\data\room\Room;
use chat\data\user\User as ChatUser;
use wcf\data\user\UserEditor;
use wcf\data\user\UserProfile;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\WCF;
use \chat\data\message\MessageAction;
use \chat\data\room\Room;
use \wcf\data\user\UserProfile;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\WCF;
/**
* The back command marks the user as being back.
*/
final class BackCommand extends AbstractCommand implements ICommand
{
class BackCommand extends AbstractCommand implements ICommand {
/**
* @inheritDoc
*/
public function allowWithoutTrigger()
{
public function allowWithoutTrigger() {
return true;
}
/**
* @inheritDoc
*/
public function getJavaScriptModuleName()
{
public function getJavaScriptModuleName() {
return 'Bastelstu.be/Chat/Command/Back';
}
/**
* @inheritDoc
*/
public function validate($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function validate($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(WCF::getUser());
if ($user->chatAway === null) {
throw new PermissionDeniedException();
}
if ($user->chatAway === null) throw new PermissionDeniedException();
}
/**
* @inheritDoc
*/
public function execute($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function execute($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(WCF::getUser());
$objectTypeID = $this->getMessageObjectTypeID('be.bastelstu.chat.messageType.back');
$rooms = \array_map(static function (Room $room) use ($user) {
return [
'roomID' => $room->roomID,
'isSilent' => !$room->canWritePublicly($user),
$rooms = array_map(function (Room $room) use ($user) {
return [ 'roomID' => $room->roomID
, 'isSilent' => !$room->canWritePublicly($user)
];
}, (new ChatUser($user->getDecoratedObject()))->getRooms());
}, (new \chat\data\user\User($user->getDecoratedObject()))->getRooms());
WCF::getDB()->beginTransaction();
$editor = new UserEditor($user->getDecoratedObject());
$editor->update([
'chatAway' => null,
]);
$editor = new \wcf\data\user\UserEditor($user->getDecoratedObject());
$editor->update([ 'chatAway' => null ]);
(new MessageAction(
[ ],
'create',
[
'data' => [
'roomID' => $room->roomID,
'userID' => $user->userID,
'username' => $user->username,
'time' => TIME_NOW,
'objectTypeID' => $objectTypeID,
'payload' => \serialize([
'rooms' => \array_values($rooms),
]),
],
'updateTimestamp' => true,
(new MessageAction([ ], 'create', [ 'data' => [ 'roomID' => $room->roomID
, 'userID' => $user->userID
, 'username' => $user->username
, 'time' => TIME_NOW
, 'objectTypeID' => $objectTypeID
, 'payload' => serialize([ 'rooms' => array_values($rooms) ])
]
))->executeAction();
, 'updateTimestamp' => true
]
)
)->executeAction();
WCF::getDB()->commitTransaction();
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 3
@ -15,96 +14,79 @@
namespace chat\system\command;
use chat\data\room\Room;
use chat\data\room\RoomAction;
use chat\data\suspension\Suspension;
use chat\data\user\User as ChatUser;
use chat\system\permission\PermissionHandler;
use wcf\data\user\UserProfile;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\exception\UserInputException;
use wcf\system\WCF;
use \chat\data\room\Room;
use \chat\data\suspension\Suspension;
use \chat\data\suspension\SuspensionAction;
use \chat\system\permission\PermissionHandler;
use \wcf\data\object\type\ObjectTypeCache;
use \wcf\data\user\UserProfile;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\WCF;
/**
* The ban command creates a new be.bastelstu.chat.suspension.ban suspension.
*/
final class BanCommand extends AbstractSuspensionCommand implements ICommand
{
class BanCommand extends AbstractSuspensionCommand implements ICommand {
/**
* @inheritDoc
*/
public function getJavaScriptModuleName()
{
public function getJavaScriptModuleName() {
return 'Bastelstu.be/Chat/Command/Ban';
}
/**
* @inheritDoc
*/
public function isAvailable(Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function isAvailable(Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(WCF::getUser());
return $user->getPermission('mod.chat.canBan') || PermissionHandler::get($user)->getPermission($room, 'mod.canBan');
}
/**
* @inheritDoc
*/
public function getObjectTypeName()
{
public function getObjectTypeName() {
return 'be.bastelstu.chat.suspension.ban';
}
/**
* @inheritDoc
*/
protected function checkPermissions($parameters, Room $room, UserProfile $user)
{
protected function checkPermissions($parameters, Room $room, UserProfile $user) {
$permission = $user->getPermission('mod.chat.canBan');
if (!$this->isGlobally($parameters)) {
$permission = $permission || PermissionHandler::get($user)->getPermission($room, 'mod.canBan');
}
if (!$permission) {
throw new PermissionDeniedException();
}
if (!$permission) throw new PermissionDeniedException();
}
/**
* @inheritDoc
*/
protected function afterCreate(Suspension $suspension, $parameters, Room $room, UserProfile $user)
{
protected function afterCreate(Suspension $suspension, $parameters, Room $room, UserProfile $user) {
parent::afterCreate($suspension, $parameters, $room, $user);
$user = new ChatUser($suspension->getUser());
$user = new \chat\data\user\User($suspension->getUser());
$rooms = [ ];
if ($suspension->getRoom() === null) {
$rooms = $user->getRooms();
} else {
}
else {
if ($user->isInRoom($suspension->getRoom())) {
$rooms = [
$suspension->getRoom(),
];
$rooms = [ $suspension->getRoom() ];
}
}
foreach ($rooms as $room) {
$parameters = [
'user' => $suspension->getUser(),
'roomID' => $room->roomID,
$parameters = [ 'user' => $suspension->getUser()
, 'roomID' => $room->roomID
];
try {
(new RoomAction(
[ ],
'leave',
$parameters
))->executeAction();
} catch (UserInputException $e) {
(new \chat\data\room\RoomAction([ ], 'leave', $parameters))->executeAction();
}
catch (UserInputException $e) {
// User already left
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,51 +14,39 @@
namespace chat\system\command;
use chat\data\message\MessageAction;
use chat\data\message\MessageEditor;
use chat\data\room\Room;
use wcf\data\user\UserProfile;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
use wcf\system\WCF;
use \chat\data\message\MessageAction;
use \chat\data\message\MessageEditor;
use \chat\data\room\Room;
use \wcf\data\user\UserProfile;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\WCF;
/**
* BroadcastCommand sends a broadcast into all channels.
*/
final class BroadcastCommand extends AbstractInputProcessedCommand implements ICommand
{
class BroadcastCommand extends AbstractInputProcessedCommand implements ICommand {
/**
* @inheritDoc
*/
public function getJavaScriptModuleName()
{
public function getJavaScriptModuleName() {
return 'Bastelstu.be/Chat/Command/Broadcast';
}
/**
* @inheritDoc
*/
public function isAvailable(Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function isAvailable(Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(WCF::getUser());
return $user->getPermission('mod.chat.canBroadcast');
}
/**
* @inheritDoc
*/
public function validate($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function validate($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
if (!$user->getPermission('mod.chat.canBroadcast')) {
throw new PermissionDeniedException();
}
if (!$user->getPermission('mod.chat.canBroadcast')) throw new PermissionDeniedException();
$this->setText($this->assertParameter($parameters, 'text'));
$this->validateText();
@ -68,39 +55,29 @@ public function validate($parameters, Room $room, ?UserProfile $user = null)
/**
* @inheritDoc
*/
public function execute($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function execute($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
$objectTypeID = $this->getMessageObjectTypeID('be.bastelstu.chat.messageType.broadcast');
$this->setText($this->assertParameter($parameters, 'text'));
WCF::getDB()->beginTransaction();
$message = (new MessageAction(
[ ],
'create',
[
'data' => [
'roomID' => $room->roomID,
'userID' => $user->userID,
'username' => $user->username,
'time' => TIME_NOW,
'objectTypeID' => $objectTypeID,
'payload' => \serialize([
'message' => $this->processor->getHtml(),
]),
],
'updateTimestamp' => true,
$message = (new MessageAction([ ], 'create', [ 'data' => [ 'roomID' => $room->roomID
, 'userID' => $user->userID
, 'username' => $user->username
, 'time' => TIME_NOW
, 'objectTypeID' => $objectTypeID
, 'payload' => serialize([ 'message' => $this->processor->getHtml() ])
]
, 'updateTimestamp' => true
]
)
)->executeAction()['returnValues'];
$this->processor->setObjectID($message->messageID);
if (MessageEmbeddedObjectManager::getInstance()->registerObjects($this->processor)) {
if (\wcf\system\message\embedded\object\MessageEmbeddedObjectManager::getInstance()->registerObjects($this->processor)) {
(new MessageEditor($message))->update([
'hasEmbeddedObjects' => 1,
'hasEmbeddedObjects' => 1
]);
}
WCF::getDB()->commitTransaction();

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,40 +14,34 @@
namespace chat\system\command;
use chat\data\message\MessageAction;
use chat\data\room\Room;
use wcf\data\DatabaseObject;
use wcf\data\user\UserEditor;
use wcf\data\user\UserProfile;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\exception\UserInputException;
use wcf\system\Regex;
use wcf\system\WCF;
use wcf\util\StringUtil;
use \chat\data\message\MessageAction;
use \chat\data\room\Room;
use \wcf\data\user\UserProfile;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\exception\UserInputException;
use \wcf\system\WCF;
use \wcf\util\StringUtil;
/**
* The color command allows a user to set a color for their username
*/
final class ColorCommand extends AbstractCommand implements ICommand
{
class ColorCommand extends AbstractCommand implements ICommand {
/**
* Regular expression matching RGB values in hexadecimal notation
* @var \wcf\system\Regex
*/
protected $colorRegex;
protected $colorRegex = null;
public function __construct(DatabaseObject $object)
{
public function __construct(\wcf\data\DatabaseObject $object) {
parent::__construct($object);
$this->colorRegex = new Regex('^#?([a-f0-9]{6})$', Regex::CASE_INSENSITIVE);
$this->colorRegex = new \wcf\system\Regex('^#?([a-f0-9]{6})$', \wcf\system\Regex::CASE_INSENSITIVE);
}
/**
* @inheritDoc
*/
public function getJavaScriptModuleName()
{
public function getJavaScriptModuleName() {
return 'Bastelstu.be/Chat/Command/Color';
}
@ -208,21 +201,16 @@ public function getJavaScriptModuleName()
'white' => 0xFFFFFF,
'whitesmoke' => 0xF5F5F5,
'yellow' => 0xFFFF00,
'yellowgreen' => 0x9ACD32,
'yellowgreen' => 0x9ACD32
];
/**
* @inheritDoc
*/
public function validate($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function validate($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(WCF::getUser());
if (!$user->getPermission('user.chat.canSetColor')) {
throw new PermissionDeniedException();
}
if (!$user->getPermission('user.chat.canSetColor')) throw new PermissionDeniedException();
foreach ($parameters as $parameter) {
$value = StringUtil::trim($this->assertParameter($parameter, 'value'));
@ -231,28 +219,12 @@ public function validate($parameters, Room $room, ?UserProfile $user = null)
switch ($this->assertParameter($parameter, 'type')) {
case 'hex':
if (!$this->colorRegex->match($value)) {
throw new UserInputException(
'message',
WCF::getLanguage()->getDynamicVariable(
'chat.error.invalidColor',
[
'color' => $value,
]
)
);
throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('chat.error.invalidColor', [ 'color' => $value ]));
}
break;
case 'word':
if (!isset(self::$colors[$value])) {
throw new UserInputException(
'message',
WCF::getLanguage()->getDynamicVariable(
'chat.error.invalidColor',
[
'color' => $value,
]
)
);
throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('chat.error.invalidColor', [ 'color' => $value ]));
}
break;
@ -265,30 +237,23 @@ public function validate($parameters, Room $room, ?UserProfile $user = null)
/**
* @inheritDoc
*/
public function execute($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function execute($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(WCF::getUser());
$objectTypeID = $this->getMessageObjectTypeID('be.bastelstu.chat.messageType.color');
$colors = [ ];
if (!isset($parameters[1])) {
$parameters[1] = $parameters[0];
}
if (!isset($parameters[1])) $parameters[1] = $parameters[0];
foreach ($parameters as $key => $parameter) {
$value = StringUtil::trim($this->assertParameter($parameter, 'value'));
switch ($this->assertParameter($parameter, 'type')) {
case 'hex':
$colors[$key] = \hexdec($value);
$colors[$key] = hexdec($value);
break;
case 'word':
if (!isset(self::$colors[$value])) {
throw new UserInputException('message');
}
if (!isset(self::$colors[$value])) throw new UserInputException('message');
$colors[$key] = self::$colors[$value];
break;
default:
@ -297,30 +262,24 @@ public function execute($parameters, Room $room, ?UserProfile $user = null)
}
WCF::getDB()->beginTransaction();
$editor = new UserEditor($user->getDecoratedObject());
$editor->update([
'chatColor1' => $colors[0],
'chatColor2' => $colors[1],
$editor = new \wcf\data\user\UserEditor($user->getDecoratedObject());
$editor->update([ 'chatColor1' => $colors[0]
, 'chatColor2' => $colors[1]
]);
(new MessageAction(
[ ],
'create',
[
'data' => [
'roomID' => $room->roomID,
'userID' => $user->userID,
'username' => $user->username,
'time' => TIME_NOW,
'objectTypeID' => $objectTypeID,
'payload' => \serialize([
'color1' => $colors[0],
'color2' => $colors[1],
]),
],
'updateTimestamp' => true,
(new MessageAction([ ], 'create', [ 'data' => [ 'roomID' => $room->roomID
, 'userID' => $user->userID
, 'username' => $user->username
, 'time' => TIME_NOW
, 'objectTypeID' => $objectTypeID
, 'payload' => serialize([ 'color1' => $colors[0]
, 'color2' => $colors[1]
])
]
))->executeAction();
, 'updateTimestamp' => true
]
)
)->executeAction();
WCF::getDB()->commitTransaction();
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,14 +14,13 @@
namespace chat\system\command;
use chat\data\room\Room;
use wcf\data\user\UserProfile;
use \chat\data\room\Room;
use \wcf\data\user\UserProfile;
/**
* Interface for Command processors.
*/
interface ICommand
{
interface ICommand {
/**
* Returns whether the command can be used even when
* no trigger is configured for it.
@ -50,7 +48,7 @@ public function getJavaScriptModuleName();
* @param UserProfile $user
* @return boolean
*/
public function isAvailable(Room $room, ?UserProfile $user = null);
public function isAvailable(Room $room, UserProfile $user = null);
/**
* Validates the execution of the command with the given parameters
@ -62,7 +60,7 @@ public function isAvailable(Room $room, ?UserProfile $user = null);
* @param Room $room
* @param UserProfile $user
*/
public function validate($parameters, Room $room, ?UserProfile $user = null);
public function validate($parameters, Room $room, UserProfile $user = null);
/**
* Executes the command with the given parameters in the given room in
@ -74,5 +72,5 @@ public function validate($parameters, Room $room, ?UserProfile $user = null);
* @param Room $room
* @param UserProfile $user
*/
public function execute($parameters, Room $room, ?UserProfile $user = null);
public function execute($parameters, Room $room, UserProfile $user = null);
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,38 +14,30 @@
namespace chat\system\command;
use chat\data\message\MessageAction;
use chat\data\room\Room;
use chat\data\room\RoomCache;
use chat\data\user\User as ChatUser;
use wcf\data\user\User;
use wcf\data\user\UserProfile;
use wcf\system\event\EventHandler;
use wcf\system\WCF;
use \chat\data\message\MessageAction;
use \chat\data\room\Room;
use \chat\data\room\RoomCache;
use \wcf\data\user\User;
use \wcf\data\user\UserProfile;
/**
* The info command shows information about a single user.
*/
final class InfoCommand extends AbstractCommand implements ICommand
{
class InfoCommand extends AbstractCommand implements ICommand {
use TNeedsUser;
/**
* @inheritDoc
*/
public function getJavaScriptModuleName()
{
public function getJavaScriptModuleName() {
return 'Bastelstu.be/Chat/Command/Info';
}
/**
* @inheritDoc
*/
public function validate($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function validate($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
$this->assertUser($this->assertParameter($parameters, 'username'));
}
@ -54,52 +45,44 @@ public function validate($parameters, Room $room, ?UserProfile $user = null)
/**
* @inheritDoc
*/
public function execute($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function execute($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
$objectTypeID = $this->getMessageObjectTypeID('be.bastelstu.chat.messageType.info');
$target = new ChatUser($this->getUser($this->assertParameter($parameters, 'username')));
$rooms = \array_values(\array_map(static function ($assoc) {
$target = new \chat\data\user\User($this->getUser($this->assertParameter($parameters, 'username')));
$rooms = array_values(array_map(function ($assoc) {
$room = RoomCache::getInstance()->getRoom($assoc['roomID']);
return [
'title' => (string)$room,
'roomID' => $assoc['roomID'],
'lastPush' => $assoc['lastPush'],
'lastPull' => $assoc['lastPull'],
'active' => $assoc['active'],
'link' => $room->getLink(),
return [ 'title' => (string) $room
, 'roomID' => $assoc['roomID']
, 'lastPush' => $assoc['lastPush']
, 'lastPull' => $assoc['lastPull']
, 'active' => $assoc['active']
, 'link' => $room->getLink()
];
}, \array_filter($target->getRoomAssociations(), static function ($assoc) {
}, array_filter($target->getRoomAssociations(), function ($assoc) {
return RoomCache::getInstance()->getRoom($assoc['roomID'])->canSee();
})));
$payload = [
'data' => [
'rooms' => $rooms,
'away' => $target->chatAway,
'user' => $target,
], 'caller' => $user,
$payload = [ 'data' => [ 'rooms' => $rooms
, 'away' => $target->chatAway
, 'user' => $target
]
, 'caller' => $user
];
EventHandler::getInstance()->fireAction($this, 'execute', $payload);
\wcf\system\event\EventHandler::getInstance()->fireAction($this, 'execute', $payload);
(new MessageAction(
[ ],
'create',
[
'data' => [
'roomID' => $room->roomID,
'userID' => $user->userID,
'username' => $user->username,
'time' => TIME_NOW,
'objectTypeID' => $objectTypeID,
'payload' => \serialize($payload['data']),
], 'updateTimestamp' => true,
(new MessageAction([ ], 'create', [ 'data' => [ 'roomID' => $room->roomID
, 'userID' => $user->userID
, 'username' => $user->username
, 'time' => TIME_NOW
, 'objectTypeID' => $objectTypeID
, 'payload' => serialize($payload['data'])
]
))->executeAction();
, 'updateTimestamp' => true
]
)
)->executeAction();
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,75 +14,49 @@
namespace chat\system\command;
use chat\data\message\MessageAction;
use chat\data\room\Room;
use wcf\data\user\UserProfile;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\exception\UserInputException;
use wcf\system\message\censorship\Censorship;
use wcf\system\WCF;
use \chat\data\message\MessageAction;
use \chat\data\room\Room;
use \wcf\data\user\UserProfile;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\exception\UserInputException;
use \wcf\system\message\censorship\Censorship;
use \wcf\system\WCF;
/**
* MeCommand represents an action message.
*/
final class MeCommand extends AbstractCommand implements ICommand
{
class MeCommand extends AbstractCommand implements ICommand {
/**
* @inheritDoc
*/
public function getJavaScriptModuleName()
{
public function getJavaScriptModuleName() {
return 'Bastelstu.be/Chat/Command/Me';
}
/**
* @inheritDoc
*/
public function validate($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function validate($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
if (!$room->canWritePublicly($user)) {
throw new PermissionDeniedException();
}
if (!$room->canWritePublicly($user)) throw new PermissionDeniedException();
$text = $this->assertParameter($parameters, 'text');
if (\mb_strlen($text) === 0) {
throw new UserInputException(
'message',
WCF::getLanguage()->getDynamicVariable('wcf.global.form.error.empty')
);
if (mb_strlen($text) === 0) {
throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('wcf.global.form.error.empty'));
}
// validate message length
if (\mb_strlen($text) > CHAT_MAX_LENGTH) {
throw new UserInputException(
'message',
WCF::getLanguage()->getDynamicVariable(
'wcf.message.error.tooLong',
[
'maxTextLength' => CHAT_MAX_LENGTH,
]
)
);
if (mb_strlen($text) > CHAT_MAX_LENGTH) {
throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('wcf.message.error.tooLong', [ 'maxTextLength' => CHAT_MAX_LENGTH ]));
}
// search for censored words
if (ENABLE_CENSORSHIP) {
$result = Censorship::getInstance()->test($text);
if ($result) {
throw new UserInputException(
'message',
WCF::getLanguage()->getDynamicVariable(
'wcf.message.error.censoredWordsFound',
[
'censoredWords' => $result,
]
)
);
throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('wcf.message.error.censoredWordsFound', [ 'censoredWords' => $result ]));
}
}
}
@ -91,30 +64,21 @@ public function validate($parameters, Room $room, ?UserProfile $user = null)
/**
* @inheritDoc
*/
public function execute($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function execute($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
$objectTypeID = $this->getMessageObjectTypeID('be.bastelstu.chat.messageType.me');
(new MessageAction(
[ ],
'create',
[
'data' => [
'roomID' => $room->roomID,
'userID' => $user->userID,
'username' => $user->username,
'time' => TIME_NOW,
'objectTypeID' => $objectTypeID,
'payload' => \serialize([
'message' => $this->assertParameter($parameters, 'text'),
]),
],
'updateTimestamp' => true,
'grantPoints' => true,
(new MessageAction([ ], 'create', [ 'data' => [ 'roomID' => $room->roomID
, 'userID' => $user->userID
, 'username' => $user->username
, 'time' => TIME_NOW
, 'objectTypeID' => $objectTypeID
, 'payload' => serialize([ 'message' => $this->assertParameter($parameters, 'text') ])
]
))->executeAction();
, 'updateTimestamp' => true
, 'grantPoints' => true
]
)
)->executeAction();
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 3
@ -15,58 +14,50 @@
namespace chat\system\command;
use chat\data\room\Room;
use chat\system\permission\PermissionHandler;
use wcf\data\user\UserProfile;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\WCF;
use \chat\data\room\Room;
use \chat\data\suspension\SuspensionAction;
use \chat\system\permission\PermissionHandler;
use \wcf\data\object\type\ObjectTypeCache;
use \wcf\data\user\UserProfile;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\WCF;
/**
* The mute command creates a new be.bastelstu.chat.suspension.mute suspension.
*/
final class MuteCommand extends AbstractSuspensionCommand implements ICommand
{
class MuteCommand extends AbstractSuspensionCommand implements ICommand {
/**
* @inheritDoc
*/
public function getJavaScriptModuleName()
{
public function getJavaScriptModuleName() {
return 'Bastelstu.be/Chat/Command/Mute';
}
/**
* @inheritDoc
*/
public function isAvailable(Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function isAvailable(Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(WCF::getUser());
return $user->getPermission('mod.chat.canMute') || PermissionHandler::get($user)->getPermission($room, 'mod.canMute');
}
/**
* @inheritDoc
*/
public function getObjectTypeName()
{
public function getObjectTypeName() {
return 'be.bastelstu.chat.suspension.mute';
}
/**
* @inheritDoc
*/
protected function checkPermissions($parameters, Room $room, UserProfile $user)
{
protected function checkPermissions($parameters, Room $room, UserProfile $user) {
$permission = $user->getPermission('mod.chat.canMute');
if (!$this->isGlobally($parameters)) {
$permission = $permission || PermissionHandler::get($user)->getPermission($room, 'mod.canMute');
}
if (!$permission) {
throw new PermissionDeniedException();
}
if (!$permission) throw new PermissionDeniedException();
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,47 +14,38 @@
namespace chat\system\command;
use chat\data\message\MessageAction;
use chat\data\message\MessageEditor;
use chat\data\room\Room;
use wcf\data\user\UserProfile;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
use wcf\system\WCF;
use \chat\data\message\MessageAction;
use \chat\data\message\MessageEditor;
use \chat\data\room\Room;
use \wcf\data\user\UserProfile;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\WCF;
/**
* The plain command creates a normal chat message
*/
final class PlainCommand extends AbstractInputProcessedCommand implements ICommand
{
class PlainCommand extends AbstractInputProcessedCommand implements ICommand {
/**
* @inheritDoc
*/
public function allowWithoutTrigger()
{
public function allowWithoutTrigger() {
return true;
}
/**
* @inheritDoc
*/
public function getJavaScriptModuleName()
{
public function getJavaScriptModuleName() {
return 'Bastelstu.be/Chat/Command/Plain';
}
/**
* @inheritDoc
*/
public function validate($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function validate($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
if (!$room->canWritePublicly($user)) {
throw new PermissionDeniedException();
}
if (!$room->canWritePublicly($user)) throw new PermissionDeniedException();
$this->setText($this->assertParameter($parameters, 'text'));
$this->validateText();
@ -64,39 +54,30 @@ public function validate($parameters, Room $room, ?UserProfile $user = null)
/**
* @inheritDoc
*/
public function execute($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function execute($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
$objectTypeID = $this->getMessageObjectTypeID('be.bastelstu.chat.messageType.plain');
$this->setText($this->assertParameter($parameters, 'text'));
WCF::getDB()->beginTransaction();
$message = (new MessageAction(
[ ],
'create',
[
'data' => [
'roomID' => $room->roomID,
'userID' => $user->userID,
'username' => $user->username,
'time' => TIME_NOW,
'objectTypeID' => $objectTypeID,
'payload' => \serialize([
'message' => $this->processor->getHtml(),
]),
],
'updateTimestamp' => true,
'grantPoints' => true,
$message = (new MessageAction([ ], 'create', [ 'data' => [ 'roomID' => $room->roomID
, 'userID' => $user->userID
, 'username' => $user->username
, 'time' => TIME_NOW
, 'objectTypeID' => $objectTypeID
, 'payload' => serialize([ 'message' => $this->processor->getHtml() ])
]
))->executeAction()['returnValues'];
, 'updateTimestamp' => true
, 'grantPoints' => true
]
)
)->executeAction()['returnValues'];
$this->processor->setObjectID($message->messageID);
if (MessageEmbeddedObjectManager::getInstance()->registerObjects($this->processor)) {
if (\wcf\system\message\embedded\object\MessageEmbeddedObjectManager::getInstance()->registerObjects($this->processor)) {
(new MessageEditor($message))->update([
'hasEmbeddedObjects' => 1,
'hasEmbeddedObjects' => 1
]);
}
WCF::getDB()->commitTransaction();

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,20 +14,21 @@
namespace chat\system\command;
use wcf\data\user\User;
use wcf\system\exception\UserInputException;
use wcf\system\WCF;
use \wcf\data\user\User;
use \wcf\system\exception\UserInputException;
use \wcf\system\WCF;
/**
* Adds helpful functions for commands that operate on a user.
*/
trait TNeedsUser
{
trait TNeedsUser {
/**
* Returns the user with the given username.
*
* @param string $username
* @return \wcf\data\user\User
*/
protected function getUser(string $username): User
{
protected function getUser($username) {
static $cache = [ ];
if (!isset($cache[$username])) {
$cache[$username] = User::getUserByUsername($username);
@ -39,22 +39,14 @@ protected function getUser(string $username): User
/**
* Checks whether the given username is valid and throws otherwise.
*
* @param string $username
* @return \wcf\data\user\User
*/
protected function assertUser(string $username): User
{
protected function assertUser($username) {
$user = $this->getUser($username);
if (!$user->userID) {
throw new UserInputException(
'message',
WCF::getLanguage()->getDynamicVariable(
'chat.error.userNotFound',
[
'username' => $username,
]
)
);
}
if (!$user->userID) throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('chat.error.userNotFound', [ 'username' => $username ]));
return $user;
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,51 +14,40 @@
namespace chat\system\command;
use chat\data\message\MessageAction;
use chat\data\message\MessageEditor;
use chat\data\room\Room;
use wcf\data\user\UserProfile;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
use wcf\system\WCF;
use \chat\data\message\MessageAction;
use \chat\data\message\MessageEditor;
use \chat\data\room\Room;
use \wcf\data\user\UserProfile;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\exception\UserInputException;
use \wcf\system\WCF;
/**
* TeamCommand sends a broadcast to all team members.
*/
final class TeamCommand extends AbstractInputProcessedCommand implements ICommand
{
class TeamCommand extends AbstractInputProcessedCommand implements ICommand {
/**
* @inheritDoc
*/
public function getJavaScriptModuleName()
{
public function getJavaScriptModuleName() {
return 'Bastelstu.be/Chat/Command/Team';
}
/**
* @inheritDoc
*/
public function isAvailable(Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function isAvailable(Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(WCF::getUser());
return $user->getPermission('mod.chat.canTeam');
}
/**
* @inheritDoc
*/
public function validate($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function validate($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
if (!$user->getPermission('mod.chat.canTeam')) {
throw new PermissionDeniedException();
}
if (!$user->getPermission('mod.chat.canTeam')) throw new PermissionDeniedException();
$this->setText($this->assertParameter($parameters, 'text'));
$this->validateText();
@ -68,37 +56,29 @@ public function validate($parameters, Room $room, ?UserProfile $user = null)
/**
* @inheritDoc
*/
public function execute($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function execute($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
$objectTypeID = $this->getMessageObjectTypeID('be.bastelstu.chat.messageType.team');
$this->setText($this->assertParameter($parameters, 'text'));
WCF::getDB()->beginTransaction();
$message = (new MessageAction(
[ ],
'create',
[
'data' => [
'roomID' => $room->roomID,
'userID' => $user->userID,
'username' => $user->username,
'time' => TIME_NOW,
'objectTypeID' => $objectTypeID,
'payload' => \serialize([
'message' => $this->processor->getHtml(),
]),
], 'updateTimestamp' => true,
$message = (new MessageAction([ ], 'create', [ 'data' => [ 'roomID' => $room->roomID
, 'userID' => $user->userID
, 'username' => $user->username
, 'time' => TIME_NOW
, 'objectTypeID' => $objectTypeID
, 'payload' => serialize([ 'message' => $this->processor->getHtml() ])
]
))->executeAction()['returnValues'];
, 'updateTimestamp' => true
]
)
)->executeAction()['returnValues'];
$this->processor->setObjectID($message->messageID);
if (MessageEmbeddedObjectManager::getInstance()->registerObjects($this->processor)) {
if (\wcf\system\message\embedded\object\MessageEmbeddedObjectManager::getInstance()->registerObjects($this->processor)) {
(new MessageEditor($message))->update([
'hasEmbeddedObjects' => 1,
'hasEmbeddedObjects' => 1
]);
}
WCF::getDB()->commitTransaction();

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,80 +14,46 @@
namespace chat\system\command;
use chat\data\message\MessageAction;
use chat\data\room\Room;
use chat\data\room\RoomAction;
use wcf\data\user\UserProfile;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\exception\UserInputException;
use wcf\system\WCF;
use \chat\data\message\MessageAction;
use \chat\data\room\Room;
use \wcf\data\user\UserProfile;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\exception\UserInputException;
use \wcf\system\WCF;
/**
* The temproom command allows a user to manage temporary rooms.
*/
final class TemproomCommand extends AbstractCommand implements ICommand
{
class TemproomCommand extends AbstractCommand implements ICommand {
use TNeedsUser;
/**
* @inheritDoc
*/
public function getJavaScriptModuleName()
{
public function getJavaScriptModuleName() {
return 'Bastelstu.be/Chat/Command/Temproom';
}
/**
* @inheritDoc
*/
public function validate($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function validate($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(WCF::getUser());
switch ($this->assertParameter($parameters, 'type')) {
case 'create':
if (!$user->getPermission('user.chat.canTemproom')) {
throw new PermissionDeniedException();
}
if (!$user->getPermission('user.chat.canTemproom')) throw new PermissionDeniedException();
break;
case 'invite':
if (!$room->isTemporary) {
throw new UserInputException(
'message',
WCF::getLanguage()->getDynamicVariable('chat.error.notInTemproom')
);
}
if ($room->ownerID !== $user->userID) {
throw new PermissionDeniedException();
}
if (!$room->isTemporary) throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('chat.error.notInTemproom'));
if ($room->ownerID !== $user->userID) throw new PermissionDeniedException();
$recipient = new UserProfile($this->assertUser($this->assertParameter($parameters, 'username')));
if ($recipient->isIgnoredUser($user->userID)) {
throw new UserInputException(
'message',
WCF::getLanguage()->getDynamicVariable(
'chat.error.userIgnoresYou',
[
'user' => $recipient,
]
)
);
}
if ($recipient->isIgnoredUser($user->userID)) throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('chat.error.userIgnoresYou', [ 'user' => $recipient ]));
break;
case 'delete':
if (!$room->isTemporary) {
throw new UserInputException(
'message',
WCF::getLanguage()->getDynamicVariable(
'chat.error.notInTemproom'
)
);
}
if ($room->ownerID !== $user->userID) {
throw new PermissionDeniedException();
}
if (!$room->isTemporary) throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('chat.error.notInTemproom'));
if ($room->ownerID !== $user->userID) throw new PermissionDeniedException();
break;
default:
throw new UserInputException('message');
@ -98,101 +63,71 @@ public function validate($parameters, Room $room, ?UserProfile $user = null)
/**
* @inheritDoc
*/
public function execute($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function execute($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(WCF::getUser());
switch ($this->assertParameter($parameters, 'type')) {
case 'create':
$fields = [
'title' => WCF::getLanguage()->getDynamicVariable(
'chat.room.temporary.blueprint',
[
'user' => $user,
]
),
'topic' => '',
'position' => 999,
'isTemporary' => true,
'ownerID' => $user->userID,
$fields = [ 'title' => WCF::getLanguage()->getDynamicVariable('chat.room.temporary.blueprint', [ 'user' => $user ])
, 'topic' => ''
, 'position' => 999
, 'isTemporary' => true
, 'ownerID' => $user->userID
];
WCF::getDB()->beginTransaction();
// create room
$tempRoom = (new RoomAction([], 'create', [
'data' => $fields,
]))->executeAction()['returnValues'];
$tempRoom = (new \chat\data\room\RoomAction([], 'create', [ 'data' => $fields ]))->executeAction()['returnValues'];
$objectTypeID = $this->getMessageObjectTypeID('be.bastelstu.chat.messageType.temproomCreated');
(new MessageAction(
[ ],
'create',
[
'data' => [
'roomID' => $room->roomID,
'userID' => $user->userID,
'username' => $user->username,
'time' => TIME_NOW,
'objectTypeID' => $objectTypeID,
'payload' => \serialize([
'room' => $tempRoom,
]),
], 'updateTimestamp' => true,
(new MessageAction([ ], 'create', [ 'data' => [ 'roomID' => $room->roomID
, 'userID' => $user->userID
, 'username' => $user->username
, 'time' => TIME_NOW
, 'objectTypeID' => $objectTypeID
, 'payload' => serialize([ 'room' => $tempRoom ])
]
))->executeAction();
, 'updateTimestamp' => true
]
)
)->executeAction();
WCF::getDB()->commitTransaction();
return;
case 'invite':
$recipient = $this->getUser($this->assertParameter($parameters, 'username'));
WCF::getDB()->beginTransaction();
try {
$sql = "INSERT INTO chat1_room_temporary_invite
$sql = "INSERT INTO chat".WCF_N."_room_temporary_invite
(userID, roomID)
VALUES (?, ?)";
$statement = WCF::getDB()->prepare($sql);
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute([ $recipient->userID, $room->roomID ]);
} catch (\wcf\system\database\DatabaseException $e) {
}
catch (\wcf\system\database\DatabaseException $e) {
WCF::getDB()->rollBackTransaction();
// Duplicate key errors don't cause harm.
if ((string)$e->getCode() !== '23000') {
throw $e;
}
if ((string) $e->getCode() !== '23000') throw $e;
return;
}
$objectTypeID = $this->getMessageObjectTypeID('be.bastelstu.chat.messageType.temproomInvited');
(new MessageAction(
[ ],
'create',
[
'data' => [
'roomID' => $room->roomID,
'userID' => $user->userID,
'username' => $user->username,
'time' => TIME_NOW,
'objectTypeID' => $objectTypeID,
'payload' => \serialize([
'recipient' => $recipient->userID,
'recipientName' => $recipient->username,
]),
],
'updateTimestamp' => true,
(new MessageAction([ ], 'create', [ 'data' => [ 'roomID' => $room->roomID
, 'userID' => $user->userID
, 'username' => $user->username
, 'time' => TIME_NOW
, 'objectTypeID' => $objectTypeID
, 'payload' => serialize([ 'recipient' => $recipient->userID
, 'recipientName' => $recipient->username
])
]
))->executeAction();
, 'updateTimestamp' => true
]
)
)->executeAction();
WCF::getDB()->commitTransaction();
return;
case 'delete':
(new RoomAction(
[
$room,
],
'delete'
))->executeAction();
(new \chat\data\room\RoomAction([ $room ], 'delete'))->executeAction();
return;
default:
throw new UserInputException('message');

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 3
@ -15,59 +14,51 @@
namespace chat\system\command;
use chat\data\room\Room;
use chat\data\suspension\Suspension;
use chat\system\permission\PermissionHandler;
use wcf\data\user\UserProfile;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\WCF;
use \chat\data\room\Room;
use \chat\data\suspension\Suspension;
use \chat\data\suspension\SuspensionAction;
use \chat\system\permission\PermissionHandler;
use \wcf\data\object\type\ObjectTypeCache;
use \wcf\data\user\UserProfile;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\WCF;
/**
* The unban command revokes a new be.bastelstu.chat.suspension.ban suspension.
*/
final class UnbanCommand extends AbstractUnsuspensionCommand implements ICommand
{
class UnbanCommand extends AbstractUnsuspensionCommand implements ICommand {
/**
* @inheritDoc
*/
public function getJavaScriptModuleName()
{
public function getJavaScriptModuleName() {
return 'Bastelstu.be/Chat/Command/Unban';
}
/**
* @inheritDoc
*/
public function isAvailable(Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function isAvailable(Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(WCF::getUser());
return $user->getPermission('mod.chat.canBan') || PermissionHandler::get($user)->getPermission($room, 'mod.canBan');
}
/**
* @inheritDoc
*/
public function getObjectTypeName()
{
public function getObjectTypeName() {
return 'be.bastelstu.chat.suspension.ban';
}
/**
* @inheritDoc
*/
protected function checkPermissions($parameters, Room $room, UserProfile $user)
{
protected function checkPermissions($parameters, Room $room, UserProfile $user) {
$permission = $user->getPermission('mod.chat.canBan');
if (!$this->isGlobally($parameters)) {
$permission = $permission || PermissionHandler::get($user)->getPermission($room, 'mod.canBan');
}
if (!$permission) {
throw new PermissionDeniedException();
}
if (!$permission) throw new PermissionDeniedException();
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 3
@ -15,58 +14,50 @@
namespace chat\system\command;
use chat\data\room\Room;
use chat\system\permission\PermissionHandler;
use wcf\data\user\UserProfile;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\WCF;
use \chat\data\room\Room;
use \chat\data\suspension\SuspensionAction;
use \chat\system\permission\PermissionHandler;
use \wcf\data\object\type\ObjectTypeCache;
use \wcf\data\user\UserProfile;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\WCF;
/**
* The unmute command revokes a new be.bastelstu.chat.suspension.mute suspension.
*/
final class UnmuteCommand extends AbstractUnsuspensionCommand implements ICommand
{
class UnmuteCommand extends AbstractUnsuspensionCommand implements ICommand {
/**
* @inheritDoc
*/
public function getJavaScriptModuleName()
{
public function getJavaScriptModuleName() {
return 'Bastelstu.be/Chat/Command/Unmute';
}
/**
* @inheritDoc
*/
public function isAvailable(Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function isAvailable(Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(WCF::getUser());
return $user->getPermission('mod.chat.canMute') || PermissionHandler::get($user)->getPermission($room, 'mod.canMute');
}
/**
* @inheritDoc
*/
public function getObjectTypeName()
{
public function getObjectTypeName() {
return 'be.bastelstu.chat.suspension.mute';
}
/**
* @inheritDoc
*/
protected function checkPermissions($parameters, Room $room, UserProfile $user)
{
protected function checkPermissions($parameters, Room $room, UserProfile $user) {
$permission = $user->getPermission('mod.chat.canMute');
if (!$this->isGlobally($parameters)) {
$permission = $permission || PermissionHandler::get($user)->getPermission($room, 'mod.canMute');
}
if (!$permission) {
throw new PermissionDeniedException();
}
if (!$permission) throw new PermissionDeniedException();
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,75 +14,61 @@
namespace chat\system\command;
use chat\data\message\MessageAction;
use chat\data\room\Room;
use chat\data\room\RoomList;
use chat\data\user\User as ChatUser;
use wcf\data\user\UserProfile;
use wcf\system\WCF;
use \chat\data\message\MessageAction;
use \chat\data\room\Room;
use \wcf\data\user\User;
use \wcf\data\user\UserProfile;
/**
* The where command shows the distribution of users among
* the different chat rooms.
*/
final class WhereCommand extends AbstractCommand implements ICommand
{
class WhereCommand extends AbstractCommand implements ICommand {
/**
* @inheritDoc
*/
public function getJavaScriptModuleName()
{
public function getJavaScriptModuleName() {
return 'Bastelstu.be/Chat/Command/Where';
}
/**
* @inheritDoc
*/
public function validate($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function validate($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
}
/**
* @inheritDoc
*/
public function execute($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function execute($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
$objectTypeID = $this->getMessageObjectTypeID('be.bastelstu.chat.messageType.where');
$roomList = new RoomList();
$roomList = new \chat\data\room\RoomList();
$roomList->readObjects();
$rooms = \array_map(static function (Room $room) {
$users = \array_map(static function (ChatUser $user) {
$rooms = array_map(function (Room $room) {
$users = array_map(function (\chat\data\user\User $user) {
return $user->jsonSerialize();
}, $room->getUsers());
return [
'roomID' => $room->roomID,
'users' => \array_values($users),
return [ 'roomID' => $room->roomID
, 'users' => array_values($users)
];
}, \array_filter($roomList->getObjects(), static function (Room $room) {
}, array_filter($roomList->getObjects(), function (Room $room) {
return $room->canSee();
}));
(new MessageAction(
[ ],
'create',
[
'data' => [
'roomID' => $room->roomID,
'userID' => $user->userID,
'username' => $user->username,
'time' => TIME_NOW,
'objectTypeID' => $objectTypeID,
'payload' => \serialize($rooms),
], 'updateTimestamp' => true,
(new MessageAction([ ], 'create', [ 'data' => [ 'roomID' => $room->roomID
, 'userID' => $user->userID
, 'username' => $user->username
, 'time' => TIME_NOW
, 'objectTypeID' => $objectTypeID
, 'payload' => serialize($rooms)
]
))->executeAction();
, 'updateTimestamp' => true
]
)
)->executeAction();
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,51 +14,35 @@
namespace chat\system\command;
use chat\data\message\MessageAction;
use chat\data\message\MessageEditor;
use chat\data\room\Room;
use wcf\data\user\UserProfile;
use wcf\system\exception\UserInputException;
use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
use wcf\system\WCF;
use \chat\data\message\MessageAction;
use \chat\data\message\MessageEditor;
use \chat\data\room\Room;
use \wcf\data\user\UserProfile;
use \wcf\system\exception\UserInputException;
use \wcf\system\WCF;
/**
* The whisper command creates a private message
* between two chat users.
*/
final class WhisperCommand extends AbstractInputProcessedCommand implements ICommand
{
class WhisperCommand extends AbstractInputProcessedCommand implements ICommand {
use TNeedsUser;
/**
* @inheritDoc
*/
public function getJavaScriptModuleName()
{
public function getJavaScriptModuleName() {
return 'Bastelstu.be/Chat/Command/Whisper';
}
/**
* @inheritDoc
*/
public function validate($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function validate($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
$recipient = new UserProfile($this->assertUser($this->assertParameter($parameters, 'username')));
if ($recipient->isIgnoredUser($user->userID)) {
throw new UserInputException(
'message',
WCF::getLanguage()->getDynamicVariable(
'chat.error.userIgnoresYou',
[
'user' => $recipient,
]
)
);
}
if ($recipient->isIgnoredUser($user->userID)) throw new UserInputException('message', WCF::getLanguage()->getDynamicVariable('chat.error.userIgnoresYou', [ 'user' => $recipient ]));
$this->setText($this->assertParameter($parameters, 'text'));
$this->validateText();
@ -68,41 +51,33 @@ public function validate($parameters, Room $room, ?UserProfile $user = null)
/**
* @inheritDoc
*/
public function execute($parameters, Room $room, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function execute($parameters, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
$objectTypeID = $this->getMessageObjectTypeID('be.bastelstu.chat.messageType.whisper');
$recipient = $this->assertUser($this->assertParameter($parameters, 'username'));
$this->setText($this->assertParameter($parameters, 'text'));
WCF::getDB()->beginTransaction();
$message = (new MessageAction(
[ ],
'create',
[
'data' => [
'roomID' => $room->roomID,
'userID' => $user->userID,
'username' => $user->username,
'time' => TIME_NOW,
'objectTypeID' => $objectTypeID,
'payload' => \serialize([
'message' => $this->processor->getHtml(),
'recipient' => $recipient->userID,
'recipientName' => $recipient->username,
]),
],
'updateTimestamp' => true,
$message = (new MessageAction([ ], 'create', [ 'data' => [ 'roomID' => $room->roomID
, 'userID' => $user->userID
, 'username' => $user->username
, 'time' => TIME_NOW
, 'objectTypeID' => $objectTypeID
, 'payload' => serialize([ 'message' => $this->processor->getHtml()
, 'recipient' => $recipient->userID
, 'recipientName' => $recipient->username
])
]
))->executeAction()['returnValues'];
, 'updateTimestamp' => true
]
)
)->executeAction()['returnValues'];
$this->processor->setObjectID($message->messageID);
if (MessageEmbeddedObjectManager::getInstance()->registerObjects($this->processor)) {
if (\wcf\system\message\embedded\object\MessageEmbeddedObjectManager::getInstance()->registerObjects($this->processor)) {
(new MessageEditor($message))->update([
'hasEmbeddedObjects' => 1,
'hasEmbeddedObjects' => 1
]);
}
WCF::getDB()->commitTransaction();

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,17 +14,15 @@
namespace chat\system\condition\room;
use chat\data\room\RoomList;
use wcf\data\DatabaseObjectList;
use wcf\system\condition\AbstractCheckboxCondition;
use wcf\system\condition\IObjectListCondition;
use wcf\system\exception\ParentClassException;
use \chat\data\room\RoomList;
use \wcf\data\DatabaseObject;
use \wcf\data\DatabaseObjectList;
use \wcf\system\exception\SystemException;
/**
* Condition implementation for rooms to only include non-empty rooms in lists.
*/
final class RoomFilledCondition extends AbstractCheckboxCondition implements IObjectListCondition
{
class RoomFilledCondition extends \wcf\system\condition\AbstractCheckboxCondition implements \wcf\system\condition\IObjectListCondition {
/**
* @inheritDoc
*/
@ -39,21 +36,11 @@ final class RoomFilledCondition extends AbstractCheckboxCondition implements IOb
/**
* @inheritDoc
*/
public function addObjectListCondition(DatabaseObjectList $objectList, array $conditionData)
{
public function addObjectListCondition(DatabaseObjectList $objectList, array $conditionData) {
if (!($objectList instanceof RoomList)) {
throw new ParentClassException(\get_class($objectList), RoomList::class);
throw new \wcf\system\exception\ParentClassException(get_class($objectList), RoomList::class);
}
$objectList->getConditionBuilder()->add(
"
EXISTS (
SELECT 1
FROM chat" . WCF_N . "_room_to_user r2u
WHERE r2u.roomID = room.roomID
AND active = ?
)",
[ 1 ]
);
$objectList->getConditionBuilder()->add("EXISTS (SELECT 1 FROM chat".WCF_N."_room_to_user r2u WHERE r2u.roomID = room.roomID AND active = ?)", [ 1 ]);
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,32 +14,24 @@
namespace chat\system\event\listener;
use chat\data\message\MessageAction;
use chat\data\user\UserAction as ChatUserAction;
use wcf\system\event\listener\IParameterizedEventListener;
use wcf\system\WCF;
use \wcf\system\WCF;
/**
* Vaporizes unneeded data.
*/
final class HourlyCleanUpCronjobExecuteChatCleanUpListener implements IParameterizedEventListener
{
class HourlyCleanUpCronjobExecuteChatCleanUpListener implements \wcf\system\event\listener\IParameterizedEventListener {
/**
* @inheritDoc
* @see \wcf\system\event\listener\IParameterizedEventListener::execute()
*/
public function execute($eventObj, $className, $eventName, array &$parameters)
{
(new MessageAction([ ], 'prune'))->executeAction();
(new ChatUserAction([ ], 'clearDeadSessions'))->executeAction();
public function execute($eventObj, $className, $eventName, array &$parameters) {
(new \chat\data\message\MessageAction([ ], 'prune'))->executeAction();
(new \chat\data\user\UserAction([], 'clearDeadSessions'))->executeAction();
$sql = "UPDATE chat1_room_to_user
$sql = "UPDATE chat".WCF_N."_room_to_user
SET active = ?
WHERE (roomID, userID) NOT IN (
SELECT roomID, userID
FROM chat1_session
)
WHERE (roomID, userID) NOT IN (SELECT roomID, userID FROM chat".WCF_N."_session)
AND active = ?";
$statement = WCF::getDB()->prepare($sql);
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute([ 0, 1 ]);
if ($statement->getAffectedRows()) {
\wcf\functions\exception\logThrowable(new \Exception('Unreachable'));

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,37 +14,29 @@
namespace chat\system\event\listener;
use chat\data\room\RoomAction;
use chat\data\room\RoomList;
use wcf\system\event\listener\IParameterizedEventListener;
use wcf\system\WCF;
use \wcf\system\WCF;
/**
* Removes empty temporary rooms.
*/
final class HourlyCleanUpCronjobExecuteTemproomListener implements IParameterizedEventListener
{
class HourlyCleanUpCronjobExecuteTemproomListener implements \wcf\system\event\listener\IParameterizedEventListener {
/**
* @inheritDoc
* @see \wcf\system\event\listener\IParameterizedEventListener::execute()
*/
public function execute($eventObj, $className, $eventName, array &$parameters)
{
$roomList = new RoomList();
public function execute($eventObj, $className, $eventName, array &$parameters) {
$roomList = new \chat\data\room\RoomList();
$roomList->getConditionBuilder()->add('isTemporary = ?', [ 1 ]);
$roomList->readObjects();
$toDelete = [ ];
WCF::getDB()->beginTransaction();
foreach ($roomList as $room) {
if (\count($room->getUsers()) === 0) {
if (count($room->getUsers()) === 0) {
$toDelete[] = $room;
}
}
if ($toDelete !== []) {
(new RoomAction(
$toDelete,
'delete'
))->executeAction();
if (!empty($toDelete)) {
(new \chat\data\room\RoomAction($toDelete, 'delete'))->executeAction();
}
WCF::getDB()->commitTransaction();
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 3
@ -15,21 +14,18 @@
namespace chat\system\event\listener;
use chat\data\room\RoomCache;
use chat\data\suspension\Suspension;
use chat\data\suspension\SuspensionList;
use wcf\system\event\listener\IParameterizedEventListener;
use \chat\data\suspension\Suspension;
use \wcf\data\object\type\ObjectTypeCache;
use \wcf\system\WCF;
/**
* Fetches information about the users suspensions
*/
final class InfoCommandSuspensionsListener implements IParameterizedEventListener
{
class InfoCommandSuspensionsListener implements \wcf\system\event\listener\IParameterizedEventListener {
/**
* @inheritDoc
* @see \wcf\system\event\listener\IParameterizedEventListener::execute()
*/
public function execute($eventObj, $className, $eventName, array &$parameters)
{
public function execute($eventObj, $className, $eventName, array &$parameters) {
if (!$parameters['caller']->getPermission('admin.chat.canManageSuspensions')) {
return;
}
@ -38,25 +34,24 @@ public function execute($eventObj, $className, $eventName, array &$parameters)
$parameters['data']['suspensions'] = [ ];
$suspensionList = new SuspensionList();
$suspensionList = new \chat\data\suspension\SuspensionList();
$suspensionList->getConditionBuilder()->add('(expires IS NULL OR expires > ?)', [ TIME_NOW ]);
$suspensionList->getConditionBuilder()->add('revoked IS NULL');
$suspensionList->getConditionBuilder()->add('userID = ?', [ $target->userID ]);
$suspensionList->sqlOrderBy = 'expires ASC, time ASC';
$suspensionList->readObjects();
$suspensions = \array_filter($suspensionList->getObjects(), static function (Suspension $suspension) {
$suspensions = array_filter($suspensionList->getObjects(), function (Suspension $suspension) {
return $suspension->isActive();
});
$parameters['data']['suspensions'] = \array_values(\array_map(static function ($suspension) {
$room = RoomCache::getInstance()->getRoom($suspension->roomID);
$parameters['data']['suspensions'] = array_values(array_map(function ($suspension) {
$room = \chat\data\room\RoomCache::getInstance()->getRoom($suspension->roomID);
$suspension = $suspension->jsonSerialize();
if ($room) {
$suspension['room'] = [
'title' => $room->getTitle(),
'link' => $room->getLink(),
$suspension['room'] = [ 'title' => $room->getTitle()
, 'link' => $room->getLink()
];
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 3
@ -15,32 +14,26 @@
namespace chat\system\event\listener;
use chat\data\command\CommandCache;
use wcf\data\package\PackageCache;
use wcf\system\cache\runtime\UserProfileRuntimeCache;
use wcf\system\event\listener\IParameterizedEventListener;
use \chat\data\command\CommandCache;
use \wcf\system\cache\runtime\UserProfileRuntimeCache;
/**
* Adds moderator permissions to the user object.
* Adds moderator permissiosn to the user object.
*/
final class RoomActionGetUsersModeratorListener implements IParameterizedEventListener
{
class RoomActionGetUsersModeratorListener implements \wcf\system\event\listener\IParameterizedEventListener {
/**
* @inheritDoc
* @see \wcf\system\event\listener\IParameterizedEventListener::execute()
*/
public function execute($eventObj, $className, $eventName, array &$users)
{
public function execute($eventObj, $className, $eventName, array &$users) {
$room = $eventObj->getObjects()[0]->getDecoratedObject();
$package = PackageCache::getInstance()->getPackageByIdentifier('be.bastelstu.chat');
$package = \wcf\data\package\PackageCache::getInstance()->getPackageByIdentifier('be.bastelstu.chat');
$muteCommand = CommandCache::getInstance()->getCommandByPackageAndIdentifier($package, 'mute')->getProcessor();
$banCommand = CommandCache::getInstance()->getCommandByPackageAndIdentifier($package, 'ban')->getProcessor();
$users = \array_map(static function (array $user) use ($room, $muteCommand, $banCommand) {
$users = array_map(function (array $user) use ($room, $muteCommand, $banCommand) {
$userProfile = UserProfileRuntimeCache::getInstance()->getObject($user['userID']);
if (!isset($user['permissions'])) {
$user['permissions'] = [];
}
if (!isset($user['permissions'])) $user['permissions'] = [];
$user['permissions']['canMute'] = $muteCommand->isAvailable($room, $userProfile);
$user['permissions']['canBan'] = $banCommand->isAvailable($room, $userProfile);

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 3
@ -15,37 +14,25 @@
namespace chat\system\event\listener;
use chat\data\suspension\Suspension;
use wcf\data\object\type\ObjectTypeCache;
use wcf\system\event\listener\IParameterizedEventListener;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\WCF;
use \chat\data\suspension\Suspension;
use \wcf\data\object\type\ObjectTypeCache;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\WCF;
/**
* Denies access to banned users.
*/
final class RoomCanJoinBanListener implements IParameterizedEventListener
{
class RoomCanJoinBanListener implements \wcf\system\event\listener\IParameterizedEventListener {
/**
* @inheritDoc
* @see \wcf\system\event\listener\IParameterizedEventListener::execute()
*/
public function execute($eventObj, $className, $eventName, array &$parameters)
{
$objectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName(
'be.bastelstu.chat.suspension',
'be.bastelstu.chat.suspension.ban'
);
\assert($objectTypeID !== null);
public function execute($eventObj, $className, $eventName, array &$parameters) {
$objectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName('be.bastelstu.chat.suspension', 'be.bastelstu.chat.suspension.ban');
if (!$objectTypeID) throw new \LogicException('Unreachable');
$suspensions = Suspension::getActiveSuspensionsByTriple(
$objectTypeID,
$parameters['user']->getDecoratedObject(),
$eventObj
);
if ($suspensions !== []) {
$parameters['result'] = new PermissionDeniedException(
WCF::getLanguage()->getDynamicVariable('chat.suspension.info.be.bastelstu.chat.suspension.ban')
);
$suspensions = Suspension::getActiveSuspensionsByTriple($objectTypeID, $parameters['user']->getDecoratedObject(), $eventObj);
if (!empty($suspensions)) {
$parameters['result'] = new PermissionDeniedException(WCF::getLanguage()->getDynamicVariable('chat.suspension.info.be.bastelstu.chat.suspension.ban'));
}
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 3
@ -15,43 +14,29 @@
namespace chat\system\event\listener;
use chat\data\user\User as ChatUser;
use chat\system\permission\PermissionHandler;
use wcf\system\event\listener\IParameterizedEventListener;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\WCF;
use \chat\system\permission\PermissionHandler;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\WCF;
/**
* Denies access when room is full.
*/
final class RoomCanJoinUserLimitListener implements IParameterizedEventListener
{
class RoomCanJoinUserLimitListener implements \wcf\system\event\listener\IParameterizedEventListener {
/**
* @inheritDoc
* @see \wcf\system\event\listener\IParameterizedEventListener::execute()
*/
public function execute($eventObj, $className, $eventName, array &$parameters)
{
if ($eventObj->userLimit === 0) {
return;
}
public function execute($eventObj, $className, $eventName, array &$parameters) {
if ($eventObj->userLimit === 0) return;
$users = $eventObj->getUsers();
if (\count($users) < $eventObj->userLimit) {
return;
}
if (count($users) < $eventObj->userLimit) return;
$user = new ChatUser($parameters['user']->getDecoratedObject());
if ($user->isInRoom($eventObj)) {
return;
}
$user = new \chat\data\user\User($parameters['user']->getDecoratedObject());
if ($user->isInRoom($eventObj)) return;
$canIgnoreLimit = PermissionHandler::get($parameters['user'])->getPermission($eventObj, 'mod.canIgnoreUserLimit');
if ($canIgnoreLimit) {
return;
}
if ($canIgnoreLimit) return;
$parameters['result'] = new PermissionDeniedException(
WCF::getLanguage()->get('chat.error.roomFull')
);
$parameters['result'] = new PermissionDeniedException(WCF::getLanguage()->get('chat.error.roomFull'));
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 3
@ -15,42 +14,30 @@
namespace chat\system\event\listener;
use chat\data\user\User as ChatUser;
use wcf\system\event\listener\IParameterizedEventListener;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\WCF;
use \chat\system\permission\PermissionHandler;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\WCF;
/**
* Denies access to temporary rooms, unless invited.
*/
final class RoomCanSeeTemproomListener implements IParameterizedEventListener
{
class RoomCanSeeTemproomListener implements \wcf\system\event\listener\IParameterizedEventListener {
/**
* @inheritDoc
* @see \wcf\system\event\listener\IParameterizedEventListener::execute()
*/
public function execute($eventObj, $className, $eventName, array &$parameters)
{
if (!$eventObj->isTemporary) {
return;
}
public function execute($eventObj, $className, $eventName, array &$parameters) {
if (!$eventObj->isTemporary) return;
$user = new ChatUser($parameters['user']->getDecoratedObject());
if ($eventObj->ownerID === $user->userID) {
return;
}
$user = new \chat\data\user\User($parameters['user']->getDecoratedObject());
if ($eventObj->ownerID === $user->userID) return;
$sql = "SELECT COUNT(*)
FROM chat1_room_temporary_invite
FROM chat".WCF_N."_room_temporary_invite
WHERE userID = ?
AND roomID = ?";
$statement = WCF::getDB()->prepare($sql);
$statement->execute([
$user->userID,
$eventObj->roomID,
]);
if ($statement->fetchSingleColumn() > 0) {
return;
}
$statement = WCF::getDB()->prepareStatement($sql);
$statement->execute([ $user->userID, $eventObj->roomID ]);
if ($statement->fetchSingleColumn() > 0) return;
$parameters['result'] = new PermissionDeniedException();
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 3
@ -15,37 +14,25 @@
namespace chat\system\event\listener;
use chat\data\suspension\Suspension;
use wcf\data\object\type\ObjectTypeCache;
use wcf\system\event\listener\IParameterizedEventListener;
use wcf\system\exception\PermissionDeniedException;
use wcf\system\WCF;
use \chat\data\suspension\Suspension;
use \wcf\data\object\type\ObjectTypeCache;
use \wcf\system\exception\PermissionDeniedException;
use \wcf\system\WCF;
/**
* Denies access to muted users.
*/
final class RoomCanWritePubliclyMuteListener implements IParameterizedEventListener
{
class RoomCanWritePubliclyMuteListener implements \wcf\system\event\listener\IParameterizedEventListener {
/**
* @inheritDoc
* @see \wcf\system\event\listener\IParameterizedEventListener::execute()
*/
public function execute($eventObj, $className, $eventName, array &$parameters)
{
$objectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName(
'be.bastelstu.chat.suspension',
'be.bastelstu.chat.suspension.mute'
);
\assert($objectTypeID !== null);
public function execute($eventObj, $className, $eventName, array &$parameters) {
$objectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName('be.bastelstu.chat.suspension', 'be.bastelstu.chat.suspension.mute');
if (!$objectTypeID) throw new \LogicException('Unreachable');
$suspensions = Suspension::getActiveSuspensionsByTriple(
$objectTypeID,
$parameters['user']->getDecoratedObject(),
$eventObj
);
if ($suspensions !== []) {
$parameters['result'] = new PermissionDeniedException(
WCF::getLanguage()->getDynamicVariable('chat.suspension.info.be.bastelstu.chat.suspension.mute')
);
$suspensions = Suspension::getActiveSuspensionsByTriple($objectTypeID, $parameters['user']->getDecoratedObject(), $eventObj);
if (!empty($suspensions)) {
$parameters['result'] = new PermissionDeniedException(WCF::getLanguage()->getDynamicVariable('chat.suspension.info.be.bastelstu.chat.suspension.mute'));
}
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 3
@ -15,21 +14,16 @@
namespace chat\system\event\listener;
use wcf\system\event\listener\IParameterizedEventListener;
use wcf\system\exception\PermissionDeniedException;
/**
* Disallow editing of temprooms in ACP.
*/
final class RoomEditFormTemproomListener implements IParameterizedEventListener
{
class RoomEditFormTemproomListener implements \wcf\system\event\listener\IParameterizedEventListener {
/**
* @inheritDoc
* @see \wcf\system\event\listener\IParameterizedEventListener::execute()
*/
public function execute($eventObj, $className, $eventName, array &$parameters)
{
public function execute($eventObj, $className, $eventName, array &$parameters) {
if ($eventObj->room->isTemporary) {
throw new PermissionDeniedException();
throw new \wcf\system\exception\PermissionDeniedException();
}
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 3
@ -15,18 +14,14 @@
namespace chat\system\event\listener;
use wcf\system\event\listener\IParameterizedEventListener;
/**
* Hides temprooms in ACP.
*/
final class RoomListPageTemproomListener implements IParameterizedEventListener
{
class RoomListPageTemproomListener implements \wcf\system\event\listener\IParameterizedEventListener {
/**
* @inheritDoc
* @see \wcf\system\event\listener\IParameterizedEventListener::execute()
*/
public function execute($eventObj, $className, $eventName, array &$parameters)
{
public function execute($eventObj, $className, $eventName, array &$parameters) {
$eventObj->objectList->getConditionBuilder()->add('isTemporary = ?', [ 0 ]);
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 3
@ -15,20 +14,17 @@
namespace chat\system\event\listener;
use chat\data\room\Room;
use wcf\system\event\listener\IParameterizedEventListener;
use \chat\data\room\Room;
/**
* Hides temprooms in ACP.
*/
final class SuspensionListPageTemproomListener implements IParameterizedEventListener
{
class SuspensionListPageTemproomListener implements \wcf\system\event\listener\IParameterizedEventListener {
/**
* @inheritDoc
* @see \wcf\system\event\listener\IParameterizedEventListener::execute()
*/
public function execute($eventObj, $className, $eventName, array &$parameters)
{
$eventObj->availableRooms = \array_filter($eventObj->availableRooms, static function (Room $room) {
public function execute($eventObj, $className, $eventName, array &$parameters) {
$eventObj->availableRooms = array_filter($eventObj->availableRooms, function (Room $room) {
return !$room->isTemporary;
});
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,86 +14,62 @@
namespace chat\system\message\type;
use chat\data\message\Message;
use wcf\data\user\UserProfile;
use wcf\system\event\EventHandler;
use wcf\system\html\output\HtmlOutputProcessor;
use wcf\system\WCF;
/**
* AttachmentMessageType represents a message with an attached file.
*/
final class AttachmentMessageType implements IMessageType, IDeletableMessageType
{
class AttachmentMessageType implements IMessageType, IDeletableMessageType {
use TCanSeeInSameRoom;
/**
* HtmlOutputProcessor to use.
* @var \wcf\system\html\output\HtmlOutputProcessor
*/
protected $processor;
protected $processor = null;
public function __construct()
{
$this->processor = new HtmlOutputProcessor();
public function __construct() {
$this->processor = new \wcf\system\html\output\HtmlOutputProcessor();
}
/**
* @inheritDoc
*/
public function getJavaScriptModuleName(): string
{
public function getJavaScriptModuleName() {
return 'Bastelstu.be/Chat/MessageType/Plain';
}
/**
* @inheritDoc
*/
public function canDelete(Message $message, ?UserProfile $user = null): bool
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function canDelete(\chat\data\message\Message $message, \wcf\data\user\UserProfile $user = null) {
if ($user === null) $user = new \wcf\data\user\UserProfile(\wcf\system\WCF::getUser());
return !!$user->getPermission('mod.chat.canDelete');
return $user->getPermission('mod.chat.canDelete');
}
/**
* @inheritDoc
* @see \chat\system\message\type\IMessageType::getPayload()
*/
public function getPayload(Message $message, ?UserProfile $user = null)
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function getPayload(\chat\data\message\Message $message, \wcf\data\user\UserProfile $user = null) {
if ($user === null) $user = new \wcf\data\user\UserProfile(\wcf\system\WCF::getUser());
$payload = $message->payload;
$payload['formattedMessage'] = null;
$payload['plaintextMessage'] = null;
$parameters = [
'message' => $message,
'user' => $user,
'payload' => $payload,
$parameters = [ 'message' => $message
, 'user' => $user
, 'payload' => $payload
];
EventHandler::getInstance()->fireAction($this, 'getPayload', $parameters);
\wcf\system\event\EventHandler::getInstance()->fireAction($this, 'getPayload', $parameters);
if ($parameters['payload']['formattedMessage'] === null) {
$this->processor->setOutputType('text/html');
$this->processor->process(
$parameters['payload']['message'],
'be.bastelstu.chat.message',
$message->messageID
);
$this->processor->process($parameters['payload']['message'], 'be.bastelstu.chat.message', $message->messageID);
$parameters['payload']['formattedMessage'] = $this->processor->getHtml();
}
if ($parameters['payload']['plaintextMessage'] === null) {
$this->processor->setOutputType('text/plain');
$this->processor->process(
$parameters['payload']['message'],
'be.bastelstu.chat.message',
$message->messageID
);
$this->processor->process($parameters['payload']['message'], 'be.bastelstu.chat.message', $message->messageID);
$parameters['payload']['plaintextMessage'] = $this->processor->getHtml();
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,80 +14,67 @@
namespace chat\system\message\type;
use chat\data\message\Message;
use chat\data\room\Room;
use wcf\data\user\UserProfile;
use wcf\system\event\EventHandler;
use wcf\system\WCF;
use \chat\data\message\Message;
use \chat\data\room\Room;
use \wcf\data\user\UserProfile;
/**
* AwayMessageType represents a notice that a user now is away from chat.
*/
final class AwayMessageType implements IMessageType
{
class AwayMessageType implements IMessageType {
use TDefaultPayload;
/**
* @inheritDoc
*/
public function getJavaScriptModuleName(): string
{
public function getJavaScriptModuleName() {
return 'Bastelstu.be/Chat/MessageType/Away';
}
/**
* @inheritDoc
* @see \chat\system\message\type\IMessageType::canSee()
*/
public function canSee(Message $message, Room $room, ?UserProfile $user = null): bool
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function canSee(Message $message, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
$roomIDs = \array_map(static function ($item) {
$roomIDs = array_map(function ($item) {
return $item['roomID'];
}, $message->payload['rooms']);
$parameters = [
'message' => $message,
'room' => $room,
'user' => $user,
'canSee' => \in_array($room->roomID, $roomIDs, true),
$parameters = [ 'message' => $message
, 'room' => $room
, 'user' => $user
, 'canSee' => in_array($room->roomID, $roomIDs, true)
];
EventHandler::getInstance()->fireAction($this, 'canSee', $parameters);
\wcf\system\event\EventHandler::getInstance()->fireAction($this, 'canSee', $parameters);
return $parameters['canSee'];
}
/**
* @inheritDoc
* @see \chat\system\message\type\IMessageType::canSeeInLog()
*/
public function canSeeInLog(Message $message, Room $room, ?UserProfile $user = null): bool
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function canSeeInLog(Message $message, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
$roomIDs = \array_map(static function ($item) {
$roomIDs = array_map(function ($item) {
return $item['roomID'];
}, $message->payload['rooms']);
$parameters = [
'message' => $message,
'room' => $room,
'user' => $user,
'canSee' => \in_array($room->roomID, $roomIDs, true),
$parameters = [ 'message' => $message
, 'room' => $room
, 'user' => $user
, 'canSee' => in_array($room->roomID, $roomIDs, true)
];
EventHandler::getInstance()->fireAction($this, 'canSeeInLog', $parameters);
\wcf\system\event\EventHandler::getInstance()->fireAction($this, 'canSeeInLog', $parameters);
return $parameters['canSee'];
}
/**
* @inheritDoc
* @see»\chat\system\message\type\IMessageType::supportsFastSelect()
*/
public function supportsFastSelect(): bool
{
public function supportsFastSelect() {
return false;
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,80 +14,67 @@
namespace chat\system\message\type;
use chat\data\message\Message;
use chat\data\room\Room;
use wcf\data\user\UserProfile;
use wcf\system\event\EventHandler;
use wcf\system\WCF;
use \chat\data\message\Message;
use \chat\data\room\Room;
use \wcf\data\user\UserProfile;
/**
* BackMessageType represents a notice that a user now is now back.
*/
final class BackMessageType implements IMessageType
{
class BackMessageType implements IMessageType {
use TDefaultPayload;
/**
* @inheritDoc
*/
public function getJavaScriptModuleName(): string
{
public function getJavaScriptModuleName() {
return 'Bastelstu.be/Chat/MessageType/Back';
}
/**
* @inheritDoc
* @see \chat\system\message\type\IMessageType::canSee()
*/
public function canSee(Message $message, Room $room, ?UserProfile $user = null): bool
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function canSee(Message $message, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
$roomIDs = \array_map(static function ($item) {
$roomIDs = array_map(function ($item) {
return $item['roomID'];
}, $message->payload['rooms']);
$parameters = [
'message' => $message,
'room' => $room,
'user' => $user,
'canSee' => \in_array($room->roomID, $roomIDs, true),
$parameters = [ 'message' => $message
, 'room' => $room
, 'user' => $user
, 'canSee' => in_array($room->roomID, $roomIDs, true)
];
EventHandler::getInstance()->fireAction($this, 'canSee', $parameters);
\wcf\system\event\EventHandler::getInstance()->fireAction($this, 'canSee', $parameters);
return $parameters['canSee'];
}
/**
* @inheritDoc
* @see \chat\system\message\type\IMessageType::canSeeInLog()
*/
public function canSeeInLog(Message $message, Room $room, ?UserProfile $user = null): bool
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function canSeeInLog(Message $message, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
$roomIDs = \array_map(static function ($item) {
$roomIDs = array_map(function ($item) {
return $item['roomID'];
}, $message->payload['rooms']);
$parameters = [
'message' => $message,
'room' => $room,
'user' => $user,
'canSee' => \in_array($room->roomID, $roomIDs, true),
$parameters = [ 'message' => $message
, 'room' => $room
, 'user' => $user
, 'canSee' => in_array($room->roomID, $roomIDs, true)
];
EventHandler::getInstance()->fireAction($this, 'canSeeInLog', $parameters);
\wcf\system\event\EventHandler::getInstance()->fireAction($this, 'canSeeInLog', $parameters);
return $parameters['canSee'];
}
/**
* @inheritDoc
* @see»\chat\system\message\type\IMessageType::supportsFastSelect()
*/
public function supportsFastSelect(): bool
{
public function supportsFastSelect() {
return false;
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,59 +14,59 @@
namespace chat\system\message\type;
use chat\data\message\Message;
use chat\data\room\Room;
use wcf\data\user\UserProfile;
use wcf\system\event\EventHandler;
use wcf\system\WCF;
use \chat\data\message\Message;
use \chat\data\room\Room;
use \wcf\data\user\UserProfile;
/**
* BroadcastMessageType represents a broadcasted message.
*/
final class BroadcastMessageType implements IMessageType, IDeletableMessageType
{
class BroadcastMessageType extends PlainMessageType {
/**
* @var PlainMessageType
* HtmlOutputProcessor to use.
* @var \wcf\system\html\output\HtmlOutputProcessor
*/
protected $plainMessageType;
protected $processor = null;
public function __construct()
{
$this->plainMessageType = new PlainMessageType();
public function __construct() {
$this->processor = new \wcf\system\html\output\HtmlOutputProcessor();
}
/**
* @inheritDoc
*/
public function getJavaScriptModuleName(): string
{
public function getJavaScriptModuleName() {
return 'Bastelstu.be/Chat/MessageType/Broadcast';
}
/**
* @inheritDoc
* @see \chat\system\message\type\IMessageType::canSee()
*/
public function getPayload(Message $message, ?UserProfile $user = null)
{
return $this->plainMessageType->getPayload($message, $user);
public function canSee(Message $message, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
$parameters = [ 'message' => $message
, 'room' => $room
, 'user' => $user
, 'canSee' => true
];
\wcf\system\event\EventHandler::getInstance()->fireAction($this, 'canSee', $parameters);
return $parameters['canSee'];
}
/**
* @inheritDoc
* @see \chat\system\message\type\IMessageType::canSeeInLog()
*/
public function canSee(Message $message, Room $room, ?UserProfile $user = null): bool
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function canSeeInLog(Message $message, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
$parameters = [
'message' => $message,
'room' => $room,
'user' => $user,
'canSee' => true,
$parameters = [ 'message' => $message
, 'room' => $room
, 'user' => $user
, 'canSee' => true
];
EventHandler::getInstance()->fireAction($this, 'canSee', $parameters);
\wcf\system\event\EventHandler::getInstance()->fireAction($this, 'canSeeInLog', $parameters);
return $parameters['canSee'];
}
@ -75,40 +74,16 @@ public function canSee(Message $message, Room $room, ?UserProfile $user = null):
/**
* @inheritDoc
*/
public function canSeeInLog(Message $message, Room $room, ?UserProfile $user = null): bool
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function canDelete(\chat\data\message\Message $message, \wcf\data\user\UserProfile $user = null) {
if ($user === null) $user = new \wcf\data\user\UserProfile(\wcf\system\WCF::getUser());
$parameters = [
'message' => $message,
'room' => $room,
'user' => $user,
'canSee' => true,
];
EventHandler::getInstance()->fireAction($this, 'canSeeInLog', $parameters);
return $parameters['canSee'];
return $user->getPermission('mod.chat.canDelete');
}
/**
* @inheritDoc
* @see»\chat\system\message\type\IMessageType::supportsFastSelect()
*/
public function canDelete(Message $message, ?UserProfile $user = null): bool
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
return !!$user->getPermission('mod.chat.canDelete');
}
/**
* @inheritDoc
*/
public function supportsFastSelect(): bool
{
public function supportsFastSelect() {
return false;
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,46 +14,41 @@
namespace chat\system\message\type;
use chat\data\message\Message;
use chat\data\room\Room;
use wcf\data\user\UserProfile;
use \chat\data\message\Message;
use \chat\data\room\Room;
use \wcf\data\user\UserProfile;
/**
* ChatUpdateMessageType informs the chat about a back end update.
*/
final class ChatUpdateMessageType implements IMessageType
{
class ChatUpdateMessageType implements IMessageType {
use TDefaultPayload;
/**
* @inheritDoc
*/
public function getJavaScriptModuleName(): string
{
public function getJavaScriptModuleName() {
return 'Bastelstu.be/Chat/MessageType/ChatUpdate';
}
/**
* @inheritDoc
* @see \chat\system\message\type\IMessageType::canSee()
*/
public function canSee(Message $message, Room $room, ?UserProfile $user = null): bool
{
public function canSee(Message $message, Room $room, UserProfile $user = null) {
return true;
}
/**
* @inheritDoc
* @see \chat\system\message\type\IMessageType::canSeeInLog()
*/
public function canSeeInLog(Message $message, Room $room, ?UserProfile $user = null): bool
{
public function canSeeInLog(Message $message, Room $room, UserProfile $user = null) {
return true;
}
/**
* @inheritDoc
* @see»\chat\system\message\type\IMessageType::supportsFastSelect()
*/
public function supportsFastSelect(): bool
{
public function supportsFastSelect() {
return false;
}
}

View File

@ -1,12 +1,11 @@
<?php
/*
* Copyright (c) 2010-2024 Tim Düsterhus.
* Copyright (c) 2010-2021 Tim Düsterhus.
*
* Use of this software is governed by the Business Source License
* included in the LICENSE file.
*
* Change Date: 2028-06-15
* Change Date: 2025-03-05
*
* On the date above, in accordance with the Business Source
* License, use of this software will be governed by version 2
@ -15,60 +14,50 @@
namespace chat\system\message\type;
use chat\data\message\Message;
use chat\data\room\Room;
use wcf\data\user\UserProfile;
use wcf\system\event\EventHandler;
use wcf\system\WCF;
use \chat\data\message\Message;
use \chat\data\room\Room;
use \wcf\data\user\UserProfile;
/**
* ColorMessageType represents a color message.
*/
final class ColorMessageType implements IMessageType
{
class ColorMessageType implements IMessageType {
use TDefaultPayload;
/**
* @inheritDoc
*/
public function getJavaScriptModuleName(): string
{
public function getJavaScriptModuleName() {
return 'Bastelstu.be/Chat/MessageType/Color';
}
/**
* @inheritDoc
* @see \chat\system\message\type\IMessageType::canSee()
*/
public function canSee(Message $message, Room $room, ?UserProfile $user = null): bool
{
if ($user === null) {
$user = new UserProfile(WCF::getUser());
}
public function canSee(Message $message, Room $room, UserProfile $user = null) {
if ($user === null) $user = new UserProfile(\wcf\system\WCF::getUser());
$parameters = [
'message' => $message,
'room' => $room,
'user' => $user,
'canSee' => true,
$parameters = [ 'message' => $message
, 'room' => $room
, 'user' => $user
, 'canSee' => true
];
EventHandler::getInstance()->fireAction($this, 'canSee', $parameters);
\wcf\system\event\EventHandler::getInstance()->fireAction($this, 'canSee', $parameters);
return $parameters['canSee'];
}
/**
* @inheritDoc
* @see \chat\system\message\type\IMessageType::canSeeInLog()
*/
public function canSeeInLog(Message $message, Room $room, ?UserProfile $user = null): bool
{
public function canSeeInLog(Message $message, Room $room, UserProfile $user = null) {
return false;
}
/**
* @inheritDoc
* @see»\chat\system\message\type\IMessageType::supportsFastSelect()
*/
public function supportsFastSelect(): bool
{
public function supportsFastSelect() {
return false;
}
}

Some files were not shown because too many files have changed in this diff Show More