Login   Register  
PHP Classes
elePHPant
Icontem

File: result.inc

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Jesse Estevez  >  Result Class - Rule-based system for processing data tied to a DB result id.  >  result.inc  >  Download  
File: result.inc
Role: ???
Content type: text/plain
Description: Source Code ( lots of comments )
Class: Result Class - Rule-based system for processing data tied to a DB result id.
Author: By
Last change:
Date: 2000-06-15 22:50
Size: 14,772 bytes
 

Contents

Class file image Download
<?


/*******************************************************************/


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;
	}


/*-----------------------------------------------------------------*/



}


/*******************************************************************/


?>