Initial commit: CloudOps infrastructure platform
This commit is contained in:
@@ -0,0 +1,323 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\FormBundle\Controller;
|
||||
|
||||
use Mautic\CoreBundle\Controller\FormController as CommonFormController;
|
||||
use Mautic\FormBundle\Entity\Action;
|
||||
use Mautic\FormBundle\Form\Type\ActionType;
|
||||
use Mautic\FormBundle\Model\FormModel;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class ActionController extends CommonFormController
|
||||
{
|
||||
/**
|
||||
* Generates new form and processes post data.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function newAction(Request $request)
|
||||
{
|
||||
$success = 0;
|
||||
$valid = $cancelled = false;
|
||||
$method = $request->getMethod();
|
||||
$session = $request->getSession();
|
||||
|
||||
if ('POST' == $method) {
|
||||
$formAction = $request->request->all()['formaction'] ?? [];
|
||||
$actionType = $formAction['type'];
|
||||
$formId = $formAction['formId'];
|
||||
} else {
|
||||
$actionType = $request->query->get('type');
|
||||
$formId = $request->query->get('formId');
|
||||
$formAction = [
|
||||
'type' => $actionType,
|
||||
'formId' => $formId,
|
||||
];
|
||||
}
|
||||
|
||||
// ajax only for form fields
|
||||
if (!$actionType
|
||||
|| !$this->security->isGranted(['form:forms:editown', 'form:forms:editother', 'form:forms:create'], 'MATCH_ONE')
|
||||
) {
|
||||
return $this->modalAccessDenied();
|
||||
}
|
||||
|
||||
// fire the form builder event
|
||||
$formModel = $this->getModel('form.form');
|
||||
\assert($formModel instanceof FormModel);
|
||||
$customComponents = $formModel->getCustomComponents();
|
||||
$form = $this->formFactory->create(ActionType::class, $formAction, [
|
||||
'action' => $this->generateUrl('mautic_formaction_action', ['objectAction' => 'new']),
|
||||
'settings' => $customComponents['actions'][$actionType],
|
||||
'formId' => $formId,
|
||||
]);
|
||||
$form->get('formId')->setData($formId);
|
||||
$formAction['settings'] = $customComponents['actions'][$actionType];
|
||||
|
||||
// Check for a submitted form and process it
|
||||
if ('POST' == $method) {
|
||||
if (!$cancelled = $this->isFormCancelled($form)) {
|
||||
if ($valid = $this->isFormValid($form)) {
|
||||
$success = 1;
|
||||
|
||||
// form is valid so process the data
|
||||
$keyId = 'new'.hash('sha1', uniqid(mt_rand()));
|
||||
|
||||
// save the properties to session
|
||||
$actions = $session->get('mautic.form.'.$formId.'.actions.modified', []);
|
||||
$formData = $form->getData();
|
||||
$formAction = array_merge($formAction, $formData);
|
||||
$formAction['id'] = $keyId;
|
||||
if (empty($formAction['name'])) {
|
||||
// set it to the event default
|
||||
$formAction['name'] = $this->translator->trans($formAction['settings']['label']);
|
||||
}
|
||||
$actions[$keyId] = $formAction;
|
||||
$session->set('mautic.form.'.$formId.'.actions.modified', $actions);
|
||||
} else {
|
||||
$success = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$viewParams = ['type' => $actionType];
|
||||
|
||||
if ($cancelled || $valid) {
|
||||
$closeModal = true;
|
||||
} else {
|
||||
$closeModal = false;
|
||||
$viewParams['tmpl'] = 'action';
|
||||
$viewParams['form'] = $form->createView();
|
||||
$header = $formAction['settings']['label'];
|
||||
$viewParams['actionHeader'] = $this->translator->trans($header);
|
||||
|
||||
if (isset($formAction['settings']['formTheme'])) {
|
||||
$viewParams['formTheme'] = $formAction['settings']['formTheme'];
|
||||
}
|
||||
}
|
||||
|
||||
$passthroughVars = [
|
||||
'mauticContent' => 'formAction',
|
||||
'success' => $success,
|
||||
'route' => false,
|
||||
];
|
||||
|
||||
if (!empty($keyId)) {
|
||||
// prevent undefined errors
|
||||
$entity = new Action();
|
||||
$blank = $entity->convertToArray();
|
||||
$formAction = array_merge($blank, $formAction);
|
||||
|
||||
$template = (!empty($formAction['settings']['template'])) ? $formAction['settings']['template'] :
|
||||
'@MauticForm/Action/base_form_action.html.twig';
|
||||
$passthroughVars['actionId'] = $keyId;
|
||||
$passthroughVars['actionHtml'] = $this->renderView($template, [
|
||||
'inForm' => true,
|
||||
'action' => $formAction,
|
||||
'id' => $keyId,
|
||||
'formId' => $formId,
|
||||
]);
|
||||
}
|
||||
|
||||
if ($closeModal) {
|
||||
// just close the modal
|
||||
$passthroughVars['closeModal'] = 1;
|
||||
|
||||
return new JsonResponse($passthroughVars);
|
||||
}
|
||||
|
||||
return $this->ajaxAction($request, [
|
||||
'contentTemplate' => '@MauticForm/Builder/'.$viewParams['tmpl'].'.html.twig',
|
||||
'viewParameters' => $viewParams,
|
||||
'passthroughVars' => $passthroughVars,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates edit form and processes post data.
|
||||
*
|
||||
* @param int $objectId
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function editAction(Request $request, $objectId)
|
||||
{
|
||||
$session = $request->getSession();
|
||||
$method = $request->getMethod();
|
||||
$formaction = $request->request->all()['formaction'] ?? [];
|
||||
$formId = 'POST' === $method ? ($formaction['formId'] ?? '') : $request->query->get('formId');
|
||||
$actions = $session->get('mautic.form.'.$formId.'.actions.modified', []);
|
||||
$success = 0;
|
||||
$valid = $cancelled = false;
|
||||
$formAction = array_key_exists($objectId, $actions) ? $actions[$objectId] : null;
|
||||
|
||||
if (null !== $formAction) {
|
||||
$formModel = $this->getModel('form.form');
|
||||
\assert($formModel instanceof FormModel);
|
||||
$actionType = $formAction['type'];
|
||||
$customComponents = $formModel->getCustomComponents();
|
||||
$formAction['settings'] = $customComponents['actions'][$actionType];
|
||||
|
||||
// ajax only for form fields
|
||||
if (!$actionType
|
||||
|| !$request->isXmlHttpRequest()
|
||||
|| !$this->security->isGranted(['form:forms:editown', 'form:forms:editother', 'form:forms:create'], 'MATCH_ONE')
|
||||
) {
|
||||
return $this->modalAccessDenied();
|
||||
}
|
||||
|
||||
$form = $this->formFactory->create(ActionType::class, $formAction, [
|
||||
'action' => $this->generateUrl('mautic_formaction_action', ['objectAction' => 'edit', 'objectId' => $objectId]),
|
||||
'settings' => $formAction['settings'],
|
||||
'formId' => $formId,
|
||||
]);
|
||||
$form->get('formId')->setData($formId);
|
||||
|
||||
// Check for a submitted form and process it
|
||||
if ('POST' == $method) {
|
||||
if (!$cancelled = $this->isFormCancelled($form)) {
|
||||
if ($valid = $this->isFormValid($form)) {
|
||||
$success = 1;
|
||||
|
||||
// form is valid so process the data
|
||||
|
||||
// save the properties to session
|
||||
$session = $request->getSession();
|
||||
$actions = $session->get('mautic.form.'.$formId.'.actions.modified');
|
||||
$formData = $form->getData();
|
||||
// overwrite with updated data
|
||||
$formAction = array_merge($actions[$objectId], $formData);
|
||||
if (empty($formAction['name'])) {
|
||||
// set it to the event default
|
||||
$formAction['name'] = $this->translator->trans($formAction['settings']['label']);
|
||||
}
|
||||
$actions[$objectId] = $formAction;
|
||||
$session->set('mautic.form.'.$formId.'.actions.modified', $actions);
|
||||
|
||||
// generate HTML for the field
|
||||
$keyId = $objectId;
|
||||
|
||||
// take note if this is a submit button or not
|
||||
if ('button' == $actionType) {
|
||||
$submits = $session->get('mautic.formactions.submits', []);
|
||||
if ('submit' == $formAction['properties']['type'] && !in_array($keyId, $submits)) {
|
||||
// button type updated to submit
|
||||
$submits[] = $keyId;
|
||||
$session->set('mautic.formactions.submits', $submits);
|
||||
} elseif ('submit' != $formAction['properties']['type'] && in_array($keyId, $submits)) {
|
||||
// button type updated to something other than submit
|
||||
$key = array_search($keyId, $submits);
|
||||
unset($submits[$key]);
|
||||
$session->set('mautic.formactions.submits', $submits);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$viewParams = ['type' => $actionType];
|
||||
if ($cancelled || $valid) {
|
||||
$closeModal = true;
|
||||
} else {
|
||||
$closeModal = false;
|
||||
$viewParams['tmpl'] = 'action';
|
||||
$viewParams['form'] = $form->createView();
|
||||
$viewParams['actionHeader'] = $this->translator->trans($formAction['settings']['label']);
|
||||
|
||||
if (isset($formAction['settings']['formTheme'])) {
|
||||
$viewParams['formTheme'] = $formAction['settings']['formTheme'];
|
||||
}
|
||||
}
|
||||
|
||||
$passthroughVars = [
|
||||
'mauticContent' => 'formAction',
|
||||
'success' => $success,
|
||||
'route' => false,
|
||||
];
|
||||
|
||||
if (!empty($keyId)) {
|
||||
$passthroughVars['actionId'] = $keyId;
|
||||
|
||||
// prevent undefined errors
|
||||
$entity = new Action();
|
||||
$blank = $entity->convertToArray();
|
||||
$formAction = array_merge($blank, $formAction);
|
||||
$template = (!empty($formAction['settings']['template'])) ? $formAction['settings']['template'] :
|
||||
'@MauticForm/Action/base_form_action.html.twig';
|
||||
$passthroughVars['actionHtml'] = $this->renderView($template, [
|
||||
'inForm' => true,
|
||||
'action' => $formAction,
|
||||
'id' => $keyId,
|
||||
'formId' => $formId,
|
||||
]);
|
||||
}
|
||||
|
||||
if ($closeModal) {
|
||||
// just close the modal
|
||||
$passthroughVars['closeModal'] = 1;
|
||||
|
||||
return new JsonResponse($passthroughVars);
|
||||
}
|
||||
|
||||
return $this->ajaxAction($request, [
|
||||
'contentTemplate' => '@MauticForm/Builder/'.$viewParams['tmpl'].'.html.twig',
|
||||
'viewParameters' => $viewParams,
|
||||
'passthroughVars' => $passthroughVars,
|
||||
]);
|
||||
}
|
||||
|
||||
return new JsonResponse(['success' => 0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the entity.
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function deleteAction(Request $request, $objectId)
|
||||
{
|
||||
$session = $request->getSession();
|
||||
$formId = $request->query->get('formId');
|
||||
$actions = $session->get('mautic.form.'.$formId.'.actions.modified', []);
|
||||
$delete = $session->get('mautic.form.'.$formId.'.actions.deleted', []);
|
||||
|
||||
// ajax only for form fields
|
||||
if (!$request->isXmlHttpRequest()
|
||||
|| !$this->security->isGranted(['form:forms:editown', 'form:forms:editother', 'form:forms:create'], 'MATCH_ONE')
|
||||
) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
$formAction = (array_key_exists($objectId, $actions)) ? $actions[$objectId] : null;
|
||||
if ('POST' == $request->getMethod() && null !== $formAction) {
|
||||
// add the field to the delete list
|
||||
if (!in_array($objectId, $delete)) {
|
||||
$delete[] = $objectId;
|
||||
$session->set('mautic.form.'.$formId.'.actions.deleted', $delete);
|
||||
}
|
||||
|
||||
// take note if this is a submit button or not
|
||||
if ('button' == $formAction['type']) {
|
||||
$submits = $session->get('mautic.formactions.submits', []);
|
||||
$properties = $formAction['properties'];
|
||||
if ('submit' == $properties['type'] && in_array($objectId, $submits)) {
|
||||
$key = array_search($objectId, $submits);
|
||||
unset($submits[$key]);
|
||||
$session->set('mautic.formactions.submits', $submits);
|
||||
}
|
||||
}
|
||||
|
||||
$dataArray = [
|
||||
'mauticContent' => 'formAction',
|
||||
'success' => 1,
|
||||
'route' => false,
|
||||
];
|
||||
} else {
|
||||
$dataArray = ['success' => 0];
|
||||
}
|
||||
|
||||
return new JsonResponse($dataArray);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\FormBundle\Controller;
|
||||
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use Mautic\CoreBundle\Controller\AjaxController as CommonAjaxController;
|
||||
use Mautic\CoreBundle\Factory\ModelFactory;
|
||||
use Mautic\CoreBundle\Helper\CoreParametersHelper;
|
||||
use Mautic\CoreBundle\Helper\InputHelper;
|
||||
use Mautic\CoreBundle\Helper\UserHelper;
|
||||
use Mautic\CoreBundle\Security\Permissions\CorePermissions;
|
||||
use Mautic\CoreBundle\Service\FlashBag;
|
||||
use Mautic\CoreBundle\Translation\Translator;
|
||||
use Mautic\FormBundle\Collector\AlreadyMappedFieldCollectorInterface;
|
||||
use Mautic\FormBundle\Collector\FieldCollectorInterface;
|
||||
use Mautic\FormBundle\Crate\FieldCrate;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
|
||||
class AjaxController extends CommonAjaxController
|
||||
{
|
||||
public function __construct(
|
||||
private FieldCollectorInterface $fieldCollector,
|
||||
private AlreadyMappedFieldCollectorInterface $mappedFieldCollector,
|
||||
ManagerRegistry $doctrine,
|
||||
ModelFactory $modelFactory,
|
||||
UserHelper $userHelper,
|
||||
CoreParametersHelper $coreParametersHelper,
|
||||
EventDispatcherInterface $dispatcher,
|
||||
Translator $translator,
|
||||
FlashBag $flashBag,
|
||||
RequestStack $requestStack,
|
||||
CorePermissions $security,
|
||||
) {
|
||||
parent::__construct($doctrine, $modelFactory, $userHelper, $coreParametersHelper, $dispatcher, $translator, $flashBag, $requestStack, $security);
|
||||
}
|
||||
|
||||
public function reorderFieldsAction(Request $request, string $name = 'fields'): JsonResponse
|
||||
{
|
||||
if ('form' === $name) {
|
||||
$name = 'fields';
|
||||
}
|
||||
$dataArray = ['success' => 0];
|
||||
$sessionId = InputHelper::clean($request->request->get('formId'));
|
||||
$sessionName = 'mautic.form.'.$sessionId.'.'.$name.'.modified';
|
||||
$session = $request->getSession();
|
||||
$orderName = ('fields' == $name) ? 'mauticform' : 'mauticform_action';
|
||||
$order = InputHelper::clean($request->request->all()[$orderName]);
|
||||
$components = $session->get($sessionName);
|
||||
|
||||
if (!empty($order) && !empty($components)) {
|
||||
$components = array_replace(array_flip($order), $components);
|
||||
$session->set($sessionName, $components);
|
||||
$dataArray['success'] = 1;
|
||||
}
|
||||
|
||||
return $this->sendJsonResponse($dataArray);
|
||||
}
|
||||
|
||||
public function getFieldsForObjectAction(Request $request): JsonResponse
|
||||
{
|
||||
$formId = $request->get('formId');
|
||||
$mappedObject = $request->get('mappedObject');
|
||||
$mappedField = $request->get('mappedField');
|
||||
$mappedFields = $this->mappedFieldCollector->getFields($formId, $mappedObject);
|
||||
$fields = $this->fieldCollector->getFields($mappedObject);
|
||||
$fields = $fields->removeFieldsWithKeys($mappedFields, $mappedField);
|
||||
|
||||
return $this->sendJsonResponse(
|
||||
[
|
||||
'fields' => array_map(
|
||||
fn (FieldCrate $field): array => [
|
||||
'label' => $field->getName(),
|
||||
'value' => $field->getKey(),
|
||||
'isListType' => $field->isListType(),
|
||||
],
|
||||
$fields->getArrayCopy()
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function reorderActionsAction(Request $request): JsonResponse
|
||||
{
|
||||
return $this->reorderFieldsAction($request, 'actions');
|
||||
}
|
||||
|
||||
public function updateFormFieldsAction(Request $request): JsonResponse
|
||||
{
|
||||
$formId = (int) $request->request->get('formId');
|
||||
$dataArray = ['success' => 0];
|
||||
$model = $this->getModel('form');
|
||||
$entity = $model->getEntity($formId);
|
||||
$formFields = empty($entity) ? [] : $entity->getFields();
|
||||
$fields = [];
|
||||
|
||||
foreach ($formFields as $field) {
|
||||
if ('button' != $field->getType()) {
|
||||
$properties = $field->getProperties();
|
||||
$options = [];
|
||||
|
||||
if (!empty($properties['list']['list'])) {
|
||||
// If the field is a SELECT field then the data gets stored in [list][list]
|
||||
$optionList = $properties['list']['list'];
|
||||
} elseif (!empty($properties['optionlist']['list'])) {
|
||||
// If the field is a radio or a checkbox then it will be stored in [optionlist][list]
|
||||
$optionList = $properties['optionlist']['list'];
|
||||
}
|
||||
if (!empty($optionList)) {
|
||||
foreach ($optionList as $listItem) {
|
||||
if (is_array($listItem) && isset($listItem['value']) && isset($listItem['label'])) {
|
||||
// The select box needs values to be [value] => label format so make sure we have that style then put it in
|
||||
$options[$listItem['value']] = $listItem['label'];
|
||||
} elseif (!is_array($listItem)) {
|
||||
// Keeping for BC
|
||||
$options[] = $listItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$fields[] = [
|
||||
'id' => $field->getId(),
|
||||
'label' => $field->getLabel(),
|
||||
'alias' => $field->getAlias(),
|
||||
'type' => $field->getType(),
|
||||
'options' => $options,
|
||||
];
|
||||
|
||||
// Be sure to not pollute the symbol table.
|
||||
unset($optionList);
|
||||
}
|
||||
}
|
||||
|
||||
$dataArray['fields'] = $fields;
|
||||
$dataArray['success'] = 1;
|
||||
|
||||
return $this->sendJsonResponse($dataArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax submit for forms.
|
||||
*/
|
||||
public function submitAction(Request $request): JsonResponse
|
||||
{
|
||||
$response = $this->forwardWithPost('Mautic\FormBundle\Controller\PublicController::submitAction', $request->request->all(), [], ['ajax' => true]);
|
||||
$responseData = json_decode($response->getContent(), true);
|
||||
$success = (!in_array($response->getStatusCode(), [404, 500]) && empty($responseData['errorMessage'])
|
||||
&& empty($responseData['validationErrors']));
|
||||
|
||||
$message = '';
|
||||
$type = '';
|
||||
if (isset($responseData['successMessage'])) {
|
||||
$message = $responseData['successMessage'];
|
||||
$type = 'notice';
|
||||
} elseif (isset($responseData['errorMessage'])) {
|
||||
$message = $responseData['errorMessage'];
|
||||
$type = 'error';
|
||||
}
|
||||
|
||||
$data = is_array($responseData)
|
||||
? array_merge($responseData, ['message' => $message, 'type' => $type, 'success' => $success])
|
||||
: [];
|
||||
|
||||
return $this->sendJsonResponse($data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\FormBundle\Controller\Api;
|
||||
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use Mautic\ApiBundle\Controller\CommonApiController;
|
||||
use Mautic\ApiBundle\Helper\EntityResultHelper;
|
||||
use Mautic\CoreBundle\Entity\CommonEntity;
|
||||
use Mautic\CoreBundle\Factory\ModelFactory;
|
||||
use Mautic\CoreBundle\Helper\AppVersion;
|
||||
use Mautic\CoreBundle\Helper\CoreParametersHelper;
|
||||
use Mautic\CoreBundle\Security\Permissions\CorePermissions;
|
||||
use Mautic\CoreBundle\Translation\Translator;
|
||||
use Mautic\FormBundle\Entity\Action;
|
||||
use Mautic\FormBundle\Entity\Field;
|
||||
use Mautic\FormBundle\Entity\Form;
|
||||
use Mautic\FormBundle\Model\ActionModel;
|
||||
use Mautic\FormBundle\Model\FieldModel;
|
||||
use Mautic\FormBundle\Model\FormModel;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
|
||||
/**
|
||||
* @extends CommonApiController<Form>
|
||||
*/
|
||||
class FormApiController extends CommonApiController
|
||||
{
|
||||
/**
|
||||
* @var FormModel|null
|
||||
*/
|
||||
protected $model;
|
||||
|
||||
public function __construct(
|
||||
CorePermissions $security,
|
||||
Translator $translator,
|
||||
EntityResultHelper $entityResultHelper,
|
||||
RouterInterface $router,
|
||||
FormFactoryInterface $formFactory,
|
||||
AppVersion $appVersion,
|
||||
RequestStack $requestStack,
|
||||
ManagerRegistry $doctrine,
|
||||
ModelFactory $modelFactory,
|
||||
EventDispatcherInterface $dispatcher,
|
||||
CoreParametersHelper $coreParametersHelper,
|
||||
) {
|
||||
$formModel = $modelFactory->getModel('form');
|
||||
\assert($formModel instanceof FormModel);
|
||||
|
||||
$this->model = $formModel;
|
||||
$this->entityClass = Form::class;
|
||||
$this->entityNameOne = 'form';
|
||||
$this->entityNameMulti = 'forms';
|
||||
$this->serializerGroups = ['formDetails', 'categoryList', 'publishDetails'];
|
||||
|
||||
$this->dataInputMasks = [
|
||||
'text' => 'html',
|
||||
'message' => 'html',
|
||||
];
|
||||
|
||||
parent::__construct($security, $translator, $entityResultHelper, $router, $formFactory, $appVersion, $requestStack, $doctrine, $modelFactory, $dispatcher, $coreParametersHelper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete fields from a form.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function deleteFieldsAction(Request $request, $formId)
|
||||
{
|
||||
if (!$this->security->isGranted(['form:forms:editown', 'form:forms:editother'], 'MATCH_ONE')) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
$entity = $this->model->getEntity($formId);
|
||||
|
||||
if (null === $entity) {
|
||||
return $this->notFound();
|
||||
}
|
||||
|
||||
$fieldsToDelete = $request->query->all()['fields'] ?? $request->request->all()['fields'] ?? [];
|
||||
|
||||
if (!is_array($fieldsToDelete)) {
|
||||
return $this->badRequest('The fields attribute must be array.');
|
||||
}
|
||||
|
||||
$this->model->deleteFields($entity, $fieldsToDelete);
|
||||
|
||||
$view = $this->view([$this->entityNameOne => $entity]);
|
||||
|
||||
return $this->handleView($view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete fields from a form.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function deleteActionsAction(Request $request, $formId)
|
||||
{
|
||||
if (!$this->security->isGranted(['form:forms:editown', 'form:forms:editother'], 'MATCH_ONE')) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
$entity = $this->model->getEntity($formId);
|
||||
|
||||
if (null === $entity) {
|
||||
return $this->notFound();
|
||||
}
|
||||
|
||||
$actionsToDelete = $request->query->all()['actions'] ?? $request->request->all()['actions'] ?? [];
|
||||
|
||||
if (!is_array($actionsToDelete)) {
|
||||
return $this->badRequest('The actions attribute must be array.');
|
||||
}
|
||||
|
||||
$this->model->deleteActions($entity, $actionsToDelete);
|
||||
|
||||
$view = $this->view([$this->entityNameOne => $entity]);
|
||||
|
||||
return $this->handleView($view);
|
||||
}
|
||||
|
||||
protected function preSaveEntity(&$entity, $form, $parameters, $action = 'edit')
|
||||
{
|
||||
$fieldModel = $this->getModel('form.field');
|
||||
\assert($fieldModel instanceof FieldModel);
|
||||
$actionModel = $this->getModel('form.action');
|
||||
\assert($actionModel instanceof ActionModel);
|
||||
$method = $this->getCurrentRequest()->getMethod();
|
||||
$isNew = false;
|
||||
$alias = $entity->getAlias();
|
||||
|
||||
if (empty($alias)) {
|
||||
// Set clean alias to prevent SQL errors
|
||||
$alias = $this->model->cleanAlias($entity->getName(), '', 10);
|
||||
$entity->setAlias($alias);
|
||||
}
|
||||
|
||||
// Set timestamps
|
||||
$this->model->setTimestamps($entity, true, false);
|
||||
|
||||
if (!$entity->getId()) {
|
||||
$isNew = true;
|
||||
|
||||
// Save the form first to get the form ID.
|
||||
// Using the repository function to not trigger the listeners twice.
|
||||
$this->model->getRepository()->saveEntity($entity);
|
||||
}
|
||||
|
||||
$formId = $entity->getId();
|
||||
$requestFieldIds = [];
|
||||
$requestActionIds = [];
|
||||
$requestUsedAliases = [];
|
||||
$currentFields = $entity->getFields();
|
||||
$currentActions = $entity->getActions();
|
||||
|
||||
// Add fields from the request
|
||||
if (!empty($parameters['fields']) && is_array($parameters['fields'])) {
|
||||
$aliases = $entity->getFieldAliases();
|
||||
|
||||
foreach ($parameters['fields'] as &$fieldParams) {
|
||||
if (empty($fieldParams['id'])) {
|
||||
// Create an unique ID if not set - the following code requires one
|
||||
$fieldParams['id'] = 'new'.hash('sha1', uniqid(mt_rand()));
|
||||
/** @var ?Field $fieldEntity */
|
||||
$fieldEntity = $fieldModel->getEntity();
|
||||
} else {
|
||||
/** @var ?Field $fieldEntity */
|
||||
$fieldEntity = $fieldModel->getEntity($fieldParams['id']);
|
||||
$requestFieldIds[] = $fieldParams['id'];
|
||||
}
|
||||
|
||||
if (is_null($fieldEntity)) {
|
||||
$msg = $this->translator->trans(
|
||||
'mautic.core.error.entity.not.found',
|
||||
[
|
||||
'%entity%' => $this->translator->trans('mautic.form.field'),
|
||||
'%id%' => $fieldParams['id'],
|
||||
],
|
||||
'flashes'
|
||||
);
|
||||
|
||||
return $this->returnError($msg, Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$fieldEntityArray = $fieldEntity->convertToArray();
|
||||
$fieldEntityArray['formId'] = $formId;
|
||||
$fieldEntityArray['mappedObject'] = $fieldParams['mappedObject'] ?? null;
|
||||
|
||||
if (!empty($fieldParams['alias'])) {
|
||||
$fieldParams['alias'] = $fieldModel->cleanAlias($fieldParams['alias'], 'f_', 25);
|
||||
|
||||
if (!in_array($fieldParams['alias'], $aliases)) {
|
||||
$fieldEntityArray['alias'] = $fieldParams['alias'];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($fieldEntityArray['alias'])) {
|
||||
$fieldEntityArray['alias'] = $fieldParams['alias'] = $fieldModel->generateAlias($fieldEntityArray['label'] ?? '', $aliases);
|
||||
}
|
||||
|
||||
// Check that the alias is not already in use by another field
|
||||
if (in_array($fieldEntityArray['alias'], $requestUsedAliases)) {
|
||||
$msg = $this->translator->trans('mautic.form.field.alias.unique', ['%alias%' => $fieldEntityArray['alias']], 'validators');
|
||||
|
||||
return $this->returnError($msg, Response::HTTP_BAD_REQUEST);
|
||||
} else {
|
||||
$requestUsedAliases[] = $fieldEntityArray['alias'];
|
||||
}
|
||||
|
||||
$fieldForm = $this->createFieldEntityForm($fieldEntityArray);
|
||||
$fieldForm->submit($fieldParams, 'PATCH' !== $method);
|
||||
|
||||
if (!$fieldForm->isValid()) {
|
||||
$formErrors = $this->getFormErrorMessages($fieldForm);
|
||||
$msg = $this->getFormErrorMessage($formErrors);
|
||||
|
||||
return $this->returnError($msg, Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
$this->model->setFields($entity, $parameters['fields']);
|
||||
}
|
||||
|
||||
// Remove fields which weren't in the PUT request
|
||||
if (!$isNew && 'PUT' === $method) {
|
||||
$fieldsToDelete = [];
|
||||
|
||||
foreach ($currentFields as $currentField) {
|
||||
if (!in_array($currentField->getId(), $requestFieldIds)) {
|
||||
$fieldsToDelete[] = $currentField->getId();
|
||||
}
|
||||
}
|
||||
|
||||
if ($fieldsToDelete) {
|
||||
$this->model->deleteFields($entity, $fieldsToDelete);
|
||||
}
|
||||
}
|
||||
|
||||
// Add actions from the request
|
||||
if (!empty($parameters['actions']) && is_array($parameters['actions'])) {
|
||||
$actions = [];
|
||||
foreach ($parameters['actions'] as &$actionParams) {
|
||||
if (empty($actionParams['id'])) {
|
||||
$actionParams['id'] = 'new'.hash('sha1', uniqid(mt_rand()));
|
||||
$actionEntity = $actionModel->getEntity();
|
||||
} else {
|
||||
$actionEntity = $actionModel->getEntity($actionParams['id']);
|
||||
$requestActionIds[] = $actionParams['id'];
|
||||
}
|
||||
|
||||
$actionEntity->setForm($entity);
|
||||
|
||||
$actionForm = $this->createActionEntityForm($actionEntity, $actionParams);
|
||||
$actionForm->submit($actionParams, 'PATCH' !== $method);
|
||||
|
||||
if (!$actionForm->isValid()) {
|
||||
$formErrors = $this->getFormErrorMessages($actionForm);
|
||||
$msg = $this->getFormErrorMessage($formErrors);
|
||||
|
||||
return $this->returnError($msg, Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
$actions[] = $actionForm->getNormData();
|
||||
}
|
||||
|
||||
// Save the form first and new actions so that new fields are available to actions.
|
||||
// Using the repository function to not trigger the listeners twice.
|
||||
$this->model->getRepository()->saveEntity($entity);
|
||||
$this->model->setActions($entity, $actions);
|
||||
}
|
||||
|
||||
// Remove actions which weren't in the PUT request
|
||||
if (!$isNew && 'PUT' === $method) {
|
||||
$actionsToDelete = [];
|
||||
|
||||
foreach ($currentActions as $currentAction) {
|
||||
if (!in_array($currentAction->getId(), $requestActionIds)) {
|
||||
$actionsToDelete[] = $currentAction->getId();
|
||||
}
|
||||
}
|
||||
|
||||
if ($actionsToDelete) {
|
||||
$this->model->deleteActions($entity, $actionsToDelete);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the form instance.
|
||||
*
|
||||
* @return FormInterface<mixed>
|
||||
*/
|
||||
protected function createActionEntityForm(Action $entity, array $action)
|
||||
{
|
||||
/** @var FormModel $formModel */
|
||||
$formModel = $this->getModel('form');
|
||||
$components = $formModel->getCustomComponents();
|
||||
$type = $action['type'] ?? $entity->getType();
|
||||
|
||||
$formActionModel = $this->getModel('form.action');
|
||||
\assert($formActionModel instanceof ActionModel);
|
||||
|
||||
return $formActionModel->createForm(
|
||||
$entity,
|
||||
$this->formFactory,
|
||||
null,
|
||||
[
|
||||
'csrf_protection' => false,
|
||||
'allow_extra_fields' => true,
|
||||
'settings' => $components['actions'][$type],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the form instance.
|
||||
*
|
||||
* @return FormInterface<mixed>
|
||||
*/
|
||||
protected function createFieldEntityForm($entity)
|
||||
{
|
||||
$formFieldModel = $this->getModel('form.field');
|
||||
\assert($formFieldModel instanceof FieldModel);
|
||||
|
||||
return $formFieldModel->createForm(
|
||||
$entity,
|
||||
$this->formFactory,
|
||||
null,
|
||||
[
|
||||
'csrf_protection' => false,
|
||||
'allow_extra_fields' => true,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CommonEntity $entity
|
||||
* @param array<mixed> $parameters
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function processForm(Request $request, $entity, $parameters = null, $method = 'PUT')
|
||||
{
|
||||
if (!isset($parameters['postAction'])) {
|
||||
$parameters['postAction'] = 'return';
|
||||
}
|
||||
|
||||
return parent::processForm($request, $entity, $parameters, $method);
|
||||
}
|
||||
|
||||
public function newEntityAction(Request $request): Response
|
||||
{
|
||||
$parameters = $request->request->all();
|
||||
|
||||
if (!isset($parameters['postAction'])) {
|
||||
$request->request->add(['postAction' => 'return']);
|
||||
}
|
||||
|
||||
return parent::newEntityAction($request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\FormBundle\Controller\Api;
|
||||
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use Mautic\ApiBundle\Controller\CommonApiController;
|
||||
use Mautic\ApiBundle\Helper\EntityResultHelper;
|
||||
use Mautic\CoreBundle\Factory\ModelFactory;
|
||||
use Mautic\CoreBundle\Helper\AppVersion;
|
||||
use Mautic\CoreBundle\Helper\CoreParametersHelper;
|
||||
use Mautic\CoreBundle\Helper\UserHelper;
|
||||
use Mautic\CoreBundle\Security\Permissions\CorePermissions;
|
||||
use Mautic\CoreBundle\Translation\Translator;
|
||||
use Mautic\FormBundle\Entity\Form;
|
||||
use Mautic\FormBundle\Entity\Submission;
|
||||
use Mautic\FormBundle\Model\SubmissionModel;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
|
||||
/**
|
||||
* @extends CommonApiController<Submission>
|
||||
*/
|
||||
class SubmissionApiController extends CommonApiController
|
||||
{
|
||||
public function __construct(CorePermissions $security, Translator $translator, EntityResultHelper $entityResultHelper, RouterInterface $router, FormFactoryInterface $formFactory, AppVersion $appVersion, RequestStack $requestStack, ManagerRegistry $doctrine, ModelFactory $modelFactory, EventDispatcherInterface $dispatcher, CoreParametersHelper $coreParametersHelper)
|
||||
{
|
||||
$formSubmissionModel = $modelFactory->getModel('form.submission');
|
||||
\assert($formSubmissionModel instanceof SubmissionModel);
|
||||
|
||||
$this->model = $formSubmissionModel;
|
||||
$this->entityClass = Submission::class;
|
||||
$this->entityNameOne = 'submission';
|
||||
$this->entityNameMulti = 'submissions';
|
||||
$this->permissionBase = 'form:forms';
|
||||
$this->serializerGroups = ['submissionDetails', 'formList', 'ipAddressList', 'leadBasicList', 'pageList'];
|
||||
|
||||
parent::__construct($security, $translator, $entityResultHelper, $router, $formFactory, $appVersion, $requestStack, $doctrine, $modelFactory, $dispatcher, $coreParametersHelper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a list of entities as defined by the API URL.
|
||||
*
|
||||
* @param int $formId
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function getEntitiesAction(Request $request, UserHelper $userHelper, $formId = null)
|
||||
{
|
||||
$form = $this->getFormOrResponseWithError($formId);
|
||||
|
||||
if ($form instanceof Response) {
|
||||
return $form;
|
||||
}
|
||||
|
||||
$this->extraGetEntitiesArguments = array_merge(
|
||||
$this->extraGetEntitiesArguments,
|
||||
[
|
||||
'form' => $form,
|
||||
'flatten_results' => true,
|
||||
'return_entities' => true,
|
||||
]
|
||||
);
|
||||
|
||||
return parent::getEntitiesAction($request, $userHelper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a list of entities for specific form and contact.
|
||||
*
|
||||
* @param int $formId
|
||||
* @param int $contactId
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function getEntitiesForContactAction(Request $request, UserHelper $userHelper, $formId, $contactId)
|
||||
{
|
||||
$filter = [
|
||||
'filter' => [
|
||||
'where' => [
|
||||
[
|
||||
'col' => 's.lead_id',
|
||||
'expr' => 'eq',
|
||||
'val' => (int) $contactId,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$this->extraGetEntitiesArguments = array_merge($this->extraGetEntitiesArguments, $filter);
|
||||
|
||||
return $this->getEntitiesAction($request, $userHelper, $formId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a specific entity as defined by the API URL.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function getEntityAction(Request $request, $formId = null, $submissionId = null)
|
||||
{
|
||||
$form = $this->getFormOrResponseWithError($formId);
|
||||
|
||||
if ($form instanceof Response) {
|
||||
return $form;
|
||||
}
|
||||
|
||||
return parent::getEntityAction($request, $submissionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to fetch the form and returns Response if
|
||||
* - Form not found
|
||||
* - User doesn't have permission to view it.
|
||||
*
|
||||
* Returns Form on success
|
||||
*
|
||||
* @param int $formId
|
||||
*
|
||||
* @return Response|Form
|
||||
*/
|
||||
protected function getFormOrResponseWithError($formId)
|
||||
{
|
||||
$formModel = $this->getModel('form');
|
||||
$form = $formModel->getEntity($formId);
|
||||
|
||||
if (!$form) {
|
||||
return $this->notFound();
|
||||
}
|
||||
|
||||
if (!$this->checkEntityAccess($form)) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,443 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\FormBundle\Controller;
|
||||
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use Mautic\CoreBundle\Controller\FormController as CommonFormController;
|
||||
use Mautic\CoreBundle\Factory\ModelFactory;
|
||||
use Mautic\CoreBundle\Helper\CoreParametersHelper;
|
||||
use Mautic\CoreBundle\Helper\UserHelper;
|
||||
use Mautic\CoreBundle\Security\Permissions\CorePermissions;
|
||||
use Mautic\CoreBundle\Service\FlashBag;
|
||||
use Mautic\CoreBundle\Translation\Translator;
|
||||
use Mautic\FormBundle\Collector\AlreadyMappedFieldCollectorInterface;
|
||||
use Mautic\FormBundle\Collector\MappedObjectCollectorInterface;
|
||||
use Mautic\FormBundle\Entity\Field;
|
||||
use Mautic\FormBundle\Event\FormBuilderEvent;
|
||||
use Mautic\FormBundle\FormEvents;
|
||||
use Mautic\FormBundle\Helper\FormFieldHelper;
|
||||
use Mautic\FormBundle\Model\FieldModel;
|
||||
use Mautic\FormBundle\Model\FormModel;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Twig\Environment;
|
||||
|
||||
class FieldController extends CommonFormController
|
||||
{
|
||||
public function __construct(
|
||||
private FormModel $formModel,
|
||||
private FieldModel $formFieldModel,
|
||||
FormFieldHelper $fieldHelper,
|
||||
FormFactoryInterface $formFactory,
|
||||
private MappedObjectCollectorInterface $mappedObjectCollector,
|
||||
private AlreadyMappedFieldCollectorInterface $alreadyMappedFieldCollector,
|
||||
ManagerRegistry $doctrine,
|
||||
ModelFactory $modelFactory,
|
||||
UserHelper $userHelper,
|
||||
CoreParametersHelper $coreParametersHelper,
|
||||
EventDispatcherInterface $dispatcher,
|
||||
Translator $translator,
|
||||
FlashBag $flashBag,
|
||||
RequestStack $requestStack,
|
||||
CorePermissions $security,
|
||||
) {
|
||||
$this->fieldHelper = $fieldHelper;
|
||||
$this->formFactory = $formFactory;
|
||||
|
||||
parent::__construct($formFactory, $fieldHelper, $doctrine, $modelFactory, $userHelper, $coreParametersHelper, $dispatcher, $translator, $flashBag, $requestStack, $security);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates new form and processes post data.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function newAction(Request $request, Environment $twig)
|
||||
{
|
||||
$success = 0;
|
||||
$valid = $cancelled = false;
|
||||
$method = $request->getMethod();
|
||||
$session = $request->getSession();
|
||||
|
||||
if ('POST' == $method) {
|
||||
$formField = $request->request->all()['formfield'] ?? [];
|
||||
$fieldType = $formField['type'];
|
||||
$formId = $formField['formId'];
|
||||
} else {
|
||||
$fieldType = $request->query->get('type');
|
||||
$formId = $request->query->get('formId');
|
||||
$formField = [
|
||||
'type' => $fieldType,
|
||||
'formId' => $formId,
|
||||
'parent' => $request->query->get('parent'),
|
||||
];
|
||||
}
|
||||
|
||||
$customComponents = $this->formModel->getCustomComponents();
|
||||
$customParams = $customComponents['fields'][$fieldType] ?? false;
|
||||
// ajax only for form fields
|
||||
if (!$fieldType
|
||||
|| !$request->isXmlHttpRequest()
|
||||
|| !$this->security->isGranted(['form:forms:editown', 'form:forms:editother', 'form:forms:create'], 'MATCH_ONE')
|
||||
) {
|
||||
return $this->modalAccessDenied();
|
||||
}
|
||||
|
||||
// Generate the form
|
||||
$form = $this->getFieldForm($formId, $formField);
|
||||
|
||||
if (!empty($customParams)) {
|
||||
$formField['isCustom'] = true;
|
||||
$formField['customParameters'] = $customParams;
|
||||
}
|
||||
|
||||
// Check for a submitted form and process it
|
||||
if ('POST' == $method) {
|
||||
if (!$cancelled = $this->isFormCancelled($form)) {
|
||||
if ($valid = $this->isFormValid($form)) {
|
||||
$success = 1;
|
||||
|
||||
// form is valid so process the data
|
||||
$keyId = 'new'.hash('sha1', uniqid(mt_rand()));
|
||||
|
||||
// save the properties to session
|
||||
$fields = $session->get('mautic.form.'.$formId.'.fields.modified', []);
|
||||
$formData = $form->getData();
|
||||
$formField = array_merge($formField, $formData);
|
||||
$formField['id'] = $keyId;
|
||||
|
||||
// Get aliases in order to generate a new one for the new field
|
||||
$aliases = [];
|
||||
foreach ($fields as $f) {
|
||||
$aliases[] = $f['alias'];
|
||||
}
|
||||
|
||||
// Generate or ensure a unique alias
|
||||
$alias = empty($formField['alias']) ? $formField['label'] : $formField['alias'];
|
||||
$formFieldModel = $this->getModel('form.field');
|
||||
\assert($formFieldModel instanceof FieldModel);
|
||||
$formField['alias'] = $formFieldModel->generateAlias($alias, $aliases);
|
||||
|
||||
// Force required for captcha if not a honeypot
|
||||
if ('captcha' == $formField['type']) {
|
||||
$formField['isRequired'] = !empty($formField['properties']['captcha']);
|
||||
}
|
||||
|
||||
// Add it to the next to last assuming the last is the submit button
|
||||
if (count($fields)) {
|
||||
$lastField = end($fields);
|
||||
$lastKey = key($fields);
|
||||
array_pop($fields);
|
||||
|
||||
$fields[$keyId] = $formField;
|
||||
$fields[$lastKey] = $lastField;
|
||||
} else {
|
||||
$fields[$keyId] = $formField;
|
||||
}
|
||||
|
||||
$session->set('mautic.form.'.$formId.'.fields.modified', $fields);
|
||||
|
||||
// Keep track of used lead fields
|
||||
if (!empty($formField['mappedObject']) && !empty($formField['mappedField']) && empty($formData['parent'])) {
|
||||
$this->alreadyMappedFieldCollector->addField($formId, $formField['mappedObject'], $formField['mappedField']);
|
||||
}
|
||||
} else {
|
||||
$success = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$viewParams = ['type' => $fieldType];
|
||||
if ($cancelled || $valid) {
|
||||
$closeModal = true;
|
||||
} else {
|
||||
$closeModal = false;
|
||||
$viewParams['tmpl'] = 'field';
|
||||
$viewParams['form'] = (isset($customParams['formTheme'])) ? $this->setFormTheme($form, $twig, $customParams['formTheme']) : $form->createView();
|
||||
$viewParams['fieldHeader'] = (!empty($customParams)) ? $this->translator->trans($customParams['label']) : $this->translator->transConditional('mautic.core.type.'.$fieldType, 'mautic.form.field.type.'.$fieldType);
|
||||
}
|
||||
|
||||
$passthroughVars = [
|
||||
'mauticContent' => 'formField',
|
||||
'success' => $success,
|
||||
'route' => false,
|
||||
];
|
||||
|
||||
if (!empty($keyId)) {
|
||||
$entity = new Field();
|
||||
$blank = $entity->convertToArray();
|
||||
$formField = array_merge($blank, $formField);
|
||||
$formEntity = $this->formModel->getEntity($formId);
|
||||
|
||||
$passthroughVars['parent'] = $formField['parent'];
|
||||
$passthroughVars['fieldId'] = $keyId;
|
||||
$template = (!empty($customParams)) ? $customParams['template'] : '@MauticForm/Field/'.$fieldType.'.html.twig';
|
||||
$leadFieldModel = $this->getModel('lead.field');
|
||||
\assert($leadFieldModel instanceof \Mautic\LeadBundle\Model\FieldModel);
|
||||
$passthroughVars['fieldHtml'] = $this->renderView(
|
||||
'@MauticForm/Builder/_field_wrapper.html.twig',
|
||||
[
|
||||
'isConditional' => !empty($formField['parent']),
|
||||
'template' => $template,
|
||||
'inForm' => true,
|
||||
'field' => $formField,
|
||||
'id' => $keyId,
|
||||
'formId' => $formId,
|
||||
'formName' => null === $formEntity ? 'newform' : $formEntity->generateFormName(),
|
||||
'mappedFields' => $this->mappedObjectCollector->buildCollection((string) $formField['mappedObject']),
|
||||
'inBuilder' => true,
|
||||
'fields' => $this->fieldHelper->getChoiceList($customComponents['fields']),
|
||||
'viewOnlyFields' => $customComponents['viewOnlyFields'],
|
||||
'formFields' => $fields,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
if ($closeModal) {
|
||||
// just close the modal
|
||||
$passthroughVars['closeModal'] = 1;
|
||||
|
||||
return new JsonResponse($passthroughVars);
|
||||
}
|
||||
|
||||
return $this->ajaxAction($request, [
|
||||
'contentTemplate' => '@MauticForm/Builder/'.$viewParams['tmpl'].'.html.twig',
|
||||
'viewParameters' => $viewParams,
|
||||
'passthroughVars' => $passthroughVars,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates edit form and processes post data.
|
||||
*
|
||||
* @param int $objectId
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function editAction(Request $request, Environment $twig, $objectId)
|
||||
{
|
||||
$session = $request->getSession();
|
||||
$method = $request->getMethod();
|
||||
$formfield = $request->request->all()['formfield'] ?? [];
|
||||
$formId = 'POST' === $method ? ($formfield['formId'] ?? '') : $request->query->get('formId');
|
||||
$fields = $session->get('mautic.form.'.$formId.'.fields.modified', []);
|
||||
$success = 0;
|
||||
$valid = $cancelled = false;
|
||||
$formField = array_key_exists($objectId, $fields) ? $fields[$objectId] : [];
|
||||
|
||||
if ($formField) {
|
||||
$fieldType = $formField['type'];
|
||||
|
||||
// ajax only for form fields
|
||||
if (!$fieldType
|
||||
|| !$request->isXmlHttpRequest()
|
||||
|| !$this->security->isGranted(['form:forms:editown', 'form:forms:editother', 'form:forms:create'], 'MATCH_ONE')
|
||||
) {
|
||||
return $this->modalAccessDenied();
|
||||
}
|
||||
|
||||
// Generate the form
|
||||
$form = $this->getFieldForm($formId, $formField);
|
||||
|
||||
// Check for a submitted form and process it
|
||||
if ('POST' == $method) {
|
||||
if (!$cancelled = $this->isFormCancelled($form)) {
|
||||
if ($valid = $this->isFormValid($form)) {
|
||||
$success = 1;
|
||||
|
||||
// form is valid so process the data
|
||||
|
||||
// save the properties to session
|
||||
$session = $request->getSession();
|
||||
$fields = $session->get('mautic.form.'.$formId.'.fields.modified');
|
||||
$formData = $form->getData();
|
||||
|
||||
// overwrite with updated data
|
||||
$formField = array_merge($fields[$objectId], $formData);
|
||||
|
||||
if (str_contains((string) $objectId, 'new')) {
|
||||
// Get aliases in order to generate update for this one
|
||||
$aliases = [];
|
||||
foreach ($fields as $k => $f) {
|
||||
if ($k != $objectId) {
|
||||
$aliases[] = $f['alias'];
|
||||
}
|
||||
}
|
||||
$formField['alias'] = $this->formFieldModel->generateAlias(
|
||||
$formField['alias'] ?? $formField['label'] ?? '',
|
||||
$aliases
|
||||
);
|
||||
}
|
||||
|
||||
// Force required for captcha if not a honeypot
|
||||
if ('captcha' == $formField['type']) {
|
||||
$formField['isRequired'] = !empty($formField['properties']['captcha']);
|
||||
}
|
||||
|
||||
$fields[$objectId] = $formField;
|
||||
$session->set('mautic.form.'.$formId.'.fields.modified', $fields);
|
||||
|
||||
// Keep track of used lead fields
|
||||
if (!empty($formField['mappedObject']) && !empty($formField['mappedField']) && empty($formData['parent'])) {
|
||||
$this->alreadyMappedFieldCollector->addField($formId, $formField['mappedObject'], $formField['mappedField']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$viewParams = ['type' => $fieldType];
|
||||
$customComponents = $this->formModel->getCustomComponents();
|
||||
$customParams = $customComponents['fields'][$fieldType] ?? false;
|
||||
|
||||
if ($cancelled || $valid) {
|
||||
$closeModal = true;
|
||||
} else {
|
||||
$closeModal = false;
|
||||
$viewParams['tmpl'] = 'field';
|
||||
$viewParams['form'] = (isset($customParams['formTheme'])) ? $this->setFormTheme(
|
||||
$form,
|
||||
$twig,
|
||||
$customParams['formTheme']
|
||||
) : $form->createView();
|
||||
$viewParams['fieldHeader'] = (!empty($customParams))
|
||||
? $this->translator->trans($customParams['label'])
|
||||
: $this->translator->transConditional('mautic.core.type.'.$fieldType, 'mautic.form.field.type.'.$fieldType);
|
||||
}
|
||||
|
||||
$passthroughVars = [
|
||||
'mauticContent' => 'formField',
|
||||
'success' => $success,
|
||||
'route' => false,
|
||||
];
|
||||
|
||||
$passthroughVars['fieldId'] = $objectId;
|
||||
$template = (!empty($customParams)) ? $customParams['template'] : '@MauticForm/Field/'.$fieldType.'.html.twig';
|
||||
|
||||
// prevent undefined errors
|
||||
$entity = new Field();
|
||||
$blank = $entity->convertToArray();
|
||||
$formField = array_merge($blank, $formField);
|
||||
|
||||
$leadFieldModel = $this->getModel('lead.field');
|
||||
\assert($leadFieldModel instanceof \Mautic\LeadBundle\Model\FieldModel);
|
||||
$passthroughVars['fieldHtml'] = $this->renderView(
|
||||
'@MauticForm/Builder/_field_wrapper.html.twig',
|
||||
[
|
||||
'isConditional' => !empty($formField['parent']),
|
||||
'template' => $template,
|
||||
'inForm' => true,
|
||||
'field' => $formField,
|
||||
'id' => $objectId,
|
||||
'formId' => $formId,
|
||||
'mappedFields' => $this->mappedObjectCollector->buildCollection((string) $formField['mappedObject']),
|
||||
'inBuilder' => true,
|
||||
'fields' => $this->fieldHelper->getChoiceList($customComponents['fields']),
|
||||
'formFields' => $fields,
|
||||
'viewOnlyFields' => $customComponents['viewOnlyFields'],
|
||||
]
|
||||
);
|
||||
|
||||
if ($closeModal) {
|
||||
// just close the modal
|
||||
$passthroughVars['closeModal'] = 1;
|
||||
|
||||
return new JsonResponse($passthroughVars);
|
||||
}
|
||||
|
||||
return $this->ajaxAction(
|
||||
$request,
|
||||
[
|
||||
'contentTemplate' => '@MauticForm/Builder/'.$viewParams['tmpl'].'.html.twig',
|
||||
'viewParameters' => $viewParams,
|
||||
'passthroughVars' => $passthroughVars,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
return new JsonResponse(['success' => 0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the entity.
|
||||
*
|
||||
* @param int $objectId
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function deleteAction(Request $request, $objectId)
|
||||
{
|
||||
$session = $request->getSession();
|
||||
$formId = $request->query->get('formId');
|
||||
$fields = $session->get('mautic.form.'.$formId.'.fields.modified', []);
|
||||
$delete = $session->get('mautic.form.'.$formId.'.fields.deleted', []);
|
||||
|
||||
// ajax only for form fields
|
||||
if (!$request->isXmlHttpRequest()
|
||||
|| !$this->security->isGranted(['form:forms:editown', 'form:forms:editother', 'form:forms:create'], 'MATCH_ONE')
|
||||
) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
$formField = (array_key_exists($objectId, $fields)) ? $fields[$objectId] : null;
|
||||
|
||||
if ('POST' === $request->getMethod() && null !== $formField) {
|
||||
if ($formField['mappedObject'] && $formField['mappedField']) {
|
||||
// Allow to select the lead field from the delete field again
|
||||
$this->alreadyMappedFieldCollector->removeField($formId, $formField['mappedObject'], $formField['mappedField']);
|
||||
}
|
||||
|
||||
// add the field to the delete list
|
||||
if (!in_array($objectId, $delete)) {
|
||||
$delete[] = $objectId;
|
||||
$session->set('mautic.form.'.$formId.'.fields.deleted', $delete);
|
||||
}
|
||||
|
||||
$dataArray = [
|
||||
'mauticContent' => 'formField',
|
||||
'success' => 1,
|
||||
'route' => false,
|
||||
];
|
||||
} else {
|
||||
$dataArray = ['success' => 0];
|
||||
}
|
||||
|
||||
return new JsonResponse($dataArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $formId
|
||||
* @param mixed[] $formField
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private function getFieldForm($formId, array $formField)
|
||||
{
|
||||
// fire the form builder event
|
||||
$formModel = $this->getModel('form.form');
|
||||
\assert($formModel instanceof FormModel);
|
||||
$customComponents = $this->formModel->getCustomComponents();
|
||||
$customParams = $customComponents['fields'][$formField['type']] ?? false;
|
||||
|
||||
$formFieldModel = $this->getModel('form.field');
|
||||
\assert($formFieldModel instanceof FieldModel);
|
||||
$form = $formFieldModel->createForm(
|
||||
$formField,
|
||||
$this->formFactory,
|
||||
(!empty($formField['id'])) ?
|
||||
$this->generateUrl('mautic_formfield_action', ['objectAction' => 'edit', 'objectId' => $formField['id']])
|
||||
: $this->generateUrl('mautic_formfield_action', ['objectAction' => 'new']),
|
||||
['customParameters' => $customParams]
|
||||
);
|
||||
$form->get('formId')->setData($formId);
|
||||
|
||||
$event = new FormBuilderEvent($this->translator);
|
||||
$this->dispatcher->dispatch($event, FormEvents::FORM_ON_BUILD);
|
||||
$event->addValidatorsToBuilder($form);
|
||||
|
||||
return $form;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,454 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\FormBundle\Controller;
|
||||
|
||||
use Mautic\CoreBundle\Controller\FormController as CommonFormController;
|
||||
use Mautic\CoreBundle\Helper\InputHelper;
|
||||
use Mautic\CoreBundle\Helper\ThemeHelper;
|
||||
use Mautic\CoreBundle\Twig\Helper\AnalyticsHelper;
|
||||
use Mautic\CoreBundle\Twig\Helper\AssetsHelper;
|
||||
use Mautic\CoreBundle\Twig\Helper\DateHelper;
|
||||
use Mautic\FormBundle\Event\SubmissionEvent;
|
||||
use Mautic\FormBundle\Model\FieldModel;
|
||||
use Mautic\FormBundle\Model\FormModel;
|
||||
use Mautic\FormBundle\Model\SubmissionModel;
|
||||
use Mautic\LeadBundle\Helper\TokenHelper;
|
||||
use Mautic\LeadBundle\Model\CompanyModel;
|
||||
use Mautic\PageBundle\Helper\TokenHelper as PageTokenHelper;
|
||||
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, PageTokenHelper $pageTokenHelper)
|
||||
{
|
||||
if ('POST' !== $request->getMethod()) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
$isAjax = $request->query->get('ajax');
|
||||
$form = null;
|
||||
$post = $request->request->all()['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, $pageTokenHelper);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
switch ($postAction) {
|
||||
case 'redirect':
|
||||
$data['redirect'] = $postActionProperty;
|
||||
break;
|
||||
case 'hideform':
|
||||
$data['hideform'] = true;
|
||||
// no break
|
||||
default:
|
||||
if (!empty($postActionProperty)) {
|
||||
$data['successMessage'] = [$postActionProperty];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
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, AnalyticsHelper $analyticsHelper, AssetsHelper $assetsHelper, ThemeHelper $themeHelper): Response
|
||||
{
|
||||
$session = $request->getSession();
|
||||
$message = $session->get('mautic.emailbundle.message', []);
|
||||
|
||||
$msg = (!empty($message['message'])) ? $message['message'] : '';
|
||||
$msgType = (!empty($message['type'])) ? $message['type'] : 'notice';
|
||||
|
||||
$analytics = $analyticsHelper->getCode();
|
||||
|
||||
if (!empty($analytics)) {
|
||||
$assetsHelper->addCustomDeclaration($analytics);
|
||||
}
|
||||
|
||||
$logicalName = $themeHelper->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.
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \Mautic\CoreBundle\Exception\FileNotFoundException
|
||||
*/
|
||||
public function previewAction(Request $request, AnalyticsHelper $analyticsHelper, AssetsHelper $assetsHelper, ThemeHelper $themeHelper, int $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 = $themeHelper->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 = $themeHelper->checkForTwigTemplate('@themes/'.$template.'/html/form.html.twig');
|
||||
$analytics = $analyticsHelper->getCode();
|
||||
|
||||
foreach ($customStylesheets as $css) {
|
||||
$assetsHelper->addStylesheet($css);
|
||||
}
|
||||
|
||||
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, PageTokenHelper $pageTokenHelper): string|array
|
||||
{
|
||||
if (count($this->tokens)) {
|
||||
return $this->tokens;
|
||||
}
|
||||
|
||||
if ($lead = $submissionEvent->getLead()) {
|
||||
$this->tokens = array_merge(
|
||||
$submissionEvent->getTokens(),
|
||||
TokenHelper::findLeadTokens(
|
||||
$string,
|
||||
$lead->getProfileFields()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$this->tokens = array_merge(
|
||||
$this->tokens,
|
||||
$pageTokenHelper->findPageTokens($string)
|
||||
);
|
||||
|
||||
return str_replace(array_keys($this->tokens), array_values($this->tokens), $string);
|
||||
}
|
||||
|
||||
public function lookupCompanyAction(Request $request, FieldModel $fieldModel, CompanyModel $companyModel): JsonResponse
|
||||
{
|
||||
$parameters = json_decode($request->getContent(), true);
|
||||
$search = InputHelper::clean($parameters['search'] ?? '');
|
||||
$formId = (int) ($parameters['formId'] ?? 0);
|
||||
|
||||
// Intentionally vague message as the JS takes care of this.
|
||||
// Make it hard to abuse this public endpoint.
|
||||
$vagueErrorMessage = ['error' => 'Invalid request param'];
|
||||
|
||||
if (mb_strlen($search) < 3 || !$formId) {
|
||||
return new JsonResponse($vagueErrorMessage, JsonResponse::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
if (!$fieldModel->getRepository()->fieldExistsByFormAndType($formId, 'companyLookup')) {
|
||||
return new JsonResponse($vagueErrorMessage, JsonResponse::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
return new JsonResponse($companyModel->getRepository()->getCompanyLookupData($search));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,557 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\FormBundle\Controller;
|
||||
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use Mautic\CoreBundle\Controller\FormController as CommonFormController;
|
||||
use Mautic\CoreBundle\Factory\ModelFactory;
|
||||
use Mautic\CoreBundle\Factory\PageHelperFactoryInterface;
|
||||
use Mautic\CoreBundle\Helper\CoreParametersHelper;
|
||||
use Mautic\CoreBundle\Helper\UserHelper;
|
||||
use Mautic\CoreBundle\Security\Permissions\CorePermissions;
|
||||
use Mautic\CoreBundle\Service\FlashBag;
|
||||
use Mautic\CoreBundle\Translation\Translator;
|
||||
use Mautic\FormBundle\Helper\FormFieldHelper;
|
||||
use Mautic\FormBundle\Helper\FormUploader;
|
||||
use Mautic\FormBundle\Model\FieldModel;
|
||||
use Mautic\FormBundle\Model\FormModel;
|
||||
use Mautic\FormBundle\Model\SubmissionModel;
|
||||
use Mautic\FormBundle\Model\SubmissionResultLoader;
|
||||
use Mautic\LeadBundle\Form\Type\BatchType;
|
||||
use Mautic\LeadBundle\Model\ListModel;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
|
||||
class ResultController extends CommonFormController
|
||||
{
|
||||
public function __construct(FormFactoryInterface $formFactory, FormFieldHelper $fieldHelper, ManagerRegistry $doctrine, ModelFactory $modelFactory, UserHelper $userHelper, CoreParametersHelper $coreParametersHelper, EventDispatcherInterface $dispatcher, Translator $translator, FlashBag $flashBag, RequestStack $requestStack, CorePermissions $security)
|
||||
{
|
||||
$this->setStandardParameters(
|
||||
'form.submission', // model name
|
||||
'form:forms', // permission base
|
||||
'mautic_form', // route base
|
||||
'mautic.formresult', // session base
|
||||
'mautic.form.result', // lang string base
|
||||
'@MauticForm/Result', // template base
|
||||
'mautic_form', // activeLink
|
||||
'formresult' // mauticContent
|
||||
);
|
||||
|
||||
parent::__construct($formFactory, $fieldHelper, $doctrine, $modelFactory, $userHelper, $coreParametersHelper, $dispatcher, $translator, $flashBag, $requestStack, $security);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse|Response
|
||||
*/
|
||||
public function indexAction(Request $request, PageHelperFactoryInterface $pageHelperFacotry, int $objectId, int $page = 1)
|
||||
{
|
||||
/** @var FormModel $formModel */
|
||||
$formModel = $this->getModel('form.form');
|
||||
$form = $formModel->getEntity($objectId);
|
||||
$session = $request->getSession();
|
||||
$formPage = $session->get('mautic.form.page', 1);
|
||||
$returnUrl = $this->generateUrl('mautic_form_index', ['page' => $formPage]);
|
||||
$viewOnlyFields = $formModel->getCustomComponents()['viewOnlyFields'];
|
||||
|
||||
if (null === $form) {
|
||||
// redirect back to form list
|
||||
return $this->postActionRedirect(
|
||||
[
|
||||
'returnUrl' => $returnUrl,
|
||||
'viewParameters' => ['page' => $formPage],
|
||||
'contentTemplate' => 'Mautic\FormBundle\Controller\FormController::indexAction',
|
||||
'passthroughVars' => [
|
||||
'activeLink' => 'mautic_form_index',
|
||||
'mauticContent' => 'form',
|
||||
],
|
||||
'flashes' => [
|
||||
[
|
||||
'type' => 'error',
|
||||
'msg' => 'mautic.form.error.notfound',
|
||||
'msgVars' => ['%id%' => $objectId],
|
||||
],
|
||||
],
|
||||
]
|
||||
);
|
||||
} elseif (!$this->security->hasEntityAccess(
|
||||
'form:forms:viewown',
|
||||
'form:forms:viewother',
|
||||
$form->getCreatedBy()
|
||||
)
|
||||
) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
if ('POST' === $request->getMethod()) {
|
||||
$this->setListFilters($request->query->get('name'));
|
||||
}
|
||||
|
||||
$pageHelper = $pageHelperFacotry->make('mautic.formresult.'.$objectId, $page);
|
||||
|
||||
// set limits
|
||||
$limit = $pageHelper->getLimit();
|
||||
$start = $pageHelper->getStart();
|
||||
|
||||
// Set order direction to desc if not set
|
||||
if (!$session->get('mautic.formresult.'.$objectId.'.orderbydir', null)) {
|
||||
$session->set('mautic.formresult.'.$objectId.'.orderbydir', 'DESC');
|
||||
}
|
||||
|
||||
$orderBy = $session->get('mautic.formresult.'.$objectId.'.orderby', 's.date_submitted');
|
||||
$orderByDir = $session->get('mautic.formresult.'.$objectId.'.orderbydir', 'DESC');
|
||||
$filters = $session->get('mautic.formresult.'.$objectId.'.filters', []);
|
||||
$model = $this->getModel('form.submission');
|
||||
|
||||
if ($request->query->has('result')) {
|
||||
// Force ID
|
||||
$filters['s.id'] = ['column' => 's.id', 'expr' => 'like', 'value' => (int) $request->query->get('result'), 'strict' => false];
|
||||
$session->set("mautic.formresult.$objectId.filters", $filters);
|
||||
}
|
||||
|
||||
// get the results
|
||||
$entities = $model->getEntities(
|
||||
[
|
||||
'start' => $start,
|
||||
'limit' => $limit,
|
||||
'filter' => ['force' => $filters],
|
||||
'orderBy' => $orderBy,
|
||||
'orderByDir' => $orderByDir,
|
||||
'form' => $form,
|
||||
'withTotalCount' => true,
|
||||
'viewOnlyFields' => $viewOnlyFields,
|
||||
'simpleResults' => true,
|
||||
]
|
||||
);
|
||||
|
||||
$count = $entities['count'];
|
||||
$results = $entities['results'];
|
||||
unset($entities);
|
||||
|
||||
if ($count && $count < ($start + 1)) {
|
||||
// the number of entities are now less then the current page so redirect to the last page
|
||||
$lastPage = $pageHelper->countPage($count);
|
||||
$pageHelper->rememberPage($lastPage);
|
||||
$returnUrl = $this->generateUrl('mautic_form_results', ['objectId' => $objectId, 'page' => $lastPage]);
|
||||
|
||||
return $this->postActionRedirect(
|
||||
[
|
||||
'returnUrl' => $returnUrl,
|
||||
'viewParameters' => ['page' => $lastPage],
|
||||
'contentTemplate' => 'Mautic\FormBundle\Controller\ResultController::indexAction',
|
||||
'passthroughVars' => [
|
||||
'activeLink' => 'mautic_form_index',
|
||||
'mauticContent' => 'formresult',
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// set what page currently on so that we can return here if need be
|
||||
$pageHelper->rememberPage($page);
|
||||
|
||||
return $this->delegateView(
|
||||
[
|
||||
'viewParameters' => [
|
||||
'items' => $results,
|
||||
'filters' => $filters,
|
||||
'form' => $form,
|
||||
'viewOnlyFields' => $viewOnlyFields,
|
||||
'page' => $page,
|
||||
'totalCount' => $count,
|
||||
'limit' => $limit,
|
||||
'tmpl' => $request->isXmlHttpRequest() ? $request->get('tmpl', 'index') : 'index',
|
||||
'canDelete' => $this->security->hasEntityAccess(
|
||||
'form:forms:editown',
|
||||
'form:forms:editother',
|
||||
$form->getCreatedBy()
|
||||
),
|
||||
'enableExportPermission'=> $this->security->isAdmin() || $this->security->isGranted('form:export:enable', 'MATCH_ONE'),
|
||||
],
|
||||
'contentTemplate' => '@MauticForm/Result/list.html.twig',
|
||||
'passthroughVars' => [
|
||||
'activeLink' => 'mautic_form_index',
|
||||
'mauticContent' => 'formresult',
|
||||
'route' => $this->generateUrl(
|
||||
'mautic_form_results',
|
||||
[
|
||||
'objectId' => $objectId,
|
||||
'page' => $page,
|
||||
]
|
||||
),
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BinaryFileResponse
|
||||
*/
|
||||
public function downloadFileAction(int $submissionId, string $field, FormUploader $formUploader)
|
||||
{
|
||||
/** @var SubmissionResultLoader $submissionResultLoader */
|
||||
$submissionResultLoader = $this->getModel('form.submission_result_loader');
|
||||
$submission = $submissionResultLoader->getSubmissionWithResult($submissionId);
|
||||
|
||||
if (!$submission) {
|
||||
throw $this->createNotFoundException();
|
||||
}
|
||||
|
||||
$results = $submission->getResults();
|
||||
$fieldEntity = $submission->getFieldByAlias($field);
|
||||
|
||||
if (empty($results[$field]) || null === $fieldEntity) {
|
||||
throw $this->createNotFoundException();
|
||||
}
|
||||
|
||||
if (empty($fieldEntity->getProperties()['public']) && !$this->security->hasEntityAccess(
|
||||
'form:forms:viewown',
|
||||
'form:forms:viewother',
|
||||
$submission->getForm()->getCreatedBy())
|
||||
) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
$fileName = $results[$field];
|
||||
$file = $formUploader->getCompleteFilePath($fieldEntity, $fileName);
|
||||
|
||||
$fs = new Filesystem();
|
||||
if (!$fs->exists($file)) {
|
||||
throw $this->createNotFoundException();
|
||||
}
|
||||
|
||||
$response = new BinaryFileResponse($file);
|
||||
$response::trustXSendfileTypeHeader();
|
||||
$response->setContentDisposition(
|
||||
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
|
||||
$fileName
|
||||
);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function downloadFileByFileNameAction(string $fieldId, string $fileName, FieldModel $fieldModel, FormUploader $formUploader): Response
|
||||
{
|
||||
$fieldEntity = $fieldModel->getEntity($fieldId);
|
||||
|
||||
if (empty($fieldEntity->getProperties()['public']) && !$this->security->hasEntityAccess(
|
||||
'form:forms:viewown',
|
||||
'form:forms:viewother',
|
||||
$fieldEntity->getForm()->getCreatedBy())
|
||||
) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
$file = $formUploader->getCompleteFilePath($fieldEntity, $fileName);
|
||||
|
||||
$fs = new Filesystem();
|
||||
if (!$fs->exists($file)) {
|
||||
throw $this->createNotFoundException();
|
||||
}
|
||||
|
||||
$response = new BinaryFileResponse($file);
|
||||
$response::trustXSendfileTypeHeader();
|
||||
$response->setContentDisposition(
|
||||
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
|
||||
$fileName
|
||||
);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $objectId
|
||||
* @param string $format
|
||||
*
|
||||
* @return Response
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function exportAction(Request $request, $objectId, $format = 'csv')
|
||||
{
|
||||
$formModel = $this->getModel('form.form');
|
||||
$form = $formModel->getEntity($objectId);
|
||||
$session = $request->getSession();
|
||||
$formPage = $session->get('mautic.form.page', 1);
|
||||
$returnUrl = $this->generateUrl('mautic_form_index', ['page' => $formPage]);
|
||||
|
||||
if (!$this->security->isAdmin() && !$this->security->isGranted('form:export:enable', 'MATCH_ONE')) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
if (null === $form) {
|
||||
// redirect back to form list
|
||||
return $this->postActionRedirect(
|
||||
[
|
||||
'returnUrl' => $returnUrl,
|
||||
'viewParameters' => ['page' => $formPage],
|
||||
'contentTemplate' => 'Mautic\FormBundle\Controller\FormController::indexAction',
|
||||
'passthroughVars' => [
|
||||
'activeLink' => 'mautic_form_index',
|
||||
'mauticContent' => 'form',
|
||||
],
|
||||
'flashes' => [
|
||||
[
|
||||
'type' => 'error',
|
||||
'msg' => 'mautic.form.error.notfound',
|
||||
'msgVars' => ['%id%' => $objectId],
|
||||
],
|
||||
],
|
||||
]
|
||||
);
|
||||
} elseif (!$this->security->hasEntityAccess(
|
||||
'form:forms:viewown',
|
||||
'form:forms:viewother',
|
||||
$form->getCreatedBy()
|
||||
)
|
||||
) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
$orderBy = $session->get('mautic.formresult.'.$objectId.'.orderby', 's.date_submitted');
|
||||
$orderByDir = $session->get('mautic.formresult.'.$objectId.'.orderbydir', 'DESC');
|
||||
$filters = $session->get('mautic.formresult.'.$objectId.'.filters', []);
|
||||
|
||||
$args = [
|
||||
'limit' => false,
|
||||
'filter' => ['force' => $filters],
|
||||
'orderBy' => $orderBy,
|
||||
'orderByDir' => $orderByDir,
|
||||
'form' => $form,
|
||||
];
|
||||
|
||||
/** @var SubmissionModel $model */
|
||||
$model = $this->getModel('form.submission');
|
||||
|
||||
return $model->exportResults($format, $form, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a form result.
|
||||
*
|
||||
* @return array|Response
|
||||
*/
|
||||
public function deleteAction(Request $request)
|
||||
{
|
||||
$formId = $request->get('formId', 0);
|
||||
$objectId = $request->get('objectId', 0);
|
||||
$session = $request->getSession();
|
||||
$page = $session->get('mautic.formresult.'.$formId.'.page', 1);
|
||||
$flashes = [];
|
||||
|
||||
if (Request::METHOD_POST === $request->getMethod()) {
|
||||
$model = $this->getModel('form.submission');
|
||||
\assert($model instanceof SubmissionModel);
|
||||
|
||||
// Find the result
|
||||
$entity = $model->getEntity($objectId);
|
||||
|
||||
if (null === $entity) {
|
||||
$flashes[] = [
|
||||
'type' => 'error',
|
||||
'msg' => 'mautic.form.error.notfound',
|
||||
'msgVars' => ['%id%' => $objectId],
|
||||
];
|
||||
} elseif (!$this->security->hasEntityAccess('form:forms:editown', 'form:forms:editother', $entity->getCreatedBy())) {
|
||||
return $this->accessDenied();
|
||||
} else {
|
||||
$id = $entity->getId();
|
||||
$model->deleteEntity($entity);
|
||||
|
||||
$flashes[] = [
|
||||
'type' => 'notice',
|
||||
'msg' => 'mautic.core.notice.deleted',
|
||||
'msgVars' => [
|
||||
'%name%' => '#'.$id,
|
||||
],
|
||||
];
|
||||
}
|
||||
} // else don't do anything
|
||||
|
||||
$viewParameters = [
|
||||
'objectId' => $formId,
|
||||
'page' => $page,
|
||||
];
|
||||
|
||||
return $this->postActionRedirect(
|
||||
[
|
||||
'returnUrl' => $this->generateUrl('mautic_form_results', $viewParameters),
|
||||
'viewParameters' => $viewParameters,
|
||||
'contentTemplate' => 'Mautic\FormBundle\Controller\ResultController::indexAction',
|
||||
'passthroughVars' => [
|
||||
'mauticContent' => 'formresult',
|
||||
],
|
||||
'flashes' => $flashes,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\RedirectResponse
|
||||
*/
|
||||
public function batchDeleteAction(Request $request)
|
||||
{
|
||||
return $this->batchDeleteStandard($request);
|
||||
}
|
||||
|
||||
protected function getModelName(): string
|
||||
{
|
||||
return 'form.submission';
|
||||
}
|
||||
|
||||
protected function getIndexRoute(): string
|
||||
{
|
||||
return 'mautic_form_results';
|
||||
}
|
||||
|
||||
protected function getActionRoute(): string
|
||||
{
|
||||
return 'mautic_form_results_action';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the main form ID as the objectId.
|
||||
*/
|
||||
protected function generateUrl(string $route, array $parameters = [], int $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH): string
|
||||
{
|
||||
$formId = $this->getFormIdFromRequest($parameters);
|
||||
switch ($route) {
|
||||
case 'mautic_form_results_action':
|
||||
$parameters['formId'] = $formId;
|
||||
break;
|
||||
case 'mautic_form_results':
|
||||
$parameters['objectId'] = $formId;
|
||||
break;
|
||||
}
|
||||
|
||||
return parent::generateUrl($route, $parameters, $referenceType);
|
||||
}
|
||||
|
||||
public function getPostActionRedirectArguments(array $args, $action): array
|
||||
{
|
||||
switch ($action) {
|
||||
case 'batchDelete':
|
||||
$formId = $this->getFormIdFromRequest();
|
||||
$args['viewParameters']['objectId'] = $formId;
|
||||
break;
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $parameters
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getFormIdFromRequest($parameters = [])
|
||||
{
|
||||
$request = $this->getCurrentRequest();
|
||||
if ($request->attributes->has('formId')) {
|
||||
$formId = $request->attributes->get('formId');
|
||||
} elseif ($request->request->has('formId')) {
|
||||
$formId = $request->request->get('formId');
|
||||
} else {
|
||||
$objectId = $parameters['objectId'] ?? 0;
|
||||
$formId = $parameters['formId'] ?? $request->query->get('formId', $objectId);
|
||||
}
|
||||
|
||||
return $formId;
|
||||
}
|
||||
|
||||
public function addToSegmentAction(Request $request, int $objectId, FormModel $formModel, SubmissionModel $model, ListModel $segmentModel): Response
|
||||
{
|
||||
$form = $formModel->getEntity($objectId);
|
||||
$session = $request->getSession();
|
||||
$formPage = $session->get('mautic.form.page', 1);
|
||||
$returnUrl = $this->generateUrl('mautic_form_index', ['page' => $formPage]);
|
||||
|
||||
if (null === $form) {
|
||||
return $this->postActionRedirect([
|
||||
'returnUrl' => $returnUrl,
|
||||
'viewParameters' => ['page' => $formPage],
|
||||
'contentTemplate' => 'Mautic\\FormBundle\\Controller\\FormController::indexAction',
|
||||
'passthroughVars' => [
|
||||
'activeLink' => 'mautic_form_index',
|
||||
'mauticContent' => 'form',
|
||||
],
|
||||
'flashes' => [
|
||||
[
|
||||
'type' => 'error',
|
||||
'msg' => 'mautic.form.error.notfound',
|
||||
'msgVars' => ['%id%' => $objectId],
|
||||
],
|
||||
],
|
||||
]);
|
||||
} elseif (!$this->security->hasEntityAccess('form:forms:viewown', 'form:forms:viewother', $form->getCreatedBy())) {
|
||||
return $this->accessDenied();
|
||||
}
|
||||
|
||||
$orderBy = $session->get('mautic.formresult.'.$objectId.'.orderby', 's.date_submitted');
|
||||
$orderByDir = $session->get('mautic.formresult.'.$objectId.'.orderbydir', 'DESC');
|
||||
$filters = $session->get('mautic.formresult.'.$objectId.'.filters', []);
|
||||
|
||||
$viewOnlyFields = $formModel->getCustomComponents()['viewOnlyFields'];
|
||||
|
||||
$entities = $model->getEntities([
|
||||
'limit' => false,
|
||||
'filter' => ['force' => $filters],
|
||||
'orderBy' => $orderBy,
|
||||
'orderByDir' => $orderByDir,
|
||||
'form' => $form,
|
||||
'viewOnlyFields' => $viewOnlyFields,
|
||||
'simpleResults' => true,
|
||||
]);
|
||||
|
||||
if (isset($entities['results'])) {
|
||||
$entities = $entities['results'];
|
||||
}
|
||||
|
||||
$contactIds = [];
|
||||
foreach ($entities as $result) {
|
||||
if (!empty($result['leadId'])) {
|
||||
$contactIds[] = (int) $result['leadId'];
|
||||
}
|
||||
}
|
||||
|
||||
$contactIds = array_values(array_unique($contactIds));
|
||||
|
||||
$lists = $segmentModel->getUserLists();
|
||||
$items = [];
|
||||
foreach ($lists as $list) {
|
||||
$items[$list['name'].' ('.$list['id'].')'] = $list['id'];
|
||||
}
|
||||
|
||||
$route = $this->generateUrl('mautic_segment_batch_contact_set');
|
||||
|
||||
$formView = $this->createForm(
|
||||
BatchType::class,
|
||||
['ids' => json_encode($contactIds)],
|
||||
[
|
||||
'items' => $items,
|
||||
'action' => $route,
|
||||
'attr' => [
|
||||
'data-submit-callback' => 'formResultBatchSubmit',
|
||||
],
|
||||
]
|
||||
)->createView();
|
||||
|
||||
return $this->delegateView([
|
||||
'viewParameters' => [
|
||||
'form' => $formView,
|
||||
],
|
||||
'contentTemplate' => '@MauticLead/Batch/form.html.twig',
|
||||
'passthroughVars' => [
|
||||
'activeLink' => 'mautic_form_index',
|
||||
'mauticContent' => 'formresult',
|
||||
'route' => $route,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user