Wiki source for ParentAction


Show raw source

=====Go Ahead... Choose Your Parent!=====

Although wikis tend to have a flat web-like structure, it would still be nice if we could specify an "official parent" on a per-page basis. However, rather than building from the bottom up, which would require parents to choose their "most favorite" child, we'll let a child choose its parent instead.

Since we want this to run on versions of MySQL that don't support subqueries, we'll have to figure out a way to cache each page's "family tree," rebuilding only when it becomes necessary. I think the current solution works well enough, but it hasn't been tested much and I don't know how well it will hold up on a busy wiki.

====The Data Model====

%%(mysql)
CREATE TABLE `wikka_parents` (
`page_tag` varchar(75) NOT NULL default '',
`parents` mediumtext NOT NULL,
`time` datetime NOT NULL default '0000-00-00 00:00:00',
KEY `page_tag` (`page_tag`)
) TYPE=MyISAM;
%%

====The Code====

Save as "parent.php" in the actions directory...

%%(php)
<?php

// Examples
// {{parent page="HomePage"}} - set HomePage as the parent
// {{parent page="HomePage" label="<b>Current Location:</b>"}} -- add a prefix to the output
// Return a div with the id set to parent

global $table_pages, $table_parents;
$table_pages = $this->config['table_prefix'] . 'pages';
$table_parents = $this->config['table_prefix'] . 'parents';

function update_parents(&$wikka, $tag)
{
static $children = array();
global $table_pages, $table_parents;

if ($row = $wikka->LoadSingle("SELECT parents, time FROM $table_parents WHERE page_tag = '$tag'"))
{
$parents = $row['parents'];
$last_updated = $row['time'];
}
else
{
$parents = $last_updated = false;
}

// check to see if pages have changed since the last time we updated the parent info
// if so, we'll have to update any parent tags we encounter
// including this page's parent's parents and so on
if ($last_updated) $updated_pages = $wikka->LoadAll("SELECT tag FROM $table_pages WHERE time > '$last_updated'");
if ($updated_pages || !$last_updated)
{
// fetch the body of this page and check it for a parent action
// ignore the action if it specifies a child item as its parent
$row = $wikka->LoadSingle("SELECT body FROM $table_pages WHERE tag = '$tag' AND latest = 'Y'");
$wikka_body = $row['body'];
$parent_tag = preg_match('/{{.*parent[^}]+page="(.+)"/iU', $wikka_body, $match) ? $match[1] : false;
array_unshift($children, $tag);
if ($parent_tag && !in_array($parent_tag, $children))
{
// remove circular references from the tree
$parents = preg_replace("/.*$tag:/", '', update_parents($wikka, $parent_tag));
$retval = "$parents:$tag";
$wikka->Query("UPDATE $table_parents SET parents = '$retval', time = NOW() WHERE page_tag = '$tag'");
if (!mysql_affected_rows()) $wikka->Query("INSERT INTO $table_parents (page_tag, parents, time) VALUES ('$tag', '$retval', NOW())");
}
else
{
$retval = $tag;
}
array_shift($children);
}
elseif ($last_updated && !$updated_pages)
{
$retval = ($row = $wikka->LoadSingle("SELECT parents FROM $table_parents WHERE page_tag = '$tag'")) ? $row['parents'] : '';
}
else
{
$retval = '';
}
return $retval;
}

$label = isset($vars['label']) ? $vars['label'] : '';
$parents = update_parents($this, $this->tag);
$parents = split(':', $parents);
foreach ($parents as $tag)
{
$url = $this->Href('', $tag);
$links[] = $tag == $this->tag ? $tag : "<a href=\"$url\">$tag</a>";
}
echo '<div id="parent">' . $label . join(' » ', $links) . '</div>';

?>
%%

====The Examples====

%%
{{parent page="HomePage"}} - set HomePage as the parent
{{parent page="HomePage" label="<b>Current Location:</b>"}} -- add a prefix to the output
%%

====The Screenshot====

{{image alt="Screenshot of the Parent action's output" url="http://bytebrite.com/img/pss.gif"}}

In case you're wondering why the links don't look like standard wiki links, it's because I'm using the UncamelAction in my setup.

====Authors====

DennyShimkoski

----
CategoryUserContributions
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki