blob: c068614deb0bf69f5b80cac00725a6db25739abc [file] [log] [blame]
Andrey Andreevc5536aa2012-11-01 17:33:58 +02001<?php
Derek Allard2067d1a2008-11-13 22:59:24 +00002/**
3 * CodeIgniter
4 *
Andrey Andreevfe9309d2015-01-09 17:48:58 +02005 * An open source application development framework for PHP
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +02007 * This content is released under the MIT License (MIT)
Eric Barnescccde962011-12-04 00:01:17 -05008 *
Instructor, BCIT0e59db62019-01-01 08:34:36 -08009 * Copyright (c) 2014 - 2019, British Columbia Institute of Technology
Eric Barnescccde962011-12-04 00:01:17 -050010 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020011 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
Derek Jonesf4a4bd82011-10-20 12:18:42 -050017 *
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020018 * The above copyright notice and this permission notice shall be included in
19 * all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 * THE SOFTWARE.
28 *
29 * @package CodeIgniter
30 * @author EllisLab Dev Team
Andrey Andreev1924e872016-01-11 12:55:34 +020031 * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
Instructor, BCIT0e59db62019-01-01 08:34:36 -080032 * @copyright Copyright (c) 2014 - 2019, British Columbia Institute of Technology (https://bcit.ca/)
33 * @license https://opensource.org/licenses/MIT MIT License
Andrey Andreevbd202c92016-01-11 12:50:18 +020034 * @link https://codeigniter.com
Andrey Andreevbdb96ca2014-10-28 00:13:31 +020035 * @since Version 1.0.0
Derek Allard2067d1a2008-11-13 22:59:24 +000036 * @filesource
37 */
Andrey Andreevc5536aa2012-11-01 17:33:58 +020038defined('BASEPATH') OR exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +000039
Derek Allard2067d1a2008-11-13 22:59:24 +000040/**
41 * Form Validation Class
42 *
43 * @package CodeIgniter
44 * @subpackage Libraries
45 * @category Validation
Derek Jonesf4a4bd82011-10-20 12:18:42 -050046 * @author EllisLab Dev Team
Andrey Andreevbd202c92016-01-11 12:50:18 +020047 * @link https://codeigniter.com/user_guide/libraries/form_validation.html
Derek Allard2067d1a2008-11-13 22:59:24 +000048 */
49class CI_Form_validation {
Barry Mienydd671972010-10-04 16:33:58 +020050
Timothy Warren0688ac92012-04-20 10:25:04 -040051 /**
52 * Reference to the CodeIgniter instance
53 *
54 * @var object
55 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +010056 protected $CI;
Derek Allard2067d1a2008-11-13 22:59:24 +000057
Timothy Warren0688ac92012-04-20 10:25:04 -040058 /**
59 * Validation data for the current form submission
60 *
61 * @var array
62 */
Andrey Andreev56454792012-05-17 14:32:19 +030063 protected $_field_data = array();
64
Timothy Warren0688ac92012-04-20 10:25:04 -040065 /**
66 * Validation rules for the current form
67 *
68 * @var array
69 */
Andrey Andreev56454792012-05-17 14:32:19 +030070 protected $_config_rules = array();
71
Timothy Warren0688ac92012-04-20 10:25:04 -040072 /**
73 * Array of validation errors
74 *
75 * @var array
76 */
Andrey Andreev78f55772012-04-03 19:59:08 +030077 protected $_error_array = array();
Andrey Andreev56454792012-05-17 14:32:19 +030078
Timothy Warren0688ac92012-04-20 10:25:04 -040079 /**
80 * Array of custom error messages
81 *
82 * @var array
83 */
Andrey Andreev78f55772012-04-03 19:59:08 +030084 protected $_error_messages = array();
Andrey Andreev56454792012-05-17 14:32:19 +030085
Timothy Warren0688ac92012-04-20 10:25:04 -040086 /**
87 * Start tag for error wrapping
88 *
89 * @var string
90 */
Andrey Andreev78f55772012-04-03 19:59:08 +030091 protected $_error_prefix = '<p>';
Andrey Andreev56454792012-05-17 14:32:19 +030092
Timothy Warren0688ac92012-04-20 10:25:04 -040093 /**
94 * End tag for error wrapping
Andrey Andreev56454792012-05-17 14:32:19 +030095 *
Timothy Warren0688ac92012-04-20 10:25:04 -040096 * @var string
97 */
Andrey Andreev78f55772012-04-03 19:59:08 +030098 protected $_error_suffix = '</p>';
Andrey Andreev56454792012-05-17 14:32:19 +030099
Timothy Warren0688ac92012-04-20 10:25:04 -0400100 /**
101 * Custom error message
102 *
103 * @var string
104 */
Andrey Andreev78f55772012-04-03 19:59:08 +0300105 protected $error_string = '';
Andrey Andreev56454792012-05-17 14:32:19 +0300106
Timothy Warren0688ac92012-04-20 10:25:04 -0400107 /**
Luigi Santivetti7bab4942019-06-16 07:40:53 +0000108 * Start tag for message wrapping
109 *
110 * @var string
111 */
112 protected $_message_prefix = '<p>';
113
114 /**
115 * End tag for message wrapping
116 *
117 * @var string
118 */
119 protected $_message_suffix = '</p>';
120
121 /**
122 * Custom message
123 *
124 * @var string
125 */
126 protected $message_string = '';
127
128 /**
Timothy Warren0688ac92012-04-20 10:25:04 -0400129 * Whether the form data has been validated as safe
130 *
131 * @var bool
132 */
Andrey Andreev78f55772012-04-03 19:59:08 +0300133 protected $_safe_form_data = FALSE;
Andrey Andreev56454792012-05-17 14:32:19 +0300134
Timothy Warren0688ac92012-04-20 10:25:04 -0400135 /**
136 * Custom data to validate
137 *
138 * @var array
139 */
Andrey Andreevcff35802012-11-26 15:49:52 +0200140 public $validation_data = array();
Derek Allard2067d1a2008-11-13 22:59:24 +0000141
Timothy Warren0688ac92012-04-20 10:25:04 -0400142 /**
143 * Initialize Form_Validation class
144 *
Andrey Andreev56454792012-05-17 14:32:19 +0300145 * @param array $rules
146 * @return void
Timothy Warren0688ac92012-04-20 10:25:04 -0400147 */
Greg Akera9263282010-11-10 15:26:43 -0600148 public function __construct($rules = array())
Barry Mienydd671972010-10-04 16:33:58 +0200149 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000150 $this->CI =& get_instance();
Barry Mienydd671972010-10-04 16:33:58 +0200151
Mike Funk326a5e72012-02-24 10:06:28 -0500152 // applies delimiters set in config file.
Mike Funk7f42d062012-03-08 09:00:57 -0500153 if (isset($rules['error_prefix']))
154 {
155 $this->_error_prefix = $rules['error_prefix'];
156 unset($rules['error_prefix']);
157 }
158 if (isset($rules['error_suffix']))
159 {
160 $this->_error_suffix = $rules['error_suffix'];
161 unset($rules['error_suffix']);
162 }
Andrey Andreev31cf46e2012-03-20 15:48:00 +0200163
Derek Allard2067d1a2008-11-13 22:59:24 +0000164 // Validation rules can be stored in a config file.
165 $this->_config_rules = $rules;
Barry Mienydd671972010-10-04 16:33:58 +0200166
Derek Allard2067d1a2008-11-13 22:59:24 +0000167 // Automatically load the form helper
168 $this->CI->load->helper('form');
169
Andrey Andreev90726b82015-01-20 12:39:22 +0200170 log_message('info', 'Form Validation Class Initialized');
Derek Allard2067d1a2008-11-13 22:59:24 +0000171 }
Barry Mienydd671972010-10-04 16:33:58 +0200172
Derek Allard2067d1a2008-11-13 22:59:24 +0000173 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200174
Derek Allard2067d1a2008-11-13 22:59:24 +0000175 /**
176 * Set Rules
177 *
178 * This function takes an array of field names and validation
Andrey Andreev4b90a372014-03-10 10:24:24 +0200179 * rules as input, any custom error messages, validates the info,
Ahmedul Haque Abid42b40002014-01-09 01:10:25 +0600180 * and stores it
Derek Allard2067d1a2008-11-13 22:59:24 +0000181 *
Timothy Warren0688ac92012-04-20 10:25:04 -0400182 * @param mixed $field
183 * @param string $label
184 * @param mixed $rules
Ahmedul Haque Abid0742fad2014-01-09 07:51:10 +0600185 * @param array $errors
Andrew Podner4296a652012-12-17 07:51:15 -0500186 * @return CI_Form_validation
Derek Allard2067d1a2008-11-13 22:59:24 +0000187 */
Andrey Andreev4b90a372014-03-10 10:24:24 +0200188 public function set_rules($field, $label = '', $rules = array(), $errors = array())
Derek Allard2067d1a2008-11-13 22:59:24 +0000189 {
190 // No reason to set rules if we have no POST data
JonoB099c4782012-03-04 14:37:30 +0000191 // or a validation array has not been specified
Andrey Andreev3b2c5082012-03-07 22:49:24 +0200192 if ($this->CI->input->method() !== 'post' && empty($this->validation_data))
Derek Allard2067d1a2008-11-13 22:59:24 +0000193 {
Greg Aker9f9af602010-11-10 15:41:51 -0600194 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000195 }
Barry Mienydd671972010-10-04 16:33:58 +0200196
tiyowanc2acb232012-03-14 21:24:00 +0400197 // If an array was passed via the first parameter instead of individual string
Derek Allard2067d1a2008-11-13 22:59:24 +0000198 // values we cycle through it and recursively call this function.
199 if (is_array($field))
200 {
201 foreach ($field as $row)
202 {
203 // Houston, we have a problem...
Andrey Andreev78f55772012-04-03 19:59:08 +0300204 if ( ! isset($row['field'], $row['rules']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000205 {
206 continue;
207 }
208
209 // If the field label wasn't passed we use the field name
Andrey Andreev78f55772012-04-03 19:59:08 +0300210 $label = isset($row['label']) ? $row['label'] : $row['field'];
Derek Allard2067d1a2008-11-13 22:59:24 +0000211
Ahmedul Haque Abid42b40002014-01-09 01:10:25 +0600212 // Add the custom error message array
Ahmedul Haque Abidea294882014-01-09 16:01:31 +0600213 $errors = (isset($row['errors']) && is_array($row['errors'])) ? $row['errors'] : array();
Ahmedul Haque Abid42b40002014-01-09 01:10:25 +0600214
Derek Allard2067d1a2008-11-13 22:59:24 +0000215 // Here we go!
Ahmedul Haque Abidbc1cbad2014-01-09 07:53:34 +0600216 $this->set_rules($row['field'], $label, $row['rules'], $errors);
Derek Allard2067d1a2008-11-13 22:59:24 +0000217 }
Andrey Andreev78f55772012-04-03 19:59:08 +0300218
Greg Aker9f9af602010-11-10 15:41:51 -0600219 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000220 }
Barry Mienydd671972010-10-04 16:33:58 +0200221
Andrey Andreev475dfac2015-04-07 00:07:04 +0300222 // No fields or no rules? Nothing to do...
223 if ( ! is_string($field) OR $field === '' OR empty($rules))
Derek Allard2067d1a2008-11-13 22:59:24 +0000224 {
Greg Aker9f9af602010-11-10 15:41:51 -0600225 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000226 }
Andrey Andreev4b90a372014-03-10 10:24:24 +0200227 elseif ( ! is_array($rules))
228 {
229 // BC: Convert pipe-separated rules string to an array
Andrey Andreev475dfac2015-04-07 00:07:04 +0300230 if ( ! is_string($rules))
Andrey Andreev4b90a372014-03-10 10:24:24 +0200231 {
232 return $this;
233 }
Andrey Andreev475dfac2015-04-07 00:07:04 +0300234
richcc936352015-09-09 15:52:26 -0400235 $rules = preg_split('/\|(?![^\[]*\])/', $rules);
Andrey Andreev4b90a372014-03-10 10:24:24 +0200236 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000237
238 // If the field label wasn't passed we use the field name
Alex Bilbied261b1e2012-06-02 11:12:16 +0100239 $label = ($label === '') ? $field : $label;
Derek Allard2067d1a2008-11-13 22:59:24 +0000240
Andrey Andreevfde170c2014-03-10 19:55:11 +0200241 $indexes = array();
242
Andrey Andreev8dc532d2011-12-24 17:57:54 +0200243 // Is the field name an array? If it is an array, we break it apart
Barry Mienydd671972010-10-04 16:33:58 +0200244 // into its components so that we can fetch the corresponding POST data later
Andrey Andreev4b90a372014-03-10 10:24:24 +0200245 if (($is_array = (bool) preg_match_all('/\[(.*?)\]/', $field, $matches)) === TRUE)
Barry Mienydd671972010-10-04 16:33:58 +0200246 {
Andrey Andreev7a7ad782012-11-12 17:21:01 +0200247 sscanf($field, '%[^[][', $indexes[0]);
Derek Allard2067d1a2008-11-13 22:59:24 +0000248
Andrey Andreev8dc532d2011-12-24 17:57:54 +0200249 for ($i = 0, $c = count($matches[0]); $i < $c; $i++)
Derek Allard2067d1a2008-11-13 22:59:24 +0000250 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100251 if ($matches[1][$i] !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000252 {
Andrey Andreev8dc532d2011-12-24 17:57:54 +0200253 $indexes[] = $matches[1][$i];
Derek Allard2067d1a2008-11-13 22:59:24 +0000254 }
255 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000256 }
Barry Mienydd671972010-10-04 16:33:58 +0200257
258 // Build our master array
Derek Allard2067d1a2008-11-13 22:59:24 +0000259 $this->_field_data[$field] = array(
Andrey Andreev56454792012-05-17 14:32:19 +0300260 'field' => $field,
261 'label' => $label,
262 'rules' => $rules,
Ahmedul Haque Abid7945d302014-01-09 16:50:23 +0600263 'errors' => $errors,
Andrey Andreev56454792012-05-17 14:32:19 +0300264 'is_array' => $is_array,
265 'keys' => $indexes,
266 'postdata' => NULL,
267 'error' => ''
Phil Sturgeonef112c02011-02-07 13:01:47 +0000268 );
Greg Aker9f9af602010-11-10 15:41:51 -0600269
270 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000271 }
272
273 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200274
Derek Allard2067d1a2008-11-13 22:59:24 +0000275 /**
JonoB099c4782012-03-04 14:37:30 +0000276 * By default, form validation uses the $_POST array to validate
Andrey Andreevc8da4fe2012-03-04 19:20:33 +0200277 *
JonoB099c4782012-03-04 14:37:30 +0000278 * If an array is set through this method, then this array will
279 * be used instead of the $_POST array
Andrey Andreev3b2c5082012-03-07 22:49:24 +0200280 *
281 * Note that if you are validating multiple arrays, then the
282 * reset_validation() function should be called after validating
JonoB883f80f2012-03-05 09:51:27 +0000283 * each array due to the limitations of CI's singleton
Andrey Andreevc8da4fe2012-03-04 19:20:33 +0200284 *
285 * @param array $data
Andrey Andreeva89c1da2014-02-08 19:03:35 +0200286 * @return CI_Form_validation
JonoB099c4782012-03-04 14:37:30 +0000287 */
Andrey Andreeva4712f52014-01-06 11:25:46 +0200288 public function set_data(array $data)
JonoB099c4782012-03-04 14:37:30 +0000289 {
Andrey Andreeva4712f52014-01-06 11:25:46 +0200290 if ( ! empty($data))
JonoB099c4782012-03-04 14:37:30 +0000291 {
Andrey Andreevc8da4fe2012-03-04 19:20:33 +0200292 $this->validation_data = $data;
JonoB099c4782012-03-04 14:37:30 +0000293 }
Andrey Andreeva89c1da2014-02-08 19:03:35 +0200294
295 return $this;
JonoB099c4782012-03-04 14:37:30 +0000296 }
Andrey Andreevc8da4fe2012-03-04 19:20:33 +0200297
JonoB099c4782012-03-04 14:37:30 +0000298 // --------------------------------------------------------------------
Derek Allard2067d1a2008-11-13 22:59:24 +0000299
300 /**
301 * Set Error Message
302 *
Andrey Andreev78f55772012-04-03 19:59:08 +0300303 * Lets users set their own error messages on the fly. Note:
304 * The key name has to match the function name that it corresponds to.
Derek Allard2067d1a2008-11-13 22:59:24 +0000305 *
Andrey Andreev78f55772012-04-03 19:59:08 +0300306 * @param array
Derek Allard2067d1a2008-11-13 22:59:24 +0000307 * @param string
Andrew Podner4296a652012-12-17 07:51:15 -0500308 * @return CI_Form_validation
Derek Allard2067d1a2008-11-13 22:59:24 +0000309 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +0100310 public function set_message($lang, $val = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000311 {
312 if ( ! is_array($lang))
313 {
314 $lang = array($lang => $val);
315 }
Barry Mienydd671972010-10-04 16:33:58 +0200316
Derek Allard2067d1a2008-11-13 22:59:24 +0000317 $this->_error_messages = array_merge($this->_error_messages, $lang);
Greg Aker9f9af602010-11-10 15:41:51 -0600318 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000319 }
Barry Mienydd671972010-10-04 16:33:58 +0200320
Derek Allard2067d1a2008-11-13 22:59:24 +0000321 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200322
Derek Allard2067d1a2008-11-13 22:59:24 +0000323 /**
Luigi Santivetti7bab4942019-06-16 07:40:53 +0000324 * Set Message
325 *
326 * Lets users set their own messages on the fly. Note:
327 * The key name has to match the function name that it corresponds to.
328 *
329 * @param array
330 * @param string
331 * @return CI_Form_validation
332 */
333 public function set_string($msg = '')
334 {
335 $this->message_string = $msg;
336 return $this;
337 }
338
339 // --------------------------------------------------------------------
340
341 /**
Derek Allard2067d1a2008-11-13 22:59:24 +0000342 * Set The Error Delimiter
343 *
344 * Permits a prefix/suffix to be added to each error message
345 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000346 * @param string
347 * @param string
Andrew Podner4296a652012-12-17 07:51:15 -0500348 * @return CI_Form_validation
Barry Mienydd671972010-10-04 16:33:58 +0200349 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +0100350 public function set_error_delimiters($prefix = '<p>', $suffix = '</p>')
Derek Allard2067d1a2008-11-13 22:59:24 +0000351 {
352 $this->_error_prefix = $prefix;
353 $this->_error_suffix = $suffix;
Greg Aker9f9af602010-11-10 15:41:51 -0600354 return $this;
Derek Allard2067d1a2008-11-13 22:59:24 +0000355 }
356
357 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200358
Derek Allard2067d1a2008-11-13 22:59:24 +0000359 /**
360 * Get Error Message
361 *
362 * Gets the error message associated with a particular field
363 *
Andrey Andreeva4712f52014-01-06 11:25:46 +0200364 * @param string $field Field name
365 * @param string $prefix HTML start tag
Andrey Andreev868301a2014-01-06 12:29:50 +0200366 * @param string $suffix HTML end tag
Andrey Andreev78f55772012-04-03 19:59:08 +0300367 * @return string
Barry Mienydd671972010-10-04 16:33:58 +0200368 */
Andrey Andreeva4712f52014-01-06 11:25:46 +0200369 public function error($field, $prefix = '', $suffix = '')
Barry Mienydd671972010-10-04 16:33:58 +0200370 {
Andrey Andreev78f55772012-04-03 19:59:08 +0300371 if (empty($this->_field_data[$field]['error']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000372 {
373 return '';
374 }
Barry Mienydd671972010-10-04 16:33:58 +0200375
Alex Bilbied261b1e2012-06-02 11:12:16 +0100376 if ($prefix === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000377 {
378 $prefix = $this->_error_prefix;
379 }
380
Alex Bilbied261b1e2012-06-02 11:12:16 +0100381 if ($suffix === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000382 {
383 $suffix = $this->_error_suffix;
384 }
385
386 return $prefix.$this->_field_data[$field]['error'].$suffix;
387 }
388
389 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200390
Derek Allard2067d1a2008-11-13 22:59:24 +0000391 /**
Luigi Santivetti7bab4942019-06-16 07:40:53 +0000392 * Get Message
393 *
394 * Gets the message associated with a particular field
395 *
396 * @param string $field Field name
397 * @param string $prefix HTML start tag
398 * @param string $suffix HTML end tag
399 * @return string
400 */
401 public function message($field, $prefix = '', $suffix = '')
402 {
403 /* No class specific message field */
404
405 if ($prefix === '')
406 {
407 $prefix = $this->_message_prefix;
408 }
409
410 if ($suffix === '')
411 {
412 $suffix = $this->_message_suffix;
413 }
414
415 return $prefix.$this->message_string.$suffix;
416 }
417
418 // --------------------------------------------------------------------
419
420 /**
Michiel Vugteveen676a0dd2012-03-02 10:10:34 +0100421 * Get Array of Error Messages
422 *
423 * Returns the error messages as an array
424 *
425 * @return array
426 */
427 public function error_array()
428 {
429 return $this->_error_array;
430 }
431
432 // --------------------------------------------------------------------
433
434 /**
Derek Allard2067d1a2008-11-13 22:59:24 +0000435 * Error String
436 *
437 * Returns the error messages as a string, wrapped in the error delimiters
438 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000439 * @param string
440 * @param string
Andrey Andreev78f55772012-04-03 19:59:08 +0300441 * @return string
Barry Mienydd671972010-10-04 16:33:58 +0200442 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +0100443 public function error_string($prefix = '', $suffix = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000444 {
vlakoff35672462013-02-15 01:36:04 +0100445 // No errors, validation passes!
Derek Allard2067d1a2008-11-13 22:59:24 +0000446 if (count($this->_error_array) === 0)
447 {
448 return '';
449 }
Barry Mienydd671972010-10-04 16:33:58 +0200450
Alex Bilbied261b1e2012-06-02 11:12:16 +0100451 if ($prefix === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000452 {
453 $prefix = $this->_error_prefix;
454 }
455
Alex Bilbied261b1e2012-06-02 11:12:16 +0100456 if ($suffix === '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000457 {
458 $suffix = $this->_error_suffix;
459 }
Barry Mienydd671972010-10-04 16:33:58 +0200460
Derek Allard2067d1a2008-11-13 22:59:24 +0000461 // Generate the error string
462 $str = '';
463 foreach ($this->_error_array as $val)
464 {
Alex Bilbied261b1e2012-06-02 11:12:16 +0100465 if ($val !== '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000466 {
467 $str .= $prefix.$val.$suffix."\n";
468 }
469 }
Barry Mienydd671972010-10-04 16:33:58 +0200470
Derek Allard2067d1a2008-11-13 22:59:24 +0000471 return $str;
472 }
473
474 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200475
Derek Allard2067d1a2008-11-13 22:59:24 +0000476 /**
477 * Run the Validator
478 *
479 * This function does all the work.
480 *
Timothy Warren0688ac92012-04-20 10:25:04 -0400481 * @param string $group
Derek Allard2067d1a2008-11-13 22:59:24 +0000482 * @return bool
Barry Mienydd671972010-10-04 16:33:58 +0200483 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +0100484 public function run($group = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000485 {
Andrey Andreevce8fa5a2015-12-14 12:57:09 +0200486 $validation_array = empty($this->validation_data)
487 ? $_POST
488 : $this->validation_data;
Barry Mienydd671972010-10-04 16:33:58 +0200489
Derek Allard2067d1a2008-11-13 22:59:24 +0000490 // Does the _field_data array containing the validation rules exist?
491 // If not, we look to see if they were assigned via a config file
Andrey Andreev8dc532d2011-12-24 17:57:54 +0200492 if (count($this->_field_data) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000493 {
Derek Jones37f4b9c2011-07-01 17:56:50 -0500494 // No validation rules? We're done...
Andrey Andreev8dc532d2011-12-24 17:57:54 +0200495 if (count($this->_config_rules) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000496 {
497 return FALSE;
498 }
Barry Mienydd671972010-10-04 16:33:58 +0200499
Andrey Andreev3b2803e2014-01-07 14:46:38 +0200500 if (empty($group))
501 {
502 // Is there a validation rule for the particular URI being accessed?
503 $group = trim($this->CI->uri->ruri_string(), '/');
504 isset($this->_config_rules[$group]) OR $group = $this->CI->router->class.'/'.$this->CI->router->method;
505 }
Barry Mienydd671972010-10-04 16:33:58 +0200506
Andrey Andreev3b2803e2014-01-07 14:46:38 +0200507 $this->set_rules(isset($this->_config_rules[$group]) ? $this->_config_rules[$group] : $this->_config_rules);
Barry Mienydd671972010-10-04 16:33:58 +0200508
Andrey Andreev901573c2012-01-11 01:40:48 +0200509 // Were we able to set the rules correctly?
Andrey Andreev8dc532d2011-12-24 17:57:54 +0200510 if (count($this->_field_data) === 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000511 {
Andrey Andreev901573c2012-01-11 01:40:48 +0200512 log_message('debug', 'Unable to find validation rules');
Derek Allard2067d1a2008-11-13 22:59:24 +0000513 return FALSE;
514 }
515 }
Barry Mienydd671972010-10-04 16:33:58 +0200516
Derek Allard2067d1a2008-11-13 22:59:24 +0000517 // Load the language file containing error messages
518 $this->CI->lang->load('form_validation');
Barry Mienydd671972010-10-04 16:33:58 +0200519
Andrey Andreev751f2472012-11-03 18:26:27 +0200520 // Cycle through the rules for each field and match the corresponding $validation_data item
Andrey Andreev55a40b72016-03-12 15:43:22 +0200521 foreach ($this->_field_data as $field => &$row)
Barry Mienydd671972010-10-04 16:33:58 +0200522 {
Andrey Andreev751f2472012-11-03 18:26:27 +0200523 // Fetch the data from the validation_data array item and cache it in the _field_data array.
Derek Allard2067d1a2008-11-13 22:59:24 +0000524 // Depending on whether the field name is an array or a string will determine where we get it from.
Andrey Andreev8dc532d2011-12-24 17:57:54 +0200525 if ($row['is_array'] === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000526 {
JonoB099c4782012-03-04 14:37:30 +0000527 $this->_field_data[$field]['postdata'] = $this->_reduce_array($validation_array, $row['keys']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000528 }
Andrey Andreevb137d232015-04-29 11:44:38 +0300529 elseif (isset($validation_array[$field]))
Derek Allard2067d1a2008-11-13 22:59:24 +0000530 {
Andrey Andreev78f55772012-04-03 19:59:08 +0300531 $this->_field_data[$field]['postdata'] = $validation_array[$field];
Derek Allard2067d1a2008-11-13 22:59:24 +0000532 }
Andrey Andreev751f2472012-11-03 18:26:27 +0200533 }
Barry Mienydd671972010-10-04 16:33:58 +0200534
Andrey Andreev751f2472012-11-03 18:26:27 +0200535 // Execute validation rules
536 // Note: A second foreach (for now) is required in order to avoid false-positives
537 // for rules like 'matches', which correlate to other validation fields.
Andrey Andreev55a40b72016-03-12 15:43:22 +0200538 foreach ($this->_field_data as $field => &$row)
Andrey Andreev751f2472012-11-03 18:26:27 +0200539 {
Andrey Andreev3d9cec92012-07-08 21:50:19 +0300540 // Don't try to validate if we have no rules set
541 if (empty($row['rules']))
542 {
543 continue;
544 }
Barry Mienydd671972010-10-04 16:33:58 +0200545
Andrey Andreev55a40b72016-03-12 15:43:22 +0200546 $this->_execute($row, $row['rules'], $row['postdata']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000547 }
548
549 // Did we end up with any errors?
550 $total_errors = count($this->_error_array);
Derek Allard2067d1a2008-11-13 22:59:24 +0000551 if ($total_errors > 0)
552 {
553 $this->_safe_form_data = TRUE;
554 }
555
556 // Now we need to re-set the POST data with the new, processed data
Andrey Andreev02ac1872016-03-16 12:19:34 +0200557 empty($this->validation_data) && $this->_reset_post_array();
Barry Mienydd671972010-10-04 16:33:58 +0200558
Andrey Andreev8dc532d2011-12-24 17:57:54 +0200559 return ($total_errors === 0);
Derek Allard2067d1a2008-11-13 22:59:24 +0000560 }
561
562 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200563
Derek Allard2067d1a2008-11-13 22:59:24 +0000564 /**
Andrey Andreev0fae6252016-05-17 13:46:55 +0300565 * Prepare rules
566 *
567 * Re-orders the provided rules in order of importance, so that
568 * they can easily be executed later without weird checks ...
569 *
570 * "Callbacks" are given the highest priority (always called),
571 * followed by 'required' (called if callbacks didn't fail),
572 * and then every next rule depends on the previous one passing.
573 *
574 * @param array $rules
575 * @return array
576 */
577 protected function _prepare_rules($rules)
578 {
579 $new_rules = array();
580 $callbacks = array();
581
582 foreach ($rules as &$rule)
583 {
584 // Let 'required' always be the first (non-callback) rule
585 if ($rule === 'required')
586 {
587 array_unshift($new_rules, 'required');
588 }
589 // 'isset' is a kind of a weird alias for 'required' ...
590 elseif ($rule === 'isset' && (empty($new_rules) OR $new_rules[0] !== 'required'))
591 {
592 array_unshift($new_rules, 'isset');
593 }
594 // The old/classic 'callback_'-prefixed rules
595 elseif (is_string($rule) && strncmp('callback_', $rule, 9) === 0)
596 {
597 $callbacks[] = $rule;
598 }
599 // Proper callables
600 elseif (is_callable($rule))
601 {
602 $callbacks[] = $rule;
603 }
604 // "Named" callables; i.e. array('name' => $callable)
605 elseif (is_array($rule) && isset($rule[0], $rule[1]) && is_callable($rule[1]))
606 {
607 $callbacks[] = $rule;
608 }
609 // Everything else goes at the end of the queue
610 else
611 {
612 $new_rules[] = $rule;
613 }
614 }
615
616 return array_merge($callbacks, $new_rules);
617 }
618
619 // --------------------------------------------------------------------
620
621 /**
Derek Allard2067d1a2008-11-13 22:59:24 +0000622 * Traverse a multidimensional $_POST array index until the data is found
623 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000624 * @param array
625 * @param array
Andrey Andreev78f55772012-04-03 19:59:08 +0300626 * @param int
Derek Allard2067d1a2008-11-13 22:59:24 +0000627 * @return mixed
Barry Mienydd671972010-10-04 16:33:58 +0200628 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +0100629 protected function _reduce_array($array, $keys, $i = 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000630 {
Andrey Andreev8dc532d2011-12-24 17:57:54 +0200631 if (is_array($array) && isset($keys[$i]))
Derek Allard2067d1a2008-11-13 22:59:24 +0000632 {
Andrey Andreev8dc532d2011-12-24 17:57:54 +0200633 return isset($array[$keys[$i]]) ? $this->_reduce_array($array[$keys[$i]], $keys, ($i+1)) : NULL;
Derek Allard2067d1a2008-11-13 22:59:24 +0000634 }
Barry Mienydd671972010-10-04 16:33:58 +0200635
Andrey Andreev2d48b4f2012-11-23 17:33:21 +0200636 // NULL must be returned for empty fields
Andrey Andreev44c34632012-11-23 18:46:34 +0200637 return ($array === '') ? NULL : $array;
Derek Allard2067d1a2008-11-13 22:59:24 +0000638 }
639
640 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200641
Derek Allard2067d1a2008-11-13 22:59:24 +0000642 /**
643 * Re-populate the _POST array with our finalized and processed data
644 *
Andrey Andreev6de924c2012-01-20 13:18:18 +0200645 * @return void
Barry Mienydd671972010-10-04 16:33:58 +0200646 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +0100647 protected function _reset_post_array()
Derek Allard2067d1a2008-11-13 22:59:24 +0000648 {
649 foreach ($this->_field_data as $field => $row)
650 {
vlakoff1228fe22013-01-14 01:30:09 +0100651 if ($row['postdata'] !== NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000652 {
Andrey Andreev8dc532d2011-12-24 17:57:54 +0200653 if ($row['is_array'] === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000654 {
Andrey Andreev063f5d82019-01-04 14:41:47 +0200655 isset($_POST[$field]) && $_POST[$field] = is_array($row['postdata']) ? NULL : $row['postdata'];
Derek Allard2067d1a2008-11-13 22:59:24 +0000656 }
657 else
658 {
Derek Jones63eeae32009-02-10 19:08:56 +0000659 // start with a reference
660 $post_ref =& $_POST;
Barry Mienydd671972010-10-04 16:33:58 +0200661
Derek Jones63eeae32009-02-10 19:08:56 +0000662 // before we assign values, make a reference to the right POST key
Andrey Andreev8dc532d2011-12-24 17:57:54 +0200663 if (count($row['keys']) === 1)
Derek Allard2067d1a2008-11-13 22:59:24 +0000664 {
Derek Jones63eeae32009-02-10 19:08:56 +0000665 $post_ref =& $post_ref[current($row['keys'])];
Derek Allard2067d1a2008-11-13 22:59:24 +0000666 }
667 else
668 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000669 foreach ($row['keys'] as $val)
670 {
Derek Jones63eeae32009-02-10 19:08:56 +0000671 $post_ref =& $post_ref[$val];
Derek Allard2067d1a2008-11-13 22:59:24 +0000672 }
673 }
Derek Jones63eeae32009-02-10 19:08:56 +0000674
Andrey Andreev5576d2c2016-03-16 12:16:45 +0200675 $post_ref = $row['postdata'];
Derek Allard2067d1a2008-11-13 22:59:24 +0000676 }
677 }
678 }
679 }
680
681 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200682
Derek Allard2067d1a2008-11-13 22:59:24 +0000683 /**
684 * Executes the Validation routines
685 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000686 * @param array
687 * @param array
688 * @param mixed
Andrey Andreev78f55772012-04-03 19:59:08 +0300689 * @param int
Derek Allard2067d1a2008-11-13 22:59:24 +0000690 * @return mixed
Barry Mienydd671972010-10-04 16:33:58 +0200691 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +0100692 protected function _execute($row, $rules, $postdata = NULL, $cycles = 0)
Derek Allard2067d1a2008-11-13 22:59:24 +0000693 {
694 // If the $_POST data is an array we will run a recursive call
Andrey Andreev7243d0b2016-03-12 11:40:34 +0200695 //
696 // Note: We MUST check if the array is empty or not!
697 // Otherwise empty arrays will always pass validation.
698 if (is_array($postdata) && ! empty($postdata))
Barry Mienydd671972010-10-04 16:33:58 +0200699 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000700 foreach ($postdata as $key => $val)
701 {
Andrey Andreev8d3099d2012-06-21 16:00:20 +0300702 $this->_execute($row, $rules, $val, $key);
Derek Allard2067d1a2008-11-13 22:59:24 +0000703 }
Barry Mienydd671972010-10-04 16:33:58 +0200704
Derek Allard2067d1a2008-11-13 22:59:24 +0000705 return;
706 }
Barry Mienydd671972010-10-04 16:33:58 +0200707
Andrey Andreev0fae6252016-05-17 13:46:55 +0300708 $rules = $this->_prepare_rules($rules);
Andrey Andreev78f55772012-04-03 19:59:08 +0300709 foreach ($rules as $rule)
Derek Allard2067d1a2008-11-13 22:59:24 +0000710 {
711 $_in_array = FALSE;
Barry Mienydd671972010-10-04 16:33:58 +0200712
Derek Allard2067d1a2008-11-13 22:59:24 +0000713 // We set the $postdata variable with the current data in our master array so that
714 // each cycle of the loop is dealing with the processed data from the last cycle
Alex Bilbied261b1e2012-06-02 11:12:16 +0100715 if ($row['is_array'] === TRUE && is_array($this->_field_data[$row['field']]['postdata']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000716 {
717 // We shouldn't need this safety, but just in case there isn't an array index
718 // associated with this cycle we'll bail out
719 if ( ! isset($this->_field_data[$row['field']]['postdata'][$cycles]))
720 {
721 continue;
722 }
Barry Mienydd671972010-10-04 16:33:58 +0200723
Derek Allard2067d1a2008-11-13 22:59:24 +0000724 $postdata = $this->_field_data[$row['field']]['postdata'][$cycles];
725 $_in_array = TRUE;
726 }
727 else
728 {
Andrey Andreev6ac51442012-06-18 13:05:17 +0300729 // If we get an array field, but it's not expected - then it is most likely
730 // somebody messing with the form on the client side, so we'll just consider
731 // it an empty field
732 $postdata = is_array($this->_field_data[$row['field']]['postdata'])
Andrey Andreev4b90a372014-03-10 10:24:24 +0200733 ? NULL
734 : $this->_field_data[$row['field']]['postdata'];
Derek Allard2067d1a2008-11-13 22:59:24 +0000735 }
736
Barry Mienydd671972010-10-04 16:33:58 +0200737 // Is the rule a callback?
Andrey Andreev4b90a372014-03-10 10:24:24 +0200738 $callback = $callable = FALSE;
739 if (is_string($rule))
Derek Allard2067d1a2008-11-13 22:59:24 +0000740 {
Andrey Andreev4b90a372014-03-10 10:24:24 +0200741 if (strpos($rule, 'callback_') === 0)
742 {
743 $rule = substr($rule, 9);
744 $callback = TRUE;
745 }
746 }
747 elseif (is_callable($rule))
748 {
749 $callable = TRUE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000750 }
Andrey Andreev60726ef2014-09-08 11:31:48 +0300751 elseif (is_array($rule) && isset($rule[0], $rule[1]) && is_callable($rule[1]))
752 {
753 // We have a "named" callable, so save the name
754 $callable = $rule[0];
755 $rule = $rule[1];
756 }
Barry Mienydd671972010-10-04 16:33:58 +0200757
Derek Allard2067d1a2008-11-13 22:59:24 +0000758 // Strip the parameter (if exists) from the rule
759 // Rules can contain a parameter: max_length[5]
760 $param = FALSE;
Andrey Andreev4b90a372014-03-10 10:24:24 +0200761 if ( ! $callable && preg_match('/(.*?)\[(.*)\]/', $rule, $match))
Derek Allard2067d1a2008-11-13 22:59:24 +0000762 {
Andrey Andreevef758bd2012-11-15 12:24:52 +0200763 $rule = $match[1];
764 $param = $match[2];
Derek Allard2067d1a2008-11-13 22:59:24 +0000765 }
Barry Mienydd671972010-10-04 16:33:58 +0200766
Andrey Andreev9e78be02016-05-25 10:54:36 +0300767 // Ignore empty, non-required inputs with a few exceptions ...
768 if (
769 ($postdata === NULL OR $postdata === '')
770 && $callback === FALSE
771 && $callable === FALSE
772 && ! in_array($rule, array('required', 'isset', 'matches'), TRUE)
773 )
774 {
775 continue;
776 }
777
Derek Allard2067d1a2008-11-13 22:59:24 +0000778 // Call the function that corresponds to the rule
Andrey Andreev60726ef2014-09-08 11:31:48 +0300779 if ($callback OR $callable !== FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000780 {
Andrey Andreev4b90a372014-03-10 10:24:24 +0200781 if ($callback)
Barry Mienydd671972010-10-04 16:33:58 +0200782 {
Andrey Andreev4b90a372014-03-10 10:24:24 +0200783 if ( ! method_exists($this->CI, $rule))
784 {
785 log_message('debug', 'Unable to find callback validation rule: '.$rule);
786 $result = FALSE;
787 }
788 else
789 {
790 // Run the function and grab the result
791 $result = $this->CI->$rule($postdata, $param);
792 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000793 }
Andrey Andreev901573c2012-01-11 01:40:48 +0200794 else
795 {
Andrey Andreev4b90a372014-03-10 10:24:24 +0200796 $result = is_array($rule)
Andrey Andreev60726ef2014-09-08 11:31:48 +0300797 ? $rule[0]->{$rule[1]}($postdata)
798 : $rule($postdata);
799
800 // Is $callable set to a rule name?
801 if ($callable !== FALSE)
802 {
803 $rule = $callable;
804 }
Andrey Andreev901573c2012-01-11 01:40:48 +0200805 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000806
807 // Re-assign the result to the master data array
Andrey Andreev8dc532d2011-12-24 17:57:54 +0200808 if ($_in_array === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000809 {
Andrey Andreev78f55772012-04-03 19:59:08 +0300810 $this->_field_data[$row['field']]['postdata'][$cycles] = is_bool($result) ? $postdata : $result;
Derek Allard2067d1a2008-11-13 22:59:24 +0000811 }
812 else
813 {
Andrey Andreev78f55772012-04-03 19:59:08 +0300814 $this->_field_data[$row['field']]['postdata'] = is_bool($result) ? $postdata : $result;
Derek Allard2067d1a2008-11-13 22:59:24 +0000815 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000816 }
Andrey Andreev78f55772012-04-03 19:59:08 +0300817 elseif ( ! method_exists($this, $rule))
Barry Mienydd671972010-10-04 16:33:58 +0200818 {
Andrey Andreev78f55772012-04-03 19:59:08 +0300819 // If our own wrapper function doesn't exist we see if a native PHP function does.
820 // Users can use any native PHP function call that has one param.
821 if (function_exists($rule))
Derek Allard2067d1a2008-11-13 22:59:24 +0000822 {
Andrey Andreev4b90a372014-03-10 10:24:24 +0200823 // Native PHP functions issue warnings if you pass them more parameters than they use
Andrey Andreev320d37c2012-04-03 20:21:39 +0300824 $result = ($param !== FALSE) ? $rule($postdata, $param) : $rule($postdata);
Barry Mienydd671972010-10-04 16:33:58 +0200825
Andrey Andreev78f55772012-04-03 19:59:08 +0300826 if ($_in_array === TRUE)
827 {
828 $this->_field_data[$row['field']]['postdata'][$cycles] = is_bool($result) ? $postdata : $result;
Derek Allard2067d1a2008-11-13 22:59:24 +0000829 }
patwork02404a12011-04-08 15:45:46 +0200830 else
831 {
Andrey Andreevcec2ba52012-04-03 20:26:38 +0300832 $this->_field_data[$row['field']]['postdata'] = is_bool($result) ? $postdata : $result;
patwork02404a12011-04-08 15:45:46 +0200833 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000834 }
Andrey Andreev901573c2012-01-11 01:40:48 +0200835 else
836 {
Andrey Andreevcec2ba52012-04-03 20:26:38 +0300837 log_message('debug', 'Unable to find validation rule: '.$rule);
838 $result = FALSE;
Andrey Andreev901573c2012-01-11 01:40:48 +0200839 }
Andrey Andreev78f55772012-04-03 19:59:08 +0300840 }
Derek Allard2067d1a2008-11-13 22:59:24 +0000841 else
842 {
Derek Allard2067d1a2008-11-13 22:59:24 +0000843 $result = $this->$rule($postdata, $param);
844
Andrey Andreev8dc532d2011-12-24 17:57:54 +0200845 if ($_in_array === TRUE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000846 {
Andrey Andreev78f55772012-04-03 19:59:08 +0300847 $this->_field_data[$row['field']]['postdata'][$cycles] = is_bool($result) ? $postdata : $result;
Derek Allard2067d1a2008-11-13 22:59:24 +0000848 }
849 else
850 {
Andrey Andreev78f55772012-04-03 19:59:08 +0300851 $this->_field_data[$row['field']]['postdata'] = is_bool($result) ? $postdata : $result;
Derek Allard2067d1a2008-11-13 22:59:24 +0000852 }
853 }
Barry Mienydd671972010-10-04 16:33:58 +0200854
Andrey Andreev901573c2012-01-11 01:40:48 +0200855 // Did the rule test negatively? If so, grab the error.
Derek Allard2067d1a2008-11-13 22:59:24 +0000856 if ($result === FALSE)
Barry Mienydd671972010-10-04 16:33:58 +0200857 {
Andrey Andreev60726ef2014-09-08 11:31:48 +0300858 // Callable rules might not have named error messages
Andrey Andreev57f10052014-06-07 12:22:37 +0300859 if ( ! is_string($rule))
Ahmedul Haque Abid42b40002014-01-09 01:10:25 +0600860 {
Andrey Andreev38b5eb02015-06-10 17:38:26 +0300861 $line = $this->CI->lang->line('form_validation_error_message_not_set').'(Anonymous function)';
Andrey Andreev57f10052014-06-07 12:22:37 +0300862 }
Andrey Andreev57f10052014-06-07 12:22:37 +0300863 else
864 {
Andrey Andreev98c14ae2016-02-09 23:43:55 +0200865 $line = $this->_get_error_message($rule, $row['field']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000866 }
Barry Mienydd671972010-10-04 16:33:58 +0200867
Derek Allard2067d1a2008-11-13 22:59:24 +0000868 // Is the parameter we are inserting into the error message the name
Andrey Andreev901573c2012-01-11 01:40:48 +0200869 // of another field? If so we need to grab its "field label"
Andrey Andreev8dc532d2011-12-24 17:57:54 +0200870 if (isset($this->_field_data[$param], $this->_field_data[$param]['label']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000871 {
Pascal Krietec1895832009-10-13 12:56:43 +0000872 $param = $this->_translate_fieldname($this->_field_data[$param]['label']);
Derek Allard2067d1a2008-11-13 22:59:24 +0000873 }
Barry Mienydd671972010-10-04 16:33:58 +0200874
Derek Allard2067d1a2008-11-13 22:59:24 +0000875 // Build the error message
Eric Roberts41cc0902012-01-24 00:59:44 -0600876 $message = $this->_build_error_msg($line, $this->_translate_fieldname($row['label']), $param);
Derek Allard2067d1a2008-11-13 22:59:24 +0000877
878 // Save the error message
879 $this->_field_data[$row['field']]['error'] = $message;
Barry Mienydd671972010-10-04 16:33:58 +0200880
Derek Allard2067d1a2008-11-13 22:59:24 +0000881 if ( ! isset($this->_error_array[$row['field']]))
882 {
883 $this->_error_array[$row['field']] = $message;
884 }
Barry Mienydd671972010-10-04 16:33:58 +0200885
Derek Allard2067d1a2008-11-13 22:59:24 +0000886 return;
887 }
888 }
889 }
890
891 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200892
Derek Allard2067d1a2008-11-13 22:59:24 +0000893 /**
Andrey Andreev98c14ae2016-02-09 23:43:55 +0200894 * Get the error message for the rule
895 *
896 * @param string $rule The rule name
897 * @param string $field The field name
898 * @return string
899 */
900 protected function _get_error_message($rule, $field)
901 {
902 // check if a custom message is defined through validation config row.
903 if (isset($this->_field_data[$field]['errors'][$rule]))
904 {
905 return $this->_field_data[$field]['errors'][$rule];
906 }
907 // check if a custom message has been set using the set_message() function
908 elseif (isset($this->_error_messages[$rule]))
909 {
910 return $this->_error_messages[$rule];
911 }
Andrey Andreevb30a64a2016-02-09 23:46:25 +0200912 elseif (FALSE !== ($line = $this->CI->lang->line('form_validation_'.$rule)))
Andrey Andreev98c14ae2016-02-09 23:43:55 +0200913 {
Andrey Andreevb30a64a2016-02-09 23:46:25 +0200914 return $line;
Andrey Andreev98c14ae2016-02-09 23:43:55 +0200915 }
916 // DEPRECATED support for non-prefixed keys, lang file again
Andrey Andreevb30a64a2016-02-09 23:46:25 +0200917 elseif (FALSE !== ($line = $this->CI->lang->line($rule, FALSE)))
Andrey Andreev98c14ae2016-02-09 23:43:55 +0200918 {
Andrey Andreevb30a64a2016-02-09 23:46:25 +0200919 return $line;
Andrey Andreev98c14ae2016-02-09 23:43:55 +0200920 }
921
922 return $this->CI->lang->line('form_validation_error_message_not_set').'('.$rule.')';
923 }
924
925 // --------------------------------------------------------------------
926
927 /**
Derek Allard2067d1a2008-11-13 22:59:24 +0000928 * Translate a field name
929 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000930 * @param string the field name
931 * @return string
Barry Mienydd671972010-10-04 16:33:58 +0200932 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +0100933 protected function _translate_fieldname($fieldname)
Derek Allard2067d1a2008-11-13 22:59:24 +0000934 {
Andrey Andreev5d8e2a62015-04-14 16:56:28 +0300935 // Do we need to translate the field name? We look for the prefix 'lang:' to determine this
936 // If we find one, but there's no translation for the string - just return it
937 if (sscanf($fieldname, 'lang:%s', $line) === 1 && FALSE === ($fieldname = $this->CI->lang->line($line, FALSE)))
Derek Allard2067d1a2008-11-13 22:59:24 +0000938 {
Andrey Andreev5d8e2a62015-04-14 16:56:28 +0300939 return $line;
Derek Allard2067d1a2008-11-13 22:59:24 +0000940 }
941
942 return $fieldname;
943 }
944
945 // --------------------------------------------------------------------
Andrey Andreevd4eec9f2012-12-14 11:07:13 +0200946
Eric Roberts41cc0902012-01-24 00:59:44 -0600947 /**
948 * Build an error message using the field and param.
949 *
950 * @param string The error message line
951 * @param string A field's human name
952 * @param mixed A rule's optional parameter
953 * @return string
954 */
955 protected function _build_error_msg($line, $field = '', $param = '')
956 {
957 // Check for %s in the string for legacy support.
Eric Roberts24a13f52012-12-12 07:09:42 -0600958 if (strpos($line, '%s') !== FALSE)
Eric Roberts41cc0902012-01-24 00:59:44 -0600959 {
960 return sprintf($line, $field, $param);
961 }
Andrew Podner4296a652012-12-17 07:51:15 -0500962
Eric Roberts41cc0902012-01-24 00:59:44 -0600963 return str_replace(array('{field}', '{param}'), array($field, $param), $line);
964 }
965
966 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +0200967
Derek Allard2067d1a2008-11-13 22:59:24 +0000968 /**
nisheeth-barthwala7447d22013-03-21 15:48:10 +0530969 * Checks if the rule is present within the validator
970 *
971 * Permits you to check if a rule is present within the validator
972 *
973 * @param string the field name
974 * @return bool
975 */
976 public function has_rule($field)
977 {
978 return isset($this->_field_data[$field]);
979 }
980
981 // --------------------------------------------------------------------
982
983 /**
Derek Allard2067d1a2008-11-13 22:59:24 +0000984 * Get the value from a form
985 *
986 * Permits you to repopulate a form field with the value it was submitted
987 * with, or, if that value doesn't exist, with the default
988 *
Derek Allard2067d1a2008-11-13 22:59:24 +0000989 * @param string the field name
990 * @param string
Andrey Andreev46ac8812012-02-28 14:32:54 +0200991 * @return string
Barry Mienydd671972010-10-04 16:33:58 +0200992 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +0100993 public function set_value($field = '', $default = '')
Derek Allard2067d1a2008-11-13 22:59:24 +0000994 {
Andrey Andreev46ac8812012-02-28 14:32:54 +0200995 if ( ! isset($this->_field_data[$field], $this->_field_data[$field]['postdata']))
Derek Allard2067d1a2008-11-13 22:59:24 +0000996 {
997 return $default;
998 }
Barry Mienydd671972010-10-04 16:33:58 +0200999
Phil Sturgeon5c561802011-01-05 16:31:59 +00001000 // If the data is an array output them one at a time.
Greg Aker03abee32011-12-25 00:31:29 -06001001 // E.g: form_input('name[]', set_value('name[]');
Phil Sturgeon5c561802011-01-05 16:31:59 +00001002 if (is_array($this->_field_data[$field]['postdata']))
1003 {
1004 return array_shift($this->_field_data[$field]['postdata']);
1005 }
Phil Sturgeonc3828712011-01-19 12:31:47 +00001006
Derek Allard2067d1a2008-11-13 22:59:24 +00001007 return $this->_field_data[$field]['postdata'];
1008 }
Barry Mienydd671972010-10-04 16:33:58 +02001009
Derek Allard2067d1a2008-11-13 22:59:24 +00001010 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001011
Derek Allard2067d1a2008-11-13 22:59:24 +00001012 /**
1013 * Set Select
1014 *
1015 * Enables pull-down lists to be set to the value the user
1016 * selected in the event of an error
1017 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001018 * @param string
1019 * @param string
Timothy Warren0688ac92012-04-20 10:25:04 -04001020 * @param bool
Derek Allard2067d1a2008-11-13 22:59:24 +00001021 * @return string
Barry Mienydd671972010-10-04 16:33:58 +02001022 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001023 public function set_select($field = '', $value = '', $default = FALSE)
Barry Mienydd671972010-10-04 16:33:58 +02001024 {
Andrey Andreev46ac8812012-02-28 14:32:54 +02001025 if ( ! isset($this->_field_data[$field], $this->_field_data[$field]['postdata']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001026 {
Andrey Andreev6de924c2012-01-20 13:18:18 +02001027 return ($default === TRUE && count($this->_field_data) === 0) ? ' selected="selected"' : '';
Derek Allard2067d1a2008-11-13 22:59:24 +00001028 }
Barry Mienydd671972010-10-04 16:33:58 +02001029
Derek Allard2067d1a2008-11-13 22:59:24 +00001030 $field = $this->_field_data[$field]['postdata'];
Andrey Andreeva587a932013-10-23 19:57:46 +03001031 $value = (string) $value;
Derek Allard2067d1a2008-11-13 22:59:24 +00001032 if (is_array($field))
1033 {
Andrey Andreeva587a932013-10-23 19:57:46 +03001034 // Note: in_array('', array(0)) returns TRUE, do not use it
1035 foreach ($field as &$v)
Derek Allard2067d1a2008-11-13 22:59:24 +00001036 {
Andrey Andreeva587a932013-10-23 19:57:46 +03001037 if ($value === $v)
1038 {
1039 return ' selected="selected"';
1040 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001041 }
Andrey Andreeva587a932013-10-23 19:57:46 +03001042
1043 return '';
Derek Allard2067d1a2008-11-13 22:59:24 +00001044 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001045 elseif (($field === '' OR $value === '') OR ($field !== $value))
Derek Allard2067d1a2008-11-13 22:59:24 +00001046 {
Andrey Andreev901573c2012-01-11 01:40:48 +02001047 return '';
Derek Allard2067d1a2008-11-13 22:59:24 +00001048 }
Barry Mienydd671972010-10-04 16:33:58 +02001049
Derek Allard2067d1a2008-11-13 22:59:24 +00001050 return ' selected="selected"';
1051 }
Barry Mienydd671972010-10-04 16:33:58 +02001052
Derek Allard2067d1a2008-11-13 22:59:24 +00001053 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001054
Derek Allard2067d1a2008-11-13 22:59:24 +00001055 /**
1056 * Set Radio
1057 *
1058 * Enables radio buttons to be set to the value the user
1059 * selected in the event of an error
1060 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001061 * @param string
1062 * @param string
Timothy Warren0688ac92012-04-20 10:25:04 -04001063 * @param bool
Derek Allard2067d1a2008-11-13 22:59:24 +00001064 * @return string
Barry Mienydd671972010-10-04 16:33:58 +02001065 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001066 public function set_radio($field = '', $value = '', $default = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001067 {
Andrey Andreev46ac8812012-02-28 14:32:54 +02001068 if ( ! isset($this->_field_data[$field], $this->_field_data[$field]['postdata']))
Derek Allard2067d1a2008-11-13 22:59:24 +00001069 {
Andrey Andreev6de924c2012-01-20 13:18:18 +02001070 return ($default === TRUE && count($this->_field_data) === 0) ? ' checked="checked"' : '';
Derek Allard2067d1a2008-11-13 22:59:24 +00001071 }
Barry Mienydd671972010-10-04 16:33:58 +02001072
Derek Allard2067d1a2008-11-13 22:59:24 +00001073 $field = $this->_field_data[$field]['postdata'];
Andrey Andreeva587a932013-10-23 19:57:46 +03001074 $value = (string) $value;
Derek Allard2067d1a2008-11-13 22:59:24 +00001075 if (is_array($field))
1076 {
Andrey Andreeva587a932013-10-23 19:57:46 +03001077 // Note: in_array('', array(0)) returns TRUE, do not use it
1078 foreach ($field as &$v)
Derek Allard2067d1a2008-11-13 22:59:24 +00001079 {
Andrey Andreeva587a932013-10-23 19:57:46 +03001080 if ($value === $v)
1081 {
1082 return ' checked="checked"';
1083 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001084 }
Andrey Andreeva587a932013-10-23 19:57:46 +03001085
1086 return '';
Derek Allard2067d1a2008-11-13 22:59:24 +00001087 }
Alex Bilbied261b1e2012-06-02 11:12:16 +01001088 elseif (($field === '' OR $value === '') OR ($field !== $value))
Derek Allard2067d1a2008-11-13 22:59:24 +00001089 {
Andrey Andreev901573c2012-01-11 01:40:48 +02001090 return '';
Derek Allard2067d1a2008-11-13 22:59:24 +00001091 }
Barry Mienydd671972010-10-04 16:33:58 +02001092
Derek Allard2067d1a2008-11-13 22:59:24 +00001093 return ' checked="checked"';
1094 }
Barry Mienydd671972010-10-04 16:33:58 +02001095
Derek Allard2067d1a2008-11-13 22:59:24 +00001096 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001097
Derek Allard2067d1a2008-11-13 22:59:24 +00001098 /**
1099 * Set Checkbox
1100 *
1101 * Enables checkboxes to be set to the value the user
1102 * selected in the event of an error
1103 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001104 * @param string
1105 * @param string
Timothy Warren0688ac92012-04-20 10:25:04 -04001106 * @param bool
Derek Allard2067d1a2008-11-13 22:59:24 +00001107 * @return string
Barry Mienydd671972010-10-04 16:33:58 +02001108 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001109 public function set_checkbox($field = '', $value = '', $default = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001110 {
Andrey Andreev8dc532d2011-12-24 17:57:54 +02001111 // Logic is exactly the same as for radio fields
1112 return $this->set_radio($field, $value, $default);
Derek Allard2067d1a2008-11-13 22:59:24 +00001113 }
Barry Mienydd671972010-10-04 16:33:58 +02001114
Derek Allard2067d1a2008-11-13 22:59:24 +00001115 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001116
Derek Allard2067d1a2008-11-13 22:59:24 +00001117 /**
1118 * Required
1119 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001120 * @param string
1121 * @return bool
1122 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001123 public function required($str)
Derek Allard2067d1a2008-11-13 22:59:24 +00001124 {
Andrey Andreev0fae6252016-05-17 13:46:55 +03001125 return is_array($str)
1126 ? (empty($str) === FALSE)
1127 : (trim($str) !== '');
Derek Allard2067d1a2008-11-13 22:59:24 +00001128 }
Barry Mienydd671972010-10-04 16:33:58 +02001129
Derek Allard2067d1a2008-11-13 22:59:24 +00001130 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001131
Derek Allard2067d1a2008-11-13 22:59:24 +00001132 /**
Dan Horrigan2280e8e2010-12-15 10:16:38 -05001133 * Performs a Regular Expression match test.
1134 *
Dan Horrigan2280e8e2010-12-15 10:16:38 -05001135 * @param string
Andrey Andreev78f55772012-04-03 19:59:08 +03001136 * @param string regex
Dan Horrigan2280e8e2010-12-15 10:16:38 -05001137 * @return bool
1138 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001139 public function regex_match($str, $regex)
Dan Horrigan2280e8e2010-12-15 10:16:38 -05001140 {
Andrey Andreev8dc532d2011-12-24 17:57:54 +02001141 return (bool) preg_match($regex, $str);
Dan Horrigan2280e8e2010-12-15 10:16:38 -05001142 }
1143
1144 // --------------------------------------------------------------------
1145
1146 /**
Derek Allard2067d1a2008-11-13 22:59:24 +00001147 * Match one field to another
1148 *
Andrey Andreeva779b2c2012-10-26 16:25:47 +03001149 * @param string $str string to compare against
1150 * @param string $field
Derek Allard2067d1a2008-11-13 22:59:24 +00001151 * @return bool
1152 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001153 public function matches($str, $field)
Derek Allard2067d1a2008-11-13 22:59:24 +00001154 {
Andrey Andreeva779b2c2012-10-26 16:25:47 +03001155 return isset($this->_field_data[$field], $this->_field_data[$field]['postdata'])
1156 ? ($str === $this->_field_data[$field]['postdata'])
1157 : FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +00001158 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001159
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001160 // --------------------------------------------------------------------
1161
1162 /**
Raul Baldner Juniorf38564d2012-10-11 11:32:23 -03001163 * Differs from another field
1164 *
1165 * @param string
1166 * @param string field
1167 * @return bool
1168 */
1169 public function differs($str, $field)
1170 {
1171 return ! (isset($this->_field_data[$field]) && $this->_field_data[$field]['postdata'] === $str);
Derek Allard2067d1a2008-11-13 22:59:24 +00001172 }
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001173
1174 // --------------------------------------------------------------------
1175
1176 /**
Andrey Andreevd09d6502012-01-03 06:38:33 +02001177 * Is Unique
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001178 *
Andrey Andreevd09d6502012-01-03 06:38:33 +02001179 * Check if the input value doesn't already exist
1180 * in the specified database field.
1181 *
Andrey Andreev9a0e0c72014-04-09 15:10:27 +03001182 * @param string $str
1183 * @param string $field
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001184 * @return bool
1185 */
1186 public function is_unique($str, $field)
1187 {
Andrey Andreev7a7ad782012-11-12 17:21:01 +02001188 sscanf($field, '%[^.].%[^.]', $table, $field);
Andrey Andreev9a0e0c72014-04-09 15:10:27 +03001189 return isset($this->CI->db)
1190 ? ($this->CI->db->limit(1)->get_where($table, array($field => $str))->num_rows() === 0)
1191 : FALSE;
Greg Aker03abee32011-12-25 00:31:29 -06001192 }
Barry Mienydd671972010-10-04 16:33:58 +02001193
Derek Allard2067d1a2008-11-13 22:59:24 +00001194 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001195
Derek Allard2067d1a2008-11-13 22:59:24 +00001196 /**
1197 * Minimum Length
1198 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001199 * @param string
Michiel Vugteveena8221ad2012-06-14 23:26:34 +02001200 * @param string
Derek Allard2067d1a2008-11-13 22:59:24 +00001201 * @return bool
Barry Mienydd671972010-10-04 16:33:58 +02001202 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001203 public function min_length($str, $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001204 {
Michiel Vugteveenceaf8872012-06-15 11:56:24 +02001205 if ( ! is_numeric($val))
Derek Allard2067d1a2008-11-13 22:59:24 +00001206 {
1207 return FALSE;
1208 }
1209
bjjay8d6c8fe2015-03-09 13:46:06 +08001210 return ($val <= mb_strlen($str));
Derek Allard2067d1a2008-11-13 22:59:24 +00001211 }
Barry Mienydd671972010-10-04 16:33:58 +02001212
Derek Allard2067d1a2008-11-13 22:59:24 +00001213 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001214
Derek Allard2067d1a2008-11-13 22:59:24 +00001215 /**
1216 * Max Length
1217 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001218 * @param string
Michiel Vugteveena8221ad2012-06-14 23:26:34 +02001219 * @param string
Derek Allard2067d1a2008-11-13 22:59:24 +00001220 * @return bool
Barry Mienydd671972010-10-04 16:33:58 +02001221 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001222 public function max_length($str, $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001223 {
Michiel Vugteveenceaf8872012-06-15 11:56:24 +02001224 if ( ! is_numeric($val))
Derek Allard2067d1a2008-11-13 22:59:24 +00001225 {
1226 return FALSE;
1227 }
1228
bjjay8d6c8fe2015-03-09 13:46:06 +08001229 return ($val >= mb_strlen($str));
Derek Allard2067d1a2008-11-13 22:59:24 +00001230 }
Barry Mienydd671972010-10-04 16:33:58 +02001231
Derek Allard2067d1a2008-11-13 22:59:24 +00001232 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001233
Derek Allard2067d1a2008-11-13 22:59:24 +00001234 /**
1235 * Exact Length
1236 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001237 * @param string
Michiel Vugteveeneccde132012-06-14 23:22:26 +02001238 * @param string
Derek Allard2067d1a2008-11-13 22:59:24 +00001239 * @return bool
Barry Mienydd671972010-10-04 16:33:58 +02001240 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001241 public function exact_length($str, $val)
Derek Allard2067d1a2008-11-13 22:59:24 +00001242 {
Michiel Vugteveenceaf8872012-06-15 11:56:24 +02001243 if ( ! is_numeric($val))
Derek Allard2067d1a2008-11-13 22:59:24 +00001244 {
1245 return FALSE;
1246 }
1247
bjjay8d6c8fe2015-03-09 13:46:06 +08001248 return (mb_strlen($str) === (int) $val);
Derek Allard2067d1a2008-11-13 22:59:24 +00001249 }
Barry Mienydd671972010-10-04 16:33:58 +02001250
Derek Allard2067d1a2008-11-13 22:59:24 +00001251 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001252
Derek Allard2067d1a2008-11-13 22:59:24 +00001253 /**
Andrey Andreevdaaca882012-11-26 22:16:12 +02001254 * Valid URL
1255 *
1256 * @param string $str
1257 * @return bool
1258 */
1259 public function valid_url($str)
1260 {
1261 if (empty($str))
1262 {
1263 return FALSE;
1264 }
1265 elseif (preg_match('/^(?:([^:]*)\:)?\/\/(.+)$/', $str, $matches))
1266 {
1267 if (empty($matches[2]))
1268 {
1269 return FALSE;
1270 }
Andrey Andreeve33c82d2016-08-10 15:18:31 +03001271 elseif ( ! in_array(strtolower($matches[1]), array('http', 'https'), TRUE))
Andrey Andreevdaaca882012-11-26 22:16:12 +02001272 {
1273 return FALSE;
1274 }
1275
1276 $str = $matches[2];
1277 }
1278
Andrey Andreev391d3392016-01-30 22:43:41 +02001279 // PHP 7 accepts IPv6 addresses within square brackets as hostnames,
1280 // but it appears that the PR that came in with https://bugs.php.net/bug.php?id=68039
1281 // was never merged into a PHP 5 branch ... https://3v4l.org/8PsSN
1282 if (preg_match('/^\[([^\]]+)\]/', $str, $matches) && ! is_php('7') && filter_var($matches[1], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== FALSE)
1283 {
1284 $str = 'ipv6.host'.substr($str, strlen($matches[1]) + 2);
1285 }
1286
Andrey Andreeva8382792016-07-28 16:40:12 +03001287 return (filter_var('http://'.$str, FILTER_VALIDATE_URL) !== FALSE);
Derek Allard2067d1a2008-11-13 22:59:24 +00001288 }
1289
1290 // --------------------------------------------------------------------
1291
1292 /**
1293 * Valid Email
1294 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001295 * @param string
1296 * @return bool
Barry Mienydd671972010-10-04 16:33:58 +02001297 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001298 public function valid_email($str)
Derek Allard2067d1a2008-11-13 22:59:24 +00001299 {
Andrey Andreeved1a0452017-06-19 08:25:23 +03001300 if (function_exists('idn_to_ascii') && preg_match('#\A([^@]+)@(.+)\z#', $str, $matches))
Andrey Andreev95496662014-06-01 00:00:13 +03001301 {
Andrey Andreev221c0952018-01-22 10:29:19 +02001302 $domain = defined('INTL_IDNA_VARIANT_UTS46')
Andrey Andreev4fd2d492017-11-09 20:38:33 +02001303 ? idn_to_ascii($matches[2], 0, INTL_IDNA_VARIANT_UTS46)
1304 : idn_to_ascii($matches[2]);
Andrey Andreev32f8c932018-06-12 16:25:44 +03001305
1306 if ($domain !== FALSE)
1307 {
1308 $str = $matches[1].'@'.$domain;
1309 }
Andrey Andreev95496662014-06-01 00:00:13 +03001310 }
1311
Andrey Andreev580388b2012-06-27 15:43:46 +03001312 return (bool) filter_var($str, FILTER_VALIDATE_EMAIL);
Derek Allard2067d1a2008-11-13 22:59:24 +00001313 }
1314
1315 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001316
Derek Allard2067d1a2008-11-13 22:59:24 +00001317 /**
1318 * Valid Emails
1319 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001320 * @param string
1321 * @return bool
Barry Mienydd671972010-10-04 16:33:58 +02001322 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001323 public function valid_emails($str)
Derek Allard2067d1a2008-11-13 22:59:24 +00001324 {
1325 if (strpos($str, ',') === FALSE)
1326 {
1327 return $this->valid_email(trim($str));
1328 }
Barry Mienydd671972010-10-04 16:33:58 +02001329
Pascal Kriete14287f32011-02-14 13:39:34 -05001330 foreach (explode(',', $str) as $email)
Derek Allard2067d1a2008-11-13 22:59:24 +00001331 {
Andrey Andreev8dc532d2011-12-24 17:57:54 +02001332 if (trim($email) !== '' && $this->valid_email(trim($email)) === FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +00001333 {
1334 return FALSE;
1335 }
1336 }
Barry Mienydd671972010-10-04 16:33:58 +02001337
Derek Allard2067d1a2008-11-13 22:59:24 +00001338 return TRUE;
1339 }
1340
1341 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001342
Derek Allard2067d1a2008-11-13 22:59:24 +00001343 /**
1344 * Validate IP Address
1345 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001346 * @param string
Andrey Andreev5a257182012-06-10 06:18:14 +03001347 * @param string 'ipv4' or 'ipv6' to validate a specific IP format
Bo-Yi Wu013c8952011-09-12 15:03:44 +08001348 * @return bool
Derek Allard2067d1a2008-11-13 22:59:24 +00001349 */
Andrey Andreev5a257182012-06-10 06:18:14 +03001350 public function valid_ip($ip, $which = '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001351 {
Andrey Andreev5a257182012-06-10 06:18:14 +03001352 return $this->CI->input->valid_ip($ip, $which);
Derek Allard2067d1a2008-11-13 22:59:24 +00001353 }
1354
1355 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001356
Derek Allard2067d1a2008-11-13 22:59:24 +00001357 /**
1358 * Alpha
1359 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001360 * @param string
1361 * @return bool
Barry Mienydd671972010-10-04 16:33:58 +02001362 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001363 public function alpha($str)
Derek Allard2067d1a2008-11-13 22:59:24 +00001364 {
Andrey Andreevacb962e2012-06-27 12:04:24 +03001365 return ctype_alpha($str);
Derek Allard2067d1a2008-11-13 22:59:24 +00001366 }
Barry Mienydd671972010-10-04 16:33:58 +02001367
Derek Allard2067d1a2008-11-13 22:59:24 +00001368 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001369
Derek Allard2067d1a2008-11-13 22:59:24 +00001370 /**
1371 * Alpha-numeric
1372 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001373 * @param string
1374 * @return bool
Barry Mienydd671972010-10-04 16:33:58 +02001375 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001376 public function alpha_numeric($str)
Derek Allard2067d1a2008-11-13 22:59:24 +00001377 {
Andrey Andreevacb962e2012-06-27 12:04:24 +03001378 return ctype_alnum((string) $str);
Derek Allard2067d1a2008-11-13 22:59:24 +00001379 }
Barry Mienydd671972010-10-04 16:33:58 +02001380
Derek Allard2067d1a2008-11-13 22:59:24 +00001381 // --------------------------------------------------------------------
Sajan Parikh2d1608a2013-02-02 08:00:39 -06001382
1383 /**
1384 * Alpha-numeric w/ spaces
1385 *
1386 * @param string
1387 * @return bool
1388 */
1389 public function alpha_numeric_spaces($str)
1390 {
Sajan Parikhdf3bfed2013-02-04 12:25:49 -06001391 return (bool) preg_match('/^[A-Z0-9 ]+$/i', $str);
Sajan Parikh2d1608a2013-02-02 08:00:39 -06001392 }
1393
1394 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001395
Derek Allard2067d1a2008-11-13 22:59:24 +00001396 /**
1397 * Alpha-numeric with underscores and dashes
1398 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001399 * @param string
1400 * @return bool
Barry Mienydd671972010-10-04 16:33:58 +02001401 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001402 public function alpha_dash($str)
Derek Allard2067d1a2008-11-13 22:59:24 +00001403 {
Andrey Andreev8dc532d2011-12-24 17:57:54 +02001404 return (bool) preg_match('/^[a-z0-9_-]+$/i', $str);
Derek Allard2067d1a2008-11-13 22:59:24 +00001405 }
Barry Mienydd671972010-10-04 16:33:58 +02001406
Derek Allard2067d1a2008-11-13 22:59:24 +00001407 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001408
Derek Allard2067d1a2008-11-13 22:59:24 +00001409 /**
1410 * Numeric
1411 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001412 * @param string
1413 * @return bool
Barry Mienydd671972010-10-04 16:33:58 +02001414 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001415 public function numeric($str)
Derek Allard2067d1a2008-11-13 22:59:24 +00001416 {
Andrey Andreev8dc532d2011-12-24 17:57:54 +02001417 return (bool) preg_match('/^[\-+]?[0-9]*\.?[0-9]+$/', $str);
Derek Allard2067d1a2008-11-13 22:59:24 +00001418
1419 }
1420
1421 // --------------------------------------------------------------------
1422
Barry Mienydd671972010-10-04 16:33:58 +02001423 /**
Derek Allard2067d1a2008-11-13 22:59:24 +00001424 * Integer
1425 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001426 * @param string
1427 * @return bool
Barry Mienydd671972010-10-04 16:33:58 +02001428 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001429 public function integer($str)
Derek Allard2067d1a2008-11-13 22:59:24 +00001430 {
Phil Sturgeonef112c02011-02-07 13:01:47 +00001431 return (bool) preg_match('/^[\-+]?[0-9]+$/', $str);
1432 }
1433
1434 // --------------------------------------------------------------------
1435
1436 /**
1437 * Decimal number
1438 *
Phil Sturgeonef112c02011-02-07 13:01:47 +00001439 * @param string
1440 * @return bool
1441 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001442 public function decimal($str)
Phil Sturgeonef112c02011-02-07 13:01:47 +00001443 {
1444 return (bool) preg_match('/^[\-+]?[0-9]+\.[0-9]+$/', $str);
1445 }
1446
1447 // --------------------------------------------------------------------
1448
1449 /**
Andrey Andreevc68905a2012-02-02 21:41:54 +02001450 * Greater than
Phil Sturgeonef112c02011-02-07 13:01:47 +00001451 *
Phil Sturgeonef112c02011-02-07 13:01:47 +00001452 * @param string
Timothy Warren0688ac92012-04-20 10:25:04 -04001453 * @param int
Phil Sturgeonef112c02011-02-07 13:01:47 +00001454 * @return bool
1455 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001456 public function greater_than($str, $min)
Phil Sturgeonef112c02011-02-07 13:01:47 +00001457 {
Andrey Andreev78f55772012-04-03 19:59:08 +03001458 return is_numeric($str) ? ($str > $min) : FALSE;
Phil Sturgeonef112c02011-02-07 13:01:47 +00001459 }
1460
1461 // --------------------------------------------------------------------
1462
1463 /**
Nick Busey98c347d2012-02-02 11:07:03 -07001464 * Equal to or Greater than
1465 *
Nick Busey98c347d2012-02-02 11:07:03 -07001466 * @param string
Timothy Warren0688ac92012-04-20 10:25:04 -04001467 * @param int
Nick Busey98c347d2012-02-02 11:07:03 -07001468 * @return bool
1469 */
Andrey Andreev3b2c5082012-03-07 22:49:24 +02001470 public function greater_than_equal_to($str, $min)
Nick Busey98c347d2012-02-02 11:07:03 -07001471 {
Andrey Andreev78f55772012-04-03 19:59:08 +03001472 return is_numeric($str) ? ($str >= $min) : FALSE;
Phil Sturgeonef112c02011-02-07 13:01:47 +00001473 }
1474
1475 // --------------------------------------------------------------------
1476
1477 /**
1478 * Less than
1479 *
Phil Sturgeonef112c02011-02-07 13:01:47 +00001480 * @param string
Timothy Warren0688ac92012-04-20 10:25:04 -04001481 * @param int
Phil Sturgeonef112c02011-02-07 13:01:47 +00001482 * @return bool
1483 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001484 public function less_than($str, $max)
Phil Sturgeonef112c02011-02-07 13:01:47 +00001485 {
Andrey Andreev78f55772012-04-03 19:59:08 +03001486 return is_numeric($str) ? ($str < $max) : FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +00001487 }
Derek Allard2067d1a2008-11-13 22:59:24 +00001488
1489 // --------------------------------------------------------------------
1490
Barry Mienydd671972010-10-04 16:33:58 +02001491 /**
Nick Busey98c347d2012-02-02 11:07:03 -07001492 * Equal to or Less than
1493 *
Nick Busey98c347d2012-02-02 11:07:03 -07001494 * @param string
Timothy Warren0688ac92012-04-20 10:25:04 -04001495 * @param int
Nick Busey98c347d2012-02-02 11:07:03 -07001496 * @return bool
1497 */
Andrey Andreev3b2c5082012-03-07 22:49:24 +02001498 public function less_than_equal_to($str, $max)
Nick Busey98c347d2012-02-02 11:07:03 -07001499 {
Andrey Andreev78f55772012-04-03 19:59:08 +03001500 return is_numeric($str) ? ($str <= $max) : FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +00001501 }
1502
1503 // --------------------------------------------------------------------
1504
Barry Mienydd671972010-10-04 16:33:58 +02001505 /**
Lance Vincenteca885d2015-01-28 17:43:23 +08001506 * Value should be within an array of values
1507 *
1508 * @param string
Andrey Andreev5b662e42015-01-29 00:13:54 +02001509 * @param string
Lance Vincenteca885d2015-01-28 17:43:23 +08001510 * @return bool
1511 */
Lance Vincent49f483d2015-01-28 22:46:19 +08001512 public function in_list($value, $list)
Lance Vincenteca885d2015-01-28 17:43:23 +08001513 {
Lance Vincent0b0117c2015-01-28 20:31:42 +08001514 return in_array($value, explode(',', $list), TRUE);
Lance Vincenteca885d2015-01-28 17:43:23 +08001515 }
1516
1517 // --------------------------------------------------------------------
1518
1519 /**
Derek Jones37f4b9c2011-07-01 17:56:50 -05001520 * Is a Natural number (0,1,2,3, etc.)
Barry Mienydd671972010-10-04 16:33:58 +02001521 *
Barry Mienydd671972010-10-04 16:33:58 +02001522 * @param string
1523 * @return bool
1524 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001525 public function is_natural($str)
Barry Mienydd671972010-10-04 16:33:58 +02001526 {
Andrey Andreevacb962e2012-06-27 12:04:24 +03001527 return ctype_digit((string) $str);
Barry Mienydd671972010-10-04 16:33:58 +02001528 }
1529
1530 // --------------------------------------------------------------------
1531
1532 /**
Derek Jones37f4b9c2011-07-01 17:56:50 -05001533 * Is a Natural number, but not a zero (1,2,3, etc.)
Barry Mienydd671972010-10-04 16:33:58 +02001534 *
Barry Mienydd671972010-10-04 16:33:58 +02001535 * @param string
1536 * @return bool
1537 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001538 public function is_natural_no_zero($str)
Barry Mienydd671972010-10-04 16:33:58 +02001539 {
Andrey Andreevacb962e2012-06-27 12:04:24 +03001540 return ($str != 0 && ctype_digit((string) $str));
Barry Mienydd671972010-10-04 16:33:58 +02001541 }
1542
Derek Allard2067d1a2008-11-13 22:59:24 +00001543 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001544
Derek Allard2067d1a2008-11-13 22:59:24 +00001545 /**
1546 * Valid Base64
1547 *
1548 * Tests a string for characters outside of the Base64 alphabet
1549 * as defined by RFC 2045 http://www.faqs.org/rfcs/rfc2045
1550 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001551 * @param string
1552 * @return bool
1553 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001554 public function valid_base64($str)
Derek Allard2067d1a2008-11-13 22:59:24 +00001555 {
Andrey Andreevcd9797a2013-06-28 14:03:48 +03001556 return (base64_encode(base64_decode($str)) === $str);
Derek Allard2067d1a2008-11-13 22:59:24 +00001557 }
Barry Mienydd671972010-10-04 16:33:58 +02001558
Derek Allard2067d1a2008-11-13 22:59:24 +00001559 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001560
Derek Allard2067d1a2008-11-13 22:59:24 +00001561 /**
1562 * Prep data for form
1563 *
1564 * This function allows HTML to be safely shown in a form.
1565 * Special characters are converted.
1566 *
Andrey Andreev4f555072016-03-12 17:21:55 +02001567 * @deprecated 3.0.6 Not used anywhere within the framework and pretty much useless
1568 * @param mixed $data Input data
1569 * @return mixed
Derek Allard2067d1a2008-11-13 22:59:24 +00001570 */
Andrey Andreev4f555072016-03-12 17:21:55 +02001571 public function prep_for_form($data)
Derek Allard2067d1a2008-11-13 22:59:24 +00001572 {
Andrey Andreev7c4d1062012-11-01 15:14:34 +02001573 if ($this->_safe_form_data === FALSE OR empty($data))
1574 {
1575 return $data;
1576 }
1577
Derek Allard2067d1a2008-11-13 22:59:24 +00001578 if (is_array($data))
1579 {
1580 foreach ($data as $key => $val)
1581 {
1582 $data[$key] = $this->prep_for_form($val);
1583 }
Barry Mienydd671972010-10-04 16:33:58 +02001584
Derek Allard2067d1a2008-11-13 22:59:24 +00001585 return $data;
1586 }
Barry Mienydd671972010-10-04 16:33:58 +02001587
Andrey Andreev901573c2012-01-11 01:40:48 +02001588 return str_replace(array("'", '"', '<', '>'), array('&#39;', '&quot;', '&lt;', '&gt;'), stripslashes($data));
Derek Allard2067d1a2008-11-13 22:59:24 +00001589 }
Barry Mienydd671972010-10-04 16:33:58 +02001590
Derek Allard2067d1a2008-11-13 22:59:24 +00001591 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001592
Derek Allard2067d1a2008-11-13 22:59:24 +00001593 /**
1594 * Prep URL
1595 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001596 * @param string
1597 * @return string
Barry Mienydd671972010-10-04 16:33:58 +02001598 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001599 public function prep_url($str = '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001600 {
Alex Bilbied261b1e2012-06-02 11:12:16 +01001601 if ($str === 'http://' OR $str === '')
Derek Allard2067d1a2008-11-13 22:59:24 +00001602 {
1603 return '';
1604 }
Barry Mienydd671972010-10-04 16:33:58 +02001605
Andrey Andreev901573c2012-01-11 01:40:48 +02001606 if (strpos($str, 'http://') !== 0 && strpos($str, 'https://') !== 0)
Derek Allard2067d1a2008-11-13 22:59:24 +00001607 {
Andrey Andreev901573c2012-01-11 01:40:48 +02001608 return 'http://'.$str;
Derek Allard2067d1a2008-11-13 22:59:24 +00001609 }
Barry Mienydd671972010-10-04 16:33:58 +02001610
Derek Allard2067d1a2008-11-13 22:59:24 +00001611 return $str;
1612 }
Barry Mienydd671972010-10-04 16:33:58 +02001613
Derek Allard2067d1a2008-11-13 22:59:24 +00001614 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001615
Derek Allard2067d1a2008-11-13 22:59:24 +00001616 /**
1617 * Strip Image Tags
1618 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001619 * @param string
1620 * @return string
Barry Mienydd671972010-10-04 16:33:58 +02001621 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001622 public function strip_image_tags($str)
Derek Allard2067d1a2008-11-13 22:59:24 +00001623 {
Andrey Andreev1a24a9d2012-06-27 00:52:47 +03001624 return $this->CI->security->strip_image_tags($str);
Derek Allard2067d1a2008-11-13 22:59:24 +00001625 }
Barry Mienydd671972010-10-04 16:33:58 +02001626
Derek Allard2067d1a2008-11-13 22:59:24 +00001627 // --------------------------------------------------------------------
Barry Mienydd671972010-10-04 16:33:58 +02001628
Derek Allard2067d1a2008-11-13 22:59:24 +00001629 /**
Derek Allard2067d1a2008-11-13 22:59:24 +00001630 * Convert PHP tags to entities
1631 *
Derek Allard2067d1a2008-11-13 22:59:24 +00001632 * @param string
1633 * @return string
Barry Mienydd671972010-10-04 16:33:58 +02001634 */
Phil Sturgeon3837ae72011-05-09 21:12:26 +01001635 public function encode_php_tags($str)
Derek Allard2067d1a2008-11-13 22:59:24 +00001636 {
Andrey Andreev838a9d62012-12-03 14:37:47 +02001637 return str_replace(array('<?', '?>'), array('&lt;?', '?&gt;'), $str);
Derek Allard2067d1a2008-11-13 22:59:24 +00001638 }
1639
JonoB099c4782012-03-04 14:37:30 +00001640 // --------------------------------------------------------------------
Andrey Andreevc8da4fe2012-03-04 19:20:33 +02001641
1642 /**
1643 * Reset validation vars
1644 *
1645 * Prevents subsequent validation routines from being affected by the
JonoB099c4782012-03-04 14:37:30 +00001646 * results of any previous validation routine due to the CI singleton.
Andrey Andreevc8da4fe2012-03-04 19:20:33 +02001647 *
Andrey Andreeva89c1da2014-02-08 19:03:35 +02001648 * @return CI_Form_validation
Andrey Andreevc8da4fe2012-03-04 19:20:33 +02001649 */
JonoB883f80f2012-03-05 09:51:27 +00001650 public function reset_validation()
Andrey Andreevc8da4fe2012-03-04 19:20:33 +02001651 {
JonoB099c4782012-03-04 14:37:30 +00001652 $this->_field_data = array();
JonoB099c4782012-03-04 14:37:30 +00001653 $this->_error_array = array();
1654 $this->_error_messages = array();
1655 $this->error_string = '';
Andrey Andreeva89c1da2014-02-08 19:03:35 +02001656 return $this;
Andrey Andreevc8da4fe2012-03-04 19:20:33 +02001657 }
1658
Derek Allard2067d1a2008-11-13 22:59:24 +00001659}