diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f047633..aff59a03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [v2.1.48](https://github.com/roadiz/core-bundle-dev-app/compare/v2.1.47...v2.1.48) (2023-10-20) + + +### Bug Fixes + +* **CustomForm:** Catch mailer transport exception when submitting custom-form answers ([52487e3](https://github.com/roadiz/core-bundle-dev-app/commit/52487e3b1ef626a771f382d9eb5b25d75ea2d483)) + ## [v2.1.47](https://github.com/roadiz/core-bundle-dev-app/compare/v2.1.46...v2.1.47) (2023-10-09) diff --git a/lib/RoadizCoreBundle/src/Controller/CustomFormController.php b/lib/RoadizCoreBundle/src/Controller/CustomFormController.php index eefdcd57..d1e749cf 100644 --- a/lib/RoadizCoreBundle/src/Controller/CustomFormController.php +++ b/lib/RoadizCoreBundle/src/Controller/CustomFormController.php @@ -158,7 +158,7 @@ public function definitionAction(Request $request, int $id): JsonResponse * @param Request $request * @param int $id * @return Response - * @throws Exception + * @throws Exception|FilesystemException */ public function postAction(Request $request, int $id): Response { @@ -221,8 +221,10 @@ public function postAction(Request $request, int $id): Response * @param Request $request * @param int $customFormId * @return Response - * @throws Exception - * @throws TransportExceptionInterface + * @throws FilesystemException + * @throws LoaderError + * @throws RuntimeError + * @throws SyntaxError */ public function addAction(Request $request, int $customFormId): Response { @@ -276,6 +278,7 @@ public function sentAction(Request $request, int $customFormId): Response * @throws LoaderError * @throws RuntimeError * @throws SyntaxError + * @deprecated Use async message handler to send email receipt from CustomFormAnswer. */ public function sendAnswer( CustomFormAnswer $answer, @@ -335,10 +338,7 @@ public function sendAnswer( * @param string|null $emailSender * @param bool $prefix * @return array|Response - * @throws LoaderError - * @throws RuntimeError - * @throws SyntaxError - * @throws TransportExceptionInterface + * @throws SyntaxError|RuntimeError|LoaderError|FilesystemException */ public function prepareAndHandleCustomFormAssignation( Request $request, @@ -378,17 +378,6 @@ public function prepareAndHandleCustomFormAssignation( $answer->toArray(false) ); - $msg = $this->translator->trans( - 'customForm.%name%.send', - ['%name%' => $customFormsEntity->getDisplayName()] - ); - - $session = $request->getSession(); - if ($session instanceof Session) { - $session->getFlashBag()->add('confirm', $msg); - } - $this->logger->info($msg); - $assignation['title'] = $this->translator->trans( 'new.answer.form.%site%', ['%site%' => $customFormsEntity->getDisplayName()] @@ -403,25 +392,46 @@ public function prepareAndHandleCustomFormAssignation( /* * Send answer notification */ - $receiver = array_filter( - array_map('trim', explode(',', $customFormsEntity->getEmail() ?? '')) - ); - $receiver = array_map(function (string $email) { - return new Address($email); - }, $receiver); - $this->sendAnswer( - $answer, - [ - 'mailContact' => $assignation['mailContact'], - 'fields' => $assignation["emailFields"], - 'customForm' => $customFormsEntity, - 'title' => $this->translator->trans( - 'new.answer.form.%site%', - ['%site%' => $customFormsEntity->getDisplayName()] - ), - ], - $receiver - ); + try { + $receiver = array_filter( + array_map('trim', explode(',', $customFormsEntity->getEmail() ?? '')) + ); + $receiver = array_map(function (string $email) { + return new Address($email); + }, $receiver); + $this->sendAnswer( + $answer, + [ + 'mailContact' => $assignation['mailContact'], + 'fields' => $assignation["emailFields"], + 'customForm' => $customFormsEntity, + 'title' => $this->translator->trans( + 'new.answer.form.%site%', + ['%site%' => $customFormsEntity->getDisplayName()] + ), + ], + $receiver + ); + + $msg = $this->translator->trans( + 'customForm.%name%.send', + ['%name%' => $customFormsEntity->getDisplayName()] + ); + + $session = $request->getSession(); + if ($session instanceof Session) { + $session->getFlashBag()->add('confirm', $msg); + } + $this->logger->info($msg); + } catch (TransportExceptionInterface $e) { + // Do not fail if answer has been registered but email has not been sent. + $this->logger->warning('Custom form answer has been registered but email could not been sent.', [ + 'exception' => $e, + 'message' => $e->getMessage(), + 'customForm' => $customFormsEntity->getDisplayName(), + 'answerId' => $answer->getId() + ]); + } return $response; } catch (EntityAlreadyExistsException $e) { diff --git a/lib/RoadizCoreBundle/src/Document/MessageHandler/AbstractLockingDocumentMessageHandler.php b/lib/RoadizCoreBundle/src/Document/MessageHandler/AbstractLockingDocumentMessageHandler.php index 13988320..e15c6139 100644 --- a/lib/RoadizCoreBundle/src/Document/MessageHandler/AbstractLockingDocumentMessageHandler.php +++ b/lib/RoadizCoreBundle/src/Document/MessageHandler/AbstractLockingDocumentMessageHandler.php @@ -47,6 +47,8 @@ public function __invoke(AbstractDocumentMessage $message): void protected function isFileLocal(DocumentInterface $document): bool { - return str_starts_with($this->documentsStorage->publicUrl($document->getMountPath()), '/'); + return + $document->isPrivate() || + str_starts_with($this->documentsStorage->publicUrl($document->getMountPath()), '/'); } } diff --git a/lib/RoadizCoreBundle/src/Form/CustomFormsType.php b/lib/RoadizCoreBundle/src/Form/CustomFormsType.php index 7c9fac62..5cd0711c 100644 --- a/lib/RoadizCoreBundle/src/Form/CustomFormsType.php +++ b/lib/RoadizCoreBundle/src/Form/CustomFormsType.php @@ -141,38 +141,21 @@ protected function addSingleField(FormBuilderInterface $builder, CustomFormField */ protected function getTypeForField(CustomFormField $field): string { - switch ($field->getType()) { - case AbstractField::ENUM_T: - case AbstractField::MULTIPLE_T: - case AbstractField::RADIO_GROUP_T: - case AbstractField::CHECK_GROUP_T: - return ChoiceType::class; - case AbstractField::DOCUMENTS_T: - return FileType::class; - case AbstractField::MARKDOWN_T: - return MarkdownType::class; - case AbstractField::COLOUR_T: - return ColorType::class; - case AbstractField::DATETIME_T: - return DateTimeType::class; - case AbstractField::DATE_T: - return DateType::class; - case AbstractField::RICHTEXT_T: - case AbstractField::TEXT_T: - return TextareaType::class; - case AbstractField::BOOLEAN_T: - return CheckboxType::class; - case AbstractField::INTEGER_T: - return IntegerType::class; - case AbstractField::DECIMAL_T: - return NumberType::class; - case AbstractField::EMAIL_T: - return EmailType::class; - case AbstractField::COUNTRY_T: - return CountryType::class; - default: - return TextType::class; - } + return match ($field->getType()) { + AbstractField::ENUM_T, AbstractField::MULTIPLE_T, AbstractField::RADIO_GROUP_T, AbstractField::CHECK_GROUP_T => ChoiceType::class, + AbstractField::DOCUMENTS_T => FileType::class, + AbstractField::MARKDOWN_T => MarkdownType::class, + AbstractField::COLOUR_T => ColorType::class, + AbstractField::DATETIME_T => DateTimeType::class, + AbstractField::DATE_T => DateType::class, + AbstractField::RICHTEXT_T, AbstractField::TEXT_T => TextareaType::class, + AbstractField::BOOLEAN_T => CheckboxType::class, + AbstractField::INTEGER_T => IntegerType::class, + AbstractField::DECIMAL_T => NumberType::class, + AbstractField::EMAIL_T => EmailType::class, + AbstractField::COUNTRY_T => CountryType::class, + default => TextType::class, + }; } /** @@ -249,6 +232,10 @@ protected function getOptionsForField(CustomFormField $field, array $formOptions $mimeTypes = [ 'application/pdf', 'application/x-pdf', + 'image/avif', + 'image/heif', + 'image/heic', + 'image/webp', 'image/jpeg', 'image/png', 'image/gif', @@ -260,7 +247,7 @@ protected function getOptionsForField(CustomFormField $field, array $formOptions $option['constraints'][] = new All([ 'constraints' => [ new File([ - 'maxSize' => '10m', + 'maxSize' => $formOptions['fileUploadMaxSize'], 'mimeTypes' => $mimeTypes ]) ] @@ -309,12 +296,15 @@ public function configureOptions(OptionsResolver $resolver): void 'recaptcha_name' => Recaptcha::FORM_NAME, 'forceExpanded' => false, 'csrf_protection' => false, + // You may reduce this value when you have multiple files upload fields + // to avoid hitting email server upload limit. + 'fileUploadMaxSize' => '10m', ]); $resolver->setRequired('customForm'); - $resolver->setAllowedTypes('customForm', [CustomForm::class]); $resolver->setAllowedTypes('forceExpanded', ['boolean']); + $resolver->setAllowedTypes('fileUploadMaxSize', ['string']); $resolver->setAllowedTypes('recaptcha_name', ['string']); }