field_names = $field_names;
}
public 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 ( "{$field_name}_{$suffix}" == $name ) {
$this->rules[ $field_name ][] = array(
'field' => $field_name,
'rule' => $args[0],
'kind' => $kind,
'args' => array_slice( $args, 1 ),
);
return true;
}
}
}
}
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error
trigger_error(
sprintf(
/* translators: %s: Method name. */
esc_html__( 'Call to undefined method: %s.', 'glotpress' ),
sprintf(
'%1$s::%2$s()',
esc_html( get_class( $this ) ),
esc_html( $name )
)
),
E_USER_ERROR
);
}
public 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;
}
public 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 ) ) {
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error
trigger_error(
sprintf(
/* translators: %s: Rule. */
__( 'Non-existent validator: %s', 'glotpress' ),
esc_html( $rule['rule'] )
),
WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE
);
continue;
}
$args = $rule['args'];
array_unshift( $args, $value );
if ( 'positive' === $rule['kind'] ) {
if ( ! $callback['positive']( ...$args ) ) {
$this->errors[] = $this->construct_error_message( $rule );
$verdict = false;
}
} else {
if ( null === $callback['negative'] ) {
if ( $callback['positive']( ...$args ) ) {
$this->errors[] = $this->construct_error_message( $rule );
$verdict = false;
}
} elseif ( ! $callback['negative']( ...$args ) ) {
$this->errors[] = $this->construct_error_message( $rule );
$verdict = false;
}
}
}
return $verdict;
}
public function construct_error_message( $rule ) {
$type_field = 'field';
$name_field = $rule['field'];
$name_rule = str_replace( '_', ' ', $rule['rule'] );
if ( 1 === preg_match( '/translation_[0-9]/', $name_field ) ) {
$type_field = 'textarea';
$name_field = 'Translation ' . ( intval( substr( $name_field, 12 ) ) + 1 );
}
if ( 'positive' == $rule['kind'] ) {
/* translators: 1: type of a validation field, 2: name of a validation field, 3: validation rule */
return sprintf( __( 'The %1$s %2$s is invalid and should be %3$s!', 'glotpress' ), $type_field, '' . $name_field . '', $name_rule );
} else { // if ( 'negative' == $rule['kind'] )
/* translators: 1: type of a validation field, 2: name of a validation field, 3: validation rule */
return sprintf( __( 'The %1$s %2$s is invalid and should not be %3$s!', 'glotpress' ), $type_field, '' . $name_field . '', $name_rule );
}
}
}
class GP_Validators {
static $callbacks = array();
public 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,
);
}
public static function unregister( $key ) {
unset( self::$callbacks[ $key ] );
}
public 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' );
GP_Validators::register( 'one_of', 'gp_is_one_of' );
GP_Validators::register( 'consisting_only_of_ASCII_characters', 'gp_is_ascii_string' );
GP_Validators::register( 'starting_and_ending_with_a_word_character', 'gp_is_starting_and_ending_with_a_word_character' );