source: trunk/lib/FormValidator.inc.php @ 144

Last change on this file since 144 was 144, checked in by scdev, 18 years ago

Q - Added lib/Validator.inc.php as a backend to FormValidator? and also to be used directly for non-form validation and assertion.

File size: 16.4 KB
RevLine 
[1]1<?php
2/**
[42]3 * FormValidator.inc.php
[1]4 * Code by Strangecode :: www.strangecode.com :: This document contains copyrighted information
5 *
[136]6 * The FormValidator class provides a method for validating input from
[1]7 * http requests and displaying errors.
8 *
[144]9 * @requires  codebase/lib/Validator.inc.php
[1]10 * @author    Quinn Comendant <quinn@strangecode.com>
[106]11 * @version   1.8
[1]12 *
[136]13 * Example of use:
14---------------------------------------------------------------------
15// The object that validates form input.
16require_once 'codebase/lib/FormValidator.inc.php';
17$fv = new FormValidator();
18
[144]19$fv->empty('field_name', sprintf(_("%s cannot be blank."), _("Field name")));
[136]20$fv->stringLength('field_name', 0, 255, sprintf(_("%s must be %f-to-%f characters in length."), _("Field name"), 0, 255));
21$fv->isInteger('field_name', sprintf(_("%s must be an integer."), _("Field name")));
22$fv->checkRegex('field_name', '/^\d{4}$|^$/', true, sprintf(_("%s must be in MMYY format."), _("Field name")));
23$fv->numericRange('field_name', 0, 65535, sprintf(_("%s must be a number between %f and %f."), _("Field name"), 0, 65535));
24$fv->validatePhone('field_name');
25$fv->validateEmail('field_name');
26$fv->validateStrDate('field_name', sprintf(_("%s must be a valid date in YYYY-MM-DD format."), _("Field name")));
27if (is_null($var)) {
28    $fv->addError('field_name', sprintf(_("%s is invalid."), _("Field name")));
29}
30if ($fv->anyErrors()) {
31    // Errors!
32}
33---------------------------------------------------------------------
[1]34 */
[42]35
[144]36// Credit card types are defined in class Validator.
37
38require_once 'codebase/lib/Validator.inc.php';
39
40class FormValidator extends Validator {
41
[100]42    // Array filling with error messages.
[1]43    var $errors = array();
[96]44   
[144]45    // Default error marker.
46    var $marker = 'sc-msg-error';
[42]47
[1]48    /**
49     * Return the current list of errors.
50     *
51     * @return array    an array of errors in the following arrangement:
52     *                  keys: the name of the variable with an error
53     *                  vals: the message to display for that error
54     */
55    function getErrorList()
56    {
57        return $this->errors;
58    }
[42]59
[1]60    /**
61     * Add an error to the errors stack.
62     *
63     * @param   string $form_name   The name of the incoming form variable.
64     * @param   string $msg         The error message for that form.
65     * @param   int    $type        The type of message: MSG_NOTICE,
66     *                              MSG_SUCCESS, MSG_WARNING, or MSG_ERR.
67     * @param   string $file        __FILE__.
68     * @param   string $line        __LINE__.
69     */
70    function addError($form_name, $msg='', $type=MSG_ERR, $file=null, $line=null)
71    {
72        $this->errors[] = array(
73            'name' => $form_name,
74            'message' => $msg,
75            'type' => $type,
76            'file' => $file,
77            'line' => $line
78        );
79    }
[42]80
[1]81    /**
82     * Check whether any errors have been triggered.
83     *
84     * @param  string $form_name the name of the incoming form variable
85     *
[42]86     * @return bool   true if any errors were found, or if found for
[1]87     *                a variable of $form_name, false otherwise
88     */
89    function anyErrors($form_name=null)
90    {
91        if (isset($form_name)) {
92            foreach ($this->errors as $err) {
93                if ($err['name'] == $form_name) {
[42]94                    return true;
[1]95                }
96            }
97            return false;
[144]98        } else {
99            return (sizeof($this->errors) > 0);           
[1]100        }
101    }
102
103    /**
104     * Reset the error list.
105     */
106    function resetErrorList()
107    {
108        $this->errors = array();
109    }
110
111    /**
112     * Prints the HTML for displaying error messages.
113     *
114     * @access  public
115     * @author  Quinn Comendant <quinn@strangecode.com>
116     * @since   15 Jul 2005 01:39:14
117     */
118    function printErrorMessages()
119    {
[136]120        $app =& App::getInstance();
[1]121        if ($this->anyErrors()) {
[106]122            ?><div class="sc-msg"><?php
[1]123            $errors = $this->getErrorList();
[136]124            foreach ($errors as $e) {
125                if ('' != $e['message'] && is_string($e['message'])) {
126                    if (error_reporting() > 0 && $app->getParam('display_errors') && isset($e['file']) && isset($e['line'])) {
127                        echo "\n<!-- [" . $e['file'] . ' : ' . $e['line'] . '] -->';
[1]128                    }
[136]129                    switch ($e['type']) {
[1]130                    case MSG_ERR:
[136]131                        echo '<div class="sc-msg-error">' . $e['message'] . '</div>';
[1]132                        break;
[42]133
[1]134                    case MSG_WARNING:
[136]135                        echo '<div class="sc-msg-warning">' . $e['message'] . '</div>';
[1]136                        break;
[42]137
[1]138                    case MSG_SUCCESS:
[136]139                        echo '<div class="sc-msg-success">' . $e['message'] . '</div>';
[1]140                        break;
[42]141
[1]142                    case MSG_NOTICE:
143                    default:
[136]144                        echo '<div class="sc-msg-notice">' . $e['message'] . '</div>';
[1]145                        break;
146                    }
147                }
148            }
149            ?></div><?php
150        }
151    }
[42]152
[1]153    /**
154     * If this form has an error, print an error marker like "<<".
155     *
156     * @param  string $form_name the name of the incoming form variable
157     * @param  string $marker    A string to print if there is an error. if
158     *                           not provided, use default.
159     */
160    function err($form_name, $marker=null)
161    {
162        if ($this->anyErrors($form_name)) {
163            if (isset($marker)) {
164                echo $marker;
165            } else {
[96]166                echo $this->marker;
[1]167            }
168        }
169    }
170
171    /**
[144]172     * Ensure the length of string is non-zero.
[1]173     *
174     * @param  string $form_name the name of the incoming form variable
175     * @param  string $msg       the message to display on error
176     *
177     * @return bool   true if form is not empty, false otherwise.
178     */
179    function notEmpty($form_name, $msg='')
180    {
[144]181        if (parent::notEmpty(getFormData($form_name))) {
[1]182            return true;
183        } else {
[144]184            $this->addError($form_name, $msg);
[1]185            return false;
186        }
187    }
[144]188   
189    /*
190    * We were using the isEmpty method *wrong* all these years and should have been using notEmpty.
191    * But the fact is the only use is to ensure a value is not empty, so this function simply becomes
192    * an alias of the one-true notEmpty() function.
193    * @since    03 Jun 2006 22:56:46
194    */
[1]195    function isEmpty($form_name, $msg='')
196    {
[144]197        $this->notEmpty($form_name, $msg='');
[1]198    }
199
200    /**
201     * Check whether input is a string.
202     *
203     * @param  string $form_name the name of the incoming form variable
204     * @param  string $msg       the message to display on error
205     *
206     * @return bool   true if form is a string, false otherwise.
207     */
208    function isString($form_name, $msg='')
209    {
[144]210        if (parent::isString(getFormData($form_name))) {
211            return true;
212        } else {
[1]213            $this->addError($form_name, $msg);
214            return false;
215        }
216    }
217
218    /**
219     * Check whether input is a number. Allows negative numbers.
220     *
221     * @param  string $form_name the name of the incoming form variable
222     * @param  string $msg       the message to display on error
223     *
224     * @return bool   true if no errors found, false otherwise
225     */
226    function isNumber($form_name, $msg='')
227    {
[144]228        if (parent::isNumber(getFormData($form_name))) {
229            return true;
230        } else {
[1]231            $this->addError($form_name, $msg);
232            return false;
233        }
234    }
235
236    /**
237     * addError if input is NOT an integer. Don't just use is_int() because the
238     * data coming from the user is *really* a string.
239     *
240     * @param  string $form_name the name of the incoming form variable
241     * @param  string $msg       the message to display on error
242     *
243     * @return bool   true if value is an integer
244     */
245    function isInteger($form_name, $msg='', $negative_ok=false)
246    {
[144]247        if (parent::isInteger(getFormData($form_name), $negative_ok)) {
248            return true;
249        } else {
[1]250            $this->addError($form_name, $msg);
251            return false;
252        }
253    }
254
255    /**
256     * Check whether input is a float. Don't just use is_float() because the
[42]257     * data coming from the user is *really* a string. Integers will also
[1]258     * pass this test.
259     *
260     * @param  string $form_name the name of the incoming form variable
261     * @param  string $msg       the message to display on error
262     *
263     * @return bool   true if value is a float
264     */
265    function isFloat($form_name, $msg='', $negative_ok=false)
266    {
[144]267        if (parent::isFloat(getFormData($form_name), $negative_ok)) {
268            return true;
269        } else {
[1]270            $this->addError($form_name, $msg);
271            return false;
272        }
273    }
274
275    /**
276     * Check whether input is an array.
277     *
278     * @param  string $form_name the name of the incoming form variable
279     * @param  string $msg       the message to display on error
280     *
281     * @return bool   true if value is a float
282     */
283    function isArray($form_name, $msg='')
284    {
[144]285        if (parent::isArray(getFormData($form_name))) {
286            return true;
287        } else {
[1]288            $this->addError($form_name, $msg);
289            return false;
290        }
291    }
[42]292
[1]293    /**
294     * Check whether input matches the specified perl regular expression
[42]295     * pattern.
[1]296     *
297     * @param  string $form_name the name of the incoming form variable
298     * @param  int    $regex     perl regex that the string must match
[144]299     * @param  bool   $valid_on_match       set to false to be valid if match, or true
[1]300     *                           to be valid on no match
301     * @param  string $msg       the message to display on error
302     *
303     * @return bool   true if value passes regex test
304     */
[144]305    function checkRegex($form_name, $regex, $valid_on_match, $msg='')
[1]306    {
[144]307        if (parent::checkRegex(getFormData($form_name), $regex, $valid_on_match)) {
308            return true;
[1]309        } else {
[144]310            $this->addError($form_name, $msg);
311            return false;
[1]312        }
313    }
[42]314
[1]315    /**
316     * Tests if the string length is between specified values. Whitespace excluded for min.
317     *
318     * @param  string $form_name the name of the incoming form variable
319     * @param  int    $min       minimum length of string, inclusive
320     * @param  int    $max       maximum length of string, inclusive
321     * @param  string $msg       the message to display on error
322     *
323     * @return bool   true if string length is within given boundaries
324     */
325    function stringLength($form_name, $min, $max, $msg='')
326    {
[144]327        if (parent::stringLength(getFormData($form_name), $min, $max)) {
328            return true;
329        } else {
[1]330            $this->addError($form_name, $msg);
331            return false;
332        }
333    }
334
335    /**
336     * Check whether input is within a valid numeric range.
337     *
338     * @param  string $form_name the name of the incoming form variable
339     * @param  int    $min       minimum value of number, inclusive
340     * @param  int    $max       maximum value of number, inclusive
341     * @param  string $msg       the message to display on error
342     *
343     * @return bool   true if no errors found, false otherwise
344     */
345    function numericRange($form_name, $min, $max, $msg='')
346    {
[144]347        if (parent::numericRange(getFormData($form_name), $min, $max)) {
[1]348            return true;
349        } else {
[144]350            $this->addError($form_name, $msg);
[1]351            return false;
352        }
353    }
354
355    /**
[23]356     * Validates an email address based on the recommendations in RFC 3696.
[42]357     * Is more loose than restrictive, to allow the many valid variants of
[23]358     * email addresses while catching the most common mistakes.
359     * http://www.faqs.org/rfcs/rfc822.html
360     * http://www.faqs.org/rfcs/rfc2822.html
361     * http://www.faqs.org/rfcs/rfc3696.html
362     * http://www.faqs.org/rfcs/rfc1035.html
[1]363     *
[23]364     * @access  public
365     * @param   string  $form_name  The name of the incoming form variable.
366     * @return  bool    Validity of address.
367     * @author  Quinn Comendant <quinn@strangecode.com>
[1]368     */
[23]369    function validateEmail($form_name)
[1]370    {
[136]371        $app =& App::getInstance();
[144]372
[1]373        $email = getFormData($form_name);
[144]374
[1]375        if ('' == trim($email)) {
[144]376            // No email address provided, and that's okay
377            return true;
[1]378        }
[23]379
[144]380        // Validator::validateEmail() returns a value that relates to the VALIDATE_EMAIL_* constants (defined in Validator.inc.php).
381        switch (parent::validateEmail($email)) {
382        case VALIDATE_EMAIL_REGEX_FAIL:
383            // Failed regex match.
384            $this->addError($form_name, sprintf(_("<em>%s</em> is not a valid email address."), oTxt($email)));
[136]385            $app->logMsg(sprintf('The email address %s is not valid.', getFormData($form_name)), LOG_DEBUG, __FILE__, __LINE__);
[23]386            return false;
[144]387            break;
388        case VALIDATE_EMAIL_LENGTH_FAIL :
389            // Failed length requirements.
390            $this->addError($form_name, sprintf(_("<em>Email address</em> must contain less than 256 characters."), oTxt($email)));
[136]391            $app->logMsg(sprintf('The email address %s must contain less than 256 characters.', getFormData($form_name)), LOG_DEBUG, __FILE__, __LINE__);
[1]392            return false;
[144]393            break;
394        case VALIDATE_EMAIL_MX_FAIL :
395            // Failed MX record test.
396            $this->addError($form_name, sprintf(_("<em>%s</em> is not a valid email domain name"), oTxt($domain)));
[136]397            $app->logMsg(sprintf('The email address %s contains an invalid email domain name (%s).', getFormData($form_name), $domain), LOG_INFO, __FILE__, __LINE__);
[23]398            return false;
[144]399            break;
400        case VALIDATE_EMAIL_SUCCESS :
401        default :
402            return true;
403            break;
[1]404        }
405    }
406
407    /**
408     * Check whether input is a valid phone number. Notice: it is now set
409     * to allow characters like - or () or + so people can type in a phone
[144]410     * number that looks like: +1 (530) 555-1212
[1]411     *
412     * @param  string  $form_name the name of the incoming form variable
413     *
414     * @return bool    true if no errors found, false otherwise
415     */
416    function validatePhone($form_name)
417    {
418        $phone = getFormData($form_name);
[42]419
[144]420        return (
421            $this->checkRegex($form_name, '/^[0-9 +().-]*$/', true, sprintf(_("The phone number <em>%s</em> is not valid."), $phone))
422            && $this->stringLength($form_name, 0, 25, sprintf(_("The phone number <em>%s</em> is too long"), $phone))
423        );
[1]424    }
425
426    /**
427     * Verifies that date can be processed by the strtotime function.
428     *
429     * @param  string  $form_name the name of the incoming form variable
430     * @param  string  $msg       the message to display on error
431     *
432     * @return bool    true if no errors found, false otherwise
433     */
434    function validateStrDate($form_name, $msg='')
435    {
[144]436        $app =& App::getInstance();
437
438        if (parent::validateStrDate(getFormData($form_name))) {
439            return true;
440        } else {
[1]441            $this->addError($form_name, $msg);
[136]442            $app->logMsg(sprintf('The string date %s is not valid.', getFormData($form_name)), LOG_DEBUG, __FILE__, __LINE__);
[1]443            return false;
444        }
445    }
[42]446
447
[1]448    /**
449     * Verifies credit card number.
450     *
451     * @param  string  $form_name   The name of the incoming form variable.
[144]452     * @param  string  $cc_type     Optional, card type to do specific checks. One of the CC_TYPE_* constants.
[1]453     *
454     * @return bool    true if no errors found, false otherwise
455     */
[144]456    function validateCCNumber($form_name, $cc_type=null)
[1]457    {
[144]458        $cc_num = getFormData($form_name);
459       
460        if (parent::validateCCNumber($cc_num, $cc_type)) {
[1]461            return true;
462        } else {
[144]463            $this->addError($form_name, sprintf(_("<em>%s</em> is not a valid credit card number."), $cc_num));
[1]464            return false;
465        }
466    }
467
468    /**
[136]469     * Check whether a file was selected for uploading. If file is missing, it's an error.
[1]470     *
471     * @param  string $form_name the name of the incoming form variable
472     * @param  string $msg       the message to display on error
473     *
474     * @return bool   true if no errors found, false otherwise
475     */
[144]476    function fileUploaded($form_name, $msg='')
[1]477    {
[144]478        if (parent::fileUploaded($form_name)) {
479            return true;
480        } else {
[1]481            $this->addError($form_name, $msg);
482            return false;
483        }
484    }
[42]485
[1]486} // THE END
487
488?>
Note: See TracBrowser for help on using the repository browser.