Prevent access to content in disabled languages
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / page / AbstractArticlePage.class.php
1 <?php
2 namespace wcf\page;
3 use wcf\data\article\category\ArticleCategory;
4 use wcf\data\article\content\ViewableArticleContent;
5 use wcf\data\article\AccessibleArticleList;
6 use wcf\data\article\ArticleEditor;
7 use wcf\data\article\ViewableArticle;
8 use wcf\data\tag\Tag;
9 use wcf\system\database\util\PreparedStatementConditionBuilder;
10 use wcf\system\exception\IllegalLinkException;
11 use wcf\system\exception\PermissionDeniedException;
12 use wcf\system\language\LanguageFactory;
13 use wcf\system\page\PageLocationManager;
14 use wcf\system\tagging\TagEngine;
15 use wcf\system\WCF;
16
17 /**
18 * Abstract implementation of the article page.
19 *
20 * @author Marcel Werk
21 * @copyright 2001-2017 WoltLab GmbH
22 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
23 * @package WoltLabSuite\Core\Page
24 * @since 3.0
25 */
26 abstract class AbstractArticlePage extends AbstractPage {
27 /**
28 * @inheritDoc
29 */
30 public $neededModules = ['MODULE_ARTICLE'];
31
32 /**
33 * article content id
34 * @var integer
35 */
36 public $articleContentID = 0;
37
38 /**
39 * article content object
40 * @var ViewableArticleContent
41 */
42 public $articleContent;
43
44 /**
45 * article object
46 * @var ViewableArticle
47 */
48 public $article;
49
50 /**
51 * list of tags
52 * @var Tag[]
53 */
54 public $tags = [];
55
56 /**
57 * category object
58 * @var ArticleCategory
59 */
60 public $category;
61
62 /**
63 * list of related articles
64 * @var AccessibleArticleList
65 */
66 public $relatedArticles;
67
68 /**
69 * @inheritDoc
70 */
71 public function readParameters() {
72 parent::readParameters();
73
74 if (isset($_REQUEST['id'])) $this->articleContentID = intval($_REQUEST['id']);
75 $this->articleContent = ViewableArticleContent::getArticleContent($this->articleContentID);
76 if ($this->articleContent === null) {
77 throw new IllegalLinkException();
78 }
79
80 // check if the language has been disabled
81 if ($this->articleContent->languageID && LanguageFactory::getInstance()->getLanguage($this->articleContent->languageID) === null) {
82 throw new IllegalLinkException();
83 }
84
85 $this->article = ViewableArticle::getArticle($this->articleContent->articleID, false);
86 $this->category = $this->article->getCategory();
87
88 // update interface language
89 if (!WCF::getUser()->userID && $this->article->isMultilingual && $this->articleContent->languageID != WCF::getLanguage()->languageID) {
90 WCF::setLanguage($this->articleContent->languageID);
91 }
92 }
93
94 /**
95 * @inheritDoc
96 */
97 public function checkPermissions() {
98 parent::checkPermissions();
99
100 if (!$this->article->canRead()) {
101 throw new PermissionDeniedException();
102 }
103 }
104
105 /**
106 * @inheritDoc
107 */
108 public function readData() {
109 parent::readData();
110
111 // update view count
112 $articleEditor = new ArticleEditor($this->article->getDecoratedObject());
113 $articleEditor->updateCounters([
114 'views' => 1
115 ]);
116
117 // get tags
118 if (MODULE_TAGGING && WCF::getSession()->getPermission('user.tag.canViewTag')) {
119 $this->tags = TagEngine::getInstance()->getObjectTags(
120 'com.woltlab.wcf.article',
121 $this->articleContent->articleContentID,
122 [$this->articleContent->languageID ?: LanguageFactory::getInstance()->getDefaultLanguageID()]
123 );
124 }
125
126 // get related articles
127 if (MODULE_TAGGING && ARTICLE_RELATED_ARTICLES) {
128 if (!empty($this->tags)) {
129 $conditionBuilder = new PreparedStatementConditionBuilder();
130 $conditionBuilder->add('objectTypeID = ?', [TagEngine::getInstance()->getObjectTypeID('com.woltlab.wcf.article')]);
131 $conditionBuilder->add('tagID IN (?)', [array_keys($this->tags)]);
132 $conditionBuilder->add('objectID <> ?', [$this->articleContentID]);
133 $sql = "SELECT objectID, COUNT(*) AS count
134 FROM wcf" . WCF_N . "_tag_to_object
135 " . $conditionBuilder . "
136 GROUP BY objectID
137 HAVING COUNT(*) >= " . round(count($this->tags) * ARTICLE_RELATED_ARTICLES_MATCH_THRESHOLD / 100) . "
138 ORDER BY count DESC";
139 $statement = WCF::getDB()->prepareStatement($sql, ARTICLE_RELATED_ARTICLES);
140 $statement->execute($conditionBuilder->getParameters());
141 $articleContentIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
142
143 if (!empty($articleContentIDs)) {
144 $conditionBuilder = new PreparedStatementConditionBuilder();
145 $conditionBuilder->add('articleContentID IN (?)', [$articleContentIDs]);
146 $sql = "SELECT articleID
147 FROM wcf" . WCF_N . "_article_content
148 " . $conditionBuilder;
149 $statement = WCF::getDB()->prepareStatement($sql);
150 $statement->execute($conditionBuilder->getParameters());
151 $articleIDs = $statement->fetchAll(\PDO::FETCH_COLUMN);
152
153 $this->relatedArticles = new AccessibleArticleList();
154 $this->relatedArticles->getConditionBuilder()->add('article.articleID IN (?)', [$articleIDs]);
155 $this->relatedArticles->sqlOrderBy = 'article.time';
156 $this->relatedArticles->readObjects();
157 }
158 }
159 }
160
161 // set location
162 PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.CategoryArticleList', $this->article->categoryID, $this->article->getCategory());
163 foreach (array_reverse($this->article->getCategory()->getParentCategories()) as $parentCategory) {
164 PageLocationManager::getInstance()->addParentLocation('com.woltlab.wcf.CategoryArticleList', $parentCategory->categoryID, $parentCategory);
165 }
166 }
167
168 /**
169 * @inheritDoc
170 */
171 public function assignVariables() {
172 parent::assignVariables();
173
174 WCF::getTPL()->assign([
175 'articleContentID' => $this->articleContentID,
176 'articleContent' => $this->articleContent,
177 'article' => $this->article,
178 'category' => $this->category,
179 'relatedArticles' => $this->relatedArticles,
180 'tags' => $this->tags
181 ]);
182 }
183 }