/** * Check if user has reached his submission limit */ public function checkIPLimit() { if ($this->ip_limit === $this::ON) { $startTime = TimeHelper::startTime($this->ip_limit_period); $ip = Yii::$app->getRequest()->getUserIP(); if ($ip === "::1") { // Usefull when app run in localhost $ip = "81.2.69.160"; } $submissions = FormSubmission::find()->select('id')->asArray()->where(['form_id' => $this->id])->andWhere(['between', 'created_at', $startTime, time()])->andWhere(['ip' => $ip])->count(); if ($this->ip_limit_number <= $submissions) { /** @var \yii\web\Response $response */ $response = Yii::$app->getResponse(); $response->format = Response::FORMAT_JSON; $response->data = array('action' => 'submit', 'success' => false, 'id' => 0, 'message' => Yii::t("app", "You have reached your Submission Limit per {period}.", ['period' => TimeHelper::getPeriodByCode($this->ip_limit_period)])); $response->send(); exit; } } }
/** * Show & Save form report * * @param $id * @return array * @throws Exception */ public function actionReport($id) { Yii::$app->response->format = Response::FORMAT_JSON; // Extract report data from post request $post = Yii::$app->request->post(); // The raw data of the report $rawReport = isset($post) && isset($post['report']) ? $post['report'] : null; // Convert to charts array $charts = Json::decode($rawReport, true); if (isset($charts)) { // Save data in single transaction $transaction = FormChart::getDb()->beginTransaction(); $success = false; try { // Delete old charts if there are FormChart::deleteAll(['form_id' => $id]); if (count($charts) > 0) { // Populate each Form Chart Model and Save foreach ($charts as $chart) { $formChartModel = new FormChart(); // Add form_id to chart $chart['form_id'] = $id; // Prepare new model data $postFormChart = ['FormChart' => $chart]; // Load & Save the model if (!$formChartModel->load($postFormChart) || !$formChartModel->save()) { throw new Exception(Yii::t("app", "Error saving the chart")); } } } $transaction->commit(); // Change success flag and message $success = true; $message = Yii::t("app", "The report has been successfully updated."); } catch (Exception $e) { // Rolls back the transaction $transaction->rollBack(); // Rethrow the exception // throw $e; $message = $e->getMessage(); } $res = array('success' => $success, 'id' => $id, 'action' => 'update', 'message' => $message); return $res; } $submissions = array(); foreach (FormSubmission::find()->select(['data', 'created_at'])->where('form_id=:form_id', [':form_id' => $id])->each(10) as $submissionModel) { $submission = $submissionModel->data; $submission['created_at'] = $submissionModel->created_at; array_push($submissions, $submission); } return $submissions; }
/** * Export form submissions. * * @param integer $id */ public function actionExportSubmissions($id) { $formModel = $this->findFormModel($id); $formDataModel = $formModel->formData; $query = FormSubmission::find()->select(['data', 'created_at'])->where('form_id=:form_id', [':form_id' => $id])->asArray(); // Create the CSV into memory $csv = Writer::createFromFileObject(new SplTempFileObject()); // Insert fields names as the CSV header $header = array_values($formDataModel->getLabels()); array_push($header, 'Submitted at'); $csv->insertOne($header); // To iterate the row one by one foreach ($query->each() as $submission) { // $submission represents one row of data from the form_submission table $data = Json::decode($submission['data'], true); foreach ($data as &$field) { if (is_array($field)) { $field = implode(', ', $field); } } $data["created_at"] = Yii::$app->formatter->asDatetime($submission['created_at']); $csv->insertOne($data); } // Print to the output stream $csv->output($formModel->name . '.csv'); }
public function uniqueFieldsValidation() { $message = Yii::t("app", "{label} '{value}' has already been taken."); foreach ($this->uniqueFields as $field) { // Only when the input value is not empty if (isset($field["name"]) && trim($this->data[$field["name"]]) !== "") { // Strip whitespace from the beginning and end of a string $value = trim($this->data[$field["name"]]); // Search "fieldName":"fieldValue" $query = FormSubmission::find()->where('form_id=:form_id', [':form_id' => $this->dataModel->form_id])->andWhere(['like', 'data', '"' . $field["name"] . '":"' . $value . '"']); if ($query->count() > 0) { $this->addError($field["name"], $field["label"], $value, $message); } } } }
/** * 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 ''; }
public function actionDeleteall() { // Get ids param $request = Yii::$app->getRequest(); $id = $request->post('id'); $ids = $request->post('ids'); // Default $success = false; $message = "No items matched the query"; $itemsDeleted = 0; try { // The number of rows deleted $itemsDeleted = 0; // Delete one to one for trigger events foreach (FormSubmission::find()->where(['id' => $ids, 'form_id' => $id])->all() as $submissionModel) { $deleted = $submissionModel->delete(); if ($deleted) { $itemsDeleted++; } } // Set response if ($itemsDeleted > 0) { $success = true; $message = Yii::t("app", "Items deleted successfully"); } } catch (\Exception $e) { // Rethrow the exception // throw $e; $message = $e->getMessage(); } // Response fornat Yii::$app->response->format = Response::FORMAT_JSON; // Response to Client $res = array('success' => $success, 'action' => 'deleteall', 'itemsDeleted' => $itemsDeleted, 'ids' => $ids, 'message' => $message); return $res; }