[ Index ]

PHP Cross Reference of GlotPress

title

Body

[close]

/gp-includes/ -> validation.php (source)

   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.
  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: %s: Method name. */
 112                  esc_html__( 'Call to undefined method: %s.', 'glotpress' ),
 113                  sprintf(
 114                      '%1$s::%2$s()',
 115                      esc_html( get_class( $this ) ),
 116                      esc_html( $name )
 117                  )
 118              ),
 119              E_USER_ERROR
 120          );
 121      }
 122  
 123  	public function run( $thing ) {
 124          $this->errors = array();
 125          $verdict      = true;
 126          foreach ( $this->field_names as $field_name ) {
 127              // Do not try to validate missing fields.
 128              if ( ! gp_object_has_var( $thing, $field_name ) ) {
 129                  continue;
 130              }
 131              $value         = $thing->$field_name;
 132              $field_verdict = $this->run_on_single_field( $field_name, $value );
 133              $verdict       = $verdict && $field_verdict;
 134          }
 135          return $verdict;
 136      }
 137  
 138  	public function run_on_single_field( $field, $value ) {
 139          if ( ! isset( $this->rules[ $field ] ) || ! is_array( $this->rules[ $field ] ) ) {
 140              // No rules means always valid.
 141              return true;
 142          }
 143          $verdict = true;
 144  
 145          foreach ( $this->rules[ $field ] as $rule ) {
 146              $callback = GP_Validators::get( $rule['rule'] );
 147              if ( is_null( $callback ) ) {
 148                  // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error
 149                  trigger_error(
 150                      sprintf(
 151                          /* translators: %s: Rule. */
 152                          __( 'Non-existent validator: %s', 'glotpress' ),
 153                          esc_html( $rule['rule'] )
 154                      ),
 155                      WP_DEBUG ? E_USER_WARNING : E_USER_NOTICE
 156                  );
 157                  continue;
 158              }
 159              $args = $rule['args'];
 160              array_unshift( $args, $value );
 161              if ( 'positive' === $rule['kind'] ) {
 162                  if ( ! $callback['positive']( ...$args ) ) {
 163                      $this->errors[] = $this->construct_error_message( $rule );
 164                      $verdict        = false;
 165                  }
 166              } else {
 167                  if ( null === $callback['negative'] ) {
 168                      if ( $callback['positive']( ...$args ) ) {
 169                          $this->errors[] = $this->construct_error_message( $rule );
 170                          $verdict        = false;
 171                      }
 172                  } elseif ( ! $callback['negative']( ...$args ) ) {
 173                      $this->errors[] = $this->construct_error_message( $rule );
 174                      $verdict        = false;
 175                  }
 176              }
 177          }
 178          return $verdict;
 179      }
 180  
 181  	public function construct_error_message( $rule ) {
 182          $type_field = 'field';
 183          $name_field = $rule['field'];
 184          $name_rule  = str_replace( '_', ' ', $rule['rule'] );
 185  
 186          if ( 1 === preg_match( '/translation_[0-9]/', $name_field ) ) {
 187              $type_field = 'textarea';
 188              $name_field = 'Translation ' . ( intval( substr( $name_field, 12 ) ) + 1 );
 189          }
 190  
 191          if ( 'positive' == $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 be %3$s!', 'glotpress' ), $type_field, '<strong>' . $name_field . '</strong>', $name_rule );
 194          } else { // if ( 'negative' == $rule['kind'] )
 195              /* translators: 1: type of a validation field, 2: name of a validation field, 3: validation rule */
 196              return sprintf( __( 'The %1$s %2$s is invalid and should not be %3$s!', 'glotpress' ), $type_field, '<strong>' . $name_field . '</strong>', $name_rule );
 197          }
 198      }
 199  }
 200  
 201  class GP_Validators {
 202      static $callbacks = array();
 203  
 204  	public static function register( $key, $callback, $negative_callback = null ) {
 205          // TODO: add data for easier generation of error messages
 206          self::$callbacks[ $key ] = array(
 207              'positive' => $callback,
 208              'negative' => $negative_callback,
 209          );
 210      }
 211  
 212  	public static function unregister( $key ) {
 213          unset( self::$callbacks[ $key ] );
 214      }
 215  
 216  	public static function get( $key ) {
 217          return gp_array_get( self::$callbacks, $key, null );
 218      }
 219  }
 220  
 221  GP_Validators::register( 'empty', 'gp_is_empty' );
 222  GP_Validators::register( 'empty_string', 'gp_is_empty_string' );
 223  GP_Validators::register( 'positive_int', 'gp_is_positive_int' );
 224  GP_Validators::register( 'int', 'gp_is_int' );
 225  GP_Validators::register( 'null', 'gp_is_null' );
 226  GP_Validators::register( 'between', 'gp_is_between' );
 227  GP_Validators::register( 'between_exclusive', 'gp_is_between_exclusive' );
 228  GP_Validators::register( 'one_of', 'gp_is_one_of' );
 229  GP_Validators::register( 'consisting_only_of_ASCII_characters', 'gp_is_ascii_string' );
 230  GP_Validators::register( 'starting_and_ending_with_a_word_character', 'gp_is_starting_and_ending_with_a_word_character' );


Generated: Wed Apr 24 01:01:14 2024 Cross-referenced by PHPXref 0.7.1