<classname><![CDATA[wcf\system\captcha\CaptchaQuestionHandler]]></classname>
</type>
<!-- captcha types -->
+
+ <!-- embedded object handlers -->
+ <type>
+ <name>com.woltlab.wcf.quote</name>
+ <definitionname>com.woltlab.wcf.message.embeddedObject</definitionname>
+ <classname><![CDATA[wcf\system\message\embedded\object\QuoteMessageEmbeddedObjectHandler]]></classname>
+ </type>
+ <type>
+ <name>com.woltlab.wcf.attachment</name>
+ <definitionname>com.woltlab.wcf.message.embeddedObject</definitionname>
+ <classname><![CDATA[wcf\system\message\embedded\object\AttachmentMessageEmbeddedObjectHandler]]></classname>
+ </type>
+ <!-- embedded object handlers -->
</import>
</data>
<name>com.woltlab.wcf.captcha</name>
<interfacename><![CDATA[wcf\system\captcha\ICaptchaHandler]]></interfacename>
</definition>
+
+ <definition>
+ <name>com.woltlab.wcf.message.embeddedObject</name>
+ <interfacename><![CDATA[wcf\system\message\embedded\object\IMessageEmbeddedObjectHandler]]></interfacename>
+ </definition>
+
+ <definition>
+ <name>com.woltlab.wcf.message</name>
+ </definition>
</import>
</data>
-<blockquote class="container containerPadding quoteBox"{if $quoteLink} cite="{$quoteLink}"{/if}>
- {if $quoteAuthor}
- <header>
- <h3>
- {if $quoteLink}
- <a href="{@$quoteLink}"{if $isExternalQuoteLink} class="externalURL"{if EXTERNAL_LINK_REL_NOFOLLOW} rel="nofollow"{/if}{if EXTERNAL_LINK_TARGET_BLANK} target="_blank"{/if}{/if}>{lang}wcf.bbcode.quote.title{/lang}</a>
- {else}
- {lang}wcf.bbcode.quote.title{/lang}
- {/if}
- </h3>
- </header>
+<blockquote class="quoteBox"{if $quoteLink} cite="{$quoteLink}"{/if}>
+ {if $quoteAuthorObject}
+ <div class="quoteAuthorAvatar"><a href="{link controller='User' object=$quoteAuthorObject}{/link}" class="userLink framed" data-user-id="{@$quoteAuthorObject->userID}">{@$quoteAuthorObject->getAvatar()->getImageTag(64)}</a></div>
{/if}
- <div>
- {@$content}
+ <div class="container containerPadding">
+ {if $quoteAuthor}
+ <header>
+ <h3>
+ {if $quoteLink}
+ <a href="{@$quoteLink}"{if $isExternalQuoteLink} class="externalURL"{if EXTERNAL_LINK_REL_NOFOLLOW} rel="nofollow"{/if}{if EXTERNAL_LINK_TARGET_BLANK} target="_blank"{/if}{/if}>{lang}wcf.bbcode.quote.title{/lang}</a>
+ {else}
+ {lang}wcf.bbcode.quote.title{/lang}
+ {/if}
+ </h3>
+ </header>
+ {/if}
+
+ <div>
+ {@$content}
+ </div>
</div>
</blockquote>
\ No newline at end of file
$this->objectType = ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.attachment.objectType', $objectType);
$this->getConditionBuilder()->add('attachment.objectTypeID = ?', array($this->objectType->objectTypeID));
+
+ $this->getConditionBuilder()->add('(SELECT embeddedObjectID FROM wcf'.WCF_N.'_message_embedded_object WHERE messageObjectTypeID = ? AND messageID = attachment.objectID AND embeddedObjectTypeID = ? AND embeddedObjectID = attachment.attachmentID) IS NULL', array(
+ ObjectTypeCache::getInstance()->getObjectTypeIDByName('com.woltlab.wcf.message', $objectType),
+ ObjectTypeCache::getInstance()->getObjectTypeIDByName('com.woltlab.wcf.message.embeddedObject', 'com.woltlab.wcf.attachment')
+ ));
}
/**
<?php
namespace wcf\data\bbcode;
-use wcf\data\attachment\GroupedAttachmentList;
-use wcf\data\object\type\ObjectTypeCache;
-use wcf\system\bbcode\AttachmentBBCode;
use wcf\system\bbcode\MessageParser;
use wcf\system\bbcode\PreParser;
use wcf\system\exception\UserInputException;
+use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
use wcf\system\WCF;
use wcf\util\ArrayUtil;
use wcf\util\StringUtil;
}
}
- // get attachments
- if (!empty($this->parameters['attachmentObjectType'])) {
- $attachmentList = new GroupedAttachmentList($this->parameters['attachmentObjectType']);
- if (!empty($this->parameters['attachmentObjectID'])) {
- $attachmentList->getConditionBuilder()->add('attachment.objectID = ?', array($this->parameters['attachmentObjectID']));
- AttachmentBBCode::setObjectID($this->parameters['attachmentObjectID']);
-
- $objectType = ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.attachment.objectType', $this->parameters['attachmentObjectType']);
- $processor = $objectType->getProcessor();
- if (!$processor->canDownload($this->parameters['attachmentObjectID']) && !$processor->canViewPreview($this->parameters['attachmentObjectID'])) {
- if (WCF::getUser()->userID) {
- $attachmentList->getConditionBuilder()->add('attachment.userID = ?', array(WCF::getUser()->userID));
- }
- else {
- $attachmentList->getConditionBuilder()->add('attachment.userID IS NULL');
- }
- }
- }
- else {
- $attachmentList->getConditionBuilder()->add('attachment.tmpHash = ?', array($this->parameters['tmpHash']));
-
- if (WCF::getUser()->userID) {
- $attachmentList->getConditionBuilder()->add('attachment.userID = ?', array(WCF::getUser()->userID));
- }
- else {
- $attachmentList->getConditionBuilder()->add('attachment.userID IS NULL');
- }
- }
-
- $attachmentList->readObjects();
- AttachmentBBCode::setAttachmentList($attachmentList);
- }
-
// get message
$message = StringUtil::trim($this->parameters['data']['message']);
+ // get embedded objects
+ MessageEmbeddedObjectManager::getInstance()->parseTemporaryMessage($message);
+
// parse URLs
if ($preParse && $enableBBCodes) {
if ($allowedBBCodesPermission) {
* @category Community Framework
*/
abstract class AbstractAttachmentObjectType implements IAttachmentObjectType {
+ /**
+ * cached objects
+ * @var array<\wcf\data\DatabaseObject>
+ */
+ protected $cachedObjects = array();
+
/**
* @see \wcf\system\attachment\IAttachmentObjectType::getMaxSize()
*/
* @see \wcf\system\attachment\IAttachmentObjectType::getObject()
*/
public function getObject($objectID) {
+ if (isset($this->cachedObjects[$objectID])) return $this->cachedObjects[$objectID];
+
return null;
}
+ /**
+ * @see \wcf\system\attachment\IAttachmentObjectType::setCachedObjects()
+ */
+ public function setCachedObjects(array $objects) {
+ foreach ($objects as $id => $object) {
+ $this->cachedObjects[$id] = $object;
+ }
+ }
+
/**
* @see \wcf\system\attachment\IAttachmentObjectType::getObject()
*/
public function cacheObjects(array $objectIDs) {}
+
+ /**
+ * @see \wcf\system\attachment\IAttachmentObjectType::setPermissions()
+ */
+ public function setPermissions(array $attachments) {
+ foreach ($attachments as $attachment) {
+ $attachment->setPermissions(array(
+ 'canDownload' => $this->canDownload($attachment->objectID),
+ 'canViewPreview' => $this->canViewPreview($attachment->objectID)
+ ));
+ }
+ }
}
* @param array<integer> $objectIDs
*/
public function cacheObjects(array $objectIDs);
+
+ /**
+ * Loads the permissions for given attachments.
+ *
+ * @param array<\wcf\data\attachment\Attachment> $attachments
+ */
+ public function setPermissions(array $attachments);
}
use wcf\data\attachment\GroupedAttachmentList;
use wcf\system\request\LinkHandler;
use wcf\util\StringUtil;
+use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
/**
* Parses the [attach] bbcode tag.
/**
* list of attachments
* @var \wcf\data\attachment\GroupedAttachmentList
+ * @deprecated
*/
protected static $attachmentList = null;
/**
* active object id
* @var integer
+ * @deprecated
*/
protected static $objectID = 0;
$attachmentID = $openingTag['attributes'][0];
}
- // get attachment for active object
- $attachments = array();
- if (self::$attachmentList !== null) {
- $attachments = self::$attachmentList->getGroupedObjects(self::$objectID);
+ // get embedded object
+ $attachment = MessageEmbeddedObjectManager::getInstance()->getObject('com.woltlab.wcf.attachment', $attachmentID);
+ if ($attachment === null) {
+ if (self::$attachmentList !== null) {
+ $attachments = self::$attachmentList->getGroupedObjects(self::$objectID);
+ if (isset($attachments[$attachmentID])) {
+ $attachment = $attachments[$attachmentID];
+
+ // mark attachment as embedded
+ $attachment->markAsEmbedded();
+ }
+ }
}
- if (isset($attachments[$attachmentID])) {
- $attachment = $attachments[$attachmentID];
-
- // mark attachment as embedded
- $attachment->markAsEmbedded();
-
+ if ($attachment !== null) {
if ($attachment->showAsImage() && $parser->getOutputType() == 'text/html') {
// image
$linkParameters = array(
* Sets the attachment list.
*
* @param \wcf\data\attachment\GroupedAttachmentList $attachments
+ * @deprecated
*/
public static function setAttachmentList(GroupedAttachmentList $attachmentList) {
self::$attachmentList = $attachmentList;
* Sets the active object id.
*
* @param integer $objectID
+ * @deprecated
*/
public static function setObjectID($objectID) {
self::$objectID = $objectID;
use wcf\system\application\ApplicationHandler;
use wcf\system\request\RouteHandler;
use wcf\system\WCF;
+use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
/**
* Parses the [quote] bbcode tag.
if (!$externalQuoteLink) {
$quoteLink = preg_replace('~^https?://~', RouteHandler::getProtocol(), $quoteLink);
}
+ $quoteAuthor = (!empty($openingTag['attributes'][0]) ? $openingTag['attributes'][0] : '');
+ $quoteAuthorObject = null;
+ if ($quoteAuthor && !$externalQuoteLink) {
+ $quoteAuthorLC = mb_strtolower($quoteAuthor);
+ foreach (MessageEmbeddedObjectManager::getInstance()->getObjects('com.woltlab.wcf.quote') as $user) {
+ if (mb_strtolower($user->username) == $quoteAuthorLC) {
+ $quoteAuthorObject = $user;
+ break;
+ }
+ }
+ }
WCF::getTPL()->assign(array(
'content' => $content,
'quoteLink' => $quoteLink,
- 'quoteAuthor' => (!empty($openingTag['attributes'][0]) ? $openingTag['attributes'][0] : ''),
+ 'quoteAuthor' => $quoteAuthor,
+ 'quoteAuthorObject' => $quoteAuthorObject,
'isExternalQuoteLink' => $externalQuoteLink
));
return WCF::getTPL()->fetch('quoteBBCodeTag');
--- /dev/null
+<?php
+namespace wcf\system\message\embedded\object;
+use wcf\data\DatabaseObjectDecorator;
+use wcf\util\ArrayUtil;
+
+/**
+ * Provides default implementations for message embedded object handlers.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2014 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.message.embedded.object
+ * @category Community Framework
+ */
+abstract class AbstractMessageEmbeddedObjectHandler extends DatabaseObjectDecorator implements IMessageEmbeddedObjectHandler {
+ /**
+ * @see \wcf\data\DatabaseObjectDecorator::$baseClass
+ */
+ protected static $baseClass = 'wcf\data\object\type\ObjectType';
+
+ /**
+ * Parses given message for specific bbcode parameters.
+ *
+ * @param string $message
+ * @param string $bbcode bbcode name
+ * @return array
+ */
+ public static function getTextParameters($message, $bbcode) {
+ if (preg_match_all('~\['.$bbcode.'\](.*?)\[/'.$bbcode.'\]~i', $message, $matches)) {
+ $results = ArrayUtil::trim($matches[1]);
+ $results = array_unique($results);
+
+ return $results;
+ }
+
+ return array();
+ }
+
+ /**
+ * Parses given message for specific bbcode parameters.
+ *
+ * @param string $message
+ * @param string $bbcode bbcode name
+ * @return array
+ */
+ public static function getFirstParameters($message, $bbcode) {
+ $pattern = '~\['.$bbcode.'=
+ (?:\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'|([^,\]]*))
+ (?:,(?:\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'|[^,\]]*))*
+ \]~ix';
+
+ if (preg_match_all($pattern, $message, $matches)) {
+ $results = ArrayUtil::trim($matches[1]);
+ $results = array_merge($results, ArrayUtil::trim($matches[2]));
+ $results = array_unique($results);
+
+ return $results;
+ }
+
+ return array();
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\message\embedded\object;
+use wcf\data\attachment\AttachmentList;
+use wcf\util\ArrayUtil;
+use wcf\data\object\type\ObjectTypeCache;
+
+/**
+ * IMessageEmbeddedObjectHandler implementation for attachments.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2014 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.message.embedded.object
+ * @category Community Framework
+ */
+class AttachmentMessageEmbeddedObjectHandler extends AbstractMessageEmbeddedObjectHandler {
+ /**
+ * @see \wcf\system\message\embedded\object\IMessageEmbeddedObjectHandler::parseMessage()
+ */
+ public function parseMessage($message) {
+ $parsedAttachmentIDs = array_unique(ArrayUtil::toIntegerArray(array_merge(self::getFirstParameters($message, 'attach'), self::getTextParameters($message, 'attach'))));
+ if (!empty($parsedAttachmentIDs)) {
+ $attachmentIDs = array();
+ foreach ($parsedAttachmentIDs as $parsedAttachmentID) {
+ if ($parsedAttachmentID) $attachmentIDs[] = $parsedAttachmentID;
+ }
+
+ $attachmentList = new AttachmentList();
+ $attachmentList->getConditionBuilder()->add("attachment.attachmentID IN (?)", array($attachmentIDs));
+ $attachmentList->readObjectIDs();
+ return $attachmentList->getObjectIDs();
+ }
+
+ return false;
+ }
+
+ /**
+ * @see \wcf\system\message\embedded\object\IMessageEmbeddedObjectHandler::loadObjects()
+ */
+ public function loadObjects(array $objectIDs) {
+ $attachmentList = new AttachmentList();
+ $attachmentList->setObjectIDs($objectIDs);
+ $attachmentList->readObjects();
+
+ // group attachments by object type
+ $groupedAttachments = array();
+ foreach ($attachmentList->getObjects() as $attachment) {
+ if (!isset($groupedAttachments[$attachment->objectTypeID])) $groupedAttachments[$attachment->objectTypeID] = array();
+ $groupedAttachments[$attachment->objectTypeID][] = $attachment;
+ }
+
+ // check permissions
+ foreach ($groupedAttachments as $objectTypeID => $attachments) {
+ $processor = ObjectTypeCache::getInstance()->getObjectType($objectTypeID)->getProcessor();
+ if ($processor !== null) {
+ $processor->setPermissions($attachments);
+ }
+ }
+
+ return $attachmentList->getObjects();
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\message\embedded\object;
+
+/**
+ * Default interface of embedded object handler.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2014 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.message.embedded.object
+ * @category Community Framework
+ */
+interface IMessageEmbeddedObjectHandler {
+ /**
+ * Parses the given message to extract embedded objects.
+ * Returns the IDs of found embedded objects.
+ *
+ * @param string $message
+ * @return array<integer>
+ */
+ public function parseMessage($message);
+
+ /**
+ * Loads and returns embedded objects.
+ *
+ * @param array $objectIDs
+ * @return array<\wcf\data\DatabaseObject>
+ */
+ public function loadObjects(array $objectIDs);
+}
--- /dev/null
+<?php
+namespace wcf\system\message\embedded\object;
+use wcf\data\object\type\ObjectTypeCache;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\SingletonFactory;
+use wcf\system\WCF;
+
+/**
+ * Default interface of embedded object handler.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2014 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.message.embedded.object
+ * @category Community Framework
+ */
+class MessageEmbeddedObjectManager extends SingletonFactory {
+ /**
+ * caches message to embedded object assignments
+ * @var array
+ */
+ protected $messageEmbeddedObjects = array();
+
+ /**
+ * caches embedded objects
+ * @var array
+ */
+ protected $embeddedObjects = array();
+
+ /**
+ * object type of the active message
+ * @var integer
+ */
+ protected $activeMessageObjectTypeID = null;
+
+ /**
+ * id of the active message
+ * @var integer
+ */
+ protected $activeMessageID = null;
+
+ /**
+ * list of embedded object handlers
+ * @var array
+ */
+ protected $embeddedObjectHandlers = null;
+
+ /**
+ * Registers the embedded objects found in given message.
+ *
+ * @param string $messageObjectType
+ * @param integer $messageID
+ * @param string $message
+ * @return boolean
+ */
+ public function registerObjects($messageObjectType, $messageID, $message) {
+ // remove [code] tags
+ $message = self::removeCodeTags($message);
+
+ // delete existing assignments
+ $this->removeObjects($messageObjectType, array($messageID));
+
+ // get object type id
+ $messageObjectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName('com.woltlab.wcf.message', $messageObjectType);
+
+ // prepare statement
+ $sql = "INSERT INTO wcf".WCF_N."_message_embedded_object
+ (messageObjectTypeID, messageID, embeddedObjectTypeID, embeddedObjectID)
+ VALUES (?, ?, ?, ?)";
+ $statement = WCF::getDB()->prepareStatement($sql);
+
+ // call embedded object handlers
+ WCF::getDB()->beginTransaction();
+ $returnValue = false;
+ foreach ($this->getEmbeddedObjectHandlers() as $handler) {
+ $objectIDs = $handler->parseMessage($message);
+ if (!empty($objectIDs)) {
+ $returnValue = true;
+ foreach ($objectIDs as $objectID) {
+ $statement->execute(array($messageObjectTypeID, $messageID, $handler->objectTypeID, $objectID));
+ }
+ }
+ }
+ WCF::getDB()->commitTransaction();
+
+ return $returnValue;
+ }
+
+ /**
+ * Removes embedded object assigments for given messages.
+ *
+ * @param string $messageObjectType
+ * @param array<integer> $messageIDs
+ */
+ public function removeObjects($messageObjectType, array $messageIDs) {
+ $conditionBuilder = new PreparedStatementConditionBuilder();
+ $conditionBuilder->add('messageObjectTypeID = ?', array(ObjectTypeCache::getInstance()->getObjectTypeIDByName('com.woltlab.wcf.message', $messageObjectType)));
+ $conditionBuilder->add('messageID IN (?)', array($messageIDs));
+
+ $sql = "DELETE FROM wcf".WCF_N."_message_embedded_object
+ ".$conditionBuilder;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditionBuilder->getParameters());
+ }
+
+ /**
+ * Loads the embedded objects for given messages.
+ *
+ * @param string $messageObjectType
+ * @param array<integer> $messageIDs
+ */
+ public function loadObjects($messageObjectType, array $messageIDs) {
+ $conditionBuilder = new PreparedStatementConditionBuilder();
+ $conditionBuilder->add('messageObjectTypeID = ?', array(ObjectTypeCache::getInstance()->getObjectTypeIDByName('com.woltlab.wcf.message', $messageObjectType)));
+ $conditionBuilder->add('messageID IN (?)', array($messageIDs));
+
+ $sql = "SELECT *
+ FROM wcf".WCF_N."_message_embedded_object
+ ".$conditionBuilder;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditionBuilder->getParameters());
+ $embeddedObjects = array();
+ while ($row = $statement->fetchArray()) {
+ if (!isset($embeddedObjects[$row['embeddedObjectTypeID']])) $embeddedObjects[$row['embeddedObjectTypeID']] = array();
+ $embeddedObjects[$row['embeddedObjectTypeID']][] = $row['embeddedObjectID'];
+
+ if (!isset($this->messageEmbeddedObjects[$row['messageObjectTypeID']][$row['messageID']][$row['embeddedObjectTypeID']])) {
+ $this->messageEmbeddedObjects[$row['messageObjectTypeID']][$row['messageID']][$row['embeddedObjectTypeID']] = array();
+ }
+ $this->messageEmbeddedObjects[$row['messageObjectTypeID']][$row['messageID']][$row['embeddedObjectTypeID']][] = $row['embeddedObjectID'];
+ }
+
+ foreach ($embeddedObjects as $embeddedObjectTypeID => $objectIDs) {
+ if (!isset($this->embeddedObjects[$embeddedObjectTypeID])) $this->embeddedObjects[$embeddedObjectTypeID] = array();
+ foreach ($this->getEmbeddedObjectHandler($embeddedObjectTypeID)->loadObjects(array_unique($objectIDs)) as $objectID => $object) {
+ $this->embeddedObjects[$embeddedObjectTypeID][$objectID] = $object;
+ }
+ }
+ }
+
+ /**
+ * Sets active message information.
+ *
+ * @param string $messageObjectType
+ * @param integer $messageID
+ */
+ public function setActiveMessage($messageObjectType, $messageID) {
+ $this->activeMessageObjectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName('com.woltlab.wcf.message', $messageObjectType);
+ $this->activeMessageID = $messageID;
+ }
+
+ /**
+ * Gets all embedded objects of a specific type.
+ *
+ * @param string $embeddedObjectType
+ * @return array
+ */
+ public function getObjects($embeddedObjectType) {
+ $embeddedObjectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName('com.woltlab.wcf.message.embeddedObject', $embeddedObjectType);
+ $returnValue = array();
+ if (!empty($this->messageEmbeddedObjects[$this->activeMessageObjectTypeID][$this->activeMessageID][$embeddedObjectTypeID])) {
+ foreach ($this->messageEmbeddedObjects[$this->activeMessageObjectTypeID][$this->activeMessageID][$embeddedObjectTypeID] as $embeddedObjectID) {
+ if (isset($this->embeddedObjects[$embeddedObjectTypeID][$embeddedObjectID])) {
+ $returnValue[] = $this->embeddedObjects[$embeddedObjectTypeID][$embeddedObjectID];
+ }
+ }
+ }
+
+ return $returnValue;
+ }
+
+ /**
+ * Returns a specific embedded object.
+ *
+ * @param string $embeddedObjectType
+ * @param integer $objectID
+ * @return \wcf\data\DatabaseObject
+ */
+ public function getObject($embeddedObjectType, $objectID) {
+ $embeddedObjectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName('com.woltlab.wcf.message.embeddedObject', $embeddedObjectType);
+ $returnValue = array();
+ if (!empty($this->messageEmbeddedObjects[$this->activeMessageObjectTypeID][$this->activeMessageID][$embeddedObjectTypeID])) {
+ foreach ($this->messageEmbeddedObjects[$this->activeMessageObjectTypeID][$this->activeMessageID][$embeddedObjectTypeID] as $embeddedObjectID) {
+ if ($embeddedObjectID == $objectID) {
+ if (isset($this->embeddedObjects[$embeddedObjectTypeID][$embeddedObjectID])) {
+ return $this->embeddedObjects[$embeddedObjectTypeID][$embeddedObjectID];
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Parses a temporary message and loads found embedded objects.
+ *
+ * @param string $message
+ */
+ public function parseTemporaryMessage($message) {
+ // remove [code] tags
+ $message = self::removeCodeTags($message);
+
+ // set active message information
+ $this->activeMessageObjectTypeID = -1;
+ $this->activeMessageID = -1;
+
+ // get embedded objects
+ foreach ($this->getEmbeddedObjectHandlers() as $handler) {
+ $objectIDs = $handler->parseMessage($message);
+ if (!empty($objectIDs)) {
+ // save assignments
+ $this->messageEmbeddedObjects[$this->activeMessageObjectTypeID][$this->activeMessageID][$handler->objectTypeID] = $objectIDs;
+
+ // loads objects
+ $this->embeddedObjects[$handler->objectTypeID] = $handler->loadObjects($objectIDs);
+ }
+ }
+ }
+
+ /**
+ * Returns all embedded object handlers.
+ *
+ * @return array
+ */
+ protected function getEmbeddedObjectHandlers() {
+ if ($this->embeddedObjectHandlers === null) {
+ $this->embeddedObjectHandlers = array();
+ foreach (ObjectTypeCache::getInstance()->getObjectTypes('com.woltlab.wcf.message.embeddedObject') as $objectType) {
+ $this->embeddedObjectHandlers[$objectType->objectTypeID] = $objectType->getProcessor();
+ }
+ }
+
+ return $this->embeddedObjectHandlers;
+ }
+
+ /**
+ * Returns a specific embedded object handler.
+ *
+ * @param integer $objectTypeID
+ * @return object
+ */
+ protected function getEmbeddedObjectHandler($objectTypeID) {
+ $this->getEmbeddedObjectHandlers();
+
+ return $this->embeddedObjectHandlers[$objectTypeID];
+ }
+
+ /**
+ * Removes code bbcode occurrences in given message.
+ *
+ * @param string $message
+ * @return string
+ */
+ protected static function removeCodeTags($message) {
+ return preg_replace("~(\[code
+ (?:=
+ (?:\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'|[^,\]]*)
+ (?:,(?:\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'|[^,\]]*))*
+ )?\])
+ (.*?)
+ (?:\[/code\])~six", '', $message);
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+namespace wcf\system\message\embedded\object;
+use wcf\data\user\UserProfile;
+use wcf\data\user\UserList;
+
+/**
+ * IMessageEmbeddedObjectHandler implementation for quotes.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2014 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package com.woltlab.wcf
+ * @subpackage system.message.embedded.object
+ * @category Community Framework
+ */
+class QuoteMessageEmbeddedObjectHandler extends AbstractMessageEmbeddedObjectHandler {
+ /**
+ * @see \wcf\system\message\embedded\object\IMessageEmbeddedObjectHandler::parseMessage()
+ */
+ public function parseMessage($message) {
+ $usernames = self::getFirstParameters($message, 'quote');
+ if (!empty($usernames)) {
+ $userList = new UserList();
+ $userList->getConditionBuilder()->add("user_table.username IN (?)", array($usernames));
+ $userList->readObjectIDs();
+ return $userList->getObjectIDs();
+ }
+
+ return false;
+ }
+
+ /**
+ * @see \wcf\system\message\embedded\object\IMessageEmbeddedObjectHandler::loadObjects()
+ */
+ public function loadObjects(array $objectIDs) {
+ return UserProfile::getUserProfiles($objectIDs);
+ }
+}
/* Quote Box */
.quoteBox {
- background-color: @wcfContentBackgroundColor;
clear: both;
- min-height: 28px;
- margin-bottom: @wcfGapTiny;
- position: relative;
-
- &.containerPadding {
- padding-left: 54px;
- }
- &::before {
- content: "\f10d";
- color: @wcfDimmedColor;
- font-family: FontAwesome;
- font-size: 28px;
- position: absolute;
- left: @wcfGapMedium;
- top: @wcfGapSmall;
+ > .container {
+ background-color: @wcfContentBackgroundColor;
+ min-height: 28px;
+ margin-bottom: @wcfGapTiny;
+ position: relative;
+
+ &.containerPadding {
+ padding-left: 54px;
+ }
+
+ > header {
+ padding-bottom: @wcfGapTiny;
+ border-bottom: 1px dotted @wcfContainerBorderColor;
+ margin-bottom: @wcfGapSmall;
+
+ > h3 {
+ font-weight: bold;
+ }
+ }
+
+ > div {
+ &::before {
+ content: "\f10d";
+ color: @wcfDimmedColor;
+ font-family: FontAwesome;
+ font-size: 28px;
+ position: absolute;
+ left: @wcfGapMedium;
+ top: @wcfGapSmall;
+ }
+ }
}
- > header {
- padding-bottom: @wcfGapTiny;
- border-bottom: 1px dotted @wcfContainerBorderColor;
- margin-bottom: @wcfGapSmall;
+ > .quoteAuthorAvatar {
+ float: left;
+
+ + .container {
+ margin-left: 90px;
+ padding-left: @wcfGapLarge;
+
+ &::before,
+ &::after {
+ border-style: inset solid inset none;
+ border-width: 15px;
+ content: "";
+ display: block;
+ height: 0;
+ position: absolute;
+ top: 15px;
+ width: 0;
+ }
+
+ &::before {
+ border-color: transparent @wcfContainerBorderColor transparent transparent;
+ left: -15px;
+ z-index: 100;
+ }
+
+ &::after {
+ border-color: transparent @wcfContentBackgroundColor transparent transparent;
+ left: -14px;
+ z-index: 101;
+ }
+
+ > div {
+ &::before {
+ display: none;
+ }
+ }
+ }
- > h3 {
- font-weight: bold;
+ > a {
+ display: inline-block;
}
}
/* nested quotes */
.quoteBox {
- background-image: none;
- padding-left: @wcfGapLarge;
- min-height: 0;
-
- &::before {
+ > .quoteAuthorAvatar {
display: none;
}
+
+ > .container {
+ margin-left: 0;
+ padding-left: @wcfGapLarge;
+ min-height: 0;
+
+ &::before,
+ &::after {
+ display: none;
+ }
+
+ > div {
+ &::before {
+ display: none;
+ }
+ }
+ }
}
}
@media only screen and (max-width: 800px) {
.quoteBox {
- &::before {
- font-size: 14px;
- left: @wcfGapSmall;
+ > .quoteAuthorAvatar {
+ display: none;
}
- &.containerPadding {
- padding-left: 28px;
+ > .container {
+ margin-left: 0 !important;
+
+ &.containerPadding {
+ padding-left: 28px;
+ }
+
+ > div {
+ &::before {
+ display: block !important;
+ font-size: 14px;
+ left: @wcfGapSmall;
+ }
+ }
}
.quoteBox {
- padding-left: @wcfGapSmall;
+ > .container {
+ padding-left: @wcfGapSmall;
+
+ > div {
+ &::before {
+ display: none !important;
+ }
+ }
+ }
}
}
}
UNIQUE KEY (objectTypeID, objectID)
);
+DROP TABLE IF EXISTS wcf1_message_embedded_object;
+CREATE TABLE wcf1_message_embedded_object (
+ messageObjectTypeID INT(10) NOT NULL,
+ messageID INT(10) NOT NULL,
+ embeddedObjectTypeID INT(10) NOT NULL,
+ embeddedObjectID INT(10) NOT NULL,
+
+ KEY (messageObjectTypeID, messageID)
+);
+
DROP TABLE IF EXISTS wcf1_moderation_queue;
CREATE TABLE wcf1_moderation_queue (
queueID INT(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
ALTER TABLE wcf1_user_object_watch ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE CASCADE;
ALTER TABLE wcf1_user_object_watch ADD FOREIGN KEY (objectTypeID) REFERENCES wcf1_object_type (objectTypeID) ON DELETE CASCADE;
+ALTER TABLE wcf1_message_embedded_object ADD FOREIGN KEY (messageObjectTypeID) REFERENCES wcf1_object_type (objectTypeID) ON DELETE CASCADE;
+ALTER TABLE wcf1_message_embedded_object ADD FOREIGN KEY (embeddedObjectTypeID) REFERENCES wcf1_object_type (objectTypeID) ON DELETE CASCADE;
+
ALTER TABLE wcf1_moderation_queue ADD FOREIGN KEY (objectTypeID) REFERENCES wcf1_object_type (objectTypeID) ON DELETE CASCADE;
ALTER TABLE wcf1_moderation_queue ADD FOREIGN KEY (userID) REFERENCES wcf1_user (userID) ON DELETE SET NULL;
ALTER TABLE wcf1_moderation_queue ADD FOREIGN KEY (assignedUserID) REFERENCES wcf1_user (userID) ON DELETE SET NULL;