Open wilr opened 11 years ago
Any progress on this issue which has reared its ugly head with me. I'm almost prepared to put up with no php validation at this point,.
No progress on it from me. Happy to review patches if you want to give it a go. If you want to disable PHP validation you may as well make the field not required and just put (required) as a label text or something.
If I'll try patching this at some point where should I start my searches for PHP side of validation. As I mentioned in #116 I couldn't find the place then...
The PHP side of validation uses the normal SilverStripe API. See UserDefinedForm::getRequiredFields(). One way would be to not use the core SilverStripe validate() method on form fields and manually invoke validate methods in the submit form method.
Since I just failed so spectacularly on identifying a jquery validation error, ironically because of this, I was wondering if anybody had any more to offer. I cant see a way round it other than to not require the conditional fields and the client is demanding that they are required. A problem and perhaps time for another custom form!
@tazzydemon What I would aim to do is ticking that required box in the cms didn't actually set the PHP required fields and validation is controlled after the rules are parsed in the form handler. I'm keen to build this when I can get around to funding it, if you want to tackle it PR's welcome.
Hi guys, i a little bit working on this. I created a method which is remove field from required fields if it's not pass the rules of dependencies. But this method need to be improved with radio, checkbox and checkbox groups.
here is the code userforms/code/model/UserDefinedForm.php
of UserDefinedForm_Controller
:
/**
* Method will checks all required fields within post data, and check did it
* need to remove field from required fields if field rules (dependencies) are negative.
*
* @param RequiredFields $requiredFields Set required fields
* @param array $post $_POST data
*
* @return bool | returns false when no post array are given and true when scripts end.
*/
public function requiredFieldsByRules(RequiredFields &$requiredFields, array $post = []) {
if(count($post) <= 0) return false;
foreach($requiredFields->getRequired() as $name) {
if(!isset($post[$name]) || empty($post[$name])) {
// field is required, but is not set or empty
// check the rules expression, maybe this field is hidden
if(($fields = $this->Fields()->filter('Name', $name)) && $fields->exists()) {
/** @var EditableFormField $field */
$field = $fields->first();
$remove = false;
foreach($field->CustomRules() as $rule) {
$rule = $rule->toMap();
$remove = (string) $rule['Display'] === 'Show' ? false : true;
$expectedValue = $rule['Value'];
$conditionFieldName = $rule['ConditionField'];
$postConditionFieldValue = isset($post[$conditionFieldName]) ? $post[$conditionFieldName] : '';
$conditionField = !empty($conditionFieldName) ? $this->Fields()->filter('Name', $conditionFieldName) : null;
if(!is_null($conditionField) && $conditionField->exists()) {
/** @var EditableFormField $conditionField */
$conditionField = $conditionField->first();
}
// todo: improve with radio, checkbox, and checkbox group inputs
switch($rule['ConditionOption']) {
case 'IsNotBlank':
if(empty($postConditionFieldValue)) {
$remove = !$remove;
}
break;
case 'IsBlank':
if(!empty($postConditionFieldValue)) {
$remove = !$remove;
}
break;
case 'HasValue':
if($postConditionFieldValue != $expectedValue) {
$remove = !$remove;
}
break;
case 'ValueLessThan':
if((float) $postConditionFieldValue >= (float) $expectedValue) {
$remove = !$remove;
}
break;
case 'ValueLessThanEqual':
if((float) $postConditionFieldValue > (float) $expectedValue) {
$remove = !$remove;
}
break;
case 'ValueGreaterThan':
if((float) $postConditionFieldValue <= (float) $expectedValue) {
$remove = !$remove;
}
break;
case 'ValueGreaterThanEqual':
if((float) $postConditionFieldValue < (float) $expectedValue) {
$remove = !$remove;
}
break;
default: // ==HasNotValue
if($postConditionFieldValue == $expectedValue) {
$remove = !$remove;
}
break;
}
}
if($remove) {
// remove field from required fields
$requiredFields->removeRequiredField($name);
}
}
}
}
return true;
}
and in the Form
method need to add this line:
// remove required fields if it's not pass the dependencies
$this->requiredFieldsByRules($required, Convert::raw2xml($_POST));
example:
/**
* Get the form for the page. Form can be modified by calling {@link updateForm()}
* on a UserDefinedForm extension.
*
* @return Form|false
*/
public function Form() {
$fields = $this->getFormFields();
if(!$fields || !$fields->exists()) return false;
$actions = $this->getFormActions();
// get the required fields including the validation
$required = $this->getRequiredFields();
// remove required fields if it's not pass the dependencies
$this->requiredFieldsByRules($required, Convert::raw2xml($_POST));
// generate the conditional logic
$this->generateConditionalJavascript();
$form = new Form($this, "Form", $fields, $actions, $required);
$form->setRedirectToFormOnValidationError(true);
$data = Session::get("FormInfo.{$form->FormName()}.data");
if(is_array($data)) $form->loadDataFrom($data);
$this->extend('updateForm', $form);
if($this->DisableCsrfSecurityToken) {
$form->disableSecurityToken();
}
return $form;
}
So when field will have a rules, this method will check is it set as required field and try to check if rules are negative.
@Doniz thanks for taking the time to do this - it may be best to move this discussion to a pull request - would you mind opening one with your code changes?
Another challenge to overcome is the configuration of jquery-validate on the frontend; It will require to be updated whenever field visibility is modified in order to not require hidden fields.
Also please note the PHP server side validation logic which fails when you mark a field as both required and having custom rules. :)
It's not going to be an easy challenge to solve in any case!
I'm going to downgrade this from a bug, as the bug of "required field is conditionally hidden" was actually prevented by the aforementioned validation rule. See https://github.com/silverstripe/silverstripe-userforms/blob/a3d425d443714157c23c3e393b8d0d498f12a3b2/code/model/editableformfields/EditableFormField.php#L238
Has anyone had any more thoughts on this since SS4 was released? Had a couple of clients keen to do this, but understand the current limitation.. Wondering if SS4 might make it any more possible?
From https://github.com/silverstripe/silverstripe-userforms/issues/116
Create textfield test. Create new textfield test1. Mark it required & set it to hide by default. Add custom rule to test1: Show This Field When test is Value test
Try submitting the form with field test set to check. The form won't validate. Now set it to test. Field test1 appears correctly. And if it is unset, the form won't pass validation. Setting test1 validates the form.