src/Service/InquiryControllerService.php line 58

Open in your IDE?
  1. <?php
  2. namespace App\Service;
  3. use App\Entity\Inquiry\InquiryInterface;
  4. use App\Repository\Inquiry\InquiryRepositoryInterface;
  5. use App\Utils\FormUtil;
  6. use Doctrine\ORM\EntityManagerInterface;
  7. use Psr\Container\ContainerInterface;
  8. use Psr\Log\LoggerInterface;
  9. use ReCaptcha\ReCaptcha;
  10. use Symfony\Component\Form\Form;
  11. use Symfony\Component\Form\FormError;
  12. use Symfony\Component\Form\FormInterface;
  13. use Symfony\Component\HttpFoundation\Request;
  14. class InquiryControllerService
  15. {
  16.     private ContainerInterface $container;
  17.     private ReCaptcha $reCaptcha;
  18.     private EntityManagerInterface $em;
  19.     private MailService $mailer;
  20.     private LoggerInterface $logger;
  21.     public function __construct(
  22.         ContainerInterface $container,
  23.         ReCaptcha $reCaptcha,
  24.         EntityManagerInterface $em,
  25.         MailService $mailer,
  26.         LoggerInterface $logger
  27.     ) {
  28.         $this->container $container;
  29.         $this->reCaptcha $reCaptcha;
  30.         $this->em $em;
  31.         $this->mailer $mailer;
  32.         $this->logger $logger;
  33.     }
  34.     /**
  35.      * 問い合わせフォームを準備する
  36.      * セッションが残っている場合アサインする
  37.      *
  38.      * @param Request $request
  39.      * @param string $sessionName
  40.      * @param string $formType
  41.      * @param InquiryInterface $inquiry
  42.      * @param array $formOptions
  43.      * @return FormInterface
  44.      */
  45.     public function prepareForm(
  46.         Request $request,
  47.         string $sessionName,
  48.         string $formType,
  49.         InquiryInterface $inquiry,
  50.         array $formOptions = []
  51.     ): FormInterface {
  52.         $form $this->container->get('form.factory')->create($formType$inquiry$formOptions);
  53.         if($request->getSession()->has($sessionName)) {
  54.             $formData $request->getSession()->get($sessionName);
  55.             FormUtil::submitAndGetData($form$formData);
  56.         }
  57.         return $form;
  58.     }
  59.     /**
  60.      * 確認ページでFormにRequestをアサインして送信済みFormを返す
  61.      *
  62.      * @param Request $request
  63.      * @param string $formType
  64.      * @param InquiryInterface $inquiry
  65.      * @param array $formOptions
  66.      * @return FormInterface
  67.      */
  68.     public function getSubmittedForm(
  69.         Request $request,
  70.         string $formType,
  71.         InquiryInterface $inquiry,
  72.         array $formOptions = []
  73.     ): FormInterface {
  74.         $form $this->container->get('form.factory')->create($formType$inquiry$formOptions);
  75.         $form->handleRequest($request);
  76.         return $form;
  77.     }
  78.     /**
  79.      * フォームをバリデーションする
  80.      *
  81.      * @param Request $request
  82.      * @param FormInterface $form
  83.      * @param InquiryInterface $inquiry
  84.      * @return bool
  85.      */
  86.     public function formValidation(
  87.         Request $request,
  88.         FormInterface $form,
  89.         InquiryInterface $inquiry,
  90.         bool $checkRecaptcha true
  91.     ): bool {
  92.         $isValid true;
  93.         if($form->isSubmitted() && $form->isValid()) {
  94.             $inquiry->setIp($request->getClientIp());
  95.             $repository $this->em->getRepository(get_class($inquiry));
  96.             if($repository->isContinuePost($inquiry)) {
  97.                 $form->addError(new FormError('連続送信は時間をおいてください'));
  98.                 $isValid false;
  99.             }
  100.             if($checkRecaptcha) {
  101.                 $reCaptchaResponse $this->reCaptcha->verify(
  102.                     $request->request->get('g-recaptcha-response'),
  103.                     $request->getClientIp()
  104.                 );
  105.                 if(!$reCaptchaResponse->isSuccess()) {
  106.                     $form->addError(new FormError("不正な処理を感知しました"));
  107.                     $this->logger->notice(
  108.                         "ReCaptcha is invalid. ".
  109.                         print_r($reCaptchaResponse->getErrorCodes(), true)
  110.                     );
  111.                     $isValid false;
  112.                 }
  113.             }
  114.         } else {
  115.             $form->addError(new FormError('入力内容に不備がありました'));
  116.             $isValid false;
  117.         }
  118.         return $isValid;
  119.     }
  120.     /**
  121.      * 入力データをセッションに保存、CSRFチェック用の空のフォームを返す
  122.      *
  123.      * @param Request $request
  124.      * @param FormInterface $form
  125.      * @param string $sessionName
  126.      * @return FormInterface
  127.      */
  128.     public function saveSession(
  129.         Request $request,
  130.         FormInterface $form,
  131.         string $sessionName,
  132.         array $viewData null
  133.     ): FormInterface {
  134.         $request->getSession()->set($sessionName$viewData $viewData FormUtil::getViewData($form));
  135.         return $this->createConfirmForm();
  136.     }
  137.     /**
  138.      * 確認ページから送信へのCSRFトークンをもつ空のフォームを返す
  139.      * @return FormInterface
  140.      */
  141.     public function createConfirmForm(): FormInterface
  142.     {
  143.         return $this->container->get('form.factory')->create();
  144.     }
  145.     /**
  146.      * 送信前のCSRFトークンチェックを行う
  147.      *
  148.      * @param Request $request
  149.      * @return bool
  150.      */
  151.     public function handleConfirmForm(Request $request): bool
  152.     {
  153.         $confirmForm $this->createConfirmForm();
  154.         $confirmForm->handleRequest($request);
  155.         return ($confirmForm->isSubmitted() && $confirmForm->isValid());
  156.     }
  157.     /**
  158.      * 送信ページでセッションにある入力データをフォームにアサインする
  159.      *
  160.      * @param Request $request
  161.      * @param InquiryInterface $inquiry
  162.      * @param string $formType
  163.      * @param string $sessionName
  164.      * @return FormInterface|null
  165.      */
  166.     public function loadSessionAndGetForm(
  167.         Request $request,
  168.         InquiryInterface $inquiry,
  169.         string $formType,
  170.         string $sessionName
  171.     ): ?FormInterface
  172.     {
  173.         if (!$request->getSession()->has($sessionName)) {
  174.             return null;
  175.         }
  176.         $form $this->container->get('form.factory')->create($formType$inquiry, [
  177.             "csrf_protection" => false
  178.         ]);
  179.         $formData $request->getSession()->get($sessionName);
  180.         FormUtil::submitAndGetData($form$formData);
  181.         return $form;
  182.     }
  183.     /**
  184.      * DB永続化してセッションを削除
  185.      *
  186.      * @param Request $request
  187.      * @param InquiryInterface $inquiry
  188.      * @param string $sessionName
  189.      * @return $this
  190.      */
  191.     public function persistAndSessionRemove(
  192.         Request $request,
  193.         InquiryInterface $inquiry,
  194.         string $sessionName
  195.     ): self
  196.     {
  197.         $inquiry
  198.             ->setSendAt(new \DateTime())
  199.             ->setToken(null)
  200.         ;
  201.         $this->em->persist($inquiry);
  202.         $this->em->flush();
  203.         $request->getSession()->remove($sessionName);
  204.         // pardot送信のエラーハンドリングのために永続化したエンティティのIDを保存
  205.         $request->getSession()->set($sessionName$inquiry->getId());
  206.         return $this;
  207.     }
  208.     public function handlePardotError(
  209.         Request $request,
  210.         InquiryRepositoryInterface $repository,
  211.         string $formType,
  212.         string $sessionName,
  213.         callable $formOptionsFunc null
  214.     ): self {
  215.         if(!$request->getSession()->has($sessionName)) return $this;
  216.         $id $request->getSession()->get($sessionName);
  217.         $id intval($id);
  218.         if(!$id) return $this;
  219.         $inquiry $repository->findOneBy(["id" => $id]);
  220.         if(!$inquiry) return $this;
  221.         $mailConfig $inquiry->getPardotErrorMailConfig();
  222.         if(!$mailConfig) return $this;
  223.         if(is_callable($formOptionsFunc)) {
  224.             $formOptions $formOptionsFunc($inquiry);
  225.         } else {
  226.             $formOptions = [];
  227.         }
  228.         $form $this->container->get('form.factory')->create($formType$inquiry$formOptions);
  229.         $mailConfig['twigAssign']['form'] = $form->createView();
  230.         $this->mailer->send($mailConfig);
  231.         return $this;
  232.     }
  233.     public function removeSession(Request $requeststring $sessionName): self
  234.     {
  235.         $request->getSession()->remove($sessionName);
  236.         return $this;
  237.     }
  238.     /**
  239.      * メール送信実行
  240.      * @param InquiryInterface $inquiry
  241.      * @param FormInterface $form
  242.      * @param callable|null $preSendConfig
  243.      * @return array
  244.      * @throws \Symfony\Component\Mailer\Exception\TransportExceptionInterface
  245.      * @throws \Twig\Error\LoaderError
  246.      * @throws \Twig\Error\RuntimeError
  247.      * @throws \Twig\Error\SyntaxError
  248.      */
  249.     public function sendmail(
  250.         InquiryInterface $inquiry,
  251.         FormInterface $form,
  252.         callable $preSendConfig null
  253.     ): array {
  254.         $sendEmails = [];
  255.         foreach($inquiry->getMailSendConfig() as $k => $mailConfig) {
  256.             $mailConfig['twigAssign']['form'] = $form->createView();
  257.             if(is_callable($preSendConfig)) {
  258.                 $mailConfig $preSendConfig($mailConfig$k);
  259.             }
  260.             $sendEmails[$k] = $this->mailer->send($mailConfig);
  261.         }
  262.         return $sendEmails;
  263.     }
  264. }