/** * {@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']); } }
/** * 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())); }
/** * 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']); } } }
/** * 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; }
/** * @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()); }
/** * @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; }
/** * @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()); } }
/** * 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(); } }
/** * @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; }