< Back to Code Samples
<?php
/*************************************************************
* MadLibs - AJAX powered Mad libs processor
*
* PURPOSE: To do back-end processing of loading, changing, and switching out words.
*
* USAGE: Just read below. It's kind of a standalone thing.
*
* NOTES: This would probably be better written as a web service, but at the time I wrote
* it, I wasn't as familiar with SOAP/WSDL/XML-RPC.
* ************************************************************/
//
// Connect to the madlibs database. The instantiation of that class is done ABOVE the
// Document Root so that it's harder for anyone to see it from the outside world.
//
require_once('../../../classes/mldb.php'); // $mldb -- uses the MySQL DBO from above.
//
// Begin: Initialize the parts of speech first. These are pre-defined in a table. They are, if I
// remember correctly, paired with descriptive versions ("Adjective") and codified version ("ADJ").
$posQuery = "SELECT * FROM partsofspeech";
$mldb->query($posQuery);
while ($pos = $mldb->fetch_object())
{ $partsOfSpeech[$pos->pos_ID] = $pos->pos; }
//
// Some very simplistic mode processing. This first bit prevents URL hacking.
//
$mode = isset($_GET['mode']) ? substr($_GET['mode'],0,1) : 0;
switch($mode)
{
case 1: // Load a new madlib
$txt = getMadLib(); // See below
$txt = addTags($txt);// See below
echo substr($txt,1); // Send back AJAX data
break;
case 2: // Grab a word
//
// This is the fancy faux-serialization processing I did. There's some very modest
// SQL Injection prevention. This was before I wrote the Safe_Query function. pos_ID
// is the ordinal value of the word's location.
//
$pos = (isset($_GET['pos_ID'])) ? mysql_escape_string($_GET['pos_ID']) : "1";
echo getRandomWord($pos); // Send back AJAX data, See below for function definition.
break;
case 3: // Grab all words
//
// This is the "go-for-broke-just-fill-out-all-the-words" method.
//
$output = "";
//
// Iterate through key/value pairs. There are possibly some security concerns
// here that I didn't address. I would probably do this differently now if I re-wrote it.
//
foreach ($_GET as $objID => $posID)
{
if ($objID == "mode") continue;
$output .= $objID . ":" . getRandomWord($posID) . ",";
}
$output = substr($output,0,-1); // Strip off the trailing character.
echo $output; // Send back to AJAX request
break;
case 4: // Create new stuff -- Not yet implemented.
/* $type = (isset($_GET['type']) ? mysql_escape_string($_GET['type']) : "word");
createNew($type);
*/
break;
case 5: // Handle Queries -- I forget what I wrote this for, but it sounds like a bad idea.
break;
default:
// do nothing.
break;
}
/** **************************************************
* createNew() - This function prompts the user for creating a new word / madlib. As
* this feature is not yet implementd, it's kind of irrelevant right now. :)
*
* @param $type allows for modal choices between creating a new word or a new madlib.
* This could probably be done differently.
* @see HTML Form tags.
* **************************************************/
function createNew ($type)
{
global $mldb; // hacky.
global $partsOfSpeech; // ditto. This should be a parameter.
switch ($type)
{
case "word":
echo "<fieldset><legend>Word Entry</legend>\r
<form method=\"post\" action=\"madlibs.php?mode=5&type=word\">\r
<select name=\"pos\" >\r";
foreach ($partsOfSpeech as $pos_ID => $pos)
{
echo "<option value=\"$pos_ID\">$pos</option>\r";
}
echo "</select>\r
<label>Enter your word*\r
<input type=\"text\" class=\"inputText\" name=\"word\" id=\"wordEntry\" />\r
</label>\r
<input type=\"submit\" name=\"submit\" />
</form></fieldset>\r";
break;
case "madlib":
break;
default:
break;
}
}
/** *************************************************************************
* getMadLib() - Grab a piping fresh madlib from the database. It's a randomized
* SELECT statement. Title is validated.
* @return The output result.
* **************************************************************************/
function getMadLib()
{
global $mldb; // Very hacky.
$mlQuery = "SELECT madlib,title FROM madlib ORDER BY RAND() LIMIT 1";
$mldb->query($mlQuery);
$result = $mldb->fetch_object();
$title = ($result->title != "") ? $result->title : "<em>Untitled</em>";
$output = "<div id=\"title\">$title</div>";
$output .= $result->madlib;
return $output;
}
/** *************************************************************************
* addTags() - Makes all parts-of-speech linkable. This would be EASILY done with
* a regex, if I was re-doing it now. All parts of speech appear as
* bracketed references. So something like [NOUN] or [ADJECTIVE] shoes.
*
* @param $txt the raw text pulled from the database.
* @return The output result.
* **************************************************************************/
function addTags($txt)
{
global $mldb; // *sigh*
global $partsOfSpeech;
// To prevent problems if there's a word at the start of the text. I forget
// why this was an issue. It may not even be necessary.
$txt = "." . $txt;
// Foreach parts of speech : $pos_ID is the "ADJ" version, $pos is the "Adjective" version.
// Essentially what this does is iterate through each parts of speech, explode the serialized
// text, manipulate the components, and then concatenate it back together. It re-explodes it
// for each part of speech -- but each time it explodes the text, the text separates into different
// segments.
// i.e.: .[NOUN] was a very [ADJECTIVE] [NOUN]. He [VERB] in a [ADJECTIVE] shoe.
// For "Noun" this would split into:
// [0] => .
// [1] => was a very [ADJECTIVE]
// [2] => . He [VERB] in a [ADJECTIVE] shoe.
//
// But for "Adjective" it would split to:
// [0] => .[NOUN] was a very
// [1] => [NOUN]. He [VERB] in a
// [2] => shoe.
//
// Interleaving the correct links with this is very easy when it's broken up like this.
//
foreach ($partsOfSpeech as $pos_ID => $pos)
{
// What we're looking for.
$needle = "[" . $pos . "]";
$count = "0";
$output = "";
// My hacky de-serialization.
$parseArray = explode($needle, $txt);
foreach ($parseArray as $index => $segment)
{
if ($count > 0)
{
//
// Specifies the ordinal of this part of speech. NOUN_1 or PART_OF_BODY_3
//
$thisID = str_replace(" ","_",$pos) . "_" . $count;
//
// This is the actual link structure. It specifies mode 2, sets the Parts of Speech ID of the
// link to the current POS ID, etc.
//
$output .= "<a class=\"word\" rel=\"$pos_ID\" id=\"$thisID\" href=\"#nogo\" onclick=\"makerequest('madlibs.php?mode=2&pos_ID=" . $pos_ID . "','$thisID'); return false;\" title=\"" . $pos . "\">" . strtoupper($pos) . "</a>";
}
$count++; // Increment the ordinal.
$output .= $segment; // Concatenate the result so far.
}
$txt = $output; // Reset the string.
}
return $txt;
}
/** ***************************************************
* getRandomWord - returns a random word of a particular part of speech.
* @param $pos_ID - the Part of Speech ID for the word. (i.e. [ADJ])
* @return The word result.
* ****************************************************/
function getRandomWord($pos_ID)
{
global $mldb;
$wordQuery = "SELECT word FROM words WHERE pos_ID='" . mysql_real_escape_string($pos_ID) . "' ORDER BY RAND() LIMIT 1";
$mldb->query($wordQuery);
$word = $mldb->fetch_object();
return $word->word;
}
?>