<?php
namespace App\Service;
use App\Entity\Form;
use App\Entity\FormLead;
use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use Exception;
class ProcessFormService extends JsonFormManager
{
// Frames
public const FRAME_MAIN = 'main';
public const FRAME_EMBED = 'embed';
public const FRAMES = [
self::FRAME_MAIN,
self::FRAME_EMBED
];
public const STRING_FRAMES = self::FRAME_MAIN . '|' . self::FRAME_EMBED;
private const DAY_FORMAT = 'Y-m-d';
/**
* @param Form $form
* @return bool
*/
public function checkActiveStatus(Form $form): bool
{
return $form->isActive() && $form->getCampaign()->isActive() && $form->getCampaign()->getCompany()->isActive();
}
/**
* @param array $field
* @param FormLead|null $formLead
* @return array
* @throws Exception
*/
public function buildOptions(array $field, ?FormLead $formLead): array
{
if (!$formLead) {
return $field['options'];
}
if (isset($field['options']['attr']['allow_data']) && !$field['options']['attr']['allow_data']) {
return $field['options'];
}
$data = null;
foreach ($formLead->getFormLeadData() as $item) {
if (self::buildFieldName($item->getField(), $item->getType()) !== $field['name']) {
continue;
}
$type = self::getTypeFromFieldName($field['name']);
if (!self::formTypeIsSupported($type)) {
throw new Exception(sprintf('El tipo %s no está soportado', $type));
}
switch ($type) {
case self::CHECKBOX_TYPE:
$data = unserialize($item->getLastValue());
break;
case self::DATETIME_TYPE:
case self::DATE_TYPE:
$data = new DateTime($item->getLastValue());
break;
default:
$data = $item->getLastValue();
}
}
if ($data) {
$field['options']['data'] = $data;
}
return $field['options'];
}
/**
* @param FormLead $formLead
* @return ArrayCollection
* @throws Exception
*/
public function getNotLeadDataInForm(FormLead $formLead): ArrayCollection
{
$leadDataInForm = $this->getLeadDataInForm($formLead);
$result = new ArrayCollection();
foreach ($formLead->getFormLeadData() as $item) {
if (!$leadDataInForm->contains($item)) {
$result->add($item);
}
}
return $result;
}
/**
* @param FormLead $formLead
* @return ArrayCollection
* @throws Exception
*/
public function getLeadDataInForm(FormLead $formLead): ArrayCollection
{
$fieldList = $this->getFormDefinitionFields();
$result = new ArrayCollection();
foreach ($fieldList as $field) {
foreach ($formLead->getFormLeadData() as $item) {
if (JsonFormManager::buildFieldName($item->getField(), $item->getType()) === $field['name']) {
$result->add($item);
}
}
}
return $result;
}
/**
* @param FormLead $formLead
* @return bool
*/
public function isAllowedRenderForm(FormLead $formLead): bool
{
$formInstance = $this->getForm();
if (!$formInstance->isTemporarilyAllow()) {
return true;
}
$date = $this->calculatePeriodStart($formLead);
$dateStart = clone $date;
$endStep = $formInstance->getNotAllowDuringStep() ?: $formInstance->getNotAllowStep();
$endScale = $formInstance->getNotAllowDuringScale() ?: $formInstance->getNotAllowScale();
$dateEnd = DateTimeService::modifyDatetime($date, $endStep, $endScale, DateTimeService::OPERATION_ADD);
if (
$dateStart->format(self::DAY_FORMAT) <= $dateEnd->format(self::DAY_FORMAT) &&
$this->getTodayFormat() <= $dateEnd->format(self::DAY_FORMAT)
) {
if ($formInstance->isOneUpdateByPeriod()) {
$updatedAt = $formLead->getPeriodUpdatedAt()->format(self::DAY_FORMAT);
return !(
$updatedAt >= $dateStart->format(self::DAY_FORMAT) &&
$updatedAt <= $dateEnd->format(self::DAY_FORMAT)
);
}
return true;
}
return false;
}
/**
* @param FormLead $formLead
* @return DateTime|false
*/
private function calculatePeriodStart(FormLead $formLead)
{
$formInstance = $this->getForm();
$date = $formLead->getPeriodStartsAt();
$step = $formInstance->getNotAllowStep();
$scale = $formInstance->getNotAllowScale();
while (true) {
$startsAt = $formLead->getPeriodStartsAt();
if ($date->format(self::DAY_FORMAT) > $this->getTodayFormat()) {
$date = DateTimeService::modifyDatetime($startsAt, $step, $scale, DateTimeService::OPERATION_SUB);
break;
}
$date = DateTimeService::modifyDatetime($startsAt, $step, $scale, DateTimeService::OPERATION_ADD);
}
return $date;
}
/**
* @return string
*/
private function getTodayFormat(): string
{
return (new DateTime())->format(self::DAY_FORMAT);
}
}