<?php
/************************************************************************
* *
* Copyright (C) 2003 Stuart Reeves *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* The GNU General Public License is available from: *
* http://www.gnu.org/copyleft/gpl.html *
* *
************************************************************************/
/* Stuart's lns (lame node system) */
/* NodeInterface provides everything to search for, and display, nodes. Once created, the object
* will display a given node, or a selection of nodes, or allow a basic regular expression assisted
* search of the node database.
*
* I think that it really needs a clean-up, especially printNode, which is awful. */
class NodeInterface
{
// Database connection information
var $host,
$user,
$passwd,
$db,
$link, // The link to the database itself
$table;
// Various attributes of the node
var $nodename,
$text,
$link,
$protected,
$metatype,
$rawtype,
$external; // External link location (if any)
// Other data (e.g. session information)
var $username,
$superuser,
$numRows, // The number of "hits" for the requested node
$relatedNodes, // Create array for the related node links. The array is
// simply a list of strings.
$firstEditor; // First author to create this node
// Display options for nodes
var $showExtLinks,
$showDistinct,
$showByTS,
$showHidden,
$showNodenameHeader,
$showRelatedNodes,
$showHomeNodes,
$truncateNodes;
// Constructor
function NodeInterface($host, $user, $passwd, $db, $table){
// Database stuff
$this->host = $host;
$this->user = $user;
$this->passwd = $passwd;
$this->db = $db;
$this->dblink = null;
$this->table = $table;
// Node stuff
$this->protected = false;
$this->metatype = METATYPE_DEFAULT;
$this->rawtype = RAWTYPE_DEFAULT;
$this->external = "";
$this->superuser = false;
$this->relatedNodes = array();
// Set default display options
$this->showExtLinks = false;
$this->showDistinct = false;
$this->showByTS = false;
$this->showHidden = false;
$this->showNodenameHeader = false;
$this->showRelatedNodes = false;
$this->showHomeNodes = false;
$this->truncateNodes = false;
}
function setShowDistinct($flag) {
$this->showDistinct = $flag;
}
function setShowByTS($flag) {
$this->showByTS = $flag;
}
function setShowExtLinks($flag) {
$this->showExtLinks = $flag;
}
function setShowHidden($flag) {
$this->showHidden = $flag;
}
function setShowNodenameHeader($flag) {
$this->showNodenameHeader = $flag;
}
function setShowRelatedNodes($flag) {
$this->showRelatedNodes = $flag;
}
function setShowHomeNodes($flag) {
$this->showHomeNodes = $flag;
}
function setTruncateNodes($flag) {
$this->truncateNodes = $flag;
}
function setUsername($username) {
$this->username = $username;
}
function setSuperuser($flag) {
$this->superuser = $flag;
}
function isProtected() {
return $this->protected;
}
function setMetatype($metatype) {
$this->metatype = $metatype;
}
function getMetatype() {
return $this->metatype;
}
function getRawtype() {
return $this->rawtype;
}
function getLink() {
return $this->link;
}
/* Returns: $this->nodename - The case-correct nodename */
function getNodename() {
return $this->nodename;
}
function getFirstEditor() {
return $this->firstEditor;
}
/* Finds out the nodename of a user's (unique) home node.
*
* Returns: $code (string) - The nodename of this user's home node
* 0 (integer) - No home node is found or an access error has occurred
* -1 (integer) - Database error (i.e. > 1 METATYPE_HOME node for a
* user) */
function getHomeNode() {
if (isset($this->username)) {
$query = "SELECT nodename FROM $this->table WHERE metatype = '" . METATYPE_HOME . "'
AND username = '$this->username'";
$this->dblink = mysql_connect($this->host, $this->user, $this->passwd);
$dbselect = mysql_select_db($this->db, $this->dblink);
$dbquery = mysql_query($query, $this->dblink);
$numRows = mysql_num_rows($dbquery);
$code = 0;
if ($numRows == 1) {
$nodedata = mysql_fetch_object($dbquery);
$code = $nodedata->nodename;
} else if ($numRows > 1)
$code = -1;
mysql_close($this->dblink);
return $code;
} else
return 0;
}
/* Creates the HTML body for any nodes that match the required nodename, and sorts them by
* timestamp (i.e. latest additions will appear at the top of the node).
*
* Args: $reqNode (string) - The requested nodename to display
* $HTMLFactory (object) - The HTMLFactory object reference
*
* Returns: $html (string) - The node as HTML
* false (boolean) - If no node is found */
function getNode($reqNode, &$HTMLFactory) {
$query = "SELECT * FROM $this->table WHERE nodename = \"$reqNode\" ORDER BY ts DESC";
$this->dblink = mysql_connect($this->host, $this->user, $this->passwd);
$dbselect = mysql_select_db($this->db, $this->dblink);
$dbquery = mysql_query($query, $this->dblink);
$this->numRows = mysql_num_rows($dbquery);
$html = $this->printNode($dbquery, $reqNode, &$HTMLFactory);
mysql_close($this->dblink);
return $html;
}
/* Displays a list of formatted nodenames, optionally with external link nodes displayed.
*
* Args: $age (string) - Maximum age of nodes to be displayed (in days)
* $offset (integer) - Limit number of output nodes by this
* $username (string) - Restrict listing to nodes authored by this user
* $metatype (string) - Restrict listing to nodes of this meta-type
*
* Returns: $html (string) - The list of nodenames as HTML */
function getNodeList($age, $offset, $username, $metatype) {
$html = "";
$query = "";
// Create default query
$opts = array(SELECT => "*",
WHERE => "",
ORDER_BY => "ORDER BY nodename ASC",
LIMIT => "");
// Populate the array with the right values for the current options
if ($this->showExtLinks) {
$opts[WHERE] = "WHERE link != '' AND hidden != 't'";
$this->showByTS = true;
}
if ($this->showDistinct) {
$opts[SELECT] = "DISTINCT nodename";
if ($opts[WHERE] == "")
$opts[WHERE] = "WHERE hidden != 't'";
else
$opts[WHERE] = $opts[WHERE] . " AND hidden != 't'";
$opts[ORDER_BY] = "ORDER BY nodename ASC";
}
if ($age > 0) {
if ($opts[WHERE] == "")
$opts[WHERE] = "WHERE TO_DAYS(NOW()) - TO_DAYS(ts) <= $age";
else
$opts[WHERE] = $opts[WHERE] . " AND TO_DAYS(NOW()) - TO_DAYS(ts) <= $age";
$this->showByTS = true;
}
if ($offset > 0) {
if ($this->showDistinct)
$opts[WHERE] = $opts[WHERE] . " AND link = ''";
else if (!$this->showExtLinks)
$opts[WHERE] = "WHERE link = '' AND hidden != 't'";
$this->showByTS = true;
$opts[LIMIT] = "LIMIT $offset";
}
if (isset($username)) {
if ($opts[WHERE] == "")
$opts[WHERE] = "WHERE username = '$username'";
else
$opts[WHERE] = $opts[WHERE] . " AND username = '$username'";
}
if (isset($metatype)) {
if ($opts[WHERE] == "")
$opts[WHERE] = "WHERE metatype = '$metatype'";
else
$opts[WHERE] = $opts[WHERE] . " AND metatype = '$metatype'";
}
if (!$this->showHomeNodes) {
if ($opts[WHERE] != "")
$opts[WHERE] = $opts[WHERE] . " AND metatype != '" . METATYPE_HOME . "'";
else
$opts[WHERE] = "metatype != '" . METATYPE_HOME . "'";
}
// Connect to the database
$this->dblink = mysql_connect($this->host, $this->user, $this->passwd);
$dbselect = mysql_select_db($this->db, $this->dblink);
$nodedataQuery = null;
if ($this->showByTS) {
$opts[ORDER_BY] = "ORDER BY ts DESC";
// If the ORDER BY clause is set for timestamp and the list is for distinct
// nodes only, then we must create a temporary table for technical reasons.
if ($this->showDistinct) {
mysql_query("CREATE TEMPORARY TABLE nodelist (nodename VARCHAR(200), ts TIMESTAMP)
TYPE = HEAP", $this->dblink);
mysql_query("INSERT INTO nodelist SELECT nodename, ts FROM $this->table " .
$opts[WHERE] . " " . $opts[ORDER_BY],
$this->dblink);
// Perform the actual DISTINCT query and delete the temporary table
$nodedataQuery = mysql_query("SELECT DISTINCT nodename FROM nodelist " .
$opts[LIMIT],
$this->dblink);
mysql_query("DROP TABLE nodelist");
}
}
// A null value for $nodedataQuery implies that the special stuff for DISTINCT listings
// ordered by timestamp was not needed
if ($nodedataQuery == null) {
$query = "SELECT " . $opts[SELECT] . " FROM $this->table " . $opts[WHERE] .
" " . $opts[ORDER_BY] . " " . $opts[LIMIT];
$nodedataQuery = mysql_query($query, $this->dblink);
}
// NOTE: bit messy here... can't think of any way to clean it up
while ($nodedata = mysql_fetch_object($nodedataQuery)) {
/* If we are displaying distinct nodes, the latest instance of this node's data must
* be obtained.
*
* Note: The nodedata data object is overwitten. */
if ($this->showDistinct) {
//$nodename = htmlentities($nodedata->nodename, ENT_QUOTES);
$distQuery = "SELECT * FROM $this->table WHERE nodename='$nodedata->nodename'
ORDER BY ts DESC LIMIT 1";
$currNodedataQuery = mysql_query($distQuery, $this->dblink);
$nodedata = mysql_fetch_object($currNodedataQuery);
}
// Skip over protected nodes if necessary
if ($this->showHidden || $nodedata->hidden != 't') {
$nodename = $nodedata->nodename;
$linked = false;
// Cater for picture nodes and external links
if ($nodedata->link != "") {
// Add indicative text if this is an external link or a picture
if ($nodedata->rawtype == RAWTYPE_IMAGE) {
$html .= "<span class=\"light\">picture: </span> ";
$linked = true;
} else if ($nodedata->rawtype == RAWTYPE_EXT_LINK && $this->showExtLinks) {
$html .= "<span class=\"light\">external link: </span> ";
$linked = true;
}
}
if ($nodedata->link == "" || $linked) {
$echoTrailingText = false;
if ($showHomeNodes || $nodedata->metatype != METATYPE_HOME) {
// Display the right author and creation/addition indicator
$html .= "<b><a title=\"$nodename\" href=\"?node=$nodename\">" .
"$nodename</a></b> <br />\n";
$html .= " " .
" <em>added by ";
if ($nodedata->username == "") {
if ($nodedata->contact != "")
$html .= "<a href=\"$nodedata->contact\">" .
"$nodedata->author</a>";
else
$html .= $nodedata->author;
} else
$html .= "<a title=\"Profile for user $nodedata->username\" " .
"href=\"?node=" . FINGER_NODE . "&_username=" .
"$nodedata->username\">$nodedata->username</a>";
if ($nodedata->username == "") {
$html .= " (<a href=\"?node=" . HELP_NODE .
"#anonymous user\">Anonymous user</a>)";
}
$echoTrailingText = true;
} else if ($metatype == METATYPE_HOME && $nodedata->username != "") {
$html .= "<a title=\"$nodedata->username's home node\" " .
"href=\"?node=$nodedata->nodename\"><strong>$nodedata->nodename" .
"</strong></a> (<a title=\"Profile for user $nodedata->username\"".
"href=\"?node=" . FINGER_NODE .
"&_username=$nodedata->username\">" .
"$nodedata->username</a>'s home node) <em>";
$echoTrailingText = true;
}
if ($echoTrailingText) {
$html .= " edited on " . Util::fmtTimestamp($nodedata->ts) ."</em>";
if (isset($this->username) && $this->username == $nodedata->username) {
$html .= " [<a href=\"?node=" . SUBMIT_NODE . "&_nodename=" .
"$nodedata->nodename&ts=$nodedata->ts\">edit this " .
"$nodedata->metatype node</a>]";
}
$html .= "<br />\n";
}
}
}
}
mysql_close($this->dblink);
return $html;
}
/* Checks for external links to indicate whether a redirect is necessary or allowed.
*
* Returns: $this->external (string) - the physical link of the node
* (e.g. "http://www.foo.net") */
function isExternal(){
// Make sure that we only flag a redirect if this node is unique
if ($this->external != "" && $this->numRows == 1) {
return $this->external;
} else
return false;
}
/* Searches for strings inside nodes using the MySQL FULLTEXT search.
*
* Args: $searchStr (string) - The search query string
* $HTMLFactory (object) - The HTMLFactory object that creates HTML widgets
*
* Returns: $html (string) - The nodes returned in the search
* false (boolean) - Search returned no results or search string empty */
function search($searchStr, &$HTMLFactory) {
if ($searchStr != "")
// Get rid of any unwanted characters in search string and tokenise
$searchStr = trim(preg_replace(SEARCH_REPLACE, " ", stripslashes($searchStr)));
else
return false;
$query = "SELECT *,MATCH(nodename, text) AGAINST(\"$searchStr\") AS score from " .
NODE_TABLE . " WHERE MATCH(nodename, text) AGAINST(\"$searchStr\") ORDER BY " .
"score DESC";
// Connect to database
$this->dblink = mysql_connect($this->host, $this->user, $this->passwd);
$dbselect = mysql_select_db($this->db, $this->dblink);
$dbquery = mysql_query($query, $this->dblink);
$this->numRows = mysql_num_rows($dbquery);
$result = "";
// Create the results if they exist
if ($this->numRows != 0) {
$html = "<a href=\"?node=" . SEARCH_NODE . "\">search</a> results for " .
"\"<em>$searchStr</em>\":" .
"<br /><br /><table align=\"right\" border=\"0\" width=\"90%\">" .
"<tr><td>" . $this->printNode($dbquery, "", &$HTMLFactory) .
"</td></tr></table>";
$result = $html;
} else
$result = false;
mysql_close($this->dblink);
return $result;
}
/* DEPRECATED
* Searches for strings inside nodes and displays node bodies that satisfy the search criteria.
*
* Args: $str (string) - the search query string
* $mode (string) - special flag to switch between AND and OR word
* searches
* $range (string) - special flag to specify the sections of the node to
* search in
*
* Returns: $html (string) - the nodes returned in the search
* false (boolean) - search returned no results or search string empty */
function locate($str, $mode, $range, $htmlfactory){
if ($str != "") {
// Get rid of any unwanted characters in search string and tokenise
$clean_str = trim(preg_replace(SEARCH_REPLACE, " ", stripslashes($str)));
$tokens = strtok($clean_str, " ");
$toklist = ""; // Initialise the tokenlist string
} else
return false;
// Create the token list for the regular expression search
switch ($mode) {
case SEARCH_LOGICAL_OR:
// Create the token list string as this: "token1|token2|token3..."
// THIS NEEDS TO BE FIXED
$toklist = $tokens;
while ($tokens) {
$tokens = strtok(" ");
if ($tokens != "")
$toklist .= "[[:space:]]|[[:space:]]$tokens.";
}
break;
case SEARCH_LOGICAL_AND:
// Creates a string where the token can either be at the start of the string, at
// the end or somewhere in the middle with whitespace
while ($tokens) {
if ($tokens != "")
$toklist .= $toklist .= "(^($tokens.+)+|((.+$tokens)$)|.+($tokens).+)";
$tokens = strtok(" ");
}
break;
}
// Check that our list of tokens actually has values in it before searching
if ($toklist != "") {
// Create the correct query string based on the range type
switch ($range) {
case SEARCH_NODENAME:
$option = "nodename REGEXP '$toklist' ORDER BY nodename";
break;
case SEARCH_TEXT:
$option = "text REGEXP '$toklist' ORDER BY nodename";
break;
case SEARCH_ALL:
$option = "nodename REGEXP '$toklist' OR text REGEXP '$toklist' ORDER BY
nodename";
break;
}
$q_str = "SELECT * FROM $this->table WHERE $option";
// Connect to database
$this->dblink = mysql_connect($this->host, $this->user, $this->passwd);
$dbselect = mysql_select_db($this->db, $this->dblink);
$dbquery = mysql_query($q_str, $this->dblink);
// Create the results if they exist
if (mysql_num_rows($dbquery) != 0) {
$html = "<a href=\"?node=".SEARCH_NODE."\">search</a> results for
\"<i>$clean_str</i>\":
<br /><br /><table align=\"right\" border=\"0\" width=\"90%\">
<tr><td>" . $this->printNode($dbquery, "", $htmlfactory) .
"</td></tr></table>";
return $html;
} else
return false;
mysql_close($this->dblink);
} else
return false;
}
/*function myLoadGIF ($imgname) {
$im = @ImageCreateFromGIF ($imgname);
if (!$im) {
$im = ImageCreate (150, 30);
$bgc = ImageColorAllocate ($im, 255, 255, 255);
$tc = ImageColorAllocate ($im, 0, 0, 0);
ImageFilledRectangle ($im, 0, 0, 150, 30, $bgc);
ImageString ($im, 1, 5, 5, "Error loading $imgname", $tc);
}
return $im;
}*/
/* Private function to format node body/date etc. output. The format of the node is:
* 1) Divider bar or line breaks
* 2) Nodename header (optional)
* 3) Node body (external link, picture or text)
* 4) Contact information with date and "add to this node" link
*
* Args: $dbquery (object) - SQL query object to display nodes from
* $reqNode (string) - The requested node of the caller function
* $HTMLFactory (object) - Reference to the currently used HTMLFactory
*
* Returns: false (boolean) - Indicates that the node was not found
* $html (string) - The HTML of the node body */
function printNode($dbquery, $reqNode, &$HTMLFactory) {
$numRows = $this->numRows;
$html = "";
$reqNode = stripslashes($reqNode);
if ($numRows == 0) {
$this->nodename = $reqNode;
return false;
}
/* Record last node name so that we can distinguish between display queries that return
* node bodies of exactly one nodename (i.e. normal node displays), and those that
* return differing nodenames (i.e. searches). */
$lastNodename = $reqNode;
$count = 0;
$lastMetatype = ""; // Records the last fetched node's metatype
$isMixedType = false; // Flagged if this node is made up of > 1 metatype
$isOwner = false; // Flagged if node is owned by the logged in user
$isProtected = false; // A node is considered protected if at least one writeup is
// protected.
$nodedata = null;
$authorHTML = ""; // Stores the last author line so that we can set it as
// $lastEditor
// Go through each row (i.e. writeup) in this node
while ($nodedata = mysql_fetch_object($dbquery)) {
if ($count == 0)
$firstRawtype = $nodedata->rawtype;
// Get the ``real'' nodename (i.e. case-correct nodename)
$this->nodename = $nodedata->nodename;
// Don't display hidden nodes if specified
if ($this->showHidden || $nodedata->hidden != 't') {
if (!$isMixedType) {
// Initialise the last metatype record
if ($lastMetatype == "")
$lastMetatype = $nodedata->metatype;
else if ($lastMetatype != $nodedata->metatype)
$isMixedType = true;
$lastMetatype = $nodedata->metatype;
}
$nodeHTML = ""; // The HTML for this single node
// Print a divider bar if needed
if (!$this->showNodenameHeader &&
$count > 0 && $count < $numRows &&
!strcasecmp($lastNodename, $nodedata->nodename)) {
$nodeHTML .= "<hr width=\"75%\">\n";
} else if ($count > 0) {
$nodeHTML .= "<br /><br />\n";
}
// Place "#" name references for each entry
$nodeHTML .= "\n<!-- BEGIN node text body -->\n" .
"<a name=\"$count\"> </a><br />\n";
++$count;
/* Create the HTML output for nodes, external links and pictures. On the basis
* of the link field data, we decide whether to treat this node as (in
* prioritised order):
* link field not empty --> picture
* or --> external link
* link field empty --> normal node */
if ($nodedata->link != "") {
$physical = $nodedata->link;
// Create HTML for picture nodes or external links
if ($nodedata->rawtype == RAWTYPE_IMAGE) {
// Output the image
/*if (mkdir(IMAGE_THUMB_PATH, 0700))
chmod(IMAGE_THUMB_PATH, 0700);
$img = $this->myLoadGIF($physical);
if($img){
// Thumbnail image space
$w = ImageSX($img);
$h = ImageSY($img);
$new_w = $w / IMAGE_SCALE_FACTOR_X;
$new_h = $h / IMAGE_SCALE_FACTOR_Y;
$new_img = ImageCreate($new_w, $new_h);
ImageCopyResized($new_img, $img, 0, 0, 0, 0,
$new_w, $new_h, $w, $h);
//ImageJPG($new_img);
$fp = fopen(IMAGE_THUMB_PATH . "/$picname.gif", "w+");
ImageGIF($new_img, IMAGE_THUMB_PATH . "/$picname.gif");
fclose($fp);
} else {
$html .= "Error: Unable to create image";
}*/
$picname = substr(strrchr($physical, "/"), 1);
$nodeHTML .= "picture display (\"<i>$picname</i>\"):<br /><br />".
"<div align=\"center\"><a href=\"$physical\">".
"<img src=\"$physical\"></a></div><br />";
} else if ($nodedata->rawtype == RAWTYPE_EXT_LINK) {
$nodeHTML .= "<span class=\"warning\">This node is an external link ".
"to <a href=\"$physical\">$physical</a></span>";
$this->external = $physical;
}
}
if ($nodedata->rawtype != RAWTYPE_EXT_LINK) {
if ($nodedata->text != "") {
/* Create node textbody with optional nodename header. Node bodies that are
* long will be truncated if the nodename header is used to display the node
* textbody. */
if ($this->showNodenameHeader && $this->truncateNodes &&
(strlen($nodedata->text) > SEARCH_TRUNCATE_CHARS_AFTER)) {
$nodeHTML .= $this->truncateText($nodedata->text) .
"<dl><dt> </dt><dd>" .
"<i><span class=\"warning\">This node entry has been " .
"truncated (<b>" .
"<a href=\"?node=$nodedata->nodename\">show all</a></b>)" .
"</span></i></dd></dl>";
} else if ($this->showRelatedNodes) {
// Search for links to nodes that exist
$nodeHTML .= $nodedata->text;
$this->findRelatedNodes($nodedata->text);
} else
$nodeHTML .= $nodedata->text;
} else
$nodeHTML .= "<span class=\"warning\">This node has been deleted</span>";
} // End if
// Add contact and timestamp information
$nodeHTML .= "<br /><br /><small>[$nodedata->metatype node added by ";
$authorHTML = "";
if ($nodedata->contact != "") {
$title = "";
if (isset($nodedata->username))
$title = "title=\"Get more information about this user\"";
$authorHTML = "<a $title href=\"$nodedata->contact\">$nodedata->author</a>";
} else {
if ($nodedata->author != "")
$authorHTML .= $nodedata->author;
else
$authorHTML .= "<span class=\"warning\">deleted</span>";
}
if (!isset($nodedata->username) && $nodedata->username == "") {
$authorHTML .= " (<a title=\"Help on anonymous users\" href=\"?node=" .
HELP_NODE . "#anonymoususers\">Anonymous user</a>)";
}
$authorHTML .= " on " . Util::fmtTimestamp($nodedata->ts);
$nodeHTML .= "$authorHTML]</small>";
if ($this->superuser ||
(isset($this->username) && $nodedata->username == $this->username)) {
$nodeHTML .= " [<a href=\"?node=" . SUBMIT_NODE . "&_nodename=" .
"$nodedata->nodename&ts=$nodedata->ts\">edit this " .
"$nodedata->metatype node</a>]";
// This will override the value of $isProtected for logged in users (i.e. will
// display [add to this node] if the protection is ``owned'' by this user).
if ($nodedata->protected == 't')
$isOwner = true;
}
if ($nodedata->protected == 't')
$isProtected = true;
// Optional printing of nodename box (i.e. packages up the HTML inside a nice
// node ``miniview'' box).
if ($this->showNodenameHeader) {
$nodeHTML = $HTMLFactory->createNodeMiniView($nodeHTML,
$nodedata->nodename,
round($nodedata->score, 2),
$nodedata->metatype);
}
$nodeHTML .= "<br/><br/>\n<!-- END node text body -->\n";
// Append the HTML output for a single node to the currently generated output
$html .= $nodeHTML;
$lastNodename = $nodedata->nodename;
} else // Alter the recorded number of rows so hidden nodes aren't counted
--$numRows;
} // End while
// Record who was the originator of this node
$this->firstEditor = $authorHTML;
// Record data about the meta-type and raw type
$dispMetatype = "";
$metaType = "";
if ($isMixedType) {
$metaType = METATYPE_DEFAULT;
$dispMetatype = "mixed";
} else {
$metaType = $lastMetatype;
$dispMetatype = $lastMetatype;
}
$this->metatype = $dispMetatype;
$this->rawtype = $firstRawtype;
/* Display an "add to this node" link on the final entry for each particular
* node, as long as this node is node protected, or owned by the logged in
* user. */
if ($this->external == "" && !$this->showNodenameHeader &&
$this->metatype != METATYPE_HOME && ($isOwner || !$isProtected)) {
$html .= "<div align=\"right\">[<a href=\"?node=" . SUBMIT_NODE .
"&_nodename=$reqNode&_metatype=$metaType\">add to this " .
"$dispMetatype node</a>]</div>";
}
if ($this->showRelatedNodes && sizeof($this->relatedNodes) > 0) {
// Get rid of duplicate entries and strip out all empty values
$this->relatedNodes = array_values(array_unique($this->relatedNodes));
$HTMLFactory->setRelatedNodes($this->relatedNodes);
}
return $html;
} // End method printNode()
/* Private method to update the array $relatedNodes. It assumes a database link has
* already been established.
*
* Args: $text (string) - The text in which to search for node links */
function findRelatedNodes($text) {
$currRelatedNodes = "";
if (preg_match_all("/<a[\=\"\?".ALLOWED_NODENAME_CHARS."]*node\=([" .
ALLOWED_NODENAME_CHARS .
"]*)\"*>/i",
$text, $currRelatedNodes)) {
$rnArrayPos = sizeof($this->relatedNodes); // Get current array length
foreach ($currRelatedNodes[1] as $currRelatedNode) {
$query = "SELECT DISTINCT nodename FROM $this->table " .
"WHERE nodename='" .
htmlentities($currRelatedNode, ENT_QUOTES) . "'";
$relatedNodeQuery = mysql_query($query, $this->dblink);
if (mysql_num_rows($relatedNodeQuery) != 0) {
$row = mysql_fetch_object($relatedNodeQuery);
$this->relatedNodes[$rnArrayPos] = $row->nodename;
++$rnArrayPos;
}
}
}
}
/* Private method to truncate node texts if they are too lengthy.
*
* Args: $text (string) - The text that needs truncating
*
* Returns: $truncText (string) - The HTML-safe, truncated text */
function truncateText($text) {
// Truncate the body of the text
$truncText = substr($text, 0, SEARCH_TRUNCATE_CHARS_AFTER);
// Search for unbalanced angle brackets and close if necessary
$angbr1 = strrchr($truncText, "<");
$angbr2 = strrchr($truncText, ">");
if ((!$angbr2 && $angbr1) || ($angbr1 > $angbr2))
$truncText .= ">";
// Add "</tag>" for each opened tag found
// TODO: alter to close tags left open, not all tags
if (preg_match_all("/<(\w+)[\s\=\?\w\"]*>/i", $truncText, $matches)) {
foreach ($matches[1] as $match)
$truncText .= "</$match>";
}
return $truncText;
}
/* Retrieves all the relevant data when editing a node.
*
* Args: $timestamp - The unique timestamp of the node to edit
*
* Returns: true (boolean) - The data was retrieved
* false (boolean) - The username and/or timestamp were not set */
function editNode($timestamp) {
if (isset($timestamp) && isset($this->username)) {
$userClause = "";
if (!$this->superuser)
$userClause = "username = '$this->username' AND ";
$query = "SELECT * FROM $this->table WHERE $userClause ts = '$timestamp'";
$this->dblink = mysql_connect($this->host, $this->user, $this->passwd);
$dbselect = mysql_select_db($this->db, $this->dblink);
$dbquery = mysql_query($query, $this->dblink);
$nodedata = mysql_fetch_object($dbquery);
// Set the protected flag
if ($nodedata->protected == 't')
$this->protected = true;
$this->text = $nodedata->text;
$this->link = $nodedata->link;
$this->metatype = $nodedata->metatype;
mysql_close($this->dblink);
} else
return false;
}
/* Reverses the square bracket parsing done for node submits.
*
* Returns: $unparsedText - The unparsed text (i.e. with [] in) */
function getUnparsedText() {
// Perform reverse method to UserInput::getParsedText()
$unparsedText = $this->text;
$unparsedText = str_replace("\n", "", $unparsedText);
$unparsedText = preg_replace("/<br\s*\/>/", "\n", $unparsedText);
$unparsedText = preg_replace_callback(NODE_UNPARSE_REGEXP,
array($this, 'unparseHTMLCallback'),
$unparsedText);
return $unparsedText;
}
/* Private callback function to convert the two types of links into their respective
* lns-style node links:
*
* <a href="?node=link">text</a> --> [link|text]
* <a href="?node=text">text</a> --> [text]
*
* Args: $link (string) - The matched HTML link text
*
* Returns: $nodeLink (string) - The lns-style version of the link */
function unparseHTMLCallback($link) {
$nodeLink = "";
if ($link[1] == $link[2])
$nodeLink = "[" . $link[1] . "]";
else
$nodeLink = "[" . $link[1] . "|" . $link[2] . "]";
return $nodeLink;
}
} // End class NodeInterface
?>