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