custom/plugins/CioSearchHeadline/src/Subscriber/SearchTermNormalizerSubscriber.php line 33

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace CioSearchHeadline\Subscriber;
  3. use Shopware\Core\Content\Product\Events\ProductSearchCriteriaEvent;
  4. use Shopware\Core\Content\Product\Events\ProductSuggestCriteriaEvent;
  5. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  6. class SearchTermNormalizerSubscriber implements EventSubscriberInterface
  7. {
  8.     /**
  9.      * Teilenummern-Pattern:
  10.      *  - dashed: alphanumerische Segmente mit Bindestrichen (z. B. A-5000-7803, 626115-0800-075, TCM5S4010022-XYZ)
  11.      *  - mixed: zusammenhängend, mind. 1 Buchstabe + 1 Ziffer (z. B. K651164)
  12.      *
  13.      * Hinweis: Es wird ausschließlich die Groß-/Kleinschreibung der Buchstaben normalisiert; Trennzeichen bleiben unverändert.
  14.      */
  15.     private const PATTERN_DASHED = '/^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)+$/';
  16.     private const PATTERN_MIXED  = '/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z0-9]{3,}$/';
  17.     public static function getSubscribedEvents(): array
  18.     {
  19.         return [
  20.             ProductSearchCriteriaEvent::class  => 'onSearch',
  21.             ProductSuggestCriteriaEvent::class => 'onSearch',
  22.         ];
  23.     }
  24.     /**
  25.      * Normalisiert passende Hersteller-/Teilenummern auf Uppercase,
  26.      * ohne Daten zu verändern – nur Query-Ebene (Request + Criteria).
  27.      */
  28.     public function onSearch(object $event): void
  29.     {
  30.         // Beide Events erben von ProductListingCriteriaEvent und bieten getRequest()/getCriteria()
  31.         if (!\method_exists($event, 'getRequest') || !\method_exists($event, 'getCriteria')) {
  32.             return;
  33.         }
  34.         $request  = $event->getRequest();
  35.         $criteria = $event->getCriteria();
  36.         if (!$request || !$criteria) {
  37.             return;
  38.         }
  39.         // 1) Term aus Request lesen
  40.         $term = (string) ($request->get('search') ?? '');
  41.         // 2) Fallback: ggf. aus Criteria
  42.         if ($term === '' && \method_exists($criteria, 'getTerm')) {
  43.             $term = (string) ($criteria->getTerm() ?? '');
  44.         }
  45.         $term = \trim($term);
  46.         if ($term === '') {
  47.             return;
  48.         }
  49.         // 3) Prüfen, ob der gesamte Term wie eine Teilenummer aussieht
  50.         $shouldNormalize =
  51.             \preg_match(self::PATTERN_DASHED, $term) === 1
  52.             || \preg_match(self::PATTERN_MIXED, $term) === 1;
  53.         if ($shouldNormalize) {
  54.             // 4a) Uppercase-Normalisierung NUR auf Query-Ebene (kompletter Term)
  55.             $normalized = \mb_strtoupper($term, 'UTF-8');
  56.             // Request-Parameter aktualisieren (für Suggest/Weiterverarbeitung)
  57.             $request->query->set('search', $normalized);
  58.             // Criteria-Term aktualisieren
  59.             if (\method_exists($criteria, 'setTerm')) {
  60.                 $criteria->setTerm($normalized);
  61.             }
  62.             return;
  63.         }
  64.         // 4b) Fallback: In Mehrwort-Suchen einzelne Token normalisieren
  65.         $parts   = \preg_split('/\s+/', $term);
  66.         $changed = false;
  67.         foreach ($parts as &$p) {
  68.             if ($p === '') {
  69.                 continue;
  70.             }
  71.             if (
  72.                 \preg_match(self::PATTERN_DASHED, $p) === 1
  73.                 || \preg_match(self::PATTERN_MIXED, $p) === 1
  74.             ) {
  75.                 $upper = \mb_strtoupper($p, 'UTF-8');
  76.                 if ($upper !== $p) {
  77.                     $p       = $upper;
  78.                     $changed = true;
  79.                 }
  80.             }
  81.         }
  82.         unset($p);
  83.         if ($changed) {
  84.             $normalized = \implode(' ', $parts);
  85.             $request->query->set('search', $normalized);
  86.             if (\method_exists($criteria, 'setTerm')) {
  87.                 $criteria->setTerm($normalized);
  88.             }
  89.         }
  90.     }
  91. }