From ef17c746ea08627eb86be9722d97abdb8cfd2f31 Mon Sep 17 00:00:00 2001 From: Marcel Werk Date: Thu, 23 Jun 2016 16:01:29 +0200 Subject: [PATCH] Added support for embedded objects in articles --- com.woltlab.wcf/objectType.xml | 4 +++ .../lib/acp/form/ArticleAddForm.class.php | 14 ++++++++ .../lib/acp/form/ArticleEditForm.class.php | 2 ++ .../files/lib/data/article/Article.class.php | 2 +- .../lib/data/article/ArticleAction.class.php | 33 +++++++++++++++++-- .../article/content/ArticleContent.class.php | 5 +-- .../ViewableArticleContentList.class.php | 12 ++++++- wcfsetup/setup/db/install.sql | 2 +- 8 files changed, 67 insertions(+), 7 deletions(-) diff --git a/com.woltlab.wcf/objectType.xml b/com.woltlab.wcf/objectType.xml index d1b6f8fe4b..aca198bf12 100644 --- a/com.woltlab.wcf/objectType.xml +++ b/com.woltlab.wcf/objectType.xml @@ -60,6 +60,10 @@ wcf\system\search\ArticleSearch wcf1_article_search_index + + com.woltlab.wcf.article.content + com.woltlab.wcf.message + diff --git a/wcfsetup/install/files/lib/acp/form/ArticleAddForm.class.php b/wcfsetup/install/files/lib/acp/form/ArticleAddForm.class.php index ad437df0f7..41f8d5158b 100644 --- a/wcfsetup/install/files/lib/acp/form/ArticleAddForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/ArticleAddForm.class.php @@ -10,6 +10,7 @@ use wcf\data\media\ViewableMediaList; use wcf\data\user\User; use wcf\form\AbstractForm; use wcf\system\exception\UserInputException; +use wcf\system\html\input\HtmlInputProcessor; use wcf\system\language\LanguageFactory; use wcf\system\request\LinkHandler; use wcf\system\WCF; @@ -127,6 +128,11 @@ class ArticleAddForm extends AbstractForm { */ public $content = []; + /** + * @var HtmlInputProcessor[] + */ + public $htmlInputProcessors = []; + /** * image ids * @var integer[] @@ -278,6 +284,9 @@ class ArticleAddForm extends AbstractForm { if (empty($this->content[$language->languageID])) { throw new UserInputException('content'.$language->languageID); } + + $this->htmlInputProcessors[$language->languageID] = new HtmlInputProcessor(); + $this->htmlInputProcessors[$language->languageID]->process($this->content[$language->languageID]); } } else { @@ -289,6 +298,9 @@ class ArticleAddForm extends AbstractForm { if (empty($this->content[0])) { throw new UserInputException('content'); } + + $this->htmlInputProcessors[0] = new HtmlInputProcessor(); + $this->htmlInputProcessors[0]->process($this->content[0]); } } @@ -307,6 +319,7 @@ class ArticleAddForm extends AbstractForm { 'tags' => (!empty($this->tags[$language->languageID]) ? $this->tags[$language->languageID] : []), 'teaser' => (!empty($this->teaser[$language->languageID]) ? $this->teaser[$language->languageID] : ''), 'content' => (!empty($this->content[$language->languageID]) ? $this->content[$language->languageID] : ''), + 'htmlInputProcessor' => (isset($this->htmlInputProcessors[$language->languageID]) ? $this->htmlInputProcessors[$language->languageID] : null), 'imageID' => (!empty($this->imageID[$language->languageID]) ? $this->imageID[$language->languageID] : null) ]; } @@ -317,6 +330,7 @@ class ArticleAddForm extends AbstractForm { 'tags' => (!empty($this->tags[0]) ? $this->tags[0] : []), 'teaser' => (!empty($this->teaser[0]) ? $this->teaser[0] : ''), 'content' => (!empty($this->content[0]) ? $this->content[0] : ''), + 'htmlInputProcessor' => (isset($this->htmlInputProcessors[0]) ? $this->htmlInputProcessors[0] : null), 'imageID' => (!empty($this->imageID[0]) ? $this->imageID[0] : null) ]; } diff --git a/wcfsetup/install/files/lib/acp/form/ArticleEditForm.class.php b/wcfsetup/install/files/lib/acp/form/ArticleEditForm.class.php index c89afc91d4..01dead1c66 100644 --- a/wcfsetup/install/files/lib/acp/form/ArticleEditForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/ArticleEditForm.class.php @@ -71,6 +71,7 @@ class ArticleEditForm extends ArticleAddForm { 'tags' => (!empty($this->tags[$language->languageID]) ? $this->tags[$language->languageID] : []), 'teaser' => (!empty($this->teaser[$language->languageID]) ? $this->teaser[$language->languageID] : ''), 'content' => (!empty($this->content[$language->languageID]) ? $this->content[$language->languageID] : ''), + 'htmlInputProcessor' => (isset($this->htmlInputProcessors[$language->languageID]) ? $this->htmlInputProcessors[$language->languageID] : null), 'imageID' => (!empty($this->imageID[$language->languageID]) ? $this->imageID[$language->languageID] : null) ]; } @@ -81,6 +82,7 @@ class ArticleEditForm extends ArticleAddForm { 'tags' => (!empty($this->tags[0]) ? $this->tags[0] : []), 'teaser' => (!empty($this->teaser[0]) ? $this->teaser[0] : ''), 'content' => (!empty($this->content[0]) ? $this->content[0] : ''), + 'htmlInputProcessor' => (isset($this->htmlInputProcessors[0]) ? $this->htmlInputProcessors[0] : null), 'imageID' => (!empty($this->imageID[0]) ? $this->imageID[0] : null) ]; } diff --git a/wcfsetup/install/files/lib/data/article/Article.class.php b/wcfsetup/install/files/lib/data/article/Article.class.php index 2402bc291a..95441a6dea 100644 --- a/wcfsetup/install/files/lib/data/article/Article.class.php +++ b/wcfsetup/install/files/lib/data/article/Article.class.php @@ -27,7 +27,7 @@ use wcf\system\WCF; * @property-read integer $enableComments * @property-read integer $comments * @property-read integer $views - * @todo + * @property-read integer $cumulativeLikes */ class Article extends DatabaseObject implements ILinkableObject { /** diff --git a/wcfsetup/install/files/lib/data/article/ArticleAction.class.php b/wcfsetup/install/files/lib/data/article/ArticleAction.class.php index c40ac0f305..3236d76d7c 100644 --- a/wcfsetup/install/files/lib/data/article/ArticleAction.class.php +++ b/wcfsetup/install/files/lib/data/article/ArticleAction.class.php @@ -6,6 +6,7 @@ use wcf\data\AbstractDatabaseObjectAction; use wcf\system\comment\CommentHandler; use wcf\system\language\LanguageFactory; use wcf\system\like\LikeHandler; +use wcf\system\message\embedded\object\MessageEmbeddedObjectManager; use wcf\system\search\SearchIndexManager; use wcf\system\tagging\TagEngine; @@ -58,6 +59,11 @@ class ArticleAction extends AbstractDatabaseObjectAction { // save article content if (!empty($this->parameters['content'])) { foreach ($this->parameters['content'] as $languageID => $content) { + if (!empty($content['htmlInputProcessor'])) { + /** @noinspection PhpUndefinedMethodInspection */ + $content['content'] = $content['htmlInputProcessor']->getHtml(); + } + /** @var ArticleContent $articleContent */ $articleContent = ArticleContentEditor::create([ 'articleID' => $article->articleID, @@ -67,6 +73,7 @@ class ArticleAction extends AbstractDatabaseObjectAction { 'content' => $content['content'], 'imageID' => $content['imageID'] ]); + $articleContentEditor = new ArticleContentEditor($articleContent); // save tags if (!empty($content['tags'])) { @@ -75,6 +82,13 @@ class ArticleAction extends AbstractDatabaseObjectAction { // update search index SearchIndexManager::getInstance()->add('com.woltlab.wcf.article', $articleContent->articleContentID, $articleContent->content, $articleContent->title, $article->time, $article->userID, $article->username, ($languageID ?: null), $articleContent->teaser); + + // save embedded objects + if (!empty($content['htmlInputProcessor'])) { + if (MessageEmbeddedObjectManager::getInstance()->registerObjects($content['htmlInputProcessor'], 'com.woltlab.wcf.article.content', $articleContent->articleContentID)) { + $articleContentEditor->update(['hasEmbeddedObjects' => 1]); + } + } } } @@ -91,11 +105,17 @@ class ArticleAction extends AbstractDatabaseObjectAction { if (!empty($this->parameters['content'])) { foreach ($this->getObjects() as $article) { foreach ($this->parameters['content'] as $languageID => $content) { + if (!empty($content['htmlInputProcessor'])) { + /** @noinspection PhpUndefinedMethodInspection */ + $content['content'] = $content['htmlInputProcessor']->getHtml(); + } + $articleContent = ArticleContent::getArticleContent($article->articleID, ($languageID ?: null)); + $articleContentEditor = null; if ($articleContent !== null) { // update - $editor = new ArticleContentEditor($articleContent); - $editor->update([ + $articleContentEditor = new ArticleContentEditor($articleContent); + $articleContentEditor->update([ 'title' => $content['title'], 'teaser' => $content['teaser'], 'content' => $content['content'], @@ -109,6 +129,7 @@ class ArticleAction extends AbstractDatabaseObjectAction { } } else { + /** @var ArticleContent $articleContent */ $articleContent = ArticleContentEditor::create([ 'articleID' => $article->articleID, 'languageID' => ($languageID ?: null), @@ -117,6 +138,7 @@ class ArticleAction extends AbstractDatabaseObjectAction { 'content' => $content['content'], 'imageID' => $content['imageID'] ]); + $articleContentEditor = new ArticleContentEditor($articleContent); } // save tags @@ -126,6 +148,13 @@ class ArticleAction extends AbstractDatabaseObjectAction { // update search index SearchIndexManager::getInstance()->add('com.woltlab.wcf.article', $articleContent->articleContentID, $articleContent->content, $articleContent->title, $article->time, $article->userID, $article->username, ($languageID ?: null), $articleContent->teaser); + + // save embedded objects + if (!empty($content['htmlInputProcessor'])) { + if ($articleContent->hasEmbeddedObjects != MessageEmbeddedObjectManager::getInstance()->registerObjects($content['htmlInputProcessor'], 'com.woltlab.wcf.article.content', $articleContent->articleContentID)) { + $articleContentEditor->update(['hasEmbeddedObjects' => ($articleContent->hasEmbeddedObjects ? 0 : 1)]); + } + } } } } diff --git a/wcfsetup/install/files/lib/data/article/content/ArticleContent.class.php b/wcfsetup/install/files/lib/data/article/content/ArticleContent.class.php index fa6408e17d..259a13acbd 100644 --- a/wcfsetup/install/files/lib/data/article/content/ArticleContent.class.php +++ b/wcfsetup/install/files/lib/data/article/content/ArticleContent.class.php @@ -10,7 +10,6 @@ use wcf\system\message\embedded\object\MessageEmbeddedObjectManager; use wcf\system\request\IRouteController; use wcf\system\request\LinkHandler; use wcf\system\WCF; -use wcf\util\MessageUtil; use wcf\util\StringUtil; /** @@ -29,6 +28,7 @@ use wcf\util\StringUtil; * @property-read string $content * @property-read string $teaser * @property-read integer $imageID + * @property-read integer $hasEmbeddedObjects */ class ArticleContent extends DatabaseObject implements ILinkableObject, IRouteController { /** @@ -94,7 +94,7 @@ class ArticleContent extends DatabaseObject implements ILinkableObject, IRouteCo */ public function getFormattedContent() { // assign embedded objects - MessageEmbeddedObjectManager::getInstance()->setActiveMessage('com.woltlab.wcf.article', $this->articleContentID); + MessageEmbeddedObjectManager::getInstance()->setActiveMessage('com.woltlab.wcf.article.content', $this->articleContentID); // TODO return (new HtmlOutputProcessor())->process($this->content); @@ -126,6 +126,7 @@ class ArticleContent extends DatabaseObject implements ILinkableObject, IRouteCo return null; } + public static function getArticleContent($articleID, $languageID) { if ($languageID !== null) { $sql = "SELECT * diff --git a/wcfsetup/install/files/lib/data/article/content/ViewableArticleContentList.class.php b/wcfsetup/install/files/lib/data/article/content/ViewableArticleContentList.class.php index 40d85efee3..40b56d0806 100644 --- a/wcfsetup/install/files/lib/data/article/content/ViewableArticleContentList.class.php +++ b/wcfsetup/install/files/lib/data/article/content/ViewableArticleContentList.class.php @@ -1,6 +1,7 @@ getObjects() as $articleContent) { if ($articleContent->imageID) { $imageIDs[] = $articleContent->imageID; } + if ($articleContent->hasEmbeddedObjects) { + $embeddedObjectPostIDs[] = $articleContent->articleContentID; + } } // cache images @@ -37,11 +41,17 @@ class ViewableArticleContentList extends ArticleContentList { $mediaList->readObjects(); $images = $mediaList->getObjects(); + /** @var ViewableArticleContent $articleContent */ foreach ($this->getObjects() as $articleContent) { if ($articleContent->imageID && isset($images[$articleContent->imageID])) { $articleContent->setImage($images[$articleContent->imageID]); } } } + + // load embedded objects + if (!empty($embeddedObjectPostIDs)) { + MessageEmbeddedObjectManager::getInstance()->loadObjects('com.woltlab.wcf.article.content', $embeddedObjectPostIDs); + } } } diff --git a/wcfsetup/setup/db/install.sql b/wcfsetup/setup/db/install.sql index 4feb29cbc9..37984080ad 100644 --- a/wcfsetup/setup/db/install.sql +++ b/wcfsetup/setup/db/install.sql @@ -166,7 +166,6 @@ CREATE TABLE wcf1_article ( comments SMALLINT(5) NOT NULL DEFAULT 0, views MEDIUMINT(7) NOT NULL DEFAULT 0, cumulativeLikes MEDIUMINT(7) NOT NULL DEFAULT 0, - hasEmbeddedObjects TINYINT(1) NOT NULL DEFAULT 0, KEY (time) ); @@ -180,6 +179,7 @@ CREATE TABLE wcf1_article_content ( teaser TEXT, content MEDIUMTEXT, imageID INT(10), + hasEmbeddedObjects TINYINT(1) NOT NULL DEFAULT 0, UNIQUE KEY (articleID, languageID) ); -- 2.20.1