valid_Core::numeric()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 1
eloc 3
c 2
b 1
f 0
nc 1
nop 1
dl 0
loc 6
rs 9.4285
1
<?php defined('SYSPATH') or die('No direct access allowed.');
2
/**
3
 * Validation helper class.
4
 *
5
 * $Id: valid.php 4367 2009-05-27 21:23:57Z samsoir $
6
 *
7
 * @package    Core
8
 * @author     Kohana Team
9
 * @copyright  (c) 2007-2008 Kohana Team
10
 * @license    http://kohanaphp.com/license.html
11
 */
12
class valid_Core
13
{
14
15
    /**
16
     * Validate email, commonly used characters only
17
     *
18
     * @param   string   email address
19
     * @return  boolean
20
     */
21
    public static function email($email)
22
    {
23
        return (bool) preg_match('/^[-_a-z0-9\'+*$^&%=~!?{}]++(?:\.[-_a-z0-9\'+*$^&%=~!?{}]+)*+@(?:(?![-.])[-a-z0-9.]+(?<![-.])\.[a-z]{2,6}|\d{1,3}(?:\.\d{1,3}){3})(?::\d++)?$/iD', (string) $email);
24
    }
25
26
    /**
27
     * Validate the domain of an email address by checking if the domain has a
28
     * valid MX record.
29
     *
30
     * @param   string   email address
31
     * @return  boolean
32
     */
33
    public static function email_domain($email)
34
    {
35
        // If we can't prove the domain is invalid, consider it valid
36
        // Note: checkdnsrr() is not implemented on Windows platforms
37
        if (! function_exists('checkdnsrr')) {
38
            return true;
39
        }
40
41
        // Check if the email domain has a valid MX record
42
        return (bool) checkdnsrr(preg_replace('/^[^@]+@/', '', $email), 'MX');
43
    }
44
45
    /**
46
     * Validate email, RFC compliant version
47
     * Note: This function is LESS strict than valid_email. Choose carefully.
48
     *
49
     * @see  Originally by Cal Henderson, modified to fit Kohana syntax standards:
50
     * @see  http://www.iamcal.com/publish/articles/php/parsing_email/
51
     * @see  http://www.w3.org/Protocols/rfc822/
52
     *
53
     * @param   string   email address
54
     * @return  boolean
55
     */
56
    public static function email_rfc($email)
57
    {
58
        $qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]';
59
        $dtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]';
60
        $atom  = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+';
61
        $pair  = '\\x5c[\\x00-\\x7f]';
62
63
        $domain_literal = "\\x5b($dtext|$pair)*\\x5d";
64
        $quoted_string  = "\\x22($qtext|$pair)*\\x22";
65
        $sub_domain     = "($atom|$domain_literal)";
66
        $word           = "($atom|$quoted_string)";
67
        $domain         = "$sub_domain(\\x2e$sub_domain)*";
68
        $local_part     = "$word(\\x2e$word)*";
69
        $addr_spec      = "$local_part\\x40$domain";
70
71
        return (bool) preg_match('/^'.$addr_spec.'$/D', (string) $email);
72
    }
73
74
    /**
75
     * Validate URL
76
     *
77
     * @param   string   URL
78
     * @return  boolean
79
     */
80
    public static function url($url)
81
    {
82
        return (bool) filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED);
83
    }
84
85
    /**
86
     * Validate IP
87
     *
88
     * @param   string   IP address
89
     * @param   boolean  allow IPv6 addresses
90
     * @param   boolean  allow private IP networks
91
     * @return  boolean
92
     */
93
    public static function ip($ip, $ipv6 = false, $allow_private = true)
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $ip. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
Coding Style introduced by
This method's name is shorter than the configured minimum length of 3 characters.

Even though PHP does not care about the name of your methods, it is generally a good practice to choose method names which can be easily understood by other human readers.

Loading history...
94
    {
95
        // By default do not allow private and reserved range IPs
96
        $flags = FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE;
97
        if ($allow_private === true) {
98
            $flags =  FILTER_FLAG_NO_RES_RANGE;
99
        }
100
101
        if ($ipv6 === true) {
102
            return (bool) filter_var($ip, FILTER_VALIDATE_IP, $flags);
103
        }
104
105
        return (bool) filter_var($ip, FILTER_VALIDATE_IP, $flags | FILTER_FLAG_IPV4);
106
    }
107
108
    /**
109
     * Validates a credit card number using the Luhn (mod10) formula.
110
     * @see http://en.wikipedia.org/wiki/Luhn_algorithm
111
     *
112
     * @param   integer       credit card number
113
     * @param   string|array  card type, or an array of card types
114
     * @return  boolean
115
     */
116
    public static function credit_card($number, $type = null)
117
    {
118
        // Remove all non-digit characters from the number
119
        if (($number = preg_replace('/\D+/', '', $number)) === '') {
120
            return false;
121
        }
122
123
        if ($type == null) {
124
            // Use the default type
125
            $type = 'default';
126
        } elseif (is_array($type)) {
127
            foreach ($type as $t) {
128
                // Test each type for validity
129
                if (valid::credit_card($number, $t)) {
130
                    return true;
131
                }
132
            }
133
134
            return false;
135
        }
136
137
        $cards = Kohana::config('credit_cards');
138
139
        // Check card type
140
        $type = strtolower($type);
141
142
        if (! isset($cards[$type])) {
143
            return false;
144
        }
145
146
        // Check card number length
147
        $length = strlen($number);
148
149
        // Validate the card length by the card type
150
        if (! in_array($length, preg_split('/\D+/', $cards[$type]['length']))) {
151
            return false;
152
        }
153
154
        // Check card number prefix
155
        if (! preg_match('/^'.$cards[$type]['prefix'].'/', $number)) {
156
            return false;
157
        }
158
159
        // No Luhn check required
160
        if ($cards[$type]['luhn'] == false) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $cards[$type]['luhn'] of type string to the boolean false. If you are specifically checking for an empty string, consider using the more explicit === '' instead.
Loading history...
161
            return true;
162
        }
163
164
        // Checksum of the card number
165
        $checksum = 0;
166
167
        for ($i = $length - 1; $i >= 0; $i -= 2) {
168
            // Add up every 2nd digit, starting from the right
169
            $checksum += $number[$i];
170
        }
171
172
        for ($i = $length - 2; $i >= 0; $i -= 2) {
173
            // Add up every 2nd digit doubled, starting from the right
174
            $double = $number[$i] * 2;
175
176
            // Subtract 9 from the double where value is greater than 10
177
            $checksum += ($double >= 10) ? $double - 9 : $double;
178
        }
179
180
        // If the checksum is a multiple of 10, the number is valid
181
        return ($checksum % 10 === 0);
182
    }
183
184
    /**
185
     * Checks if a phone number is valid.
186
     *
187
     * @param   string   phone number to check
188
     * @return  boolean
189
     */
190
    public static function phone($number, $lengths = null)
191
    {
192
        if (! is_array($lengths)) {
193
            $lengths = array(7,10,11);
194
        }
195
196
        // Remove all non-digit characters from the number
197
        $number = preg_replace('/\D+/', '', $number);
198
199
        // Check if the number is within range
200
        return in_array(strlen($number), $lengths);
201
    }
202
203
    /**
204
     * Tests if a string is a valid date string.
205
     *
206
     * @param   string   date to check
207
     * @return  boolean
208
     */
209
    public static function date($str)
210
    {
211
        return (strtotime($str) !== false);
212
    }
213
214
    /**
215
     * Checks whether a string consists of alphabetical characters only.
216
     *
217
     * @param   string   input string
218
     * @param   boolean  trigger UTF-8 compatibility
219
     * @return  boolean
220
     */
221
    public static function alpha($str, $utf8 = false)
222
    {
223
        return ($utf8 === true)
224
            ? (bool) preg_match('/^\pL++$/uD', (string) $str)
225
            : ctype_alpha((string) $str);
226
    }
227
228
    /**
229
     * Checks whether a string consists of alphabetical characters and numbers only.
230
     *
231
     * @param   string   input string
232
     * @param   boolean  trigger UTF-8 compatibility
233
     * @return  boolean
234
     */
235
    public static function alpha_numeric($str, $utf8 = false)
236
    {
237
        return ($utf8 === true)
238
            ? (bool) preg_match('/^[\pL\pN]++$/uD', (string) $str)
239
            : ctype_alnum((string) $str);
240
    }
241
242
    /**
243
     * Checks whether a string consists of alphabetical characters, numbers, underscores and dashes only.
244
     *
245
     * @param   string   input string
246
     * @param   boolean  trigger UTF-8 compatibility
247
     * @return  boolean
248
     */
249
    public static function alpha_dash($str, $utf8 = false)
250
    {
251
        return ($utf8 === true)
252
            ? (bool) preg_match('/^[-\pL\pN_]++$/uD', (string) $str)
253
            : (bool) preg_match('/^[-a-z0-9_]++$/iD', (string) $str);
254
    }
255
256
    /**
257
     * Checks whether a string consists of digits only (no dots or dashes).
258
     *
259
     * @param   string   input string
260
     * @param   boolean  trigger UTF-8 compatibility
261
     * @return  boolean
262
     */
263
    public static function digit($str, $utf8 = false)
264
    {
265
        return ($utf8 === true)
266
            ? (bool) preg_match('/^\pN++$/uD', (string) $str)
267
            : ctype_digit((string) $str);
268
    }
269
270
    /**
271
     * Checks whether a string is a valid number (negative and decimal numbers allowed).
272
     *
273
     * @see Uses locale conversion to allow decimal point to be locale specific.
274
     * @see http://www.php.net/manual/en/function.localeconv.php
275
     *
276
     * @param   string   input string
277
     * @return  boolean
278
     */
279
    public static function numeric($str)
280
    {
281
        // Use localeconv to set the decimal_point value: Usually a comma or period.
282
        $locale = localeconv();
283
        return (bool) preg_match('/^-?[0-9'.$locale['decimal_point'].']++$/D', (string) $str);
284
    }
285
286
    /**
287
     * Checks whether a string is a valid text. Letters, numbers, whitespace,
288
     * dashes, periods, and underscores are allowed.
289
     *
290
     * @param   string   text to check
291
     * @return  boolean
292
     */
293
    public static function standard_text($str)
294
    {
295
        // pL matches letters
296
        // pN matches numbers
297
        // pZ matches whitespace
298
        // pPc matches underscores
299
        // pPd matches dashes
300
        // pPo matches normal puncuation
301
        return (bool) preg_match('/^[\pL\pN\pZ\p{Pc}\p{Pd}\p{Po}]++$/uD', (string) $str);
302
    }
303
304
    /**
305
     * Checks if a string is a proper decimal format. The format array can be
306
     * used to specify a decimal length, or a number and decimal length, eg:
307
     * array(2) would force the number to have 2 decimal places, array(4,2)
308
     * would force the number to have 4 digits and 2 decimal places.
309
     *
310
     * @param   string   input string
311
     * @param   array    decimal format: y or x,y
312
     * @return  boolean
313
     */
314
    public static function decimal($str, $format = null)
315
    {
316
        // Create the pattern
317
        $pattern = '/^[0-9]%s\.[0-9]%s$/';
318
319
        if (! empty($format)) {
320
            if (count($format) > 1) {
321
                // Use the format for number and decimal length
322
                $pattern = sprintf($pattern, '{'.$format[0].'}', '{'.$format[1].'}');
323
            } elseif (count($format) > 0) {
324
                // Use the format as decimal length
325
                $pattern = sprintf($pattern, '+', '{'.$format[0].'}');
326
            }
327
        } else {
328
            // No format
329
            $pattern = sprintf($pattern, '+', '+');
330
        }
331
332
        return (bool) preg_match($pattern, (string) $str);
333
    }
334
} // End valid
335