Smarty Forum Index Smarty
The discussions here are for Smarty, a template engine for the PHP programming language.

SmartyValidate custom criteria functions

 
Post new topic   Reply to topic    Smarty Forum Index -> Add-ons
View previous topic :: View next topic  
Author Message
infect
Smarty Rookie


Joined: 04 Jun 2004
Posts: 9

PostPosted: Mon Jun 07, 2004 11:05 pm    Post subject: SmartyValidate custom criteria functions Reply with quote

I was just wondering what values an "isCustom" custom function should return. The documentation shows an example function signature, but not an actual function.

From the documentation:

Quote:

isCustom
--------

example:
{validate field="password" criteria="isCustom" function="passValid" message="..."}

"isCustom": checks a field against a php function. "function" is
required, and must be an existing PHP function. Class method
calls must be wrapped in a PHP function. The function must be
registered with the register_criteria() method.

custom functions are called like so:

passValid($value, $empty, &$params, &$formvars) { }

Where $value is the form value being tested and $empty is the boolean value
of the "empty" attribute. The third value holds the array of ALL the
attributes for this validator. $params is passed by reference so you can
manipulate the session data within your function if necessary. The fourth
parameter is ALL the submitted form vars, passed by reference so you can
manipulate them if necessary.



most importantly, the line that reads:

Quote:

passValid($value, $empty, &$params, &$formvars) { }


if for example, i wanted to make a function to make sure all characters in a field are alphanumeric, this is what i came up with:

Code:

// NOTE: IT IS ASSUMED THAT THESE CRITERIA HAVE ALREADY BEEN RUN: notEmpty, isLength
function username_alphanumeric($value, $empty, &$params, &$formvars)
{
   // extract the field data into $username
   if(ereg('[^A-Za-z0-9]', $username))
   {
      echo "Usernames must contain only letters and numbers.";
   }
   else
   {
      echo "$username is a valid username.";
   }
}


it is obviously incomplete, but instead of echoing the messages, should i be returning true and false, or printing out their error message directly from $params only if it fails? just a bit confused, any help would be greatly appreciated.
Back to top
View user's profile Send private message
infect
Smarty Rookie


Joined: 04 Jun 2004
Posts: 9

PostPosted: Tue Jun 08, 2004 12:00 am    Post subject: Reply with quote

this seems to have worked:

Code:

// NOTE: IT IS ASSUMED THAT THESE CRITERIA HAVE ALREADY BEEN RUN: notEmpty, isLength
function username_alphanumeric($value, $empty, &$params, &$formvars)
{
   if(ereg('[^A-Za-z0-9]', $value))
   {
      return false;
   }
   else
   {
      return true;
   }
}


or, for brevity:

Code:

// NOTE: IT IS ASSUMED THAT THESE CRITERIA HAVE ALREADY BEEN RUN: notEmpty, isLength
function username_alphanumeric($value, $empty, &$params, &$formvars)
{

   return !ereg('[^A-Za-z0-9]', $value);
}
Back to top
View user's profile Send private message
mohrt
Administrator


Joined: 16 Apr 2003
Posts: 7367
Location: Lincoln Nebraska, USA

PostPosted: Tue Jun 08, 2004 12:29 am    Post subject: Reply with quote

That is correct, your function should return true/false. The error message is stated in the template tag. If you'd rather have the function determine the error message, you can reset it from within the function:

$params['message'] = 'That is incorrect.';

Or, you can assign one or more variables in the $formvars array. If you assign that array to Smarty after the validation they will be available from within the template.

$formvars['errors'][] = 'username is incorrect';
$formvars['errors'][] = 'password is incorrect';
Back to top
View user's profile Send private message Visit poster's website
infect
Smarty Rookie


Joined: 04 Jun 2004
Posts: 9

PostPosted: Tue Jun 08, 2004 5:11 am    Post subject: smarty validator bug? Reply with quote

monte, is there a limitation to the number of criteria you can register to a function? for some reason it will not run both of my custom criteria together, but if i disable one, then the other works perfectly...

I've checked my code over and over and can't seem to find what i might be doing wrong. I was wondering if maybe the smartyvalidator class doesn't keep more than one "isCustom" function stored at a time, what do you think?

this may be the relevant code, i'm not sure:
Code:

    function register_criteria($func_name, $form = 'default') {
        if(!SmartyValidate::is_init($form)) {
            trigger_error("SmartyValidate: [register_criteria] form '$form' is not initialized.");
            return false;
        }
        if(!function_exists($func_name)) {
            trigger_error("SmartyValidate: [register_criteria] function '$function' does not exist.");
            return false;
        }
        if(!in_array($func_name, $_SESSION['SmartyValidate'][$form]['registered_criteria']))
            $_SESSION['SmartyValidate'][$form]['registered_criteria'][] = $func_name;
        return true;
    }


when $_SESSION['SmartyValidate'][$form]['registered_criteria'][] = $func_name; is set, it does not look like any index is being changed in order to accommodate additional functions, it seems as though it is simply being reset. I could be totally off, but i think i'm doing it right.

here's my code for reference:
function.validate_form.php
Code:

<?php
require_once(SMARTY_DIR . 'SmartyValidate.class.php');

// WARNING: I'M CURRENTLY NOT ESCAPING ALL DATA FROM THE FORM! THIS IS BAD! FIX!

function smarty_function_validate_form($params, &$smarty)
{
   $isValidFormData = valid_form(&$smarty);
   $smarty->assign($params['isValidFormData'], $isValidFormData);
}

function valid_form(&$smarty)
{
   // required initialization
    SmartyValidate::connect($smarty);

   SmartyValidate::register_criteria('username_availible');
   SmartyValidate::register_criteria('username_alphanumeric');
   
   // initialize the form validater
   if(empty($_POST))
   {
      // register custom criteria for checking if username is availible
      return false;
   }
   else
   {   
      // validate after a POST
      if(SmartyValidate::is_valid($_POST))
      {
         // no errors      
         // TODO: submit values into database
         $query = "INSERT INTO user (username, username_crc, password, first_name, last_name, date_created, email_address, phone_number) VALUES ('%s',%u,'%s','%s', '%s', NOW(),'%s','%s')";
         $query = sprintf($query, mysql_escape_string($_POST['username']), crc32($_POST['username']), md5($_POST['password']), mysql_escape_string($_POST['first_name']), mysql_escape_string($_POST['last_name']), $_POST['email_address'], $_POST['phone_number']);

         // TODO: send them a verification email
         
         // TODO: clear data and send them to the "succeeded" page
         
         // clear session data and continue
         SmartyValidate::disconnect();
         return true;
      }
      else
      {
         // error, redraw the form   
         
         $smarty->assign($_POST);
         return false;
      }   
   }
   
}

// custom criteria functions
// NOTE: IT IS ASSUMED THAT THESE CRITERIA HAVE ALREADY BEEN RUN:  isLength

function username_availible($value, $empty, &$params, &$formvars)
{
   echo "GOT HERE: username_availible (start) <br>";
   if(!get_magic_quotes_gpc())
   {
      $value = addslashes($value);
   }
      
   $query = "SELECT * FROM user WHERE username_crc=%u AND username='%s'";
   $query = sprintf($query, crc32($value), $value);
   echo "QUERY: $query<br>";
   
   $result = mysql_query($query);
   $num_rows = @mysql_num_rows($result);
   if ($num_rows)
   {
      return false;
   }
   else
   {
      return true;
   }
   
}

function username_alphanumeric($value, $empty, &$params, &$formvars)
{
   echo " GOT HERE: username_alphanumeric (start) <br>";
   return !ereg('[^A-Za-z0-9]', $value); // if it does contain those characters, then the test should fail...
}


?>


and registration_form.tpl:
Code:


<form method="post" action="?action=register" name="register">
   <fieldset>
      <legend>Registration Information</legend>
      <p class="inputRequirement">* Required information</p>
      <div class="formRow"><label>First Name:</label> <input name="first_name" type="text" class="textbox" {if $smarty.post.first_name != ""} value="{$smarty.post.first_name}" {/if} />
         <span class="inputRequirement">* {validate field="first_name" criteria="notEmpty" transform="trim" message="First Name is required."}</span></div>
      <div class="formRow"><label>Last Name:</label> <input name="last_name" type="text" class="textbox" {if $smarty.post.last_name != ""} value="{$smarty.post.last_name}" {/if} />
         <span class="inputRequirement">* {validate field="last_name" criteria="notEmpty" transform="trim" message="Last Name is required."}</span></div>
      <div class="formRow"><label>Phone Number:</label> <input name="phone_number" type="text" class="textbox" {if $smarty.post.phone_number != ""} value="{$smarty.post.phone_number}" {/if} />
         <span class="inputRequirement">{validate field="phone_number" criteria="isNumber" empty="yes" transform="trim" message="Phone Number must be a number."}</span></div>
      <div class="formRow"><label>Email Address:</label> <input name="email_address" type="text" class="textbox" {if $smarty.post.email_address != ""} value="{$smarty.post.email_address}" {/if} />
         <span class="inputRequirement">* {validate field="email_address" criteria="isEmail" transform="trim" message="Email Address not valid."}</span></div>
      <div class="formRow"><label>Re-Type Email Address:</label> <input name="email_address_verify" type="text" class="textbox" {if $smarty.post.email_address_verify != ""} value="{$smarty.post.email_address_verify}" {/if} />
         <span class="inputRequirement">* {validate field="email_address_verify" criteria="isEqual" field2="email_address" transform="trim" message="Email Addresses do not match."}</span></div>
   </fieldset>
   <div class="fieldSetSpacer"><!-- spacer --></div>
   <fieldset>
      <legend>Account Information</legend>
      <p class="inputRequirement">* Required information</p>
      <div class="formRow"><label>Preferred Username:</label> <input name="username" type="text" class="textbox" {if $smarty.post.username != ""} value="{$smarty.post.username}" {/if} />
         <span class="inputRequirement">* {validate field="username" criteria="isCustom" function="username_alphanumeric" message="Username may only include alphanumeric characters (a-z, 0-9)."}{validate field="username" criteria="isLength" transform="trim" min="6" max="20" message="Username must be between 6 and 20 characters long."}{validate field="username" criteria="isCustom" function="username_availible" message="Username is not availible, please try a different name."}</span></div>
      <div class="formRow"><label>Password:</label> <input name="password" type="password" class="textbox" {if $smarty.post.password != ""} value="{$smarty.post.password}" {/if} />
         <span class="inputRequirement">* {validate field="password" criteria="isLength" transform="trim" min="6" max="50" message="Password must be at least 6 characters long."}</span></div>
      <div class="formRow"><label>Re-Type Password:</label> <input name="password_verify" type="password" class="textbox" {if $smarty.post.password_verify != ""} value="{$smarty.post.password_verify}" {/if} />
         <span class="inputRequirement">* {validate field="password" criteria="isEqual" field2="password_verify" message="Passwords do not match."}</span></div>
   </fieldset>
   <br />
   <input type="submit" value="Register!" />
</form>
Back to top
View user's profile Send private message
mohrt
Administrator


Joined: 16 Apr 2003
Posts: 7367
Location: Lincoln Nebraska, USA

PostPosted: Tue Jun 08, 2004 1:44 pm    Post subject: Reply with quote

There is no limit to the number of criteria on a single form element, however as soon as one criteria fails, the rest are ignored.
Back to top
View user's profile Send private message Visit poster's website
jaey
Smarty Regular


Joined: 25 May 2004
Posts: 36
Location: Louisville, Kentucky, USA

PostPosted: Mon Jun 14, 2004 4:24 am    Post subject: Reply with quote

The relevent lines from infect's template are:

Code:
{validate field="username" criteria="isCustom" function="username_alphanumeric" ...}
{validate field="username" criteria="isCustom" function="username_availible" ...}


The relevent lines of code from "plugins/function.validate.php" in SmartyValidate (version 2.1-b1) appear to be:

Code:
 1    $_sess =& $_SESSION['SmartyValidate'][$_form]['validators'];
 2
 3    $_found = false;
 4    if(isset($_sess) && is_array($_sess)) {
 5        foreach($_sess as $_key => $_field) {
 6            if($_field['field'] == $params['field']
 7                && $_field['criteria'] == $params['criteria']) {
 8                // field exists
 9                $_found = true;
10                if(isset($_sess[$_key]['valid'])
11                        && !$_sess[$_key]['valid']) {
12                    // not valid, show error and reset
13                    $_halt[$_form] = $params['halt'];
14                    $_echo = true;
15                    if(isset($params['assign'])) {
16                        $smarty->assign($params['assign'], $params['message']);
17                        $_echo = false;
18                    }
19                    if(isset($params['append'])) {
20                        $smarty->append($params['append'], $params['message']);
21                        $_echo = false;
22                    }
23                    if($_echo) {
24                        // no assign or append, so echo message
25                        echo $params['message'];
26                    }
27                    $_sess[$_key]['valid'] = null;
28                    break;
29                }
30            }
31        }
32    }
33    if(!$_found) {
34        // create
35        $_sess[] = $params;
36    }


The way I read this code, a validator only gets added to the session if lines 6 and 7 evaluate to false. Looking at the two lines from infect's template, the first validator will be processed. However, lines 6 and 7 will evaluate to true for the second validator since the field name and criteria are the same for both validators. This means that the second validator will be ignored.
Back to top
View user's profile Send private message
infect
Smarty Rookie


Joined: 04 Jun 2004
Posts: 9

PostPosted: Mon Jun 14, 2004 6:28 am    Post subject: Reply with quote

Right you are... I'll try that and see if it fixes the problem. I really appreciate your time!

... one question though... on the initial load... wouldn't everything be loaded completely?
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Smarty Forum Index -> Add-ons All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP