The system currently:
  1. Detects whenever a page mentions its name
  2. Detects whenever a page stops mentioning its name
  3. Allows admins to create "link groups"
  4. Allows managers to move links between "link groups" with ease
  5. Allows managers to assign weights to individual links
  6. Renders "link groups" in a variety of styles
  7. Allows content of linked pages to be embedded within the calling page

The Data Model


you may have to replace wikka_ with your used prefix --NilsLindenberg

CREATE TABLE `wikka_link_manager_groups` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(100) NOT NULL DEFAULT '',
  `description` MEDIUMTEXT,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `name` (`name`)
) TYPE=MyISAM AUTO_INCREMENT=1 ;

CREATE TABLE `wikka_link_manager_links` (
  `link_id` INT(11) NOT NULL AUTO_INCREMENT,
  `this_tag` VARCHAR(75) NOT NULL DEFAULT '',
  `page_tag` VARCHAR(75) NOT NULL DEFAULT '',
  `link_group_id` INT(11) DEFAULT NULL,
  `weight` INT(11) DEFAULT NULL,
  PRIMARY KEY  (`link_id`)
) TYPE=MyISAM AUTO_INCREMENT=1 ;


The PHP Code


I've found that it's convenient to keep a "common settings" file in the actions directory to store variables shared between actions and handlers. In my setup, I call it "common.ini.php". Here is the code:

<?php
// all
$base_url = 'http://localhost/wikka/wikka.php';
$page_var = 'wakka';

// linkmanager.php
$table_link_groups = $this->config['table_prefix'] . 'link_manager_groups';
$table_links = $this->config['table_prefix'] . 'link_manager_links';
$table_pages = $this->config['table_prefix'] . 'pages';
?>


Next up is the "linkmanager.php" file, which should also be saved in the actions directory...

<?php

/**
* admin interface
* {{linkmanager}}
*
* display options
* {{lmshow}} -- (default) returns all groups as definition list (dl) of links (using the default "box" style)
* {{lmshow style="CSS STYLE"}} -- replace CSS STYLE with box, event, or table for different looks
* {{lmshow group="Group One"}} -- show the group labeled "Group One" as dl of links
* {{lmshow group="Group One" embed="all"}} -- embed the entire body of every link in this page
* {{lmshow group="Group One" embed="Overview"}} -- embed section with heading "Overview" of every link in this page
*/


include('actions/common.ini.php');

$is_admin = $this->IsAdmin();
$has_access = $this->HasAccess('write');

if ($has_access)
{
    if (isset($_POST['update_links']))
    {
        mysql_query("DELETE FROM $table_links WHERE this_tag = '$this->tag'");
        $links_to_move = isset($_POST['selected_links']) ? $_POST['selected_links'] : array();
        if (isset($_POST['link_weights']))
        {
            foreach ($_POST['link_weights'] as $page_tag => $link_weight)
            {
                if (empty($link_weight)) $link_weight = 'NULL';
                if (isset($links_to_move[$page_tag]))
                {
                    $link_group_id =  $_POST['group_select'];
                    unset($links_to_move[$page_tag]);
                }
                else
                {
                    $link_group_id = isset($_POST['link_group_ids']) ? $_POST['link_group_ids'][$page_tag] : '';
                }
                mysql_query("INSERT INTO $table_links (this_tag, page_tag, link_group_id, weight) VALUES ('$this->tag', '$page_tag', $link_group_id, $link_weight)");
            }
        }
        if (count($links_to_move) && $_POST['group_select'] != 'None')
        {
            foreach ($links_to_move as $page_tag => $junk)
            {
                mysql_query("INSERT INTO $table_links (this_tag, page_tag, link_group_id) VALUES ('$this->tag', '$page_tag', $_POST[group_select])");
            }
        }
    }
}

if ($is_admin)
{
    if (isset($_GET['delete_group']))
    {
        mysql_query("DELETE FROM $table_link_groups WHERE id = $_GET[group_id]");
    }

    if (isset($_POST['add_new_group']))
    {
        $new_group_name = mysql_real_escape_string($_POST['group_name']);
        $new_group_description = mysql_real_escape_string($_POST['group_description']);
        mysql_query("INSERT INTO $table_link_groups (name, description) VALUES ('$new_group_name', '$new_group_description')");
    }

    if (isset($_POST['update_groups']))
    {
        $group_names = $_POST['group_names'];
        $group_descriptions = $_POST['group_descriptions'];
        foreach ($group_names as $group_id => $group_name)
        {
            $group_description = mysql_real_escape_string($group_descriptions[$group_id]);
            mysql_query("UPDATE $table_link_groups SET name = '$group_name', description = '$group_description' WHERE id = $group_id");
        }
    }
}

if ($has_access)
{
    echo "<form id=\"add_link_group\" action=\"$base_url\" method=\"post\">";
    echo "<input type=\"hidden\" name=\"$page_var\" value=\"$this->tag\">";
    if ($is_admin)
    {
?>
<h3 style="border-bottom: 1px solid #aaa;">Manage Link Groups</h3>
<div style="background: #fafafa">
<div style="background: #eef"><table cellpadding="5" id="add_link_group">
<tr><th>Name</th><th>Description</th></tr>
<tr>
<td valign="top"><input type="text" name="group_name" value=""></td>
<td><textarea cols="40" rows="2" name="group_description"></textarea></td>
</tr>
<tr><td colspan="3" align="right"><input type="submit" name="add_new_group" value="Add Group"></td></tr>
</table></div>
<?php
    }
    $sql = "SELECT id, name, description FROM $table_link_groups ORDER BY id DESC";
    $result = mysql_query($sql);
    if ($result && mysql_num_rows($result))
    {
        $group_select = '<select name="group_select"><option value="none">None</option>';
        $manage_groups = '<table cellpadding="5" id="edit_link_groups"><tr><th>Name</th><th>Description</th><th align="center">Actions</th></tr>';
        while ($row = mysql_fetch_array($result))
        {
            $groups[$row['id']] = $row['name'];
            $group_select .= "<option value=\"$row[id]\">$row[name]</option>";
            $delete = "<a href=\"$base_url?$page_var=$this->tag&delete_group=1&group_id=$row[id]\">Delete</a>";
            $manage_groups .= "<tr><td valign=\"top\"><input type=\"text\" name=\"group_names[$row[id]]\" value=\"$row[name]\"></td>";
            $manage_groups .= "<td><textarea name=\"group_descriptions[$row[id]]\" cols=\"40\" rows=\"2\">$row[description]</textarea></td><td align=\"center\" valign=\"top\">$delete</td></tr>";
        }
        $manage_groups .= '<tr><td colspan="2" align="right"><input type="submit" name="update_groups" value="Update Groups"></td><td>&nbsp;</td></tr>';
        $manage_groups .= '</table></div>';
        $group_select .= '</select>';
    }
    if ($is_admin) echo $manage_groups;
?>
<h3 style="border-bottom: 1px solid #aaa;">Manage Links</h3>
<?php
    $sql = "SELECT link_id, tag, link_group_id, weight FROM $table_pages LEFT JOIN $table_links ON tag = page_tag WHERE MATCH (body) AGAINST ('$this->tag') AND latest = 'Y' AND tag != '$this->tag' ORDER BY link_group_id DESC, weight DESC";
    $result = mysql_query($sql);
    if ($result && mysql_num_rows($result))
    {
        echo '<table width="500" cellpadding="5" id="edit_links"><tr><th>&nbsp;</th><th>Page Tag</th><th align="center">Group</th><th align="center">Weight</th></tr>';
        while ($row = mysql_fetch_array($result))
        {
            $group_valid = isset($groups[$row['link_group_id']]);
            if ($group_valid) $valid_links[] = $row['link_id'];
            $color = (++$i % 2 != 0) ? 'bgcolor="#f6f6f6"' : '';
            $group_name = $group_valid && $row['link_group_id'] ? $groups[$row['link_group_id']] . "<input type=\"hidden\" name=\"link_group_ids[$row[tag]]\" value=\"$row[link_group_id]\">" : 'None';
            $group_weight = $group_valid && $row['link_id'] ? "<input size=\"3\" type=\"text\" name=\"link_weights[$row[tag]]\" value=\"$row[weight]\">" : 'None';
            echo "<tr $color><td><input type=\"checkbox\" name=\"selected_links[$row[tag]]\"></td>";
            echo "<td><a href=\"$base_url?$page_var=$row[tag]\">$row[tag]</a></td>";
            echo "<td align=\"center\">$group_name</td>";
            echo "<td align=\"center\">$group_weight</td></tr>";
        }
        echo "<tr><td align=\"right\" colspan=\"4\"><b>move selected links to:</b>&nbsp;$group_select&nbsp;";
        echo '<input type="submit" name="update_links" value="Update Links"></td></tr>';
        echo '</table>';
        // remove links that have been unlinked in the source document
        $valid_links = join(',', $valid_links);
        mysql_query("DELETE FROM $table_links WHERE this_tag = '$this->tag' AND link_id NOT IN ($valid_links)");
    }
    else
    {
        echo '<p>There are no pages linking to this one.</p>';
    }
    echo '</form>';
}
?>


Now, save the following code as "lmshow.php" in the same directory...

<?php

include('actions/common.ini.php');

if (!function_exists('smart_title'))
{
    function smart_title($wikka_body)
    {
        return preg_match('/(=){2,5}([^=]*)(=){2,5}/', $wikka_body, $matches) ? $matches[2] : '';
    }
}
if (!function_exists('fetch_section'))
{
    function fetch_section($wikka_body, $section)
    {
        return preg_match("/(=){2,5}$section(=){2,5}([^=]*)/ism", $wikka_body, $matches) ? $matches[3] : false;
    }
}

$group = isset($vars['group']) ? $vars['group'] : '__ALL__';
$embed = isset($vars['embed']) ? $vars['embed'] : false;
$css_class = isset($vars['style']) ? $vars['style'] : 'box';

$group_where = $group == '__ALL__' ? '' : "WHERE name = '$group'";
$link_where = '';

$sql = "SELECT id, name, description FROM $table_link_groups $group_where";
$result = mysql_query($sql);
if ($result && mysql_num_rows($result))
{
    while ($row = mysql_fetch_array($result))
    {
        if (strtolower($row['name']) == strtolower($group)) $link_where =  "AND link_group_id = $row[id]";
        $groups[$row['id']]['name'] = $row['name'];
        $groups[$row['id']]['description'] = $row['description'];
        $count[$row['id']] = ceil(strlen($row['description']) / 25);
    }
}
else
{
    return false;
}

$sql = "SELECT link_group_id, page_tag, body  FROM $table_links l, $table_pages p WHERE l.page_tag = p.tag AND p.latest ='Y' AND this_tag = '$this->tag' $link_where ORDER BY weight DESC";
$result = mysql_query($sql);
if ($result && mysql_num_rows($result))
{
    while ($row = mysql_fetch_array($result))
    {
        $groups[$row['link_group_id']]['links'][$row['page_tag']] = $row['body'];
        ++$count[$row['link_group_id']];
    }
    arsort($count);
    foreach ($count as $id => $n)
    {
        if (is_array($groups[$id]['links']))
        {
            $name = $groups[$id]['name'];
            $css_id = str_replace(' ', '_', $name);
            if ($embed)
            {
                foreach ($groups[$id]['links'] as $page_tag => $body)
                {
                    $body = preg_replace('/{{.*linkmanager.*}}/U', '', $body);
                    $body = preg_replace('/{{.*lmshow.*}}/U', '', $body);
                    $output .= ($embed == 'all') ? trim($body) : fetch_section($body, $embed);
                    $output .= "\n\n";
                }
                echo $this->Format($output);
            }
            else
            {
                echo "<dl class=\"lm_$css_class\" id=\"lm_$css_id\">";
                echo "<dt>$name</dt>";
                if ($summary = $groups[$id]['description']) echo "<dd class=\"summary\">$summary</dd>";
                foreach ($groups[$id]['links'] as $page_tag => $body)
                {
                    $title = empty($body) ? '' : 'title="' . smart_title($body) . '"';
                    echo "<dd><a href=\"$base_url?$page_var=$page_tag\" $title>$page_tag</a></dd>";
                }
                echo '</dl>';
            }
        }
    }
}
?>


Required CSS Definitions


Add this to the end of your wikka.css file...

dl.lm_box
{
    float: left;
    width: 176px;
    padding: 4px 0px 4px 2px;
    background: #F1F1F1;
    border: 1px solid #999;
    border-left: 1px solid #999;
    margin: 10px;
    margin-bottom: 20px;
    text-align: left;
}

dl.lm_box dt {
    border: solid 1px #ccc;
    background: #e6e6e6;
    font-weight: bold;
    padding: 2px;
}

dl.lm_box dd.summary {
    padding: 5px;
    margin: 2px 2px 0px 0px;
    background: #fafafa;
}

dl.lm_box dd {
    padding: 0px;
    margin: 2px 2px 0px 0px;
}

dl.lm_box dd a
{
    display: block;
    border: solid 1px #e6e6e6;
    padding: 2px 6px 2px 6px;
    margin: 0px 2px;
    background: #e6e6e6;
    height: 1%;
    line-height: 1em;
    color: #000;
}

dl.lm_box dd a:hover
{
    border: solid 1px #999;
    background: #CCC;
}

dl.lm_box dd a:hover, dl.lm_box dd a:visited, dl.lm_box dd a:active, dl.lm_box dd a:link
{
    text-decoration: none ! important;
}

dl.lm_event
{
margin: 0;
padding: 0;
font-family: georgia, times, serif;
}

.lm_event dt
{
position: relative;
left: 0;
top: 1.5em;
width: 15em;
font-weight: bold;
}

.lm_event dd
{
border-left: 1px solid #000;
margin: 0 0 0 12em;
padding: 0 0 .5em 1.5em;
}

dl.lm_table { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd;}

.lm_table dt
{
width: 15em;
padding: .5em;
float: left;
margin: 0;
font-weight: bold;
}

.lm_table dd
{
margin-left: 16em;
padding: .5em;
}


Lastly, you may want to save the following code as "clearfloats.php" in the actions directory.

<?php
    echo '<div style="margin-bottom:-4em;clear:both;">&nbsp;</div>';
?>


The Much Needed Example


This is taken directly from my test setup, which can be seen in the screenshot below.

{{linkmanager}}

====Using the lmshow Action====

{{lmshow}}
{{clearfloats}}

And some more text goes here...


The Screenshot


Screenshot of the LinkManager action

I actually moused over the link at the bottom to show that link titles are automatically extracted from the linked pages and inserted into each anchor tag's title attribute, but I guess the old PrtScrn button didn't like that idea too much!


But Wait... There's More!


The action can do a lot more than display links. All of the display options are given at the top of linkmanager.php, but I'll repeat them here for easy reference.

{{lmshow}} -- (default) returns all groups as definition list (dl) of links (using the default "box" style)
{{lmshow style="CSS STYLE"}} -- replace CSS STYLE with box, event, or table for different looks
{{lmshow group="Group One"}} -- show the group labeled "Group One" as dl of links
{{lmshow group="Group One" embed="all"}} -- embed the entire body of every link in this page
{{lmshow group="Group One" embed="Overview"}} -- embed section with heading "Overview" of every link in this page


References and Places I Stole From


Todo List/Discussion Topics


Authors


DennyShimkoski


CategoryUserContributions
There are 8 comments on this page. [Show comments]
Valid XHTML :: Valid CSS: :: Powered by WikkaWiki