From fffc2ce7037efbed7ebada268fa4abb98b7fe242 Mon Sep 17 00:00:00 2001 From: Peter Lohse Date: Mon, 22 Dec 2025 11:38:56 +0100 Subject: [PATCH 1/2] PHPStan Level 6 --- .../lib/acp/form/FaqQuestionAddForm.class.php | 30 ++++++++++++++----- .../acp/page/FaqQuestionListPage.class.php | 6 ++-- files/lib/data/faq/Question.class.php | 2 +- files/lib/data/faq/QuestionAction.class.php | 7 ++--- files/lib/data/faq/QuestionEditor.class.php | 8 ++--- files/lib/data/faq/QuestionList.class.php | 6 +--- .../data/faq/category/FaqCategory.class.php | 9 ++++-- .../faq/category/FaqCategoryCache.class.php | 13 ++++++-- files/lib/page/FaqQuestionListPage.class.php | 10 +++++-- .../FaqQuestionAttachmentObjectType.class.php | 4 +++ files/lib/system/bbcode/FaqBBCode.class.php | 2 +- .../box/FaqCategoriesBoxController.class.php | 1 + .../questions/search/GetSearch.class.php | 1 + .../admin/FaqQuestionGridView.class.php | 7 +++-- .../system/search/FaqQuestionSearch.class.php | 6 +++- ...tionSearchIndexRebuildDataWorker.class.php | 6 ++++ phpstan-ambient.neon | 3 ++ phpstan.neon | 16 ++++++++++ 18 files changed, 99 insertions(+), 38 deletions(-) create mode 100644 phpstan-ambient.neon create mode 100644 phpstan.neon diff --git a/files/lib/acp/form/FaqQuestionAddForm.class.php b/files/lib/acp/form/FaqQuestionAddForm.class.php index eb1cd23..077466b 100644 --- a/files/lib/acp/form/FaqQuestionAddForm.class.php +++ b/files/lib/acp/form/FaqQuestionAddForm.class.php @@ -4,12 +4,15 @@ use Laminas\Diactoros\Response\RedirectResponse; use Override; +use wcf\data\faq\category\FaqCategory; +use wcf\data\faq\category\FaqCategoryNode; use wcf\data\faq\category\FaqCategoryNodeTree; use wcf\data\faq\Question; use wcf\data\faq\QuestionAction; use wcf\data\faq\QuestionEditor; use wcf\data\IStorableObject; use wcf\data\language\item\LanguageItemList; +use wcf\data\language\Language; use wcf\form\AbstractFormBuilderForm; use wcf\system\form\builder\container\FormContainer; use wcf\system\form\builder\container\TabFormContainer; @@ -23,10 +26,12 @@ use wcf\system\form\builder\IFormDocument; use wcf\system\html\input\HtmlInputProcessor; use wcf\system\language\LanguageFactory; -use wcf\system\request\IRouteController; use wcf\system\request\LinkHandler; use wcf\system\WCF; +/** + * @extends AbstractFormBuilderForm + */ class FaqQuestionAddForm extends AbstractFormBuilderForm { /** @@ -57,8 +62,14 @@ class FaqQuestionAddForm extends AbstractFormBuilderForm protected int $isMultilingual = 0; + /** + * @var array + */ protected array $multiLingualAnswers = []; + /** + * @var array + */ protected array $categories; #[Override] @@ -205,13 +216,7 @@ protected function setFormAction() 'isMultilingual' => $this->isMultilingual, ]; if ($this->formObject !== null) { - if ($this->formObject instanceof IRouteController) { - $parameters['object'] = $this->formObject; - } else { - $object = $this->formObject; - - $parameters['id'] = $object->{$object::getDatabaseTableIndexName()}; - } + $parameters['object'] = $this->formObject; } $this->form->action(LinkHandler::getInstance()->getControllerLink(static::class, $parameters)); @@ -227,6 +232,9 @@ public function assignVariables() ]); } + /** + * @return array + */ protected function getCategories(): array { if (!isset($this->categories)) { @@ -235,9 +243,15 @@ protected function getCategories(): array $categoryList = $categoryTree->getIterator(); $this->categories = []; + /** + * @var FaqCategoryNode $category + */ foreach ($categoryList as $category) { $this->categories[$category->categoryID] = $category; + /** + * @var FaqCategory[] + */ $childCategories = $category->getAllChildCategories(); if (!\count($childCategories)) { continue; diff --git a/files/lib/acp/page/FaqQuestionListPage.class.php b/files/lib/acp/page/FaqQuestionListPage.class.php index d9e9405..23357d0 100644 --- a/files/lib/acp/page/FaqQuestionListPage.class.php +++ b/files/lib/acp/page/FaqQuestionListPage.class.php @@ -4,10 +4,12 @@ use Override; use wcf\page\AbstractGridViewPage; -use wcf\system\gridView\AbstractGridView; use wcf\system\gridView\admin\FaqQuestionGridView; use wcf\system\WCF; +/** + * @extends AbstractGridViewPage + */ final class FaqQuestionListPage extends AbstractGridViewPage { /** @@ -33,7 +35,7 @@ public function readParameters() } #[Override] - protected function createGridView(): AbstractGridView + protected function createGridView(): FaqQuestionGridView { return new FaqQuestionGridView(); } diff --git a/files/lib/data/faq/Question.class.php b/files/lib/data/faq/Question.class.php index 9a688d1..cba885d 100644 --- a/files/lib/data/faq/Question.class.php +++ b/files/lib/data/faq/Question.class.php @@ -85,7 +85,7 @@ public function isAccessible(?User $user = null): bool return false; } - if ($this->getCategory()) { + if ($this->getCategory()->categoryID) { return $this->getCategory()->isAccessible($user); } diff --git a/files/lib/data/faq/QuestionAction.class.php b/files/lib/data/faq/QuestionAction.class.php index c1b02e6..59f24e7 100644 --- a/files/lib/data/faq/QuestionAction.class.php +++ b/files/lib/data/faq/QuestionAction.class.php @@ -16,8 +16,7 @@ use wcf\system\WCF; /** - * @method QuestionEditor[] getObjects() - * @method QuestionEditor getSingleObject() + * @extends AbstractDatabaseObjectAction */ final class QuestionAction extends AbstractDatabaseObjectAction implements ISortableAction, IToggleAction { @@ -139,7 +138,7 @@ public function update() $this->updateSearchIndex($object); //update show order - if (isset($this->parameters['data']['showOrder']) && $this->parameters['data']['showOrder'] !== null) { + if (isset($this->parameters['data']['showOrder'])) { if ($object->showOrder < $this->parameters['data']['showOrder']) { $sql = "UPDATE wcf1_faq_questions SET showOrder = showOrder - 1 @@ -188,7 +187,7 @@ public function update() } } - private function updateSearchIndex($object) + private function updateSearchIndex(Question|QuestionEditor $object): void { if (isset($this->parameters['answer_i18n'])) { foreach ($this->parameters['answer_i18n'] as $languageID => $answer) { diff --git a/files/lib/data/faq/QuestionEditor.class.php b/files/lib/data/faq/QuestionEditor.class.php index dc31cf8..d97ceb9 100644 --- a/files/lib/data/faq/QuestionEditor.class.php +++ b/files/lib/data/faq/QuestionEditor.class.php @@ -9,9 +9,9 @@ use wcf\system\WCF; /** - * @method static Question create(array $parameters = []) - * @method Question getDecoratedObject() * @mixin Question + * @extends DatabaseObjectEditor + * @implements IEditableCachedObject */ final class QuestionEditor extends DatabaseObjectEditor implements IEditableCachedObject { @@ -31,10 +31,6 @@ public static function resetCache() */ public function updateShowOrder(int $showOrder): int { - if ($showOrder === null) { - $showOrder = \PHP_INT_MAX; - } - //check showOrder if ($showOrder < $this->showOrder) { $sql = "UPDATE wcf1_faq_questions diff --git a/files/lib/data/faq/QuestionList.class.php b/files/lib/data/faq/QuestionList.class.php index f35f243..48a8643 100644 --- a/files/lib/data/faq/QuestionList.class.php +++ b/files/lib/data/faq/QuestionList.class.php @@ -5,11 +5,7 @@ use wcf\data\DatabaseObjectList; /** - * @method Question current() - * @method Question[] getObjects() - * @method Question|null getSingleObject() - * @method Question|null search($objectID) - * @property Question[] $objects + * @extends DatabaseObjectList */ final class QuestionList extends DatabaseObjectList { diff --git a/files/lib/data/faq/category/FaqCategory.class.php b/files/lib/data/faq/category/FaqCategory.class.php index a3e45f5..acdee10 100644 --- a/files/lib/data/faq/category/FaqCategory.class.php +++ b/files/lib/data/faq/category/FaqCategory.class.php @@ -18,7 +18,7 @@ /** * @method FaqCategory[] getChildCategories() * @method FaqCategory[] getAllChildCategories() - * @method FaqCategory getParentCategory() + * @method ?FaqCategory getParentCategory() * @method FaqCategory[] getParentCategories() * @method static FaqCategory|null getCategory($categoryID) */ @@ -26,6 +26,9 @@ final class FaqCategory extends AbstractDecoratedCategory implements IAccessible { public const OBJECT_TYPE_NAME = 'dev.tkirch.wsc.faq.category'; + /** + * @var array> + */ private array $userPermissions = []; private bool $prefix = false; @@ -40,7 +43,7 @@ public function isAccessible(?User $user = null) return $this->getPermission('canViewFAQ', $user); } - public function getPermission($permission, ?User $user = null, $isMod = false) + public function getPermission(string $permission, ?User $user = null, bool $isMod = false): bool { if ($user === null) { $user = WCF::getUser(); @@ -74,7 +77,7 @@ public function getTitle(): string return ($this->prefix ? '  ' : '') . WCF::getLanguage()->get($this->title); } - public function setPrefix($prefix = true) + public function setPrefix(bool $prefix = true): void { $this->prefix = $prefix; } diff --git a/files/lib/data/faq/category/FaqCategoryCache.class.php b/files/lib/data/faq/category/FaqCategoryCache.class.php index 92b8366..bd51c1c 100644 --- a/files/lib/data/faq/category/FaqCategoryCache.class.php +++ b/files/lib/data/faq/category/FaqCategoryCache.class.php @@ -2,6 +2,7 @@ namespace wcf\data\faq\category; +use wcf\data\category\Category; use wcf\system\category\CategoryHandler; use wcf\system\SingletonFactory; use wcf\system\WCF; @@ -14,7 +15,7 @@ final class FaqCategoryCache extends SingletonFactory */ private array $questions; - private function initQuestions() + private function initQuestions(): void { $this->questions = []; @@ -38,7 +39,13 @@ private function initQuestions() $this->countQuestions($categoryToParent, $contacts, 0); } - private function countQuestions(array $categoryToParent, array &$contacts, $categoryID) + /** + * + * @param array> $categoryToParent + * @param array &$contacts + * @param int $categoryID + */ + private function countQuestions(array $categoryToParent, array &$contacts, int $categoryID): int { $count = (isset($contacts[$categoryID])) ? $contacts[$categoryID] : 0; if (isset($categoryToParent[$categoryID])) { @@ -54,7 +61,7 @@ private function countQuestions(array $categoryToParent, array &$contacts, $cate return $count; } - public function getQuestions($categoryID) + public function getQuestions(int $categoryID): int { if (!isset($this->questions)) { $this->initQuestions(); diff --git a/files/lib/page/FaqQuestionListPage.class.php b/files/lib/page/FaqQuestionListPage.class.php index e00a75d..41e31b7 100644 --- a/files/lib/page/FaqQuestionListPage.class.php +++ b/files/lib/page/FaqQuestionListPage.class.php @@ -20,6 +20,9 @@ class FaqQuestionListPage extends AbstractPage */ public $neededPermissions = ['user.faq.canViewFAQ']; + /** + * @var array + */ protected array $faqs = []; protected int $showFaqAddDialog = 0; @@ -67,8 +70,7 @@ public function readData() } if ( isset($this->category) - && $this->category !== null - && $this->category->categoryID != $category->categoryID + && $this->category->categoryID !== $category->categoryID ) { continue; } @@ -115,6 +117,10 @@ public function assignVariables() ]); } + /** + * @param list $questionIDs + * @return array|GroupedAttachmentList + */ protected function getAttachmentList(array $questionIDs): array|GroupedAttachmentList { if ($questionIDs === []) { diff --git a/files/lib/system/attachment/FaqQuestionAttachmentObjectType.class.php b/files/lib/system/attachment/FaqQuestionAttachmentObjectType.class.php index 7c533bc..fc0150e 100644 --- a/files/lib/system/attachment/FaqQuestionAttachmentObjectType.class.php +++ b/files/lib/system/attachment/FaqQuestionAttachmentObjectType.class.php @@ -3,8 +3,12 @@ namespace wcf\system\attachment; use Override; +use wcf\data\faq\Question; use wcf\system\WCF; +/** + * @extends AbstractAttachmentObjectType + */ final class FaqQuestionAttachmentObjectType extends AbstractAttachmentObjectType { #[Override] diff --git a/files/lib/system/bbcode/FaqBBCode.class.php b/files/lib/system/bbcode/FaqBBCode.class.php index 9879e2c..3c372e1 100644 --- a/files/lib/system/bbcode/FaqBBCode.class.php +++ b/files/lib/system/bbcode/FaqBBCode.class.php @@ -38,7 +38,7 @@ public function getParsedTag(array $openingTag, $content, array $closingTag, BBC return WCF::getTPL()->render('wcf', 'faqBBCode', [ 'question' => $question, 'collapseQuestion' => $collapse, - ], true); + ]); } return $question->getTitle() . "\n\n" . $question->getPlainOutput(); diff --git a/files/lib/system/box/FaqCategoriesBoxController.class.php b/files/lib/system/box/FaqCategoriesBoxController.class.php index 13eb871..b09ec91 100644 --- a/files/lib/system/box/FaqCategoriesBoxController.class.php +++ b/files/lib/system/box/FaqCategoriesBoxController.class.php @@ -29,6 +29,7 @@ protected function getActiveCategory(): ?AbstractDecoratedCategory || RequestHandler::getInstance()->getActiveRequest()->getRequestObject() instanceof FaqQuestionPage ) { if (isset(RequestHandler::getInstance()->getActiveRequest()->getRequestObject()->category)) { + // @phpstan-ignore property.protected $activeCategory = RequestHandler::getInstance()->getActiveRequest()->getRequestObject()->category; } } diff --git a/files/lib/system/endpoint/controller/hanashi/questions/search/GetSearch.class.php b/files/lib/system/endpoint/controller/hanashi/questions/search/GetSearch.class.php index eee7f38..e4ad91c 100644 --- a/files/lib/system/endpoint/controller/hanashi/questions/search/GetSearch.class.php +++ b/files/lib/system/endpoint/controller/hanashi/questions/search/GetSearch.class.php @@ -63,6 +63,7 @@ private function getQuestionsIDs(string $query): array } /** + * @param list $questionIDs * @return list */ private function getQuestions(array $questionIDs): array diff --git a/files/lib/system/gridView/admin/FaqQuestionGridView.class.php b/files/lib/system/gridView/admin/FaqQuestionGridView.class.php index bbee498..5ade73a 100644 --- a/files/lib/system/gridView/admin/FaqQuestionGridView.class.php +++ b/files/lib/system/gridView/admin/FaqQuestionGridView.class.php @@ -5,7 +5,7 @@ use Override; use wcf\acp\form\FaqQuestionEditForm; use wcf\data\category\CategoryNodeTree; -use wcf\data\DatabaseObjectList; +use wcf\data\faq\Question; use wcf\data\faq\QuestionList; use wcf\system\gridView\AbstractGridView; use wcf\system\gridView\GridViewColumn; @@ -25,6 +25,9 @@ use wcf\system\view\filter\ObjectIdFilter; use wcf\system\WCF; +/** + * @extends AbstractGridView + */ final class FaqQuestionGridView extends AbstractGridView { public function __construct() @@ -93,7 +96,7 @@ public function __construct() } #[Override] - protected function createObjectList(): DatabaseObjectList + protected function createObjectList(): QuestionList { return new QuestionList(); } diff --git a/files/lib/system/search/FaqQuestionSearch.class.php b/files/lib/system/search/FaqQuestionSearch.class.php index d720e00..0219835 100644 --- a/files/lib/system/search/FaqQuestionSearch.class.php +++ b/files/lib/system/search/FaqQuestionSearch.class.php @@ -3,12 +3,16 @@ namespace wcf\system\search; use Override; +use wcf\data\faq\Question; use wcf\data\faq\QuestionList; use wcf\data\search\ISearchResultObject; use wcf\system\WCF; final class FaqQuestionSearch extends AbstractSearchProvider { + /** + * @var array + */ private array $faqCache = []; #[Override] @@ -78,7 +82,7 @@ public function isAccessible(): bool } #[Override] - public function getCustomIconName(): ?string + public function getCustomIconName(): string { return 'circle-question'; } diff --git a/files/lib/system/worker/FaqQuestionSearchIndexRebuildDataWorker.class.php b/files/lib/system/worker/FaqQuestionSearchIndexRebuildDataWorker.class.php index d058535..fdbbad7 100644 --- a/files/lib/system/worker/FaqQuestionSearchIndexRebuildDataWorker.class.php +++ b/files/lib/system/worker/FaqQuestionSearchIndexRebuildDataWorker.class.php @@ -8,6 +8,9 @@ use wcf\data\language\item\LanguageItemList; use wcf\system\search\SearchIndexManager; +/** + * @extends AbstractRebuildDataWorker + */ final class FaqQuestionSearchIndexRebuildDataWorker extends AbstractRebuildDataWorker { /** @@ -96,6 +99,9 @@ public function execute() } } + /** + * @return array> + */ private function getLanguageCache(): array { $languageVariables = []; diff --git a/phpstan-ambient.neon b/phpstan-ambient.neon new file mode 100644 index 0000000..75ae073 --- /dev/null +++ b/phpstan-ambient.neon @@ -0,0 +1,3 @@ +parameters: + dynamicConstantNames: + - SIMPLE_FAQ_VIEW \ No newline at end of file diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..18adf2d --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,16 @@ +includes: + - phpstan-ambient.neon + - ../WCF/phpstan-ambient.neon + +parameters: + level: 6 + phpVersion: + min: 80102 + max: 80499 + paths: + - files + scanFiles: + - constants.php + - ../WCF/constants.php + scanDirectories: + - ../WCF/wcfsetup/install/files \ No newline at end of file From 8ab2f03ee9a637c3fca7da69a28f3925765b3ddf Mon Sep 17 00:00:00 2001 From: Peter Lohse Date: Thu, 1 Jan 2026 15:56:34 +0100 Subject: [PATCH 2/2] replace list<> --- files/lib/data/faq/category/FaqCategoryCache.class.php | 2 +- files/lib/page/FaqQuestionListPage.class.php | 2 +- .../controller/hanashi/questions/ChangeShowOrder.class.php | 2 +- .../controller/hanashi/questions/search/GetSearch.class.php | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/files/lib/data/faq/category/FaqCategoryCache.class.php b/files/lib/data/faq/category/FaqCategoryCache.class.php index bd51c1c..fdfa567 100644 --- a/files/lib/data/faq/category/FaqCategoryCache.class.php +++ b/files/lib/data/faq/category/FaqCategoryCache.class.php @@ -41,7 +41,7 @@ private function initQuestions(): void /** * - * @param array> $categoryToParent + * @param array $categoryToParent * @param array &$contacts * @param int $categoryID */ diff --git a/files/lib/page/FaqQuestionListPage.class.php b/files/lib/page/FaqQuestionListPage.class.php index 41e31b7..1e362c6 100644 --- a/files/lib/page/FaqQuestionListPage.class.php +++ b/files/lib/page/FaqQuestionListPage.class.php @@ -118,7 +118,7 @@ public function assignVariables() } /** - * @param list $questionIDs + * @param int[] $questionIDs * @return array|GroupedAttachmentList */ protected function getAttachmentList(array $questionIDs): array|GroupedAttachmentList diff --git a/files/lib/system/endpoint/controller/hanashi/questions/ChangeShowOrder.class.php b/files/lib/system/endpoint/controller/hanashi/questions/ChangeShowOrder.class.php index 3ddbc57..d675f19 100644 --- a/files/lib/system/endpoint/controller/hanashi/questions/ChangeShowOrder.class.php +++ b/files/lib/system/endpoint/controller/hanashi/questions/ChangeShowOrder.class.php @@ -37,7 +37,7 @@ public function __invoke(ServerRequestInterface $request, array $variables): Res } /** - * @param list $items + * @param ShowOrderItem[] $items */ private function saveShowOrder(array $items): void { diff --git a/files/lib/system/endpoint/controller/hanashi/questions/search/GetSearch.class.php b/files/lib/system/endpoint/controller/hanashi/questions/search/GetSearch.class.php index e4ad91c..6deb4d3 100644 --- a/files/lib/system/endpoint/controller/hanashi/questions/search/GetSearch.class.php +++ b/files/lib/system/endpoint/controller/hanashi/questions/search/GetSearch.class.php @@ -36,7 +36,7 @@ public function __invoke(ServerRequestInterface $request, array $variables): Res } /** - * @return list + * @return int[] */ private function getQuestionsIDs(string $query): array { @@ -63,8 +63,8 @@ private function getQuestionsIDs(string $query): array } /** - * @param list $questionIDs - * @return list + * @param int[] $questionIDs + * @return Question[] */ private function getQuestions(array $questionIDs): array {