[ Index ] |
PHP Cross Reference of GlotPress |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Translation Validation API 4 * 5 * @package GlotPress 6 * @since 1.0.0 7 */ 8 9 /** 10 * Core class to handle validation of translations. 11 * 12 * Uses magic methods in the format of [field]_[rule]. 13 * 14 * The below is a list of all magic methods called to ensure Scrutinizer recognizes them. 15 * Note that once a method has been defined from one file it will not be redefine in subsequent file sections. 16 * 17 * From gp_includes/things/administrative-permissions.php: 18 * 19 * @method bool user_id_should_not_be( string $name, array $args = null ) 20 * @method bool action_should_not_be( string $name, array $args = null ) 21 * @method bool object_type_should_be( string $name, array $args = null ) 22 * @method bool object_id_should_be( string $name, array $args = null ) 23 * 24 * From gp_includes/things/glossary-entry.php: 25 * 26 * @method bool term_should_not_be( string $name, array $args = null ) 27 * @method bool part_of_speech_should_not_be( string $name, array $args = null ) 28 * @method bool glossary_id_should_be( string $name, array $args = null ) 29 * @method bool last_edited_by_should_be( string $name, array $args = null ) 30 * 31 * From gp_includes/things/original.php: 32 * 33 * @method bool singular_should_not_be( string $name, array $args = null ) 34 * @method bool status_should_not_be( string $name, array $args = null ) 35 * @method bool project_id_should_be( string $name, array $args = null ) 36 * @method bool priority_should_be( string $name, array $args = null ) 37 * 38 * From gp_includes/things/translation.php: 39 * 40 * @method bool translation_0_should_not_be( string $name, array $args = null ) 41 * @method bool original_id_should_be( string $name, array $args = null ) 42 * @method bool translation_set_id_should_be( string $name, array $args = null ) 43 * @method bool user_id_should_be( string $name, array $args = null ) 44 * @method bool user_id_last_modified_should_not_be( string $name, array $args = null ) 45 * 46 * From gp_includes/things/glossary.php: 47 * 48 * @method bool translation_set_id_should_not_be( string $name, array $args = null ) 49 * 50 * From gp_includes/things/project.php: 51 * 52 * @method bool name_should_not_be( string $name, array $args = null ) 53 * @method bool slug_should_not_be( string $name, array $args = null ) 54 * 55 * From gp_includes/things/translation-set.php: 56 * 57 * @method bool locale_should_not_be( string $name, array $args = null ) 58 * @method bool project_id_should_not_be( string $name, array $args = null ) 59 * 60 * From gp_includes/things/validator-permission.php: 61 * 62 * @method bool locale_slug_should_not_be( string $name, array $args = null ) 63 * @method bool user_id_should_not_be( string $name, array $args = null ) 64 * @method bool action_should_not_be( string $name, array $args = null ) 65 * @method bool set_slug_should_not_be( string $name, array $args = null ) 66 */ 67 class GP_Validation_Rules { 68 69 var $rules = array(); 70 71 public $errors = array(); 72 public $field_names; 73 74 static $positive_suffices = array( 75 'should_be', 76 'should', 77 'can', 78 'can_be', 79 ); 80 static $negative_suffices = array( 81 'should_not_be', 82 'should_not', 83 'cant', 84 'cant_be', 85 ); 86 87 public function __construct( $field_names ) { 88 $this->field_names = $field_names; 89 } 90 91 public function __call( $name, $args ) { 92 foreach ( array( 'positive', 'negative' ) as $kind ) { 93 $suffices = "{$kind}_suffices"; 94 foreach ( self::$$suffices as $suffix ) { 95 foreach ( $this->field_names as $field_name ) { 96 if ( "{$field_name}_{$suffix}" == $name ) { 97 $this->rules[ $field_name ][] = array( 98 'field' => $field_name, 99 'rule' => $args[0], 100 'kind' => $kind, 101 'args' => array_slice( $args, 1 ), 102 ); 103 return true; 104 } 105 } 106 } 107 } 108 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error 109 trigger_error( 110 sprintf( 111 /* translators: 1: Class name, 2: method name. */ 112 'Call to undefined method: %1$::%2$().', 113 esc_html( get_class( $this ) ), 114 esc_html( $name ) 115 ), 116 E_USER_ERROR 117 ); 118 } 119 120 public function run( $thing ) { 121 $this->errors = array(); 122 $verdict = true; 123 foreach ( $this->field_names as $field_name ) { 124 // Do not try to validate missing fields. 125 if ( ! gp_object_has_var( $thing, $field_name ) ) { 126 continue; 127 } 128 $value = $thing->$field_name; 129 $field_verdict = $this->run_on_single_field( $field_name, $value ); 130 $verdict = $verdict && $field_verdict; 131 } 132 return $verdict; 133 } 134 135 public function run_on_single_field( $field, $value ) { 136 if ( ! isset( $this->rules[ $field ] ) || ! is_array( $this->rules[ $field ] ) ) { 137 // No rules means always valid. 138 return true; 139 } 140 $verdict = true; 141 142 foreach ( $this->rules[ $field ] as $rule ) { 143 $callback = GP_Validators::get( $rule['rule'] ); 144 if ( is_null( $callback ) ) { 145 // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error 146 trigger_error( 147 sprintf( 148 /* translators: %s: Rule. */ 149 __( 'Non-existent validator: %s', 'glotpress' ), 150 esc_html( $rule['rule'] ) 151 ), 152 WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE 153 ); 154 continue; 155 } 156 $args = $rule['args']; 157 array_unshift( $args, $value ); 158 if ( 'positive' === $rule['kind'] ) { 159 if ( ! $callback['positive']( ...$args ) ) { 160 $this->errors[] = $this->construct_error_message( $rule ); 161 $verdict = false; 162 } 163 } else { 164 if ( null === $callback['negative'] ) { 165 if ( $callback['positive']( ...$args ) ) { 166 $this->errors[] = $this->construct_error_message( $rule ); 167 $verdict = false; 168 } 169 } elseif ( ! $callback['negativ']( ...$args ) ) { 170 $this->errors[] = $this->construct_error_message( $rule ); 171 $verdict = false; 172 } 173 } 174 } 175 return $verdict; 176 } 177 178 public function construct_error_message( $rule ) { 179 $type_field = 'field'; 180 $name_field = $rule['field']; 181 $name_rule = str_replace( '_', ' ', $rule['rule'] ); 182 183 if ( 1 === preg_match( '/translation_[0-9]/', $name_field ) ) { 184 $type_field = 'textarea'; 185 $name_field = 'Translation ' . ( intval( substr( $name_field, 12 ) ) + 1 ); 186 } 187 188 if ( 'positive' == $rule['kind'] ) { 189 /* translators: 1: type of a validation field, 2: name of a validation field, 3: validation rule */ 190 return sprintf( __( 'The %1$s %2$s is invalid and should be %3$s!', 'glotpress' ), $type_field, '<strong>' . $name_field . '</strong>', $name_rule ); 191 } else { // if ( 'negative' == $rule['kind'] ) 192 /* translators: 1: type of a validation field, 2: name of a validation field, 3: validation rule */ 193 return sprintf( __( 'The %1$s %2$s is invalid and should not be %3$s!', 'glotpress' ), $type_field, '<strong>' . $name_field . '</strong>', $name_rule ); 194 } 195 } 196 } 197 198 class GP_Validators { 199 static $callbacks = array(); 200 201 public static function register( $key, $callback, $negative_callback = null ) { 202 // TODO: add data for easier generation of error messages 203 self::$callbacks[ $key ] = array( 204 'positive' => $callback, 205 'negative' => $negative_callback, 206 ); 207 } 208 209 public static function unregister( $key ) { 210 unset( self::$callbacks[ $key ] ); 211 } 212 213 public static function get( $key ) { 214 return gp_array_get( self::$callbacks, $key, null ); 215 } 216 } 217 218 GP_Validators::register( 'empty', 'gp_is_empty' ); 219 GP_Validators::register( 'empty_string', 'gp_is_empty_string' ); 220 GP_Validators::register( 'positive_int', 'gp_is_positive_int' ); 221 GP_Validators::register( 'int', 'gp_is_int' ); 222 GP_Validators::register( 'null', 'gp_is_null' ); 223 GP_Validators::register( 'between', 'gp_is_between' ); 224 GP_Validators::register( 'between_exclusive', 'gp_is_between_exclusive' );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Apr 21 01:02:02 2021 | Cross-referenced by PHPXref 0.7.1 |