<definitionname>com.woltlab.wcf.message</definitionname>
</type>
+ <type>
+ <name>com.woltlab.wcf.page</name>
+ <definitionname>com.woltlab.wcf.searchableObjectType</definitionname>
+ <classname>wcf\system\search\PageSearch</classname>
+ <searchindex>wcf1_page_search_index</searchindex>
+ </type>
+
<type>
<name>com.woltlab.wcf.bbcode.smiley</name>
<definitionname>com.woltlab.wcf.category</definitionname>
<classname>wcf\system\worker\ArticleRebuildDataWorker</classname>
<nicevalue>50</nicevalue>
</type>
+ <type>
+ <name>com.woltlab.wcf.page</name>
+ <definitionname>com.woltlab.wcf.rebuildData</definitionname>
+ <classname>wcf\system\worker\PageRebuildDataWorker</classname>
+ <nicevalue>50</nicevalue>
+ </type>
<type>
<name>com.woltlab.wcf.poll</name>
<definitionname>com.woltlab.wcf.rebuildData</definitionname>
use wcf\system\html\simple\HtmlSimpleParser;
use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
use wcf\system\page\handler\ILookupPageHandler;
+use wcf\system\search\SearchIndexManager;
use wcf\system\WCF;
/**
]);
$pageContentEditor = new PageContentEditor($pageContent);
+ // update search index
+ if ($page->pageType == 'text' || $page->pageType == 'html') {
+ SearchIndexManager::getInstance()->set(
+ 'com.woltlab.wcf.page',
+ $pageContent->pageContentID,
+ $pageContent->content,
+ $pageContent->title,
+ 0,
+ null,
+ '',
+ $languageID ?: null
+ );
+ }
+
// save embedded objects
if (!empty($content['htmlInputProcessor'])) {
/** @noinspection PhpUndefinedMethodInspection */
$pageContentEditor = new PageContentEditor($pageContent);
}
+ // update search index
+ if ($page->pageType == 'text' || $page->pageType == 'html') {
+ SearchIndexManager::getInstance()->set(
+ 'com.woltlab.wcf.page',
+ $pageContent->pageContentID,
+ $pageContent->content,
+ $pageContent->title,
+ 0,
+ null,
+ '',
+ $languageID ?: null
+ );
+ }
+
// save embedded objects
if (!empty($content['htmlInputProcessor'])) {
/** @noinspection PhpUndefinedMethodInspection */
* @inheritDoc
*/
public function delete() {
+ $pageContentIDs = [];
foreach ($this->getObjects() as $page) {
if ($page->pageType == 'tpl') {
foreach ($page->getPageContents() as $languageID => $content) {
}
}
}
+
+ foreach ($page->getPageContents() as $pageContent) {
+ $pageContentIDs[] = $pageContent->pageContentID;
+ }
}
parent::delete();
+
+ if (!empty($pageContentIDs)) {
+ // delete entry from search index
+ SearchIndexManager::getInstance()->delete('com.woltlab.wcf.page', $pageContentIDs);
+ }
}
}
--- /dev/null
+<?php
+namespace wcf\data\page\content;
+use wcf\data\DatabaseObjectDecorator;
+use wcf\data\search\ISearchResultObject;
+use wcf\system\request\LinkHandler;
+use wcf\system\search\SearchResultTextParser;
+
+/**
+ * Represents an page content as a search result.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2017 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Page\Content
+ * @since 3.1
+ *
+ * @method PageContent getDecoratedObject()
+ * @mixin PageContent
+ */
+class SearchResultPageContent extends DatabaseObjectDecorator implements ISearchResultObject {
+ /**
+ * @inheritDoc
+ */
+ protected static $baseClass = PageContent::class;
+
+ /**
+ * @inheritDoc
+ */
+ public function getUserProfile() {
+ return null;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getSubject() {
+ return $this->getDecoratedObject()->title;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getTime() {
+ return 0;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getLink($query = '') {
+ return LinkHandler::getInstance()->getCmsLink($this->getDecoratedObject()->pageID, ($this->getDecoratedObject()->languageID ?: -1));
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getObjectTypeName() {
+ return 'com.woltlab.wcf.page';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getFormattedMessage() {
+ if ($this->getDecoratedObject()->pageType == 'text') {
+ $message = SearchResultTextParser::getInstance()->parse($this->getDecoratedObject()->getFormattedContent());
+ }
+ else {
+ $message = SearchResultTextParser::getInstance()->parse($this->getDecoratedObject()->getParsedContent());
+ }
+
+ return $message;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getContainerTitle() {
+ return '';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getContainerLink() {
+ return '';
+ }
+}
--- /dev/null
+<?php
+namespace wcf\data\page\content;
+
+/**
+ * Represents a list of page content as search results.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2017 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data\Page\Content
+ * @since 3.1
+ *
+ * @method SearchResultPageContent current()
+ * @method SearchResultPageContent[] getObjects()
+ * @method SearchResultPageContent|null search($objectID)
+ * @property SearchResultPageContent[] $objects
+ */
+class SearchResultPageContentList extends PageContentList {
+ /**
+ * @inheritDoc
+ */
+ public $decoratorClassName = SearchResultPageContent::class;
+}
use wcf\system\exception\SystemException;
use wcf\system\language\LanguageFactory;
use wcf\system\request\RouteHandler;
+use wcf\system\search\SearchIndexManager;
use wcf\system\WCF;
use wcf\util\StringUtil;
public $className = PageEditor::class;
/**
- * @inheritDoc
+ * page content
+ * @var mixed[]
*/
protected $content = [];
+ /**
+ * pages objects
+ * @var Page[]
+ */
+ protected $pages = [];
+
/**
* @inheritDoc
*/
}
// store content for later import
+ $this->pages[$page->pageID] = $page;
$this->content[$page->pageID] = $content;
return $page;
}
}
WCF::getDB()->commitTransaction();
+
+ // create search index tables
+ SearchIndexManager::getInstance()->createSearchIndices();
+
+ // update search index
+ foreach ($this->pages as $pageID => $page) {
+ if ($page->pageType == 'text' || $page->pageType == 'html') {
+ foreach ($page->getPageContents() as $languageID => $pageContent) {
+ SearchIndexManager::getInstance()->set(
+ 'com.woltlab.wcf.page',
+ $pageContent->pageContentID,
+ $pageContent->content,
+ $pageContent->title,
+ 0,
+ null,
+ '',
+ $languageID ?: null
+ );
+ }
+ }
+ }
}
}
}
--- /dev/null
+<?php
+namespace wcf\system\search;
+use wcf\data\object\type\ObjectTypeCache;
+use wcf\data\page\content\SearchResultPageContent;
+use wcf\data\page\content\SearchResultPageContentList;
+use wcf\form\IForm;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\WCF;
+
+/**
+ * An implementation of ISearchableObjectType for searching in cms pages.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2017 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Search
+ * @since 3.1
+ */
+class PageSearch extends AbstractSearchableObjectType {
+ /**
+ * message data cache
+ * @var SearchResultPageContent[]
+ */
+ public $messageCache = [];
+
+ /**
+ * @inheritDoc
+ */
+ public function cacheObjects(array $objectIDs, array $additionalData = null) {
+ $list = new SearchResultPageContentList();
+ $list->setObjectIDs($objectIDs);
+ $list->readObjects();
+ foreach ($list->getObjects() as $content) {
+ $this->messageCache[$content->pageContentID] = $content;
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getObject($objectID) {
+ if (isset($this->messageCache[$objectID])) {
+ return $this->messageCache[$objectID];
+ }
+
+ return null;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getTableName() {
+ return 'wcf'.WCF_N.'_page_content';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getIDFieldName() {
+ return $this->getTableName().'.pageContentID';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getSubjectFieldName() {
+ return $this->getTableName().'.title';
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getUsernameFieldName() {
+ return "''";
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getTimeFieldName() {
+ return 'wcf'.WCF_N.'_page_content.pageContentID';
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+ /**
+ * @inheritDoc
+ */
+ public function getConditions(IForm $form = null) {
+ $conditionBuilder = new PreparedStatementConditionBuilder();
+ $conditionBuilder->add('wcf'.WCF_N.'_page.pageType IN (?) AND wcf'.WCF_N.'_page.isDisabled = ?', [['text', 'html'], 0]);
+
+ // acl
+ $objectTypeID = ObjectTypeCache::getInstance()->getObjectTypeIDByName('com.woltlab.wcf.acl.simple', 'com.woltlab.wcf.page');
+ $conditionBuilder->add('(
+ wcf'.WCF_N.'_page_content.pageID NOT IN (
+ SELECT objectID FROM wcf' . WCF_N . '_acl_simple_to_group WHERE objectTypeID = ?
+ UNION
+ SELECT objectID FROM wcf' . WCF_N . '_acl_simple_to_user WHERE objectTypeID = ?
+ )
+ OR
+ wcf'.WCF_N.'_page_content.pageID IN (
+ SELECT objectID FROM wcf' . WCF_N . '_acl_simple_to_group WHERE objectTypeID = ? AND groupID IN (?)
+ UNION
+ SELECT objectID FROM wcf' . WCF_N . '_acl_simple_to_user WHERE objectTypeID = ? AND userID = ?
+ )
+ )', [$objectTypeID, $objectTypeID, $objectTypeID, WCF::getUser()->getGroupIDs(), $objectTypeID, WCF::getUser()->userID]);
+
+ return $conditionBuilder;
+ }
+
+ /** @noinspection PhpMissingParentCallCommonInspection */
+ /**
+ * @inheritDoc
+ */
+ public function getJoins() {
+ return 'INNER JOIN wcf'.WCF_N.'_page ON (wcf'.WCF_N.'_page.pageID = '.$this->getTableName().'.pageID)';
+ }
+}
--- /dev/null
+<?php
+namespace wcf\system\worker;
+use wcf\data\page\content\PageContentEditor;
+use wcf\data\page\content\PageContentList;
+use wcf\data\page\PageList;
+use wcf\system\html\input\HtmlInputProcessor;
+use wcf\system\message\embedded\object\MessageEmbeddedObjectManager;
+use wcf\system\search\SearchIndexManager;
+
+/**
+ * Worker implementation for updating cms pages.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2017 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Worker
+ * @since 3.1
+ *
+ * @method PageList getObjectList()
+ */
+class PageRebuildDataWorker extends AbstractRebuildDataWorker {
+ /**
+ * @inheritDoc
+ */
+ protected $objectListClassName = PageList::class;
+
+ /**
+ * @inheritDoc
+ */
+ protected $limit = 100;
+
+ /**
+ * @var HtmlInputProcessor
+ */
+ protected $htmlInputProcessor;
+
+ /**
+ * @inheritDoc
+ */
+ protected function initObjectList() {
+ parent::initObjectList();
+
+ $this->objectList->sqlOrderBy = 'page.pageID';
+ $this->objectList->getConditionBuilder()->add('page.pageType <> ?', ['system']);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function execute() {
+ parent::execute();
+
+ if (!$this->loopCount) {
+ // reset search index
+ SearchIndexManager::getInstance()->reset('com.woltlab.wcf.page');
+ }
+
+ if (!count($this->objectList)) {
+ return;
+ }
+ $pages = $this->objectList->getObjects();
+
+ // update page content
+ $pageContentList = new PageContentList();
+ $pageContentList->getConditionBuilder()->add('page_content.pageID IN (?)', [$this->objectList->getObjectIDs()]);
+ $pageContentList->readObjects();
+ foreach ($pageContentList as $pageContent) {
+ $page = $pages[$pageContent->pageID];
+ if ($page->pageType == 'text' || $page->pageType == 'html') {
+ // update search index
+ SearchIndexManager::getInstance()->set(
+ 'com.woltlab.wcf.page',
+ $pageContent->pageContentID,
+ $pageContent->content,
+ $pageContent->title,
+ 0,
+ null,
+ '',
+ $pageContent->languageID
+ );
+ }
+
+ // update embedded objects
+ $this->getHtmlInputProcessor()->processEmbeddedContent($pageContent->content, 'com.woltlab.wcf.page.content', $pageContent->pageContentID);
+
+ $hasEmbeddedObjects = 0;
+ if (MessageEmbeddedObjectManager::getInstance()->registerObjects($this->getHtmlInputProcessor())) {
+ $hasEmbeddedObjects = 1;
+ }
+
+ if ($hasEmbeddedObjects != $pageContent->hasEmbeddedObjects) {
+ $pageContentEditor = new PageContentEditor($pageContent);
+ $pageContentEditor->update(['hasEmbeddedObjects' => $hasEmbeddedObjects]);
+ }
+ }
+ }
+
+ /**
+ * @return HtmlInputProcessor
+ */
+ protected function getHtmlInputProcessor() {
+ if ($this->htmlInputProcessor === null) {
+ $this->htmlInputProcessor = new HtmlInputProcessor();
+ }
+
+ return $this->htmlInputProcessor;
+ }
+}
<item name="wcf.acp.rebuildData.com.woltlab.wcf.databaseConvertEncoding.description"><![CDATA[Warnung: Die Ausführung dieser Aktion kann bei umfangreichen Datenbanken sehr lange dauern.]]></item>
<item name="wcf.acp.rebuildData.com.woltlab.wcf.comment"><![CDATA[Kommentare aktualisieren]]></item>
<item name="wcf.acp.rebuildData.com.woltlab.wcf.comment.description"><![CDATA[Aktualisiert die Kommentare]]></item>
+ <item name="wcf.acp.rebuildData.com.woltlab.wcf.page"><![CDATA[Seiten aktualisieren]]></item>
+ <item name="wcf.acp.rebuildData.com.woltlab.wcf.page.description"><![CDATA[Aktualisiert den Suchindex für CMS-Seiten]]></item>
</category>
<category name="wcf.acp.rescueMode">
<item name="wcf.search.error.user.noMatches"><![CDATA[Es wurde kein Eintrag von diesem Autor gefunden.]]></item>
<item name="wcf.search.object.com.woltlab.wcf.article"><![CDATA[Artikel]]></item>
<item name="wcf.search.type.com.woltlab.wcf.article"><![CDATA[Artikel]]></item>
+ <item name="wcf.search.object.com.woltlab.wcf.page"><![CDATA[Seite]]></item>
+ <item name="wcf.search.type.com.woltlab.wcf.page"><![CDATA[Seiten]]></item>
</category>
<category name="wcf.style">
<item name="wcf.acp.rebuildData.com.woltlab.wcf.databaseConvertEncoding.description"><![CDATA[Warning: This action may take a while to complete on large databases.]]></item>
<item name="wcf.acp.rebuildData.com.woltlab.wcf.comment"><![CDATA[Rebuild Comments]]></item>
<item name="wcf.acp.rebuildData.com.woltlab.wcf.comment.description"><![CDATA[Rebuilds the comments.]]></item>
+ <item name="wcf.acp.rebuildData.com.woltlab.wcf.page"><![CDATA[Rebuild Pages]]></item>
+ <item name="wcf.acp.rebuildData.com.woltlab.wcf.page.description"><![CDATA[Rebuilds the page search index.]]></item>
</category>
<category name="wcf.acp.rescueMode">
<item name="wcf.search.error.user.noMatches"><![CDATA[There were no items matching this author.]]></item>
<item name="wcf.search.object.com.woltlab.wcf.article"><![CDATA[Article]]></item>
<item name="wcf.search.type.com.woltlab.wcf.article"><![CDATA[Articles]]></item>
+ <item name="wcf.search.object.com.woltlab.wcf.page"><![CDATA[Page]]></item>
+ <item name="wcf.search.type.com.woltlab.wcf.page"><![CDATA[Pages]]></item>
</category>
<category name="wcf.style">