Skip to content

Instantly share code, notes, and snippets.

@Zauberfisch
Last active August 29, 2015 14:13
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Zauberfisch/a4df461ca9d82be7005a to your computer and use it in GitHub Desktop.
Save Zauberfisch/a4df461ca9d82be7005a to your computer and use it in GitHub Desktop.
Better SilverStripe Form Validator
<?php
/**
* @author zauberfisch
*/
class BaseValidator extends Validator {
protected $validateFields, $requireFields;
/**
* @param bool|string[]|\FormField[]|\FieldList $validateFields
* @param bool|string[]|\FormField[]|\FieldList $requireFields
*/
public function __construct($validateFields = true, $requireFields = false) {
$this->validateFields = $validateFields;
$this->requireFields = $requireFields;
parent::__construct();
}
/**
* @return array Errors (if any)
*/
public function validate(){
$this->errors = null;
$valid = $this->php($this->form->getData());
if (!$valid && !$this->errors) {
// hack workaround to make "return false;" in ->php() work
$this->errors = [[]];
}
return $this->errors;
}
/**
* @param array $data
* @return bool
*/
public function php($data) {
$valid = true;
if ($this->validateFields) {
$valid = $this->validateFields($this->validateFields) && $valid;
}
if ($this->requireFields) {
$valid = $this->requireFields($this->requireFields, $data) && $valid;
}
return $valid;
}
/**
* @param null|string[]|\FormField[]|\FieldList $fields
* @return bool
*/
public function validateFields($fields = null) {
if (!is_array($fields) && !(is_object($fields) && $fields->is_a('FieldList'))) {
$fields = $this->form->Fields();
}
$valid = true;
foreach ($fields as $field) {
$valid = $this->validateField($field) && $valid;
}
return $valid;
}
/**
* @param string|\FormField $field
* @return bool
*/
public function validateField($field) {
return $this->getField($field)[0]->validate($this);
}
/**
* @param null|string[]|\FormField[]|\FieldList $fields
* @param array $data
* @return bool
*/
public function requireFields($fields = null, $data) {
if (!is_array($fields) && !(is_object($fields) && $fields->is_a('FieldList'))) {
$fields = $this->form->Fields();
}
$valid = true;
foreach ($fields as $field) {
$valid = ($this->requireField($field, $data) && $valid);
}
return $valid;
}
/**
* @param string|\FormField $field
* @param array $data
* @return bool
*/
public function requireField($field, $data) {
list($field, $fieldName) = $this->getField($field);
if (!isset($data[$fieldName]) || !$data[$fieldName]) {
$this->validationError(
$fieldName,
_t(
'Form.FIELDISREQUIRED',
'{name} is required',
['name' => strip_tags('"' . ($field->Title() ? $field->Title() : $fieldName) . '"')]
),
'required'
);
return false;
}
return true;
}
/**
* @param \FormField|string $field
* @return array
*/
protected function getField($field) {
if (is_object($field) && $field->is_a('FormField')) {
$fieldName = $field->getName();
} else {
$fieldName = $field;
$field = $this->form->Fields()->dataFieldByName($field);
}
return [$field, $fieldName];
}
/**
* @param string $fieldName
* @param string $message
* @param string $messageType
*/
public function validationError($fieldName, $message, $messageType = '') {
parent::validationError($fieldName, $message, $messageType);
}
}
<?php
/**
* @author zauberfisch
*/
class LambdaValidator extends BaseValidator {
protected $callback, $validateFields, $requireFields;
/**
* @param callable $callback
* @param bool|string[]|\FormField[]|\FieldList $validateFields
* @param bool|string[]|\FormField[]|\FieldList $requireFields
*/
public function __construct(callable $callback, $validateFields = true, $requireFields = false) {
$this->callback = $callback;
parent::__construct($validateFields, $requireFields);
}
/**
* @param array $data
* @return bool
*/
public function php($data) {
$valid = parent::php($data);
$valid = call_user_func($this->callback, $data, $this->form, $this) && $valid;
return $valid;
}
}
@Zauberfisch
Copy link
Author

example:

$validateAllFieldsByDefault = false;
$requireAllFieldsByDefault = false;
$callback = function ($data, Form $form, LambdaValidator $validator) {
    $valid = true;
    // check if a field is valid (will call EmailField->validate()) (eg make sure an email address is valid)
    // this will be valid if EmailField->validate() returns true or if the field is empty
    // only nececary if $validateAllFieldsByDefault is valse, otherwise the validator will do it on all fields
    $valid = $validator->validateField('Email') && $valid;
    // ensure the field is not empty
    // only nececary if $validateAllFieldsByDefault is valse, otherwise the validator will do it on all fields
    $valid = $validator->requireField('Email') && $valid;

    if ($valid) {
        // lets disallow @example.com
        $parts = explode('@', $data['Email']);
        if ($parts[1] == 'example.com') {
            $validator->validationError(
                'Email', // name of the field
                _t('Account.ExampleEmail', 'E-Mail Addresses of example.com are not allowed here'), // message
                'required' // message type
            );
            $valid = false;
        }
    }
    return $valid;
};
$validator = new LambdaValidator($callback, $validateAllFieldsByDefault, $requireAllFieldsByDefault);

$form = new Form($this, $name, $fields, $actions, $validator);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment