The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Apache::Voodoo::api

Synopsis

Each page module must inherit from Apache::Voodoo. This module provides the new() method to make the package a proper object under Voodoo, along with some other minor black magic. Inheriting from this module provides access to some essential methods for interacting with Voodoo.

        package my_app::index;

        use strict;
        use base ("Apache::Voodoo");

        sub handle {
                my $self = shift;
                my $p    = shift;

                # hash reference of data suitable for passing to the 
                # params() method in HTML::Tempate
                return $hash_ref;
        }

        1;

$p is a hash reference that contains plethora of things:

dbh

DBI object already connected to the database as described in the Voodoo configuration file.

dir_config

Directory configuration directives from Apache (see the mod_perl docs for $r->dir_config)

document_root

/path/to/the/document/root/for/this/site

params

key / value pairs of all the url POST or GET parameters. If a given key is present more than once in the POST/GET parameters then the value is an array reference of them.

session

Apache::Session object where you may store any client persistant data.

Voodoo keeps a few of it's own internal variables here as well, so a little bit of care must be taken to not clobber them. 'timestamp' and 'history' are reserved, look but don't touch.

template_conf

Contents of the matching template_conf section in the Voodoo configuration file.

uri

/the/current/url/minus/the/server.com/part/and/parameters

user-agent

User-agent string as presented by the browser

The call and return syntax is the same for any page modules and pre/post includes.

METHODS INHERITED FROM Apache::Voodoo

init()

Since the new() method is reserved for some Voodoo specific black magic, you may add the init method in your modules to do basically the same sorts of things that you would normally do inside a new(). For example:

 usage:
    sub init {
        my $self = shift;
        $self->{'some_private_var'} = 'SOME VALUE';
    }

Debugging

db_error()

Used to report catastrophic database errors to the error_log file and to the web browser. If DEBUG is turned on, then the details or the error will be displayed, otherwise a 500 error is returned to Apache. This method uses die() internally and thus DOES NOT RETURN.

 usage:
        $dbh->selectall_arrayref($query) || $self->db_error();
debug($one_message, [ $two_message, ... ] )

Prints user debugging messages to the error_log file and to the 'Debug' section of the DEBUG template block. (See Apache::Voodoo::Debug for more details). Messages can be turn on or off globally using the DEBUG option of the Voodoo configuration file.

If any of the parameters to debug a references, they printed using Data::Dumper.

 usage:
     return $self->debug('The value of foo is:',$foo);
mark($message)

Optionally appends a Time::HiRes time stamp to the 'Generation Time' section of the DEBUG block. Messages can be turn on or off globally using the DEBUG option of the configuration.

 usage:
     $self->mark('descriptive message about this point in the code');

 example:

     $self->mark('Start of big nasty loop');
     foreach (@lots_of_stuff) {
         # do stuff
     }
     $self->mark('End of big nasty loop');

Browser Redirection

access_denied( [ $error ], [ $uri ] )

By default it redirects to /access_denied which should contain some appropriate access denied message. If there is a handler associated with that page, the optional $error parameter can by used to proved the handling module with some additional information. The second parameter can be used to have the user redirected somewhere else besides the default location. If the second param is not used and the access_denied template does not exist, then the standard Apache 403 (Forbidden) is returned to the user.

 usage:
    return $self->access_denied;
        or
    return $self->access_denied('need_user_privilege');
                or
    return $self->access_denied('need_user_privilege', '/user/access_denied');
display_error($error,$uri)

Redirects the user to a generic error message display page.

 usage:
        return $self->display_error('stuff went bang!','/index');
history($voodo_session,$index)

Voodoo keeps a running list of the last 10 urls visited in the current session. This method provides access to that list. $index == 0 is the current page, $index == 1 is the page before this one. Successive requests to the same page with different parameters DOES NOT add a new entry to this history, rather it only updates the URI parameters for that entry in the history. For example, if you click the 'next' link in paginated result set 10 times, the history doesn't contain 10 entries for each of those pages.

 usage:
    $url = $self->history($p->{'session'},3);
tardis($p, $uri1, [$uri2, ...] )

Often within a website there is the need to go back to a previous page that the user has already visited. For example the page that let's you view a record contains an 'edit' link for that record. After the edit has finished, odds are you'd want to send the user back to that view page. This can quickly lead to a lot of tedious parameter management for those return-to pages. Plus there may be more than one entry point for the current module only adding to the complexity. Tardis provides a convenient way search the history for a set of URI's and redirect the user back to the first one it finds.

The uri's must contain the full path, relative uri's don't work. You do not need to specify the parameters for that page, in fact doing so would kinda defeat the point :)

If no history items match, it redirects to the previously accessed uri.

 usage:
    return $self->tardis($p,'/first/url/no_params','/second/url/no_params');

 example:
    /admin/view_user and /admin/list_user contain a link to the edit command.  Each
    takes different parameters and the user could have been on either before clicking
    the edit link.

    Your edit method could look like this:

    sub edit {
        my $self = shift;
        my $p = shift;
  
        # do some stuff

        return $self->tardis($p,'/admin/view_user','/admin/list_user');
    }

    You no longer have to figure out which link they came from, and what parameters they
    were using at the time.
redirect($uri)

Redirects the user to the given URI. These may be absolute or relative

 usage:
        return $self->redirect('/some/uri');

Data Manipulation

prep_select($array_of_arrays, [ $selected_value ] )

Ever notice how when you're making select lists or lists of radio buttons that you end up doing 95% of them exactly the same way? This method does the HTML::Template-ifying of the data for you for those 95% cases.

 usage:
    $return->{'my_list' = $self->prep_select(
        [
            [ $id_value,  $select_label  ], 
            [ $id_value2, $select_label2 ], ...
        ],
        $id_value_to_mark_selected
    );

    or

    $return->{'my_list' = $self->prep_select(
        [
            [ $id_value,  $select_label  ], 
            [ $id_value2, $select_label2 ], ...
        ],
        [ $selected_id1, $select_id2, ... ]
    );


 corresponding HTML::template for select lists (lines broken up for clarity):
     <select name="my_list">
     <tmpl_loop my_list>
         <option 
             value="<tmpl_var ID>" 
             <tmpl_if SELECTED>selected</tmpl_if>
         >
             <tmpl_var NAME>
         </option>
     </tmpl_loop>
     </select>

 corresponding HTML::template for radio buttons:
     <tmpl_loop my_list>
         <input 
             type="radio"
             name="my_list"
             value="<tmpl_var ID>"
             <tmpl_if SELECTED>checked</tmpl_if>
         >
         <tmpl_var NAME>
     </tmpl_loop>
trim($string)

Removes leading and trailing whitespace

 usage:
    $value = $self->trim("  <-- these spaces will be removed -->  ");
raw_mode($content_type,$contents, [ \%optional_http_headers ] )

This method is used to bypass the normal templating subsystem and allows the 'contents' to be streamed directly to the browser. Useful for generating CSVs and binary data from within Voodoo.

 usage:
    return $self->raw_mode(
        'text/csv',
        $contents,
        {
            'Content-disposition' => "attachment;filename=SomeFile.csv"
        }
    );
last_insert_id()

Returns the value of the last auto_increment id in MySQL

Eventually I'm going to subclass DBI for Voodoo and include this there :)

AUTHOR

Maverick, /\/\averick@smurfbaneDOTorg

COPYRIGHT

Copyright (c) 2005 Steven Edwards. All rights reserved.

You may use and distribute Voodoo under the terms described in the LICENSE file include in this package or Apache::Voodoo::license. The summary is it's a legalese version of the Artistic License :)