示例#1
0
 /**
  * {@inheritdoc}
  */
 public function buildForm(FormBuilderInterface $builder, array $options)
 {
     $builder->addEventSubscriber(new CleanFormSubscriber(['content' => 'html', 'customHtml' => 'html', 'redirectUrl' => 'url']));
     $builder->addEventSubscriber(new FormExitSubscriber('page.page', $options));
     $builder->add('title', 'text', ['label' => 'mautic.core.title', 'label_attr' => ['class' => 'control-label'], 'attr' => ['class' => 'form-control']]);
     $builder->add('customHtml', 'textarea', ['label' => 'mautic.page.form.customhtml', 'required' => false, 'attr' => ['class' => 'form-control editor editor-basic-fullpage editor-builder-tokens builder-html', 'data-token-callback' => 'page:getBuilderTokens', 'data-token-activator' => '{']]);
     $template = $options['data']->getTemplate();
     if (empty($template)) {
         $template = $this->defaultTheme;
     }
     $builder->add('template', 'theme_list', ['feature' => 'page', 'data' => $template, 'attr' => ['class' => 'form-control not-chosen hidden', 'tooltip' => 'mautic.page.form.template.help'], 'empty_value' => 'mautic.core.none', 'data' => $options['data']->getTemplate() ? $options['data']->getTemplate() : 'blank']);
     $builder->add('isPublished', 'yesno_button_group');
     $builder->add('publishUp', 'datetime', ['widget' => 'single_text', 'label' => 'mautic.core.form.publishup', 'label_attr' => ['class' => 'control-label'], 'attr' => ['class' => 'form-control', 'data-toggle' => 'datetime'], 'format' => 'yyyy-MM-dd HH:mm', 'required' => false]);
     $builder->add('publishDown', 'datetime', ['widget' => 'single_text', 'label' => 'mautic.core.form.publishdown', 'label_attr' => ['class' => 'control-label'], 'attr' => ['class' => 'form-control', 'data-toggle' => 'datetime'], 'format' => 'yyyy-MM-dd HH:mm', 'required' => false]);
     $builder->add('sessionId', 'hidden');
     //Custom field for redirect URL
     $this->model->getRepository()->setCurrentUser($this->user);
     $redirectUrlDataOptions = '';
     $pages = $this->model->getRepository()->getPageList('', 0, 0, $this->canViewOther, 'variant', [$options['data']->getId()]);
     foreach ($pages as $page) {
         $redirectUrlDataOptions .= "|{$page['alias']}";
     }
     $transformer = new IdToEntityModelTransformer($this->em, 'MauticPageBundle:Page');
     $builder->add($builder->create('variantParent', 'hidden')->addModelTransformer($transformer));
     $builder->add($builder->create('translationParent', 'page_list', ['label' => 'mautic.core.form.translation_parent', 'label_attr' => ['class' => 'control-label'], 'attr' => ['class' => 'form-control', 'tooltip' => 'mautic.core.form.translation_parent.help'], 'required' => false, 'multiple' => false, 'empty_value' => 'mautic.core.form.translation_parent.empty', 'top_level' => 'translation', 'ignore_ids' => [(int) $options['data']->getId()]])->addModelTransformer($transformer));
     $formModifier = function (FormInterface $form, $isVariant) {
         if ($isVariant) {
             $form->add('variantSettings', 'pagevariant', ['label' => false]);
         }
     };
     // Building the form
     $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use($formModifier) {
         $formModifier($event->getForm(), $event->getData()->getVariantParent());
     });
     // After submit
     $builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use($formModifier) {
         $data = $event->getData();
         $formModifier($event->getForm(), $data['variantParent']);
     });
     $builder->add('metaDescription', 'textarea', ['label' => 'mautic.page.form.metadescription', 'label_attr' => ['class' => 'control-label'], 'attr' => ['class' => 'form-control', 'maxlength' => 160], 'required' => false]);
     $builder->add('redirectType', 'redirect_list', ['feature' => 'page', 'attr' => ['class' => 'form-control', 'tooltip' => 'mautic.page.form.redirecttype.help'], 'empty_value' => 'mautic.page.form.redirecttype.none']);
     $builder->add('redirectUrl', 'url', ['required' => true, 'label' => 'mautic.page.form.redirecturl', 'label_attr' => ['class' => 'control-label'], 'attr' => ['class' => 'form-control', 'maxlength' => 200, 'tooltip' => 'mautic.page.form.redirecturl.help', 'data-toggle' => 'field-lookup', 'data-action' => 'page:fieldList', 'data-target' => 'redirectUrl', 'data-options' => $redirectUrlDataOptions]]);
     $builder->add('alias', 'text', ['label' => 'mautic.core.alias', 'label_attr' => ['class' => 'control-label'], 'attr' => ['class' => 'form-control', 'tooltip' => 'mautic.page.help.alias'], 'required' => false]);
     //add category
     $builder->add('category', 'category', ['bundle' => 'page']);
     $builder->add('language', 'locale', ['label' => 'mautic.core.language', 'label_attr' => ['class' => 'control-label'], 'attr' => ['class' => 'form-control', 'tooltip' => 'mautic.page.form.language.help'], 'required' => false, 'empty_data' => 'en']);
     $builder->add('buttons', 'form_buttons', ['pre_extra_buttons' => [['name' => 'builder', 'label' => 'mautic.core.builder', 'attr' => ['class' => 'btn btn-default btn-dnd btn-nospin btn-builder text-primary', 'icon' => 'fa fa-cube', 'onclick' => "Mautic.launchBuilder('page');"]]]]);
     if (!empty($options['action'])) {
         $builder->setAction($options['action']);
     }
 }
示例#2
0
 /**
  * Let the calendar to edit / create new entities.
  *
  * @param EventGeneratorEvent $event
  */
 public function onCalendarEventGenerate(EventGeneratorEvent $event)
 {
     $source = $event->getSource();
     if ($source != 'page') {
         return;
     }
     $entityId = $event->getEntityId();
     $entity = $this->pageModel->getEntity($entityId);
     $event->setModel($this->pageModel);
     $event->setEntity($entity);
     $event->setContentTemplate('MauticPageBundle:SubscribedEvents\\Calendar:modal.html.php');
     $event->setFormName('page_publish_dates');
     $event->setAccess($this->security->hasEntityAccess('page:pages:viewown', 'page:pages:viewother', $entity->getCreatedBy()));
 }
示例#3
0
 /**
  * Compile events for the lead timeline
  *
  * @param LeadTimelineEvent $event
  */
 public function onTimelineGenerate(LeadTimelineEvent $event)
 {
     // Set available event types
     $eventTypeKey = 'form.submitted';
     $eventTypeName = $this->translator->trans('mautic.form.event.submitted');
     $event->addEventType($eventTypeKey, $eventTypeName);
     if (!$event->isApplicable($eventTypeKey)) {
         return;
     }
     /** @var \Mautic\FormBundle\Entity\SubmissionRepository $submissionRepository */
     $submissionRepository = $this->em->getRepository('MauticFormBundle:Submission');
     $rows = $submissionRepository->getSubmissions($event->getQueryOptions());
     // Add total to counter
     $event->addToCounter($eventTypeKey, $rows);
     if (!$event->isEngagementCount()) {
         // Add the submissions to the event array
         foreach ($rows['results'] as $row) {
             // Convert to local from UTC
             $form = $this->formModel->getEntity($row['form_id']);
             $submission = $submissionRepository->getEntity($row['id']);
             $event->addEvent(['event' => $eventTypeKey, 'eventLabel' => ['label' => $form->getName(), 'href' => $this->router->generate('mautic_form_action', ['objectAction' => 'view', 'objectId' => $form->getId()])], 'eventType' => $eventTypeName, 'timestamp' => $row['dateSubmitted'], 'extra' => ['submission' => $submission, 'form' => $form, 'page' => $this->pageModel->getEntity($row['page_id'])], 'contentTemplate' => 'MauticFormBundle:SubscribedEvents\\Timeline:index.html.php', 'icon' => 'fa-pencil-square-o']);
         }
     }
 }
示例#4
0
 /**
  * Renders the HTML for the language bar for a given page.
  *
  * @param $page
  *
  * @return string
  */
 protected function renderLanguageBar($page)
 {
     static $langbar = '';
     if (empty($langbar)) {
         $parent = $page->getTranslationParent();
         $children = $page->getTranslationChildren();
         //check to see if this page is grouped with another
         if (empty($parent) && empty($children)) {
             return;
         }
         $related = [];
         //get a list of associated pages/languages
         if (!empty($parent)) {
             $children = $parent->getTranslationChildren();
         } else {
             $parent = $page;
             //parent is self
         }
         if (!empty($children)) {
             $lang = $parent->getLanguage();
             $trans = $this->translator->trans('mautic.page.lang.' . $lang);
             if ($trans == 'mautic.page.lang.' . $lang) {
                 $trans = $lang;
             }
             $related[$parent->getId()] = ['lang' => $trans, 'url' => $this->pageModel->generateUrl($parent, false) . '?ntrd=1'];
             foreach ($children as $c) {
                 $lang = $c->getLanguage();
                 $trans = $this->translator->trans('mautic.page.lang.' . $lang);
                 if ($trans == 'mautic.page.lang.' . $lang) {
                     $trans = $lang;
                 }
                 $related[$c->getId()] = ['lang' => $trans, 'url' => $this->pageModel->generateUrl($c, false) . '?ntrd=1'];
             }
         }
         //sort by language
         uasort($related, function ($a, $b) {
             return strnatcasecmp($a['lang'], $b['lang']);
         });
         if (empty($related)) {
             return;
         }
         $langbar = $this->templating->render('MauticPageBundle:SubscribedEvents\\PageToken:langbar.html.php', ['pages' => $related]);
     }
     return $langbar;
 }
示例#5
0
 /**
  * @param LeadMergeEvent $event
  */
 public function onLeadMerge(LeadMergeEvent $event)
 {
     $this->pageModel->getHitRepository()->updateLead($event->getLoser()->getId(), $event->getVictor()->getId());
     $this->pageVideoModel->getHitRepository()->updateLead($event->getLoser()->getId(), $event->getVictor()->getId());
 }
示例#6
0
 /**
  * @param      $post
  * @param      $server
  * @param Form $form
  *
  * @return bool|array
  */
 public function saveSubmission($post, $server, Form $form, Request $request = null, $returnEvent = false)
 {
     $leadFields = $this->leadFieldModel->getFieldListWithProperties(false);
     //everything matches up so let's save the results
     $submission = new Submission();
     $submission->setDateSubmitted(new \DateTime());
     $submission->setForm($form);
     //set the landing page the form was submitted from if applicable
     if (!empty($post['mauticpage'])) {
         $page = $this->pageModel->getEntity((int) $post['mauticpage']);
         if ($page != null) {
             $submission->setPage($page);
         }
     }
     $ipAddress = $this->ipLookupHelper->getIpAddress();
     $submission->setIpAddress($ipAddress);
     if (!empty($post['return'])) {
         $referer = $post['return'];
     } elseif (!empty($server['HTTP_REFERER'])) {
         $referer = $server['HTTP_REFERER'];
     } else {
         $referer = '';
     }
     //clean the referer by removing mauticError and mauticMessage
     $referer = InputHelper::url($referer, null, null, ['mauticError', 'mauticMessage']);
     $submission->setReferer($referer);
     // Create an event to be dispatched through the processes
     $submissionEvent = new SubmissionEvent($submission, $post, $server, $request);
     // Get a list of components to build custom fields from
     $components = $this->formModel->getCustomComponents();
     $fields = $form->getFields();
     $fieldArray = [];
     $results = [];
     $tokens = [];
     $leadFieldMatches = [];
     $validationErrors = [];
     /** @var Field $f */
     foreach ($fields as $f) {
         $id = $f->getId();
         $type = $f->getType();
         $alias = $f->getAlias();
         $value = isset($post[$alias]) ? $post[$alias] : '';
         $fieldArray[$id] = ['id' => $id, 'type' => $type, 'alias' => $alias];
         if ($type == 'captcha') {
             $captcha = $this->fieldHelper->validateFieldValue($type, $value, $f);
             if (!empty($captcha)) {
                 $props = $f->getProperties();
                 //check for a custom message
                 $validationErrors[$alias] = !empty($props['errorMessage']) ? $props['errorMessage'] : implode('<br />', $captcha);
             }
             continue;
         }
         if ($f->isRequired() && empty($value)) {
             //field is required, but hidden from form because of 'ShowWhenValueExists'
             if ($f->getShowWhenValueExists() === false && !isset($post[$alias])) {
                 continue;
             }
             //somehow the user got passed the JS validation
             $msg = $f->getValidationMessage();
             if (empty($msg)) {
                 $msg = $this->translator->trans('mautic.form.field.generic.validationfailed', ['%label%' => $f->getLabel()], 'validators');
             }
             $validationErrors[$alias] = $msg;
             continue;
         }
         if (in_array($type, $components['viewOnlyFields'])) {
             //don't save items that don't have a value associated with it
             continue;
         }
         //clean and validate the input
         if ($f->isCustom()) {
             if (!isset($components['fields'][$f->getType()])) {
                 continue;
             }
             $params = $components['fields'][$f->getType()];
             if (!empty($value)) {
                 if (isset($params['valueFilter'])) {
                     if (is_string($params['valueFilter']) && is_callable(['\\Mautic\\CoreBundle\\Helper\\InputHelper', $params['valueFilter']])) {
                         $value = InputHelper::_($value, $params['valueFilter']);
                     } elseif (is_callable($params['valueFilter'])) {
                         $value = call_user_func_array($params['valueFilter'], [$f, $value]);
                     } else {
                         $value = InputHelper::_($value, 'clean');
                     }
                 } else {
                     $value = InputHelper::_($value, 'clean');
                 }
             }
             // @deprecated - BC support; to be removed in 3.0 - be sure to remove support in FormBuilderEvent as well
             if (isset($params['valueConstraints']) && is_callable($params['valueConstraints'])) {
                 $customErrors = call_user_func_array($params['valueConstraints'], [$f, $value]);
                 if (!empty($customErrors)) {
                     $validationErrors[$alias] = is_array($customErrors) ? implode('<br />', $customErrors) : $customErrors;
                 }
             }
         } elseif (!empty($value)) {
             $filter = $this->fieldHelper->getFieldFilter($type);
             $value = InputHelper::_($value, $filter);
             $isValid = $this->validateFieldValue($f, $value);
             if (true !== $isValid) {
                 $validationErrors[$alias] = is_array($isValid) ? implode('<br />', $isValid) : $isValid;
             }
         }
         // Check for custom validators
         $isValid = $this->validateFieldValue($f, $value);
         if (true !== $isValid) {
             $validationErrors[$alias] = $isValid;
         }
         $leadField = $f->getLeadField();
         if (!empty($leadField)) {
             $leadValue = $value;
             if (is_array($leadValue)) {
                 // Multiselect lead fields store the values with bars
                 $delimeter = 'multiselect' === $leadFields[$leadField]['type'] ? '|' : ', ';
                 $leadValue = implode($delimeter, $leadValue);
             }
             $leadFieldMatches[$leadField] = $leadValue;
         }
         //convert array from checkbox groups and multiple selects
         if (is_array($value)) {
             $value = implode(', ', $value);
         }
         $tokens["{formfield={$alias}}"] = $value;
         //save the result
         if ($f->getSaveResult() !== false) {
             $results[$alias] = $value;
         }
     }
     // Set the results
     $submission->setResults($results);
     // Update the event
     $submissionEvent->setFields($fieldArray)->setTokens($tokens)->setResults($results)->setContactFieldMatches($leadFieldMatches);
     // @deprecated - BC support; to be removed in 3.0 - be sure to remove the validator option from addSubmitAction as well
     $this->validateActionCallbacks($submissionEvent, $validationErrors, $alias);
     //return errors if there any - this should be moved to right after foreach($fields) once validateActionCallbacks support is dropped
     if (!empty($validationErrors)) {
         return ['errors' => $validationErrors];
     }
     // Create/update lead
     if (!empty($leadFieldMatches)) {
         $lead = $this->createLeadFromSubmit($form, $leadFieldMatches, $leadFields);
         $submission->setLead($lead);
     }
     // Get updated lead if applicable with tracking ID
     if ($form->isInKioskMode()) {
         $lead = $this->leadModel->getCurrentLead();
     } else {
         list($lead, $trackingId, $generated) = $this->leadModel->getCurrentLead(true);
         //set tracking ID for stats purposes to determine unique hits
         $submission->setTrackingId($trackingId);
     }
     $submission->setLead($lead);
     // Save the submission
     $this->saveEntity($submission);
     // Now handle post submission actions
     try {
         $this->executeFormActions($submissionEvent);
     } catch (ValidationException $exception) {
         // The action invalidated the form for whatever reason
         $this->deleteEntity($submission);
         if ($validationErrors = $exception->getViolations()) {
             return ['errors' => $validationErrors];
         }
         return ['errors' => [$exception->getMessage()]];
     }
     if (!$form->isStandalone()) {
         // Find and add the lead to the associated campaigns
         $campaigns = $this->campaignModel->getCampaignsByForm($form);
         if (!empty($campaigns)) {
             foreach ($campaigns as $campaign) {
                 $this->campaignModel->addLead($campaign, $lead);
             }
         }
     }
     if ($this->dispatcher->hasListeners(FormEvents::FORM_ON_SUBMIT)) {
         // Reset action config from executeFormActions()
         $submissionEvent->setActionConfig(null, []);
         // Dispatch to on submit listeners
         $this->dispatcher->dispatch(FormEvents::FORM_ON_SUBMIT, $submissionEvent);
     }
     //get callback commands from the submit action
     if ($submissionEvent->hasPostSubmitCallbacks()) {
         return ['callback' => $submissionEvent];
     }
     // made it to the end so return the submission event to give the calling method access to tokens, results, etc
     // otherwise return false that no errors were encountered (to keep BC really)
     return $returnEvent ? ['submission' => $submissionEvent] : false;
 }
示例#7
0
 /**
  * @param MauticEvents\CommandListEvent $event
  */
 public function onBuildCommandList(MauticEvents\CommandListEvent $event)
 {
     if ($this->security->isGranted(['page:pages:viewown', 'page:pages:viewother'], 'MATCH_ONE')) {
         $event->addCommands('mautic.page.pages', $this->pageModel->getCommandList());
     }
 }
示例#8
0
 /**
  * Set a widget detail when needed.
  *
  * @param WidgetDetailEvent $event
  */
 public function onWidgetDetailGenerate(WidgetDetailEvent $event)
 {
     $this->checkPermissions($event);
     $canViewOthers = $event->hasPermission('page:pages:viewother');
     if ($event->getType() == 'page.hits.in.time') {
         $widget = $event->getWidget();
         $params = $widget->getParams();
         if (isset($params['flag'])) {
             $params['filter']['flag'] = $params['flag'];
         }
         if (!$event->isCached()) {
             $event->setTemplateData(['chartType' => 'line', 'chartHeight' => $widget->getHeight() - 80, 'chartData' => $this->pageModel->getHitsLineChartData($params['timeUnit'], $params['dateFrom'], $params['dateTo'], $params['dateFormat'], $params['filter'], $canViewOthers)]);
         }
         $event->setTemplate('MauticCoreBundle:Helper:chart.html.php');
         $event->stopPropagation();
     }
     if ($event->getType() == 'unique.vs.returning.leads') {
         if (!$event->isCached()) {
             $params = $event->getWidget()->getParams();
             $event->setTemplateData(['chartType' => 'pie', 'chartHeight' => $event->getWidget()->getHeight() - 80, 'chartData' => $this->pageModel->getNewVsReturningPieChartData($params['dateFrom'], $params['dateTo'], [], $canViewOthers)]);
         }
         $event->setTemplate('MauticCoreBundle:Helper:chart.html.php');
         $event->stopPropagation();
     }
     if ($event->getType() == 'dwell.times') {
         if (!$event->isCached()) {
             $params = $event->getWidget()->getParams();
             $event->setTemplateData(['chartType' => 'pie', 'chartHeight' => $event->getWidget()->getHeight() - 80, 'chartData' => $this->pageModel->getDwellTimesPieChartData($params['dateFrom'], $params['dateTo'], [], $canViewOthers)]);
         }
         $event->setTemplate('MauticCoreBundle:Helper:chart.html.php');
         $event->stopPropagation();
     }
     if ($event->getType() == 'popular.pages') {
         if (!$event->isCached()) {
             $params = $event->getWidget()->getParams();
             if (empty($params['limit'])) {
                 // Count the pages limit from the widget height
                 $limit = round(($event->getWidget()->getHeight() - 80) / 35 - 1);
             } else {
                 $limit = $params['limit'];
             }
             $pages = $this->pageModel->getPopularPages($limit, $params['dateFrom'], $params['dateTo'], [], $canViewOthers);
             $items = [];
             // Build table rows with links
             if ($pages) {
                 foreach ($pages as &$page) {
                     $pageUrl = $this->router->generate('mautic_page_action', ['objectAction' => 'view', 'objectId' => $page['id']]);
                     $row = [['value' => $page['title'], 'type' => 'link', 'link' => $pageUrl], ['value' => $page['hits']]];
                     $items[] = $row;
                 }
             }
             $event->setTemplateData(['headItems' => [$event->getTranslator()->trans('mautic.dashboard.label.title'), $event->getTranslator()->trans('mautic.dashboard.label.hits')], 'bodyItems' => $items, 'raw' => $pages]);
         }
         $event->setTemplate('MauticCoreBundle:Helper:table.html.php');
         $event->stopPropagation();
     }
     if ($event->getType() == 'created.pages') {
         if (!$event->isCached()) {
             $params = $event->getWidget()->getParams();
             if (empty($params['limit'])) {
                 // Count the pages limit from the widget height
                 $limit = round(($event->getWidget()->getHeight() - 80) / 35 - 1);
             } else {
                 $limit = $params['limit'];
             }
             $pages = $this->pageModel->getPageList($limit, $params['dateFrom'], $params['dateTo'], [], $canViewOthers);
             $items = [];
             // Build table rows with links
             if ($pages) {
                 foreach ($pages as &$page) {
                     $pageUrl = $this->router->generate('mautic_page_action', ['objectAction' => 'view', 'objectId' => $page['id']]);
                     $row = [['value' => $page['name'], 'type' => 'link', 'link' => $pageUrl]];
                     $items[] = $row;
                 }
             }
             $event->setTemplateData(['headItems' => [$event->getTranslator()->trans('mautic.dashboard.label.title')], 'bodyItems' => $items, 'raw' => $pages]);
         }
         $event->setTemplate('MauticCoreBundle:Helper:table.html.php');
         $event->stopPropagation();
     }
     if ($event->getType() == 'device.granularity') {
         $widget = $event->getWidget();
         $params = $widget->getParams();
         if (!$event->isCached()) {
             $event->setTemplateData(['chartType' => 'pie', 'chartHeight' => $widget->getHeight() - 80, 'chartData' => $this->pageModel->getDeviceGranularityData($params['dateFrom'], $params['dateTo'], [], $canViewOthers)]);
         }
         $event->setTemplate('MauticCoreBundle:Helper:chart.html.php');
         $event->stopPropagation();
     }
 }
示例#9
0
 /**
  * @param $post
  * @param $server
  * @param Form $form
  *
  * @return boolean|string false if no error was encountered; otherwise the error message
  */
 public function saveSubmission($post, $server, Form $form)
 {
     $fieldHelper = new FormFieldHelper($this->translator);
     //everything matches up so let's save the results
     $submission = new Submission();
     $submission->setDateSubmitted(new \DateTime());
     $submission->setForm($form);
     $ipAddress = $this->ipLookupHelper->getIpAddress();
     $submission->setIpAddress($ipAddress);
     if (!empty($post['return'])) {
         $referer = $post['return'];
     } elseif (!empty($server['HTTP_REFERER'])) {
         $referer = $server['HTTP_REFERER'];
     } else {
         $referer = '';
     }
     //clean the referer by removing mauticError and mauticMessage
     $referer = InputHelper::url($referer, null, null, array('mauticError', 'mauticMessage'));
     $submission->setReferer($referer);
     $fields = $form->getFields();
     $fieldArray = array();
     $results = array();
     $tokens = array();
     $leadFieldMatches = array();
     $validationErrors = array();
     foreach ($fields as $f) {
         $id = $f->getId();
         $type = $f->getType();
         $alias = $f->getAlias();
         $value = isset($post[$alias]) ? $post[$alias] : '';
         $fieldArray[$id] = array('id' => $id, 'type' => $type, 'alias' => $alias);
         if (in_array($type, array('button', 'freetext'))) {
             //don't save items that don't have a value associated with it
             continue;
         } elseif ($type == 'captcha') {
             $captcha = $fieldHelper->validateFieldValue($type, $value, $f);
             if (!empty($captcha)) {
                 $props = $f->getProperties();
                 //check for a custom message
                 $validationErrors[$alias] = !empty($props['errorMessage']) ? $props['errorMessage'] : implode('<br />', $captcha);
             }
             continue;
         }
         if ($f->isRequired() && empty($value)) {
             //somehow the user got passed the JS validation
             $msg = $f->getValidationMessage();
             if (empty($msg)) {
                 $msg = $this->translator->trans('mautic.form.field.generic.validationfailed', array('%label%' => $f->getLabel()), 'validators');
             }
             $validationErrors[$alias] = $msg;
             continue;
         }
         //clean and validate the input
         if ($f->isCustom()) {
             $params = $f->getCustomParameters();
             if (!empty($value)) {
                 if (isset($params['valueFilter'])) {
                     if (is_string($params['inputFilter'] && method_exists('\\Mautic\\CoreBundle\\Helper\\InputHelper', $params['valueFilter']))) {
                         $value = InputHelper::_($value, $params['valueFilter']);
                     } elseif (is_callable($params['valueFilter'])) {
                         $value = call_user_func_array($params['valueFilter'], array($f, $value));
                     } else {
                         $value = InputHelper::_($value, 'clean');
                     }
                 } else {
                     $value = InputHelper::_($value, 'clean');
                 }
             }
             if (isset($params['valueConstraints']) && is_callable($params['valueConstraints'])) {
                 $customErrors = call_user_func_array($params['valueConstraints'], array($f, $value));
                 if (!empty($customErrors)) {
                     $validationErrors[$alias] = is_array($customErrors) ? implode('<br />', $customErrors) : $customErrors;
                 }
             }
         } elseif (!empty($value)) {
             $filter = $fieldHelper->getFieldFilter($type);
             $value = InputHelper::_($value, $filter);
             $validation = $fieldHelper->validateFieldValue($type, $value);
             if (!empty($validation)) {
                 $validationErrors[$alias] = is_array($validation) ? implode('<br />', $validation) : $validation;
             }
         }
         //convert array from checkbox groups and multiple selects
         if (is_array($value)) {
             $value = implode(", ", $value);
         }
         $tokens["{formfield={$alias}}"] = $value;
         //save the result
         if ($f->getSaveResult() !== false) {
             $results[$alias] = $value;
         }
         $leadField = $f->getLeadField();
         if (!empty($leadField)) {
             $leadFieldMatches[$leadField] = $value;
         }
     }
     $submission->setResults($results);
     //execute submit actions
     $actions = $form->getActions();
     //get post submit actions to make sure it still exists
     $components = $this->formModel->getCustomComponents();
     $availableActions = $components['actions'];
     $args = array('post' => $post, 'server' => $server, 'factory' => $this->factory, 'submission' => $submission, 'fields' => $fieldArray, 'form' => $form, 'tokens' => $tokens);
     foreach ($actions as $action) {
         $key = $action->getType();
         if (!isset($availableActions[$key])) {
             continue;
         }
         $settings = $availableActions[$key];
         $args['action'] = $action;
         $args['config'] = $action->getProperties();
         if (array_key_exists('validator', $settings)) {
             $callback = $settings['validator'];
             if (is_callable($callback)) {
                 if (is_array($callback)) {
                     $reflection = new \ReflectionMethod($callback[0], $callback[1]);
                 } elseif (strpos($callback, '::') !== false) {
                     $parts = explode('::', $callback);
                     $reflection = new \ReflectionMethod($parts[0], $parts[1]);
                 } else {
                     $reflection = new \ReflectionMethod(null, $callback);
                 }
                 $pass = array();
                 foreach ($reflection->getParameters() as $param) {
                     if (isset($args[$param->getName()])) {
                         $pass[] = $args[$param->getName()];
                     } else {
                         $pass[] = null;
                     }
                 }
                 list($validated, $validatedMessage) = $reflection->invokeArgs($this, $pass);
                 if (!$validated) {
                     $validationErrors[$alias] = $validatedMessage;
                 }
             }
         }
     }
     //return errors
     if (!empty($validationErrors)) {
         return array('errors' => $validationErrors);
     }
     //set the landing page the form was submitted from if applicable
     if (!empty($post['mauticpage'])) {
         $page = $this->pageModel->getEntity((int) $post['mauticpage']);
         if ($page != null) {
             $submission->setPage($page);
         }
     }
     // Add a feedback parameter
     $args['feedback'] = array();
     // Create/update lead
     if (!empty($leadFieldMatches)) {
         $this->createLeadFromSubmit($form, $leadFieldMatches);
     }
     if ($form->isStandalone()) {
         // Now handle post submission actions
         foreach ($actions as $action) {
             $key = $action->getType();
             if (!isset($availableActions[$key])) {
                 continue;
             }
             $settings = $availableActions[$key];
             $args['action'] = $action;
             $args['config'] = $action->getProperties();
             // Set the lead each time in case an action updates it
             $args['lead'] = $this->leadModel->getCurrentLead();
             $callback = $settings['callback'];
             if (is_callable($callback)) {
                 if (is_array($callback)) {
                     $reflection = new \ReflectionMethod($callback[0], $callback[1]);
                 } elseif (strpos($callback, '::') !== false) {
                     $parts = explode('::', $callback);
                     $reflection = new \ReflectionMethod($parts[0], $parts[1]);
                 } else {
                     $reflection = new \ReflectionMethod(null, $callback);
                 }
                 $pass = array();
                 foreach ($reflection->getParameters() as $param) {
                     if (isset($args[$param->getName()])) {
                         $pass[] = $args[$param->getName()];
                     } else {
                         $pass[] = null;
                     }
                 }
                 $returned = $reflection->invokeArgs($this, $pass);
                 $args['feedback'][$key] = $returned;
             }
         }
     }
     // Get updated lead with tracking ID
     if ($form->isInKioskMode()) {
         $lead = $this->leadModel->getCurrentLead();
     } else {
         list($lead, $trackingId, $generated) = $this->leadModel->getCurrentLead(true);
         //set tracking ID for stats purposes to determine unique hits
         $submission->setTrackingId($trackingId);
     }
     $submission->setLead($lead);
     if (!$form->isStandalone()) {
         // Find and add the lead to the associated campaigns
         $campaigns = $this->campaignModel->getCampaignsByForm($form);
         if (!empty($campaigns)) {
             foreach ($campaigns as $campaign) {
                 $this->campaignModel->addLead($campaign, $lead);
             }
         }
     }
     //save entity after the form submission events are fired in case a new lead is created
     $this->saveEntity($submission);
     if ($this->dispatcher->hasListeners(FormEvents::FORM_ON_SUBMIT)) {
         $event = new SubmissionEvent($submission, $post, $server);
         $this->dispatcher->dispatch(FormEvents::FORM_ON_SUBMIT, $event);
     }
     //last round of callback commands from the submit actions; first come first serve
     foreach ($args['feedback'] as $k => $data) {
         if (!empty($data['callback'])) {
             return array('callback' => $data);
         }
     }
     //made it to the end so return false that there was not an error
     return false;
 }