public function process(Request $request)
 {
     // Ajax-validation is only possible, if the _formID was submitted (automatically done by the FormBuilder).
     if (\Request::has('_formID')) {
         // The FormBuilder should have saved the requestObject this form uses inside the session.
         // We check, if it is there, and can continue only, if it is.
         $sessionKeyForRequestObject = 'htmlBuilder.formBuilder.requestObjects.' . \Request::input('_formID');
         if (Session::has($sessionKeyForRequestObject)) {
             // Normally we assume a successful submission and return just an empty JSON-array.
             $returnCode = 200;
             $return = [];
             // We instantiate the requestObject.
             $formRequest = FormBuilderTools::getRequestObject(Session::get($sessionKeyForRequestObject));
             // We instantiate a controller with the submitted request-data
             // and the rules and messages from the requestObject.
             $validator = Validator::make(\Request::all(), $formRequest->rules(), $formRequest->messages());
             // Perform validation, extract error-messages for all fields on failure, put them inside a $return['errors']-array, and return status code 422.
             if ($validator->fails()) {
                 $errors = [];
                 foreach (array_dot(\Request::all()) as $fieldName => $fieldValue) {
                     $fieldErrors = FormBuilderTools::extractErrorsForField($fieldName, $validator->errors()->getMessages(), \Request::all());
                     if (count($fieldErrors) > 0) {
                         $errors[FormBuilderTools::convertArrayFieldDotNotation2HtmlName($fieldName)] = $fieldErrors;
                     }
                 }
                 $return['errors'] = $errors;
                 $returnCode = 422;
             }
             return new JsonResponse($return, $returnCode);
         }
     }
 }
Пример #2
0
 /**
  * Add required-symbol to legend.
  */
 protected function task_20_addRequiredSymbolToLegend()
 {
     if ($this->hasLegend()) {
         $fieldRules = app()['formbuilder']->getRulesForField($this->getName());
         if (FormBuilderTools::existRules($fieldRules)) {
             if (is_string($fieldRules)) {
                 $fieldRules = explode('|', $fieldRules);
             }
             if (array_search('required', $fieldRules) !== false) {
                 $this->legend($this->getLegend() . '<sup>*</sup>');
             }
         }
     }
 }
Пример #3
0
 public function validate($attribute, $value, $parameters, $validator)
 {
     $isValid = true;
     // We only validate, if honeypot-protection is basically enabled in the config.
     if (config('htmlbuilder.formBuilder.honeypot.enabled')) {
         $honeypotFieldName = FormBuilderTools::getHoneypotFieldName();
         $fullRequest = Request::all();
         if (isset($fullRequest[$honeypotFieldName])) {
             if (strlen($fullRequest[$honeypotFieldName]) > 0) {
                 $isValid = false;
             }
         } else {
             $isValid = false;
         }
     }
     return $isValid;
 }
Пример #4
0
 /**
  * Gets the error(s) of field $name from $errors.
  * Furthermore: If it is the first element of an array (e.g. domainList.0.domainName),
  * the errors of the array itself are also returned.
  * For multidimensional arrays this works recursively.
  * Example:
  *  This server-side request array:
  *      domainList => [
  *          0 => [
  *              domainLabel => 'first-domain',
  *              domainPdo   => 'at',
  *          ],
  *          1 => [
  *              domainLabel => 'second-domain',
  *              domainPdo   => 'at',
  *          ],
  *
  *  Returns errors in the following structure:
  *
  *      - Field 'domainList[0][domainLabel]' returns errors for:
  *          - domainList[0][domainLabel]
  *          - domainList[0]
  *          - domainList
  *      - Field 'domainList[0][domainPdo]' returns errors for:
  *          - domainList[0][domainPdo]
  *      - Field 'domainList[1][domainLabel]' returns errors for:
  *          - domainList[1][domainLabel]
  *          - domainList[1]
  *      - Field 'domainList[1][domainPdo]' returns errors for:
  *          - domainList[1][domainPdo]
  *
  * @param string $name: Name of the field (array-fields must be in dot-notation (e.g. "domainList.0.domainName"))
  * @param array $errors: Array of all errors (in dot-notation)
  * @param array $request: Array of full request (in dot-notation)
  * @return array
  */
 public static function extractErrorsForField($name = '', $errors = [], $request = [])
 {
     $return = [];
     $isArray = false;
     // Check, if the name is an array-key (e.g. "domainList.0.domainName").
     if (strpos($name, '.') !== false) {
         $isArray = true;
     }
     // If the field is the first element of an array,
     // we also add errors regarding the array itself.
     // (e.g. in case of a 'size:5' validation rule on the array itself)
     if ($isArray) {
         $arrayName = substr($name, 0, strrpos($name, '.'));
         $arrayFieldKey = substr($name, strrpos($name, '.') + 1);
         $addArrayErrors = true;
         if (array_has($request, $arrayName) && strval(key(array_get($request, $arrayName))) !== $arrayFieldKey) {
             $addArrayErrors = false;
         }
         if ($addArrayErrors) {
             $return = array_merge(FormBuilderTools::extractErrorsForField($arrayName, $errors, $request), $return);
         }
     }
     // Get the errors (if present) from $this->errors.
     if (isset($errors[$name])) {
         $return = array_merge($return, $errors[$name]);
     }
     return $return;
 }
Пример #5
0
 /**
  * Gets the error(s) of a field currently stored in the FormBuilder-object.
  * Furthermore: If it is the first element of an array (e.g. domainName[0]),
  * the errors of the array itself are also returned.
  * This even works for multidimensional arrays.
  * Example:
  *  This server-side request array:
  *      domainList => [
  *          0 => [
  *              domainLabel => 'first-domain',
  *              domainPdo   => 'at',
  *          ],
  *          1 => [
  *              domainLabel => 'second-domain',
  *              domainPdo   => 'at',
  *          ],
  *
  *  Returns errors in the following structure:
  *
  *      - Field 'domainList[0][domainLabel]' returns errors for:
  *          - domainList[0][domainLabel]
  *          - domainList[0]
  *          - domainList
  *      - Field 'domainList[0][domainPdo]' returns errors for:
  *          - domainList[0][domainPdo]
  *      - Field 'domainList[1][domainLabel]' returns errors for:
  *          - domainList[1][domainLabel]
  *          - domainList[1]
  *      - Field 'domainList[1][domainPdo]' returns errors for:
  *          - domainList[1][domainPdo]
  *
  * @param string $name
  * @return array
  */
 public function getErrorsForField($name = '')
 {
     $errors = [];
     if (count($this->errors) > 0) {
         $errors = FormBuilderTools::extractErrorsForField(FormBuilderTools::convertArrayFieldHtmlName2DotNotation($name), $this->errors, Request::old());
     }
     return $errors;
 }
Пример #6
0
 /**
  * Applies laravel-validation-rules to properties of this object.
  *
  */
 private function applyRules()
 {
     if (FormBuilderTools::existRules($this->rules)) {
         // Format the laravel-rules-array.
         $rules = FormBuilderTools::explodeRules($this->rules);
         foreach ($rules as $rule => $parameters) {
             switch ($rule) {
                 case 'accepted':
                 case 'required':
                     $this->attrRequired = true;
                     break;
                 case 'not_numeric':
                     $this->attrPattern = '\\D+';
                     break;
                 case 'url':
                 case 'active_url':
                     $this->attrType = 'url';
                     break;
                 case 'alpha':
                     $this->attrPattern = '[a-zA-Z]+';
                     break;
                 case 'alpha_dash':
                     $this->attrPattern = '[a-zA-Z0-9_\\-]+';
                     break;
                 case 'alpha_num':
                     $this->attrPattern = '[a-zA-Z0-9]+';
                     break;
                 case 'between':
                     if ($this::TAG === 'input') {
                         if ($this->attrType === 'number') {
                             $this->attrMin = $parameters[0];
                             $this->attrMax = $parameters[1];
                         } else {
                             $this->attrPattern .= '.{' . $parameters[0] . ',' . $parameters[1] . '}';
                             $this->attrMaxlength = $parameters[1];
                         }
                     } else {
                         if ($this::TAG === 'textarea') {
                             $this->attrMaxlength = $parameters[1];
                         }
                     }
                     break;
                 case 'in':
                     $parameters = sizeof($parameters) == 1 ? $parameters[0] : '(' . join('|', $parameters) . ')';
                     $this->attrPattern = '^' . $parameters . '$';
                     break;
                 case 'ip':
                     //TODO
                     break;
                 case 'max':
                     if ($this::TAG === 'input') {
                         if ($this->attrType === 'number') {
                             $this->attrMax = $parameters[0];
                         } else {
                             $this->attrMaxlength = $parameters[0];
                         }
                     } else {
                         if ($this::TAG === 'textarea') {
                             $this->attrMaxlength = $parameters[0];
                         }
                     }
                     break;
                 case 'min':
                     if ($this->attrType === 'number') {
                         $this->attrMin = $parameters[0];
                     } else {
                         if (isset($this->attrPattern)) {
                             $this->attrPattern .= ".{" . $parameters[0] . ",}";
                         } else {
                             $this->attrPattern = ".{" . $parameters[0] . ",}";
                         }
                     }
                     break;
                 case 'not_in':
                     $this->attrPattern = '(?:(?!^' . join('$|^', $parameters) . '$).)*';
                     break;
                 case 'numeric':
                     $this->attrType = 'number';
                     $this->attrPattern = '[+-]?\\d*\\.?\\d+';
                     break;
                 case 'mimes':
                     if (array_search('jpeg', $parameters) !== false) {
                         array_push($parameters, 'jpg');
                     }
                     $this->attrAccept = '.' . implode(',.', $parameters);
                     break;
             }
         }
     }
 }
Пример #7
0
 /**
  * Handle setting the session-info and generation of the captcha-field, if captcha-protection is enabled in the config.
  */
 protected function task_1100_handleCaptchaProtection()
 {
     if (config('htmlbuilder.formBuilder.captcha.enabled')) {
         // We retrieve the captcha-rules.
         $captchaRules = app()['formbuilder']->getRulesForField('_captcha');
         // If there are any, ...
         if (strlen($captchaRules) > 0) {
             // Captcha-protection only works, if a request-object was stated via the requestObject() method,
             // so we throw an exception, if this was not the case.
             if (!$this->hasRequestObject()) {
                 throw new MandatoryOptionMissingException('The form with ID "' . app()['formbuilder']->getID() . '"" should display a captcha, ' . 'but no request-object was stated via the Form::open()->requestObject() method. ' . 'Captcha only works if this is the case.');
             }
             // Set where the captcha-answer will be stored in the session.
             $sessionKeyForCaptchaData = 'htmlBuilder.formBuilder.captcha.' . $this->getRequestObject();
             // We unset any old captcha-answer currently set in the session for this form
             Request::session()->forget($sessionKeyForCaptchaData);
             $ruleParameters = FormBuilderTools::explodeRules($captchaRules);
             $ruleParameters = $ruleParameters['captcha'];
             // If a specific limit is set for this request via the first rule-parameter, we use this value.
             if (isset($ruleParameters[0]) && is_numeric($ruleParameters[0])) {
                 $requestLimit = $ruleParameters[0];
             } else {
                 $requestLimit = config('htmlbuilder.formBuilder.captcha.defaultLimit');
             }
             // If a specific decay-time is set for this request via the first rule-parameter, we use this value.
             if (isset($ruleParameters[1]) && is_numeric($ruleParameters[1])) {
                 $decayTime = $ruleParameters[1];
             } else {
                 $decayTime = config('htmlbuilder.formBuilder.captcha.decayTime');
             }
             // Now let's see, if the limit for this particular request has been reached.
             // We use the laravel-built in RateLimiter for that.
             // The Key of the RateLimiter is a hash of the RequestObject and the client-IP.
             $rateLimiterKey = sha1($this->getRequestObject() . Request::ip());
             // A requestLimit of 0 means, a captcha is always required.
             if ($requestLimit === "0" || app(RateLimiter::class)->tooManyAttempts($rateLimiterKey, $requestLimit, $decayTime)) {
                 // If it has been reached, we must append a captcha-field.
                 // First we generate a captcha-question and an answer.
                 $captchaData = FormBuilderTools::generateCaptcha();
                 // Then we add the captcha-field to the output.
                 $this->output .= app()->make(InputText::class, ['_captcha'])->required(true)->value('')->label($captchaData['question'])->placeholder(trans('Nicat-HtmlBuilder::htmlbuilder.captchaPlaceholder'))->helpText(trans('Nicat-HtmlBuilder::htmlbuilder.captchaHelpText'))->generate();
                 // Furthermore we also set the required captcha-answer in the session.
                 // This is used when the CaptchaValidator actually checks the captcha.
                 Request::session()->put($sessionKeyForCaptchaData, $captchaData);
             }
         }
     }
 }
Пример #8
0
 public function dynamicList($arrayName = '', DynamicListTemplateContract $template, $addButtonLabel = '', $minItems = null, $maxItems = null)
 {
     $this->dynamicListArrayName = $arrayName;
     $this->dynamicListTemplate = $template;
     // Get the submitted base-array.
     $submittedArray = app()['formbuilder']->getSubmittedValueForField($this->dynamicListArrayName);
     // If $minItems or $maxItems was not set via arguments, we try to get them from the FormBuilder.
     if (is_null($minItems) || is_null($maxItems)) {
         // Get the array-rules from the formbuilder.
         $arrayRules = FormBuilderTools::explodeRules(app()['formbuilder']->getRulesForField($this->dynamicListArrayName));
         // Set minimum count of items from the gathered rules, or use default value.
         if (is_null($minItems) && isset($arrayRules['min'][0])) {
             $minItems = $arrayRules['min'][0];
         } else {
             $minItems = 1;
         }
         // Set maximum count of items from the gathered rules, or use default value.
         if (is_null($minItems) && isset($arrayRules['max'][0])) {
             $maxItems = $arrayRules['max'][0];
         } else {
             $maxItems = 10;
         }
     }
     // Set some basic stuff at the template.
     $this->dynamicListTemplate->isDynamicListTemplate = true;
     $this->dynamicListTemplate->performDynamicListModifications();
     $this->dynamicListTemplate->wrap(false);
     if (method_exists($this, 'labelMode')) {
         $this->dynamicListTemplate->labelMode('sr-only');
     }
     $this->dynamicListTemplate->data('dynamiclist-group', $this->dynamicListArrayName);
     // If data was submitted for this array, we have to add each submitted child using the same key it was submitted with.
     if (is_array($submittedArray) && count($submittedArray) > 0) {
         foreach ($submittedArray as $submittedChildKey => $submittedChild) {
             $this->addDynamicListChild($submittedChildKey);
         }
     } else {
         if (app('formbuilder')->getDefaultValueForField($this->dynamicListArrayName)) {
             foreach (app('formbuilder')->getDefaultValueForField($this->dynamicListArrayName) as $itemKey => $item) {
                 $this->addDynamicListChild($itemKey);
             }
         } else {
             $i = 0;
             while ($i < $minItems) {
                 $this->addDynamicListChild($i);
                 $i++;
             }
         }
     }
     // We must also add an empty template to be available for the javascript-functionality.
     $template = $this->dynamicListTemplate;
     $template->hidden();
     $template->data('dynamiclist-template', true);
     $this->addDynamicListChild('%itemID%', true);
     // Then we add the add-row button.
     if (!(strlen($addButtonLabel) > 0)) {
         $addButtonLabel = trans('Nicat-HtmlBuilder::htmlbuilder.dynamicListAddButtonTitle');
     }
     $button = new Button('addRow');
     $button->context('success')->addClass('btn-sm')->title($addButtonLabel)->data('dynamiclist-add', true)->data('dynamiclist-group', $this->dynamicListArrayName)->data('dynamiclist-min', $minItems)->data('dynamiclist-max', $maxItems)->content('<i class="fa fa-plus"></i> ' . $addButtonLabel);
     $this->appendChild($button);
     // We add the alert for maximum-reached.
     $alert = new DivAlertInfo();
     $alert->hidden()->content(trans('Nicat-HtmlBuilder::htmlbuilder.dynamicListMaximumReached'))->data('dynamiclist-maxalert', true)->data('dynamiclist-group', $this->dynamicListArrayName);
     $this->appendChild($alert);
     return $this;
 }