diff --git a/config/packages/doctrine.yaml b/config/packages/doctrine.yaml index 9bcf3103..4048f399 100644 --- a/config/packages/doctrine.yaml +++ b/config/packages/doctrine.yaml @@ -43,7 +43,7 @@ doctrine: dql: string_functions: - regexp: DoctrineExtensions\Query\Mysql\Regexp + regexp: App\Doctrine\Functions\Regexp field: DoctrineExtensions\Query\Mysql\Field field2: App\Doctrine\Functions\Field2 diff --git a/src/DataTables/Filters/Constraints/TextConstraint.php b/src/DataTables/Filters/Constraints/TextConstraint.php index 60f83328..186a4477 100644 --- a/src/DataTables/Filters/Constraints/TextConstraint.php +++ b/src/DataTables/Filters/Constraints/TextConstraint.php @@ -113,7 +113,7 @@ class TextConstraint extends AbstractConstraint //Regex is only supported on MySQL and needs a special function if ($this->operator === 'REGEX') { - $queryBuilder->andWhere(sprintf('REGEXP(%s, :%s) = 1', $this->property, $this->identifier)); + $queryBuilder->andWhere(sprintf('REGEXP(%s, :%s) = TRUE', $this->property, $this->identifier)); $queryBuilder->setParameter($this->identifier, $this->value); } } diff --git a/src/DataTables/Filters/PartSearchFilter.php b/src/DataTables/Filters/PartSearchFilter.php index 34dd2d7a..84dfe9b3 100644 --- a/src/DataTables/Filters/PartSearchFilter.php +++ b/src/DataTables/Filters/PartSearchFilter.php @@ -129,7 +129,7 @@ class PartSearchFilter implements FilterInterface //Convert the fields to search to a list of expressions $expressions = array_map(function (string $field): string { if ($this->regex) { - return sprintf("REGEXP(%s, :search_query) = 1", $field); + return sprintf("REGEXP(%s, :search_query) = TRUE", $field); } return sprintf("%s LIKE :search_query", $field); diff --git a/src/Doctrine/Functions/Regexp.php b/src/Doctrine/Functions/Regexp.php new file mode 100644 index 00000000..d7c6f1e7 --- /dev/null +++ b/src/Doctrine/Functions/Regexp.php @@ -0,0 +1,52 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Doctrine\Functions; + +use Doctrine\DBAL\Platforms\AbstractMySQLPlatform; +use Doctrine\DBAL\Platforms\PostgreSQLPlatform; +use Doctrine\DBAL\Platforms\SQLitePlatform; +use Doctrine\ORM\Query\SqlWalker; + +/** + * Similar to the regexp function, but with support for multi platform. + */ +class Regexp extends \DoctrineExtensions\Query\Mysql\Regexp +{ + public function getSql(SqlWalker $sqlWalker): string + { + $platform = $sqlWalker->getConnection()->getDatabasePlatform(); + + // + if ($platform instanceof AbstractMySQLPlatform || $platform instanceof SQLitePlatform) { + $operator = 'REGEXP'; + } elseif ($platform instanceof PostgreSQLPlatform) { + //Use the case-insensitive operator, to have the same behavior as MySQL + $operator = '~*'; + } else { + throw new \RuntimeException('Platform ' . gettype($platform) . ' does not support regular expressions.'); + } + + return '(' . $this->value->dispatch($sqlWalker) . ' ' . $operator . ' ' . $this->regexp->dispatch($sqlWalker) . ')'; + } +} \ No newline at end of file diff --git a/tests/DatatablesAvailabilityTest.php b/tests/DatatablesAvailabilityTest.php index 7c7d055b..23bc6f92 100644 --- a/tests/DatatablesAvailabilityTest.php +++ b/tests/DatatablesAvailabilityTest.php @@ -99,6 +99,9 @@ class DatatablesAvailabilityTest extends WebTestCase //Test using filters yield ['/category/1/parts?part_filter%5Bname%5D%5Boperator%5D=%3D&part_filter%5Bname%5D%5Bvalue%5D=BC547&part_filter%5Bcategory%5D%5Boperator%5D=INCLUDING_CHILDREN&part_filter%5Btags%5D%5Boperator%5D=ANY&part_filter%5Btags%5D%5Bvalue%5D=Test&part_filter%5Bsubmit%5D=']; yield ['/category/1/parts?part_filter%5Bcategory%5D%5Boperator%5D=INCLUDING_CHILDREN&part_filter%5Bstorelocation%5D%5Boperator%5D=%3D&part_filter%5Bstorelocation%5D%5Bvalue%5D=1&part_filter%5BattachmentsCount%5D%5Boperator%5D=%3D&part_filter%5BattachmentsCount%5D%5Bvalue1%5D=3&part_filter%5Bsubmit%5D=']; + + //Test regex search + yield ['/parts/search?category=1&comment=1&description=1&ipn=1&keyword=test&mpn=1&name=1&ordernr=1®ex=1&storelocation=1&tags=1']; } public function testOrdering(): void