HedgeClipper [part 2]!
by , 01-20-2013 at 11:19 PM (82697 Views)
Hey guys, I hope everyone has had a great start to the new year.
If you're just joining us, we're making hedgeclipper: a user log-in system. Last time, we outlined the basics of how hedgeclipper will work, and wrote a controller function for the whole thing. This time, we're going to focus on checking if the user is logged in or not. Before we start demanding a username and password, we're going to check if our user already logged in on a previous page visit. Have a look:
Hedgeclipper stores user info in the $_SESSION superglobal, so basically, this function just checks if there is any user login info present.PHP Code:/**
* this function checks if a user is currently logged in.
* if so, it sets up the user's info for hedgeclipper to use.
*
* @return bool true if the user is logged in; false otherwise
*/
function hedgeclipper_checkLoggedIn(){
# hedgeclipper info is stored in session, so make sure one has been started.
if( !session_id() ){ session_start(); }
# check if there are any hooks to do
hedgeclipper_doHook( 'checkLoggedIn_start' );
# check if hedgeclipper info exists:
if( !empty( $_SESSION['hedgeclipper'] ) ){
# pull the data from the session;
# hedgeclipper_userinfo() validates and stores it
if( hedgeclipper_userinfo( $_SESSION['hedgeclipper'] ) ){
# now we can check if the user has logged in or not:
if( # start with a basic login check
hedgeclipper_userinfo( 'auth','last_login' ) > 0
# and see if there's a hook also
&& hedgeclipper_doHook( 'checkLoggedIn_success' )
){
# all good.
return true;
}
}
}
# if we get to this point, either the user is not logged in, or something went wrong.
hedgeclipper_doHook( 'checkLoggedIn_fail' );
return false;
}
last_logincontains a unix timestamp, set when the user last logged in - if it's0, the user hasn't logged in yet. If it's greater than 0, then we have a record of the user logging in, and we don't need to ask again.
There are several spots in this function where we call another function calledhedgeclipper_doHook(). This is fun: if there is a function in the hedgeclipper options tied to a particular event, this will run that function and return the result. This allows us to add custom functionality without rewriting (and possibly breaking!) the actual hedgeclipper functions.
For example, we might want hedgeclipper to check not only if the user logged in, but that they logged in recently. No problem!Now, if the user logged in more than an hour ago, this function will return FALSE and the login check will fail.PHP Code:# EXAMPLE USAGE - not part of hedgeclipper #
// write a custom check function:
function check_recentLogin(){
# check if login was within last hour
if( hedgeclipper_userinfo( 'auth','last_login' ) > time() + 60*60 ){
return true;
}
# not recent... :(
return false;
}
// register our "hook" in options, under the "checkLoggedIn_success" event:
hedgeclipper_options( array( 'hooks'=>array( 'checkLoggedIn_success'=>'check_recentLogin' ) ) );
Another function that both these functions call ishedgeclipper_userinfo(). This one work similarly to thehedgeclipper_options()function, except that it doesn't manage options: it manages information about the user.
There are three categories of information to manage:
- auth. Info about authentication (login status) and authorization (permissions).
- user. Info about the user specifically (e.g., their name, email, etc.).
- app. Arbitrary info that's not specifically about the user or their authorization, but you want to associate with the user and their session. User preferences might be a good example of info to store here.
There are a few functions that this function uses to set up default values for "auth", "user", and "app". This is also where you can "hook" your own functions, if you want to add to the default items. Because this post is too long already, I'll link to those functions so you can check 'em out.PHP Code:/**
* this function organizes and stores all the info hedgeclipper needs.
*
* @param string $mode determines category to use: "auth","user","app"
* also accepts "all" to get the whole $userinfo array.
* @param string|array $info to *get* info, pass the key name
* to *set* info, pass an array with "key"=>"new info"
* @return string|bool the info if requested, or TRUE if new info was set;
* FALSE otherwise
*/
function hedgeclipper_userinfo( $mode,$info=null ){
# static containers for each userinfo category
static $auth;
static $user;
static $app;
# set defaults for each userinfo category
if( empty( $auth ) ){ $auth = hedgeclipper_userinfo_auth_default(); }
if( empty( $user ) ){ $user = hedgeclipper_userinfo_user_default(); }
if( empty( $app ) ){ $app = hedgeclipper_userinfo_app_default(); }
# check $mode:
switch( $mode ){
# use $auth array:
case 'auth':
# if $info is the name of an $auth key, return that item's value.
if( is_string( $info ) && array_key_exists( $auth[$info] ) ){
return $auth[$info];
}
# if $auth contains the name of an $auth key and a value, set the key to that value.
if( is_array( $info ) && (count( $info ) == 2) && array_key_exists( $auth[$info[0]] ) ){
$auth[$info[0]] = $info[1];
return true;
}
# otherwise, return false.
return false;
# use $user array:
case 'user':
# works the same way as "auth".
if( is_string( $info ) && array_key_exists( $user[$info] ) ){
return $user[$info];
}
if( is_array( $info ) && (count( $info ) == 2) && array_key_exists( $user[$info[0]] ) ){
$user[$info[0]] = $info[1];
return true;
}
return false;
# use $app:
case 'app':
# works the same way, but allows new keys to be set arbitrarily.
if( is_string( $info ) && array_key_exists( $app[$info] ){
return $app[$info];
}
if( is_array( $info ) && (count( $info ) == 2) ){
$app[$info[0]] = $info[1];
return true;
}
return false;
# use all:
case 'all':
# set all new userinfo
if( is_array( $info ) && isset( $info['auth'] ) && isset( $info['user'] ) && isset( $info['app'] ) ){
$auth = $info['auth'];
$user = $info['user'];
$app = $info['app'];
return true;
}
return array( $auth,$user,$app );
# do nothing:
default: return;
}
}
The last bit of code we'll look at today is hedgeclipper_checkLoggedIn()'s complementary function: where checkLoggedIn gets info from the session,hedgeclipper_rememberLoggedIn()will store info in the session.Let's take a quick break from coding and look at some good ol'fashioned HTML. We're going to put our HTML in "template" files - that way, we can keep it organized and we can also edit or replace individual parts easily.PHP Code:/**
* this function updates the php session with hedgeclipper's info.
*/
function hedgeclipper_rememberLoggedIn(){
# update the "last activity" time
hedgeclipper_userinfo( 'auth',array( 'last_activity','now' ) );
# save all hedgeclipper userinfo to session
if( !session_id() ){ session_start(); }
$_SESSION['hedgeclipper'] = hedgeclipper_userinfo( 'all' );
}
hedgeclippertemplate.loginform.htmlIn your browser, the form will look something like this:HTML Code:<!-------------------------------------------- html markup for hedgeclipper login form. there are two "placeholders" in the markup. the hedgeclipper functions will look for and replace them with dynamic values: -- %action% will be replaced by the appropriate URL to submit the form to. -- %token% will be replaced by a unique security token to help prevent brute force attacks. --------------------------------------------> <form class="hedgeclipper_login" action="%action%" method="post"> <fieldset> <legend>log in with <b>hedgeclipper</b></legend> <input type="hidden" name="hedgeclipper[token]" value="%token%"> <p><label for="hedgeclipper[email]">Email: </label><input type="email" name="hedgeclipper[email]" required> <p><label for="hedgeclipper[password]">Password: </label><input type="password" name="hedgeclipper[password]" required> <p><label> </label><input type="submit" value="Log In"> </fieldset> </form>
You might clean it up with some basic CSS:Code:.hedgeclipper_login{ border: 1px outset gray; background: #eee; font-family: sans-serif; } .hedgeclipper_login label{ display: inline-block; width: 8em; }
That's a lot of stuff we covered...! Next time, we'll look how to handle actual login attempts, and also some database stuff!
See ya next time,
-Adrian





![Submit "HedgeClipper [part 2]!" to del.icio.us](images/misc/bookmarksite_delicious.gif)
![Submit "HedgeClipper [part 2]!" to StumbleUpon](images/misc/bookmarksite_stumbleupon.gif)
![Submit "HedgeClipper [part 2]!" to Google](images/misc/bookmarksite_google.gif)
![Submit "HedgeClipper [part 2]!" to Digg](images/misc/bookmarksite_digg.gif)

