From 0b81efde8858687390fced4d4f42e338fc75e0e0 Mon Sep 17 00:00:00 2001 From: Niklan Date: Tue, 11 Feb 2025 20:25:48 +0500 Subject: [PATCH] =?UTF-8?q?Increase=20PHPStan=20level=208=20=E2=86=92=209?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Utils/SearchApiResultItemsHelper.php | 2 + .../About/Repository/AboutSettings.php | 25 +++++-- .../Contact/Form/ContactSettingsForm.php | 14 ++-- .../Contact/Repository/ContactSettings.php | 18 +++-- .../StaticPage/Home/Form/HomeSettingsForm.php | 42 +++++------ .../Home/Repository/HomeSettings.php | 20 ++++- .../SearchApiResultItemsHelperTest.php | 75 +++++++++++++++++++ 7 files changed, 154 insertions(+), 42 deletions(-) diff --git a/app/Drupal/niklan/src/Search/Utils/SearchApiResultItemsHelper.php b/app/Drupal/niklan/src/Search/Utils/SearchApiResultItemsHelper.php index 41a5bc19..44591834 100644 --- a/app/Drupal/niklan/src/Search/Utils/SearchApiResultItemsHelper.php +++ b/app/Drupal/niklan/src/Search/Utils/SearchApiResultItemsHelper.php @@ -11,6 +11,8 @@ final class SearchApiResultItemsHelper { public static function extractEntityIds(ResultSetInterface $result_set): array { + // @todo Validate IDs against pattern: + // "entity:[entity_type_id]/[entity_id]:[language]". return \array_map(static function (ItemInterface $result_item) { [$entity_info, $source_info] = \explode('/', $result_item->getId()); [, $entity_type_id] = \explode(':', $entity_info); diff --git a/app/Drupal/niklan/src/StaticPage/About/Repository/AboutSettings.php b/app/Drupal/niklan/src/StaticPage/About/Repository/AboutSettings.php index 628a0fe4..ba82484a 100644 --- a/app/Drupal/niklan/src/StaticPage/About/Repository/AboutSettings.php +++ b/app/Drupal/niklan/src/StaticPage/About/Repository/AboutSettings.php @@ -11,7 +11,10 @@ final class AboutSettings extends LanguageAwareSettingsStore { public const string TEXT_FORMAT = 'text'; public function getPhotoMediaId(): ?string { - return $this->getStore()->get('photo_media_id'); + $photo_media_id = $this->getStore()->get('photo_media_id'); + \assert(\is_string($photo_media_id) || \is_null($photo_media_id), 'Photo media ID must be a string or null.'); + + return $photo_media_id; } public function setPhotoMediaId(?string $id): self { @@ -29,7 +32,10 @@ public function setTitle(string $title): self { } public function getTitle(): string { - return $this->getStore()->get('title', "I'm an alien 👽"); + $title = $this->getStore()->get('title', "I'm an alien 👽"); + \assert(\is_string($title), 'Title must be a string.'); + + return $title; } public function setSubtitle(string $subtitle): self { @@ -40,7 +46,10 @@ public function setSubtitle(string $subtitle): self { public function getSubtitle(): string { /* cSpell:ignore traveller */ - return $this->getStore()->get('subtitle', 'Greetings traveller!'); + $subtitle = $this->getStore()->get('subtitle', 'Greetings traveller!'); + \assert(\is_string($subtitle), 'Subtitle must be a string.'); + + return $subtitle; } public function setSummary(string $summary): self { @@ -56,7 +65,10 @@ public function getSummary(): string { how I see the world around us.

HTML; - return $this->getStore()->get('summary', $default); + $summary = $this->getStore()->get('summary', $default); + \assert(\is_string($summary), 'Summary must be a string.'); + + return $summary; } public function setDescription(string $description): self { @@ -76,7 +88,10 @@ public function getDescription(): string {

Join me on this exciting journey through the universe and Earth!

HTML; - return $this->getStore()->get('description', $default); + $description = $this->getStore()->get('description', $default); + \assert(\is_string($description), 'Description must be a string.'); + + return $description; } #[\Override] diff --git a/app/Drupal/niklan/src/StaticPage/Contact/Form/ContactSettingsForm.php b/app/Drupal/niklan/src/StaticPage/Contact/Form/ContactSettingsForm.php index df41c9c5..44f08785 100644 --- a/app/Drupal/niklan/src/StaticPage/Contact/Form/ContactSettingsForm.php +++ b/app/Drupal/niklan/src/StaticPage/Contact/Form/ContactSettingsForm.php @@ -49,16 +49,18 @@ public function buildForm(array $form, FormStateInterface $form_state): array { #[\Override] public function submitForm(array &$form, FormStateInterface $form_state): void { - $this - ->getSettings() - ->setEmail($form_state->getValue('email')) - ->setTelegram($form_state->getValue('telegram')) - ->setDescription($form_state->getValue(['description', 'value'])); + $settings = $this->getSettings(); + + \assert(\is_string($form_state->getValue('email'))); + $settings->setEmail($form_state->getValue('email')); + \assert(\is_string($form_state->getValue('telegram'))); + $settings->setTelegram($form_state->getValue('telegram')); + \assert(\is_string($form_state->getValue(['description', 'value']))); + $settings->setDescription($form_state->getValue(['description', 'value'])); parent::submitForm($form, $form_state); } - #[\Override] protected function getSettings(): ContactSettings { $settings = $this->getContainer()->get(ContactSettings::class); \assert($settings instanceof ContactSettings); diff --git a/app/Drupal/niklan/src/StaticPage/Contact/Repository/ContactSettings.php b/app/Drupal/niklan/src/StaticPage/Contact/Repository/ContactSettings.php index bf341240..a3c0ab50 100644 --- a/app/Drupal/niklan/src/StaticPage/Contact/Repository/ContactSettings.php +++ b/app/Drupal/niklan/src/StaticPage/Contact/Repository/ContactSettings.php @@ -11,7 +11,10 @@ final class ContactSettings extends LanguageAwareSettingsStore { public const string TEXT_FORMAT = 'text'; public function getEmail(): string { - return $this->getStore()->get('email', 'example@example.com'); + $email = $this->getStore()->get('email', 'example@example.com'); + \assert(\is_string($email), 'Email must be a string.'); + + return $email; } public function setEmail(string $email): self { @@ -21,7 +24,10 @@ public function setEmail(string $email): self { } public function getTelegram(): string { - return $this->getStore()->get('telegram', 'https://t.me'); + $telegram = $this->getStore()->get('telegram', 'https://t.me'); + \assert(\is_string($telegram), 'Telegram must be a string.'); + + return $telegram; } public function setTelegram(string $url): self { @@ -31,10 +37,10 @@ public function setTelegram(string $url): self { } public function getDescription(): string { - return $this->getStore()->get( - key: 'description', - default: 'Additional information about how to contact the author.', - ); + $description = $this->getStore()->get('description', 'Additional information about how to contact the author.'); + \assert(\is_string($description), 'Description must be a string.'); + + return $description; } public function setDescription(string $description): self { diff --git a/app/Drupal/niklan/src/StaticPage/Home/Form/HomeSettingsForm.php b/app/Drupal/niklan/src/StaticPage/Home/Form/HomeSettingsForm.php index 05d39ce0..d6b78e2d 100644 --- a/app/Drupal/niklan/src/StaticPage/Home/Form/HomeSettingsForm.php +++ b/app/Drupal/niklan/src/StaticPage/Home/Form/HomeSettingsForm.php @@ -55,7 +55,7 @@ public function submitForm(array &$form, FormStateInterface $form_state): void { $cards = []; /** - * @param array{ + * @var array{ * media_id: string, * title: string, * description: string @@ -68,17 +68,15 @@ public function submitForm(array &$form, FormStateInterface $form_state): void { 'description' => $card_item['description'], ]; } - - $heading = $form_state->getValue('heading'); - \assert(is_string($heading)); - $description = $form_state->getValue(['description', 'value']); - \assert(\is_string($description)); - $this - ->getSettings() - ->setHeading($heading) - ->setDescription($description) - ->setCards($cards); - + + $settings = $this->getSettings(); + + \assert(\is_string($form_state->getValue('heading'))); + $settings->setHeading($form_state->getValue('heading')); + \assert(\is_string($form_state->getValue(['description', 'value']))); + $settings->setDescription($form_state->getValue(['description', 'value'])); + $settings->setCards($cards); + parent::submitForm($form, $form_state); } @@ -128,12 +126,12 @@ protected function getSettings(): HomeSettings { private function buildCards(array &$form, FormStateInterface $form_state): void { $cards = $this->getSettings()->getCards(); $cards_count = $form_state->get('cards_count'); - + if (!isset($cards_count)) { $cards_count = \count($cards); $form_state->set('cards_count', $cards_count); } - + $form['cards'] = [ '#type' => 'details', '#open' => $form_state->get('keep_cards_open') ?? FALSE, @@ -142,7 +140,8 @@ private function buildCards(array &$form, FormStateInterface $form_state): void '#suffix' => '', ]; - $form['cards']['items'] = [ + /** @var array> $items */ + $items = [ '#type' => 'table', // Workaround for an empty string if not set. See #3247373. '#input' => FALSE, @@ -161,11 +160,11 @@ private function buildCards(array &$form, FormStateInterface $form_state): void ], ], ]; - + for ($i = 0; $i < $cards_count; $i++) { $card_data = $cards[$i] ?? []; - - /** + + /** * @var array{ * '#attributes': array{'class': array}, * '#weight': int, @@ -202,10 +201,11 @@ private function buildCards(array &$form, FormStateInterface $form_state): void '#attributes' => ['class' => ['weight']], ], ]; - - $form['cards']['items'][$i] = $row; + + $items[$i] = $row; } - + + $form['cards']['items'] = $items; $form['cards']['actions'] = ['#type' => 'actions']; $form['cards']['actions']['add'] = [ // Workaround for core bug #2897377. diff --git a/app/Drupal/niklan/src/StaticPage/Home/Repository/HomeSettings.php b/app/Drupal/niklan/src/StaticPage/Home/Repository/HomeSettings.php index cf83cb0d..18b83879 100644 --- a/app/Drupal/niklan/src/StaticPage/Home/Repository/HomeSettings.php +++ b/app/Drupal/niklan/src/StaticPage/Home/Repository/HomeSettings.php @@ -12,34 +12,46 @@ final class HomeSettings extends LanguageAwareSettingsStore { public function getHeading(): string { $heading = $this->getStore()->get('heading', 'Web Developer Blog'); - \assert(is_string($heading), 'The heading must be a string.'); + \assert(\is_string($heading), 'The heading must be a string.'); + return $heading; } public function setHeading(string $heading): self { $this->getStore()->set('heading', $heading); + return $this; } public function getDescription(): string { $description = $this->getStore()->get('description', 'The homepage description.'); - \assert(is_string($description), 'The description must be a string.'); + \assert(\is_string($description), 'The description must be a string.'); + return $description; } public function setDescription(string $description): self { $this->getStore()->set('description', $description); + return $this; } public function setCards(array $cards): self { $this->getStore()->set('cards', $cards); + return $this; } + /** + * @return array{}|array */ public function getCards(): array { $cards = $this->getStore()->get('cards', []); - \assert(is_array($cards), 'The cards must be an array.'); + \assert(\is_array($cards), 'The cards must be an array.'); + return $cards; } @@ -48,4 +60,4 @@ protected function getStoreId(): string { return 'niklan.home_settings'; } -} \ No newline at end of file +} diff --git a/app/Drupal/niklan/tests/src/Unit/Utility/SearchApiResultItemsHelperTest.php b/app/Drupal/niklan/tests/src/Unit/Utility/SearchApiResultItemsHelperTest.php index 1619d103..af5219df 100644 --- a/app/Drupal/niklan/tests/src/Unit/Utility/SearchApiResultItemsHelperTest.php +++ b/app/Drupal/niklan/tests/src/Unit/Utility/SearchApiResultItemsHelperTest.php @@ -46,4 +46,79 @@ public function testExtractEntityIds(): void { self::assertEquals($expected_ids, $extracted_ids); } + public function testExtractEntityIdsWithEmptyResultSet(): void { + $result_set = $this->prophesize(ResultSetInterface::class); + $result_set->getResultItems()->willReturn([]); + + $extracted_ids = SearchApiResultItemsHelper::extractEntityIds($result_set->reveal()); + self::assertEquals([], $extracted_ids); + } + + public function testExtractEntityIdsWithDifferentEntityTypes(): void { + $item_ids = [ + 'entity:node/10:ru', + 'entity:user/20:en', + 'entity:comment/30:es', + ]; + + $result_items = []; + + foreach ($item_ids as $item_id) { + $result_item = $this->prophesize(ItemInterface::class); + $result_item->getId()->willReturn($item_id); + $result_items[$item_id] = $result_item->reveal(); + } + + $result_set = $this->prophesize(ResultSetInterface::class); + $result_set->getResultItems()->willReturn($result_items); + + $extracted_ids = SearchApiResultItemsHelper::extractEntityIds($result_set->reveal()); + $expected_ids = [ + 'entity:node/10:ru' => new EntitySearchResult('node', '10', 'ru'), + 'entity:user/20:en' => new EntitySearchResult('user', '20', 'en'), + 'entity:comment/30:es' => new EntitySearchResult('comment', '30', 'es'), + ]; + self::assertEquals($expected_ids, $extracted_ids); + } + + public function testExtractEntityIdsWithDifferentLanguages(): void { + $item_ids = [ + 'entity:node/100:de', + 'entity:user/200:fr', + 'entity:comment/300:ja', + ]; + + $result_items = []; + + foreach ($item_ids as $item_id) { + $result_item = $this->prophesize(ItemInterface::class); + $result_item->getId()->willReturn($item_id); + $result_items[$item_id] = $result_item->reveal(); + } + + $result_set = $this->prophesize(ResultSetInterface::class); + $result_set->getResultItems()->willReturn($result_items); + + $extracted_ids = SearchApiResultItemsHelper::extractEntityIds($result_set->reveal()); + $expected_ids = [ + 'entity:node/100:de' => new EntitySearchResult('node', '100', 'de'), + 'entity:user/200:fr' => new EntitySearchResult('user', '200', 'fr'), + 'entity:comment/300:ja' => new EntitySearchResult('comment', '300', 'ja'), + ]; + self::assertEquals($expected_ids, $extracted_ids); + } + + public function testExtractEntityIdsWithInvalidFormat(): void { + $item_id = 'invalid_format'; + + $result_item = $this->prophesize(ItemInterface::class); + $result_item->getId()->willReturn($item_id); + + $result_set = $this->prophesize(ResultSetInterface::class); + $result_set->getResultItems()->willReturn([$item_id => $result_item->reveal()]); + + $extracted_ids = SearchApiResultItemsHelper::extractEntityIds($result_set->reveal()); + self::assertEquals([], $extracted_ids); + } + }