From: Alexander Ebert Date: Wed, 2 Dec 2015 17:41:39 +0000 (+0100) Subject: Added {page}-PIP and CMS routing support X-Git-Tag: 3.0.0_Beta_1~2030^2~215 X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=3295fb92932cdb9c1a627a664b2bf87dd8819aea;p=GitHub%2FWoltLab%2FWCF.git Added {page}-PIP and CMS routing support --- diff --git a/com.woltlab.wcf/templates/cms.tpl b/com.woltlab.wcf/templates/cms.tpl new file mode 100644 index 0000000000..d92be9d231 --- /dev/null +++ b/com.woltlab.wcf/templates/cms.tpl @@ -0,0 +1,59 @@ +{include file='documentHeader'} + + + {if !$page->isLandingPage}{$content[title]} - {/if}{PAGE_TITLE|language} + + {include file='headInclude'} + + + + + + +{include file='header'} + +{if $page->isLandingPage} +
+

{PAGE_TITLE|language}

+ {hascontent}

{content}{PAGE_DESCRIPTION|language}{/content}

{/hascontent} +
+{else} +
+

{$content[title]}

+
+{/if} + +{include file='userNotice'} + +
+ {hascontent} + + {/hascontent} +
+ +
+ {@$content[content]} +
+ +
+ {hascontent} + + {/hascontent} +
+ +{include file='footer'} + + + diff --git a/wcfsetup/install/files/lib/data/page/Page.class.php b/wcfsetup/install/files/lib/data/page/Page.class.php index d0f8a83491..5f4cf10a82 100644 --- a/wcfsetup/install/files/lib/data/page/Page.class.php +++ b/wcfsetup/install/files/lib/data/page/Page.class.php @@ -1,6 +1,7 @@ prepareStatement($sql); - $statement->execute(array($this->pageID)); + $statement->execute([$this->pageID]); while ($row = $statement->fetchArray()) { - $content[($row['languageID'] ?: 0)] = array( + $content[($row['languageID'] ?: 0)] = [ 'title' => $row['title'], 'content' => $row['content'], 'metaDescription' => $row['metaDescription'], 'metaKeywords' => $row['metaKeywords'], 'customURL' => $row['customURL'] - ); + ]; } return $content; } + /** + * Returns content for a single language, passing `null` for `$languageID` is undefined + * for multilingual pages. + * + * @param integer $languageID language id or `null` if there are no localized versions + * @return string[] page content data + * @throws \wcf\system\database\DatabaseException + */ + public function getPageContentByLanguage($languageID = null) { + $conditions = new PreparedStatementConditionBuilder(); + $conditions->add("pageID = ?", [$this->pageID]); + if ($this->isMultilingual) $conditions->add("languageID = ?", [$languageID]); + else $conditions->add("languageID IS NULL"); + + $sql = "SELECT * + FROM wcf".WCF_N."_page_content + ".$conditions; + $statement = WCF::getDB()->prepareStatement($sql, 1); + $statement->execute($conditions->getParameters()); + $row = $statement->fetchSingleRow(); + + return ($row !== false) ? $row : []; + } + /** * Returns the page URL. * @@ -84,6 +110,22 @@ class Page extends DatabaseObject { // @todo } + /** + * Returns the page with the given identifier. + * + * @param string $identifier unique page identifier + * @return Page + */ + public static function getPageByIdentifier($identifier) { + $sql = "SELECT * + FROM wcf".WCF_N."_page + WHERE identifier = ?"; + $statement = WCF::getDB()->prepareStatement($sql); + $statement->execute([$identifier]); + + return $statement->fetchObject(Page::class); + } + /** * Returns the page with the given name. * @@ -95,10 +137,8 @@ class Page extends DatabaseObject { FROM wcf".WCF_N."_page WHERE name = ?"; $statement = WCF::getDB()->prepareStatement($sql); - $statement->execute(array($name)); - $row = $statement->fetchArray(); - if ($row !== false) return new Page(null, $row); + $statement->execute([$name]); - return null; + return $statement->fetchObject(Page::class); } } diff --git a/wcfsetup/install/files/lib/page/CmsPage.class.php b/wcfsetup/install/files/lib/page/CmsPage.class.php new file mode 100644 index 0000000000..df64878fdc --- /dev/null +++ b/wcfsetup/install/files/lib/page/CmsPage.class.php @@ -0,0 +1,79 @@ + + * @package com.woltlab.wcf + * @subpackage page + * @category Community Framework + */ +class CmsPage extends AbstractPage { + /** + * @var string[] + */ + public $content; + + /** + * @var integer + */ + public $languageID; + + /** + * @var Page + */ + public $page; + + /** + * @var integer + */ + public $pageID; + + /** + * @inheritDoc + * @throws IllegalLinkException + */ + public function readParameters() { + parent::readParameters(); + + if (isset($_GET['languageID'])) $this->languageID = intval($_GET['languageID']); + if (isset($_GET['pageID'])) $this->pageID = intval($_GET['pageID']); + + if ($this->pageID) { + $this->page = new Page($this->pageID); + } + + if ($this->page === null) { + throw new IllegalLinkException(); + } + + $this->content = $this->page->getPageContentByLanguage($this->languageID); + if (empty($this->content)) { + throw new IllegalLinkException(); + } + + $this->canonicalURL = LinkHandler::getInstance()->getCmsLink($this->pageID, $this->languageID); + } + + /** + * @inheritDoc + */ + public function assignVariables() { + parent::assignVariables(); + + WCF::getTPL()->assign([ + 'canonicalURL' => $this->canonicalURL, + 'content' => $this->content, + 'contentLanguageID' => $this->languageID, + 'page' => $this->page, + 'pageID' => $this->pageID + ]); + } +} diff --git a/wcfsetup/install/files/lib/system/cache/builder/RoutingCacheBuilder.class.php b/wcfsetup/install/files/lib/system/cache/builder/RoutingCacheBuilder.class.php index 01f30355e8..6dd4523bfb 100644 --- a/wcfsetup/install/files/lib/system/cache/builder/RoutingCacheBuilder.class.php +++ b/wcfsetup/install/files/lib/system/cache/builder/RoutingCacheBuilder.class.php @@ -143,7 +143,7 @@ class RoutingCacheBuilder extends AbstractCacheBuilder { $data['reverse'][$abbreviations[$packageID]][preg_replace('~^.*?([A-Za-z0-9]+)(?:Action|Form|Page)~', '$1', $row['controller'])] = $customUrl; } else { - $cmsIdentifier = '__WCF_CMS__' . $row['pageID'] . '-' . $row['languageID']; + $cmsIdentifier = '__WCF_CMS__' . $row['pageID'] . '-' . ($row['languageID'] ?: 0); $data['lookup'][$abbreviations[$packageID]][$customUrl] = $cmsIdentifier; $data['reverse'][$abbreviations[$packageID]][$cmsIdentifier] = $customUrl; } diff --git a/wcfsetup/install/files/lib/system/request/CmsLinkHandler.class.php b/wcfsetup/install/files/lib/system/request/CmsLinkHandler.class.php new file mode 100644 index 0000000000..08c95dd734 --- /dev/null +++ b/wcfsetup/install/files/lib/system/request/CmsLinkHandler.class.php @@ -0,0 +1,11 @@ +getLink('Cms', [ + 'application' => '' + ]); + } +} diff --git a/wcfsetup/install/files/lib/system/request/ControllerMap.class.php b/wcfsetup/install/files/lib/system/request/ControllerMap.class.php index 3a7a662c1f..3dcb0149bd 100644 --- a/wcfsetup/install/files/lib/system/request/ControllerMap.class.php +++ b/wcfsetup/install/files/lib/system/request/ControllerMap.class.php @@ -1,9 +1,9 @@ ciControllers = RoutingCacheBuilder::getInstance()->getData([], 'ciControllers'); $this->customUrls = RoutingCacheBuilder::getInstance()->getData([], 'customUrls'); @@ -92,9 +102,10 @@ class ControllerMap extends SingletonFactory { if (isset($this->customUrls['lookup'][$application]) && isset($this->customUrls['lookup'][$application][$controller])) { $data = $this->customUrls['lookup'][$application][$controller]; if (preg_match('~^__WCF_CMS__(?P\d+)-(?P\d+)$~', $data, $matches)) { - // TODO: this does not work, it should match the returned array below return [ - 'controller' => '\\wcf\\page\\CmsPage', + 'className' => CmsPage::class, + 'controller' => 'cms', + 'pageType' => 'page', 'languageID' => $matches['languageID'], 'pageID' => $matches['pageID'] ]; @@ -144,6 +155,28 @@ class ControllerMap extends SingletonFactory { return $urlController; } + /** + * Looks up a cms page URL, returns an array containing the application identifier + * and url controller name or null if there was no match. + * + * @param integer $pageID page id + * @param integer $languageID content language id + * @return string[]|null + */ + public function lookupCmsPage($pageID, $languageID) { + $key = '__WCF_CMS__' . $pageID . '-' . ($languageID ?: 0); + foreach ($this->customUrls['reverse'] as $application => $reverseURLs) { + if (isset($reverseURLs[$key])) { + return [ + 'application' => $application, + 'controller' => $reverseURLs[$key] + ]; + } + } + + return null; + } + /** * Returns the class data for the active request or null if for the given * configuration no proper class exist. diff --git a/wcfsetup/install/files/lib/system/request/LinkHandler.class.php b/wcfsetup/install/files/lib/system/request/LinkHandler.class.php index 0b53908a16..5f7306fc45 100644 --- a/wcfsetup/install/files/lib/system/request/LinkHandler.class.php +++ b/wcfsetup/install/files/lib/system/request/LinkHandler.class.php @@ -2,6 +2,7 @@ namespace wcf\system\request; use wcf\data\DatabaseObjectDecorator; use wcf\system\application\ApplicationHandler; +use wcf\system\language\LanguageFactory; use wcf\system\menu\page\PageMenu; use wcf\system\Regex; use wcf\system\SingletonFactory; @@ -214,4 +215,54 @@ class LinkHandler extends SingletonFactory { return $url; } + + /** + * Returns the full URL to a CMS page. The `$languageID` parameter is optional and if not + * present (or the integer value `-1` is given) will cause the handler to pick the correct + * language version based upon the user's language. + * + * Passing in an illegal page id will cause this method to fail silently, returning an + * empty string. + * + * @param integer $pageID page id + * @param integer $languageID language id, optional + * @return string full URL of empty string if `$pageID` is invalid + * @throws \wcf\system\exception\SystemException + */ + public function getCmsLink($pageID, $languageID = -1) { + // use current language + if ($languageID === -1) { + $data = ControllerMap::getInstance()->lookupCmsPage($pageID, WCF::getLanguage()->languageID); + + // no result + if ($data === null) { + // attempt to use the default language instead + if (LanguageFactory::getInstance()->getDefaultLanguageID() != WCF::getLanguage()->languageID) { + $data = ControllerMap::getInstance()->lookupCmsPage($pageID, LanguageFactory::getInstance()->getDefaultLanguageID()); + } + + // no result, possibly this is a non-multilingual page + if ($data === null) { + $data = ControllerMap::getInstance()->lookupCmsPage($pageID, null); + } + + // still no result, page does not exist at all + if ($data === null) { + return ''; + } + } + } + else { + $data = ControllerMap::getInstance()->lookupCmsPage($pageID, $languageID); + + // no result, page does not exist or at least not in the given language + if ($data === null) { + return ''; + } + } + + return $this->getLink($data['controller'], [ + 'application' => $data['application'] + ]); + } } diff --git a/wcfsetup/install/files/lib/system/request/RequestHandler.class.php b/wcfsetup/install/files/lib/system/request/RequestHandler.class.php index c30085a1f5..7256ed8b5e 100644 --- a/wcfsetup/install/files/lib/system/request/RequestHandler.class.php +++ b/wcfsetup/install/files/lib/system/request/RequestHandler.class.php @@ -173,6 +173,7 @@ class RequestHandler extends SingletonFactory { $this->activeRequest = new Request($classData['className'], $classData['controller'], $classData['pageType']); } catch (SystemException $e) { + die("
".$e->getMessage());
 			throw new IllegalLinkException();
 		}
 	}
@@ -243,7 +244,7 @@ class RequestHandler extends SingletonFactory {
 		// set default controller
 		$applicationObj = WCF::getApplicationObject(ApplicationHandler::getInstance()->getApplication($application));
 		$routeData['controller'] = preg_replace('~^.*?\\\([^\\\]+)(?:Action|Form|Page)$~', '\\1', $applicationObj->getPrimaryController());
-		$routeData['controller'] = ControllerMap::getInstance()->lookup($routeData['controller']);
+		$routeData['controller'] = ControllerMap::getInstance()->lookup($application, $routeData['controller']);
 	}
 	
 	/**
diff --git a/wcfsetup/install/files/lib/system/template/plugin/PageBlockTemplatePlugin.class.php b/wcfsetup/install/files/lib/system/template/plugin/PageBlockTemplatePlugin.class.php
new file mode 100644
index 0000000000..b67c8317f6
--- /dev/null
+++ b/wcfsetup/install/files/lib/system/template/plugin/PageBlockTemplatePlugin.class.php
@@ -0,0 +1,91 @@
+
+ * @package	com.woltlab.wcf
+ * @subpackage	system.template.plugin
+ * @category	Community Framework
+ */
+class PageBlockTemplatePlugin implements IBlockTemplatePlugin {
+	/**
+	 * internal loop counter
+	 * @var	integer
+	 */
+	protected $counter = 0;
+	
+	/**
+	 * @inheritDoc
+	 */
+	public function execute($tagArgs, $blockContent, TemplateEngine $tplObj) {
+		$pageID = null;
+		if (!empty($tagArgs['pageID'])) {
+			$pageID = intval($tagArgs['pageID']);
+		}
+		else if (!empty($blockContent)) {
+			$page = Page::getPageByIdentifier($blockContent);
+			$pageID = ($page) ? $page->pageID : 0;
+		}
+		
+		if ($pageID === null) {
+			throw new SystemException("Missing 'pageID' attribute or unique identifier.");
+		}
+		
+		$languageID = -1;
+		if (!empty($tagArgs['languageID'])) {
+			$languageID = intval($tagArgs['languageID']);
+		}
+		else if (!empty($tagArgs['language'])) {
+			$language = LanguageFactory::getInstance()->getLanguageByCode($tagArgs['language']);
+			if ($language !== null) $languageID = $language->languageID;
+		}
+		
+		return LinkHandler::getInstance()->getCmsLink($pageID, $languageID);
+	}
+	
+	/**
+	 * @inheritDoc
+	 */
+	public function init($tagArgs, TemplateEngine $tplObj) {
+		$this->counter = 0;
+	}
+	
+	/**
+	 * @inheritDoc
+	 */
+	public function next(TemplateEngine $tplObj) {
+		if ($this->counter == 0) {
+			$this->counter++;
+			return true;
+		}
+		
+		return false;
+	}
+}
diff --git a/wcfsetup/install/files/style/layout/global.scss b/wcfsetup/install/files/style/layout/global.scss
index 8925b8e124..0634df45ee 100644
--- a/wcfsetup/install/files/style/layout/global.scss
+++ b/wcfsetup/install/files/style/layout/global.scss
@@ -121,3 +121,56 @@ strong {
 		}
 	}
 }
+
+.nativeList {
+	margin: 1em 0 1em 40px;
+	
+	ul,
+	ol {
+		margin-bottom: 0;
+		margin-top: 0;
+	}
+	
+	li {
+		margin: 5px 0;
+	}
+}
+
+ul.nativeList {
+	list-style-type: disc;
+}
+ol.nativeList {
+	list-style-type: decimal;
+}
+
+/* simulate native HTML styles for certain elements */
+.htmlContent {
+	p {
+		margin: 1em 0;
+	}
+	
+	h1 {
+		@extend .wcfFontTitle;
+	}
+	
+	h2 {
+		@extend .wcfFontHeadline;
+	}
+	
+	h1, h2, h3, h4, h5, h6 {
+		font-weight: bold;
+		margin: 0.5em 0;
+	}
+	
+	ul, ol {
+		@extend .nativeList;
+	}
+	
+	ul {
+		list-style-type: disc;
+	}
+	
+	ol {
+		list-style-type: decimal;
+	}
+}