tier-pricing-table
/
src
/
Addons
/
NonLoggedInUsers
/
Wholesale
/
Services
/
ApplicationValidator.php
ApplicationValidator.php in Tiered Pricing Table for WooCommerce 8.0.2, at src/Addons/NonLoggedInUsers/Wholesale/Services/ApplicationValidator.php
| 1 | <?php namespace TierPricingTable\Addons\NonLoggedInUsers\Wholesale\Services; |
| 2 | |
| 3 | /** |
| 4 | * Validates and sanitizes the registration form input. Pure: the environment (the form's fields, |
| 5 | * whether an e-mail is taken) is passed in, so it can be unit-tested without WordPress. |
| 6 | */ |
| 7 | class ApplicationValidator { |
| 8 | |
| 9 | const MIN_PASSWORD_LENGTH = 8; |
| 10 | |
| 11 | /** |
| 12 | * @param array $input raw form values |
| 13 | * @param array $config { |
| 14 | * @type array $fields the form's fields: [ key, label, type, required, options ] each |
| 15 | * @type bool $isGuest true when a new customer account has to be created |
| 16 | * @type bool $needsPassword true when the form asks for a password |
| 17 | * @type bool $needsTerms true when the terms checkbox is shown |
| 18 | * @type callable $emailExists fn( string $email ): bool |
| 19 | * } |
| 20 | * |
| 21 | * @return array{data: array, errors: array<string, string>} |
| 22 | */ |
| 23 | public static function validate( array $input, array $config ): array { |
| 24 | $fields = (array) ( $config['fields'] ?? array() ); |
| 25 | $isGuest = ! empty( $config['isGuest'] ); |
| 26 | $needsPassword = ! empty( $config['needsPassword'] ); |
| 27 | $needsTerms = ! empty( $config['needsTerms'] ); |
| 28 | $emailExists = $config['emailExists'] ?? null; |
| 29 | |
| 30 | $errors = array(); |
| 31 | $data = array(); |
| 32 | |
| 33 | if ( '' !== trim( (string) ( $input['tpt_wholesale_website_url'] ?? '' ) ) ) { |
| 34 | // the honeypot field is hidden from people; a value means a bot filled the form |
| 35 | $errors['spam'] = __( 'The form could not be submitted. Please try again.', 'tier-pricing-table' ); |
| 36 | |
| 37 | return array( 'data' => $data, 'errors' => $errors ); |
| 38 | } |
| 39 | |
| 40 | if ( $isGuest ) { |
| 41 | $data['first_name'] = self::text( $input['first_name'] ?? '' ); |
| 42 | $data['last_name'] = self::text( $input['last_name'] ?? '' ); |
| 43 | $data['email'] = self::email( $input['email'] ?? '' ); |
| 44 | |
| 45 | if ( '' === $data['first_name'] ) { |
| 46 | $errors['first_name'] = __( 'Please enter your first name.', 'tier-pricing-table' ); |
| 47 | } |
| 48 | |
| 49 | if ( '' === $data['last_name'] ) { |
| 50 | $errors['last_name'] = __( 'Please enter your last name.', 'tier-pricing-table' ); |
| 51 | } |
| 52 | |
| 53 | if ( '' === $data['email'] ) { |
| 54 | $errors['email'] = __( 'Please enter a valid e-mail address.', 'tier-pricing-table' ); |
| 55 | } elseif ( is_callable( $emailExists ) && $emailExists( $data['email'] ) ) { |
| 56 | $errors['email'] = __( 'An account with this e-mail address already exists. Please log in and apply from your account.', |
| 57 | 'tier-pricing-table' ); |
| 58 | } |
| 59 | |
| 60 | if ( $needsPassword ) { |
| 61 | $password = (string) ( $input['password'] ?? '' ); |
| 62 | |
| 63 | if ( strlen( $password ) < self::MIN_PASSWORD_LENGTH ) { |
| 64 | $errors['password'] = sprintf( |
| 65 | /* translators: %d: minimum number of characters */ |
| 66 | __( 'Please choose a password of at least %d characters.', 'tier-pricing-table' ), |
| 67 | self::MIN_PASSWORD_LENGTH |
| 68 | ); |
| 69 | } else { |
| 70 | $data['password'] = $password; |
| 71 | } |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | foreach ( $fields as $field ) { |
| 76 | $key = (string) ( $field['key'] ?? '' ); |
| 77 | |
| 78 | if ( '' === $key ) { |
| 79 | continue; |
| 80 | } |
| 81 | |
| 82 | $raw = $input[ $key ] ?? ''; |
| 83 | $type = (string) ( $field['type'] ?? 'text' ); |
| 84 | $required = ! empty( $field['required'] ); |
| 85 | $label = (string) ( $field['label'] ?? $key ); |
| 86 | $error = ''; |
| 87 | |
| 88 | switch ( $type ) { |
| 89 | case 'textarea': |
| 90 | $value = self::textarea( $raw ); |
| 91 | break; |
| 92 | case 'email': |
| 93 | $value = self::email( $raw ); |
| 94 | |
| 95 | if ( '' !== trim( (string) $raw ) && '' === $value ) { |
| 96 | $error = __( 'Please enter a valid e-mail address.', 'tier-pricing-table' ); |
| 97 | } |
| 98 | break; |
| 99 | case 'url': |
| 100 | $value = self::url( $raw ); |
| 101 | |
| 102 | if ( '' !== trim( (string) $raw ) && '' === $value ) { |
| 103 | $error = __( 'Please enter a valid website address.', 'tier-pricing-table' ); |
| 104 | } |
| 105 | break; |
| 106 | case 'number': |
| 107 | $value = self::text( $raw ); |
| 108 | |
| 109 | if ( '' !== $value && ! is_numeric( $value ) ) { |
| 110 | $error = __( 'Please enter a number.', 'tier-pricing-table' ); |
| 111 | $value = ''; |
| 112 | } |
| 113 | break; |
| 114 | case 'select': |
| 115 | $value = self::text( $raw ); |
| 116 | $options = array_map( 'strval', (array) ( $field['options'] ?? array() ) ); |
| 117 | |
| 118 | if ( '' !== $value && ! in_array( $value, $options, true ) ) { |
| 119 | $error = __( 'Please choose one of the options.', 'tier-pricing-table' ); |
| 120 | $value = ''; |
| 121 | } |
| 122 | break; |
| 123 | case 'checkbox': |
| 124 | $value = empty( $raw ) ? '' : '1'; |
| 125 | break; |
| 126 | default: |
| 127 | $value = self::text( $raw ); |
| 128 | } |
| 129 | |
| 130 | $data[ $key ] = $value; |
| 131 | |
| 132 | if ( '' === $error && $required && '' === $value ) { |
| 133 | $error = 'checkbox' === $type |
| 134 | /* translators: %s: field label */ |
| 135 | ? sprintf( __( 'Please tick "%s".', 'tier-pricing-table' ), $label ) |
| 136 | : __( 'This field is required.', 'tier-pricing-table' ); |
| 137 | } |
| 138 | |
| 139 | if ( '' !== $error ) { |
| 140 | $errors[ $key ] = $error; |
| 141 | } |
| 142 | } |
| 143 | |
| 144 | if ( $needsTerms && empty( $input['terms'] ) ) { |
| 145 | $errors['terms'] = __( 'Please accept the terms to continue.', 'tier-pricing-table' ); |
| 146 | } |
| 147 | |
| 148 | return array( 'data' => $data, 'errors' => $errors ); |
| 149 | } |
| 150 | |
| 151 | protected static function text( $value ): string { |
| 152 | $value = is_scalar( $value ) ? (string) $value : ''; |
| 153 | $value = function_exists( 'sanitize_text_field' ) ? sanitize_text_field( $value ) : trim( strip_tags( $value ) ); |
| 154 | |
| 155 | return mb_substr( $value, 0, 200 ); |
| 156 | } |
| 157 | |
| 158 | protected static function textarea( $value ): string { |
| 159 | $value = is_scalar( $value ) ? (string) $value : ''; |
| 160 | $value = function_exists( 'sanitize_textarea_field' ) ? sanitize_textarea_field( $value ) : trim( strip_tags( $value ) ); |
| 161 | |
| 162 | return mb_substr( $value, 0, 2000 ); |
| 163 | } |
| 164 | |
| 165 | protected static function email( $value ): string { |
| 166 | $value = strtolower( trim( is_scalar( $value ) ? (string) $value : '' ) ); |
| 167 | |
| 168 | return filter_var( $value, FILTER_VALIDATE_EMAIL ) ? $value : ''; |
| 169 | } |
| 170 | |
| 171 | protected static function url( $value ): string { |
| 172 | $value = trim( is_scalar( $value ) ? (string) $value : '' ); |
| 173 | |
| 174 | if ( '' === $value ) { |
| 175 | return ''; |
| 176 | } |
| 177 | |
| 178 | if ( ! preg_match( '#^https?://#i', $value ) ) { |
| 179 | $value = 'https://' . $value; |
| 180 | } |
| 181 | |
| 182 | return filter_var( $value, FILTER_VALIDATE_URL ) ? mb_substr( $value, 0, 200 ) : ''; |
| 183 | } |
| 184 | } |
| 185 |