<?php
namespace App\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Security\Core\Security;
use App\Admin\Entity\StdBlocks;
use App\Admin\Entity\StdDomains;
use App\Admin\Entity\StdDomainsValues;
use App\Admin\Entity\StdNotifications;
use App\Admin\Entity\StdPagesContent;
use App\Admin\Entity\StdUsers;
use App\Entity\Forms;
use App\Event\StdDeleteUserDataEvent;
use App\Event\StdFormsSubmitEvent;
use App\Form\StdDynamicForm;
use App\Repository\FormsRepository;
use App\Utils\Functions;
use ReCaptcha\ReCaptcha;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use Twig\Environment;
use Symfony\Component\Mailer\MailerInterface;
class StdFormsSubscriber implements EventSubscriberInterface
{
private $entitymanager;
private $twig;
private $mailer;
private $security;
private $formfactory;
private $formsRepository;
public function __construct(MailerInterface $mailer,Environment $twig,EntityManagerInterface $entitymanager,Security $security,FormFactoryInterface $formfactory,FormsRepository $formsRepository)
{
$this->entitymanager=$entitymanager;
$this->twig=$twig;
$this->mailer=$mailer;
$this->security = $security;
$this->formfactory = $formfactory;
$this->formsRepository=$formsRepository;
}
public static function getSubscribedEvents(): array
{
return [
StdFormsSubmitEvent::NAME => 'onFormSubmit',
StdDeleteUserDataEvent::NAME => 'onDeleteUserData',
];
}
public function onFormSubmit(StdFormsSubmitEvent $event)
{
$request=$event->getRequest();
$formsdirectory=$event->getFormsDirectory();
$form = $this->formfactory->create(StdDynamicForm::class);
$form->handleRequest($request);
$editContent = null;
if ($form->isSubmitted() && $form->isValid()) {
$user = $this->entitymanager->getRepository(StdUsers::class)->findOneById(0);
$dataForm = $request->request->all();
if(isset($dataForm["form_original_form_id"]) && isset($dataForm["form_edit"]) && $dataForm["form_original_form_id"]!='' && $dataForm["form_edit"] == 1){
$newForm = $this->entitymanager->getRepository(Forms::class)->findOneById($dataForm["form_original_form_id"]);
$editContent = $newForm->getContent();
}else{
$newForm = new Forms();
}
$recaptchaToken = $dataForm["recaptchatoken"];
if($recaptchaToken != 0){
$recaptcha = new ReCaptcha(Functions::getConfig("GOOGLE_RECAPTCHA_SECRET","",$this->entitymanager), new \ReCaptcha\RequestMethod\CurlPost());
$recaptchaRes = $recaptcha
->setScoreThreshold(Functions::getConfig("GOOGLE_RECAPTCHA_SCORE_THRESHOLD","",$this->entitymanager) ?? "0.5")
->verify($recaptchaToken);
if(!$recaptchaRes->isSuccess()){
$event->setResult([
"success"=>false,
"message"=>"Recaptcha Error",
"formHtmlRender"=>""
]);
return false;
}
} else {
$event->setResult([
"success"=>false,
"message"=>"Recaptcha Error",
"formHtmlRender"=>""
]);
return false;
}
$filesArray = $request->files->all();
$folderName = Functions::cleanString($dataForm["form_name"]);
$attach = $attachEmail = [];
$i=0;
if(isset($dataForm["insert_new_message"]) && $dataForm["insert_new_message"]!=""){
$webUser = $this->security->getUser();
$newMessageTemp = $dataForm[$dataForm["insert_new_message"]];
$dataForm[$dataForm["insert_new_message"]] = [];
$nowDate = new DateTime();
$nowDateFormated = $nowDate->format('Y-m-d H:i:s');
if($webUser){
$dataForm[$dataForm["insert_new_message"]][] =
array(
"createdBy"=> $webUser->getId()
,"createdByName"=> $webUser->getName()
,"createdAt"=> $nowDateFormated
,"message"=> $newMessageTemp
);
}
else{
$dataForm[$dataForm["insert_new_message"]][] = \json_encode(
array(
"createdBy"=> ""
,"createdByName"=> ""
,"createdAt"=> $nowDateFormated
,"message"=> $newMessageTemp
));
}
}
$rep = $this->entitymanager->getRepository(StdPagesContent::class);
$formhasuploads=false;
$uploadssettings=[];
if (isset($dataForm["form_id"])){
$formPage = $rep->findOneBy(["pageId" => $dataForm["form_id"], "languageCode" => $request->getLocale()]);
if (isset($formPage)) {
$pageFields = $formPage->getContent();
//get all the fields that are files block form_file
foreach ($pageFields["fields"] as $block) {
$block = (array) $block;
$component = (array) $block["components"];
$settings=(array)$block["settings"];
$blockName = (string) $block["block"];
if(Functions::startsWith($blockName, 'form_file')){
$formhasuploads=true;
//save the settings form_accept and form_extension in the array uploadsettings with key the name of the field
$uploadssettings[$component["form_input_name"]]=["accept"=>$settings["form_accept"],"extension"=>$settings["form_extension"]];
}
}
}
}
if(count($filesArray)>0 && $formhasuploads){
foreach ($filesArray as $file_key=>$files) {
if($files instanceof UploadedFile){
$files=[$files];
}
if($files != null){
foreach ($files as $file) {
$i++;
$originalName=$file->getClientOriginalName();
$mimeType=$file->getClientMimeType();
$extension = $file->guessExtension();
//check if the file extension is allowed
if(isset($uploadssettings[$file_key]) && $uploadssettings[$file_key]["extension"]!=""){
$allowedExtensions=explode(",",$uploadssettings[$file_key]["extension"]);
if(!in_array($extension,$allowedExtensions)){
$event->setResult([
"success"=>false,
"message"=>"File extension not allowed",
"formHtmlRender"=>""
]);
return false;
}
}else if(!isset($uploadssettings[$file_key]) ){
$event->setResult([
"success"=>false,
"message"=>"File extension not allowed",
"formHtmlRender"=>""
]);
return false;
}
//check if the file mime type is allowed
if(isset($uploadssettings[$file_key]) && $uploadssettings[$file_key]["accept"]!=""){
$allowedMimeTypes=explode(",",$uploadssettings[$file_key]["accept"]);
if(!in_array($mimeType,$allowedMimeTypes)){
$event->setResult([
"success"=>false,
"message"=>"File mime type not allowed",
"formHtmlRender"=>""
]);
return false;
}
}else if(!isset($uploadssettings[$file_key]) ){
$event->setResult([
"success"=>false,
"message"=>"File mime type not allowed",
"formHtmlRender"=>""
]);
return false;
}
$fileName = Functions::generateUniqueFileName() . '.' . $file->guessExtension();
try {
$file->move(
$formsdirectory . '/' . $folderName . '/',
$fileName
);
} catch (\FileException $e) { }
$newImage = ["name" => $file->getClientOriginalName(), "file_name" => $fileName,"type"=>"file"];
if($editContent){
$editContent[$file_key][] = $newImage;
$dataForm[$file_key] = $editContent[$file_key];
} else {
$dataForm[$file_key][] = $newImage;
}
$dataForm[$file_key][] = ["name" => $file->getClientOriginalName(), "file_name" => $fileName,"type"=>"file"];
$attachEmail[$i]["path"] = $formsdirectory . '/' . $folderName . '/' . $fileName;
$attachEmail[$i]["originalName"] = $originalName;
$attachEmail[$i]["mimeType"] = $mimeType;
}
}
}
}
if($this->security->getUser()!=null){
$newForm->setNetuserId($this->security->getUser()->getId());
}
$newForm->setFormName($dataForm["form_name"]);
$newForm->setFormType($dataForm["form_type"]);
$newForm->setContent($dataForm);
$newForm->setCreatedDate(new \DateTime());
$newForm->setUpdatedDate(new \DateTime());
$newForm->setCreatedBy($user);
$newForm->setUpdatedBy($user);
$sendEmail = false;
if (isset($dataForm["form_id"])){
if (isset($formPage)) {
if (isset($pageFields["form_email_sender"]) && $pageFields["form_email_sender"] == 1){
$sendEmail = true;
}
$renderedform=$this->renderFormContent($dataForm,$pageFields);
$repNotifications = $this->entitymanager->getRepository(StdNotifications::class);
$to = "";
if (strpos($pageFields["form_input_email_to_send"], ',') !== false){
$pageFields["form_input_email_to_send"] = explode(',', str_replace([' '], [''], $pageFields["form_input_email_to_send"]));
$to = array();
foreach($pageFields["form_input_email_to_send"] as $tosend){
if (isset($dataForm[$tosend])) {
$tosend_emails = explode(';', preg_replace('/[\s,]+/', ';', $dataForm[$tosend]));
$tosend_emails = array_filter($tosend_emails, 'strlen');
$to = array_merge($tosend_emails, $to);
}
}
} else {
if (isset($dataForm[$pageFields["form_input_email_to_send"]])) {
$to = $dataForm[$pageFields["form_input_email_to_send"]];
}
}
if ($sendEmail && $to != "") {
$userNotification = $repNotifications->findOneBy(["id"=>$pageFields["form_notification_user"]]);
$emailContent = $userNotification?$userNotification->getEmailBody():"";
$subject = $userNotification?$userNotification->getEmailSubject():"";
$template = Functions::twig_template_from_string($this->twig, '{% extends "admin/emails/base.html.twig" %}{% block content %} ' . $emailContent . ' {% endblock %}');
$body = $template->render(array_merge($dataForm,array("rendered_form"=>$renderedform,"locale"=>$request->getLocale())));
$template = Functions::twig_template_from_string($this->twig, html_entity_decode($subject, ENT_QUOTES | ENT_XML1, 'UTF-8'));
$subject = $template->render($dataForm);
$ccEmails = $pageFields["form_notification_user_cc"];
$cc = array_filter(explode(";", $ccEmails));
$bccEmails = $pageFields["form_notification_user_bcc"];
$bcc = array_filter(explode(";", $bccEmails));
if (isset($pageFields["form_input_email_to_send"])) {
if ($to == "" && isset($dataForm[$pageFields["form_input_email_to_send"]])) {
$to = $dataForm[$pageFields["form_input_email_to_send"]];
}
if($to != ""){
Functions::sendEmail($this->mailer,$pageFields["form_email_from"], $pageFields["form_email_from_name"], $to, $cc, $bcc, $subject, $body , null,$this->entitymanager);
}
}
}
// Send to admin
if( $pageFields["form_notification_admin"] && $pageFields["form_email_to"]!=""){
$adminNotification = $repNotifications->findOneBy(["id"=>$pageFields["form_notification_admin"]]);
$emailContent = $adminNotification?$adminNotification->getEmailBody():"";
$subject = $adminNotification?$adminNotification->getEmailSubject():"";
$template = Functions::twig_template_from_string($this->twig, '{% extends "admin/emails/base.html.twig" %}{% block content %} ' . $emailContent . ' {% endblock %}');
$body = $template->render(array_merge($dataForm,array("rendered_form"=>$renderedform,"locale"=>$request->getDefaultLocale())));
$template = Functions::twig_template_from_string($this->twig, html_entity_decode($subject, ENT_QUOTES | ENT_XML1, 'UTF-8'));
$subject = $template->render($dataForm);
$toEmails = $pageFields["form_email_to"];
$to = explode(";", $toEmails);
$ccEmails = $pageFields["form_email_admin_cc"];
$cc = array_filter(explode(";", $ccEmails));
$bccEmails = $pageFields["form_email_admin_bcc"];
$bcc = array_filter(explode(";", $bccEmails));
Functions::sendEmail($this->mailer,$pageFields["form_email_from"], $pageFields["form_email_from_name"], $to, $cc, $bcc, $subject, $body , $attachEmail,$this->entitymanager);
}
}
}
$this->entitymanager->persist($newForm);
$this->entitymanager->flush();
$event->setResult([
"success"=>true,
"message"=>"customizable message",
"formHtmlRender"=>"html to re-render form in case of errors"
]);
$event->setId($newForm->getId());
return true;
}
else{
$event->setResult([
"success"=>false,
"message"=>"Form not valid",
"formHtmlRender"=>""
]);
return false;
}
}
private function renderFormContent($values,$formcontent)
{
$formname=$values["form_name"];
$folderName = Functions::cleanString($formname);
$content=$formcontent["fields"];
$result="";
foreach ($content as $block) {
$block = (array) $block;
$component = (array) $block["components"];
$blockName = (string) $block["block"];
$domainvalues=[];
$stdblock = $this->entitymanager->getRepository(StdBlocks::class)->findOneBy(['machineName' => $blockName]);
if ($stdblock) {
$stdsettings = $stdblock->getSettings();
if (isset($stdsettings["isFormDomain"]) && $stdsettings["isFormDomain"]){
//get the domain values for the selected domain
if($component["form_select_domain"]){
$domainvalues = $this->entitymanager->getRepository(StdDomainsValues::class)->findBy(["domain"=>$component["form_select_domain"]]);
}
}
else if (isset($stdsettings["isFormStatus"]) && $stdsettings["isFormStatus"]){
//get the domain values for the selected domain
$domainobj = $this->entitymanager->getRepository(StdDomains::class)->findOneBy(["machineName"=>"form_status"]);
if($domainobj){
$domainvalues = $this->entitymanager->getRepository(StdDomainsValues::class)->findBy(["domain"=>$domainobj->getId("id")]);
}
}
}
if(isset($component["form_input_name"]) && !Functions::startsWith($blockName, 'form_file') ){
$name = $component["form_input_name"];
$payload=[];
if(isset($values[$name])){
$payload=array_merge([
'value' => isset($values[$name])?$values[$name]:[],
'settings' => $block["settings"],
'fields' => $block["components"],
'repeatable' => $block["repeatable"],
'values'=>$domainvalues
]);
}
}else if (isset($component["form_input_name"]) && Functions::startsWith($blockName, 'form_file')) {
$name = $component["form_input_name"];
$payload=[];
$attachments = [];
$i = 0;
if(isset($values["foto"])){
foreach($values["foto"] as $attach){
$href = '/forms/'.$folderName .'/'.$attach["file_name"];
$attachments[$i]["href"] = $href;
$attachments[$i]["name"] = $attach["name"];
$i++;
}
}
$payload=array_merge([
'anexos' => $attachments,
'settings' => $block["settings"],
'fields' => $block["components"],
'repeatable' => $block["repeatable"],
]);
}else {
continue;
}
$skin="default";
if($block["skin"]!="")
$skin=$block["skin"];
if($payload!=[]){
if ($this->twig->getLoader()->exists("blocks/".$block["block"]."/".$block["block"].".".$skin.".email.twig")){
$result.=$this->twig->render("blocks/".$block["block"]."/".$block["block"].".".$skin.".email.twig", $payload);
}elseif($this->twig->getLoader()->exists("blocks/".$block["block"]."/".$block["block"].".default.email.twig")){
$result.=$this->twig->render("blocks/".$block["block"]."/".$block["block"].".default.email.twig", $payload);
}
}
}
return $result;
}
public function onDeleteUserData(StdDeleteUserDataEvent $event)
{
$address=$event->getAddress();
// find std_forms to delete
$formsToRemove=$this->formsRepository->findContentByTerm($address);
foreach($formsToRemove as $form){
$this->entitymanager->remove($form);
}
$this->entitymanager->flush();
}
}
?>