Пример #1
0
 /**
  * @param Form $form
  * @param      $formHtml
  */
 public function populateValuesWithLead(Form $form, &$formHtml)
 {
     $formName = $form->generateFormName();
     $lead = $this->leadModel->getCurrentLead();
     $fields = $form->getFields();
     /** @var \Mautic\FormBundle\Entity\Field $f */
     foreach ($fields as $f) {
         $leadField = $f->getLeadField();
         $isAutoFill = $f->getIsAutoFill();
         if (isset($leadField) && $isAutoFill) {
             $value = $lead->getFieldValue($leadField);
             if (!empty($value)) {
                 $this->fieldHelper->populateField($f, $value, $formName, $formHtml);
             }
         }
     }
 }
Пример #2
0
 /**
  * Validates a field value.
  *
  * @param Field $field
  * @param       $value
  *
  * @return bool|string True if valid; otherwise string with invalid reason
  */
 protected function validateFieldValue(Field $field, $value)
 {
     $standardValidation = $this->fieldHelper->validateFieldValue($field->getType(), $value);
     if (!empty($standardValidation)) {
         return $standardValidation;
     }
     $components = $this->formModel->getCustomComponents();
     foreach ([$field->getType(), 'form'] as $type) {
         if (isset($components['validators'][$type])) {
             foreach ($components['validators'][$type] as $validator) {
                 $event = $this->dispatcher->dispatch($validator['eventName'], new ValidationEvent($field, $value));
                 if (!$event->isValid()) {
                     return $event->getInvalidReason();
                 }
             }
         }
     }
     return true;
 }
Пример #3
0
 /**
  * Generates edit form and processes post data
  *
  * @param int  $objectId
  * @param bool $ignorePost
  * @param bool $forceTypeSelection
  *
  * @return \Symfony\Component\HttpFoundation\JsonResponse|Response
  */
 public function editAction($objectId, $ignorePost = false, $forceTypeSelection = false)
 {
     /** @var \Mautic\FormBundle\Model\FormModel $model */
     $model = $this->factory->getModel('form');
     $formData = $this->request->request->get('mauticform');
     $sessionId = isset($formData['sessionId']) ? $formData['sessionId'] : null;
     if ($objectId instanceof Form) {
         $entity = $objectId;
         $objectId = sha1(uniqid(mt_rand(), true));
     } else {
         $entity = $model->getEntity($objectId);
         // Process submit of cloned form
         if ($entity == null && $objectId == $sessionId) {
             $entity = $model->getEntity();
         }
     }
     $session = $this->factory->getSession();
     $cleanSlate = true;
     //set the page we came from
     $page = $this->factory->getSession()->get('mautic.form.page', 1);
     //set the return URL
     $returnUrl = $this->generateUrl('mautic_form_index', array('page' => $page));
     $postActionVars = array('returnUrl' => $returnUrl, 'viewParameters' => array('page' => $page), 'contentTemplate' => 'MauticFormBundle:Form:index', 'passthroughVars' => array('activeLink' => '#mautic_form_index', 'mauticContent' => 'form'));
     //form not found
     if ($entity === null) {
         return $this->postActionRedirect(array_merge($postActionVars, array('flashes' => array(array('type' => 'error', 'msg' => 'mautic.form.error.notfound', 'msgVars' => array('%id%' => $objectId))))));
     } elseif (!$this->factory->getSecurity()->hasEntityAccess('form:forms:editown', 'form:forms:editother', $entity->getCreatedBy())) {
         return $this->accessDenied();
     } elseif ($model->isLocked($entity)) {
         //deny access if the entity is locked
         return $this->isLocked($postActionVars, $entity, 'form.form');
     }
     $action = $this->generateUrl('mautic_form_action', array('objectAction' => 'edit', 'objectId' => $objectId));
     $form = $model->createForm($entity, $this->get('form.factory'), $action);
     ///Check for a submitted form and process it
     if (!$ignorePost && $this->request->getMethod() == 'POST') {
         $valid = false;
         if (!($cancelled = $this->isFormCancelled($form))) {
             //set added/updated fields
             $modifiedFields = $session->get('mautic.form.' . $objectId . '.fields.modified', array());
             $deletedFields = $session->get('mautic.form.' . $objectId . '.fields.deleted', array());
             $fields = array_diff_key($modifiedFields, array_flip($deletedFields));
             //set added/updated actions
             $modifiedActions = $session->get('mautic.form.' . $objectId . '.actions.modified', array());
             $deletedActions = $session->get('mautic.form.' . $objectId . '.actions.deleted', array());
             $actions = array_diff_key($modifiedActions, array_flip($deletedActions));
             if ($valid = $this->isFormValid($form)) {
                 //make sure that at least one field is selected
                 if (empty($fields)) {
                     //set the error
                     $form->addError(new FormError($this->get('translator')->trans('mautic.form.form.fields.notempty', array(), 'validators')));
                     $valid = false;
                 } else {
                     $model->setFields($entity, $fields);
                     $model->deleteFields($entity, $deletedFields);
                     if ($entity->isStandalone()) {
                         if (!($alias = $entity->getAlias())) {
                             $alias = $model->cleanAlias($entity->getName(), '', 10);
                             $entity->setAlias($alias);
                         }
                         if (!$entity->getId()) {
                             // Set timestamps because this is a new clone
                             $model->setTimestamps($entity, true, false);
                         }
                         // save the form first so that new fields are available to actions
                         // use the repository method to not trigger listeners twice
                         $model->getRepository()->saveEntity($entity);
                         if (count($actions)) {
                             // Now set and persist the actions
                             $model->setActions($entity, $actions);
                         }
                         // Delete deleted actions
                         if (count($deletedActions)) {
                             $this->factory->getModel('form.action')->deleteEntities($deletedActions);
                         }
                     } else {
                         // Clear the actions
                         $entity->clearActions();
                         // Delete all actions
                         if (count($modifiedActions)) {
                             $this->factory->getModel('form.action')->deleteEntities(array_keys($modifiedActions));
                         }
                     }
                     // Persist and execute listeners
                     $model->saveEntity($entity, $form->get('buttons')->get('save')->isClicked());
                     // Reset objectId to entity ID (can be session ID in case of cloned entity)
                     $objectId = $entity->getId();
                     $this->addFlash('mautic.core.notice.updated', array('%name%' => $entity->getName(), '%menu_link%' => 'mautic_form_index', '%url%' => $this->generateUrl('mautic_form_action', array('objectAction' => 'edit', 'objectId' => $entity->getId()))));
                     if ($form->get('buttons')->get('save')->isClicked()) {
                         $viewParameters = array('objectAction' => 'view', 'objectId' => $entity->getId());
                         $returnUrl = $this->generateUrl('mautic_form_action', $viewParameters);
                         $template = 'MauticFormBundle:Form:view';
                     }
                 }
             }
         } else {
             //unlock the entity
             $model->unlockEntity($entity);
             $viewParameters = array('page' => $page);
             $returnUrl = $this->generateUrl('mautic_form_index', $viewParameters);
             $template = 'MauticFormBundle:Form:index';
         }
         if ($cancelled || $valid && $form->get('buttons')->get('save')->isClicked()) {
             //remove fields from session
             $this->clearSessionComponents($objectId);
             // Clear session items in case columns changed
             $session->remove('mautic.formresult.' . $entity->getId() . '.orderby');
             $session->remove('mautic.formresult.' . $entity->getId() . '.orderbydir');
             $session->remove('mautic.formresult.' . $entity->getId() . '.filters');
             return $this->postActionRedirect(array_merge($postActionVars, array('returnUrl' => $returnUrl, 'viewParameters' => $viewParameters, 'contentTemplate' => $template)));
         } elseif ($form->get('buttons')->get('apply')->isClicked()) {
             //rebuild everything to include new ids
             $cleanSlate = true;
             $reorder = true;
         }
     } else {
         $cleanSlate = true;
         //lock the entity
         $model->lockEntity($entity);
         $form->get('sessionId')->setData($objectId);
     }
     // Get field and action settings
     $customComponents = $model->getCustomComponents();
     $fieldHelper = new FormFieldHelper($this->get('translator'));
     $availableFields = $fieldHelper->getList($customComponents['fields']);
     if ($cleanSlate) {
         //clean slate
         $this->clearSessionComponents($objectId);
         //load existing fields into session
         $modifiedFields = array();
         $usedLeadFields = array();
         $existingFields = $entity->getFields()->toArray();
         foreach ($existingFields as $formField) {
             // Check to see if the field still exists
             if ($formField->getType() !== 'button' && !isset($availableFields[$formField->getType()])) {
                 continue;
             }
             $id = $formField->getId();
             $field = $formField->convertToArray();
             if (!$id) {
                 // Cloned entity
                 $id = $field['id'] = $field['sessionId'] = 'new' . hash('sha1', uniqid(mt_rand()));
             }
             unset($field['form']);
             if (isset($customComponents['fields'][$field['type']])) {
                 // Set the custom parameters
                 $field['customParameters'] = $customComponents['fields'][$field['type']];
             }
             $modifiedFields[$id] = $field;
             if (!empty($field['leadField'])) {
                 $usedLeadFields[$id] = $field['leadField'];
             }
         }
         $session->set('mautic.form.' . $objectId . '.fields.leadfields', $usedLeadFields);
         if (!empty($reorder)) {
             uasort($modifiedFields, function ($a, $b) {
                 return $a['order'] > $b['order'];
             });
         }
         $session->set('mautic.form.' . $objectId . '.fields.modified', $modifiedFields);
         $deletedFields = array();
         // Load existing actions into session
         $modifiedActions = array();
         $existingActions = $entity->getActions()->toArray();
         foreach ($existingActions as $formAction) {
             // Check to see if the action still exists
             if (!isset($customComponents['actions'][$formAction->getType()])) {
                 continue;
             }
             $id = $formAction->getId();
             $action = $formAction->convertToArray();
             if (!$id) {
                 // Cloned entity so use a random Id instead
                 $action['id'] = $id = 'new' . hash('sha1', uniqid(mt_rand()));
             }
             unset($action['form']);
             $modifiedActions[$id] = $action;
         }
         if (!empty($reorder)) {
             uasort($modifiedActions, function ($a, $b) {
                 return $a['order'] > $b['order'];
             });
         }
         $session->set('mautic.form.' . $objectId . '.actions.modified', $modifiedActions);
         $deletedActions = array();
     }
     return $this->delegateView(array('viewParameters' => array('fields' => $availableFields, 'actions' => $customComponents['choices'], 'formFields' => $modifiedFields, 'formActions' => $modifiedActions, 'deletedFields' => $deletedFields, 'deletedActions' => $deletedActions, 'tmpl' => $this->request->isXmlHttpRequest() ? $this->request->get('tmpl', 'index') : 'index', 'activeForm' => $entity, 'form' => $form->createView(), 'forceTypeSelection' => $forceTypeSelection), 'contentTemplate' => 'MauticFormBundle:Builder:index.html.php', 'passthroughVars' => array('activeLink' => '#mautic_form_index', 'mauticContent' => 'form', 'route' => $this->generateUrl('mautic_form_action', array('objectAction' => 'edit', 'objectId' => $entity->getId())))));
 }
Пример #4
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->factory->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->factory->getModel('form')->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->factory->getModel('page.page')->getEntity((int) $post['mauticpage']);
         if ($page != null) {
             $submission->setPage($page);
         }
     }
     // Add a feedback parameter
     $args['feedback'] = array();
     /** @var \Mautic\LeadBundle\Model\LeadModel $leadModel */
     $leadModel = $this->factory->getModel('lead');
     // 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'] = $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 = $leadModel->getCurrentLead();
     } else {
         list($lead, $trackingId, $generated) = $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
         /** @var \Mautic\CampaignBundle\Model\CampaignModel $campaignModel */
         $campaignModel = $this->factory->getModel('campaign');
         $campaigns = $campaignModel->getCampaignsByForm($form);
         if (!empty($campaigns)) {
             foreach ($campaigns as $campaign) {
                 $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;
 }
Пример #5
0
                $ignoreNumericalKeys = true;
                break;
            case 'country' == $leadFieldType:
                $list = \Mautic\LeadBundle\Helper\FormFieldHelper::getCountryChoices();
                break;
            case 'region' == $leadFieldType:
                $list = \Mautic\LeadBundle\Helper\FormFieldHelper::getRegionChoices();
                break;
            case 'timezone' == $leadFieldType:
                $list = \Mautic\LeadBundle\Helper\FormFieldHelper::getTimezonesChoices();
                break;
            case 'locale':
                $list = \Mautic\LeadBundle\Helper\FormFieldHelper::getLocaleChoices();
                break;
        }
    }
    if (empty($parseList)) {
        if (isset($list)) {
            $parseList = $list;
        } elseif (!empty($properties['list'])) {
            $parseList = $properties['list'];
        } elseif (!empty($properties['optionlist'])) {
            $parseList = $properties['optionlist'];
        }
        if (isset($parseList['list'])) {
            $parseList = $parseList['list'];
        }
    }
    $list = \Mautic\FormBundle\Helper\FormFieldHelper::parseList($parseList, false, $ignoreNumericalKeys);
    $firstListValue = reset($list);
}