function set_rule($rules)
    {

        // continue only if argument is an array
        if (is_array($rules))

            // iterate through the given rules
            foreach ($rules as $rule_name => $rule_properties) {

                // make sure the rule's name is lowercase
                $rule_name = strtolower($rule_name);

                // if custom rule
                if ($rule_name == 'custom')

                    // if more custom rules are specified at once
                    if (is_array($rule_properties[0]) && count($rule_properties[0]) >= 3)

                        // iterate through the custom rules
                        // and add them one by one
                        foreach ($rule_properties as $rule) $this->rules[$rule_name][] = $rule;

                    // if a single custom rule is specified
                    // save the custom rule to the "custom" rules array
                    else $this->rules[$rule_name][] = $rule_properties;

                // for all the other rules
                // add the rule to the rules array
                else $this->rules[$rule_name] = $rule_properties;

                // for some rules we do some additional settings
                switch ($rule_name) {

                    // we set a reserved attribute for the control by which we're telling the
                    // _render_attributes() method to append a special class to the control when rendering it
                    // so that we can also control user input from javascript
                    case 'alphabet':
                    case 'digits':
                    case 'alphanumeric':
                    case 'number':
                    case 'float':

                        $this->set_attributes(array('onkeypress' => 'javascript:return $(\'#' . $this->form_properties['name'] . '\').data(\'Zebra_Form\').filter_input(\'' . $rule_name . '\', event' . ($rule_properties[0] != '' ? ', \'' . addcslashes($rule_properties[0], '\'') . '\'' : '') . ');'));

                        // for controls having these rules,
                        if (in_array($rule_name, array('digits', 'number', 'float')))

                            // change the control's type to "number"
                            $this->set_attributes(array('type' => 'number'));

                        break;

                    // if the rule is about the length of the input
                    case 'length':

                        // if there is a maximum of allowed characters
                        if ($rule_properties[1] > 0) {

                            // set the maxlength attribute of the control
                            $this->set_attributes(array('maxlength' => $rule_properties[1]));

                            // if there is a 5th argument to the rule, the argument is boolean true
                            if (isset($rule_properties[4]) && $rule_properties[4] === true) {

                                // add an extra class so that the JavaScript library will know to show the character counter
                                $this->set_attributes(array('class' => 'show-character-counter'), false);

                            }

                        }

                        break;

                    // if the "email" rule is set
                    case 'email':

                        // change the element's type to "email"
                        $this->set_attributes(array('type' => 'email'));

                        break;

                }

            }

    }
function set_rule($rules)
    {

        // continue only if argument is an array
        if (is_array($rules))

            // iterate through the given rules
            foreach ($rules as $rule_name => $rule_properties) {

                // make sure the rule's name is lowercase
                $rule_name = strtolower($rule_name);

                // if custom rule
                if ($rule_name == 'custom')

                    // if more custom rules are specified at once
                    if (is_array($rule_properties[0]) && count($rule_properties[0]) >= 3)

                        // iterate through the custom rules
                        // and add them one by one
                        foreach ($rule_properties as $rule) $this->rules[$rule_name][] = $rule;

                    // if a single custom rule is specified
                    // save the custom rule to the "custom" rules array
                    else $this->rules[$rule_name][] = $rule_properties;

                // for all the other rules
                // add the rule to the rules array
                else $this->rules[$rule_name] = $rule_properties;

                // for some rules we do some additional settings
                switch ($rule_name) {

                    // we set a reserved attribute for the control by which we're telling the
                    // _render_attributes() method to append a special class to the control when rendering it
                    // so that we can also control user input from javascript
                    case 'alphabet':
                    case 'digits':
                    case 'alphanumeric':
                    case 'number':
                    case 'float':

                        $this->set_attributes(array('onkeypress' => 'javascript:return $(\'#' . $this->form_properties['name'] . '\').data(\'Zebra_Form\').filter_input(\'' . $rule_name . '\', event' . ($rule_properties[0] != '' ? ', \'' . addcslashes($rule_properties[0], '\'') . '\'' : '') . ');'));

                        // for controls having these rules,
                        if (in_array($rule_name, array('digits', 'number', 'float')))

                            // change the control's type to "number"
                            $this->set_attributes(array('type' => 'number'));

                        break;

                    // if the rule is about the length of the input
                    case 'length':

                        // if there is a maximum of allowed characters
                        if ($rule_properties[1] > 0) {

                            // set the maxlength attribute of the control
                            $this->set_attributes(array('maxlength' => $rule_properties[1]));

                            // if there is a 5th argument to the rule, the argument is boolean true
                            if (isset($rule_properties[4]) && $rule_properties[4] === true) {

                                // add an extra class so that the JavaScript library will know to show the character counter
                                $this->set_attributes(array('class' => 'show-character-counter'), false);

                            }

                        }

                        break;

                    // if the "email" rule is set
                    case 'email':

                        // change the element's type to "email"
                        $this->set_attributes(array('type' => 'email'));

                        break;

                }

            }

    }
function set_rule ( $ rules ) { // continue only if argument is an array if ( is_array ( $ rules ) ) // iterate through the given rules foreach ( $ rules as $ rule_name => $ rule_properties ) { // make sure the rule's name is lowercase $ rule_name = strtolower ( $ rule_name ) ; // if custom rule if ( $ rule_name == 'custom' ) // if more custom rules are specified at once if ( is_array ( $ rule_properties [ 0 ] ) && count ( $ rule_properties [ 0 ] ) >= 3 ) // iterate through the custom rules // and add them one by one foreach ( $ rule_properties as $ rule ) $ this -> rules [ $ rule_name ] [ ] = $ rule ; // if a single custom rule is specified // save the custom rule to the "custom" rules array else $ this -> rules [ $ rule_name ] [ ] = $ rule_properties ; // for all the other rules // add the rule to the rules array else $ this -> rules [ $ rule_name ] = $ rule_properties ; // for some rules we do some additional settings switch ( $ rule_name ) { // we set a reserved attribute for the control by which we're telling the // _render_attributes() method to append a special class to the control when rendering it // so that we can also control user input from javascript case 'alphabet' : case 'digits' : case 'alphanumeric' : case 'number' : case 'float' : $ this -> set_attributes ( array ( 'onkeypress' => 'javascript:return $(\'#' . $ this -> form_properties [ 'name' ] . '\').data(\'Zebra_Form\').filter_input(\'' . $ rule_name . '\', event' . ( $ rule_properties [ 0 ] != '' ? ', \'' . addcslashes ( $ rule_properties [ 0 ] , '\'' ) . '\'' : '' ) . ');' ) ) ; // for controls having these rules, if ( in_array ( $ rule_name , array ( 'digits' , 'number' , 'float' ) ) ) // change the control's type to "number" $ this -> set_attributes ( array ( 'type' => 'number' ) ) ; break ; // if the rule is about the length of the input case 'length' : // if there is a maximum of allowed characters if ( $ rule_properties [ 1 ] > 0 ) { // set the maxlength attribute of the control $ this -> set_attributes ( array ( 'maxlength' => $ rule_properties [ 1 ] ) ) ; // if there is a 5th argument to the rule, the argument is boolean true if ( isset ( $ rule_properties [ 4 ] ) && $ rule_properties [ 4 ] === true ) { // add an extra class so that the JavaScript library will know to show the character counter $ this -> set_attributes ( array ( 'class' => 'show-character-counter' ) , false ) ; } } break ; // if the "email" rule is set case 'email' : // change the element's type to "email" $ this -> set_attributes ( array ( 'type' => 'email' ) ) ; break ; } } }
Sets a single or an array of validation rules for the control.

<code>
// $obj is a reference to a control
$obj->set_rule(array(
'rule #1'    =>  array($arg1, $arg2, ... $argn),
'rule #2'    =>  array($arg1, $arg2, ... $argn),
...
...
'rule #n'    =>  array($arg1, $arg2, ... $argn),
));
// where 'rule #1', 'rule #2', 'rule #n' are any of the rules listed below
// and $arg1, $arg2, $argn are arguments specific to each rule
</code>

When a validation rule is not passed, a variable becomes available in the template file, having the name
as specified by the rule's <b>error_block</b> argument and having the value as specified by the rule's
<b>error_message</b> argument.

<samp>Validation rules are checked in the given order, the exceptions being the "dependencies", "required" and
"upload" rules, which are *always* checked in the order of priority: "dependencies" has priority over "required"
which in turn has priority over "upload".</samp>

I usually have at the top of my custom templates something like (assuming all errors are sent to an error block
named "error"):

<code>echo (isset($zf_error) ? $zf_error : (isset($error) ? $error : ''));</code>

<samp>The above code nees to be used only for custom templates, or when the output is generated via callback
functions! For automatically generated templates it is all taken care for you automatically by the library! Notice
the $zf_error variable which is automatically created by the library if there is a SPAM or a CSRF error! Unless
you use it, these errors will not be visible for the user. Again, remember, we're talking about custom templates,
or output generated via callback functions.</samp>

One or all error messages can be displayed in an error block.
See the {@link Zebra_Form::show_all_error_messages() show_all_error_messages()} method.

<b>Everything related to error blocks applies only for server-side validation.</b><br>
<b>See the {@link Zebra_Form::client_side_validation() client_side_validation()} method for configuring how errors
are to be displayed to the user upon client-side validation.</b>

Available rules are
-   age
-   alphabet
-   alphanumeric
-   captcha
-   compare
-   convert
-   custom
-   date
-   datecompare
-   dependencies
-   digits
-   email
-   emails
-   filesize
-   filetype
-   float
-   image
-   length
-   number
-   range
-   regexp
-   required
-   resize
-   upload
-   url

Rules description:

-   <b>age</b>

<code>'age' => array($range, $error_block, $error_message)</code>

where

-   <i>range</i> is an array with 2 values, representing the minimum and maximum age allowed. 0 (zero) means
"any age". Therefore, a range of array(21, 0) would validate ages above 20, array(6, 12) would
validate ages between 6 and 12 (inclusive), while (0, 12) would validate ages below 13

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

Validates if the difference in years between the current date and the date entered in the control is whitin the
allowed range

Available for the following controls: {@link Zebra_Form_Text text}

<code>
// $obj is a reference to a control
$obj->set_rule(
'age' => array(
array(21, 0)            // allow ages above 20
'error',                // variable to add the error message to
'Age must be above 20'  // error message if value doesn't validate
)
);
</code>

-   <b>alphabet</b>

<code>'alphabet' => array($additional_characters, $error_block, $error_message)</code>

where

-   <i>additional_characters</i> is a list of additionally allowed characters besides the alphabet (provide
an empty string if none); note that if you want to use / (backslash) you need to specify it as three (3)
backslashes ("///")!

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

Validates if the value contains only characters from the alphabet (case-insensitive a to z) <b>plus</b> characters
given as additional characters (if any).

Available for the following controls: {@link Zebra_Form_Password password}, {@link Zebra_Form_Text text},
{@link Zebra_Form_Textarea textarea}

<code>
// $obj is a reference to a control
$obj->set_rule(
'alphabet' => array(
'-'                                     // allow alphabet plus dash
'error',                                // variable to add the error message to
'Only alphabetic characters allowed!'   // error message if value doesn't validate
)
);
</code>

-   <b>alphanumeric</b>

<code>'alphanumeric' => array($additional_characters, $error_block, $error_message)</code>

where

-   <i>additional_characters</i> is a list of additionally allowed characters besides the alphabet and
digits 0 to 9 (provide an empty string if none); note that if you want to use / (backslash) you need to
specify it as three (3) backslashes ("///")!

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

Validates if the value contains only characters from the alphabet (case-insensitive a to z) and digits (0 to 9)
<b>plus</b> characters given as additional characters (if any).

Available for the following controls: {@link Zebra_Form_Password password}, {@link Zebra_Form_Text text},
{@link Zebra_Form_Textarea textarea}

<code>
// $obj is a reference to a control
$obj->set_rule(
'alphanumeric' => array(
'-',                                    // allow alphabet, digits and dash
'error',                                // variable to add the error message to
'Only alphanumeric characters allowed!' // error message if value doesn't validate
)
);
</code>

-   <b>captcha</b>

<code>'captcha' => array($error_block, $error_message)</code>

where

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

Validates if the value matches the characters seen in the {@link Zebra_Form_Captcha captcha} image
(therefore, there must be a {@link Zebra_Form_Captcha captcha} image on the form)

Available only for the {@link Zebra_Form_Text text} control

<i>This rule is not available client-side!</i>

<code>
// $obj is a reference to a control
$obj->set_rule(
'captcha' => array(
'error',                            // variable to add the error message to
'Characters not entered correctly!' // error message if value doesn't validate
)
);
</code>

-   <b>compare</b>

<code>'compare' => array($control, $error_block, $error_message)</code>

where

-   <i>control</i> is the name of a control on the form to compare values with

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

Validates if the value is the same as the value of the control indicated by <i>control</i>.

Useful for password confirmation.

Available for the following controls: {@link Zebra_Form_Password password}, {@link Zebra_Form_Text text},
{@link Zebra_Form_Textarea textarea}

<code>
// $obj is a reference to a control
$obj->set_rule(
'compare' => array(
'password'                          // name of the control to compare values with
'error',                            // variable to add the error message to
'Password not confirmed correctly!' // error message if value doesn't validate
)
);
</code>

-   <b>convert</b>

<samp>This rule requires the prior inclusion of the {@link http://stefangabos.ro/php-libraries/zebra-image Zebra_Image}
library!</samp>

<code>'convert' => array($type, $jpeg_quality, $preserve_original_file, $overwrite, $error_block, $error_message)</code>

where

-   <i>type</i> the type to convert the image to; can be (case-insensitive) JPG, PNG or GIF

-   <i>jpeg_quality</i>: Indicates the quality of the output image (better quality means bigger file size).

Range is 0 - 100

Available only if <b>type</b> is "jpg".

-   <i>preserve_original_file</i>: Should the original file be preserved after the conversion is done?

-   <i>$overwrite</i>: If a file with the same name as the converted file already exists, should it be
overwritten or should the name be automatically computed.

If a file with the same name as the converted file already exists and this argument is FALSE, a suffix of
"_n" (where n is an integer) will be appended to the file name.

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

This rule will convert an image file uploaded using the <b>upload</b> rule from whatever its type (as long as is one
of the supported types) to the type indicated by <i>type</i>.

Validates if the uploaded file is an image file and <i>type</i> is valid.

This is not actually a "rule", but because it can generate an error message it is included here

You should use this rule in conjunction with the <b>upload</b> and <b>image</b> rules.

If you are also using the <b>resize</b> rule, make sure you are using it AFTER the <b>convert</b> rule!

Available only for the {@link Zebra_Form_File file} control

<i>This rule is not available client-side!</i>

<code>
// $obj is a reference to a file upload control
$obj->set_rule(
'convert' => array(
'jpg',                          // type to convert to
85,                             // converted file quality
false,                          // preserve original file?
false,                          // overwrite if converted file already exists?
'error',                        // variable to add the error message to
'File could not be uploaded!'   // error message if value doesn't validate
)
);
</code>

-   <b>custom</b>

Using this rule, custom rules can be applied to the submitted values.

<code>'custom'=>array($callback_function_name, [optional arguments to be passed to the function], $error_block, $error_message)</code>

where

-   <i>callback_function_name</i> is the name of the callback function

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

<i>The callback function's first argument must ALWAYS be the control's submitted value. The optional arguments to
be passed to the callback function will start as of the second argument!</i>

<i>The callback function MUST return TRUE on success or FALSE on failure!</i>

Multiple custom rules can also be set through an array of callback functions:

<code>
'custom' => array(

array($callback_function_name1, [optional arguments to be passed to the function], $error_block, $error_message),
array($callback_function_name1, [optional arguments to be passed to the function], $error_block, $error_message)

)
</code>

<b>If {@link Zebra_Form::client_side_validation() client-side validation} is enabled (enabled by default), the
custom function needs to also be available in JavaScript, with the exact same name as the function in PHP!</b>

For example, here's a custom rule for checking that an entered value is an integer, greater than 21:

<code>
// the custom function in JavaScript
<script type="text/javascript">
function is_valid_number(value)
{
// return false if the value is less than 21
if (value < 21) return false;
// return true otherwise
return true;
}
<&92;script>
</code>

<code>
// the callback function in PHP
function is_valid_number($value)
{
// return false if the value is less than 21
if ($value < 21) return false;
// return true otherwise
return true;
}

// create a new form
$form = new Zebra_Form('my_form');

// add a text control to the form
$obj = $form->add('text', 'my_text');

// set two rules:
// on that requires the value to be an integer
// and a custom rule that requires the value to be greater than 21
$obj->set_rule(
'number'    =>  array('', 'error', 'Value must be an integer!'),
'custom'    =>  array(
'is_valid_number',
'error',
'Value must be greater than 21!'
)
);
</code>

And here's how I do validations using <b>AJAX</b>:

In my website's main JavaScript file I have something like:

<code>
var valid = null;

// I have functions like these for everything that I need checked through AJAX; note that they are in the global
// namespace and outside the DOM-ready event

// functions have to return TRUE in order for the rule to be considered as obeyed
function username_not_taken(username) {
$.ajax({data: 'username=' + username});
return valid;
}

function emailaddress_not_taken(email) {
$.ajax({data: 'email=' + email});
return valid;
}

// in the DOM ready event
$(document).ready(function() {

// I setup an AJAX object that will handle all my AJAX calls
$.ajaxSetup({
url: 'path/to/validator/',  // actual work will be done in PHP
type: 'post',
dataType: 'text',
async: false,               // this is important!
global: false,
beforeSend: function() {
valid = null;
},
success: function(data, textStatus) {
if (data == 'valid') valid = true;
else valid = false;
}
});

// ...other JavaScript code for your website...

}
</code>

I also have a "validation.php" "helper" file which contains the PHP functions that do the actual checkings. This
file is included both in the page where I create the form (used by the server-side validation) and also by the
file defined by the "url" property of the AJAX object (used for client-side validation). This might look something
like:

<code>
function username_not_taken($username) {
// check for username and return TRUE if it's NOT taken, or FALSE otherwise
}

function emailaddress_not_taken($email) {
// check for email address and return TRUE if it's NOT taken, or FALSE otherwise
}
</code>

As stated above, when I create a form I include this "helper" file at the top, because the functions in it will
be used by the server-side validation, and set the custom rules like this:

<code>
$obj->set_rule(array(
'custom'  =>  array(
'username_not_taken',
'error',
'This user name is already taken!'
),
));
</code>

...and finally, at the "url" set in the AJAX object, I have something like:

<code>
// include the "helper" file
require 'path/to/validation.php';

if (

// make sure it's an AJAX request
isset($_SERVER['HTTP_X_REQUESTED_WITH']) &&

// make sure it has a referrer
isset($_SERVER['HTTP_REFERER']) &&

// make sure it comes from your website
strpos($_SERVER['HTTP_REFERER'], 'your/website/base/url') === 0

) {

if (

// i run functions depending on what's in the $_POST and also make some extra sanity checks
(isset($_POST['username']) && count($_POST) == 1 && username_not_taken($_POST['username'])) ||
(isset($_POST['email']) && count($_POST) == 1 && emailaddress_not_taken($_POST['email']))

// if whatever I'm checking is OK, I just echo "valid"
// (this will be later used by the AJAX object)
) echo 'valid';

}

// do nothing for any other case

</code>

-   <b>date</b>

<code>'date' => array($error_block, $error_message)</code>

where

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

Validates if the value is a propper date, formated according to the format set through the
{@link Zebra_Form_Date::format() format()} method.

Available only for the {@link Zebra_Form_Date date} control.

<i>Note that the validation is language dependant: if the form's language is other than English and month names
are expected, the script will expect the month names to be given in that particular language, as set in the
language file!</i>

<code>
// $obj is a reference to a control
$obj->set_rule(
'date' => array(
'error',        // variable to add the error message to
'Invalid date!' // error message if value doesn't validate
)
);
</code>

-   <b>datecompare</b>

<code>'datecompare' => array($control, $comparison_operator, $error_block, $error_message)</code>

where

-   <i>control</i> is the name of a date control on the form to compare values with

-   <i>comparison_operator</i> indicates how the value should be, compared to the value of <i>control</i>.<br>
Possible values are <, <=, >, >=

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

Validates if the value satisfies the comparison operator when compared to the other date control's value.

Available only for the {@link Zebra_Form_Date date} control.

<code>
// $obj is a reference to a control
$obj->set_rule(
'datecompare' => array(
'another_date'                      // name of another date control on the form
'>',                                // comparison operator
'error',                            // variable to add the error message to
'Date must be after another_date!'  // error message if value doesn't validate
)
);
</code>

-   <b>dependencies</b>

<code>'dependencies' => array($conditions)</code>

or

<code>'dependencies' => array(array($conditions), 'callback_function_name[, arguments]')</code>

where

-   <i>$conditions</i> an array of associative arrays where the keys represent the <b>names</b> of form controls
(remember: <i>names</i>, not IDs, and without the square brackets ([]) used for checkbox groups and multiple
selects), while the associated value/values represent the value/values that those controls need to have in
order for the current control to be validated. Notable exceptions are the {@link Zebra_Form_Submit submit}
and {@link Zebra_Form_Image image} elements, where the associated value must *always* be "click".

<i>Only when all conditions are met, the control's other rules will be checked!</i>

-   <i>callback_function_name</i> is the name of an existing JavaScript function which will be executed whenever
the value of any of the controls listed in the "dependencies" rule changes - useful for showing/hiding controls
that depend on the values of other controls.

An element's other existing rules will be checked only if this rule is passed.

Conditions can be applied to an infinite depth and will be checked accordingly - so, a control may depend on
another control which, in turn, may depend on another control and so on, and all this will be automatically taken
care of: say control C depends on control B having the value "1", while control B depends on control A having the
value "2"; now, even if B has the value "1", as long as A doesn't have the value "2", control C will not be
validated.

<samp>The library will terminate exection and will trigger an error message if an infinite loop of dependencies is
detected. Also, dependencies on non-existing elements will be ignored. And finally, this rule should only be used
with custom templates.</samp>

Available for the following controls: {@link Zebra_Form_Checkbox checkbox}, {@link Zebra_Form_Date date},
{@link Zebra_Form_File file}, {@link Zebra_Form_Password password}, {@link Zebra_Form_Radio radio}
{@link Zebra_Form_Select select}, {@link Zebra_Form_Text text}, {@link Zebra_Form_Textarea textarea},
{@link Zebra_Form_Time time}.

<code>
// $obj is a reference to a control
$obj->set_rule(array(

// any other rules will be checked only
// if all of the following conditions are met
'dependencies'  =>  array(

// the value of the control named "input1" is "Value 1"
'input1'    =>  'Value 1',

// the value of the control named "input2" is "Value 2" OR "Value 3"
'input2'    =>  array('Value 2', 'Value 3'),

// the value of the control named "radio1" is "Option 1" OR "Option 2"
'radio1'    =>  array('Option 1', 'Option 2'),

// the value of the control named "checkbox1" (where multiple options can
// be checked, same as for multiple selects) is
// 'Option 1' AND 'Option 2'
//  OR
// 'Option 4'
//  OR
// 'Option 1' AND 'Option 3'
'checkbox1' =>  array(
array('Option 1', 'Option 2')
'Option 4',
array('Option 1', 'Option 3')
),

// the "submit" control having the "btnsubmit" ID is clicked
'btnsubmit' =>  'click',

),

// this rule will be checked only
// if all of the conditions above are met
'required'      =>  array('error', 'Value is required!'),
));
</code>

Whenever any of the elements in the "dependencies" rule changes value, the library will check if all the conditions
are met and, if a callback function is attached, will execute the callback function. The callback function's first
argument will be the boolean result of checking if all the conditions are met. Optionally, additional comma separated
arguments may be passed to the callback function (separated with a comma from the function name). Optional arguments
can be used for having a single callback function instead of more, and doing different actions depending on the
optional argument/arguments

To attach a callback function, declare the "dependencies" rule like this:

<code>
// $obj is a reference to a control
$obj->set_rule(array(

// notice an array of arrays...
'dependencies'  =>  array(array(

// conditions

), 'callback_function[, argument]'),

));
</code>

Here are some examples of how to define the callback function in JavaScript:

<code>
// in the global scope and outside the "domready" event
var my_callback = function(valid) {
// all conditions are met
if (valid) {}
// if not all conditions are met
else {}
}

// ...here comes the rest of your code
$(document).ready(function() {});

/* ======================================================{@*}

// the same as above, again, outside the "domready" event
function my_callback(valid) {
// all conditions are met
if (valid) {}
// if not all conditions are met
else {}
}

// ...here comes the rest of your code
$(document).ready(function() {});

/* ======================================================{@*}

// create a variable in the global scope
var my_callback;

// put your function inside the "doready" event
$(document).ready(function() {

// but tied to the variable from the global scope...
my_callback = function(valid) {
// all conditions are met
if (valid) {}
// if not all conditions are met
else {}
}

});

/* ======================================================{@*}

// don't pollute the global scope, use namespaces
$(document).ready(function() {

myNameSpace = {
my_callback: function(valid) {
// all conditions are met
if (valid) {}
// if not all conditions are met
else {}
}
}

});

// in PHP, refer to the callback function like myNameSpace.my_callback
$obj->set_rule(array(

// notice an array of arrays...
'dependencies'  =>  array(array(
// conditions
), 'myNameSpace.my_callback'),

));

</code>

-   <b>digits</b>

<code>'digits' => array($additional_characters, $error_block, $error_message)</code>

where

-   <i>additional_characters</i> is a list of additionally allowed characters besides digits (provide
an empty string if none); note that if you want to use / (backslash) you need to specify it as three (3)
backslashes ("///")!

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

Validates if the value contains only digits (0 to 9) <b>plus</b> characters given as additional characters (if any).

<b>When this rule is set, element's "type" attribute will be automatically changed to "number", making
the element more friendly to mobile users</b>

Available for the following controls: {@link Zebra_Form_Password password}, {@link Zebra_Form_Text text},
{@link Zebra_Form_Textarea textarea}

<code>
// $obj is a reference to a control
$obj->set_rule(
'digits' => array(
'-'                         // allow digits and dash
'error',                    // variable to add the error message to
'Only digits are allowed!'  // error message if value doesn't validate
)
);
</code>

-   <b>email</b>

<code>'email' => array($error_block, $error_message)</code>

where

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

Validates if the value is a properly formatted email address.

<b>When this rule is set, element's "type" attribute will be automatically changed to "email", making
the element more friendly to mobile users</b>

Available for the following controls: {@link Zebra_Form_Password password}, {@link Zebra_Form_Text text},
{@link Zebra_Form_Textarea textarea}

<code>
// $obj is a reference to a control
$obj->set_rule(
'email' => array(
'error',                    // variable to add the error message to
'Invalid email address!'    // error message if value doesn't validate
)
);
</code>

-   <b>emails</b>

<code>'emails' => array($error_block, $error_message)</code>

where

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

Validates if the value is a properly formatted email address <b>or</b> a comma separated list of properly
formatted email addresses.

Available for the following controls: {@link Zebra_Form_Password password}, {@link Zebra_Form_Text text},
{@link Zebra_Form_Textarea textarea}

<code>
// $obj is a reference to a control
$obj->set_rule(
'emails' => array(
'error',                        // variable to add the error message to
'Invalid email address(es)!'    // error message if value doesn't validate
)
);
</code>

-   <b>filesize</b>

<code>'filesize' => array($file_size, $error_block, $error_message)</code>

where

-   <i>file_size</i> is the allowed file size, in bytes

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

Validates if the size (in bytes) of the uploaded file is not larger than the value (in bytes) specified by
<i>file_size</i>.

<b>Note that $file_size should be lesser or equal to the value of upload_max_filesize set in php.ini!</b>

Available only for the {@link Zebra_Form_File file} control.

<code>
// $obj is a reference to a control
$obj->set_rule(
'filesize' => array(
'102400',                           // maximum allowed file size (in bytes)
'error',                            // variable to add the error message to
'File size must not exceed 100Kb!'  // error message if value doesn't validate
)
);
</code>

-   <b>filetype</b>

<b>If you want to check for images use the dedicated "image" rule instead!</b>

<code>'filetype' => array($file_types, $error_block, $error_message)</code>

where

-   <i>file_types</i> is a string of comma separated file extensions representing uploadable file types

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

Validates only if the uploaded file's MIME type matches the MIME types associated with the extensions set by
<i>file_types</i> as defined in <i>mimes.json</i> file.

Note that for PHP versions 5.3.0+, compiled with the "php_fileinfo" extension, the uploaded file's mime type is
determined using PHP's {@link http://php.net/manual/en/function.finfo-file.php finfo_file} function; Otherwise,
the library relies on information available in the $_FILES super-global for determining an uploaded file's MIME
type, which, as it turns out, is determined solely by the file's extension, representing a potential security
risk;

Available only for the {@link Zebra_Form_File file} control.

<code>
// $obj is a reference to a control
$obj->set_rule(
'filetype' => array(
'xls, xlsx'                 // allow only EXCEL files to be uploaded
'error',                    // variable to add the error message to
'Not a valid Excel file!'   // error message if value doesn't validate
)
);
</code>

-   <b>float</b>

<code>'float' => array($additional_characters, $error_block, $error_message)</code>

where

-   <i>additional_characters</i> is a list of additionally allowed characters besides digits, one dot and one
minus sign (provide an empty string if none); note that if you want to use / (backslash) you need to specify
it as three (3) backslashes ("///")!

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

Validates if the value contains only digits (0 to 9) and/or <b>one</b> dot (but not as the very first character)
and/or <b>one</b> minus sign (but only if it is the very first character) <b>plus</b> characters given as
additional characters (if any).

<b>When this rule is set, element's "type" attribute will be automatically changed to "number", making
the element more friendly to mobile users</b>

Available for the following controls: {@link Zebra_Form_Password password}, {@link Zebra_Form_Text text},
{@link Zebra_Form_Textarea textarea}

<code>
// $obj is a reference to a control
$obj->set_rule(
'float' => array(
''                  // don't allow any extra characters
'error',            // variable to add the error message to
'Invalid number!'   // error message if value doesn't validate
)
);
</code>

-   <b>image</b>

<code>'image' => array($error_block, $error_message)</code>

where

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed


Validates only if the uploaded file is a valid GIF, PNG or JPEG image file.

Available only for the {@link Zebra_Form_File file} control.

<code>
// $obj is a reference to a control
$obj->set_rule(
'image' => array(
'error',                                // variable to add the error message to
'Not a valid GIF, PNG or JPEG file!'    // error message if value doesn't validate
)
);
</code>

-   <b>length</b>

<code>'length' => array($minimum_length, $maximum_length, $error_block, $error_message, $show_counter)</code>

where

-   <i>minimum_length</i> is the minimum number of characters the values should contain

-   <i>maximum_length</i> is the maximum number of characters the values should contain

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

-   <i>show_counter</i> if set to TRUE, a counter showing the remaining characters will be displayed along with
the element

<i>If you want to change the counter's position, do so by setting margins for the .Zebra_Character_Counter
class in the zebra_form.css file</i>


Validates only if the number of characters of the value is between $minimum_length and $maximum_length.

If an exact length is needed, set both $minimum_length and $maximum_length to the same value.

Set $maximum_length to 0 (zero) if no upper limit needs to be set for the value's length.

Available for the following controls: {@link Zebra_Form_Password password}, {@link Zebra_Form_Text text},
{@link Zebra_Form_Textarea textarea}

<code>
// $obj is a reference to a control
$obj->set_rule(
'length' => array(
3,                                              // minimum length
6,                                              // maximum length
'error',                                        // variable to add the error message to
'Value must have between 3 and 6 characters!'   // error message if value doesn't validate
)
);
</code>

-   <b>number</b>

<code>'number' => array($additional_characters, $error_block, $error_message)</code>

where

-   <i>additional_characters</i> is a list of additionally allowed characters besides digits and one
minus sign (provide an empty string if none); note that if you want to use / (backslash) you need to specify
it as three (3) backslashes ("///")!

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

Validates if the value contains only digits (0 to 9) and/or <b>one</b> minus sign (but only if it is the very
first character) <b>plus</b> characters given as additional characters (if any).

<b>When this rule is set, element's "type" attribute will be automatically changed to "number", making
the element more friendly to mobile users</b>

Available for the following controls: {@link Zebra_Form_Password password}, {@link Zebra_Form_Text text},
{@link Zebra_Form_Textarea textarea}

<code>
// $obj is a reference to a control
$obj->set_rule(
'number' => array(
''                  // don't allow any extra characters
'error',            // variable to add the error message to
'Invalid integer!'  // error message if value doesn't validate
)
);
</code>

-   <b>range</b>

<code>'range' => array($range, $error_block, $error_message)</code>

where

-   <i>range</i> is an array with 2 values, representing the minimum and maximum allowed values. 0 (zero) means
"any value". Therefore, a range of array(100, 0) would validate values of 100 and above, array(50, 100)
would validate values between 50 and 100 (inclusive), while (0, 50) would validate values below 51

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

Validates if the value is within range

Available for the following controls: {@link Zebra_Form_Text text}

<code>
// $obj is a reference to a control
$obj->set_rule(
'range' => array(
array(50, 100)                                                  // allow values between 50 and 100 (inclusive)
'error',                                                        // variable to add the error message to
'The entered value must be between 50 and 100 (inclusive)'      // error message if value doesn't validate
)
);
</code>

-   <b>regexp</b>

<code>'regexp' => array($regular_expression, $error_block, $error_message)</code>

where

-   <i>regular_expression</i> is the regular expression pattern (without delimiters) to be tested on the value

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

Validates if the value satisfies the given regular expression

Available for the following controls: {@link Zebra_Form_Password password}, {@link Zebra_Form_Text text},
{@link Zebra_Form_Textarea textarea}

<code>
// $obj is a reference to a control
$obj->set_rule(
'regexp' => array(
'^0123'                         // the regular expression
'error',                        // variable to add the error message to
'Value must begin with "0123"'  // error message if value doesn't validate
)
);
</code>

-   <b>required</b>

<code>'required' => array($error_block, $error_message)</code>

where

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed


Validates only if a value exists.

Available for the following controls: {@link Zebra_Form_Checkbox checkbox}, {@link Zebra_Form_Date date},
{@link Zebra_Form_File file}, {@link Zebra_Form_Password password}, {@link Zebra_Form_Radio radio},
{@link Zebra_Form_Select select}, {@link Zebra_Form_Text text}, {@link Zebra_Form_Textarea textarea},
{@link Zebra_Form_Time time}

<code>
// $obj is a reference to a control
$obj->set_rule(
'required' => array(
'error',            // variable to add the error message to
'Field is required' // error message if value doesn't validate
)
);
</code>

-   <b>resize</b>

<samp>This rule requires the prior inclusion of the {@link http://stefangabos.ro/php-libraries/zebra-image Zebra_Image}
library!</samp>

<code>'resize' => array(
$prefix,
$width,
$height,
$preserve_aspect_ratio,
$method,
$background_color,
$enlarge_smaller_images,
$jpeg_quality,
$error_block,
$error_message,
)
</code>

where

-   <i>prefix</i>: If the resized image is to be saved as a new file and the originally uploaded file needs to be
preserved, specify a prefix to be used for the new file. This way, the resized image will have the same name as
the original file but prefixed with the given value (i.e. "thumb_").

Specifying an empty string as argument will instruct the script to apply the resizing to the uploaded image
and therefore overwriting the originally uploaded file.

-   <i>width</i> is the width to resize the image to.

If set to <b>0</b>, the width will be automatically adjusted, depending on the value of the <b>height</b>
argument so that the image preserves its aspect ratio.

If <b>preserve_aspect_ratio</b> is set to TRUE and both this and the <b>height</b> arguments are values
greater than <b>0</b>, the image will be resized to the exact required width and height and the aspect ratio
will be preserved (see the description for the <b>method</b> argument below on how can this be done).

If <b>preserve_aspect_ratio</b> is set to FALSE, the image will be resized to the required width and the
aspect ratio will be ignored.

If both <b>width</b> and <b>height</b> are set to <b>0</b>, a copy of the source image will be created
(<b>jpeg_quality</b> will still apply).

If either <b>width</b> or <b>height</b> are set to <b>0</b>, the script will consider the value of the
<b>preserve_aspect_ratio</b> to bet set to TRUE regardless of its actual value!

-   <i>height</i> is the height to resize the image to.

If set to <b>0</b>, the height will be automatically adjusted, depending on the value of the <b>width</b>
argument so that the image preserves its aspect ratio.

If <b>preserve_aspect_ratio</b> is set to TRUE and both this and the <b>width</b> arguments are values greater
than <b>0</b>, the image will be resized to the exact required width and height and the aspect ratio will be
preserved (see the description for the <b>method</b> argument below on how can this be done).

If <b>preserve_aspect_ratio</b> is set to FALSE, the image will be resized to the required height and the
aspect ratio will be ignored.

If both <b>height</b> and <b>width</b> are set to <b>0</b>, a copy of the source image will be created
(<b>jpeg_quality</b> will still apply).

If either <b>height</b> or <b>width</b> are set to <b>0</b>, the script will consider the value of the
<b>preserve_aspect_ratio</b> to bet set to TRUE regardless of its actual value!

-   <i>preserve_aspect_ratio</i>: If set to TRUE, the image will be resized to the given width and height and the
aspect ratio will be preserved.

Set this to FALSE if you want the image forcefully resized to the exact dimensions given by width and height
ignoring the aspect ratio

-   <i>method</i>: is the method to use when resizing images to exact width and height while preserving aspect
ratio.

If the <b>preserve_aspect_ratio</b> property is set to TRUE and both the <b>width</b> and <b>height</b>
arguments are values greater than <b>0</b>, the image will be resized to the exact given width and height
and the aspect ratio will be preserved by using on of the following methods:

-   <b>ZEBRA_IMAGE_BOXED</b> - the image will be scalled so that it will fit in a box with the given width and
height (both width/height will be smaller or equal to the required width/height) and then it will be centered
both horizontally and vertically. The blank area will be filled with the color specified by the
<b>background_color</b> argument. (the blank area will be filled only if the image is not transparent!)

-   <b>ZEBRA_IMAGE_NOT_BOXED</b> - the image will be scalled so that it <i>could</i> fit in a box with the given
width and height but will not be enclosed in a box with given width and height. The new width/height will be
both smaller or equal to the required width/height

-   <b>ZEBRA_IMAGE_CROP_TOPLEFT</b>
-   <b>ZEBRA_IMAGE_CROP_TOPCENTER</b>
-   <b>ZEBRA_IMAGE_CROP_TOPRIGHT</b>
-   <b>ZEBRA_IMAGE_CROP_MIDDLELEFT</b>
-   <b>ZEBRA_IMAGE_CROP_CENTER</b>
-   <b>ZEBRA_IMAGE_CROP_MIDDLERIGHT</b>
-   <b>ZEBRA_IMAGE_CROP_BOTTOMLEFT</b>
-   <b>ZEBRA_IMAGE_CROP_BOTTOMCENTER</b>
-   <b>ZEBRA_IMAGE_CROP_BOTTOMRIGHT</b>

For the methods involving crop, first the image is scaled so that both its sides are equal or greater than the
respective sizes of the bounding box; next, a region of required width and height will be cropped from indicated
region of the resulted image.

-   <i>background_color</i> is the hexadecimal color of the blank area (without the #). See the <b>method</b>
argument.

-   <i>enlarge_smaller_images</i>: if set to FALSE, images having both width and height smaller than the required
width and height, will be left untouched (<b>jpeg_quality</b> will still apply).

-   <i>jpeg_quality</i> indicates the quality of the output image (better quality means bigger file size).

Range is 0 - 100

Available only for JPEG files.

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

<i>This rule must come</i> <b>after</b> <i>the</i> <b>upload</b> <i>rule!</i>

This is not an actual "rule", but because it can generate an error message it is included here.

Available only for the {@link Zebra_Form_File file} control

<i>This rule is not available client-side!</i>

<code>
// $obj is a reference to a control
$obj->set_rule(
'resize' => array(
'thumb_',                           // prefix
'150',                              // width
'150',                              // height
true,                               // preserve aspect ratio
ZEBRA_IMAGE_BOXED,                  // method to be used
'FFFFFF',                           // background color
true,                               // enlarge smaller images
85,                                 // jpeg quality
'error',                            // variable to add the error message to
'Thumbnail could not be created!'   // error message if value doesn't validate
)
);

// for multiple resizes, use an array of arrays:
$obj->set_rule(
'resize' => array(
array('thumb1_', 150, 150, true, ZEBRA_IMAGE_BOXED, 'FFFFFF', true, 85, 'error', 'Error!'),
array('thumb2_', 300, 300, true, ZEBRA_IMAGE_BOXED, 'FFFFFF', true, 85, 'error', 'Error!'),
)
);
</code>

-   <b>upload</b>

<code>'upload' => array($upload_path, $file_name, $error_block, $error_message)</code>

where

-   <i>upload_path</i> the path where to upload the file to, relative to the currently running script.

-   <i>file_name</i>: specifies whether the uploaded file's original name should be preserved, should it be
prefixed with a string, or should it be randomly generated.

Possible values can be <b>TRUE</b>: the uploaded file's original name will be preserved; <b>FALSE</b> (or,
for better code readability, you should use the "ZEBRA_FORM_UPLOAD_RANDOM_NAMES" constant instead of "FALSE")
: the uploaded file will have a randomly generated name; <b>a string</b>: the uploaded file's original name
will be preserved but it will be prefixed with the given string (i.e. "original_", or "tmp_").

Note that when set to TRUE or a string, a suffix of "_n" (where n is an integer) will be appended to the
file name if a file with the same name already exists at the given path.

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

Validates if the file was successfully uploaded to the folder specified by <b>upload_path</b>.

<i>Remember to check the form's {@link Zebra_Form::$file_upload $file_upload} property for information about the
uploaded file after the form is submitted!</i>

<i>Remember to check the form's {@link Zebra_Form::$file_upload_permissions $file_upload_permissions} property
for how to set the filesystem permissions of the uploaded files!</i>

<i>Note that once this rule is run client-side, the DOM element the rule is attached to, will get a data-attribute
called</i> <b>file_info</b> <i>which will contain information about the uploaded file, accessible via JavaScript.</i>

<code>
console.log($('#element_id').data('file_info'))
</code>

This is not actually a "rule", but because it can generate an error message it is included here

You should use this rule in conjunction with the <b>filesize</b> rule

Available only for the {@link Zebra_Form_File file} control

<i>This rule is not available client-side!</i>

<code>
// $obj is a reference to a control
$obj->set_rule(
'upload' => array(
'tmp',                              // path to upload file to
ZEBRA_FORM_UPLOAD_RANDOM_NAMES,     // upload file with random-generated name
'error',                            // variable to add the error message to
'File could not be uploaded!'       // error message if value doesn't validate
)
);
</code>

-   <b>url</b>

<code>'url' => array($require_protocol, $error_block, $error_message)</code>

where

-   <i>require_protocol</i> indicates whether the <i>http</i> or <i>https</i> prefix should be mandatory or not

-   <i>error_block</i> is the PHP variable to append the error message to, in case the rule does not validate

-   <i>error_message</i> is the error message to be shown when rule is not obeyed

Validates if the value represents a valid URL

The regular expression used is the following:

<code>/^(http(s)?\:\/\/)?[^\s\.]+\..{2,}/i</code>

Some example URLs that are considered valid by this rule are:
-   google.com (if the <i>require_protocol</i> attribut is set to FALSE)
-   http://google.com
-   http://www.google.com
-   http://www.google.com?foo=bar
-   http://www.google.com?foo=bar#anchor

<samp>Note that this rule will only validate common URLs and does not attempt to be a validator for all possible
valid URLs, and therefore it will fail on most of the more exotic URLs used in the tests {@link http://mathiasbynens.be/demo/url-regex here}.
Keep that in mind when deciding on whether to use this rule or not. Nevertheless, this should be enough for
validating most of the URLs you encountered on a daily basis.</samp>

Available for the following controls: {@link Zebra_Form_Password password}, {@link Zebra_Form_Text text},
{@link Zebra_Form_Textarea textarea}

<code>
// $obj is a reference to a control
$obj->set_rule(
'url' => array(
true,               // require users to start the URL with http:// or https:// in order for the URL to be valid
'error',            // variable to add the error message to
'Not a valid URL!'  // error message if value doesn't validate
)
);
</code>

@param  array   $rules  An associative array

See above how it needs to be specified for each rule

@return void
Sets a single or an array of validation rules for the control .