field_names = $field_names; } function __call( $name, $args ) { foreach( array( 'positive', 'negative' ) as $kind ) { $suffices = "{$kind}_suffices"; foreach( self::$$suffices as $suffix ) { foreach( $this->field_names as $field_name ) { if ( $name == "{$field_name}_{$suffix}" ) { $this->rules[$field_name][] = array( 'field' => $field_name, 'rule' => $args[0], 'kind' => $kind, 'args' => array_slice( $args, 1 ) ); return true; } } } } trigger_error(sprintf('Call to undefined function: %s::%s().', get_class($this), $name), E_USER_ERROR); } function run( $thing ) { $this->errors = array(); $verdict = true; foreach( $this->field_names as $field_name ) { // do not try to validate missing fields if ( !gp_object_has_var( $thing, $field_name ) ) continue; $value = $thing->$field_name; $field_verdict = $this->run_on_single_field( $field_name, $value ); $verdict = $verdict && $field_verdict; } return $verdict; } function run_on_single_field( $field, $value ) { if ( !isset( $this->rules[$field] ) || !is_array( $this->rules[$field] ) ) { // no rules means always valid return true; } $verdict = true; foreach( $this->rules[$field] as $rule ) { $callback = GP_Validators::get( $rule['rule'] ); if ( is_null( $callback ) ) { trigger_error( __('Non-existent validator: ' . $rule['rule'] ) ); continue; } $args = $rule['args']; array_unshift( $args, $value ); if ( 'positive' == $rule['kind'] ) { if ( !call_user_func_array( $callback['positive'], $args ) ) { $this->errors[] = $this->construct_error_message( $rule, $value ); $verdict = false; } } else { if ( is_null( $callback['negative'] ) ) { if ( call_user_func_array( $callback['positive'], $args ) ) { $this->errors[] = $this->construct_error_message( $rule, $value ); $verdict = false; } } else if ( !call_user_func_array( $callback['negative'], $args ) ) { $this->errors[] = $this->construct_error_message( $rule, $value ); $verdict = false; } } } return $verdict; } function construct_error_message( $rule, $value ) { $type_field = 'field'; $name_field = $rule['field']; $name_rule = str_replace( '_', ' ', $rule['rule'] ); if( strpos( $name_field, 'translation_' ) === 0 ) { $type_field = 'textarea'; $name_field = 'Translation ' . ( intval( substr( $name_field, 12 ) ) + 1 ); } if ( 'positive' == $rule['kind'] ) return sprintf( __('The %s %s is invalid and should be %s!'), $type_field, $name_field, $name_rule ); else //if ( 'negative' == $rule['kind'] ) return sprintf( __('The %s %s is invalid and should not be %s!'), $type_field, $name_field, $name_rule ); } } class GP_Validators { static $callbacks = array(); static function register( $key, $callback, $negative_callback = null ) { // TODO: add data for easier generation of error messages self::$callbacks[$key] = array( 'positive' => $callback, 'negative' => $negative_callback ); } static function unregister( $key ) { unset( self::$callbacks[$key] ); } static function get( $key ) { return gp_array_get( self::$callbacks, $key, null ); } } GP_Validators::register( 'empty', 'gp_is_empty' ); GP_Validators::register( 'empty_string', 'gp_is_empty_string' ); GP_Validators::register( 'positive_int', 'gp_is_positive_int' ); GP_Validators::register( 'int', 'gp_is_int' ); GP_Validators::register( 'null', 'gp_is_null' ); GP_Validators::register( 'between', 'gp_is_between' ); GP_Validators::register( 'between_exclusive', 'gp_is_between_exclusive' );