Using alternate approach to deal with mentions
authorAlexander Ebert <ebert@woltlab.com>
Fri, 12 Aug 2016 13:45:50 +0000 (15:45 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Fri, 12 Aug 2016 13:45:56 +0000 (15:45 +0200)
Using a custom element has too many drawbacks and issues, all though
being far more elegant, it is just not worth it.

16 files changed:
com.woltlab.wcf/bbcode.xml
com.woltlab.wcf/objectType.xml
com.woltlab.wcf/templates/htmlNodeWoltlabMention.tpl [deleted file]
com.woltlab.wcf/templates/userBBCodeTag.tpl [new file with mode: 0644]
com.woltlab.wcf/templates/wysiwyg.tpl
wcfsetup/install/files/acp/templates/wysiwyg.tpl
wcfsetup/install/files/js/3rdParty/redactor2/plugins/WoltLabMention.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Redactor/Mention.js
wcfsetup/install/files/lib/system/bbcode/UserBBCode.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/html/input/filter/MessageHtmlInputFilter.class.php
wcfsetup/install/files/lib/system/html/input/node/HtmlInputNodeTextParser.class.php
wcfsetup/install/files/lib/system/html/input/node/HtmlInputNodeWoltlabMention.class.php [deleted file]
wcfsetup/install/files/lib/system/html/output/node/HtmlOutputNodeWoltlabMention.class.php [deleted file]
wcfsetup/install/files/lib/system/message/embedded/object/UserMessageEmbeddedObjectHandler.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/option/user/group/BBCodeSelectUserGroupOptionType.class.php
wcfsetup/install/files/lib/util/MessageUtil.class.php

index 994191ce16a6dfffe14e12da8a5cebf8c6b5a0cb..405afd377491a4666f5a2aaf388e08ca97a1d721 100644 (file)
                                </attribute>
                        </attributes>
                </bbcode>
+               
+               <bbcode name="user">
+                       <classname>wcf\system\bbcode\UserBBCode</classname>
+                       <attributes>
+                               <attribute name="0">
+                                       <validationpattern>^\d+$</validationpattern>
+                                       <required>1</required>
+                               </attribute>
+                       </attributes>
+               </bbcode>
        </import>
 </data>
index 7e8e7d82533d9208cc790334108a5e5ccba15242..238c692a73a40981571dbb24ce59358cfa39be8b 100644 (file)
                        <definitionname>com.woltlab.wcf.message.embeddedObject</definitionname>
                        <classname>wcf\system\message\embedded\object\MediaMessageEmbeddedObjectHandler</classname>
                </type>
+               <type>
+                       <name>com.woltlab.wcf.user</name>
+                       <definitionname>com.woltlab.wcf.message.embeddedObject</definitionname>
+                       <classname>wcf\system\message\embedded\object\UserMessageEmbeddedObjectHandler</classname>
+               </type>
                <!-- embedded object handlers -->
                
                <type>
diff --git a/com.woltlab.wcf/templates/htmlNodeWoltlabMention.tpl b/com.woltlab.wcf/templates/htmlNodeWoltlabMention.tpl
deleted file mode 100644 (file)
index ac2b3d7..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-{if $userProfile === null}
-       {* user no longer exists, use plain output rather than using a broken link *}
-       @{$username}
-{else}
-       {* non-breaking space below to prevent wrapping of user avatar and username *}
-       <a href="{link controller='User' object=$userProfile->getDecoratedObject()}{/link}">{@$userProfile->getAvatar()->getImageTag(16)}&nbsp;{$userProfile->username}</a>
-{/if}
\ No newline at end of file
diff --git a/com.woltlab.wcf/templates/userBBCodeTag.tpl b/com.woltlab.wcf/templates/userBBCodeTag.tpl
new file mode 100644 (file)
index 0000000..540243b
--- /dev/null
@@ -0,0 +1,7 @@
+{if $userProfile === null}
+       {* user no longer exists, use plain output rather than using a broken link *}
+       @{$username}
+{else}
+       {* non-breaking space below to prevent wrapping of user avatar and username *}
+       <a href="{link controller='User' object=$userProfile->getDecoratedObject()}{/link}">{@$userProfile->getAvatar()->getImageTag(16)}&nbsp;{$userProfile->username}</a>
+{/if}
index ac556360d4b19c016be00f57401931f2e10a719e..00ed92391cfd967b81b5968b41285faa34ad5cbc 100644 (file)
@@ -1,25 +1,3 @@
-<style>
-       woltlab-mention {
-               background-color: rgb(241, 246, 251);
-               border: 1px solid rgb(176, 200, 224);
-               border-radius: 2px;
-               display: inline-block;
-               margin: 0 3px;
-               padding: 0 2px;
-       }
-       
-       woltlab-mention::before {
-               color: rgb(125, 130, 135);
-               content: "@";
-               padding-right: 2px;
-       }
-       
-       woltlab-mention::after {
-               color: rgb(44, 62, 80);
-               content: attr(data-username);
-       }
-</style>
-
 <script data-relocate="true">
        head.load([
                {if ENABLE_DEBUG_MODE}
index 973115b20dd799336e6c3520f44413940dad75c6..00ed92391cfd967b81b5968b41285faa34ad5cbc 100644 (file)
@@ -1,13 +1,3 @@
-<style>
-       woltlab-mention {
-               background-color: rgb(240, 248, 255);
-               border: 1px solid rgb(52, 152, 219);
-               display: inline-block;
-               margin: 0 3px;
-               padding: 0 2px;
-       }
-</style>
-
 <script data-relocate="true">
        head.load([
                {if ENABLE_DEBUG_MODE}
index 6bb45fbcc223f53a1f38c14c02f370e4e1aacdac..73595dcbc421fd61d477b55fe2f26ac6bf14f641 100644 (file)
@@ -3,8 +3,6 @@ $.Redactor.prototype.WoltLabMention = function() {
        
        return {
                init: function() {
-                       //var WoltLabMention = document.registerElement('woltlab-mention');
-                       
                        require(['WoltLabSuite/Core/Ui/Redactor/Mention'], (function(UiRedactorMention) {
                                new UiRedactorMention(this);
                        }).bind(this));
index a86ac9a55948ec481f9062cf6b802807e2aa970f..11cc32de5b9cab5faafeaa59f91fc292ee6738d3 100644 (file)
@@ -143,16 +143,8 @@ define(['Ajax', 'Environment', 'EventHandler', 'Ui/Alignment'], function(Ajax, E
                        range.deleteContents();
                        range.collapse(true);
                        
-                       var mention = elCreate('woltlab-mention');
-                       elAttr(mention, 'contenteditable', 'false');
-                       elData(mention, 'user-id', elData(item, 'user-id'));
-                       elData(mention, 'username', elData(item, 'username'));
-                       
-                       // U+200C = zero width non-joiner
-                       var text = document.createTextNode('\u200c');
-                       
+                       var text = document.createTextNode('@' + elData(item, 'username') + '\u00A0');
                        range.insertNode(text);
-                       range.insertNode(mention);
                        
                        newRange = document.createRange();
                        newRange.selectNode(text);
diff --git a/wcfsetup/install/files/lib/system/bbcode/UserBBCode.class.php b/wcfsetup/install/files/lib/system/bbcode/UserBBCode.class.php
new file mode 100644 (file)
index 0000000..d8bc47b
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+namespace wcf\system\bbcode;
+use wcf\data\user\UserProfile;
+use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
+use wcf\system\WCF;
+
+/**
+ * Parses the [user] bbcode tag.
+ *
+ * @author      Alexander Ebert
+ * @copyright   2001-2016 WoltLab GmbH
+ * @license     GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package     WoltLabSuite\Core\System\Bbcode
+ * @since       3.0
+ */
+class UserBBCode extends AbstractBBCode {
+       /**
+        * @inheritDoc
+        */
+       public function getParsedTag(array $openingTag, $content, array $closingTag, BBCodeParser $parser) {
+               $userID = (!empty($openingTag['attributes'][0])) ? intval($openingTag['attributes'][0]) : 0;
+               if (!$userID) {
+                       return "[user]{$content}[/user]";
+               }
+               
+               /** @var UserProfile $userProfile */
+               $userProfile = MessageEmbeddedObjectManager::getInstance()->getObject('com.woltlab.wcf.user', $userID);
+               if ($userProfile === null) {
+                       return '@'.$content;
+               }
+               
+               return WCF::getTPL()->fetch('userBBCodeTag', 'wcf', [
+                       'username' => $content,
+                       'userProfile' => $userProfile
+               ], true);
+       }
+}
index 11a3efacd95b9b4792f726927034fa751ee3fbda..04938470aa97861bfa9cc8da66c9d7429684191d 100644 (file)
@@ -67,12 +67,6 @@ class MessageHtmlInputFilter implements IHtmlInputFilter {
                $definition->addAttribute('img', 'data-media-id', 'Number');
                $definition->addAttribute('img', 'data-media-size', new \HTMLPurifier_AttrDef_Enum(['small', 'medium', 'large', 'original']));
                
-               // mention
-               $definition->addElement('woltlab-mention', 'Inline', 'Inline', '', [
-                       'data-user-id' => 'Number',
-                       'data-username' => 'Text'
-               ]);
-               
                // spoiler
                $definition->addElement('woltlab-spoiler', 'Block', 'Flow', '', [
                        'data-label' => 'Text'
index f7ee2238fce9a78ed86967fff2effe730142737d..d7d2b0372f7dec6bdeaf238154227798beece21a 100644 (file)
@@ -7,6 +7,7 @@ use wcf\system\bbcode\BBCodeHandler;
 use wcf\system\bbcode\HtmlBBCodeParser;
 use wcf\system\database\util\PreparedStatementConditionBuilder;
 use wcf\system\WCF;
+use wcf\util\JSON;
 use wcf\util\StringUtil;
 
 /**
@@ -294,9 +295,10 @@ class HtmlInputNodeTextParser {
                                }
                                
                                if ($pos !== false) {
-                                       $element = $text->ownerDocument->createElement('woltlab-mention');
-                                       $element->setAttribute('data-user-id', $userID);
-                                       $element->setAttribute('data-username', $username);
+                                       $element = $text->ownerDocument->createElement('woltlab-metacode');
+                                       $element->setAttribute('data-name', 'user');
+                                       $element->setAttribute('data-attributes', base64_encode(JSON::encode([$userID])));
+                                       $element->appendChild($text->ownerDocument->createTextNode($username));
                                        
                                        $marker = $this->addReplacement($text, $element);
                                        
diff --git a/wcfsetup/install/files/lib/system/html/input/node/HtmlInputNodeWoltlabMention.class.php b/wcfsetup/install/files/lib/system/html/input/node/HtmlInputNodeWoltlabMention.class.php
deleted file mode 100644 (file)
index 91e37d8..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-<?php
-namespace wcf\system\html\input\node;
-use wcf\system\html\node\AbstractHtmlNodeProcessor;
-
-/**
- * Processes `<woltlab-mention>`.
- * 
- * @author      Alexander Ebert
- * @copyright   2001-2016 WoltLab GmbH
- * @license     GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package     WoltLabSuite\Core\System\Html\Input\Node
- * @since       3.0
- */
-class HtmlInputNodeWoltlabMention extends AbstractHtmlInputNode {
-       /**
-        * @inheritDoc
-        */
-       protected $tagName = 'woltlab-mention';
-       
-       /**
-        * @inheritDoc
-        */
-       public function isAllowed(AbstractHtmlNodeProcessor $htmlNodeProcessor) {
-               // mentions are always allowed
-               return [];
-       }
-       
-       /**
-        * @inheritDoc
-        */
-       public function process(array $elements, AbstractHtmlNodeProcessor $htmlNodeProcessor) {
-               // TODO
-               
-               $userIds = [];
-               
-               /** @var \DOMElement $mention */
-               foreach ($elements as $mention) {
-                       $userId = intval($mention->getAttribute('data-user-id'));
-                       if ($userId) {
-                               $userIds[] = $userId;
-                       }
-               }
-               
-               if (!empty($userIds)) {
-                       
-               }
-       }
-}
diff --git a/wcfsetup/install/files/lib/system/html/output/node/HtmlOutputNodeWoltlabMention.class.php b/wcfsetup/install/files/lib/system/html/output/node/HtmlOutputNodeWoltlabMention.class.php
deleted file mode 100644 (file)
index d580e7a..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-<?php
-namespace wcf\system\html\output\node;
-use wcf\data\user\UserProfile;
-use wcf\system\cache\runtime\UserProfileRuntimeCache;
-use wcf\system\html\node\AbstractHtmlNodeProcessor;
-use wcf\system\WCF;
-use wcf\util\DOMUtil;
-use wcf\util\StringUtil;
-
-/**
- * Processes user mentions.
- * 
- * @author      Alexander Ebert
- * @copyright   2001-2016 WoltLab GmbH
- * @license     GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @package     WoltLabSuite\Core\System\Html\Output\Node
- * @since       3.0
- */
-class HtmlOutputNodeWoltlabMention extends AbstractHtmlOutputNode {
-       /**
-        * @inheritDoc
-        */
-       protected $tagName = 'woltlab-mention';
-       
-       /**
-        * @var UserProfile[]
-        */
-       protected $userProfiles;
-       
-       /**
-        * @inheritDoc
-        */
-       public function process(array $elements, AbstractHtmlNodeProcessor $htmlNodeProcessor) {
-               if ($this->outputType === 'text/html' || $this->outputType === 'text/simplified-html') {
-                       $this->userProfiles = [];
-                       
-                       $userIds = [];
-                       /** @var \DOMElement $element */
-                       foreach ($elements as $element) {
-                               $userId = intval($element->getAttribute('data-user-id'));
-                               $username = StringUtil::trim($element->getAttribute('data-username'));
-                               
-                               if ($userId === 0 || $username === '') {
-                                       DOMUtil::removeNode($element);
-                                       continue;
-                               }
-                               
-                               $userIds[] = $userId;
-                               $nodeIdentifier = StringUtil::getRandomID();
-                               $htmlNodeProcessor->addNodeData($this, $nodeIdentifier, ['userId' => $userId, 'username' => $username]);
-                               
-                               $htmlNodeProcessor->renameTag($element, 'wcfNode-' . $nodeIdentifier);
-                       }
-                       
-                       if (!empty($userIds)) {
-                               $this->userProfiles = UserProfileRuntimeCache::getInstance()->getObjects($userIds);
-                       }
-               }
-               else if ($this->outputType === 'text/plain') {
-                       /** @var \DOMElement $element */
-                       foreach ($elements as $element) {
-                               $htmlNodeProcessor->replaceElementWithText($element, '@' . $element->getAttribute('data-username'), false);
-                       }
-               }
-       }
-       
-       /**
-        * @inheritDoc
-        */
-       public function replaceTag(array $data) {
-               WCF::getTPL()->assign([
-                       'username' => $data['username'],
-                       'userId' => $data['userId'],
-                       'userProfile' => $this->userProfiles[$data['userId']]
-               ]);
-               
-               return WCF::getTPL()->fetch('htmlNodeWoltlabMention');
-       }
-}
diff --git a/wcfsetup/install/files/lib/system/message/embedded/object/UserMessageEmbeddedObjectHandler.class.php b/wcfsetup/install/files/lib/system/message/embedded/object/UserMessageEmbeddedObjectHandler.class.php
new file mode 100644 (file)
index 0000000..4873dcd
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+namespace wcf\system\message\embedded\object;
+use wcf\system\cache\runtime\UserProfileRuntimeCache;
+use wcf\system\html\input\HtmlInputProcessor;
+
+/**
+ * Parses embedded users.
+ *
+ * @author     Alexander Ebert
+ * @copyright  2001-2016 WoltLab GmbH
+ * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package    WoltLabSuite\Core\System\Message\Embedded\Object
+ */
+class UserMessageEmbeddedObjectHandler extends AbstractMessageEmbeddedObjectHandler {
+       /**
+        * @inheritDoc
+        */
+       public function parse(HtmlInputProcessor $htmlInputProcessor, array $embeddedData) {
+               $objectIDs = [];
+               if (!empty($embeddedData['user'])) {
+                       for ($i = 0, $length = count($embeddedData['user']); $i < $length; $i++) {
+                               $objectIDs[] = intval($embeddedData['user'][$i][0]);
+                       }
+               }
+               
+               return array_unique($objectIDs);
+       }
+       
+       /**
+        * @inheritDoc
+        */
+       public function loadObjects(array $objectIDs) {
+               return UserProfileRuntimeCache::getInstance()->getObjects($objectIDs);
+       }
+}
index b533ea903d87f4615a97e4922737676a2fa44206..900ccbecd8bf06ec36942814fa072be258e4e3c5 100644 (file)
@@ -26,7 +26,7 @@ class BBCodeSelectUserGroupOptionType extends AbstractOptionType implements IUse
         * list of bbcode tags that are always available
         * @var string[]
         */
-       protected static $alwaysAvailable = ['align', 'attach', 'b', 'code', 'i', 'list', 'quote', 's', 'sub', 'sup', 'table', 'td', 'tr', 'tt', 'u', 'wsm', 'wsmg', 'wsp'];
+       protected static $alwaysAvailable = ['align', 'attach', 'b', 'code', 'i', 'list', 'quote', 's', 'sub', 'sup', 'table', 'td', 'tr', 'tt', 'u', 'user', 'wsm', 'wsmg', 'wsp'];
        
        /**
         * @inheritDoc
index dac872fcb5ccbcb6bc546ad1ddecd308a73c81bf..e056bea12c8ff4253dcddfcdf74ffa1600cfccc8 100644 (file)
@@ -46,15 +46,19 @@ class MessageUtil {
        public static function getMentionedUsers(HtmlInputProcessor $htmlInputProcessor) {
                $usernames = [];
                
-               $elements = $htmlInputProcessor->getHtmlInputNodeProcessor()->getDocument()->getElementsByTagName('woltlab-mention');
+               $elements = $htmlInputProcessor->getHtmlInputNodeProcessor()->getDocument()->getElementsByTagName('woltlab-metacode');
                /** @var \DOMElement $element */
                foreach ($elements as $element) {
+                       if ($element->getAttribute('data-name') != 'user') {
+                               continue;
+                       }
+                       
                        if (DOMUtil::hasParent($element, 'blockquote')) {
                                // ignore mentions within quotes
                                continue;
                        }
                        
-                       $usernames[] = $element->getAttribute('data-username');
+                       $usernames[] = $element->textContent;
                }
                
                return $usernames;