diff --git a/src/Controller/PartListsController.php b/src/Controller/PartListsController.php index 2040cee6..52d65d2a 100644 --- a/src/Controller/PartListsController.php +++ b/src/Controller/PartListsController.php @@ -31,6 +31,7 @@ use App\Entity\Parts\Footprint; use App\Entity\Parts\Manufacturer; use App\Entity\Parts\Storelocation; use App\Entity\Parts\Supplier; +use App\Exceptions\InvalidRegexException; use App\Form\Filters\PartFilterType; use App\Services\Parts\PartsTableActionHandler; use App\Services\Trees\NodesListBuilder; @@ -151,19 +152,19 @@ class PartListsController extends AbstractController if ($table->isCallback()) { try { - return $table->getResponse(); - } catch (DriverException $driverException) { - if ($driverException->getCode() === 1139) { - - //Show only the part after "1139" - $regex_message = preg_replace('/^.*1139 /', '', $driverException->getMessage()); - - $errors = $this->translator->trans('part.table.invalid_regex') . ': ' . $regex_message; - - return ErrorDataTable::errorTable($this->dataTableFactory, $request, $errors); - } else { - throw $driverException; + try { + return $table->getResponse(); + } catch (DriverException $driverException) { + if ($driverException->getCode() === 1139) { + //Convert the driver exception to InvalidRegexException so it has the same hanlder as for SQLite + throw InvalidRegexException::fromDriverException($driverException); + } else { + throw $driverException; + } } + } catch (InvalidRegexException $exception) { + $errors = $this->translator->trans('part.table.invalid_regex').': '.$exception->getReason(); + return ErrorDataTable::errorTable($this->dataTableFactory, $request, $errors); } } diff --git a/src/Doctrine/SQLiteRegexExtension.php b/src/Doctrine/SQLiteRegexExtension.php index 1cdab603..0845ffb2 100644 --- a/src/Doctrine/SQLiteRegexExtension.php +++ b/src/Doctrine/SQLiteRegexExtension.php @@ -20,6 +20,7 @@ namespace App\Doctrine; +use App\Exceptions\InvalidRegexException; use Doctrine\Bundle\DoctrineBundle\EventSubscriber\EventSubscriberInterface; use Doctrine\DBAL\Event\ConnectionEventArgs; use Doctrine\DBAL\Events; @@ -43,7 +44,11 @@ class SQLiteRegexExtension implements EventSubscriberInterface //Ensure that the function really exists on the connection, as it is marked as experimental according to PHP documentation if($native_connection instanceof \PDO && method_exists($native_connection, 'sqliteCreateFunction' )) { $native_connection->sqliteCreateFunction('REGEXP', function ($pattern, $value) { - return (false !== mb_ereg($pattern, $value)) ? 1 : 0; + try { + return (false !== mb_ereg($pattern, $value)) ? 1 : 0; + } catch (\ErrorException $e) { + throw InvalidRegexException::fromMBRegexError($e); + } }); } } diff --git a/src/Exceptions/InvalidRegexException.php b/src/Exceptions/InvalidRegexException.php new file mode 100644 index 00000000..a94201d0 --- /dev/null +++ b/src/Exceptions/InvalidRegexException.php @@ -0,0 +1,80 @@ +. + */ + +namespace App\Exceptions; + +use Doctrine\DBAL\Exception\DriverException; +use ErrorException; + +class InvalidRegexException extends \RuntimeException +{ + private ?string $reason; + + public function __construct(string $reason = null) + { + $this->reason = $reason; + parent::__construct('Invalid regular expression'); + } + + /** + * Returns the reason for the exception (what the regex driver deemed invalid) + * @return string|null + */ + public function getReason(): ?string + { + return $this->reason; + } + + /** + * Creates a new exception from a driver exception happening, when MySQL encounters an invalid regex + * @param DriverException $exception + * @return self + */ + public static function fromDriverException(DriverException $exception): self + { + //1139 means invalid regex error + if ($exception->getCode() !== 1139) { + throw new \InvalidArgumentException('The given exception is not a driver exception', 0, $exception); + } + + //Reason is the part after the erorr code + $reason = preg_replace('/^.*1139 /', '', $exception->getMessage()); + + return new self($reason); + } + + /** + * Creates a new exception from the errorException thrown by mb_ereg + * @param ErrorException $ex + * @return self + */ + public static function fromMBRegexError(ErrorException $ex): self + { + //Ensure that the error is really a mb_ereg error + if ($ex->getSeverity() !== E_WARNING || !strpos($ex->getMessage(), 'mb_ereg()') !== false) { + throw new \InvalidArgumentException('The given exception is not a mb_ereg error', 0, $ex); + } + + //Reason is the part after the erorr code + $reason = preg_replace('/^.*mb_ereg\(\): /', '', $ex->getMessage()); + + return new self($reason); + } +} \ No newline at end of file