2007-07-19 12:40:28 +02:00
|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* This validation class handles all form and custom form validation through
|
|
|
|
* the use of Required fields.
|
2008-03-06 03:06:47 +01:00
|
|
|
*
|
2007-07-19 12:40:28 +02:00
|
|
|
* Relies on javascript for client-side validation, and marking fields after serverside validation.
|
|
|
|
*
|
2008-03-06 03:06:47 +01:00
|
|
|
* Acts as a visitor to individual form fields.
|
|
|
|
*
|
2008-01-11 02:49:50 +01:00
|
|
|
* @todo Automatically mark fields after serverside validation and replace the form through
|
2007-07-19 12:40:28 +02:00
|
|
|
* FormResponse if the request was made by ajax.
|
|
|
|
*
|
2008-01-09 05:18:36 +01:00
|
|
|
* @package forms
|
|
|
|
* @subpackage validators
|
|
|
|
*/
|
2007-07-19 12:40:28 +02:00
|
|
|
abstract class Validator extends Object {
|
2009-03-03 03:24:29 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @var Form $form
|
|
|
|
*/
|
2007-07-19 12:40:28 +02:00
|
|
|
protected $form;
|
2009-03-03 03:24:29 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @var array $errors
|
|
|
|
*/
|
2007-07-19 12:40:28 +02:00
|
|
|
protected $errors;
|
2008-08-18 02:07:37 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Static for default value of $this->javascriptValidationHandler.
|
|
|
|
* Set with Validator::set_javascript_validation_handler();
|
2009-03-03 03:24:29 +01:00
|
|
|
* @var string
|
2008-08-18 02:07:37 +02:00
|
|
|
*/
|
2009-03-03 03:24:29 +01:00
|
|
|
protected static $javascript_validation_handler = "prototype";
|
2008-08-18 02:07:37 +02:00
|
|
|
|
|
|
|
/**
|
2009-03-03 03:24:29 +01:00
|
|
|
* Handler for javascript validation. Can be "prototype" or "none".
|
|
|
|
* @var string
|
2008-08-18 02:07:37 +02:00
|
|
|
*/
|
2009-03-03 03:24:29 +01:00
|
|
|
protected $javascriptValidationHandler = null;
|
2008-08-18 02:07:37 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Call this function to set the javascript validation handler for all valdiation on your site.
|
|
|
|
* This could be called from _config.php to set site-wide javascript validation, or from ContentController::init()
|
|
|
|
* to affect only the front-end site.
|
2009-03-03 03:24:29 +01:00
|
|
|
* Use instance method {@link setJavascriptValidationHandler()} to
|
|
|
|
* only set handler for a specific form instance.
|
2008-08-18 02:07:37 +02:00
|
|
|
*
|
|
|
|
* @param $handler A string representing the handler to use: 'prototype' or 'none'.
|
|
|
|
* @todo Add 'jquery' as a handler option.
|
|
|
|
*/
|
2009-03-03 03:24:29 +01:00
|
|
|
public static function set_javascript_validation_handler($handler) {
|
|
|
|
if($handler == 'prototype' || $handler == 'none') {
|
|
|
|
self::$javascript_validation_handler = $handler;
|
|
|
|
} else {
|
|
|
|
user_error("Validator::setJavascriptValidationHandler() passed bad handler '$handler'", E_USER_WARNING);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns global validation handler used for all forms by default,
|
|
|
|
* unless overwritten by {@link setJavascriptValidationHandler()}.
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public static function get_javascript_validator_handler() {
|
|
|
|
return self::$javascript_validation_handler;
|
2008-08-18 02:07:37 +02:00
|
|
|
}
|
2007-07-19 12:40:28 +02:00
|
|
|
|
2008-08-18 02:07:37 +02:00
|
|
|
/**
|
2009-03-03 03:24:29 +01:00
|
|
|
* Set JavaScript validation for this validator.
|
|
|
|
* Use static method {@link set_javascript_validation_handler()}
|
|
|
|
* to set handlers globally.
|
|
|
|
*
|
|
|
|
* @param string $handler
|
2008-08-18 02:07:37 +02:00
|
|
|
*/
|
|
|
|
public function setJavascriptValidationHandler($handler) {
|
|
|
|
if($handler == 'prototype' || $handler == 'none') {
|
2009-03-03 03:24:29 +01:00
|
|
|
$this->javascriptValidationHandler = $handler;
|
2008-08-18 02:07:37 +02:00
|
|
|
} else {
|
|
|
|
user_error("Validator::setJavascriptValidationHandler() passed bad handler '$handler'", E_USER_WARNING);
|
|
|
|
}
|
|
|
|
}
|
2009-03-03 03:24:29 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the current javascript validation handler for this form.
|
|
|
|
* If not set, falls back to the global static {@link self::$javascript_validation_handler}.
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function getJavascriptValidationHandler() {
|
|
|
|
return ($this->javascriptValidationHandler) ? $this->javascriptValidationHandler : self::$javascript_validation_handler;
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
|
|
|
|
2009-03-03 03:24:29 +01:00
|
|
|
/**
|
|
|
|
* @param Form $form
|
|
|
|
*/
|
2007-07-19 12:40:28 +02:00
|
|
|
function setForm($form) {
|
|
|
|
$this->form = $form;
|
|
|
|
}
|
|
|
|
|
2009-03-03 03:24:29 +01:00
|
|
|
/**
|
|
|
|
* @return array Errors (if any)
|
|
|
|
*/
|
2007-07-19 12:40:28 +02:00
|
|
|
function validate(){
|
|
|
|
$this->errors = null;
|
|
|
|
$this->php($this->form->getData());
|
|
|
|
|
|
|
|
return $this->errors;
|
|
|
|
}
|
|
|
|
|
2008-03-06 03:06:47 +01:00
|
|
|
/**
|
|
|
|
* Callback to register an error on a field (Called from implementations of {@link FormField::validate})
|
|
|
|
*
|
|
|
|
* @param $fieldName name of the field
|
|
|
|
* @param $message error message to display
|
2009-03-12 17:47:29 +01:00
|
|
|
* @param $messageType optional parameter, gets loaded into the HTML class attribute in the rendered output. See {@link getErrors()} for details.
|
2008-03-06 03:06:47 +01:00
|
|
|
*/
|
2009-03-12 17:47:29 +01:00
|
|
|
function validationError($fieldName, $message, $messageType='') {
|
2007-07-19 12:40:28 +02:00
|
|
|
$this->errors[] = array(
|
|
|
|
'fieldName' => $fieldName,
|
|
|
|
'message' => $message,
|
|
|
|
'messageType' => $messageType,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2009-03-03 03:24:29 +01:00
|
|
|
/**
|
2009-03-12 17:47:29 +01:00
|
|
|
* @deprecated 2.4 Use Validator->getErrors() and custom code
|
2009-03-03 03:24:29 +01:00
|
|
|
*/
|
2009-02-03 06:14:04 +01:00
|
|
|
function showError() {
|
|
|
|
Debug::show($this->errors);
|
2007-08-23 07:47:54 +02:00
|
|
|
}
|
|
|
|
|
2009-03-12 17:47:29 +01:00
|
|
|
/**
|
|
|
|
* @deprecated 2.4 Use custom code
|
|
|
|
*/
|
2007-08-23 07:47:54 +02:00
|
|
|
function getCombinedError(){
|
|
|
|
if($this->errors) {
|
|
|
|
foreach($this->errors as $error){
|
|
|
|
$ret['message'] .= $error['message']."<br />";
|
|
|
|
$ret['messageType'] .= $error['messageType']."<br />";
|
|
|
|
}
|
|
|
|
|
|
|
|
return $ret;
|
|
|
|
}
|
|
|
|
}
|
2009-03-12 17:47:29 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @deprecated 2.4 Use getErrors()
|
|
|
|
*/
|
2007-08-23 07:47:54 +02:00
|
|
|
function getError(){
|
2009-03-12 17:47:29 +01:00
|
|
|
return $this->getErrors();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns all errors found by a previous call to {@link validate()}.
|
|
|
|
* The array contains the following keys for each error:
|
|
|
|
* - 'fieldName': the name of the FormField instance
|
|
|
|
* - 'message': Validation message (optionally localized)
|
|
|
|
* - 'messageType': Arbitrary type of the message which is rendered as a CSS class in the FormField template,
|
|
|
|
* e.g. <span class="message (type)">. Usually "bad|message|validation|required", which renders differently
|
|
|
|
* if sapphire/css/Form.css is included.
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
function getErrors() {
|
2007-08-23 07:47:54 +02:00
|
|
|
return $this->errors;
|
|
|
|
}
|
|
|
|
|
2007-07-19 12:40:28 +02:00
|
|
|
function requireField($fieldName, $data) {
|
|
|
|
if(!$data[$fieldName]) $this->validationError($fieldName, "$fieldName is required", "required");
|
|
|
|
}
|
|
|
|
|
|
|
|
function includeJavascriptValidation() {
|
2009-03-03 03:24:29 +01:00
|
|
|
if($this->getJavascriptValidationHandler() == 'prototype') {
|
ENHANCEMENT Introduced constants for system paths like /sapphire in preparation for a more flexible directory reorganisation. Instead of hardcoding your path, please use the following constants: BASE_PATH, BASE_URL, SAPPHIRE_DIR, SAPPHIRE_PATH, CMS_DIR, CMS_PATH, THIRDPARTY_DIR, THIRDPARTY_PATH, ASSETS_DIR, ASSETS_PATH, THEMES_DIR, THEMES_PATH
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@63154 467b73ca-7a2a-4603-9d3b-597d59a354a9
2008-09-27 18:02:38 +02:00
|
|
|
Requirements::javascript(THIRDPARTY_DIR . "/prototype.js");
|
|
|
|
Requirements::javascript(THIRDPARTY_DIR . "/behaviour.js");
|
|
|
|
Requirements::javascript(THIRDPARTY_DIR . "/prototype_improvements.js");
|
2009-03-10 23:08:52 +01:00
|
|
|
Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang');
|
ENHANCEMENT Introduced constants for system paths like /sapphire in preparation for a more flexible directory reorganisation. Instead of hardcoding your path, please use the following constants: BASE_PATH, BASE_URL, SAPPHIRE_DIR, SAPPHIRE_PATH, CMS_DIR, CMS_PATH, THIRDPARTY_DIR, THIRDPARTY_PATH, ASSETS_DIR, ASSETS_PATH, THEMES_DIR, THEMES_PATH
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@63154 467b73ca-7a2a-4603-9d3b-597d59a354a9
2008-09-27 18:02:38 +02:00
|
|
|
Requirements::javascript(SAPPHIRE_DIR . "/javascript/Validator.js");
|
2008-08-18 02:07:37 +02:00
|
|
|
|
|
|
|
$code = $this->javascript();
|
|
|
|
$formID = $this->form->FormName();
|
|
|
|
$js = <<<JS
|
2007-07-19 12:40:28 +02:00
|
|
|
Behaviour.register({
|
|
|
|
'#$formID': {
|
|
|
|
validate : function(fromAnOnBlur) {
|
|
|
|
initialiseForm(this, fromAnOnBlur);
|
|
|
|
$code
|
2009-03-10 23:17:26 +01:00
|
|
|
|
2007-07-19 12:40:28 +02:00
|
|
|
var error = hasHadFormError();
|
|
|
|
if(!error && fromAnOnBlur) clearErrorMessage(fromAnOnBlur);
|
2009-03-10 23:17:26 +01:00
|
|
|
if(error && !fromAnOnBlur) focusOnFirstErroredField();
|
2007-07-19 12:40:28 +02:00
|
|
|
|
|
|
|
return !error;
|
|
|
|
},
|
|
|
|
onsubmit : function() {
|
2007-11-19 02:52:13 +01:00
|
|
|
if(typeof this.bypassValidation == 'undefined' || !this.bypassValidation) return this.validate();
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
'#$formID input' : {
|
|
|
|
initialise: function() {
|
|
|
|
if(!this.old_onblur) this.old_onblur = function() { return true; }
|
|
|
|
if(!this.old_onfocus) this.old_onfocus = function() { return true; }
|
|
|
|
},
|
|
|
|
onblur : function() {
|
|
|
|
if(this.old_onblur()) {
|
2008-11-10 04:51:35 +01:00
|
|
|
// Don't perform instant validation for CalendarDateField fields; it creates usability wierdness.
|
|
|
|
if(this.parentNode.className.indexOf('calendardate') == -1 || this.value) {
|
|
|
|
return $('$formID').validate(this);
|
|
|
|
} else {
|
|
|
|
return true;
|
|
|
|
}
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
'#$formID select' : {
|
|
|
|
initialise: function() {
|
|
|
|
if(!this.old_onblur) this.old_onblur = function() { return true; }
|
|
|
|
},
|
|
|
|
onblur : function() {
|
|
|
|
if(this.old_onblur()) {
|
|
|
|
return $('$formID').validate(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
JS;
|
|
|
|
|
2008-08-18 02:07:37 +02:00
|
|
|
Requirements::customScript($js);
|
|
|
|
// HACK Notify the form that the validators client-side validation code has already been included
|
|
|
|
if($this->form) $this->form->jsValidationIncluded = true;
|
|
|
|
}
|
2007-07-19 12:40:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns true if the named field is "required".
|
|
|
|
* Used by FormField to return a value for FormField::Required(), to do things like show *s on the form template.
|
|
|
|
* By default, it always returns false.
|
|
|
|
*/
|
|
|
|
function fieldIsRequired($fieldName) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
abstract function javascript();
|
|
|
|
|
|
|
|
abstract function php($data);
|
|
|
|
}
|
2009-03-10 23:08:52 +01:00
|
|
|
?>
|