<classname>wcf\system\user\notification\object\type\ArticleCommentResponseUserNotificationObjectType</classname>
<category>com.woltlab.wcf.page</category>
</type>
+ <type>
+ <name>com.woltlab.wcf.article</name>
+ <definitionname>com.woltlab.wcf.moderation.report</definitionname>
+ <classname>wcf\system\moderation\queue\report\ArticleModerationQueueReportHandler</classname>
+ </type>
<!-- /articles -->
<type>
<div class="col-xs-12 col-md-6">
<ul class="articleLikeButtons buttonGroup">
<li class="jsOnly"><span class="button reactButton{if $articleLikeData[$article->articleID]|isset && $articleLikeData[$article->articleID]->reactionTypeID} active{/if}" title="{lang}wcf.reactions.react{/lang}">{if $articleLikeData[$article->articleID]|isset && $articleLikeData[$article->articleID]->reactionTypeID}{@$__wcf->getReactionHandler()->getReactionTypeByID($articleLikeData[$article->articleID]->reactionTypeID)->renderIcon()}{else}<img src="{$__wcf->getPath()}/images/reaction/reactionIcon.svg" class="reactionType" alt="">{/if}</span></li>
+ <li class="jsReportArticle jsOnly" data-object-id="{@$articleContent->articleContentID}"><a href="#" title="{lang}wcf.moderation.report.reportContent{/lang}" class="button jsTooltip"><span class="icon icon16 fa-exclamation-triangle"></span> <span class="invisible">{lang}wcf.moderation.report.reportContent{/lang}</span></a></li>
</ul>
</div>
{/if}
</script>
{/if}
+{if $__wcf->session->getPermission('user.profile.canReportContent')}
+ <script data-relocate="true">
+ $(function() {
+ WCF.Language.addObject({
+ 'wcf.moderation.report.reportContent': '{lang}wcf.moderation.report.reportContent{/lang}',
+ 'wcf.moderation.report.success': '{lang}wcf.moderation.report.success{/lang}'
+ });
+ new WCF.Moderation.Report.Content('com.woltlab.wcf.article', '.jsReportArticle');
+ });
+ </script>
+{/if}
+
{include file='footer'}
--- /dev/null
+<article class="message messageReduced">
+ <section class="messageContent">
+ <header class="messageHeader">
+ <div class="box32 messageHeaderWrapper">
+ {if $article->getUserProfile()->userID}
+ <a href="{link controller='User' object=$article->getUserProfile()->getDecoratedObject()}{/link}">{@$article->getUserProfile()->getAvatar()->getImageTag(32)}</a>
+ {else}
+ <span>{@$article->getUserProfile()->getAvatar()->getImageTag(32)}</span>
+ {/if}
+
+ <div class="messageHeaderBox">
+ <h2 class="messageTitle">
+ <a href="{@$article->getLink()}">{$article->getTitle()}</a>
+ </h2>
+
+ <ul class="messageHeaderMetaData">
+ <li>
+ {if $article->getUserProfile()->userID}
+ <a href="{link controller='User' object=$article->getUserProfile()->getDecoratedObject()}{/link}" class="username">{$article->getUserProfile()}</a>
+ {else}
+ {$article->getUserProfile()->username}
+ {/if}
+ </li>
+ <li><span class="messagePublicationTime">{@$article->time|time}</span></li>
+
+ {event name='messageHeaderMetaData'}
+ </ul>
+ </div>
+ </div>
+
+ {event name='messageHeader'}
+ </header>
+
+ <div class="messageBody">
+ {event name='beforeMessageText'}
+
+ <div class="messageText">
+ {@$article->getFormattedContent()}
+ </div>
+
+ {event name='afterMessageText'}
+ </div>
+ </section>
+</article>
use wcf\data\article\content\ArticleContent;
use wcf\data\DatabaseObject;
use wcf\data\ILinkableObject;
+use wcf\data\IUserContent;
use wcf\data\object\type\ObjectTypeCache;
use wcf\system\article\discussion\CommentArticleDiscussionProvider;
use wcf\system\article\discussion\IArticleDiscussionProvider;
* @property-read integer $isDeleted is 1 if the article is in trash bin, otherwise 0
* @property-read integer $hasLabels is `1` if labels are assigned to the article
*/
-class Article extends DatabaseObject implements ILinkableObject {
+class Article extends DatabaseObject implements ILinkableObject, IUserContent {
/**
* indicates that article is unpublished
*/
return $discussionProviders;
}
+
+ /**
+ * @inheritDoc
+ * @since 3.2
+ */
+ public function getTime() {
+ return $this->time;
+ }
+
+ /**
+ * @inheritDoc
+ * @since 3.2
+ */
+ public function getUserID() {
+ return $this->userID;
+ }
+
+ /**
+ * @inheritDoc
+ * @since 3.2
+ */
+ public function getUsername() {
+ return $this->username;
+ }
}
--- /dev/null
+<?php
+namespace wcf\system\moderation\queue\report;
+use wcf\data\article\ArticleAction;
+use wcf\data\article\ViewableArticle;
+use wcf\data\moderation\queue\ModerationQueue;
+use wcf\data\moderation\queue\ViewableModerationQueue;
+use wcf\system\cache\runtime\ViewableArticleRuntimeCache;
+use wcf\system\moderation\queue\AbstractModerationQueueHandler;
+use wcf\system\moderation\queue\ModerationQueueManager;
+use wcf\system\WCF;
+
+/**
+ * An implementation of IModerationQueueReportHandler for articles.
+ *
+ * @author Joshua Ruesweg
+ * @copyright 2001-2018 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Suite\System\Moderation\Queue\Report
+ * @since 3.2
+ */
+class ArticleModerationQueueReportHandler extends AbstractModerationQueueHandler implements IModerationQueueReportHandler {
+ /**
+ * @inheritDoc
+ */
+ protected $definitionName = 'com.woltlab.wcf.moderation.report';
+
+ /**
+ * @inheritDoc
+ */
+ protected $objectType = 'com.woltlab.wcf.article';
+
+ /**
+ * @inheritDoc
+ */
+ public function canReport($objectID) {
+ if (!$this->isValid($objectID)) {
+ return false;
+ }
+
+ if (!$this->getReportedObject($objectID)->canRead()) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getReportedContent(ViewableModerationQueue $queue) {
+ WCF::getTPL()->assign([
+ 'article' => $this->getArticle($queue->getAffectedObject()->articleID),
+ ]);
+
+ return WCF::getTPL()->fetch('moderationArticle');
+ }
+
+ /**
+ * @inheritDoc
+ *
+ * @return ViewableArticle|null
+ */
+ public function getReportedObject($objectID) {
+ if ($this->isValid($objectID)) {
+ return $this->getArticle($objectID);
+ }
+
+ return null;
+ }
+
+ /**
+ * @param $articleID
+ * @return ViewableArticle|null
+ */
+ public function getArticle($articleID) {
+ return ViewableArticleRuntimeCache::getInstance()->getObject($articleID);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function assignQueues(array $queues) {
+ $assignments = $orphanedQueueIDs = [];
+
+ // first cache all articles
+ foreach ($queues as $queue) {
+ ViewableArticleRuntimeCache::getInstance()->cacheObjectID($queue->objectID);
+ }
+
+ // now process articles
+ foreach ($queues as $queue) {
+ $article = ViewableArticleRuntimeCache::getInstance()->getObject($queue->objectID);
+
+ if ($article === null) {
+ $orphanedQueueIDs[] = $queue->queueID;
+ }
+ else {
+ if ($article->canDelete()) {
+ $assignments[$queue->queueID] = true;
+ }
+ else {
+ $assignments[$queue->queueID] = false;
+ }
+ }
+ }
+
+ ModerationQueueManager::getInstance()->removeOrphans($orphanedQueueIDs);
+ ModerationQueueManager::getInstance()->setAssignment($assignments);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getContainerID($objectID) {
+ if ($this->isValid($objectID)) {
+ return $this->getArticle($objectID)->getCategory()->categoryID;
+ }
+
+ return 0;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function isValid($objectID) {
+ if ($this->getArticle($objectID) === null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function populate(array $queues) {
+ // first cache all articles
+ foreach ($queues as $queue) {
+ ViewableArticleRuntimeCache::getInstance()->cacheObjectID($queue->objectID);
+ }
+
+ foreach ($queues as $object) {
+ $article = ViewableArticleRuntimeCache::getInstance()->getObject($object->objectID);
+ if ($article !== null) {
+ $object->setAffectedObject($article->getDecoratedObject());
+ }
+ else {
+ $object->setIsOrphaned();
+ }
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function canRemoveContent(ModerationQueue $queue) {
+ if ($this->isValid($queue->objectID)) {
+ return $this->getArticle($queue->objectID)->canDelete();
+ }
+
+ return false;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function removeContent(ModerationQueue $queue, $message) {
+ if ($this->isValid($queue->objectID)) {
+ (new ArticleAction([$this->getArticle($queue->objectID)->getDecoratedObject()], 'trash'))->executeAction();
+ }
+ }
+}
\ No newline at end of file
<item name="wcf.moderation.type.com.woltlab.wcf.comment.comment"><![CDATA[Kommentar]]></item>
<item name="wcf.moderation.type.com.woltlab.wcf.comment.response"><![CDATA[Antwort auf Kommentar]]></item>
<item name="wcf.moderation.type.com.woltlab.wcf.user"><![CDATA[Benutzerprofil]]></item>
+ <item name="wcf.moderation.type.com.woltlab.wcf.article"><![CDATA[Artikel]]></item>
<item name="wcf.moderation.showAll"><![CDATA[Alle Einträge anzeigen]]></item>
<item name="wcf.moderation.showDeletedContent"><![CDATA[Gelöschte Inhalte anzeigen]]></item>
<item name="wcf.moderation.deletedContent.objectTypes"><![CDATA[Gelöschte Inhalte]]></item>
<item name="wcf.moderation.type.com.woltlab.wcf.comment.comment"><![CDATA[Comment]]></item>
<item name="wcf.moderation.type.com.woltlab.wcf.comment.response"><![CDATA[Comment Reply]]></item>
<item name="wcf.moderation.type.com.woltlab.wcf.user"><![CDATA[User Profile]]></item>
+ <item name="wcf.moderation.type.com.woltlab.wcf.article"><![CDATA[Article]]></item>
<item name="wcf.moderation.showAll"><![CDATA[Display All Items]]></item>
<item name="wcf.moderation.showDeletedContent"><![CDATA[Display Deleted Content]]></item>
<item name="wcf.moderation.deletedContent.objectTypes"><![CDATA[Deleted Content]]></item>