|null */ private ?array $words = null; /** * @param array{words?: list}|null $config */ public function __construct(?array $config = null) { if ($config !== null) { $this->words = $this->normalizeList($config['words'] ?? []); } } /** * Findet das erste Blacklist-Wort, das in Titel oder Text vorkommt. */ public function findInPressRelease(PressRelease $pressRelease): ?string { $haystack = $pressRelease->title.' '.$pressRelease->text; return $this->find($haystack); } /** * Findet das erste Blacklist-Wort in einem beliebigen String. * Vergleich ist case-insensitiv und ganzwörtlich. */ public function find(string $text): ?string { $words = $this->words(); if ($words === []) { return null; } $needle = $this->normalizeText($text); foreach ($words as $word) { $padded = ' '.trim($word).' '; if (trim($padded) === '') { continue; } if (str_contains($needle, $padded)) { return trim($padded); } } return null; } public function matches(string $text): bool { return $this->find($text) !== null; } /** * @return list */ private function words(): array { if ($this->words === null) { $this->words = $this->normalizeList((array) config('blacklist.words', [])); } return $this->words; } /** * @param array $words * @return list */ private function normalizeList(array $words): array { return array_values(array_filter(array_map( fn ($word): string => $this->normalizeText((string) $word), $words, ), fn (string $word): bool => $word !== '')); } private function normalizeText(string $text): string { $text = mb_strtolower($text, 'UTF-8'); $text = preg_replace('/[^\p{L}\p{N}\s]+/u', ' ', $text) ?? ''; $text = preg_replace('/\s+/u', ' ', $text) ?? ''; return ' '.trim($text).' '; } }