<?
/*******************************************************************/
class result
{
/*===================================================================
CLASS SUMMARY
Class Name: result
Author: jestevez
Created on: 5/22/00 4:09 PM
Last Change: 6/15/00 9:33 PM
Version: 0.1 This is a beta.
For complete documentation, please see the Result Class User Guide.
Things you need to change...
(1) Property: $path_to_templates
(2) Constructor: result()
(3) Method: parse_rule_element()
You can find them by looking for CHANGE in the code below.
===================================================================*/
// PROPERTIES
// CHANGE (1)
// You must set the value below to the path to your result templates. The path must end with '/'.
var $path_to_templates = ''; // String. The path to your result class templates.
var $result_id = FALSE; // Boolean A db result id passed to the contructor.
var $debug = FALSE; // Boolean If TRUE, messages will output to screen.
var $num_rows = 0; // Integer Number of returned DB as referenced by result id.
var $offset = 0; // Integer The default offset.
var $all_rules = array (); // Array Holds all rules.
var $html_buffer = ''; // String Buffers HTML for return.
var $dominant_rule = ''; // String Which ever rule correctly specifies the num_rows.
/*=================================================================*/
// CONSTRUCTOR
function result ( $result_id )
// Use the result_id to get the number of rows.
// If the result_id isn't set or is false, kick an error.
// 5/28/00 10:31 AM by Pippen
{
if ( $result_id )
{
$this->result_id = $result_id;
// CHANGE (2)
// Change the line below one that works with your database!
// The line should return the number of rows associated with the passed $result_id.
$this->num_rows = db_numrows ( $this->result_id );
return ( TRUE );
}
// You might want to set an error here: set_error ( DB_ERROR, 'Result class passed a result_id that was not valid.' );
}
/*=================================================================*/
// METHODS
/*-----------------------------------------------------------------*/
function set_result_rule ( $rule )
// 6/6/00 9:13 AM by jestevez
// Take the rule and see if it specifies a test.
// If it does, run the test and return false if the test is not passed.
// Otherwise, add the control.
// The return value is not significant to the class, but may
// be useful to the programmer.
{
// Check to see if the input is an array: assert_array ( $rule );
$is_test = in_array ( 'test', array_keys ( $rule ) );
$test_OK = $rule['test'];
if ( $is_test and ! $test_OK )
{
return ( FALSE );
}
$name = $rule['name'];
$this->all_rules[$name] = $rule;
return ( TRUE );
}
/*-----------------------------------------------------------------*/
function unset_result_rule ( $rule_name, $test = 1 )
// 6/6/00 9:13 AM by jestevez
// If the test passes, delete the rule.
// The default test always passes.
// The return value is not significant to the class, but may
// be useful to the programmer.
{
if ( ! $test )
{
return ( FALSE );
}
unset ( $this->all_rules[$rule_name] );
return ( TRUE );
}
/*-----------------------------------------------------------------*/
function get_result_html ( )
// Find a rule that applies to the number of rows returned.
// Apply that rule.
{
$num_rows = $this->num_rows;
$this->debug ( "Num rows is $num_rows." );
foreach ( $this->all_rules as $rule_name => $rule_value )
{
$max = (int) $rule_value['max'];
$min = (int) $rule_value['min'];
$redirect = (string) $rule_value['redirect'];
if ( $min <= $num_rows and $num_rows <= $max )
{
// If we are inside this clause it is because we found a rule that
// applies to the number of results returned by result_id passed to the class.
// Some rules ask us to redirect.
if ( $redirect )
{
// This will not work if any output has already been sent to the browser.
header ( "Location: $redirect" );
exit;
}
$this->dominant_rule = $rule_value;
$this->apply_dominant_rule ( );
break; // ... because only one rule should be used.
}
}
return ( $this->html_buffer );
}
/*-----------------------------------------------------------------*/
function include_template ( $template )
// In order to include elements, we need to first include their parent template.
// If we can't include the parent template, we're in trouble, so kick errors.
// 5/26/00 2:30 PM by jestevez
{
// IMPORTANT: Change the line below to point make sure it points to your template.
$template_path = $this->path_to_templates . $template . '.tpl';
if ( ! is_readable ( $template_path ) )
{
$this->debug ( "Error trying to use template $template_path" );
// Put in code to log error?
return ( FALSE );
}
include ( $template_path );
$this->debug ( "Template '$template' is OK" );
return ( TRUE );
}
/*-----------------------------------------------------------------*/
function debug ( $message )
// If debugging is on, output a debugging message.
// 5/26/00 4:56 PM by jestevez
{
if ( $this->debug )
{
print ("<BR><B>Result Class Debugging:</B> $message.");
}
}
/*-----------------------------------------------------------------*/
function parse_rule_element ( $element, $arguments, $type = '' )
/*--------------
NOTE: This function is recursive in 2 ways.
i. It keeps calling itself until the $element passed is not an array.
ii. If the element passed needs data from the DB,
the function gets that data, adds it to the $arguments,
and calls itself again.
5/26/00 2:51 PM by jestevez
--------------*/
{
if ( is_string ( $type ) AND $type == 'data' )
{
// This element expects data from the database.
// Loop through the data from the db, merge it with any rule specified $arguments.
// For each row, send the element back to this function,
// but this time, set type to 0 so no data is fetched from db.
// But before we actually loop through the data, lets put up
// control the widgets that let the user 'page' through results from a query.
$this->prepare_scroll_controls ();
$offset = $this->offset;
$last = $this->last;
$this->generate_scroll_controls ();
$this->debug ( "Offset is $offset." );
$this->debug ( "Last is $last." );
for ($i = $offset; $i < $last; $i++ )
{
// CHANGE (3)
// Change the call to db_fetch_array to one that
// returns an assoc array of col names and values of the row $i of your db result!
$row = db_fetch_array($this->result_id, $i, PGSQL_ASSOC );
$element_arguments = array_merge ( (array) $arguments, (array) $row );
$this->parse_rule_element ( $element, $element_arguments, '' );
unset ( $element_arguments );
}
// unset ( $type );
return ( TRUE );
}
// If we've gotten this far then $arguments has any data needed from DB.
// We are now free to go ahead and process the element.
if ( is_array ( $element ) )
{
foreach ( $element as $this_element )
{
$this->parse_rule_element ( $this_element, $arguments, $type );
}
return ( TRUE );
}
// If we have gotten this far, then $element has complete $arguments
// and is not an array. We can now include the element.
// To include an element we need to know which template it is in,
// so get the template name and then include the element.
// Some elements might specify a template.
// If they do, they are of form "template.element".
// If that is the case, then break the element apart into $template and $element.
// If that isn't the case, use the template set by the dominant rule.
if ( strstr ( $element, '.' ) )
{
list ( $template, $element ) = explode ( '.', $element );
}
else
{
$template = $this->dominant_rule['template'];
}
$fully_specified_element = $template . '_' . $element;
// If the function isn't defined, we need to include the template for it.
if ( ! function_exists ( $fully_specified_element ) )
{
// The rule format depends on functions in the rule template.
// So, we have to try to include the template.
// If we can't, we have a problem.
if ( ! $this->include_template ( $template ) )
{
return ( FALSE );
}
}
$this->include_element ( $fully_specified_element, $arguments );
return ( TRUE );
}
/*-----------------------------------------------------------------*/
function include_element ( $fully_specified_element, $arguments )
/*--------------------------------
6/13/00 4:05 PM by jestevez
Execute a template function ( a $fully_specified_element )
and send any returned values to HTML buffer.
Arguments includes any info from the database
and any explicit arguments specified by a rule.
All content comes through this function.
--------------------------------*/
{
if ( function_exists ( $fully_specified_element ) )
{
$this->debug ( "Including element $fully_specified_element.");
$this->html_buffer .= $fully_specified_element ( $arguments );
return ( TRUE );
}
$this->debug ( "Element $fully_specified_element does not exist." );
// Put in code to log error?
return ( FALSE );
}
/*-----------------------------------------------------------------*/
function apply_dominant_rule ( )
// Use the dominant rule to return HTML.
// 5/22/00 4:09 PM by psuda
{
$rule = (array) $this->dominant_rule;
$name = (string) $rule['name'];
$template = (string) $rule['template'];
$format = $rule['format'];
$arguments = $rule['arguments'];
$this->debug ( "Applying rule \"$name\"" );
// The rule format specifies which functions of the template to use.
// Take the format elements one at a time and parse them.
// This is where they have a chance to generate output, talk to database, etc...
foreach ( $format as $type => $element )
{
$this->parse_rule_element ( $element, $arguments, $type );
}
}
/*-----------------------------------------------------------------*/
function generate_scroll_controls ( )
// This function produces links "Next" and "Prev"
// which let the user "scroll" through a set of results.
// 6/7/00 12:04 PM by jestevez
{
$offset = $this->offset;
$num_rows = $this->num_rows;
$rule = $this->dominant_rule;
$scroll_args = $rule['scroll_args'];
$limit = $this->limit;
// If there is no limit, we don't need no stinkin' scroll controls.
if ( ! $limit )
{
return ( TRUE );
}
// If the total number of rows is less than the limit, we don't need no stinkin' controls.
if ( $num_rows < $limit )
{
return ( TRUE );
}
// Scroll arguments will be appended to the "next" and "prev" links.
// Passing the query is too dangerous, so we pass along variables that the page will use
// to reassemble the query. Collectively we call these the 'scroll args'.
// Not all pages will have scroll arguments, so only build them if there are some.
if ( count ( $scroll_args ) )
{
foreach ( $scroll_args as $name )
{
// We only grab values from global scope,
// because all url values get dumped to global scope anyway.
global $$name;
$value = $$name;
$buffer[] = $name . '=' . urlencode ( $value );
}
$scroll_args = implode ( '&', $buffer );
}
// Build "Next" link.
if ( $offset + $limit < $num_rows )
{
// If we don't get here, there are no more results to show, so no link.
$next_offset = $offset + $limit;
$next_link = '[' . html_a ( "?offset=$next_offset&$scroll_args", 'Next' ) . ']';
}
// Build "Prev" link.
if ( $offset - $limit > -1 )
{
// If we don't get here, there are no results in front of the current results, so no link.
$prev_offset = $offset - $limit;
$prev_link = '[' . html_a ( "?offset=$prev_offset&$scroll_args", 'Prev' ) . ']';
}
// Figure out the current rows being displayed.
$first = (string) $offset + 1;
$last = (string) $offset + $limit;
// Adjust $last to handle the "end" exception.
if ( $last > $num_rows )
{
$last = $num_rows;
}
// Handle the case where first = last.
if ( $first == $last )
{
$first_last_message = "<b>result $first</b>";
}
else
{
$first_last_message = "results <B>$first to $last</b>";
}
//Take the final message and add it to the result HTML buffer.
$message = "Showing $first_last_message [of $num_rows found]";
$this->html_buffer .= "<P>$prev_link $message $next_link<P>";
}
/*-----------------------------------------------------------------*/
function prepare_scroll_controls ()
// To loop through db results we need an offset and a last row.
// The last row is based on the limit.
// So, we get an offset and limit first. They are used to get the last row.
{
$this->get_offset ();
$this->get_limit ( );
$this->get_last ( );
}
/*-----------------------------------------------------------------*/
function get_offset ( )
// Get a safe value for an offset.
// If there is no offset, set it to 0.
{
$offset = $this->dominant_rule['offset'];
if ( $offset == '' )
{
$offset = 0;
}
$this->offset = $offset;
}
/*-----------------------------------------------------------------*/
function get_limit ( )
// Figure out a safe value for a limit.
// We don't want to go past num_rows.
{
$limit = $this->dominant_rule['limit'];
if ( $limit == '' )
{
$limit = $this->num_rows;
}
$this->limit = $limit;
}
/*-----------------------------------------------------------------*/
function get_last ( )
// Figure out the last row of results to display.
// Make sure the last row is not greater than the total number of rows.
{
$offset = $this->offset;
$limit = $this->limit;
$num_rows = $this->num_rows;
if ( $offset + $limit > $num_rows )
{
$last = $num_rows;
}
else
{
$last = $offset + $limit;
}
$this->last = $last;
}
/*-----------------------------------------------------------------*/
}
/*******************************************************************/
?>
|