diff --git a/src/Controller/PartListsController.php b/src/Controller/PartListsController.php index e544c481..a714f7eb 100644 --- a/src/Controller/PartListsController.php +++ b/src/Controller/PartListsController.php @@ -22,6 +22,7 @@ declare(strict_types=1); namespace App\Controller; +use App\DataTables\ErrorDataTable; use App\DataTables\Filters\PartFilter; use App\DataTables\Filters\PartSearchFilter; use App\DataTables\PartsDataTable; @@ -33,6 +34,7 @@ use App\Entity\Parts\Supplier; use App\Form\Filters\PartFilterType; use App\Services\Parts\PartsTableActionHandler; use App\Services\Trees\NodesListBuilder; +use Doctrine\DBAL\Exception\DriverException; use Doctrine\ORM\EntityManagerInterface; use Omines\DataTablesBundle\DataTableFactory; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; @@ -41,6 +43,7 @@ use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Contracts\Translation\TranslatorInterface; class PartListsController extends AbstractController { @@ -48,11 +51,14 @@ class PartListsController extends AbstractController private NodesListBuilder $nodesListBuilder; private DataTableFactory $dataTableFactory; - public function __construct(EntityManagerInterface $entityManager, NodesListBuilder $nodesListBuilder, DataTableFactory $dataTableFactory) + private TranslatorInterface $translator; + + public function __construct(EntityManagerInterface $entityManager, NodesListBuilder $nodesListBuilder, DataTableFactory $dataTableFactory, TranslatorInterface $translator) { $this->entityManager = $entityManager; $this->nodesListBuilder = $nodesListBuilder; $this->dataTableFactory = $dataTableFactory; + $this->translator = $translator; } /** @@ -144,7 +150,21 @@ class PartListsController extends AbstractController ->handleRequest($request); if ($table->isCallback()) { - return $table->getResponse(); + 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; + } + } } return $this->render($template, array_merge([ diff --git a/src/DataTables/ErrorDataTable.php b/src/DataTables/ErrorDataTable.php new file mode 100644 index 00000000..29888f17 --- /dev/null +++ b/src/DataTables/ErrorDataTable.php @@ -0,0 +1,85 @@ +. + */ + +namespace App\DataTables; + +use App\DataTables\Column\RowClassColumn; +use App\Entity\Parts\Part; +use Omines\DataTablesBundle\Adapter\ArrayAdapter; +use Omines\DataTablesBundle\Column\TextColumn; +use Omines\DataTablesBundle\DataTable; +use Omines\DataTablesBundle\DataTableFactory; +use Omines\DataTablesBundle\DataTableTypeInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\OptionsResolver\OptionsResolver; + +class ErrorDataTable implements DataTableTypeInterface +{ + public function configureOptions(OptionsResolver $optionsResolver): void + { + $optionsResolver->setRequired('errors'); + $optionsResolver->setAllowedTypes('errors', ['array', 'string']); + $optionsResolver->setNormalizer('errors', function (OptionsResolver $optionsResolver, $errors) { + if (is_string($errors)) { + $errors = [$errors]; + } + + return $errors; + }); + } + + public function configure(DataTable $dataTable, array $options) + { + $optionsResolver = new OptionsResolver(); + $this->configureOptions($optionsResolver); + $options = $optionsResolver->resolve($options); + + $dataTable + ->add('dont_matter_we_only_set_color', RowClassColumn::class, [ + 'render' => function ($value, $context) { + return 'table-warning'; + }, + ]) + + ->add('error', TextColumn::class, [ + 'label' => 'error_table.error', + 'render' => function ($value, $context) { + return ' ' . $value; + }, + ]) + ; + + //Build the array containing data + $data = []; + foreach ($options['errors'] as $error) { + $data[] = ['error' => $error]; + } + + $dataTable->createAdapter(ArrayAdapter::class, $data); + } + + public static function errorTable(DataTableFactory $dataTableFactory, Request $request, $errors): Response + { + $error_table = $dataTableFactory->createFromType(self::class, ['errors' => $errors]); + $error_table->handleRequest($request); + return $error_table->getResponse(); + } +} \ No newline at end of file diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf index 788f7474..9f7464c2 100644 --- a/translations/messages.en.xlf +++ b/translations/messages.en.xlf @@ -10960,31 +10960,31 @@ Element 3 - + attachment.max_file_size Maximum file size - + user.saml_user SSO / SAML user - + user.saml_user.pw_change_hint Your user uses single sign-on (SSO). You can not change the password and 2FA settings here. Configure them on your central SSO provider instead! - + login.sso_saml_login Single Sign-On Login (SSO) - + login.local_login_hint The form below is only for log in with a local user. If you want to log in via single sign-on, press the button above. @@ -11188,106 +11188,118 @@ Element 3 - + measurement_unit.new New Measurement Unit - + measurement_unit.edit Edit Measurement Unit - + user.aboutMe.label About Me - + storelocation.owner.label Owner - + storelocation.part_owner_must_match.label Part Lot owner must match storage location owner - + part_lot.owner Owner - + part_lot.owner.help Only the owner can withdraw or add stock to this lot. - + log.element_edited.changed_fields.owner Owner - + log.element_edited.changed_fields.instock_unknown Amount unknown - + log.element_edited.changed_fields.needs_refill Refill needed - + part.withdraw.access_denied Not allowed to do the desired action. Please check your permissions and the owner of the part lots. - + part.info.amount.less_than_desired Less than desired - + log.cli_user CLI user - + log.element_edited.changed_fields.part_owner_must_match Part owner must match storage location owner - + part.filter.lessThanDesired - In stock less than desired (total amount < min. amount) + - + part.filter.lotOwner Lot owner - + user.show_email_on_profile.label Show email on public profile page + + + error_table.error + An error occured during your request. + + + + + part.table.invalid_regex + Invalid Regex expression + + diff --git a/translations/security.en.xlf b/translations/security.en.xlf index 03d410c0..2c9d8957 100644 --- a/translations/security.en.xlf +++ b/translations/security.en.xlf @@ -8,7 +8,7 @@ - + saml.error.cannot_login_local_user_per_saml You can not login as local user via SSO! Use your local user password instead. diff --git a/translations/validators.en.xlf b/translations/validators.en.xlf index a24e6a0d..1f3438de 100644 --- a/translations/validators.en.xlf +++ b/translations/validators.en.xlf @@ -300,19 +300,19 @@ - + validator.attachment.name_not_blank Set a value here, or upload a file to automatically use its filename as name for the attachment. - + validator.part_lot.owner_must_match_storage_location_owner The owner of this lot must match the owner of the selected storage location (%owner_name%)! - + validator.part_lot.owner_must_not_be_anonymous A lot owner must not be the anonymous user!