diff --git a/acloptions.xml b/acloptions.xml
index 8042782..5df092e 100644
--- a/acloptions.xml
+++ b/acloptions.xml
@@ -1,8 +1,34 @@
-
+
+
+ timwolla.wcf.chat.room
+
+
+ timwolla.wcf.chat.room
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/acpMenu.xml b/acpMenu.xml
new file mode 100644
index 0000000..2752765
--- /dev/null
+++ b/acpMenu.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ wcf.acp.menu.link.content
+
+
+
+ index.php/ChatRoomList/
+ wcf.acp.menu.link.chat
+ admin.content.chat.canEditRoom,admin.content.chat.canDeleteRoom
+ 1
+
+
+
+ index.php/ChatRoomAdd/
+ wcf.acp.menu.link.chat
+ admin.content.chat.canAddRoom
+ 2
+
+
+
diff --git a/acptemplate/chatRoomAdd.tpl b/acptemplate/chatRoomAdd.tpl
new file mode 100644
index 0000000..a3c0e81
--- /dev/null
+++ b/acptemplate/chatRoomAdd.tpl
@@ -0,0 +1,101 @@
+{include file='header'}
+
+
+
+
+
+
+
+
+
+
+
+ {lang}wcf.acp.chat.room.{$action}{/lang}
+
+
+
+{if $errorField}
+
{lang}wcf.global.form.error{/lang}
+{/if}
+
+{if $success|isset}
+ {lang}wcf.global.form.{$action}.success{/lang}
+{/if}
+
+
+
+
+
+{include file='footer'}
\ No newline at end of file
diff --git a/acptemplate/chatRoomList.tpl b/acptemplate/chatRoomList.tpl
new file mode 100644
index 0000000..e42144a
--- /dev/null
+++ b/acptemplate/chatRoomList.tpl
@@ -0,0 +1,58 @@
+{include file='header'}
+
+
+
+
+
+
+ {lang}wcf.acp.chat.room.list{/lang}
+
+
+
+
+
+
+ {hascontent}
+
+ {content}
+ {foreach from=$objects item=chatRoom}
+ -
+
+ {$chatRoom->title|language}
+
+
+ {if $__wcf->session->getPermission('admin.content.chat.canEditRoom')}
+
+ {/if}
+ {if $__wcf->session->getPermission('admin.content.chat.canDeleteRoom')}
+
+ {/if}
+
+
+
+ {/foreach}
+ {/content}
+
+ {hascontentelse}
+ {lang}wcf.acp.chat.room.noneAvailable{/lang}
+ {/hascontent}
+
+
+{include file='footer'}
\ No newline at end of file
diff --git a/build.php b/build.php
index f10da56..5b96816 100755
--- a/build.php
+++ b/build.php
@@ -15,6 +15,7 @@ Cleaning up
EOT;
if (file_exists('file.tar')) unlink('file.tar');
if (file_exists('template.tar')) unlink('template.tar');
+ if (file_exists('acptemplate.tar')) unlink('acptemplate.tar');
foreach (glob('file/js/*.js') as $jsFile) unlink($jsFile);
foreach (glob('file/style/*.css') as $cssFile) unlink($cssFile);
if (file_exists('timwolla.wcf.chat.tar')) unlink('timwolla.wcf.chat.tar');
@@ -60,15 +61,25 @@ EOT;
if ($code != 0) exit($code);
echo <<
+ * @package timwolla.wcf.chat
+ */
+final class Update {
+ private $rooms = null;
+ public function __construct() {
+ $this->rooms = \wcf\data\chat\room\ChatRoom::getCache();
+ }
+
+ public function execute() {
+ foreach ($this->rooms as $room) {
+ $messageAction = new \wcf\data\chat\message\ChatMessageAction(array(), 'create', array(
+ 'data' => array(
+ 'roomID' => $room->roomID,
+ 'time' => TIME_NOW,
+ 'type' => \wcf\data\chat\message\ChatMessage::TYPE_INFORMATION,
+ // TODO: Language item
+ 'message' => 'Tims Chat was updated. Please refresh the page.'
+ )
+ ));
+ $messageAction->executeAction();
+ }
+ }
+}
+$update = new Update();
+$update->execute();
diff --git a/file/icon/chat.svg b/file/icon/chat.svg
new file mode 100644
index 0000000..19808ff
--- /dev/null
+++ b/file/icon/chat.svg
@@ -0,0 +1,58 @@
+
+
+
+
diff --git a/file/js/TimWolla.WCF.Chat.coffee b/file/js/TimWolla.WCF.Chat.coffee
index 8b81072..7bd749c 100644
--- a/file/js/TimWolla.WCF.Chat.coffee
+++ b/file/js/TimWolla.WCF.Chat.coffee
@@ -9,12 +9,18 @@
TimWolla ?= {}
TimWolla.WCF ?= {}
+consoleMock = console
consoleMock ?=
log: () ->,
- warn: () ->
+ warn: () ->,
+ error: () ->
(($, window, console) ->
TimWolla.WCF.Chat =
+ # Tims Chat stops loading when this reaches zero
+ # TODO: We need an explosion animation
+ shields: 3
+
# Templates
titleTemplate: null
messageTemplate: null
@@ -34,17 +40,21 @@ consoleMock ?=
events:
newMessage: $.Callbacks()
userMenu: $.Callbacks()
+ pe:
+ getMessages: null
+ refreshRoomList: null
+ fish: null
init: () ->
console.log '[TimWolla.WCF.Chat] Initializing'
@bindEvents()
@events.newMessage.add $.proxy @notify, @
- new WCF.PeriodicalExecuter $.proxy(@refreshRoomList, @), 60e3
- new WCF.PeriodicalExecuter $.proxy(@getMessages, @), @config.reloadTime * 1e3
+ @pe.refreshRoomList = new WCF.PeriodicalExecuter $.proxy(@refreshRoomList, @), 60e3
+ @pe.getMessages = new WCF.PeriodicalExecuter $.proxy(@getMessages, @), @config.reloadTime * 1e3
@refreshRoomList()
@getMessages()
- console.log '[TimWolla.WCF.Chat] Finished initializing'
+ console.log '[TimWolla.WCF.Chat] Finished initializing - Shields at 104 percent'
###
# Autocompletes a username
###
@@ -64,6 +74,7 @@ consoleMock ?=
# Binds all the events needed for Tims Chat.
###
bindEvents: () ->
+ # Mark window as focused
$(window).focus $.proxy () ->
document.title = @titleTemplate.fetch
title: $('#timsChatRoomList .activeMenuItem a').text()
@@ -71,12 +82,19 @@ consoleMock ?=
@isActive = true
, @
+ # Mark window as blurred
$(window).blur $.proxy () ->
@isActive = false
, @
+ # Unload the chat
+ window.onbeforeunload = $.proxy () ->
+ @unload()
+ return undefined
+ , @
+
# Insert a smiley
- $('.smiley').click $.proxy (event) ->
+ $('.jsSmiley').click $.proxy (event) ->
@insertText ' ' + $(event.target).attr('alt') + ' '
, @
@@ -118,11 +136,11 @@ consoleMock ?=
# Clears the stream
$('#timsChatClear').click (event) ->
- event.preventDefault()
- $('.timsChatMessage').remove()
- @oldScrollTop = $('.timsChatMessageContainer').scrollTop()
- $('.timsChatMessageContainer').scrollTop $('.timsChatMessageContainer ul').height()
- $('#timsChatInput').focus()
+ event.preventDefault()
+ $('.timsChatMessage').remove()
+ @oldScrollTop = null
+ $('.timsChatMessageContainer').scrollTop $('.timsChatMessageContainer ul').height()
+ $('#timsChatInput').focus()
# Toggle Buttons
$('.timsChatToggle').click (event) ->
@@ -139,7 +157,7 @@ consoleMock ?=
# Immediatly scroll down when activating autoscroll
$('#timsChatAutoscroll').click (event) ->
- $(this).removeClass('hot')
+ $(this).parent().removeClass('default')
if $(this).data 'status'
$('.timsChatMessageContainer').scrollTop $('.timsChatMessageContainer ul').height()
@oldScrollTop = $('.timsChatMessageContainer').scrollTop()
@@ -172,15 +190,15 @@ consoleMock ?=
# Set new topic
if data.topic is ''
- return if $('#topic').text().trim() is ''
+ return if $('#timsChatTopic').text().trim() is ''
- $('#topic').wcfBlindOut 'vertical', () ->
+ $('#timsChatTopic').wcfBlindOut 'vertical', () ->
$(@).text ''
else
- $('#topic').text data.topic
- $('#topic').wcfBlindIn() if $('#topic').text().trim() isnt '' and $('#topic').is(':hidden')
+ $('#timsChatTopic').text data.topic
+ $('#timsChatTopic').wcfBlindIn() if $('#timsChatTopic').text().trim() isnt '' and $('#timsChatTopic').is(':hidden')
- $('.timsChatMessage').animate('opacity', .8);
+ $('.timsChatMessage').addClass('unloaded', 800);
@handleMessages data.messages
document.title = @titleTemplate.fetch data
, @)
@@ -198,7 +216,7 @@ consoleMock ?=
# Frees the fish
###
freeTheFish: () ->
- return if $.wcfIsset('fish')
+ return if $.wcfIsset 'fish'
console.warn '[TimWolla.WCF.Chat] Freeing the fish'
fish = $ '' + WCF.String.escapeHTML('><((((\u00B0>') + '
'
fish.css
@@ -210,16 +228,16 @@ consoleMock ?=
zIndex: 9999
fish.appendTo $ 'body'
- new WCF.PeriodicalExecuter(() ->
+ @pe.fish = new WCF.PeriodicalExecuter(() ->
left = Math.random() * 100 - 50
top = Math.random() * 100 - 50
- fish = $('#fish')
+ fish = $ '#fish'
left *= -1 unless fish.width() < (fish.position().left + left) < ($(document).width() - fish.width())
top *= -1 unless fish.height() < (fish.position().top + top) < ($(document).height() - fish.height())
- fish.text('><((((\u00B0>') if left > 0
- fish.text('<\u00B0))))><') if left < 0
+ fish.text '><((((\u00B0>' if left > 0
+ fish.text '<\u00B0))))><' if left < 0
fish.animate
top: '+=' + top
@@ -237,6 +255,15 @@ consoleMock ?=
@handleMessages(data.messages)
@handleUsers(data.users)
, @)
+ error: $.proxy((jqXHR, textStatus, errorThrown) ->
+ console.error '[TimWolla.WCF.Chat] Battle Station hit - shields at ' + (--@shields / 3 * 104) + ' percent'
+ if @shields is 0
+ @pe.refreshRoomList.stop()
+ @pe.getMessages.stop()
+ @freeTheFish()
+ console.error '[TimWolla.WCF.Chat] We got destroyed, but could free our friend the fish before he was killed as well. Have a nice life in freedom!'
+ alert 'herp i cannot load messages'
+ , @)
###
# Inserts the new messages.
#
@@ -248,14 +275,16 @@ consoleMock ?=
if $('.timsChatMessageContainer').scrollTop() < @oldScrollTop
if $('#timsChatAutoscroll').data('status') is 1
$('#timsChatAutoscroll').click()
- $('#timsChatAutoscroll').addClass('hot').fadeOut('slow').fadeIn('slow')
+ $('#timsChatAutoscroll').parent().addClass('default').fadeOut('slow').fadeIn('slow')
# Insert the messages
for message in messages
+ continue if $.wcfIsset 'timsChatMessage'+message.messageID # Prevent problems with race condition
@events.newMessage.fire message
output = @messageTemplate.fetch message
li = $ ''
+ li.attr 'id', 'timsChatMessage'+message.messageID
li.addClass 'timsChatMessage timsChatMessage'+message.type
li.addClass 'ownMessage' if message.sender is WCF.User.userID
li.append output
@@ -314,7 +343,7 @@ consoleMock ?=
$(@).remove();
- $('#toggleUsers .badge').text(users.length);
+ $('#toggleUsers .wcf-badge').text(users.length);
###
# Inserts text into our input.
#
@@ -371,7 +400,7 @@ consoleMock ?=
success: $.proxy((data, textStatus, jqXHR) ->
$('#timsChatRoomList li').remove()
$('#toggleRooms a').removeClass 'ajaxLoad'
- $('#toggleRooms .badge').text(data.length);
+ $('#toggleRooms .wcf-badge').text(data.length);
for room in data
li = $ ''
@@ -447,4 +476,11 @@ consoleMock ?=
else
li.addClass 'activeMenuItem'
li.find('.timsChatUserMenu').wcfBlindIn 'vertical'
+ ###
+ # Unloads the chat.
+ ###
+ unload: () ->
+ $.ajax @config.unloadURL,
+ type: 'POST'
+ async: false
)(jQuery, @, consoleMock)
diff --git a/file/lib/acp/form/ChatRoomAddForm.class.php b/file/lib/acp/form/ChatRoomAddForm.class.php
new file mode 100644
index 0000000..e5a95e1
--- /dev/null
+++ b/file/lib/acp/form/ChatRoomAddForm.class.php
@@ -0,0 +1,149 @@
+
+ * @package timwolla.wcf.chat
+ * @subpackage acp.form
+ */
+class ChatRoomAddForm extends ACPForm {
+ /**
+ * @see \wcf\acp\form\ACPForm::$activeMenuItem
+ */
+ public $activeMenuItem = 'wcf.acp.menu.link.chat.room.add';
+
+ /**
+ * @see \wcf\page\AbstractPage::$neededPermissions
+ */
+ public $neededPermissions = array('admin.content.chat.canAddRoom');
+
+ /**
+ * Title of the room
+ *
+ * @var string
+ */
+ public $title = '';
+
+ /**
+ * Topic of the room
+ *
+ * @var string
+ */
+ public $topic = '';
+
+ /**
+ * @see \wcf\page\AbstractPage::__construct()
+ */
+ public function __construct() {
+ $this->objectTypeID = \wcf\system\acl\ACLHandler::getInstance()->getObjectTypeID('timwolla.wcf.chat.room');
+
+ parent::__construct();
+ }
+
+ /**
+ * @see \wcf\page\IPage::readParameters()
+ */
+ public function readParameters() {
+ parent::readParameters();
+
+ I18nHandler::getInstance()->register('title');
+ I18nHandler::getInstance()->register('topic');
+ }
+
+ /**
+ * @see \wcf\form\IForm::readFormParameters()
+ */
+ public function readFormParameters() {
+ parent::readFormParameters();
+
+ I18nHandler::getInstance()->readValues();
+
+ if (I18nHandler::getInstance()->isPlainValue('title')) $this->title = I18nHandler::getInstance()->getValue('title');
+ if (I18nHandler::getInstance()->isPlainValue('topic')) $this->topic = I18nHandler::getInstance()->getValue('topic');
+ }
+
+ /**
+ * @see \wcf\form\IForm::validate()
+ */
+ public function validate() {
+ parent::validate();
+
+ // validate title
+ if (!I18nHandler::getInstance()->validateValue('title')) {
+ throw new UserInputException('title');
+ }
+ }
+
+ /**
+ * @see \wcf\form\IForm::save()
+ */
+ public function save() {
+ parent::save();
+
+ // save room
+ $this->objectAction = new \wcf\data\chat\room\ChatRoomAction(array(), 'create', array('data' => array(
+ 'title' => $this->title,
+ 'topic' => $this->topic
+ )));
+ $this->objectAction->executeAction();
+ $returnValues = $this->objectAction->getReturnValues();
+ $chatRoomEditor = new \wcf\data\chat\room\ChatRoomEditor($returnValues['returnValues']);
+ $roomID = $returnValues['returnValues']->roomID;
+
+ if (!I18nHandler::getInstance()->isPlainValue('title')) {
+ I18nHandler::getInstance()->save('title', 'wcf.chat.room.title'.$roomID, 'wcf.chat.room', PackageDependencyHandler::getPackageID('timwolla.wcf.chat'));
+
+ // update title
+ $chatRoomEditor->update(array(
+ 'title' => 'wcf.chat.room.title'.$roomID
+ ));
+ }
+
+ if (!I18nHandler::getInstance()->isPlainValue('topic')) {
+ I18nHandler::getInstance()->save('topic', 'wcf.chat.room.topic'.$roomID, 'wcf.chat.room', PackageDependencyHandler::getPackageID('timwolla.wcf.chat'));
+
+ // update topic
+ $chatRoomEditor->update(array(
+ 'topic' => 'wcf.chat.room.topic'.$roomID
+ ));
+ }
+
+ \wcf\system\acl\ACLHandler::getInstance()->save($roomID, $this->objectTypeID);
+ \wcf\system\chat\permission\ChatPermissionHandler::clearCache();
+
+ $this->saved();
+
+ // reset values
+ $this->topic = $this->title = '';
+ I18nHandler::getInstance()->disableAssignValueVariables();
+
+ // show success
+ WCF::getTPL()->assign(array(
+ 'success' => true
+ ));
+ }
+
+ /**
+ * @see \wcf\page\IPage::assignVariables()
+ */
+ public function assignVariables() {
+ parent::assignVariables();
+
+ I18nHandler::getInstance()->assignVariables();
+
+ WCF::getTPL()->assign(array(
+ 'action' => 'add',
+ 'title' => $this->title,
+ 'topic' => $this->topic,
+ 'objectTypeID' => $this->objectTypeID
+ ));
+ }
+}
diff --git a/file/lib/acp/form/ChatRoomEditForm.class.php b/file/lib/acp/form/ChatRoomEditForm.class.php
new file mode 100644
index 0000000..a0298be
--- /dev/null
+++ b/file/lib/acp/form/ChatRoomEditForm.class.php
@@ -0,0 +1,129 @@
+
+ * @package timwolla.wcf.chat
+ * @subpackage acp.form
+ */
+class ChatRoomEditForm extends ChatRoomAddForm {
+ /**
+ * @see \wcf\page\AbstractPage::$templateName
+ */
+ public $templateName = 'chatRoomAdd';
+
+ /**
+ * @see \wcf\acp\form\ACPForm::$activeMenuItem
+ */
+ public $activeMenuItem = 'wcf.acp.menu.link.chat.room.list';
+
+ /**
+ * @see \wcf\page\AbstractPage::$neededPermissions
+ */
+ public $neededPermissions = array('admin.content.chat.canEditRoom');
+
+ /**
+ * room id
+ *
+ * @var integer
+ */
+ public $roomID = 0;
+
+ /**
+ * room object
+ *
+ * @var \wcf\data\chat\room\ChatRoom
+ */
+ public $roomObj = null;
+
+ /**
+ * @see \wcf\page\IPage::readParameters()
+ */
+ public function readParameters() {
+ parent::readParameters();
+
+ if (isset($_REQUEST['id'])) $this->roomID = intval($_REQUEST['id']);
+ $this->roomObj = new \wcf\data\chat\room\ChatRoom($this->roomID);
+ if (!$this->roomObj->roomID) {
+ throw new \wcf\system\exception\IllegalLinkException();
+ }
+ }
+
+ /**
+ * @see \wcf\form\IForm::save()
+ */
+ public function save() {
+ ACPForm::save();
+
+ $this->title = 'wcf.chat.room.title'.$this->roomObj->roomID;
+ if (I18nHandler::getInstance()->isPlainValue('title')) {
+ I18nHandler::getInstance()->remove($this->title, PackageDependencyHandler::getPackageID('timwolla.wcf.chat'));
+ $this->title = I18nHandler::getInstance()->getValue('title');
+ }
+ else {
+ I18nHandler::getInstance()->save('title', $this->title, 'wcf.chat.room', PackageDependencyHandler::getPackageID('timwolla.wcf.chat'));
+ }
+
+ $this->topic = 'wcf.chat.room.topic'.$this->roomObj->roomID;
+ if (I18nHandler::getInstance()->isPlainValue('topic')) {
+ I18nHandler::getInstance()->remove($this->topic, PackageDependencyHandler::getPackageID('timwolla.wcf.chat'));
+ $this->topic = I18nHandler::getInstance()->getValue('topic');
+ }
+ else {
+ I18nHandler::getInstance()->save('topic', $this->topic, 'wcf.chat.room', PackageDependencyHandler::getPackageID('timwolla.wcf.chat'));
+ }
+
+ \wcf\system\acl\ACLHandler::getInstance()->save($this->roomID, $this->objectTypeID);
+ \wcf\system\chat\permission\ChatPermissionHandler::clearCache();
+
+ // update room
+ $this->objectAction = new \wcf\data\chat\room\ChatRoomAction(array($this->roomID), 'update', array('data' => array(
+ 'title' => $this->title,
+ 'topic' => $this->topic
+ )));
+ $this->objectAction->executeAction();
+
+ $this->saved();
+
+ // show success
+ WCF::getTPL()->assign(array(
+ 'success' => true
+ ));
+ }
+
+ /**
+ * @see \wcf\page\IPage::readData()
+ */
+ public function readData() {
+ parent::readData();
+
+ if (!count($_POST)) {
+ I18nHandler::getInstance()->setOptions('title', PackageDependencyHandler::getPackageID('timwolla.wcf.chat'), $this->roomObj->title, 'wcf.chat.room.title\d+');
+ I18nHandler::getInstance()->setOptions('topic', PackageDependencyHandler::getPackageID('timwolla.wcf.chat'), $this->roomObj->topic, 'wcf.chat.room.topic\d+');
+
+ $this->title = $this->roomObj->title;
+ $this->topic = $this->roomObj->topic;
+ }
+ }
+
+ /**
+ * @see \wcf\page\IPage::assignVariables()
+ */
+ public function assignVariables() {
+ parent::assignVariables();
+
+ I18nHandler::getInstance()->assignVariables((bool) count($_POST));
+
+ WCF::getTPL()->assign(array(
+ 'roomID' => $this->roomID,
+ 'action' => 'edit'
+ ));
+ }
+}
\ No newline at end of file
diff --git a/file/lib/acp/page/ChatRoomListPage.class.php b/file/lib/acp/page/ChatRoomListPage.class.php
new file mode 100644
index 0000000..ac1314a
--- /dev/null
+++ b/file/lib/acp/page/ChatRoomListPage.class.php
@@ -0,0 +1,46 @@
+
+ * @package timwolla.wcf.chat
+ * @subpackage acp.page
+ */
+class ChatRoomListPage extends \wcf\page\MultipleLinkPage {
+ /**
+ * @see \wcf\page\AbstractPage::$neededPermissions
+ */
+ public $neededPermissions = array(
+ 'admin.content.chat.canEditRoom',
+ 'admin.content.chat.canDeleteRoom'
+ );
+
+ /**
+ * @see \wcf\page\MultipleLinkPage::$objectListClassName
+ */
+ public $objectListClassName = '\wcf\data\chat\room\ChatRoomList';
+
+ /**
+ * @see \wcf\page\MultipleLinkPage::$sortField
+ */
+ public $sortField = 'position';
+
+ /**
+ * @see \wcf\page\MultipleLinkPage::$sortOrder
+ */
+ public $sortOrder = 'ASC';
+
+ /**
+ * @see \wcf\page\IPage::show()
+ */
+ public function show() {
+ // set active menu item.
+ \wcf\system\menu\acp\ACPMenu::getInstance()->setActiveMenuItem('wcf.acp.menu.link.chat.room.list');
+
+ parent::show();
+ }
+}
diff --git a/file/lib/action/ChatLeaveAction.class.php b/file/lib/action/ChatLeaveAction.class.php
new file mode 100644
index 0000000..f2f3146
--- /dev/null
+++ b/file/lib/action/ChatLeaveAction.class.php
@@ -0,0 +1,65 @@
+
+ * @package timwolla.wcf.chat
+ * @subpackage action
+ */
+class ChatLeaveAction extends AbstractAction {
+ /**
+ * @see \wcf\action\AbstractAction::$neededModules
+ */
+ public $neededModules = array('CHAT_ACTIVE');
+ //public $neededPermissions = array('user.chat.canEnter');
+ public $room = null;
+ public $userData = array();
+
+ /**
+ * @see \wcf\action\IAction::execute()
+ */
+ public function execute() {
+ parent::execute();
+
+ // validate
+ if (!WCF::getUser()->userID) {
+ throw new IllegalLinkException();
+ }
+
+ $this->userData['roomID'] = \wcf\util\ChatUtil::readUserData('roomID');
+
+ $this->room = chat\room\ChatRoom::getCache()->search($this->userData['roomID']);
+ if (!$this->room) throw new \wcf\system\exception\IllegalLinkException();
+ if (!$this->room->canEnter()) throw new \wcf\system\exception\PermissionDeniedException();
+
+ if (CHAT_DISPLAY_JOIN_LEAVE) {
+ $this->userData['color'] = \wcf\util\ChatUtil::readUserData('color');
+
+ $messageAction = new chat\message\ChatMessageAction(array(), 'create', array(
+ 'data' => array(
+ 'roomID' => $this->room->roomID,
+ 'sender' => WCF::getUser()->userID,
+ 'username' => WCF::getUser()->username,
+ 'time' => TIME_NOW,
+ 'type' => chat\message\ChatMessage::TYPE_LEAVE,
+ 'message' => '',
+ 'color1' => $this->userData['color'][1],
+ 'color2' => $this->userData['color'][2]
+ )
+ ));
+ $messageAction->executeAction();
+ }
+
+ \wcf\util\ChatUtil::writeUserData(array('roomID' => null));
+
+ $this->executed();
+ header("HTTP/1.0 204 No Content");
+ exit;
+ }
+}
diff --git a/file/lib/data/chat/message/ChatMessage.class.php b/file/lib/data/chat/message/ChatMessage.class.php
index ebbddfa..f8e5db5 100755
--- a/file/lib/data/chat/message/ChatMessage.class.php
+++ b/file/lib/data/chat/message/ChatMessage.class.php
@@ -13,12 +13,12 @@ use \wcf\system\WCF;
*/
class ChatMessage extends \wcf\data\DatabaseObject {
/**
- * @see wcf\data\DatabaseObject::$databaseTableName
+ * @see \wcf\data\DatabaseObject::$databaseTableName
*/
protected static $databaseTableName = 'chat_message';
/**
- * @see wcf\data\DatabaseObject::$databaseTableIndexName
+ * @see \wcf\data\DatabaseObject::$databaseTableIndexName
*/
protected static $databaseTableIndexName = 'messageID';
@@ -110,7 +110,8 @@ class ChatMessage extends \wcf\data\DatabaseObject {
'time' => $this->time,
'receiver' => $this->receiver,
'type' => $this->type,
- 'roomID' => $this->roomID
+ 'roomID' => $this->roomID,
+ 'messageID' => $this->messageID
);
if ($raw) return $array;
diff --git a/file/lib/data/chat/message/ChatMessageAction.class.php b/file/lib/data/chat/message/ChatMessageAction.class.php
index 4d6d4ff..fef87e4 100644
--- a/file/lib/data/chat/message/ChatMessageAction.class.php
+++ b/file/lib/data/chat/message/ChatMessageAction.class.php
@@ -12,7 +12,7 @@ namespace wcf\data\chat\message;
*/
class ChatMessageAction extends \wcf\data\AbstractDatabaseObjectAction {
/**
- * @see wcf\data\AbstractDatabaseObjectAction::$className
+ * @see \wcf\data\AbstractDatabaseObjectAction::$className
*/
protected $className = '\wcf\data\chat\message\ChatMessageEditor';
}
diff --git a/file/lib/data/chat/message/ChatMessageEditor.class.php b/file/lib/data/chat/message/ChatMessageEditor.class.php
index abad314..ee54251 100644
--- a/file/lib/data/chat/message/ChatMessageEditor.class.php
+++ b/file/lib/data/chat/message/ChatMessageEditor.class.php
@@ -12,7 +12,7 @@ namespace wcf\data\chat\message;
*/
class ChatMessageEditor extends \wcf\data\DatabaseObjectEditor {
/**
- * @see wcf\data\DatabaseObjectDecorator::$baseClass
+ * @see \wcf\data\DatabaseObjectDecorator::$baseClass
*/
protected static $baseClass = '\wcf\data\chat\message\ChatMessage';
diff --git a/file/lib/data/chat/message/ChatMessageList.class.php b/file/lib/data/chat/message/ChatMessageList.class.php
index 2f3e01e..bb3853e 100644
--- a/file/lib/data/chat/message/ChatMessageList.class.php
+++ b/file/lib/data/chat/message/ChatMessageList.class.php
@@ -12,7 +12,7 @@ namespace wcf\data\chat\message;
*/
class ChatMessageList extends \wcf\data\DatabaseObjectList {
/**
- * @see wcf\data\DatabaseObjectList::$className
+ * @see \wcf\data\DatabaseObjectList::$className
*/
public $className = 'wcf\data\chat\message\ChatMessage';
diff --git a/file/lib/data/chat/room/ChatRoom.class.php b/file/lib/data/chat/room/ChatRoom.class.php
index 9193bf0..bc29a31 100644
--- a/file/lib/data/chat/room/ChatRoom.class.php
+++ b/file/lib/data/chat/room/ChatRoom.class.php
@@ -1,6 +1,7 @@
getTitle();
+ }
+
+ /**
+ * Returns the number of users currently active in this room.
+ *
+ * @return integer
+ */
+ public function countUsers() {
+ $packageID = \wcf\system\package\PackageDependencyHandler::getPackageID('timwolla.wcf.chat');
+
+ $sql = "SELECT
+ count(*) as count
+ FROM
+ wcf".WCF_N."_user_storage
+ WHERE
+ field = 'roomID'
+ AND packageID = ".intval($packageID)."
+ AND fieldValue = ".intval($this->roomID);
+ $stmt = WCF::getDB()->prepareStatement($sql);
+ $stmt->execute();
+ $row = $stmt->fetchArray();
+
+ return $row['count'];
+ }
+
/**
* Loads the room cache.
*/
@@ -37,7 +68,7 @@ class ChatRoom extends \wcf\data\DatabaseObject implements \wcf\system\request\I
CacheHandler::getInstance()->addResource(
'chatrooms',
WCF_DIR.'cache/cache.chatrooms.php',
- 'wcf\system\cache\builder\ChatRoomCacheBuilder'
+ '\wcf\system\cache\builder\ChatRoomCacheBuilder'
);
self::$cache = CacheHandler::getInstance()->get('chatrooms');
}
@@ -46,10 +77,12 @@ class ChatRoom extends \wcf\data\DatabaseObject implements \wcf\system\request\I
}
/**
- * @see \wcf\data\chat\room\ChatRoom::getTitle();
+ * Returns the ID of this chat-room.
+ *
+ * @see \wcf\system\request\IRouteController
*/
- public function __toString() {
- return $this->getTitle();
+ public function getID() {
+ return $this->roomID;
}
/**
@@ -62,12 +95,39 @@ class ChatRoom extends \wcf\data\DatabaseObject implements \wcf\system\request\I
}
/**
- * Returns the ID of this chat-room.
- *
- * @see \wcf\system\request\RRouteHandler
+ * Returns the users that are currently active in this room.
+ *
+ * @return array<\wcf\data\user\User>
*/
- public function getID() {
- return $this->roomID;
+ public function getUsers() {
+ $packageID = \wcf\system\package\PackageDependencyHandler::getPackageID('timwolla.wcf.chat');
+
+ $sql = "SELECT
+ userID
+ FROM
+ wcf".WCF_N."_user_storage
+ WHERE
+ field = 'roomID'
+ AND packageID = ".intval($packageID)."
+ AND fieldValue = ".intval($this->roomID);
+ $stmt = WCF::getDB()->prepareStatement($sql);
+ $stmt->execute();
+ $userIDs = array();
+ while ($row = $stmt->fetchArray()) $userIDs[] = $row['userID'];
+
+ if (!count($userIDs)) return;
+
+ $sql = "SELECT
+ *
+ FROM
+ wcf".WCF_N."_user
+ WHERE
+ userID IN (".rtrim(str_repeat('?,', count($userIDs)), ',').")
+ ORDER BY
+ username ASC";
+ $stmt = WCF::getDB()->prepareStatement($sql);
+ $stmt->execute($userIDs);
+ return $stmt->fetchObjects('\wcf\data\user\User');
}
/**
@@ -76,6 +136,8 @@ class ChatRoom extends \wcf\data\DatabaseObject implements \wcf\system\request\I
* @return boolean
*/
public function canEnter() {
- return \wcf\system\chat\permissions\ChatPermissionHandler::getInstance()->getPermission($this, 'canEnter');
+ $ph = \wcf\system\chat\permission\ChatPermissionHandler::getInstance();
+
+ return $ph->getPermission($this, 'user.canEnter') || $ph->getPermission($this, 'mod.canAlwaysEnter');
}
}
diff --git a/file/lib/data/chat/room/ChatRoomAction.class.php b/file/lib/data/chat/room/ChatRoomAction.class.php
new file mode 100644
index 0000000..d83f994
--- /dev/null
+++ b/file/lib/data/chat/room/ChatRoomAction.class.php
@@ -0,0 +1,95 @@
+
+ * @package timwolla.wcf.chat
+ * @subpackage data.chat.room
+ */
+class ChatRoomAction extends \wcf\data\AbstractDatabaseObjectAction {
+ /**
+ * @see \wcf\data\AbstractDatabaseObjectAction::$className
+ */
+ protected $className = '\wcf\data\chat\room\ChatRoomEditor';
+
+ /**
+ * @see \wcf\data\AbstractDatabaseObjectAction::$permissionsDelete
+ */
+ protected $permissionsDelete = array('admin.content.chat.canDeleteRoom');
+
+ /**
+ * @see \wcf\data\AbstractDatabaseObjectAction::$permissionsUpdate
+ */
+ protected $permissionsUpdate = array('admin.content.chat.canEditRoom');
+
+ /**
+ * Fixes create to append new boards.
+ */
+ public function create() {
+ $room = parent::create();
+
+ WCF::getDB()->beginTransaction();
+ $sql = "SELECT max(position) as max
+ FROM wcf".WCF_N."_chat_room
+ FOR UPDATE";
+ $stmt = WCF::getDB()->prepareStatement($sql);
+ $stmt->execute();
+ $row = $stmt->fetchArray();
+
+ $sql = "UPDATE wcf".WCF_N."_chat_room
+ SET position = ".($row['max'] + 1)."
+ WHERE roomID = ?";
+ $stmt = WCF::getDB()->prepareStatement($sql);
+ $stmt->execute(array($room->roomID));
+ WCF::getDB()->commitTransaction();
+
+ return $room;
+ }
+
+ /**
+ * Validates parameters to update sorting.
+ */
+ public function validateUpdatePosition() {
+ // validate permissions
+ if (is_array($this->permissionsUpdate) && count($this->permissionsUpdate)) {
+ try {
+ WCF::getSession()->checkPermissions($this->permissionsUpdate);
+ }
+ catch (\wcf\system\exception\PermissionDeniedException $e) {
+ throw new ValidateActionException('Insufficient permissions');
+ }
+ }
+ else {
+ throw new ValidateActionException('Insufficient permissions');
+ }
+
+ if (!isset($this->parameters['data']['structure'])) {
+ throw new ValidateActionException('Missing parameter structure');
+ }
+ }
+
+ /**
+ * Updates sorting.
+ */
+ public function updatePosition() {
+ $roomList = new \wcf\data\chat\room\ChatRoomList();
+ $roomList->sqlOrderBy = "chat_room.position";
+ $roomList->sqlLimit = 0;
+ $roomList->readObjects();
+
+ $i = 0;
+ WCF::getDB()->beginTransaction();
+ foreach ($this->parameters['data']['structure'][0] as $roomID) {
+ $room = $roomList->search($roomID);
+ if ($room === null) continue;
+ $editor = new ChatRoomEditor($room);
+ $editor->update(array('position' => $i++));
+ }
+ WCF::getDB()->commitTransaction();
+ }
+}
diff --git a/file/lib/data/chat/room/ChatRoomEditor.class.php b/file/lib/data/chat/room/ChatRoomEditor.class.php
index 73e0a2a..43216c4 100644
--- a/file/lib/data/chat/room/ChatRoomEditor.class.php
+++ b/file/lib/data/chat/room/ChatRoomEditor.class.php
@@ -1,5 +1,6 @@
clearResource('chatrooms');
+ \wcf\system\cache\CacheHandler::getInstance()->clear(WCF_DIR.'cache', 'cache.chatrooms.php');
+ }
+
+ /**
+ * @see \wcf\data\DatabaseObjectEditor::deleteAll()
+ */
+ public static function deleteAll(array $objectIDs = array()) {
+ parent::deleteAll($objectIDs);
+ $packageID = \wcf\system\package\PackageDependencyHandler::getPackageID('timwolla.wcf.chat');
+
+ WCF::getDB()->beginTransaction();
+ foreach ($objectIDs as $objectID) {
+ \wcf\system\language\I18nHandler::getInstance()->remove('wcf.chat.room.title'.$objectID, $packageID);
+ \wcf\system\language\I18nHandler::getInstance()->remove('wcf.chat.room.topic'.$objectID, $packageID);
+ }
+ WCF::getDB()->commitTransaction();
+
+ return count($objectIDs);
}
}
diff --git a/file/lib/data/chat/room/ChatRoomList.class.php b/file/lib/data/chat/room/ChatRoomList.class.php
index 6a311d7..7e369be 100644
--- a/file/lib/data/chat/room/ChatRoomList.class.php
+++ b/file/lib/data/chat/room/ChatRoomList.class.php
@@ -12,7 +12,7 @@ namespace wcf\data\chat\room;
*/
class ChatRoomList extends \wcf\data\DatabaseObjectList {
/**
- * @see wcf\data\DatabaseObjectList::$className
+ * @see \wcf\data\DatabaseObjectList::$className
*/
public $className = 'wcf\data\chat\room\ChatRoom';
}
diff --git a/file/lib/form/ChatForm.class.php b/file/lib/form/ChatForm.class.php
index 32e9d54..554f5a3 100644
--- a/file/lib/form/ChatForm.class.php
+++ b/file/lib/form/ChatForm.class.php
@@ -1,15 +1,14 @@
* @package timwolla.wcf.chat
@@ -20,10 +19,14 @@ class ChatForm extends AbstractForm {
public $message = '';
public $room = null;
public $userData = array();
+
+ /**
+ * @see \wcf\page\AbstractForm::$useTemplate
+ */
public $useTemplate = false;
/**
- * @see \wcf\page\AbstractPage::readData()
+ * @see \wcf\page\IPage::readData()
*/
public function readData() {
$this->userData['color'] = \wcf\util\ChatUtil::readUserData('color');
@@ -37,17 +40,17 @@ class ChatForm extends AbstractForm {
}
/**
- * @see \wcf\form\AbstractForm::readFormParameters()
+ * @see \wcf\form\IForm::readFormParameters()
*/
public function readFormParameters() {
parent::readFormParameters();
- if (isset($_REQUEST['text'])) $this->message = StringUtil::trim($_REQUEST['text']);
+ if (isset($_REQUEST['text'])) $this->message = \wcf\util\MessageUtil::stripCrap(StringUtil::trim($_REQUEST['text']));
if (isset($_REQUEST['smilies'])) $this->enableSmilies = intval($_REQUEST['smilies']);
}
/**
- * @see \wcf\form\AbstractForm::validate()
+ * @see \wcf\form\IForm::validate()
*/
public function validate() {
parent::validate();
@@ -55,10 +58,14 @@ class ChatForm extends AbstractForm {
if ($this->message === '') {
throw new UserInputException('text');
}
+
+ if (strlen($this->message) > CHAT_MAX_LENGTH) {
+ throw new UserInputException('text', 'tooLong');
+ }
}
/**
- * @see \wcf\form\AbstractForm::save()
+ * @see \wcf\form\IForm::save()
*/
public function save() {
parent::save();
@@ -107,4 +114,12 @@ class ChatForm extends AbstractForm {
$this->saved();
}
+
+ /**
+ * @see \wcf\page\IPage::show()
+ */
+ public function show() {
+ header("HTTP/1.0 204 No Content");
+ parent::show();
+ }
}
diff --git a/file/lib/page/ChatMessagePage.class.php b/file/lib/page/ChatMessagePage.class.php
index 873e95a..4b1a5d9 100644
--- a/file/lib/page/ChatMessagePage.class.php
+++ b/file/lib/page/ChatMessagePage.class.php
@@ -22,14 +22,14 @@ class ChatMessagePage extends AbstractPage {
public $useTemplate = false;
/**
- * @see \wcf\page\Page::readData()
+ * @see \wcf\page\Page::readData()
*/
public function readData() {
parent::readData();
$this->readRoom();
$this->readMessages();
- $this->readUsers();
+ $this->users = $this->room->getUsers();
}
public function readMessages() {
@@ -54,34 +54,6 @@ class ChatMessagePage extends AbstractPage {
if (!$this->room->canEnter()) throw new \wcf\system\exception\PermissionDeniedException();
}
- public function readUsers() {
- $packageID = \wcf\system\package\PackageDependencyHandler::getPackageID('timwolla.wcf.chat');
-
- $sql = "SELECT
- userID
- FROM
- wcf".WCF_N."_user_storage
- WHERE
- field = 'roomID'
- AND packageID = ".intval($packageID)."
- AND fieldValue = ".intval($this->roomID);
- $stmt = WCF::getDB()->prepareStatement($sql);
- $stmt->execute();
- while ($row = $stmt->fetchArray()) $userIDs[] = $row['userID'];
-
- $sql = "SELECT
- *
- FROM
- wcf".WCF_N."_user
- WHERE
- userID IN (".rtrim(str_repeat('?,', count($userIDs)), ',').")
- ORDER BY
- username ASC";
- $stmt = WCF::getDB()->prepareStatement($sql);
- $stmt->execute($userIDs);
- $this->users = $stmt->fetchObjects('\wcf\data\user\User');
- }
-
/**
* @see \wcf\page\IPage::show()
*/
@@ -94,6 +66,11 @@ class ChatMessagePage extends AbstractPage {
parent::show();
@header('Content-type: application/json');
+ // enable gzip compression
+ if (HTTP_ENABLE_GZIP && HTTP_GZIP_LEVEL > 0 && HTTP_GZIP_LEVEL < 10 && !defined('HTTP_DISABLE_GZIP')) {
+ \wcf\util\HeaderUtil::compressOutput();
+ }
+
$json = array('users' => array(), 'messages' => array());
foreach ($this->messages as $message) {
diff --git a/file/lib/page/ChatPage.class.php b/file/lib/page/ChatPage.class.php
index d7dbe78..0023607 100644
--- a/file/lib/page/ChatPage.class.php
+++ b/file/lib/page/ChatPage.class.php
@@ -105,25 +105,24 @@ class ChatPage extends AbstractPage {
public function readParameters() {
parent::readParameters();
- if ($this->action == 'Message') {
- new ChatMessagePage();
- exit;
- }
- else if ($this->action == 'Log') {
- //TODO: Initialise LogPage
- exit;
- }
- else if ($this->action == 'RefreshRoomList') {
- new ChatRefreshRoomListPage();
- exit;
- }
- else if ($this->action == 'Send') {
- new \wcf\form\ChatForm();
- exit;
- }
- else if ($this->action == 'Copyright') {
- new ChatCopyrightPage();
- exit;
+ switch ($this->action) {
+ case 'Message':
+ new ChatMessagePage();
+ exit;
+ case 'Log':
+ exit;
+ case 'RefreshRoomList':
+ new ChatRefreshRoomListPage();
+ exit;
+ case 'Send':
+ new \wcf\form\ChatForm();
+ exit;
+ case 'Leave':
+ new \wcf\action\ChatLeaveAction();
+ exit;
+ case 'Copyright':
+ new ChatCopyrightPage();
+ exit;
}
if (isset($_REQUEST['id'])) $this->roomID = (int) $_REQUEST['id'];
diff --git a/file/lib/system/cache/builder/ChatPermissionCacheBuilder.class.php b/file/lib/system/cache/builder/ChatPermissionCacheBuilder.class.php
new file mode 100644
index 0000000..947b05b
--- /dev/null
+++ b/file/lib/system/cache/builder/ChatPermissionCacheBuilder.class.php
@@ -0,0 +1,44 @@
+
+ * @package timwolla.wcf.chat
+ * @subpackage system.cache.builder
+ */
+class ChatPermissionCacheBuilder implements ICacheBuilder {
+ /**
+ * @see wcf\system\cache\ICacheBuilder::getData()
+ */
+ public function getData(array $cacheResource) {
+ $data = array();
+ list(, $groupIDsStr) = explode('-', $cacheResource['cache']);
+ $groupIDs = explode(',', $groupIDsStr);
+
+ if (count($groupIDs)) {
+ $conditionBuilder = new \wcf\system\database\util\PreparedStatementConditionBuilder();
+ $conditionBuilder->add('acl_option.packageID IN (?)', array(\wcf\system\package\PackageDependencyHandler::getDependencies()));
+ $conditionBuilder->add('acl_option.objectTypeID = ?', array(\wcf\system\acl\ACLHandler::getInstance()->getObjectTypeID('timwolla.wcf.chat.room')));
+ $conditionBuilder->add('option_to_group.optionID = acl_option.optionID');
+ $conditionBuilder->add('option_to_group.groupID IN (?)', array($groupIDs));
+ $sql = "SELECT option_to_group.groupID, option_to_group.objectID AS roomID, option_to_group.optionValue,
+ acl_option.optionName AS permission
+ FROM wcf".WCF_N."_acl_option acl_option,
+ wcf".WCF_N."_acl_option_to_group option_to_group
+ ".$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 $data[$row['roomID']][$row['permission']] = $row['optionValue'] || $data[$row['roomID']][$row['permission']];
+ }
+ }
+
+ return $data;
+ }
+}
\ No newline at end of file
diff --git a/file/lib/system/cache/builder/ChatRoomCacheBuilder.class.php b/file/lib/system/cache/builder/ChatRoomCacheBuilder.class.php
index c21267f..985d823 100644
--- a/file/lib/system/cache/builder/ChatRoomCacheBuilder.class.php
+++ b/file/lib/system/cache/builder/ChatRoomCacheBuilder.class.php
@@ -12,7 +12,7 @@ namespace wcf\system\cache\builder;
*/
class ChatRoomCacheBuilder implements ICacheBuilder {
/**
- * @see wcf\system\cache\ICacheBuilder::getData()
+ * @see \wcf\system\cache\ICacheBuilder::getData()
*/
public function getData(array $cacheResource) {
// get all chat rooms
diff --git a/file/lib/system/chat/permissions/ChatPermissionHandler.class.php b/file/lib/system/chat/permission/ChatPermissionHandler.class.php
similarity index 70%
rename from file/lib/system/chat/permissions/ChatPermissionHandler.class.php
rename to file/lib/system/chat/permission/ChatPermissionHandler.class.php
index d525b9e..fc3e79e 100644
--- a/file/lib/system/chat/permissions/ChatPermissionHandler.class.php
+++ b/file/lib/system/chat/permission/ChatPermissionHandler.class.php
@@ -1,6 +1,7 @@
true,
+ 'user.canWrite' => true,
+ 'mod.canAlwaysEnter' => false,
+ 'mod.canAlwaysWrite' => false
+ );
/**
- * @see wcf\system\SingletonFactory::init()
+ * @see \wcf\system\SingletonFactory::init()
*/
protected function init() {
$packageID = PackageDependencyHandler::getPackageID('timwolla.wcf.chat');
$ush = \wcf\system\user\storage\UserStorageHandler::getInstance();
- // TODO: get groups permissions
+
+ // get groups permissions
+ $groups = implode(',', WCF::getUser()->getGroupIDs());
+ $groupsFileName = \wcf\util\StringUtil::getHash(implode('-', WCF::getUser()->getGroupIDs()));
+ CacheHandler::getInstance()->addResource('chatPermission-'.$groups, WCF_DIR.'cache/cache.chatPermission-'.$groupsFileName.'.php', 'wcf\system\cache\builder\ChatPermissionCacheBuilder');
+ $this->chatPermissions = CacheHandler::getInstance()->get('chatPermission-'.$groups);
// get user permissions
if (WCF::getUser()->userID) {
@@ -75,7 +87,20 @@ class ChatPermissionHandler extends \wcf\system\SingletonFactory {
* @return boolean
*/
public function getPermission(\wcf\data\chat\room\ChatRoom $room, $permission) {
- if (!isset($this->chatPermissions[$room->roomID][$permission])) return true;
+ if (!isset($this->chatPermissions[$room->roomID][$permission])) {
+ return isset(self::$defaults[$permission]) ? self::$defaults[$permission] : false;
+ }
return (boolean) $this->chatPermissions[$room->roomID][$permission];
}
+
+ /**
+ * Clears the cache.
+ */
+ public static function clearCache() {
+ $packageID = PackageDependencyHandler::getPackageID('timwolla.wcf.chat');
+ $ush = \wcf\system\user\storage\UserStorageHandler::getInstance();
+
+ $ush->resetAll('chatUserPermissions', $packageID);
+ \wcf\system\cache\CacheHandler::getInstance()->clear(WCF_DIR.'cache', 'cache.chatPermission-[a-f0-9]{40}.php');
+ }
}
\ No newline at end of file
diff --git a/file/lib/system/event/listener/ChatRouteListener.class.php b/file/lib/system/event/listener/ChatRouteListener.class.php
index 991bb35..7b6ee57 100644
--- a/file/lib/system/event/listener/ChatRouteListener.class.php
+++ b/file/lib/system/event/listener/ChatRouteListener.class.php
@@ -8,17 +8,17 @@ namespace wcf\system\event\listener;
* @copyright 2010-2012 Tim Düsterhus
* @license Creative Commons Attribution-NonCommercial-ShareAlike
* @package timwolla.wcf.chat
- * @subpackage system.event.listener
+ * @subpackage system.event.listener
*/
class ChatRouteListener implements \wcf\system\event\IEventListener {
/**
- * @see wcf\system\event\IEventListener::execute()
+ * @see \wcf\system\event\IEventListener::execute()
*/
public function execute($eventObj, $className, $eventName) {
$route = new \wcf\system\request\Route('chatAction');
$route->setSchema('/{controller}/{action}');
$route->setParameterOption('controller', null, 'Chat');
- $route->setParameterOption('action', null, '(Message|Log|Send|RefreshRoomList|Copyright)');
+ $route->setParameterOption('action', null, '(Message|Log|Send|RefreshRoomList|Copyright|Leave)');
$eventObj->addRoute($route);
}
}
diff --git a/file/lib/system/menu/page/ChatPageMenuItemProvider.class.php b/file/lib/system/menu/page/ChatPageMenuItemProvider.class.php
index 978c956..e38a136 100644
--- a/file/lib/system/menu/page/ChatPageMenuItemProvider.class.php
+++ b/file/lib/system/menu/page/ChatPageMenuItemProvider.class.php
@@ -17,7 +17,7 @@ class ChatPageMenuItemProvider extends DefaultPageMenuItemProvider {
/**
* Hides the button when there is no valid room
*
- * @see \wcf\system\menu\page\PageMenuItemProvider::isVisible()
+ * @see \wcf\system\menu\page\PageMenuItemProvider::isVisible()
*/
public function isVisible() {
// guests are not supported
@@ -43,7 +43,7 @@ class ChatPageMenuItemProvider extends DefaultPageMenuItemProvider {
/**
* Modifies the link to show the Link we would be redirect to.
*
- * @see \wcf\system\menu\page\PageMenuItemProvider::getLink()
+ * @see \wcf\system\menu\page\PageMenuItemProvider::getLink()
*/
public function getLink() {
return \wcf\system\request\LinkHandler::getInstance()->getLink('Chat', array(
diff --git a/file/lib/system/option/TimeIntervalOptionType.class.php b/file/lib/system/option/TimeIntervalOptionType.class.php
index 7f35c22..68421af 100644
--- a/file/lib/system/option/TimeIntervalOptionType.class.php
+++ b/file/lib/system/option/TimeIntervalOptionType.class.php
@@ -12,14 +12,14 @@ namespace wcf\system\option;
*/
class TimeIntervalOptionType extends TextOptionType {
/**
- * @see wcf\system\option\IOptionType::getData()
+ * @see \wcf\system\option\IOptionType::getData()
*/
public function getData(\wcf\data\option\Option $option, $newValue) {
return \wcf\util\ChatUtil::timeModifier($newValue);
}
/**
- * @see wcf\system\option\TextOptionType::getFormElement()
+ * @see \wcf\system\option\TextOptionType::getFormElement()
*/
public function getFormElement(\wcf\data\option\Option $option, $value) {
$tmp = (int) ($value / 60);
diff --git a/file/lib/util/ChatUtil.class.php b/file/lib/util/ChatUtil.class.php
index 2cfde2c..1be6657 100644
--- a/file/lib/util/ChatUtil.class.php
+++ b/file/lib/util/ChatUtil.class.php
@@ -67,7 +67,7 @@ class ChatUtil {
if ($data[WCF::getUser()->userID] === null) {
switch ($field) {
case 'color':
- $data[WCF::getUser()->userID] = array(1 => 0xFF0000, 2 => 0x00FF00);
+ $data[WCF::getUser()->userID] = array(1 => self::getRandomNumber(), 2 => self::getRandomNumber() * 0xFFFF);
break;
}
static::writeUserData(array($field => $data[WCF::getUser()->userID]));
@@ -79,6 +79,16 @@ class ChatUtil {
else return $data[WCF::getUser()->userID];
}
+ /**
+ * Returns a random number.
+ *
+ * @return integer
+ */
+ public static function /* int */ getRandomNumber() {
+ return 4; // chosen by a fair dice roll
+ // guaranteed to be random
+ }
+
/**
* Writes user data
*
diff --git a/file/style/timwolla.wcf.chat.scss b/file/style/timwolla.wcf.chat.scss
index 916840d..6445270 100644
--- a/file/style/timwolla.wcf.chat.scss
+++ b/file/style/timwolla.wcf.chat.scss
@@ -11,7 +11,7 @@
text-align: left;
}
-.sidebar {
+.wcf-sidebar {
margin-bottom: -20px !important;
overflow: auto;
padding: 0;
@@ -32,7 +32,7 @@
}
}
-#timsChatTopic, #smileyList, #timsChatOptions {
+#timsChatTopic, #smileyList {
padding: 5px;
}
@@ -43,7 +43,7 @@
padding-left: 7px !important;
}
-#smileyList .smilies, .smallButtons {
+#smileyList .smilies {
li {
display: inline;
margin: 5px 5px 0 0;
@@ -63,7 +63,9 @@
}
#timsChatOptions {
- display: inline-block;
+ > ul {
+ text-align: right;
+ }
}
#timsChatUserList {
@@ -100,7 +102,7 @@
}
}
- .unloaded {
+ &.unloaded {
opacity: 0.4;
}
}
@@ -178,7 +180,7 @@
}
}
- &.active .badge {
+ &.active .wcf-badge {
font-size: 65% !important;
color: #fff;
background-color: #369;
diff --git a/install.sql b/install.sql
index 21aa183..0a3219d 100644
--- a/install.sql
+++ b/install.sql
@@ -1,46 +1,47 @@
DROP TABLE IF EXISTS wcf1_chat_message;
CREATE TABLE wcf1_chat_message (
- messageID int(10) NOT NULL AUTO_INCREMENT,
- roomID int(10) NOT NULL,
- sender int(10) DEFAULT NULL,
- username varchar(255) DEFAULT NULL,
- receiver int(10) DEFAULT NULL,
- time int(10) NOT NULL,
- type tinyint(3) NOT NULL DEFAULT 1,
- message mediumtext NOT NULL,
- enableSmilies tinyint(1) NOT NULL DEFAULT 1,
- enableHTML tinyint(1) NOT NULL DEFAULT 0,
- color1 int(10) NOT NULL DEFAULT 0,
- color2 int(10) NOT NULL DEFAULT 0,
- PRIMARY KEY (messageID),
- KEY roomID (roomID),
- KEY sender (sender),
- KEY receiver (receiver)
+ messageID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ roomID INT(10) NOT NULL,
+ sender INT(10) DEFAULT NULL,
+ username VARCHAR(255) DEFAULT NULL,
+ receiver INT(10) DEFAULT NULL,
+ time INT(10) NOT NULL,
+ type TINYINT(3) NOT NULL DEFAULT 1,
+ message MEDIUMTEXT NOT NULL,
+ enableSmilies TINYINT(1) NOT NULL DEFAULT 1,
+ enableHTML TINYINT(1) NOT NULL DEFAULT 0,
+ color1 INT(10) NOT NULL DEFAULT 0,
+ color2 INT(10) NOT NULL DEFAULT 0,
+
+ KEY roomID (roomID),
+ KEY sender (sender),
+ KEY receiver (receiver)
);
DROP TABLE IF EXISTS wcf1_chat_room;
CREATE TABLE wcf1_chat_room (
- roomID int(10) NOT NULL AUTO_INCREMENT,
- title varchar(25) NOT NULL,
- topic varchar(255) NOT NULL,
- position int(10) NOT NULL DEFAULT 0,
- permanent tinyint(1) NOT NULL DEFAULT 1,
- owner int(10) DEFAULT NULL,
- PRIMARY KEY (roomID),
- KEY positionKey (position),
- KEY owner (owner)
+ roomID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ title VARCHAR(255) NOT NULL,
+ topic VARCHAR(255) NOT NULL,
+ position INT(10) NOT NULL DEFAULT 0,
+ permanent TINYINT(1) NOT NULL DEFAULT 1,
+ owner INT(10) DEFAULT NULL,
+
+ KEY positionKey (position),
+ KEY owner (owner)
);
DROP TABLE IF EXISTS wcf1_chat_room_suspension;
CREATE TABLE wcf1_chat_room_suspension (
- roomID int(10) NOT NULL,
- userID int(10) NOT NULL,
- type tinyint(3) NOT NULL,
- time int(10) NOT NULL,
- PRIMARY KEY (roomID, userID),
- KEY userID (userID),
- KEY type (type, time),
- KEY time (time)
+ userID INT(10) NOT NULL,
+ roomID INT(10) DEFAULT NULL,
+ type TINYINT(3) NOT NULL,
+ time INT(10) NOT NULL,
+
+ UNIQUE KEY main (userID, roomID),
+ KEY roomID (roomID),
+ KEY type (type, time),
+ KEY time (time)
);
ALTER TABLE wcf1_chat_message ADD FOREIGN KEY (receiver) REFERENCES wcf1_user (userID) ON DELETE CASCADE;
@@ -52,7 +53,7 @@ ALTER TABLE wcf1_chat_room ADD FOREIGN KEY (owner) REFERENCES wcf1_user (userID)
ALTER TABLE wcf1_chat_room_suspension ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE;
ALTER TABLE wcf1_chat_room_suspension ADD FOREIGN KEY (roomID) REFERENCES wcf1_chat_room (roomID) ON DELETE CASCADE;
-INSERT INTO wcf1_chat_room (title, topic, position) VALUES ('Testroom 1', 'Topic of Testroom 1', 1);
+INSERT INTO wcf1_chat_room (title, topic, position) VALUES ('wcf.chat.room.title1', 'wcf.chat.room.topic1', 1);
INSERT INTO wcf1_chat_room (title, topic, position) VALUES ('Testroom 2', 'Topic of Testroom 2', 2);
INSERT INTO wcf1_chat_room (title, topic, position) VALUES ('Testroom with a very long', 'The topic of this room is rather loing as well!', 3);
INSERT INTO wcf1_chat_room (title, topic, position) VALUES ('Room w/o topic', '', 4);
diff --git a/language/de.xml b/language/de.xml
index 5330609..768f216 100644
--- a/language/de.xml
+++ b/language/de.xml
@@ -1,5 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
@@ -14,8 +26,8 @@
-
-
+
+
@@ -24,11 +36,7 @@
-
-
-
-
-
+
@@ -55,4 +63,14 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/option.xml b/option.xml
index 13418c2..b491edd 100644
--- a/option.xml
+++ b/option.xml
@@ -49,7 +49,7 @@
1
7
-