Spaces:
No application file
No application file
namespace Mautic\FormBundle\Controller; | |
use Mautic\CoreBundle\Controller\FormController as CommonFormController; | |
use Mautic\CoreBundle\Helper\InputHelper; | |
use Mautic\CoreBundle\Twig\Helper\DateHelper; | |
use Mautic\FormBundle\Event\SubmissionEvent; | |
use Mautic\FormBundle\Model\FormModel; | |
use Mautic\FormBundle\Model\SubmissionModel; | |
use Mautic\LeadBundle\Helper\TokenHelper; | |
use Symfony\Component\HttpFoundation\JsonResponse; | |
use Symfony\Component\HttpFoundation\RedirectResponse; | |
use Symfony\Component\HttpFoundation\Request; | |
use Symfony\Component\HttpFoundation\Response; | |
class PublicController extends CommonFormController | |
{ | |
private array $tokens = []; | |
/** | |
* @return RedirectResponse|Response | |
*/ | |
public function submitAction(Request $request, DateHelper $dateTemplateHelper) | |
{ | |
if ('POST' !== $request->getMethod()) { | |
return $this->accessDenied(); | |
} | |
$isAjax = $request->query->get('ajax', false); | |
$form = null; | |
$post = $request->request->get('mauticform'); | |
$messengerMode = (!empty($post['messenger'])); | |
$server = $request->server->all(); | |
$return = $post['return'] ?? false; | |
if (empty($return)) { | |
// try to get it from the HTTP_REFERER | |
$return = $server['HTTP_REFERER'] ?? false; | |
} | |
if (!empty($return)) { | |
// remove mauticError and mauticMessage from the referer so it doesn't get sent back | |
$return = InputHelper::url($return, null, null, null, ['mauticError', 'mauticMessage'], true); | |
$query = (!str_contains($return, '?')) ? '?' : '&'; | |
} | |
$translator = $this->translator; | |
// check to ensure there is a formId | |
if (!isset($post['formId'])) { | |
$error = $translator->trans('mautic.form.submit.error.unavailable', [], 'flashes'); | |
} else { | |
$formModel = $this->getModel('form.form'); | |
$form = $formModel->getEntity($post['formId']); | |
// check to see that the form was found | |
if (null === $form) { | |
$error = $translator->trans('mautic.form.submit.error.unavailable', [], 'flashes'); | |
} else { | |
// get what to do immediately after successful post | |
$postAction = $form->getPostAction(); | |
$postActionProperty = $form->getPostActionProperty(); | |
// check to ensure the form is published | |
$status = $form->getPublishStatus(); | |
if ('pending' == $status) { | |
$error = $translator->trans( | |
'mautic.form.submit.error.pending', | |
[ | |
'%date%' => $dateTemplateHelper->toFull($form->getPublishUp()), | |
], | |
'flashes' | |
); | |
} elseif ('expired' == $status) { | |
$error = $translator->trans( | |
'mautic.form.submit.error.expired', | |
[ | |
'%date%' => $dateTemplateHelper->toFull($form->getPublishDown()), | |
], | |
'flashes' | |
); | |
} elseif ('published' != $status) { | |
$error = $translator->trans('mautic.form.submit.error.unavailable', [], 'flashes'); | |
} else { | |
$formSubmissionModel = $this->getModel('form.submission'); | |
\assert($formSubmissionModel instanceof SubmissionModel); | |
$result = $formSubmissionModel->saveSubmission($post, $server, $form, $request, true); | |
if (!empty($result['errors'])) { | |
if ($messengerMode || $isAjax) { | |
$error = $result['errors']; | |
} else { | |
$error = ($result['errors']) ? | |
$this->translator->trans('mautic.form.submission.errors').'<br /><ol><li>'. | |
implode('</li><li>', $result['errors']).'</li></ol>' : false; | |
} | |
} elseif (!empty($result['callback'])) { | |
/** @var SubmissionEvent $submissionEvent */ | |
$submissionEvent = $result['callback']; | |
$callbackResponses = $submissionEvent->getPostSubmitCallbackResponse(); | |
// These submit actions have requested a callback after all is said and done | |
$callbacksRequested = $submissionEvent->getPostSubmitCallback(); | |
foreach ($callbacksRequested as $key => $callbackRequested) { | |
$callbackRequested['messengerMode'] = $messengerMode; | |
$callbackRequested['ajaxMode'] = $isAjax; | |
if (isset($callbackRequested['eventName'])) { | |
$submissionEvent->setPostSubmitCallback($key, $callbackRequested); | |
$submissionEvent->setContext($key); | |
$this->dispatcher->dispatch($submissionEvent, $callbackRequested['eventName']); | |
} | |
if ($submissionEvent->isPropagationStopped() && $submissionEvent->hasPostSubmitResponse()) { | |
if ($messengerMode) { | |
$callbackResponses[$key] = $submissionEvent->getPostSubmitResponse(); | |
} else { | |
return $submissionEvent->getPostSubmitResponse(); | |
} | |
} | |
} | |
} elseif (isset($result['submission'])) { | |
/** @var SubmissionEvent $submissionEvent */ | |
$submissionEvent = $result['submission']; | |
} | |
} | |
} | |
} | |
if (isset($submissionEvent) && !empty($postActionProperty)) { | |
// Replace post action property with tokens to support custom redirects, etc | |
$postActionProperty = $this->replacePostSubmitTokens($postActionProperty, $submissionEvent); | |
} | |
if ($messengerMode || $isAjax) { | |
// Return the call via postMessage API | |
$data = ['success' => 1]; | |
if (!empty($error)) { | |
if (is_array($error)) { | |
$data['validationErrors'] = $error; | |
} else { | |
$data['errorMessage'] = $error; | |
} | |
$data['success'] = 0; | |
} else { | |
// Include results in ajax response for JS callback use | |
if (isset($submissionEvent)) { | |
$data['results'] = $submissionEvent->getResults(); | |
} | |
if ('redirect' == $postAction) { | |
$data['redirect'] = $postActionProperty; | |
} elseif (!empty($postActionProperty)) { | |
$data['successMessage'] = [$postActionProperty]; | |
} | |
if (!empty($callbackResponses)) { | |
foreach ($callbackResponses as $response) { | |
// Convert the responses to something useful for a JS response | |
if ($response instanceof RedirectResponse && !isset($data['redirect'])) { | |
$data['redirect'] = $response->getTargetUrl(); | |
} elseif ($response instanceof Response) { | |
if (!isset($data['successMessage'])) { | |
$data['successMessage'] = []; | |
} | |
$data['successMessage'][] = $response->getContent(); | |
} elseif (is_array($response)) { | |
$data = array_merge($data, $response); | |
} elseif (is_string($response)) { | |
if (!isset($data['successMessage'])) { | |
$data['successMessage'] = []; | |
} | |
$data['successMessage'][] = $response; | |
} // ignore anything else | |
} | |
} | |
// Combine all messages into one | |
if (isset($data['successMessage'])) { | |
$data['successMessage'] = implode('<br /><br />', $data['successMessage']); | |
} | |
} | |
if (isset($post['formName'])) { | |
$data['formName'] = $post['formName']; | |
} | |
if ($isAjax) { | |
// Post via ajax so return a json response | |
return new JsonResponse($data); | |
} else { | |
$response = json_encode($data); | |
return $this->render('@MauticForm/messenger.html.twig', ['response' => $response]); | |
} | |
} else { | |
if (!empty($error)) { | |
if ($return) { | |
$hash = (null !== $form) ? '#'.strtolower($form->getAlias()) : ''; | |
return $this->redirect($return.$query.'mauticError='.rawurlencode($error).$hash); | |
} else { | |
$msg = $error; | |
$msgType = 'error'; | |
} | |
} elseif ('redirect' == $postAction) { | |
return $this->redirect($postActionProperty); | |
} elseif ('return' == $postAction) { | |
if (!empty($return)) { | |
if (!empty($postActionProperty)) { | |
$return .= $query.'mauticMessage='.rawurlencode($postActionProperty); | |
} | |
return $this->redirect($return); | |
} else { | |
$msg = $this->translator->trans('mautic.form.submission.thankyou'); | |
} | |
} else { | |
$msg = $postActionProperty; | |
} | |
$session = $request->getSession(); | |
$session->set( | |
'mautic.emailbundle.message', | |
[ | |
'message' => $msg, | |
'type' => (empty($msgType)) ? 'notice' : $msgType, | |
] | |
); | |
return $this->redirectToRoute('mautic_form_postmessage'); | |
} | |
} | |
/** | |
* Displays a message. | |
*/ | |
public function messageAction(Request $request): Response | |
{ | |
$session = $request->getSession(); | |
$message = $session->get('mautic.emailbundle.message', []); | |
$msg = (!empty($message['message'])) ? $message['message'] : ''; | |
$msgType = (!empty($message['type'])) ? $message['type'] : 'notice'; | |
$analytics = $this->factory->getHelper('twig.analytics')->getCode(); | |
if (!empty($analytics)) { | |
$this->factory->getHelper('template.assets')->addCustomDeclaration($analytics); | |
} | |
$logicalName = $this->factory->getHelper('theme')->checkForTwigTemplate('@themes/'.$this->coreParametersHelper->get('theme').'/html/message.html.twig'); | |
return $this->render($logicalName, [ | |
'message' => $msg, | |
'type' => $msgType, | |
'template' => $this->coreParametersHelper->get('theme'), | |
]); | |
} | |
/** | |
* Gives a preview of the form. | |
* | |
* @param int $id | |
* | |
* @return Response | |
* | |
* @throws \Exception | |
* @throws \Mautic\CoreBundle\Exception\FileNotFoundException | |
*/ | |
public function previewAction(Request $request, $id = 0) | |
{ | |
$model = $this->getModel('form.form'); | |
\assert($model instanceof FormModel); | |
$objectId = (empty($id)) ? (int) $request->get('id') : $id; | |
$css = InputHelper::string((string) $request->get('css')); | |
$form = $model->getEntity($objectId); | |
$customStylesheets = (!empty($css)) ? explode(',', $css) : []; | |
$template = null; | |
if (null === $form || !$form->isPublished()) { | |
return $this->notFound(); | |
} else { | |
$html = $model->getContent($form); | |
$model->populateValuesWithGetParameters($form, $html); | |
$viewParams = [ | |
'content' => $html, | |
'stylesheets' => $customStylesheets, | |
'name' => $form->getName(), | |
'metaRobots' => '<meta name="robots" content="index">', | |
]; | |
if ($form->getNoIndex()) { | |
$viewParams['metaRobots'] = '<meta name="robots" content="noindex">'; | |
} | |
// Use form specific template or system-wide default theme | |
$template = $form->getTemplate() ?? $this->coreParametersHelper->get('theme'); | |
if (!empty($template)) { | |
$theme = $this->factory->getTheme($template); | |
if ($theme->getTheme() != $template) { | |
$config = $theme->getConfig(); | |
if (in_array('form', $config['features'])) { | |
$template = $theme->getTheme(); | |
} else { | |
$template = null; | |
} | |
} | |
} | |
} | |
$viewParams['template'] = $template; | |
if (!empty($template)) { | |
$logicalName = $this->factory->getHelper('theme')->checkForTwigTemplate('@themes/'.$template.'/html/form.html.twig'); | |
$assetsHelper = $this->factory->getHelper('template.assets'); | |
$analytics = $this->factory->getHelper('twig.analytics')->getCode(); | |
foreach ($customStylesheets as $css) { | |
$assetsHelper->addStylesheet($css); | |
} | |
$this->factory->getHelper('template.slots')->set('pageTitle', $form->getName()); | |
if (!empty($analytics)) { | |
$assetsHelper->addCustomDeclaration($analytics); | |
} | |
if ($form->getNoIndex()) { | |
$assetsHelper->addCustomDeclaration('<meta name="robots" content="noindex">'); | |
} | |
return $this->render($logicalName, $viewParams); | |
} | |
return $this->render('@MauticForm/form.html.twig', $viewParams); | |
} | |
/** | |
* Generates JS file for automatic form generation. | |
*/ | |
public function generateAction(Request $request): Response | |
{ | |
// Don't store a visitor with this request | |
defined('MAUTIC_NON_TRACKABLE_REQUEST') || define('MAUTIC_NON_TRACKABLE_REQUEST', 1); | |
$formId = (int) $request->get('id'); | |
$model = $this->getModel('form.form'); | |
\assert($model instanceof FormModel); | |
$form = $model->getEntity($formId); | |
$js = ''; | |
if (null !== $form) { | |
$status = $form->getPublishStatus(); | |
if ('published' === $status) { | |
$js = $model->getAutomaticJavascript($form); | |
} | |
} | |
$response = new Response(); | |
$response->setContent($js); | |
$response->setStatusCode(Response::HTTP_OK); | |
$response->headers->set('Content-Type', 'text/javascript'); | |
return $response; | |
} | |
/** | |
* @return Response | |
*/ | |
public function embedAction(Request $request) | |
{ | |
$formId = (int) $request->get('id'); | |
/** @var FormModel $model */ | |
$model = $this->getModel('form'); | |
$form = $model->getEntity($formId); | |
if (null !== $form) { | |
$status = $form->getPublishStatus(); | |
if ('published' === $status) { | |
if ($request->get('video')) { | |
return $this->render( | |
'@MauticForm/Public/videoembed.html.twig', | |
['form' => $form, 'fieldSettings' => $model->getCustomComponents()['fields']] | |
); | |
} | |
$content = $model->getContent($form, false, true); | |
return new Response($content); | |
} | |
} | |
return new Response('', Response::HTTP_NOT_FOUND); | |
} | |
/** | |
* @return string|string[] | |
*/ | |
private function replacePostSubmitTokens($string, SubmissionEvent $submissionEvent): string|array | |
{ | |
if (empty($this->tokens)) { | |
if ($lead = $submissionEvent->getLead()) { | |
$this->tokens = array_merge( | |
$submissionEvent->getTokens(), | |
TokenHelper::findLeadTokens( | |
$string, | |
$lead->getProfileFields() | |
) | |
); | |
} | |
} | |
return str_replace(array_keys($this->tokens), array_values($this->tokens), $string); | |
} | |
} | |