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