PX : code

Amnuts MadLibs by Andrew Collington
Rating: 5.00
Download this code


<?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
// php@amnuts.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->tagPositionsTRUE);
            foreach (
$tags as $position => $type)
            {
                
$tag '{' $type '}';
                
$this->outText['story'] = substr_replace($this->outText['story'], '<span class="madlibWord">' $word_list[$position] . '</span>'$positionstrlen($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)));
    }

}

?>

Comments or questions?
PX is running PHP 5.2.17
Thanks to Miranda Productions for hosting and bandwidth.
Use of any code from PX is at your own risk.