diff --git a/src/Filters/FullTextSearch.php b/src/Filters/FullTextSearch.php new file mode 100644 index 0000000..8abeb15 --- /dev/null +++ b/src/Filters/FullTextSearch.php @@ -0,0 +1,98 @@ +indexColumns = $indexColumns; + $this->searchPhrase = $searchPhrase; + $this->mode = $mode; + } + + /** + * @inheritDoc + */ + public function doGetUniqueIdentifiersToFilter(Collection $list) + { + $ids = []; + + //We need to make sure our search value does not contain any diacritics + $searchValueCleaned = preg_replace('/&([a-z]{1,2})(acute|cedil|circ|grave|lig|orn|ring|slash|th|tilde|uml|caron);/i','$1', htmlentities($this->searchPhrase)); + foreach ($list as $item) { + $columnsToSearch = $this->indexColumns; + + foreach ($columnsToSearch as $column) { + if (preg_match("/$searchValueCleaned/i", $item[$column])) { + $ids[] = $item->UniqueIdentifier; + break; + } + } + } + + return $ids; + } + + /** + * @inheritDoc + */ + public function getSettingsArray() + { + $settings = parent::getSettingsArray(); + $settings["indexColumns"] = $this->indexColumns; + $settings["searchPhrase"] = $this->searchPhrase; + $settings["mode"] = $this->mode; + + return $settings; + } + + /** + * Builds a new instance of the FullTextSearch from the settings array + * + * @param $settings + * + * @return FullTextSearch + * + * @throws ImplementationException + */ + public static function fromSettingsArray($settings) + { + return new self($settings["indexColumns"], $settings["searchPhrase"], $settings["mode"]); + } +} diff --git a/src/Repositories/MySql/Filters/MySqlFullTextSearch.php b/src/Repositories/MySql/Filters/MySqlFullTextSearch.php new file mode 100644 index 0000000..e324700 --- /dev/null +++ b/src/Repositories/MySql/Filters/MySqlFullTextSearch.php @@ -0,0 +1,75 @@ +getSettingsArray(); + if (!isset($settings["indexColumns"]) || !isset($settings["searchPhrase"]) || !isset($settings["mode"])) { + throw new ImplementationException("Filter passed to doFilterWithRepository was \"" . get_class($originalFilter) . "\" expected " . \Unislim\WebApp\Shared\Filters\MySqlFullTextSearch::class); + } + + $implodedColumns = StringTools::implodeIgnoringBlanks(",", $settings["indexColumns"]); + if (self::canFilter($repository, $implodedColumns, $propertiesToAutoHydrate)) { + $searchPhrase = $settings["searchPhrase"]; + $paramName = uniqid() . str_replace(".", "", $implodedColumns); + + $originalFilter->filteredByRepository = true; + + $words = preg_split("/\W+/", $searchPhrase); + $newWords = []; + foreach($words as $word){ + if ($word) { + $newWords[] = $word."*"; + } + } + + $searchPhrase = implode(" ", $newWords); + + $params[$paramName] = $searchPhrase; + + $parameter = ":" . $paramName; + + return "MATCH ({$implodedColumns}) AGAINST ({$parameter} IN {$settings["mode"]} MODE)"; + } + + parent::doFilterWithRepository($repository, $originalFilter, $params, $propertiesToAutoHydrate); + } + + /** + * @inheritDoc + */ + protected static function canFilter(Repository $repository, $columnName, &$propertiesToAutoHydrate) + { + $schema = $repository->getRepositorySchema(); + $columns = $schema->getColumns(); + + //We need to explode the column name as we will have passed an imploded list of columns that + //comprise the index + $providedColumns = preg_split('@/@', $columnName, NULL, PREG_SPLIT_NO_EMPTY); + foreach ($providedColumns as $column) { + if (!isset($column, $columns)) { + if (!self::canFilterTrait($repository, $column, $propertiesToAutoHydrate)) { + return false; + } + } + } + + return true; + } +}