<?php
 class vB_Utility_WordList { use vB_Utility_Trait_NoSerialize; private vB_Utility_String $stringUtil; private array $reList; private string $nonwordChar = '\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f'; public static function createFromText(vB_Utility_String $stringUtil, string $text) : self { $list = new self($stringUtil); $list->reList = $list->getReList($list->getTermList($text)); return $list; } private function __construct(vB_Utility_String $stringUtil) { $this->stringUtil = $stringUtil; } private function getTermList(string $text) : array { $terms = []; $words = preg_split('#[ \r\n\t]+#', $text, -1, PREG_SPLIT_NO_EMPTY); $currentTerm = []; foreach ($words AS $word) { if (count($currentTerm)) { $last = $this->stringUtil->substr($word, -1, 1); if ($last == '}') { $currentTerm[] = $this->stringUtil->substr($word, 0, -1); $currentTerm[0] = $this->stringUtil->substr($currentTerm[0], 1); $terms[] = $currentTerm; $currentTerm = []; } else { $currentTerm[] = $word; } } else { $first = $this->stringUtil->substr($word, 0, 1); if ($first == '{') { $last = $this->stringUtil->substr($word, -1, 1); if ($last == '}') { $terms[] = [$this->stringUtil->substr($word, 1, -1)]; } else { $currentTerm[] = $word; } } else { $terms[] = $word; } } } $terms = array_merge($terms, $currentTerm); return $terms; } private function getReList(array $terms) : array { $nonwordChar = '[' . $this->nonwordChar . ']'; $reList = []; foreach ($terms AS $term) { if (is_array($term)) { $escapedwords = []; foreach ($term AS $word) { $escapedwords[] = preg_quote($word, '#'); } $escapedwords = implode('\\s*', $escapedwords); $reList[] = '#(?<=' . $nonwordChar . '|^)' . $escapedwords . '(?=' . $nonwordChar . '|$)#si'; } else { $escapedword = preg_quote($term, '#'); $reList[] = "#$escapedword#si"; } } return $reList; } public function censor(string $text, string $replacechar) : string { if (!$text) { return $text; } $censormatch = function($matches) use($replacechar) { $modifier = ($this->stringUtil->isDefaultCharset('utf-8') ? 'u' : ''); $value = preg_replace('#[^\\s]#' . $modifier, $replacechar, $matches[0]); return $value; }; $text = preg_replace_callback($this->reList, $censormatch, $text); return $text; } public function getMatchedWords(string $text) : array { $whitespaceRE = '#\\s+#' . ($this->stringUtil->isDefaultCharset('utf-8') ? 'u' : ''); $foundwords = []; foreach ($this->reList AS $re) { if (preg_match_all($re, $text, $matches)) { foreach ($matches[0] AS $match) { $match = preg_replace($whitespaceRE, ' ', $match); $match = $this->stringUtil->strtolower($match); $foundwords[$match] = true; } } } if (!empty($foundwords)) { $foundwords = array_keys($foundwords); sort($foundwords); } return $foundwords; } public function isMatch(string $text) : bool { $words = $this->getMatchedWords($text); return (count($words) > 0); } } 