{@$articleContent->getFormattedContent()}
</div>
</article>
-
+
+{hascontent}
+ <section class="section">
+ <h2 class="sectionTitle">{lang}wcf.article.moreArticles{/lang}</h2>
+
+ <amp-carousel width="400" height="300" layout="responsive" type="slides" autoplay delay="5000">
+ {content}
+ {foreach from=$additionalArticles item='additionalArticle'}
+ {if $additionalArticle->getImage()}
+ <a href="{link controller='ArticleAmp' object=$additionalArticle->getArticleContent()}{/link}">
+ <figure>
+ <amp-img src="{$additionalArticle->getImage()->getThumbnailLink('large')}" layout="fill"></amp-img>
+ <figcaption>{$additionalArticle->getTitle()}</figcaption>
+ </figure>
+ </a>
+ {/if}
+ {/foreach}
+ {/content}
+ </amp-carousel>
+ </section>
+{/hascontent}
+
+{if $relatedArticles|count}
+ {hascontent}
+ <section class="section">
+ <h2 class="sectionTitle">{lang}wcf.article.relatedArticles{/lang}</h2>
+
+ <amp-carousel width="400" height="300" layout="responsive" type="slides" autoplay delay="5000">
+ {content}
+ {foreach from=$relatedArticles item='relatedArticle'}
+ {if $relatedArticle->getImage()}
+ <a href="{link controller='ArticleAmp' object=$relatedArticle->getArticleContent()}{/link}">
+ <figure>
+ <amp-img src="{$relatedArticle->getImage()->getThumbnailLink('large')}" layout="fill"></amp-img>
+ <figcaption>{$relatedArticle->getTitle()}</figcaption>
+ </figure>
+ </a>
+ {/if}
+ {/foreach}
+ {/content}
+ </amp-carousel>
+ </section>
+ {/hascontent}
+{/if}
+
{include file='ampFooter'}
padding: 30px 10px;
}
+ .section {
+ margin-top: 30px;
+ }
+
+ .sectionTitle {
+ font-weight: 300;
+ font-size: 23px;
+ line-height: 1.05;
+ margin: 0;
+ }
+
.article .articleTitle {
font-weight: 300;
font-size: 23px;
color: rgb(125, 130, 135);
}
+ .article .articleImage {
+ margin: 0;
+ }
+
+ .article .articleImage figcaption {
+ color: rgb(125, 130, 135);
+ font-size: smaller;
+ margin-top: 5px;
+ text-align: center;
+ }
+
.article .articleImage,
.article .articleContent,
.article .articleTeaser {
padding: 7px 7px 7px 0;
}
+ amp-carousel {
+ margin-top: 20px;
+ }
+
+ amp-carousel figcaption {
+ background-color: rgba(0,0,0,.6);
+ bottom: 0;
+ color: #fff;
+ left: 0;
+ padding: 10px;
+ position: absolute;
+ right: 0;
+ }
+
.breadcrumbs li:nth-child(2) {
padding-left: 20px;
}
}
</style>
{literal}<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>{/literal}
+ <script async custom-element="amp-carousel" src="https://cdn.ampproject.org/v0/amp-carousel-0.1.js"></script>
<script async custom-element="amp-sidebar" src="https://cdn.ampproject.org/v0/amp-sidebar-0.1.js"></script>
<script async custom-element="amp-user-notification" src="https://cdn.ampproject.org/v0/amp-user-notification-0.1.js"></script>
<script async custom-element="amp-analytics" src="https://cdn.ampproject.org/v0/amp-analytics-0.1.js"></script>
--- /dev/null
+<?php
+namespace wcf\page;
+use wcf\data\article\AccessibleArticleList;
+use wcf\data\article\CategoryArticleList;
+use wcf\data\article\content\ViewableArticleContent;
+use wcf\data\article\ArticleEditor;
+use wcf\data\article\ViewableArticle;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\exception\IllegalLinkException;
+use wcf\system\exception\PermissionDeniedException;
+use wcf\system\language\LanguageFactory;
+use wcf\system\page\PageLocationManager;
+use wcf\system\tagging\TagEngine;
+use wcf\system\WCF;
+
+/**
+ * Abstract implementation of the article page.
+ *
+ * @author Marcel Werk
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Page
+ * @since 3.0
+ */
+abstract class AbstractArticlePage extends AbstractPage {
+ /**
+ * @inheritDoc
+ */
+ public $neededModules = ['MODULE_ARTICLE'];
+
+ /**
+ * article content id
+ * @var integer
+ */
+ public $articleContentID = 0;
+
+ /**
+ * article content object
+ * @var ViewableArticleContent
+ */
+ public $articleContent;
+
+ /**
+ * article object
+ * @var ViewableArticle
+ */
+ public $article;
+
+ /**
+ * list of tags
+ * @var Tag[]
+ */
+ public $tags = [];
+
+ /**
+ * category object
+ * @var ArticleCategory
+ */
+ public $category;
+
+ /**
+ * list of related articles
+ * @var AccessibleArticleList
+ */
+ public $relatedArticles;
+
+ /**
+ * @inheritDoc
+ */
+ public function readParameters() {
+ parent::readParameters();
+
+ if (isset($_REQUEST['id'])) $this->articleContentID = intval($_REQUEST['id']);
+ $this->articleContent = ViewableArticleContent::getArticleContent($this->articleContentID);
+ if ($this->articleContent === null) {
+ throw new IllegalLinkException();
+ }
+ $this->article = ViewableArticle::getArticle($this->articleContent->articleID);
+ $this->category = $this->article->getCategory();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function checkPermissions() {
+ parent::checkPermissions();
+
+ if (!$this->article->canRead()) {
+ throw new PermissionDeniedException();
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function readData() {
+ parent::readData();
+
+ // update view count
+ $articleEditor = new ArticleEditor($this->article->getDecoratedObject());
+ $articleEditor->updateCounters([
+ 'views' => 1
+ ]);
+
+ // get tags
+ if (MODULE_TAGGING && WCF::getSession()->getPermission('user.tag.canViewTag')) {
+ $this->tags = TagEngine::getInstance()->getObjectTags(
+ 'com.woltlab.wcf.article',
+ $this->articleContent->articleContentID,
+ [($this->articleContent->languageID ?: LanguageFactory::getInstance()->getDefaultLanguageID())]
+ );
+ }
+
+ // get related articles
+ if (MODULE_TAGGING && ARTICLE_RELATED_ARTICLES) {
+ if (!empty($this->tags)) {
+ $conditionBuilder = new PreparedStatementConditionBuilder();
+ $conditionBuilder->add('objectTypeID = ?', [TagEngine::getInstance()->getObjectTypeID('com.woltlab.wcf.article')]);
+ $conditionBuilder->add('tagID IN (?)', [array_keys($this->tags)]);
+ $conditionBuilder->add('objectID <> ?', [$this->articleContentID]);
+ $sql = "SELECT objectID, COUNT(*) AS count
+ FROM wcf" . WCF_N . "_tag_to_object
+ " . $conditionBuilder . "
+ GROUP BY objectID
+ HAVING COUNT(*) > " . (round(count($this->tags) * (ARTICLE_RELATED_ARTICLES_MATCH_THRESHOLD / 100))) . "
+ ORDER BY count DESC";
+ $statement = WCF::getDB()->prepareStatement($sql, ARTICLE_RELATED_ARTICLES);
+ $statement->execute($conditionBuilder->getParameters());
+ $articleContentIDs = [];
+ while ($row = $statement->fetchArray()) {
+ $articleContentIDs[] = $row['objectID'];
+ }
+
+ if (!empty($articleContentIDs)) {
+ $conditionBuilder = new PreparedStatementConditionBuilder();
+ $conditionBuilder->add('articleContentID IN (?)', [$articleContentIDs]);
+ $sql = "SELECT articleID
+ FROM wcf" . WCF_N . "_article_content
+ " . $conditionBuilder;
+ $statement = WCF::getDB()->prepareStatement($sql);
+ $statement->execute($conditionBuilder->getParameters());
+ $articleIDs = [];
+ while ($row = $statement->fetchArray()) {
+ $articleIDs[] = $row['articleID'];
+ }
+
+ $this->relatedArticles = new AccessibleArticleList();
+ $this->relatedArticles->getConditionBuilder()->add('article.articleID IN (?)', [$articleIDs]);
+ $this->relatedArticles->sqlOrderBy = 'article.time';
+ $this->relatedArticles->readObjects();
+ }
+ }
+ }
+
+ // set location
+ PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.CategoryArticleList', $this->article->categoryID, $this->article->getCategory());
+ foreach ($this->article->getCategory()->getParentCategories() as $parentCategory) {
+ PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.CategoryArticleList', $parentCategory->categoryID, $parentCategory);
+ }
+ PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.ArticleList');
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function assignVariables() {
+ parent::assignVariables();
+
+ WCF::getTPL()->assign([
+ 'articleContentID' => $this->articleContentID,
+ 'articleContent' => $this->articleContent,
+ 'article' => $this->article,
+ 'category' => $this->category,
+ 'relatedArticles' => $this->relatedArticles,
+ 'tags' => $this->tags
+ ]);
+ }
+}
<?php
namespace wcf\page;
-use wcf\data\article\content\ViewableArticleContent;
-use wcf\data\article\ArticleEditor;
+use wcf\data\article\CategoryArticleList;
use wcf\data\article\ViewableArticle;
-use wcf\system\exception\IllegalLinkException;
-use wcf\system\exception\PermissionDeniedException;
-use wcf\system\page\PageLocationManager;
+use wcf\system\request\LinkHandler;
use wcf\system\WCF;
/**
* @package WoltLabSuite\Core\Page
* @since 3.0
*/
-class ArticleAmpPage extends AbstractPage {
+class ArticleAmpPage extends AbstractArticlePage {
/**
* @inheritDoc
*/
public $templateName = 'ampArticle';
/**
- * @inheritDoc
- */
- public $neededModules = ['MODULE_ARTICLE'];
-
- /**
- * article content id
- * @var integer
- */
- public $articleContentID = 0;
-
- /**
- * article content object
- * @var ViewableArticleContent
- */
- public $articleContent;
-
- /**
- * article object
- * @var ViewableArticle
+ * list of additional articles
+ * @var ViewableArticle[]
*/
- public $article;
+ public $additionalArticles;
/**
* @inheritDoc
public function readParameters() {
parent::readParameters();
- if (isset($_REQUEST['id'])) $this->articleContentID = intval($_REQUEST['id']);
- $this->articleContent = ViewableArticleContent::getArticleContent($this->articleContentID);
- if ($this->articleContent === null) {
- throw new IllegalLinkException();
- }
- $this->article = ViewableArticle::getArticle($this->articleContent->articleID);
- }
-
- /**
- * @inheritDoc
- */
- public function checkPermissions() {
- parent::checkPermissions();
-
- if (!$this->article->canRead()) {
- throw new PermissionDeniedException();
- }
+ $this->canonicalURL = LinkHandler::getInstance()->getLink('ArticleAmp', ['object' => $this->articleContent]);
}
/**
public function readData() {
parent::readData();
- // update view count
- $articleEditor = new ArticleEditor($this->article->getDecoratedObject());
- $articleEditor->updateCounters([
- 'views' => 1
- ]);
-
- // set location
- PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.CategoryArticleList', $this->article->categoryID, $this->article->getCategory());
- foreach ($this->article->getCategory()->getParentCategories() as $parentCategory) {
- PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.CategoryArticleList', $parentCategory->categoryID, $parentCategory);
- }
- PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.ArticleList');
+ // get next/previous articles
+ $nextArticleList = new CategoryArticleList($this->article->categoryID);
+ $nextArticleList->getConditionBuilder()->add('article.time > ?', [$this->article->time]);
+ $nextArticleList->sqlOrderBy = 'article.time';
+ $nextArticleList->sqlLimit = 3;
+ $nextArticleList->readObjects();
+ $previousArticleList = new CategoryArticleList($this->article->categoryID);
+ $previousArticleList->getConditionBuilder()->add('article.time < ?', [$this->article->time]);
+ $previousArticleList->sqlOrderBy = 'article.time DESC';
+ $previousArticleList->sqlLimit = 3;
+ $previousArticleList->readObjects();
+ $this->additionalArticles = array_merge($nextArticleList->getObjects(), $previousArticleList->getObjects());
}
/**
parent::assignVariables();
WCF::getTPL()->assign([
- 'articleContentID' => $this->articleContentID,
- 'articleContent' => $this->articleContent,
- 'article' => $this->article,
- 'category' => $this->article->getCategory(),
- 'regularCanonicalURL' => $this->articleContent->getLink()
+ 'regularCanonicalURL' => $this->articleContent->getLink(),
+ 'additionalArticles' => $this->additionalArticles
]);
}
}
<?php
namespace wcf\page;
-use wcf\data\article\category\ArticleCategory;
-use wcf\data\article\content\ViewableArticleContent;
-use wcf\data\article\AccessibleArticleList;
-use wcf\data\article\ArticleEditor;
use wcf\data\article\CategoryArticleList;
use wcf\data\article\ViewableArticle;
use wcf\data\comment\StructuredCommentList;
use wcf\data\like\object\LikeObject;
-use wcf\data\tag\Tag;
use wcf\system\comment\manager\ICommentManager;
use wcf\system\comment\CommentHandler;
-use wcf\system\database\util\PreparedStatementConditionBuilder;
-use wcf\system\exception\IllegalLinkException;
-use wcf\system\exception\PermissionDeniedException;
-use wcf\system\language\LanguageFactory;
use wcf\system\like\LikeHandler;
-use wcf\system\page\PageLocationManager;
use wcf\system\request\LinkHandler;
-use wcf\system\tagging\TagEngine;
use wcf\system\MetaTagHandler;
use wcf\system\WCF;
* @package WoltLabSuite\Core\Page
* @since 3.0
*/
-class ArticlePage extends AbstractPage {
- /**
- * @inheritDoc
- */
- public $neededModules = ['MODULE_ARTICLE'];
-
- /**
- * article content id
- * @var integer
- */
- public $articleContentID = 0;
-
- /**
- * article content object
- * @var ViewableArticleContent
- */
- public $articleContent;
-
- /**
- * article object
- * @var ViewableArticle
- */
- public $article;
-
+class ArticlePage extends AbstractArticlePage {
/**
* next article in this category
* @var ViewableArticle
*/
public $commentList;
- /**
- * list of related articles
- * @var AccessibleArticleList
- */
- public $relatedArticles;
-
- /**
- * list of tags
- * @var Tag[]
- */
- public $tags = [];
-
/**
* like data for the article
* @var LikeObject[]
*/
public $articleLikeData = [];
- /**
- * category object
- * @var ArticleCategory
- */
- public $category;
-
/**
* @inheritDoc
*/
public function readParameters() {
parent::readParameters();
- if (isset($_REQUEST['id'])) $this->articleContentID = intval($_REQUEST['id']);
- $this->articleContent = ViewableArticleContent::getArticleContent($this->articleContentID);
- if ($this->articleContent === null) {
- throw new IllegalLinkException();
- }
- $this->article = ViewableArticle::getArticle($this->articleContent->articleID);
$this->canonicalURL = $this->articleContent->getLink();
- $this->category = $this->article->getCategory();
- }
-
- /**
- * @inheritDoc
- */
- public function checkPermissions() {
- parent::checkPermissions();
-
- if (!$this->article->canRead()) {
- throw new PermissionDeniedException();
- }
}
/**
public function readData() {
parent::readData();
- // update view count
- $articleEditor = new ArticleEditor($this->article->getDecoratedObject());
- $articleEditor->updateCounters([
- 'views' => 1
- ]);
-
// get comments
if ($this->article->enableComments) {
$this->commentObjectTypeID = CommentHandler::getInstance()->getObjectTypeID('com.woltlab.wcf.articleComment');
$this->commentList = CommentHandler::getInstance()->getCommentList($this->commentManager, $this->commentObjectTypeID, $this->articleContent->articleContentID);
}
- // get next entry
+ // get next article
$articleList = new CategoryArticleList($this->article->categoryID);
$articleList->getConditionBuilder()->add('article.time > ?', [$this->article->time]);
$articleList->sqlOrderBy = 'article.time';
$articleList->readObjects();
foreach ($articleList as $article) $this->nextArticle = $article;
- // get previous entry
+ // get previous article
$articleList = new CategoryArticleList($this->article->categoryID);
$articleList->getConditionBuilder()->add('article.time < ?', [$this->article->time]);
- $articleList->sqlOrderBy = 'article.time';
+ $articleList->sqlOrderBy = 'article.time DESC';
$articleList->sqlLimit = 1;
$articleList->readObjects();
foreach ($articleList as $article) $this->previousArticle = $article;
- // get tags
- if (MODULE_TAGGING && WCF::getSession()->getPermission('user.tag.canViewTag')) {
- $this->tags = TagEngine::getInstance()->getObjectTags(
- 'com.woltlab.wcf.article',
- $this->articleContent->articleContentID,
- [($this->articleContent->languageID ?: LanguageFactory::getInstance()->getDefaultLanguageID())]
- );
- }
-
- // get related articles
- if (MODULE_TAGGING && ARTICLE_RELATED_ARTICLES) {
- if (!empty($this->tags)) {
- $conditionBuilder = new PreparedStatementConditionBuilder();
- $conditionBuilder->add('objectTypeID = ?', [TagEngine::getInstance()->getObjectTypeID('com.woltlab.wcf.article')]);
- $conditionBuilder->add('tagID IN (?)', [array_keys($this->tags)]);
- $conditionBuilder->add('objectID <> ?', [$this->articleContentID]);
- $sql = "SELECT objectID, COUNT(*) AS count
- FROM wcf" . WCF_N . "_tag_to_object
- " . $conditionBuilder . "
- GROUP BY objectID
- HAVING COUNT(*) > " . (round(count($this->tags) * (ARTICLE_RELATED_ARTICLES_MATCH_THRESHOLD / 100))) . "
- ORDER BY count DESC";
- $statement = WCF::getDB()->prepareStatement($sql, ARTICLE_RELATED_ARTICLES);
- $statement->execute($conditionBuilder->getParameters());
- $articleContentIDs = [];
- while ($row = $statement->fetchArray()) {
- $articleContentIDs[] = $row['objectID'];
- }
-
- if (!empty($articleContentIDs)) {
- $conditionBuilder = new PreparedStatementConditionBuilder();
- $conditionBuilder->add('articleContentID IN (?)', [$articleContentIDs]);
- $sql = "SELECT articleID
- FROM wcf" . WCF_N . "_article_content
- " . $conditionBuilder;
- $statement = WCF::getDB()->prepareStatement($sql);
- $statement->execute($conditionBuilder->getParameters());
- $articleIDs = [];
- while ($row = $statement->fetchArray()) {
- $articleIDs[] = $row['articleID'];
- }
-
- $this->relatedArticles = new AccessibleArticleList();
- $this->relatedArticles->getConditionBuilder()->add('article.articleID IN (?)', [$articleIDs]);
- $this->relatedArticles->sqlOrderBy = 'article.time';
- $this->relatedArticles->readObjects();
- }
- }
- }
-
// fetch likes
if (MODULE_LIKE) {
$objectType = LikeHandler::getInstance()->getObjectType('com.woltlab.wcf.likeableArticle');
$this->articleLikeData = LikeHandler::getInstance()->getLikeObjects($objectType);
}
- // set location
- PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.CategoryArticleList', $this->article->categoryID, $this->article->getCategory());
- foreach ($this->article->getCategory()->getParentCategories() as $parentCategory) {
- PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.CategoryArticleList', $parentCategory->categoryID, $parentCategory);
- }
- PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.ArticleList');
-
// add meta/og tags
MetaTagHandler::getInstance()->addTag('og:title', 'og:title', $this->articleContent->getTitle() . ' - ' . WCF::getLanguage()->get(PAGE_TITLE), true);
MetaTagHandler::getInstance()->addTag('og:url', 'og:url', LinkHandler::getInstance()->getLink('Article', ['object' => $this->articleContent, 'appendSession' => false]), true);
parent::assignVariables();
WCF::getTPL()->assign([
- 'articleContentID' => $this->articleContentID,
- 'articleContent' => $this->articleContent,
- 'article' => $this->article,
- 'category' => $this->article->getCategory(),
'previousArticle' => $this->previousArticle,
'nextArticle' => $this->nextArticle,
'commentCanAdd' => WCF::getSession()->getPermission('user.article.canAddComment'),
'commentObjectTypeID' => $this->commentObjectTypeID,
'lastCommentTime' => ($this->commentList ? $this->commentList->getMinCommentTime() : 0),
'likeData' => ((MODULE_LIKE && $this->commentList) ? $this->commentList->getLikeData() : []),
- 'relatedArticles' => $this->relatedArticles,
- 'tags' => $this->tags,
'articleLikeData' => $this->articleLikeData
]);
}
<item name="wcf.article.nextArticle"><![CDATA[Nächster Artikel]]></item>
<item name="wcf.article.previousArticle"><![CDATA[Vorheriger Artikel]]></item>
<item name="wcf.article.relatedArticles"><![CDATA[Verwandte Artikel]]></item>
+ <item name="wcf.article.moreArticles"><![CDATA[Weitere Artikel]]></item>
<item name="wcf.article.aboutAuthor"><![CDATA[Über den Autor]]></item>
<item name="wcf.article.articleComments"><![CDATA[{#$article->comments} Kommentar{if $article->comments != 1}e{/if}]]></item>
<item name="wcf.article.articleViews"><![CDATA[{#$article->views} mal gelesen]]></item>
<item name="wcf.article.nextArticle"><![CDATA[Next Article]]></item>
<item name="wcf.article.previousArticle"><![CDATA[Previous Article]]></item>
<item name="wcf.article.relatedArticles"><![CDATA[Related Articles]]></item>
+ <item name="wcf.article.moreArticles"><![CDATA[More Articles]]></item>
<item name="wcf.article.aboutAuthor"><![CDATA[About the Author]]></item>
<item name="wcf.article.articleComments"><![CDATA[{#$article->comments} Comment{if $article->comments != 1}s{/if}]]></item>
<item name="wcf.article.articleViews"><![CDATA[{#$article->views} View{if $article->views != 1}s{/if}]]></item>