Location: PHPKode > scripts > MadLibs > madlibs/class.madlibs.php
<?php

//
// class.madlibs.php
// version 1.0.0, 3rd September, 2003
//
// Description
//
// This class allows you to easily add a madlibs game to your website.
// You can load the madlib stories in via the file system or a database.
// If using the file system, the stories must contain the title on the
// first line and then story in the rest of the file.  If using a database
// then the schema is as follows:
//
//     CREATE TABLE madlibs
//     (
//       id      int(11)      NOT NULL auto_increment,
//       title   varchar(255) NOT NULL default '',
//       story   mediumtext   NOT NULL,
//       PRIMARY KEY (id)
//     )
//
// Stories are requied to have specific tags in them for replacement.  The
// format for the tags in the stories as '{TAGNAME}'.  See the function
// 'setDefaultTags' for a list of all default tags.  The class already comes
// loaded with a vast array of tags, though you can easily add to or remove 
// from that list at run time.
//
// Examples of use
//
//    Using the file system:
//
//        require 'class.madlibs.php';
//        $ml = new madlibs();
//        $ml->useFS('./stories', '.txt');
//        $ml->displayMadlib();
//
//    Using the file system:
//
//        require 'class.madlibs.php';
//        $ml = new madlibs();
//        $ml->useDB('username', 'password', 'madlibs', 'mydb', 'localhost');
//        $ml->displayMadlib();
//
// Examples of stories
//
//        A simple test title
//        Yesterday, {OPPOSITESEX} and I went to the beach.  We had a really 
//        {ADJECTIVE} time!  We {VERB-ED} with my {NOUN}.
//
// Feedback
//
// There is message board at the following address:
//
//    http://php.amnuts.com/forums/index.php
//
// Please use that to post up any comments, questions, bug reports, etc.  You
// can also use the board to show off your use of the script.
//
// Support
//
// If you like this script, or any of my others, then please take a moment
// to consider giving a donation.  This will encourage me to make updates and
// create new scripts which I would make available to you.  If you would like
// to donate anything, then there is a link from my website to PayPal.
//
// Andrew Collington, 2003
// hide@address.com, http://php.amnuts.com/
//


class madlibs
{
	var $useType;
	var $dbUser;
	var $dbPass;
	var $dbHost;
	var $dbName;
	var $dbTbl;
	var $dbID;
	var $fsPath;
	var $fsExt;
	var $inText;
	var $outText;
	var $tags;
	var $tagPositions;


	//
	// the constructor
	//
	function madlibs()
	{
		$this->useType = '';
		$this->tagPositions = array();
		$this->inText  = array();
		$this->outText = array();
		$this->setDefaultTags();
	}

	//
	// set the default replacement tags
	//
	function setDefaultTags()
	{
		$this->tags =
			array(
				'VERB'            => 'A verb',
				'VERB-ED'         => 'A verb ending in \'ed\'',
				'VERB-ING'        => 'A verb ending in \'ing\'',
				'VERB-S'          => 'A verb ending in \'s\'',
				'NOUN'            => 'A noun',
				'NOUN-PLURAL'     => 'A plural noun',
				'ADJECTIVE'       => 'An adjective',
				'ADVERB'          => 'An adverb',
				'EMOTION'         => 'An emotion',
				'NUMBER'          => 'A number',
				'PLACE'           => 'The name of a place',
				'ROOM'            => 'The name of a room',
				'FOOD'            => 'The name of some food',
				'MALE'            => 'A man\'s name',
				'FEMALE'          => 'A woman\'s name',
				'OPPOSITESEX'     => 'Name of a member of the opposite sex',
				'SAMESEX'         => 'Name of a member of the same sex',
				'ANIMAL'          => 'An animal',
				'ANIMAL-PLURAL'   => 'An animal (plural)',
				'FUNNY'           => 'Something funny',
				'BODYPART'        => 'A body part',
				'BODYPART-PLURAL' => 'A body part (plural)',
				'CELEBRITY'       => 'The name of a celebrity',
				'MADEUP'          => 'Just make up a word'
			);
	}


	//
	// allows you to add new tags to the list on the fly
	// $name is the tag name, eg, 'VERB'
	// $description is the text displayed to the user, eg, 'A verb'
	//
	function addTag($name, $description)
	{
		$this->tags[$name] = $description;
		return (array_key_exists($name, $this->tags)) ? TRUE : FALSE;
	}


	//
	// allows you to remove a tag from the tag list on the fly
	// $name is the tag name, eg, 'VERB'
	//
	function deleteTag($name)
	{
		if (array_key_exists($name, $this->tags))
		{
			$this->tags[$name] = NULL;
			unset($this->tags[$name]);
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}


	//
	// sets the class to use a MySQL database for the story storage area
	// $user is the username used to access to database
	// $pass is the password for the user account
	// $table is the table name that stores the story information
	// $database is the name of the database that contains the $table
	// $host is the host address of the database
	//
	function useDB($user='username', $pass='password', $table='madlibs', $database='demo', $host='localhost')
	{
		$this->useType = 'db';
		$this->dbUser  = $user;
		$this->dbPass  = $pass;
		$this->dbHost  = $host;
		$this->dbName  = $database;
		$this->dbTbl   = $table;
		$this->dbID    = NULL;

		$this->dbID = @mysql_connect($this->dbHost, $this->dbUser, $this->dbPass) or die("Unable to connect to mysql server: {$this->dbHost}");
		@mysql_select_db($this->dbName, $this->dbID) or die("Unable to select database: {$this->dbName}");
	}


	//
	// sets the class to use the file system for the story storage area
	// $path is the path to the story files
	// $extension is the extensions of the story files, including the period if one is used
	// the name of the file is arbitrary
	//
	function useFS($path = 'stories', $extension = '.txt')
	{
		$this->useType = 'fs';
		$this->fsPath  = $path;
		$this->fsExt   = $extension;
	}


	//
	// loads the story information
	//
	function getStory()
	{
		if ($this->useType == 'db')
		{
			$sql = "SELECT * FROM {$this->dbTbl} " .
					($_POST['id'] ? "WHERE id = {$_POST['id']}" : "ORDER BY RAND() LIMIT 1");
			$result = @mysql_query($sql, $this->dbID);
			if (mysql_num_rows($result))
			{
				$data = @mysql_fetch_object($result);
				$this->inText['id']    = $data->id;
				$this->inText['title'] = trim(stripslashes($data->title));
				$this->inText['story'] = trim(stripslashes($data->story));
			}
		}
		else if ($this->useType == 'fs')
		{
			if ($_POST['id'])
			{
				$file = $_POST['id'];
			}
			else
			{
				$filelist = array();
				if ($dir = @opendir($this->fsPath))
				{
					while (($file = readdir($dir)) !== FALSE)
					{
						if ($file == '.' || $file == '..') continue;
						if (preg_match("/{$this->fsExt}$/", $file))
						{
							$filelist[] = $file;
						}
					}
					closedir($dir);
					srand((float)microtime() * 10000000);
					$file = $filelist[array_rand($filelist)];
				}
			}

			$data = array();
			$data = @file($this->fsPath . '/' . $file);
			if (!empty($data))
			{
				$this->inText['id']    = $file;
				$this->inText['title'] = trim(@array_shift($data));
				$this->inText['story'] = trim(@join('', $data));
			}
		}
	}


	//
	// displays the madlib
	// if the form hasn't been displayed then it will show the form, else it
	// will show the story complete with madlib sustitutions
	//
	function displayMadlib()
	{
		$this->getStory();
		if (!isset($_POST['positions']))
		{
			if ($this->inText['story'])
			{
				$this->getTagPositions();
				$this->showForm();
			}
			else
			{
				echo 'No madlib story has been loaded.';
			}
		}
		else
		{
			if ($this->inText['story'])
			{
				$this->decompPositions($_POST['positions']);
				$this->replaceTags($_POST['word']);
				echo '<div class="madlibTitle">', $this->outText['title'], "</div>\n";
				echo '<div class="madlibStory">', nl2br($this->outText['story']), "</div>\n";
			}
			else
			{
				echo 'No madlib story has been loaded.';
			}
		}
	}


	//
	// displays the form the user's words
	//
	function showForm()
	{
		echo '<form name="madlibForm" action="', $_SERVER['PHP_SELF'], '" method="post">';
		echo '<input type="hidden" name="id" value="', urlencode($this->inText['id']), '">';
		echo '<input type="hidden" name="positions" value="', $this->compPositions(), '">';
		
		echo "<p>Please enter the following:</p>\n";
		echo '<table border="0" cellpadding="5" cellspacing="0" class="madlibTable">';
		foreach ($this->tagPositions as $id => $type)
		{
			echo '<tr><td>', $this->tags[$type], '</td><td><input type="textbox" name="word[', $id, ']"></td></tr>', "\n";
		}
		echo '<tr><td colspan="2" align="center"><input type="submit" value="see your madlib"></td></tr>';
		echo "\n</table>\n</form>\n";
	}


	//
	// determines where in the tags lie
	//
	function getTagPositions()
	{
		foreach ($this->tags as $key => $desc)
		{
			$positions = array();
			$tag = '{' . $key . '}';
			$positions = $this->multi_strpos($tag, $this->inText['story']);
			if (!empty($positions))
			{
				foreach ($positions as $place)
				{
					$this->tagPositions[$place] = $key;
				}
			}
		}
		ksort($this->tagPositions);
	}
	

	//
	// does the tag substitution for the finished story
	//
	function replaceTags($word_list)
	{
		$this->outText = $this->inText;
		if (!empty($this->tagPositions))
		{
			$tags = array_reverse($this->tagPositions, TRUE);
			foreach ($tags as $position => $type)
			{
				$tag = '{' . $type . '}';
				$this->outText['story'] = substr_replace($this->outText['story'], '<span class="madlibWord">' . $word_list[$position] . '</span>', $position, strlen($tag));
			}
		}
	}


	//
	// function to determine multiple occurrences of a word in a string
	// from a post by arduenn at hotpop dot com on the php.net comments
	//
	function multi_strpos($pattern, $sequence)
	{
		$n = -1;
		while (ereg($pattern, $sequence))
		{
			$n++;
			$fragment = split($pattern, $sequence);
			$trimsize = (strlen($fragment[0]))+1;
			$sequence = "*".substr($sequence, $trimsize);
			$position[$n] = (strlen($fragment[0]) + $position[($n-1)]);
		}
		return $position;
	}


	//
	// compresses the tag position array for use in a form
	//
	function compPositions()
	{
		return urlencode(base64_encode(serialize($this->tagPositions)));
	}


	//
	// decompresses the tag information array from a string
	// $positions is the compressed structure
	//
	function decompPositions($positions)
	{
		$this->tagPositions = unserialize(base64_decode(urldecode($positions)));
	}

}

?>
Return current item: MadLibs