--- /dev/null
+<?php
+namespace wcf\data;
+use wcf\data\user\User;
+
+/**
+ * Interface for objects whose access is restrictable so that access for every user
+ * has to be checked separately.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Data
+ * @since 3.0
+ */
+interface IAccessibleObject {
+ /**
+ * Returns `true` if the given user can access the object.
+ *
+ * @param User $user checked user, if `null` active user is used instead
+ * @return boolean
+ */
+ public function isAccessible(User $user = null);
+}
\ No newline at end of file
<?php
namespace wcf\data\article\category;
use wcf\data\category\AbstractDecoratedCategory;
+use wcf\data\IAccessibleObject;
use wcf\data\user\User;
use wcf\data\user\UserProfile;
use wcf\data\ITitledLinkObject;
* @method ArticleCategory[] getParentCategories()
* @method static ArticleCategory|null getCategory($categoryID)
*/
-class ArticleCategory extends AbstractDecoratedCategory implements ITitledLinkObject {
+class ArticleCategory extends AbstractDecoratedCategory implements IAccessibleObject, ITitledLinkObject {
/**
* object type name of the article categories
* @var string
protected $userPermissions = [];
/**
- * Returns true if the category is accessible for the active user.
- *
- * @param User $user
- * @return boolean
+ * @inheritDoc
*/
public function isAccessible(User $user = null) {
if ($this->getObjectType()->objectType != self::OBJECT_TYPE_NAME) return false;
*/
public function getLink() {
return LinkHandler::getInstance()->getLink('CategoryArticleList', [
+ 'forceFrontend' => true,
'object' => $this->getDecoratedObject()
]);
}
<?php
namespace wcf\system\page\handler;
use wcf\data\article\category\ArticleCategory;
-use wcf\data\object\type\ObjectTypeCache;
-use wcf\data\page\Page;
-use wcf\data\user\online\UserOnline;
-use wcf\system\database\util\PreparedStatementConditionBuilder;
use wcf\system\request\LinkHandler;
-use wcf\system\WCF;
/**
* Menu page handler for the category article list page.
* @since 3.0
*/
class CategoryArticleListPageHandler extends AbstractLookupPageHandler implements IOnlineLocationPageHandler {
- use TOnlineLocationPageHandler;
+ use TDecoratedCategoryOnlineLocationLookupPageHandler;
/**
- * @inheritDoc
+ * @see TDecoratedCategoryLookupPageHandler::getDecoratedCategoryClass()
*/
- public function getLink($objectID) {
- return LinkHandler::getInstance()->getLink('CategoryArticleList', [
- 'object' => ArticleCategory::getCategory($objectID),
- 'forceFrontend' => true
- ]);
- }
-
- /**
- * @inheritDoc
- */
- public function isValid($objectID) {
- return ArticleCategory::getCategory($objectID) !== null;
- }
-
- /** @noinspection PhpMissingParentCallCommonInspection */
- /**
- * @inheritDoc
- */
- public function isVisible($objectID = null) {
- return ArticleCategory::getCategory($objectID)->isAccessible();
- }
-
- /**
- * @inheritDoc
- */
- public function lookup($searchString) {
- $conditionBuilder = new PreparedStatementConditionBuilder();
- $conditionBuilder->add('category.objectTypeID = ?', [ObjectTypeCache::getInstance()->getObjectTypeIDByName('com.woltlab.wcf.category', 'com.woltlab.wcf.article.category')]);
- $conditionBuilder->add('(category.title LIKE ? OR language_item.languageItemValue LIKE ?)', ['%' . $searchString . '%', '%' . $searchString . '%']);
- $sql = "SELECT DISTINCT categoryID
- FROM wcf".WCF_N."_category category
- LEFT JOIN wcf".WCF_N."_language_item language_item
- ON (language_item.languageItem = category.title)
- ".$conditionBuilder;
- $statement = WCF::getDB()->prepareStatement($sql, 10);
- $statement->execute($conditionBuilder->getParameters());
- $results = [];
- while ($categoryID = $statement->fetchColumn()) {
- $category = ArticleCategory::getCategory($categoryID);
-
- // build hierarchy
- $description = '';
- foreach ($category->getParentCategories() as $parentCategory) {
- $description .= $parentCategory->getTitle() . ' » ';
- }
-
- $results[] = [
- 'description' => $description,
- 'image' => 'fa-folder-open-o',
- 'link' => $category->getLink(),
- 'objectID' => $categoryID,
- 'title' => $category->getTitle()
- ];
- }
-
- return $results;
- }
-
- /**
- * @inheritDoc
- */
- public function getOnlineLocation(Page $page, UserOnline $user) {
- if ($user->pageObjectID === null) {
- return '';
- }
-
- $category = ArticleCategory::getCategory($user->pageObjectID);
- if ($category === null || !$category->isAccessible()) {
- return '';
- }
-
- return WCF::getLanguage()->getDynamicVariable('wcf.page.onlineLocation.'.$page->identifier, ['category' => $category]);
+ protected function getDecoratedCategoryClass() {
+ return ArticleCategory::class;
}
}
--- /dev/null
+<?php
+namespace wcf\system\page\handler;
+use wcf\data\category\AbstractDecoratedCategory;
+use wcf\data\ILinkableObject;
+use wcf\data\object\type\ObjectTypeCache;
+use wcf\system\database\util\PreparedStatementConditionBuilder;
+use wcf\system\exception\ParentClassException;
+use wcf\system\WCF;
+
+/**
+ * Provides the `isValid` and `lookup` methods for looking up decorated categories.
+ *
+ * Note: This only works in the class extends `AbstractDecoratedCategory` and defines a
+ * constant `OBJECT_TYPE_NAME` with the name of the `com.woltlab.wcf.category` object type.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Page\Handler
+ * @since 3.0
+ */
+trait TDecoratedCategoryLookupPageHandler {
+ /**
+ * Returns the name of the decorated class name.
+ *
+ * @return string
+ */
+ abstract protected function getDecoratedCategoryClass();
+
+ /**
+ * @see ILookupPageHandler::getLink()
+ */
+ public function getLink($objectID) {
+ $className = $this->getDecoratedCategoryClass();
+ $category = $className::getCategory($objectID);
+
+ if ($category instanceof ILinkableObject) {
+ return $category->getLink();
+ }
+
+ throw new \LogicException("If '" . $className . "' does not implement '" . ILinkableObject::class . "', the 'getLink' method needs to be overwritten.");
+ }
+
+ /**
+ * @see ILookupPageHandler::isValid()
+ */
+ public function isValid($objectID = null) {
+ $className = $this->getDecoratedCategoryClass();
+
+ return $className::getCategory($objectID)->isAccessible();
+ }
+
+ /**
+ * @see ILookupPageHandler::lookup()
+ */
+ public function lookup($searchString) {
+ $className = $this->getDecoratedCategoryClass();
+ if (!is_subclass_of($className, AbstractDecoratedCategory::class)) {
+ throw new ParentClassException($className, AbstractDecoratedCategory::class);
+ }
+
+ $conditionBuilder = new PreparedStatementConditionBuilder();
+ $conditionBuilder->add('category.objectTypeID = ?', [ObjectTypeCache::getInstance()->getObjectTypeIDByName('com.woltlab.wcf.category', $className::OBJECT_TYPE_NAME)]);
+ $conditionBuilder->add('(category.title LIKE ? OR language_item.languageItemValue LIKE ?)', ['%' . $searchString . '%', '%' . $searchString . '%']);
+ $sql = "SELECT DISTINCT categoryID
+ FROM wcf".WCF_N."_category category
+ LEFT JOIN wcf".WCF_N."_language_item language_item
+ ON (language_item.languageItem = category.title)
+ ".$conditionBuilder;
+ $statement = WCF::getDB()->prepareStatement($sql, 10);
+ $statement->execute($conditionBuilder->getParameters());
+ $results = [];
+ while ($categoryID = $statement->fetchColumn()) {
+ /** @var AbstractDecoratedCategory $category */
+ $category = $className::getCategory($categoryID);
+
+ // build hierarchy
+ $description = '';
+ foreach ($category->getParentCategories() as $parentCategory) {
+ $description .= $parentCategory->getTitle() . ' » ';
+ }
+
+ $results[] = [
+ 'description' => $description,
+ 'image' => 'fa-folder-open-o',
+ 'link' => $category->getLink(),
+ 'objectID' => $categoryID,
+ 'title' => $category->getTitle()
+ ];
+ }
+
+ return $results;
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+namespace wcf\system\page\handler;
+use wcf\data\category\AbstractDecoratedCategory;
+use wcf\data\IAccessibleObject;
+
+/**
+ * Implementation of the `IMenuPageHandler::isVisible()` methods for decorated category-bound pages.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Page\Handler
+ * @since 3.0
+ */
+trait TDecoratedCategoryMenuPageHandler {
+ /**
+ * Returns the name of the decorated class name.
+ *
+ * @return string
+ */
+ abstract protected function getDecoratedCategoryClass();
+
+ /**
+ * @see IMenuPageHandler::isVisible()
+ */
+ public function isVisible($objectID = null) {
+ $className = $this->getDecoratedCategoryClass();
+
+ /** @var AbstractDecoratedCategory $category */
+ $category = $className::getCategory($objectID);
+
+ // check if category exists
+ if ($category === null) {
+ return false;
+ }
+
+ // check if access to category is restricted
+ if ($category instanceof IAccessibleObject && !$className->isAccessible()) {
+ return false;
+ }
+
+ // fallback to default value of AbstractMenuPageHandler::isVisible()
+ return true;
+ }
+}
\ No newline at end of file
--- /dev/null
+<?php
+namespace wcf\system\page\handler;
+
+/**
+ * Implementation of the `IOnlineLocationPageHandler` and `ILookupPageHandler` interfaces
+ * and implementing the `IMenuPageHandler::isVisible()` method..
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Page\Handler
+ * @since 3.0
+ */
+trait TDecoratedCategoryOnlineLocationLookupPageHandler {
+ use TDecoratedCategoryOnlineLocationPageHandler;
+ use TDecoratedCategoryLookupPageHandler;
+ use TDecoratedCategoryMenuPageHandler;
+}
--- /dev/null
+<?php
+namespace wcf\system\page\handler;
+use wcf\data\category\AbstractDecoratedCategory;
+use wcf\data\IAccessibleObject;
+use wcf\data\page\Page;
+use wcf\data\user\online\UserOnline;
+use wcf\system\exception\ParentClassException;
+use wcf\system\WCF;
+
+/**
+ * Implementation of the `IOnlineLocationPageHandler` interface for decorated category-bound pages.
+ *
+ * @author Matthias Schmidt
+ * @copyright 2001-2016 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\System\Page\Handler
+ * @since 3.0
+ */
+trait TDecoratedCategoryOnlineLocationPageHandler {
+ use TOnlineLocationPageHandler;
+
+ /**
+ * Returns the name of the decorated class name.
+ *
+ * @return string
+ */
+ abstract protected function getDecoratedCategoryClass();
+
+ /**
+ * @see IOnlineLocationPageHandler::getOnlineLocation()
+ */
+ public function getOnlineLocation(Page $page, UserOnline $user) {
+ if ($user->pageObjectID === null) {
+ return '';
+ }
+
+ $className = $this->getDecoratedCategoryClass();
+ if (!is_subclass_of($className, AbstractDecoratedCategory::class)) {
+ throw new ParentClassException($className, AbstractDecoratedCategory::class);
+ }
+
+ /** @var AbstractDecoratedCategory $category */
+ $category = $className::getCategory($user->pageObjectID);
+ if ($category === null) {
+ return '';
+ }
+
+ if ($category instanceof IAccessibleObject && !$category->isAccessible()) {
+ return null;
+ }
+
+ return WCF::getLanguage()->getDynamicVariable('wcf.page.onlineLocation.'.$page->identifier, ['category' => $category]);
+ }
+}
\ No newline at end of file