Skip to content

Conversation

@mnocon
Copy link
Contributor

@mnocon mnocon commented Dec 12, 2025

Added ibexa/phpstan ruleset. It detected one issue:

~/Desktop/repos/mnocon/doc/4.6 improve-phpstan *1 !2 ❯ composer phpstan                                                                                                                       15:42:36
> phpstan analyse
Note: Using configuration file /Users/marek/Desktop/repos/mnocon/doc/4.6/phpstan.neon.
 258/258 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

 ------ ------------------------------------------------------------------------ 
  Line   back_office/search/src/EventSubscriber/MySuggestionEventSubscriber.php  
 ------ ------------------------------------------------------------------------ 
  :44    Closure is missing a return type declaration       

@mnocon mnocon requested a review from a team December 12, 2025 14:50
@github-actions
Copy link

Preview of modified files: no change to preview.

@github-actions
Copy link

code_samples/ change report

Before (on target branch)After (in current PR)

code_samples/back_office/search/src/EventSubscriber/MySuggestionEventSubscriber.php

docs/administration/back_office/customize_search_suggestion.md@48:``` php
docs/administration/back_office/customize_search_suggestion.md@49:[[= include_file('code_samples/back_office/search/src/EventSubscriber/MySuggestionEventSubscriber.php') =]]
docs/administration/back_office/customize_search_suggestion.md@50:```

001⫶<?php declare(strict_types=1);
002⫶
003⫶namespace App\EventSubscriber;
004⫶
005⫶use App\Search\Model\Suggestion\ProductSuggestion;
006⫶use Ibexa\Contracts\ProductCatalog\ProductServiceInterface;
007⫶use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery;
008⫶use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion;
009⫶use Ibexa\Contracts\Search\Event\BuildSuggestionCollectionEvent;
010⫶use Psr\Log\LoggerAwareInterface;
011⫶use Psr\Log\LoggerAwareTrait;
012⫶use Symfony\Component\EventDispatcher\EventSubscriberInterface;
013⫶
014⫶class MySuggestionEventSubscriber implements EventSubscriberInterface, LoggerAwareInterface
015⫶{
016⫶ use LoggerAwareTrait;
017⫶
018⫶ private ProductServiceInterface $productService;
019⫶
020⫶ public function __construct(
021⫶ ProductServiceInterface $productService,
022⫶ ) {
023⫶ $this->productService = $productService;
024⫶ }
025⫶
026⫶ public static function getSubscribedEvents(): array
027⫶ {
028⫶ return [
029⫶ BuildSuggestionCollectionEvent::class => ['onBuildSuggestionCollectionEvent', -1],
030⫶ ];
031⫶ }
032⫶
033⫶ public function onBuildSuggestionCollectionEvent(BuildSuggestionCollectionEvent $event): BuildSuggestionCollectionEvent
034⫶ {
035⫶ $suggestionQuery = $event->getQuery();
036⫶ $suggestionCollection = $event->getSuggestionCollection();
037⫶
038⫶ $text = $suggestionQuery->getQuery();
039⫶ $words = explode(' ', preg_replace('/\s+/', ' ', $text));
040⫶ $limit = $suggestionQuery->getLimit();
041⫶
042⫶ try {
043⫶ $productQuery = new ProductQuery(null, new Criterion\LogicalOr([

code_samples/back_office/search/src/EventSubscriber/MySuggestionEventSubscriber.php

docs/administration/back_office/customize_search_suggestion.md@48:``` php
docs/administration/back_office/customize_search_suggestion.md@49:[[= include_file('code_samples/back_office/search/src/EventSubscriber/MySuggestionEventSubscriber.php') =]]
docs/administration/back_office/customize_search_suggestion.md@50:```

001⫶<?php declare(strict_types=1);
002⫶
003⫶namespace App\EventSubscriber;
004⫶
005⫶use App\Search\Model\Suggestion\ProductSuggestion;
006⫶use Ibexa\Contracts\ProductCatalog\ProductServiceInterface;
007⫶use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery;
008⫶use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion;
009⫶use Ibexa\Contracts\Search\Event\BuildSuggestionCollectionEvent;
010⫶use Psr\Log\LoggerAwareInterface;
011⫶use Psr\Log\LoggerAwareTrait;
012⫶use Symfony\Component\EventDispatcher\EventSubscriberInterface;
013⫶
014⫶class MySuggestionEventSubscriber implements EventSubscriberInterface, LoggerAwareInterface
015⫶{
016⫶ use LoggerAwareTrait;
017⫶
018⫶ private ProductServiceInterface $productService;
019⫶
020⫶ public function __construct(
021⫶ ProductServiceInterface $productService,
022⫶ ) {
023⫶ $this->productService = $productService;
024⫶ }
025⫶
026⫶ public static function getSubscribedEvents(): array
027⫶ {
028⫶ return [
029⫶ BuildSuggestionCollectionEvent::class => ['onBuildSuggestionCollectionEvent', -1],
030⫶ ];
031⫶ }
032⫶
033⫶ public function onBuildSuggestionCollectionEvent(BuildSuggestionCollectionEvent $event): BuildSuggestionCollectionEvent
034⫶ {
035⫶ $suggestionQuery = $event->getQuery();
036⫶ $suggestionCollection = $event->getSuggestionCollection();
037⫶
038⫶ $text = $suggestionQuery->getQuery();
039⫶ $words = explode(' ', preg_replace('/\s+/', ' ', $text));
040⫶ $limit = $suggestionQuery->getLimit();
041⫶
042⫶ try {
043⫶ $productQuery = new ProductQuery(null, new Criterion\LogicalOr([
044⫶                new Criterion\ProductName(implode(' ', array_map(static function (string $word) {
044⫶                new Criterion\ProductName(implode(' ', array_map(static function (string $word): string {
045⫶                    return "$word*";
046⫶ }, $words))),
047⫶ new Criterion\ProductCode($words),
048⫶ new Criterion\ProductType($words),
049⫶ ]), [], 0, $limit);
050⫶ $searchResult = $this->productService->findProducts($productQuery);
051⫶
052⫶ if ($searchResult->getTotalCount()) {
053⫶ $maxScore = 0.0;
054⫶ $suggestionsByContentIds = [];
055⫶ /** @var \Ibexa\Contracts\Search\Model\Suggestion\ContentSuggestion $suggestion */
056⫶ foreach ($suggestionCollection as $suggestion) {
057⫶ $maxScore = max($suggestion->getScore(), $maxScore);
058⫶ $suggestionsByContentIds[$suggestion->getContent()->id] = $suggestion;
059⫶ }
060⫶
061⫶ /** @var \Ibexa\ProductCatalog\Local\Repository\Values\Product $product */
062⫶ foreach ($searchResult as $product) {
063⫶ $contentId = $product->getContent()->id;
064⫶ if (array_key_exists($contentId, $suggestionsByContentIds)) {
065⫶ $suggestionCollection->remove($suggestionsByContentIds[$contentId]);
066⫶ }
067⫶
068⫶ $productSuggestion = new ProductSuggestion($maxScore + 1, $product);
069⫶ $suggestionCollection->append($productSuggestion);
070⫶ }
071⫶ }
072⫶ } catch (\Throwable $throwable) {
073⫶ $this->logger->error($throwable);
074⫶ }
075⫶
076⫶ return $event;
077⫶ }
078⫶}

045⫶                    return "$word*";
046⫶ }, $words))),
047⫶ new Criterion\ProductCode($words),
048⫶ new Criterion\ProductType($words),
049⫶ ]), [], 0, $limit);
050⫶ $searchResult = $this->productService->findProducts($productQuery);
051⫶
052⫶ if ($searchResult->getTotalCount()) {
053⫶ $maxScore = 0.0;
054⫶ $suggestionsByContentIds = [];
055⫶ /** @var \Ibexa\Contracts\Search\Model\Suggestion\ContentSuggestion $suggestion */
056⫶ foreach ($suggestionCollection as $suggestion) {
057⫶ $maxScore = max($suggestion->getScore(), $maxScore);
058⫶ $suggestionsByContentIds[$suggestion->getContent()->id] = $suggestion;
059⫶ }
060⫶
061⫶ /** @var \Ibexa\ProductCatalog\Local\Repository\Values\Product $product */
062⫶ foreach ($searchResult as $product) {
063⫶ $contentId = $product->getContent()->id;
064⫶ if (array_key_exists($contentId, $suggestionsByContentIds)) {
065⫶ $suggestionCollection->remove($suggestionsByContentIds[$contentId]);
066⫶ }
067⫶
068⫶ $productSuggestion = new ProductSuggestion($maxScore + 1, $product);
069⫶ $suggestionCollection->append($productSuggestion);
070⫶ }
071⫶ }
072⫶ } catch (\Throwable $throwable) {
073⫶ $this->logger->error($throwable);
074⫶ }
075⫶
076⫶ return $event;
077⫶ }
078⫶}

Download colorized diff

@mnocon mnocon merged commit abbf66e into 4.6 Dec 12, 2025
1 check was pending
@mnocon mnocon deleted the ibexa-phpstan branch December 12, 2025 15:13
mnocon added a commit that referenced this pull request Dec 14, 2025
* Added ibexa/phpstan rules

* PHP & JS CS Fixes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants