<?php
namespace Score\CmsBundle\Controller\Form;
use DateTime;
use Score\BaseBundle\Services\Generator;
use Score\CmsBundle\Entity\Form\Webform;
use Score\CmsBundle\Entity\Form\WebformValue;
use Score\CmsBundle\Services\MailerManager;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Contracts\Translation\TranslatorInterface;
class PublicController extends AbstractController
{
/**
* @Route("/api/form-load/{id}", name="cms_api_form_load")
*/
public function loadFormAction(Request $request, TranslatorInterface $translator, $id)
{
header('Access-Control-Allow-Origin: *');
$isAdmin = ($request->headers->get('referer') && str_contains($request->headers->get('referer'), '/admin/form/')); // editovanie, data a example
$em = $this->getDoctrine()->getManager();
$form = $em->getRepository(Webform::class)->findOneByIdentifier($id);
// ak neexistuje alebo nieje verejny (cez zapor)
if (!($form && ($form->getVisibility() || $isAdmin))) {
return new JsonResponse([
"status" => "error",
"message" => $translator->trans("score.alert.form.error.load")
]);
}
$data = [
"formId" => $form->getIdentifier(),
"identifier" => $form->getIdentifier(),
"formName" => $form->getName(),
"formDescription" => $form->getDescription(),
"isActive" => $form->getIsActive(),
"successMessage" => $form->getSuccessMessage(),
"visibility" => $form->getVisibility(),
"items" => []
];
if ($isAdmin) {
$data['sendMail'] = $form->getSendMail();
$data['mailList'] = $form->getMailListArr();
$data['params'] = $form->getParamsArr();
}
foreach ($form->getFields() as $field) {
$data["items"][] = [
"identifier" => $field->getIdentifier(),
"title" => $field->getTitle(),
"helpText" => $field->getHelpText(),
"type" => $field->getType(),
"sortOrder" => $field->getSortOrder(),
"required" => $field->getRequired(),
"choices" => $field->getChoicesArr(),
"rows" => $field->getRows(),
"length" => $field->getLength(),
"min" => $field->getMin(),
"max" => $field->getMax(),
];
}
usort($data["items"], function ($a, $b) {
return $a['sortOrder'] <=> $b['sortOrder'];
});
return new JsonResponse([
'status' => "ok",
"data" => $data
]);
}
/**
* @Route("/api/form-save-data", name="cms_api_form_save_data")
*/
public function saveDataAction(Request $request,TranslatorInterface $translator, Generator $generator, MailerManager $mailerManager)
{
header('Access-Control-Allow-Origin: *');
$em = $this->getDoctrine()->getManager();
$form = $em->getRepository(Webform::class)->findOneByIdentifier($request->get("formId"));
if (!$form) {
return new JsonResponse([
"status" => "error",
"message" => $translator->trans("score.alert.form.error.saveData")
]);
}
$inputData = json_decode($request->get("formData"), true);
$key = array_search('access_check', array_column($inputData, 'identifier'));
$robots = array_key_exists("value", $inputData[$key]) && $inputData[$key]["value"];
array_splice($inputData, $key, 1); // removes that field
if ($this->dataAreValid($form, $inputData) && !$robots) {
$code = $generator->generate(18);
foreach ($inputData as $input) {
$value = new WebformValue();
$value->setForm($form)
->setIdentifier($code)
->setFieldIdentifier($input["identifier"])
->setValid($input["valid"]);
$value->setValueArr(array_key_exists("value", $input) ? $input["value"] : "");
if ($this->getUser())
$value->setUserId($this->getUser()->getId());
$em->persist($value);
}
$value = new WebformValue();
$value->setForm($form)
->setIdentifier($code)
->setFieldIdentifier("referer")
->setValid(true)
->setValueArr($request->headers->get('referer'));
$em->persist($value);
$em->flush();
if ($form->getSendMail() && $form->getMailListArr())
$this->sendMailNotification($mailerManager, $form, $code);
return new JsonResponse([
'status' => "ok",
"data" => [],
"successMessage" => $form->getSuccessMessage(),
]);
}
return new JsonResponse([
"status" => "error",
"message" => $translator->trans("score.alert.form.error.dataInvalid"),
]);
}
private function sendMailNotification(MailerManager $mailerManager, $form, $entryId)
{
//$id = '21f742534aa38f44';
//$entryId = 'df992a42acca2698fd';
$em = $this->getDoctrine()->getManager();
$values = $em->getRepository(WebformValue::class)->findBy(["identifier" => $entryId]);
if (!count($values))
return false;
//$form = $values[0]->getForm();
$fields = $form->getFields();
$entries = [];
foreach ($values as $v) {
$fs = array_values(
$fields->filter(
function ($ff) use($v) {
return ($v->getFieldIdentifier() === $ff->getIdentifier());
}
)->toArray()
);
$stringValue = $this->getStringValue($v->getValueArr(), $fs);
$entries[] = [
'label' => $fs ? $fs[0]->getTitle() : "-",
'value' => $stringValue,
];
}
$body = $this->renderView(
'@ScoreCms/Mail/form_submited.html.twig', [
'entries' => $entries,
'entryId' => $entryId,
'form' => $form
]
);
foreach ($form->getMailListArr() as $email) {
$mailerManager
->setTo($email)
->setSubject("Upozornenie na vyplnenie formuláru – " . $form->getName())
->setBody($body)
->send();
}
return true;
//return new Response($body);
}
private function getStringValue($v, $fs)
{
if (!$fs) {
return is_array($v) ? implode(", ", $v) : strval($v);
}
$field = $fs[0];
switch ($field->getType()) {
case "text":
case "textarea":
case "email":
case "number":
case "tel":
return strval($v);
case "date":
return (new DateTime($v))->format('d. m. Y');
case "star":
return ($v . "%");
case "select":
case "radio":
case "checkbox":
$value = "";
if (is_array($v)) {
$values = [];
foreach ($v as $one) {
$values[] = $this->getChoiceLabel($one, $field->getChoicesArr());
}
$value = implode(", ", $values);
} else {
$value = $this->getChoiceLabel($v, $field->getChoicesArr());
}
return $value;
default:
return "-";
}
}
private function getChoiceLabel($v, $choices)
{
$key = array_search($v, array_column($choices, 'value'));
if ($key === false) {
return "neznáme";
}
return $choices[$key]['label'];
}
private function dataAreValid($form, $data)
{
function isValidAnswer($choices, $value)
{
if (is_array($value)) {
foreach ($value as $v) {
if (!isValidAnswer($choices, $v))
return false;
}
return true;
} else {
$key = array_search($value, array_column($choices, 'value'));
return ($choices[$key]["valid"] === true && $value !== "");
}
}
function checkValue($item, $value)
{
switch ($item->getType()) {
case "text":
case "textarea":
return (strlen($value) > 1);
case "email":
$re = '/^[^\s@]+@[^\s@]+\.[^\s@]+$/';
return (preg_match($re, $value) === 1);
case "number":
return (is_numeric($value));
case "date":
$arr = explode('-', $value);
return (isset($arr[0], $arr[1], $arr[2]) && checkdate($arr[1], $arr[2], $arr[0]));
case "tel":
$re = '/^(((\+|0{2})[0-9]{3})|0)(\s?[0-9]{3}\s?[0-9]{3}\s?[0-9]{3})$/';
return (preg_match($re, $value) === 1);
case "select":
case "radio":
return (strlen($value) >= 1 && isValidAnswer($item->getChoicesArr(), $value));
case "checkbox":
return (is_array($value) && count($value) >= 1 && isValidAnswer($item->getChoicesArr(), $value));
case "star":
return ($value > 1 && $value < 101);
default:
return false;
}
}
if (count($form->getFields()) !== count($data))
return false;
$validItems = [];
foreach ($form->getFields() as $field) {
if ($field->getRequired()) {
$key = array_search($field->getIdentifier(), array_column($data, 'identifier'));
$value = isset($data[$key]["value"]) ? $data[$key]["value"] : "";
$validItems[] = checkValue($field, $value);
} else {
$validItems[] = true;
}
}
return (!in_array(false, $validItems));
}
}