Esempio n. 1
0
 /**
  * Updates an existing Form model (except id).
  * Updates an existing FormData model (only data field).
  * Updates an existing FormConfirmation model (except id & form_id).
  * Updates an existing FormEmail model (except id & form_id).
  * If update is successful, the browser will be redirected to the 'index' page.
  *
  * @param int|null $id
  * @return string|\yii\web\Response
  * @throws NotFoundHttpException
  * @throws \Exception
  * @throws \yii\db\Exception
  */
 public function actionSettings($id = null)
 {
     /** @var \app\models\Form $formModel */
     $formModel = $this->findFormModel($id);
     $formDataModel = $formModel->formData;
     $formConfirmationModel = $formModel->formConfirmation;
     $formEmailModel = $formModel->formEmail;
     $formUIModel = $formModel->ui;
     $postData = Yii::$app->request->post();
     if ($formModel->load($postData) && $formConfirmationModel->load($postData) && $formEmailModel->load($postData) && $formUIModel->load($postData) && Model::validateMultiple([$formModel, $formConfirmationModel, $formEmailModel, $formUIModel])) {
         // Save data in single transaction
         $transaction = Form::getDb()->beginTransaction();
         try {
             // Save Form Model
             if (!$formModel->save()) {
                 throw new \Exception(Yii::t("app", "Error saving Form Model"));
             }
             // Save data field in FormData model
             if (isset($postData['Form']['name'])) {
                 // Convert JSON Data of Form Data Model to PHP Array
                 /** @var \app\components\JsonToArrayBehavior $builderField */
                 $builderField = $formDataModel->behaviors['builderField'];
                 // Set form name by json key path. If fail, throw \ArrayAccessException
                 $builderField->setSafeValue('settings.name', $postData['Form']['name']);
                 // Save to DB
                 $builderField->save();
                 // If fail, throw \Exception
             }
             // Save FormConfirmation Model
             if (!$formConfirmationModel->save()) {
                 throw new \Exception(Yii::t("app", "Error saving Form Confirmation Model"));
             }
             // Save FormEmail Model
             if (!$formEmailModel->save()) {
                 throw new \Exception(Yii::t("app", "Error saving Form Email Model"));
             }
             // Save FormUI Model
             if (!$formUIModel->save()) {
                 throw new \Exception(Yii::t("app", "Error saving Form UI Model"));
             }
             $transaction->commit();
             Yii::$app->getSession()->setFlash('success', Yii::t('app', 'The form settings have been successfully updated'));
             return $this->redirect(['index']);
         } catch (\Exception $e) {
             // Rolls back the transaction
             $transaction->rollBack();
             // Rethrow the exception
             throw $e;
         }
     } else {
         // Select id & name of all themes in the system
         $themes = Theme::find()->select(['id', 'name'])->asArray()->all();
         $themes = ArrayHelper::map($themes, 'id', 'name');
         return $this->render('settings', ['formModel' => $formModel, 'formDataModel' => $formDataModel, 'formConfirmationModel' => $formConfirmationModel, 'formEmailModel' => $formEmailModel, 'formUIModel' => $formUIModel, 'themes' => $themes]);
     }
 }
Esempio n. 2
0
 /**
  * Update form
  *
  * @param $id
  * @return array|string
  * @throws \yii\db\Exception
  */
 public function actionUpdateForm($id)
 {
     if (Yii::$app->request->isAjax) {
         // Response fornat
         Yii::$app->response->format = Response::FORMAT_JSON;
         // Extract FormBuilder data from post request
         $post = Yii::$app->request->post();
         $data = ['FormBuilder' => Json::decode($post['FormBuilder'], true)];
         $formBuilder = new FormBuilder();
         $success = false;
         $message = '';
         $code = 0;
         // Form Builder Validation
         if ($formBuilder->load($data) && $formBuilder->validate()) {
             // Save data in single transaction
             $transaction = Form::getDb()->beginTransaction();
             try {
                 // Parse html form fields to array
                 $formDOM = new FormDOM();
                 // If two elements has same id, throw a exception
                 $formDOM->loadHTML(ArrayHelper::getValue($data, 'FormBuilder.html'));
                 $formDOM->loadXpath();
                 $formDOM->loadFields();
                 // Get Form Model
                 $formModel = $this->findFormModel($id);
                 // Get FormData Model
                 $formDataModel = $formModel->formData;
                 // Get FormEmail Model
                 $formEmailModel = $formModel->formEmail;
                 // Filter reCaptcha component
                 $reCaptchaComponent = ArrayHelper::filter(ArrayHelper::getValue($data, 'FormBuilder.data.initForm'), 'recaptcha', 'name');
                 // Post Form
                 $postForm = ['Form' => ['name' => ArrayHelper::getValue($data, 'FormBuilder.data.settings.name'), 'recaptcha' => count($reCaptchaComponent) > 0 ? 1 : 0]];
                 // Post Form Data
                 $postFormData = ['FormData' => ['form_id' => $id, 'builder' => Json::htmlEncode(ArrayHelper::getValue($data, 'FormBuilder.data')), 'fields' => $formDOM->getFieldsAsJSON(), 'html' => Html::encode(ArrayHelper::getValue($data, 'FormBuilder.html')), 'height' => ArrayHelper::getValue($data, 'FormBuilder.data.height')]];
                 if (!$formModel->load($postForm) || !$formModel->save()) {
                     throw new Exception(Yii::t('app', 'Error saving data'), 1);
                 }
                 if (!$formDataModel->load($postFormData) || !$formDataModel->validate() || !$formDataModel->save()) {
                     throw new Exception(Yii::t('app', 'Error saving data'), 2);
                 }
                 // If From Field of Form Email Model is not a email
                 if (!$formEmailModel->fromIsEmail()) {
                     // Get form fields
                     $fields = Json::decode($formDOM->getFieldsAsJSON(), true);
                     // If the Email Field was modified
                     if (!$formBuilder->hasSameEmailField($formEmailModel->from, $fields)) {
                         // Delete From Field of FormEmail Model
                         $formEmailModel->from = null;
                         if (!$formEmailModel->save()) {
                             throw new Exception(Yii::t('app', 'Error saving data'), 3);
                         }
                     }
                 }
                 $transaction->commit();
                 // Change success flag and message
                 $success = true;
                 $message = Yii::t("app", "The form has been successfully updated");
             } catch (Exception $e) {
                 // Rolls back the transaction
                 $transaction->rollBack();
                 // Rethrow the exception
                 // throw $e;
                 $message = $e->getMessage();
                 $code = $e->getCode();
             }
         }
         // Response to Client
         $res = array('success' => $success, 'id' => $id, 'action' => 'update', 'message' => $message, 'code' => $code);
         return $res;
     }
     return '';
 }
Esempio n. 3
0
 /**
  * Insert a Form Submission Model
  *
  * @param $id
  * @return array
  * @throws NotFoundHttpException
  * @throws \Exception
  * @throws \yii\db\Exception
  */
 public function actionA($id)
 {
     if (Yii::$app->request->isAjax) {
         // The HTTP post request
         $post = Yii::$app->request->post();
         if (isset($post)) {
             // If no model, throw NotFoundHttpException
             $formModel = $this->findFormModel($id);
             /**************+++++++++++++++++
                /* Spam Filter
                /*******************************/
             // Honeypot filter. If spam, throw NotFoundHttpException
             $formModel->checkHoneypot($post);
             // reCAPTCHA Validation. If error, send response to browser
             $formModel->validateRecaptcha($post);
             /**************+++++++++++++++++
                /* Submission Limit
                /*******************************/
             // If error, send response to browser
             $formModel->checkTotalLimit();
             $formModel->checkIPLimit();
             /**************+++++++++++++++++
                /* Prepare response by default
                /*******************************/
             // Response fornat
             Yii::$app->response->format = Response::FORMAT_JSON;
             // Default response
             $response = array('action' => 'submit', 'success' => true, 'id' => 0, 'message' => Yii::t('app', 'Your message has been sent. {startTag}Thank you!{endTag}', ['startTag' => '<strong>', 'endTag' => '</strong>']));
             /**************+++++++++++++++++
                /* Prepare data
                /*******************************/
             // Set public scenario of the submission
             $formSubmissionModel = new FormSubmission(['scenario' => 'public']);
             /** @var \app\models\FormData $formDataModel */
             $formDataModel = $formModel->formData;
             // Get all fields except buttons and files
             $fields = $formDataModel->getFieldsWithoutFilesAndButtons();
             // Get file fields
             $fileFields = $formDataModel->getFileFields();
             // Remove fields with null values and
             // Strip whitespace from the beginning and end of each post value
             $submissionData = $formSubmissionModel->cleanSubmission($fields, $post);
             // Get uploaded files
             $files = $formSubmissionModel->getUploadedFiles($fileFields);
             // File paths cache
             $filePaths = array();
             // Prepare Submission for validation
             $postFormSubmission = ['FormSubmission' => ['form_id' => $formModel->id, 'data' => $submissionData]];
             /**************+++++++++++++++++
                /* FormSubmission Validation
                /*******************************/
             if ($formSubmissionModel->load($postFormSubmission) && $formSubmissionModel->validate()) {
                 Yii::$app->trigger($this::EVENT_SUBMISSION_RECEIVED, new SubmissionEvent(['sender' => $this, 'form' => $formModel, 'submission' => $formSubmissionModel, 'files' => $files]));
                 if ($formModel->saveToDB()) {
                     /**************+++++++++++++++++
                        /* Save to DB
                        /*******************************/
                     // Save submission in single transaction
                     $transaction = Form::getDb()->beginTransaction();
                     try {
                         // Save submission without validation
                         if ($formSubmissionModel->save(false)) {
                             // Save files to DB and disk
                             /* @var $file \yii\web\UploadedFile */
                             foreach ($files as $file) {
                                 if (isset($file)) {
                                     // Save file to DB
                                     $fileModel = new FormSubmissionFile();
                                     $fileModel->submission_id = $formSubmissionModel->primaryKey;
                                     $fileModel->form_id = $formModel->id;
                                     // Replace special characters before the file is saved
                                     $fileModel->name = preg_replace("/[^a-zA-Z0-9]/", "", $file->baseName) . "-" . $formSubmissionModel->primaryKey;
                                     $fileModel->extension = $file->extension;
                                     $fileModel->size = $file->size;
                                     $fileModel->status = 1;
                                     $fileModel->save();
                                     // Throw exception if validation fail
                                     if (isset($fileModel->errors) && count($fileModel->errors) > 0) {
                                         throw new \Exception(Yii::t("app", "Error saving files."));
                                     }
                                     // Save file to disk
                                     $filePath = $fileModel->getFilePath();
                                     $file->saveAs($filePath);
                                     array_push($filePaths, $filePath);
                                 }
                             }
                             // Change response id
                             $response["id"] = $formSubmissionModel->primaryKey;
                         }
                         $transaction->commit();
                     } catch (\Exception $e) {
                         // Rolls back the transaction
                         $transaction->rollBack();
                         // Rethrow the exception
                         throw $e;
                     }
                 } else {
                     /**************+++++++++++++++++
                        /* Don't save to DB
                        /*******************************/
                     // Save files to disk
                     foreach ($files as $file) {
                         /* @var $file \yii\web\UploadedFile */
                         if (isset($file)) {
                             $filePath = $formModel::FILES_DIRECTORY . DIRECTORY_SEPARATOR . $formModel->id . DIRECTORY_SEPARATOR . $file->name;
                             $file->saveAs($filePath);
                             array_push($filePaths, $filePath);
                         }
                     }
                 }
                 Yii::$app->trigger($this::EVENT_SUBMISSION_ACCEPTED, new SubmissionEvent(['sender' => $this, 'form' => $formModel, 'submission' => $formSubmissionModel, 'files' => $files, 'filePaths' => $filePaths]));
             } else {
                 Yii::$app->trigger($this::EVENT_SUBMISSION_REJECTED, new SubmissionEvent(['sender' => $this, 'form' => $formModel, 'submission' => $formSubmissionModel]));
                 // Print validation errors
                 $errors = array();
                 foreach ($formSubmissionModel->errors as $field => $messages) {
                     array_push($errors, array("field" => $field, "messages" => $messages));
                 }
                 // Change response
                 $response["success"] = false;
                 $response["message"] = Yii::t('app', 'There is {startTag}an error in your submission{endTag}.', ['startTag' => '<strong>', 'endTag' => '</strong>']);
                 $response["errors"] = $errors;
             }
             return $response;
         }
     }
     return '';
 }