During one of my recent projects, I required some form of general purpose links listing/display in MODx. At first I considered using MODx's built-in Weblinks system along with Wayfinder or another display snippet. I ended up deciding against this in order to avoid cluttering the document tree (which becomes an efficiency problem in the current core) as well as provide a more meaningful interface for managing links.
Favorite LinksFavorite Links solves these issues and offers a broad range of customizability. Favorite Links consists of a module which allows for the management of a list of links and the corresponding snippet which handles link display. I've done a decent amount of testing and believe everything is fairly stable but both the snippet/module should still be considered development releases.
Favorite Links has several components, organized below for better access: Latest Version: [Updated 4/12/07]
Favorite Links SnippetSnippet Name: FavoriteLinks
Description: <strong>0.0.7</strong> Favorite Links Snippet
Required files: FavoriteLinks-0.0.7.zip, Extract directory from zip file above and place in assets/snippets/.
Snippet Code:<?php
/*---------------------------------------------------------------------------
* Favorite Links Snippet - Displays customized listing for "favorite" links
* - Used in conjunction w/ the Favorite Links module
*----------------------------------------------------------------------------
*
* 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.
*
* 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.
*
* @author Brian Stanback (www.stanback.net)
* @copyright Brian Stanback 2007
* @created: 2007/02/27
* @updated: 2007/04/18
* @version 0.0.7
*
$params = array();
/**
* General parameters
*--------------------------------------------------------------------------*/
$params['basePath'] = isset($basePath) ? $basePath : $modx->config['base_path'] . 'assets/snippets/FavoriteLinks/';
// Path to Favorite Links snippet directory (default: modx_base/assets/snippets/FavoriteLinks/)
$params['id'] = isset($id) ? $id : '';
// Unique identifier
// FavoriteLinks will set any global placeholders like this: [+id_PhName+]
// (Required if using pagination with several instances of FavoriteLinks on a single page)
$params['dispType'] = isset($dispType) ? $dispType : 'list';
// Type of results to display
// Possible types: list, tags, dates, results
$params['landing'] = isset($landing) ? intval($landing) : $modx->documentIdentifier;
// Page ID containing the [!FavoriteLinks? &results=`1`!] snippet call
$params['results'] = isset($results) ? intval($results) : 0;
// Set to 1 to allow the snippet call to be used for displaying
// results by specific tag/date
$params['startId'] = isset($startId) ? intval($startId) : 0;
// Start displaying data after the specified link ID
$params['tagSeparator'] = isset($tagSeparator) ? $tagSeparator : ', ';
// Separate tag display using the specified string
// Default: comma and a space
$params['tags'] = isset($tags) ? $tags : '';
// Display results matching the specified tag(s)
// Multiple tags are separated by a comma and a space
$params['excludeTags'] = isset($excludeTags) ? $excludeTags : '';
// Display results which do not match the specified tag(s)
// Multiple tags are separated by a comma and a space
$params['boolean'] = isset($boolean) ? $boolean : 'OR';
// Boolean operator to use when filtering by multiple &tags (default: OR)
// Options:
// OR - display records matching any defined tag
// AND - only display records matching all defined tags
$params['filter'] = isset($filter) ? $filter : '';
// Display only the links/dates/tags with a title or summary matching the filter text
$params['startDate'] = isset($startDate) ? $startDate : null;
// Return links added on or after the specified date
// Example: 2007-01-03
// Example: -1 Month
$params['endDate'] = isset($endDate) ? $endDate : null;
// Return results added on or before the specified date
$params['tplOuter'] = isset($tplOuter) ? $tplOuter : '@FILE:tpl/outer.tpl';
// Outer container template for links display/archive
// Default: @FILE:tpl/outer.tpl
// Possible placeholders:
// [+favlinks_items+]
//
// Templates can be:
// Any valid chunk name
// Code via @CODE:
// File via @FILE:
$params['tplNoResults'] = isset($tplNoResults) ? $tplNoResults : '@CODE:<p>No links found.</p>';
// Text or chunk to display when there are no results
// Default: @CODE:<p>No links found.</p>
/**
* Link display parameters
*--------------------------------------------------------------------------*/
$params['paginate'] = isset($paginate) ? intval($paginate) : 0;
// Split up the display into pages after reaching the specified number of links
// When paginate is enabled, &maxLinks becomes the number of links per page
// If set to 0, pagination is disabled
// Default: 0 (disabled)
$params['paginateAlwaysShowLinks'] = isset($paginateAlwaysShowLinks) ? intval($paginateAlwaysShowLinks) : 1;
// Whether or not to always show previous/next links
// Set to 1 to show or 0 to hide when there are 1 page or fewer links
// Default: 1 (enabled)
$params['paginateSplitter'] = isset($paginateSplitter) ? $paginateSplitter : ' ';
// Splitter character/text to include between page numbers
$params['showLinks'] = isset($showLinks) ? intval($showLinks) : 1;
// To show individual links, set to 1
// For only showing the tags/dates, set to 0
// Default: 1
// Only applicable to taglist and datelist display types
$params['sortLinks'] = isset($sortLinks) ? $sortLinks : 'title ASC';
// Sort link items
// Possible fields: id, url, title, summ, tags, xfn, rating, added, RAND()
// Add ASC or DESC to change the sort order, example: &sortLinks=`added DESC`
// Default: title ASC
$params['maxLinks'] = isset($maxLinks) ? intval($maxLinks) : 100000;
// Maximum number of links to display in the result
$params['offsetLinks'] = isset($offsetLinks) ? intval($offsetLinks) : 0;
// Offset for the links result
$params['tplLink'] = isset($tplLink) ? $tplLink : '@FILE:tpl/link.tpl';
// Template for each individual link in the listing
// Default: @FILE:tpl/link.tpl
// Possible placeholders:
// [+id+], [+url+], [+title+], [+summ+], [+tags+], [+xfn+], [+rating+], [+added+]
$params['tplAltLink'] = isset($tplAltLink) ? $tplAltLink : '';
// Template for alternating links
/**
* Tag-specific parameters
*--------------------------------------------------------------------------*/
$params['sortTags'] = isset($sortTags) ? $sortTags : 'count DESC';
// Sort tag items
// Possible fields: tag, count
// Add ASC or DESC to change the sort order, example: &sortTags=`tag ASC`
// Default: count DESC
$params['maxTags'] = isset($maxTags) ? intval($maxTags) : 100000;
// Maximum number of tags to display in the result
$params['offsetTags'] = isset($offsetTags) ? intval($offsetTags) : 0;
// Offset for the tags result
$params['tplTag'] = isset($tplTag) ? $tplTag : '@FILE:tpl/tag.tpl';
// Template for each individual tag
// Default: @FILE:tpl/tag.tpl
// Possible placeholders:
// [+url+], [+class+], [+tag+], [+count+], [+favlinks_links+]
/**
* Date-specific parameters
*--------------------------------------------------------------------------*/
$params['groupByYears'] = isset($groupByYears) ? intval($groupByYears) : 1;
// To show dates grouped by years, set to 1
// To show dates grouped by combined month and year, set to 0
// Default: 1
// Note: If this is set to 0, only &tplMonth will be used
$params['sortYears'] = isset($sortYears) ? $sortYears : 'ASC';
// Direction to sort the years
// Can be: ASC (for ascending order) or DESC (for descending)
// Default: ASC
$params['sortMonths'] = isset($sortMonths) ? $sortMonths : 'ASC';
// Direction to sort the months
// Can be: ASC (for ascending order) or DESC (for descending)
// Default: ASC
$params['tplYear'] = isset($tplYear) ? $tplYear : '@FILE:tpl/year.tpl';
// Template for each year
// Default: @FILE:tpl/year.tpl
// Possible placeholders:
// [+url+], [+year+], [+count+], [+favlinks_months+]
$params['tplMonth'] = isset($tplMonth) ? $tplMonth : '@FILE:tpl/month.tpl';
// Template for each month
// Default: @FILE:tpl/month.tpl
// Possible placeholders:
// [+url+], [+month+], [+month_name+], [+year+], [+count+], [+favlinks_links+]
/*--------------------------------------------------------------------------*/
include_once($params['basePath'] . 'classes/favoritelinks.class.inc.php');
if ($params['paginate']) // Set offset according to requested value
{
$params['offsetPage'] = isset($_REQUEST['offset']) ? intval($_REQUEST['offset']) : 0;
$params['offsetLinks'] += ($params['offsetPage'] * $params['maxLinks']);
}
if (class_exists('FavoriteLinks'))
$favlinks = new FavoriteLinks($params);
else
{
$modx->logEvent(1, 3, 'FavoriteLinks: Error loading main class:' . $params['basePath'] . 'classes/favoritelinks.class.inc.php');
return 'FavoriteLinks: Error loading main class';
}
return $favlinks->execute();
?>
Favorite Links ModuleThe module will automatically create the needed database table when it is first run. The default table name is: prefix_favorite_links, and you can manage your links through this module.
Module name: Favorite Links
Description: Management for favorite links snippet.
Required files: none.
Module Code//<?php
/**
* Favorite Links Module
* Brian Stanback
* 2007/04/12
* Version 0.0.5
* Compatible with MODx 0.9.5
*
* Loosely Based off of Friends List Module by Garry Nutting
*/
$_lang['action_title'] = 'Links Listing';
$_lang['add_link'] = 'Add Link';
$_lang['cancel'] = 'Cancel';
$_lang['delete'] = 'Delete';
$_lang['edit'] = 'Edit';
$_lang['error_unfilled'] = 'Please fill all required fields';
$_lang['form_message'] = '<p>To add a new link, enter link details in the form on the left and click the "Add Link" button. Tags should be separated by a comma and a space, eg. tag1, tag2, tag3. For an explanation and more information on XFN, please visit <a href="http://gmpg.org/xfn/">http://gmpg.org/xfn/</a></p><br /><p>To update a link select the link from the list, click the \'Edit\' button, and update the details in the form on the left.</p><br /><p>To remove a link select the link from the list and click the \'Delete\' button.</p>';
$_lang['form_title'] = 'Add/Update a Link';
$_lang['favlinks_title'] = 'Title';
$_lang['favlinks_url'] = 'URL';
$_lang['favlinks_summ'] = 'Summary';
$_lang['favlinks_rating'] = 'Rating';
$_lang['favlinks_tags'] = 'Tags';
$_lang['favlinks_xfn'] = 'XFN';
$_lang['filter'] = 'Filter';
$_lang['go'] = 'Go';
$_lang['link_added'] = 'The link has been added.';
$_lang['link_deleted'] = 'The link has been deleted.';
$_lang['link_updated'] = 'The link has been updated.';
$_lang['module_title'] = 'Favorite Links';
$_lang['no_records'] = 'No links have been added.';
$_lang['update_link'] = 'Update Link';
$basePath = $modx->config['base_path'];
$siteURL = $modx->config['site_url'];
$tb_prefix = $modx->db->config['table_prefix'];
// Include grid control class
include_once($basePath . 'manager/includes/controls/datagrid.class.php');
// Get configuration values
global $manager_theme;
$table = $modx->getFullTableName('favorite_links');
// Handle request data
$link_id = (isset($_POST['link_id'])) ? intval($_POST['link_id']) : '';
$title = (isset($_POST['title'])) ? $_POST['title'] : '';
$url = (isset($_POST['url']) && $_POST['url'] != 'http://') ? $_POST['url'] : 'http://';
$summ = (isset($_POST['summ'])) ? $_POST['summ'] : '';
$tags = (isset($_POST['tags'])) ? $_POST['tags'] : '';
$xfn = (isset($_POST['xfn'])) ? $_POST['xfn'] : '';
$rating = (isset($_POST['rating'])) ? $_POST['rating'] : '';
// Determine what action to take
if (isset($_POST['edit']) && $link_id > 0)
{
$action = 'edit';
}
elseif (isset($_POST['delete']) && $link_id > 0)
{
$action = 'delete';
}
elseif (isset($_POST['action']))
{
$action = $_POST['action'];
}
// Check for required fields
if (($action == 'add' || $action == 'update') && (!$title || !$url))
$error = $_lang['error_unfilled'] . ' (*)';
if ($action == 'update' && !isset($error))
{
$tags = ':' . str_replace(', ', ':', $tags) . ':';
$fields = array(
'title' => $modx->db->escape($title),
'url' => $modx->db->escape($url),
'summ' => $modx->db->escape($summ),
'tags' => $modx->db->escape($tags),
'xfn' => $modx->db->escape($xfn),
'rating' => $modx->db->escape($rating)
);
$modx->db->update($fields, $table, 'id=' . $link_id);
$msg .= $_lang['link_updated'];
$link_id = ''; $title = ''; $url = 'http://'; $summ = ''; $tags = ''; $xfn = ''; $rating = '';
}
elseif ($action == 'delete')
{
$modx->db->delete($table, 'id=' . $link_id);
$msg .= $_lang['link_deleted'];
$link_id = '';
}
elseif ($action == 'add' && !isset($error))
{
$tags = ':' . str_replace(', ', ':', $tags) . ':';
$fields = array(
'title' => $modx->db->escape($title),
'url' => $modx->db->escape($url),
'summ' => $modx->db->escape($summ),
'tags' => $modx->db->escape($tags),
'xfn' => $modx->db->escape($xfn),
'rating' => $modx->db->escape($rating),
'added' => time()
);
$modx->db->insert($fields, $table);
$msg .= $_lang['link_added'];
$link_id = ''; $title = ''; $url = 'http://'; $summ = ''; $tags = ''; $xfn = ''; $rating = '';
}
if ($action == 'edit')
{
$result = $modx->db->select('*', $table, 'id="' . $link_id . '"');
$row = $modx->db->getRow($result);
$title = $row['title'];
$url = $row['url'];
$summ = $row['summ'];
$tags = str_replace(':', ', ', trim($row['tags'], ':'));
$xfn = $row['xfn'];
$rating = $row['rating'];
}
if (!function_exists('checkLinksTable'))
{
/**
* Create the table if it does not exist
*/
function checkLinksTable($table, &$errorMsg)
{
global $modx;
$sql = "CREATE TABLE IF NOT EXISTS " . $table . " (" .
"`id` int(11) NOT NULL auto_increment PRIMARY KEY, " .
"`title` varchar(255) NOT NULL, " .
"`url` varchar(255) NOT NULL, " .
"`summ` text, " .
"`tags` varchar(255), " .
"`rating` float(2), " .
"`xfn` varchar(64), " .
"`added` char(10)" .
")";
if (!$modx->db->query($sql))
$errorMsg .= "<p class=\"error\">Error creating table {$table}!</p>\n";
}
}
checkLinksTable($table, $errorMsg);
$filter = "";
if ($_POST['filter'])
{
$q = $modx->db->escape($_POST['filter']);
$filter .= "(url LIKE '%$q%' OR title LIKE '%$q%' OR summ LIKE '%$q%')";
}
if ($_POST['tag'])
{
$q = $modx->db->escape($_POST['tag']);
if ($filter != "") $filter .= " AND ";
$filter .= "(tags LIKE '%:$q:%')";
}
$linksQuery = $modx->db->select('*', $table, $filter, 'added DESC');
// Page header
$output .= '
<html>
<head>
<link rel="stylesheet" type="text/css" href="media/style/' . $manager_theme . '/style.css" />
<style type="text/css">
.topdiv {
border: 0;
}
.subdiv {
border: 0;
}
li {
list-style:none;
}
.tplbutton {
text-align: right;
}
#bttn .bttnheight {
height: 25px !important;
padding: 0px;
padding-top: 6px;
float: left;
vertical-align: middle !important;
}
ul.sortableList {
padding-left: 20px;
margin: 0px;
width: 300px;
font-family: Arial, sans-serif;
}
ul.sortableList li {
font-weight: bold;
cursor: move;
color: grey;
padding: 2px 2px;
margin: 2px 0px;
border: 1px solid #000000;
background-image: url("media/style/' . $manager_theme . '/images/bg/grid_hdr.gif");
background-repeat: repeat-x;
}
#bttn .bttnheight {
height: 25px !important;
padding: 0px;
padding-top: 6px;
float: left;
vertical-align: middle !important;
}
#bttn a{
cursor: default !important;
font: icon !important;
color: black !important;
border: 0px !important;
padding: 5px 5px 7px 5px!important;
white-space: nowrap !important;
vertical-align: middle !important;
background: transparent !important;
text-decoration: none;
}
#bttn a:hover {
border: 1px solid darkgreen !important;
padding: 4px 4px 6px 4px !important;
background-image: url("media/style/' . $manager_theme . '/images/bg/button_dn.gif") !important;
text-decoration: none;
}
#bttn a img {
vertical-align: middle !important;
}
.go a {
cursor: default !important;
font: icon !important;
color: black !important;
border: 0px !important;
padding: 5px 5px 7px 5px !important;
white-space: nowrap !important;
vertical-align: middle !important;
background: transparent;
text-decoration: none;
}
.go a:hover {
border: 1px solid darkgreen !important;
padding: 4px 4px 6px 4px !important;
background: url("media/style/' . $manager_theme . '/images/bg/button_dn.gif");
text-decoration: none;
}
.go a img {
vertical-align: middle !important;
}
.form_message {
font-size: 85%;
}
.gridItem, .gridAltItem {
font-sizE: 95%;
}
td {
font-size: 90%;
}
</style>
</head>
<body>
<div class="subTitle" id="bttn">
<span class="right"><img src="media/style/' . $manager_theme . '/images/_tx_.gif" width="1" height="5"><br />' . $_lang['module_title'] . '</span>
<div class="bttnheight"><a id="Button5" onclick="document.location.href=\'index.php?a=106\';">
<img src="media/style/' . $manager_theme . '/images/icons/close.gif" alt="" /> Close Favorite Links Manager</a>
</div>
<div class="bttnheight"><a id="Button5" onclick="document.location.href=\'index.php?a=106\';">
<img src="media/style' . $manager_theme . '/images/icons/link_add.png" alt="" /> Import / Export</a>
</div>
<div class="stay"></div>
</div>
<div class="sectionHeader">' . $_lang['form_title'] . '</div>
<div class="sectionBody">
';
$output .= '
<table><tr><td style="width: 60%;" valign="top">
<form name="details" method="post" action="">
<input type="hidden" name="action" value="' . (($action == 'edit') ? 'update' : 'add') . '" />
<input type="hidden" name="link_id" value="' . $link_id . '" />
<table border="0" cellspacing="0" cellpadding="1" width="95%">
<tr><td>' . $_lang['favlinks_title'] . ': * </td><td><input type="text" name="title" value="' . $title . '" style="width: 100%;" /></td></tr>
<tr><td>' . $_lang['favlinks_url'] . ': * </td><td><input type="text" name="url" value="' . $url . '" style="width: 100%;" /></td></tr>
<tr><td valign="top">' . $_lang['favlinks_summ'] . ': </td><td><textarea name="summ" rows="2" style="width: 100%; height: auto;">' . $summ . '</textarea></td></tr>
<tr><td>' . $_lang['favlinks_tags'] . ': </td><td><input type="text" name="tags" value="' . $tags . '" style="width: 100%;" /></td></tr>
<tr><td>' . $_lang['favlinks_xfn'] . ': </td><td><input type="text" name="xfn" value="' . $xfn . '" style="width: 100%;" /></td></tr>
<tr><td>' . $_lang['favlinks_rating'] . ': </td><td><input type="text" name="rating" value="' . $rating . '" style="width: 100%;" /></td></tr>
<tr><td> </td><td><br /><input type="submit" name="postform" value="' . (($action == 'edit') ? $_lang['update_link'] : $_lang['add_link']) . '" /></td></tr>
</table>
</form>
</td><td valign="top" class="form_message">' . $_lang['form_message'] . '</td></tr></table>';
// Output any messages or errors
$output .= '<div>';
$output .= '<p class="warning">' . $msg . '</p>';
if (isset($error)) {
$output .= '<p class="warning">' . $error . '</p>';
}
$output .= '</div>';
$output .= '</div>
<div class="sectionHeader">' . $_lang['action_title'] . '</div>
<div class="sectionBody">
<form name="links" method="post" action="">
<div style="float: right;">' . $_lang['filter'] . ': <select name="tag" onchange="links.submit()"><option value="">-</option>';
// Get tags from database, populating array
$result = $modx->db->select('DISTINCT tags', $table);
$tags = array();
while ($row = $modx->db->getRow($result))
{
foreach (explode(':', trim($row['tags'], ':')) as $tag) $tags[$tag]++;
}
ksort($tags);
foreach ($tags as $tag => $occurances)
{
// Output tags
if ($tag == $_POST['tag'])
$output .= "<option selected=\"selected\" value=\"$tag\">$tag</option>";
else
$output .= "<option value=\"$tag\">$tag</option>";
}
$output .= '
</select> <input type="text" name="filter" size="20" value="' . $_POST['filter'] . '" /> <input type="submit" value="' . $_lang['go'] . '" /></div>
<input type="submit" value="' . $_lang['edit'] . '" name="edit" />
<input type="submit" value="' . $_lang['delete'] . '" name="delete" /><br /><br />';
// Render links grid
$grid = new DataGrid('', $linksQuery);
$grid->noRecordMsg = $_lang['no_records'];
$grid->cssClass = "grid";
$grid->columnHeaderClass = "gridHeader";
$grid->itemClass = "gridItem";
$grid->altItemClass = "gridAltItem";
$grid->columns = " ," . $_lang['favlinks_title'] . "," . $_lang['favlinks_url'] . "," . $_lang['favlinks_rating'];
$grid->colTypes = "template:<input type='radio' value='[+id+]' name='link_id' />";
$grid->colWidths = "5%,35%,35%,15%";
$grid->fields = "template,title,url,rating";
$output .= $grid->render();
$output .= '</form>';
$output .= '</div></body></html>';
return $output;
Favorite Links FormPlease visit this post for code and example use of FavoriteLinksForm. Thanks.