Bookmark Manager
An integrated bookmark manager/
social bookmarking∞ framework in the spirit of
de.lirio.us∞.
Note: Scroll down to the import section for scripts to import de.lirio.us data and other bookmarks into the
BookmarkManager.
Screenshots
Main page
Add bookmark page
Design ideas
- Allow both user-specific and site-wide bookmark access (other than those tagged as "private")
- Allow tagging of objects other than URIs (such as pages)
- Implement as both a handler and an action
- Gordon Luk (creator of Freetag∞, the engine behind Bookmark Manager) has some interesting comments about tagging here∞.
- Here's another Wikka tagging project∞ using the Freetag∞ engine. It would be useful to investigate the merging of that project with this one to permit page tagging in addition to bookmark tagging.
Progress reports
- Beta test announcement: Well, after hacking around with Scuttle, I decided it was much too complex for what I had in mind. Nils suggested another project, Freetag∞, that seems to provide the basic functionality needed without all of the formatting/presentation overhead. I think something like this would be a cool addition (as a 100% modular plugin) to Wikka...
- Progress is going well. Add/edit/delete capabilities have been added. Two Perl scripts (see below) have been provided that allow you to export your bookmarks from de.lirio.us and import them into BookmarkManager. Beta currently running under Wikka 1.1.6.2-alpha. A page of 25 links (out of 600+) and 100 tags (out of 1200+) renders in approximately 1.1 seconds. A tag seach of 1207 tags takes approximately 1.2 seconds.
- More enhancements and modifications: Numeric tags, link pagination, tag pagination, tag/link editing and deletion.
- More cool stuff: Support for bookmarklets (small Javascript bookmark that immediately saves the page you are viewing and returns to the page), tag links within link descriptors, better use of screen real estate using CSS.
- Tags are now searchable! Searchable titles/descriptions to come...
TODO
Indicates issues that have been addressed
- This code is most likely not yet safe for a production environment! I've worked to secure all data passed in from GET/POST requests, as well as from Wikka itself in some cases. I'm hoping a few more folks have time to look over the code for any obvious security weaknesses.
- User tags should be displayed as raw tags.
- As a general consideration it would be nice to provide this functionality as a handler.
- it would be nice to have a link for the add-form near list yours.
- how about something like my tags / all tags? List all/list yours now provides this functionality
- what would be usefull: If I tag a link with the name of an existing wiki-page, this link could show up at the end of the page.
- Need to fix logic so "your" tags only display "your" links (also, identify tag cloud as "all" or "yours")
- Optional logic to display tags in a right-justified vertical list instead of a cloud
- Paging, user prefs
- Tag pages as well as links
- Please put the wikka_freetag class in a file like Wikka.freetag.class.php in the new \libs directory.
- $freetag_options -> why not use the params provided by wikka ($this->mysql_host, etc.)?
- Create bookmarklets such as these (borrowed from de.lirio.us∞): Implemented...see below for details
- Provide edit/delete functionality
- Search functionality (multi-tag, by title/desc)
- Restricting spam. Some ideas: Option to allow only registered users to set bookmarks Implemented; using "captcha" images to preclude automated scripts
- It would be nice if tags in each bookmarks were links pointing to the list of bookmarks with the same tag.
- Move markup to their own div tags∞
- Move helper functions, class extensions to libs/ dir∞
- Fix PHP warnings w/r/t/ null arrays in ksort, min, max, etc.
- The codebase is getting large enough to consider distributing as a tarball/zipfile.
- Split processing of tags and links so they are independent of each other (AJAX??)
- Check/warn on link dupes during add new link operation
- Title and description: What's the diff? More useful to display URL in lieu of one of these?
- Export options: RSS, all to file, to screen (suitable for copy-and-paste), etc.
Installation
- Install a copy of Freetag∞ in 3rdparty/plugins/ (version 0.250 or better) Note: Rename the installation directory (Freetag-0.250) to 'freetag'
- Create a MySQL database (I used freetag as the DB name) and use the MySQL dump below to create the necessary tables (such as mysql -u root freetag < wikka_freetag.sql):
wikka_freetag.sql
-- $Id: freetag.sql,v 1.2 2006/05/29 17:11:44 brian Exp brian $
--
-- MySQL dump 9.11
-- Freetag Structure v2.02
--
-- Table structure for table `freetags`
--
DROP TABLE IF EXISTS freetags;
CREATE TABLE freetags (
id int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
tag varchar(30) NOT NULL DEFAULT '',
raw_tag varchar(50) NOT NULL DEFAULT '',
PRIMARY KEY (id)
) TYPE=MyISAM;
--
-- Table structure for table `freetagged_objects`
--
DROP TABLE IF EXISTS freetagged_objects;
CREATE TABLE freetagged_objects (
tag_id int(10) UNSIGNED NOT NULL DEFAULT '0',
tagger_id int(10) UNSIGNED NOT NULL DEFAULT '0',
object_id int(10) UNSIGNED NOT NULL DEFAULT '0',
tagged_on datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`tag_id`,`tagger_id`,`object_id`),
KEY `tag_id_index` (`tag_id`),
KEY `tagger_id_index` (`tagger_id`),
KEY `object_id_index` (`object_id`)
) TYPE=MyISAM;
--
-- Table structure for table `freetag_bookmarks`
--
DROP TABLE IF EXISTS freetag_bookmarks;
CREATE TABLE freetag_bookmarks (
bookmark_id int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
title varchar(255) NOT NULL DEFAULT '',
uri varchar(255) NOT NULL,
description varchar(255) DEFAULT NULL,
wikka_id varchar(75) NOT NULL,
private tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`bookmark_id`),
KEY `bookmark_id_index` (`bookmark_id`)
) TYPE=MyISAM;
--
-- Table structure for table `freetag_wikka_id_map`
--
DROP TABLE IF EXISTS freetag_wikka_id_map;
CREATE TABLE freetag_wikka_id_map (
tagger_id int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
wikka_id varchar(75) NOT NULL DEFAULT '',
PRIMARY KEY(`tagger_id`)
) TYPE=MyISAM;
- Save the following file as actions/bookmarks.php:
bookmarks.php
<?php
/**
* Bookmark manager with tagging
*
* Allows users (registered or not) to tag objects such as
* bookmarks and display linked tags in the spirit of
* {@link http://de.licio.us} and {@link http://de.lirio.us}.
*
* Usage: {{bookmarks}}
*
* Credits:
* Gordon Luk's Freetag for PHP4 {@link http://www.getluky.net/freetag}
*
* 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 Licence for more details:
*
* http://www.gnu.org/copyleft/gpl.html
*
*
* @author {@link http://wikkawiki.org/BrianKoontz Brian Koontz} <brian@pongonova.net>
* @copyright Copyright (c) 2006, Brian Koontz <brian@pongonova.net>
* @name BookmarkManager
* @package Actions
* @filesource
* @license http://www.gnu.org/copyleft/gpl.html
* @since Wikka 1.1.6.1
* @version $Id: bookmarks.php,v 1.8 2006/08/10 04:03:38 brian Exp brian $
*
*/
// Check for freetag class and helper libraries
include_once('libs/Wikka.freetag.class.php');
include_once('libs/Wikka.freetag.lib.php');
/********************************************************************/
/* DB connection params */
/********************************************************************/
$freetag_options =
array(
'db_user' =>
$this->
config['mysql_user'],
'db_pass' =>
$this->
config['mysql_password'],
'db_host' =>
$this->
config['mysql_host'],
'db_name' =>
'freetag',
'PCONNECT' =>
true,
);
$freetag =
new wikka_freetag
($freetag_options);
$wikka_id =
$this->
GetUserName();
$tagger_id = wikka_id_to_tagger_id
($wikka_id,
$this,
$freetag_options);
$all_obj_count = count_objects
(NULL,
$this,
$freetag_options);
$your_obj_count = count_objects
($wikka_id,
$this,
$freetag_options);
$search_type =
"";
if(isset($_REQUEST['action'])) {
if($_REQUEST['action']==
"list_yours") {
$search_type =
"search_yours";
} else {
$search_type =
"search_all";
}
}
echo "<a href=\"".
$this->
href().
"&action=list_all".
"\">List all</a> (".
$all_obj_count.
") | ".
"<a href=\"".
$this->
href().
"&action=list_yours".
"\">List yours</a> (".
$your_obj_count.
") | ".
"<a href=\"".
$this->
href().
"&action=add".
"\">Add</a>".
$this->
FormOpen().
"<input type=\"hidden\" name=\"action\" value=\"".
$search_type.
"\" />".
"Search: ".
"<input name=\"search\" size=\"20\" />".
"<input type=\"radio\" name=\"search_type\" value=\"tags\" checked>Tags".
"<input type=\"radio\" name=\"search_type\" value=\"title_desc\">Title/Desc".
$this->
FormClose();
if(!
isset($_REQUEST['action'])) {
// Display all tags at start of session
$this->
Redirect($this->
href().
"&action=list_all");
}
// Search by tags, titles, or descriptions
// Action name: search
// Search field name: search
// Radio buttons: search_type: "tags" or "title_desc"
if(isset($_REQUEST['action']) &&
($_REQUEST['action']==
"search_yours") ||
($_REQUEST['action']==
"search_all")) {
if(isset($_REQUEST['search_type']) &&
($_REQUEST['search_type']==
"tags") &&
isset($_REQUEST['search'])) {
if($_REQUEST['action'] ==
"search_yours") {
$this->
Redirect($this->
href().
"&search_term=".
$_REQUEST['search'].
"&action=list_yours");
} else {
$this->
Redirect($this->
href().
"&search_term=".
$_REQUEST['search'].
"&action=list_all");
}
}
}
// Add new entry to DB
if(isset($_REQUEST['action']) &&
($_REQUEST['action']==
"add")) {
$values =
array();
// Check for request from a bookmarklet...check to see if user
// is logged in...if not, redirect to login page and come back
// here when done
if(isset($_REQUEST['wikka_bookmarklet'])) {
$values['uri'] =
mysql_real_escape_string($_REQUEST['uri']);
if(isset($_REQUEST['title'])) {
$values['title'] =
mysql_real_escape_string($_REQUEST['title']);
}
$values['referrer'] =
$_SERVER['HTTP_REFERER'];
$values['when_done'] =
"add_link";
save_to_current_session
($values);
//session_write_close();
if(!
$this->
GetUser()) {
$_SESSION['go_back'] =
$this->
Href(null,
$this->
MiniHref().
"&action=add");
//session_write_close();
$this->
Redirect($this->
config['base_url'].
"UserSettings");
}
}
// The next clause checks to see if we're returning from a
// login request while trying to execute a bookmarklet
if(isset($_SESSION['when_done']) &&
($_SESSION['when_done']==
"add_link")) {
$values['uri'] =
$_SESSION['uri'];
$values['title'] =
$_SESSION['title'];
$_SESSION['when_done'] =
"return";
//session_write_close();
}
if(trim($_REQUEST['tags']) !=
"") {
// Private bookmark?
$private =
0;
if(strpos(trim($_REQUEST['tags']),
"@private") !==
false)
$private =
1;
// Converts numeric tag "123" to "123_" to facilitate
// alphanumeric sorting (otherwise, PHP converts string to
// true integer).
$tags =
preg_split('/\s+/',
$_REQUEST['tags'], -
1, PREG_SPLIT_NO_EMPTY
);
$tags =
preg_replace('/^([0-9]+)$/',
"$1_",
$tags);
$tags =
implode(" ",
$tags);
$this->
Query("insert ".
$freetag_options['db_name'].
".freetag_bookmarks set ".
"title = '".mysql_real_escape_string
($_REQUEST['title']).
"', ".
"uri = '".mysql_real_escape_string
($this->
cleanUrl($_REQUEST['uri'])).
"', ".
"wikka_id = '".mysql_real_escape_string
($wikka_id).
"', ".
"private = '".
$private.
"', ".
"description = '".mysql_real_escape_string
($_REQUEST['desc']).
"';");
$last_id =
$this->
LoadSingle("select last_insert_id();");
$freetag->
tag_object($tagger_id,
$last_id['last_insert_id()'],
$tags);
// Check to see if it's time to return to the page from which
// the bookmarklet was called
if(isset($_SESSION['when_done']) &&
($_SESSION['when_done']==
"return")) {
if(isset($_SESSION['referrer'])) {
$referrer =
$_SESSION['referrer'];
unset($_SESSION['go_back']);
unset($_SESSION['uri']);
unset($_SESSION['title']);
unset($_SESSION['referrer']);
unset($_SESSION['when_done']);
$this->
Redirect($referrer);
}
}
// Otherwise, go back to tag/link list view
$this->
Redirect($this->
href().
"&action=list_yours");
} else {
// Display add form
print($this->
FormOpen());
?>
<input type=
"hidden" name=
"action" value=
"add" />
<table>
<tr>
<td align=
"right">Title:</td>
<td><input name=
"title" size=
"40" value=
"<?php echo $values['title']; ?>" /></td>
</tr>
<tr>
<td align=
"right">URI:</td> <td><input name=
"uri" size=
"40" value=
"<?php echo $values['uri']; ?>" /></td> </tr>
<tr>
<td align=
"right">Description:</td>
<td><input name=
"desc" size=
"40"/></td>
</tr>
<tr>
<td align=
"right"></td>
<td><?php
echo $this->
Format("Use blank space between tags, include \"@private\" for private bookmark"); ?></td>
</tr>
<tr>
<td align=
"right">Tags:</td>
<td><input name=
"tags" size=
"40"/></td>
</tr>
<tr>
<td></td>
<td><input type=
"submit" value=
"Add" size=
"40" /></td>
</tr>
</table>
<?php
print($this->
FormClose());
}
}
// Edit entry
if(isset($_REQUEST['action']) &&
($_REQUEST['action']==
"edit") &&
(isset($_REQUEST['object_id']))) {
$object_id =
mysql_real_escape_string($_REQUEST['object_id']);
$obj =
$this->
LoadSingle("select bookmark_id,title,uri,description,wikka_id from ".
$freetag_options['db_name'].
".freetag_bookmarks where bookmark_id = ".
$object_id.
";");
// Is the logged-in user the owner?
if($wikka_id !=
$obj['wikka_id']) {
$this->
Redirect($this->
href().
"&action=list_all");
}
if(isset($_REQUEST['modify']) &&
trim($_REQUEST['tags']) !=
"") {
// Delete all tags, then re-tag
$freetag->
delete_all_object_tags_for_user($tagger_id,
$object_id);
// Private bookmark?
$private =
0;
if(strpos(trim($_REQUEST['tags']),
"@private") !==
false)
$private =
1;
$this->
Query("update ".
$freetag_options['db_name'].
".freetag_bookmarks set ".
"title = '".mysql_real_escape_string
($_REQUEST['title']).
"', ".
"uri = '".mysql_real_escape_string
($this->
cleanUrl($_REQUEST['uri'])).
"', ".
"wikka_id = '".mysql_real_escape_string
($wikka_id).
"', ".
"private = '".
$private.
"', ".
"description = '".mysql_real_escape_string
($_REQUEST['desc']).
"' ".
"where bookmark_id = ".mysql_real_escape_string
($object_id).
" ".
"limit 1;");
$freetag->
tag_object($tagger_id,
$obj['bookmark_id'],
$_REQUEST['tags']);
$this->
Redirect($this->
href().
"&action=list_yours");
}
// Display add form
print($this->
FormOpen());
?>
<input type=
"hidden" name=
"action" value=
"edit" />
<input type=
"hidden" name=
"modify" value=
"yes" />
<input type=
"hidden" name=
"object_id" value=
"<?php print $object_id ?>" />
<table>
<tr>
<td align=
"right">Title:</td>
<td><input name=
"title" size=
"40" value=
"<?php print $obj['title']; ?>"/></td>
</tr>
<tr>
<td align=
"right">URI:</td>
<td><input name=
"uri" size=
"40" value=
"<?php print $obj['uri']; ?>"/></td>
</tr>
<tr>
<td align=
"right">Description:</td>
<td><input name=
"desc" size=
"40" value=
"<?php print $obj['description']; ?>"/></td>
</tr>
<tr>
<td align=
"right"></td>
<td><?php
echo $this->
Format("Use blank space between tags, include \"@private\" for private bookmark"); ?></td>
</tr>
<tr>
<td align=
"right">Tags:</td>
<?php
$tags =
$freetag->
get_tags_on_object($object_id);
$taglist =
"";
foreach($tags as $idx=>
$res) {
$taglist .=
trim($res['raw_tag']).
" ";
}
?>
<td><input name=
"tags" size=
"40" value=
"<?php print $taglist?>"/></td>
</tr>
<tr>
<td></td>
<td><input type=
"submit" value=
"Edit" size=
"40" /></td>
</tr>
</table>
<?php
print($this->
FormClose());
}
// Delete entry
if(isset($_REQUEST['action']) &&
$_REQUEST['action']==
"delete") {
$object_id =
mysql_real_escape_string($_REQUEST['object_id']);
$obj =
$this->
LoadSingle("select bookmark_id,wikka_id from ".
$freetag_options['db_name'].
".freetag_bookmarks where bookmark_id = ".mysql_real_escape_string
($object_id).
";");
// Is the logged-in user the owner?
if($wikka_id !=
$obj['wikka_id']) {
$this->
Redirect($this->
href().
"&action=list_all");
}
// Delete all tags first...
$freetag->
delete_all_object_tags_for_user($tagger_id,
$object_id);
// ...then delete object
$this->
Query("delete from ".
$freetag_options['db_name'].
".freetag_bookmarks where bookmark_id = ".mysql_real_escape_string
($object_id).
" limit 1;");
$this->
Redirect($this->
href().
"&action=list_yours");
}
// List all bookmarks (ordered by most recent)
if(isset($_REQUEST['action']) &&
($_REQUEST['action']==
"list_all")) {
$offset =
0;
if(isset($_REQUEST['offset'])) {
$offset =
mysql_real_escape_string($_REQUEST['offset']);
}
$limit =
25;
if(isset($_REQUEST['limit'])) {
$limit =
mysql_real_escape_string($_REQUEST['limit']);
}
$tag_offset =
0;
if(isset($_REQUEST['tag_offset'])) {
$tag_offset =
mysql_real_escape_string($_REQUEST['tag_offset']);
}
$tag_limit =
100;
if(isset($_REQUEST['tag_limit'])) {
$tag_limit =
mysql_real_escape_string($_REQUEST['tag_limit']);
}
// Output tag cloud
$url_opts =
$this->
href().
"&action=list_all";
$search_term =
NULL;
$header =
"All tags";
if(isset($_REQUEST['search_term'])) {
$search_term =
mysql_real_escape_string($_REQUEST['search_term']);
$header =
"All tags by search";
}
output_tag_cloud
($freetag,
$url_opts,
NULL,
$header,
$tag_offset,
$tag_limit,
$search_term);
$ids =
"";
$tag =
"";
if(isset($_REQUEST['tag']) &&
$_REQUEST['tag'] !=
"") {
$ids =
$freetag->
get_most_recent_objects(NULL,
$_REQUEST['tag'],
$offset,
$limit);
$tag =
mysql_real_escape_string($_REQUEST['tag']);
} else {
$ids =
$freetag->
get_most_recent_objects(NULL,NULL,
$offset,
$limit);
}
foreach($ids as $key=>
$val) {
$tags =
$freetag->
get_tags_on_object($val['object_id']);
$obj =
$this->
LoadSingle("select title,uri,description,wikka_id from ".
$freetag_options['db_name'].
".freetag_bookmarks where bookmark_id = ".
$val['object_id'].
" and private = 0;");
if(!
isset($obj)) {
continue;
}
print "<div class=\"bookmark_block\">\n";
print "<div class=\"bookmark_title\"><a href=\"".
$obj['uri'].
"\">".
$obj['title'].
"</a></div>\n";
print "<div class=\"bookmark_box\"><div class=\"bookmark_desc\">".
($obj['description'] ?
$obj['description'] :
" ").
"</div>\n";
$taglist =
"";
$link =
$url_opts.
"&tag_offset=".
$tag_offset.
"&tag_limit=".
$tag_limit;
foreach($tags as $idx=>
$res) {
$temp_tag =
trim($res['tag']);
$taglist .=
"<a href=\"".
$link.
"&tag=".
$temp_tag.
"\">".
$temp_tag.
"</a> ";
}
print $taglist.
"by ".
$obj['wikka_id'].
" (created: ".
$val['tagged_on'].
")\n";
//print "</div><div class=\"clear\"> </div><hr/>";
print "</div></div>\n";
}
// Display pagination links
$obj_count =
0;
$tag_url =
"";
if($tag !=
"") {
$obj_count = count_tagged_objects
(NULL,
$tag,
$this,
$freetag_options,
$freetag);
$tag_url =
"&tag=".
$tag;
} else {
$obj_count = count_objects
(NULL,
$this,
$freetag_options);
}
$prev_offset =
$offset -
$limit;
$prev_url =
"";
if($prev_offset <
0) {
$prev_offset =
0;
}
if($offset >
0) {
$prev_url =
"<a href=\"".
$this->
href().
"&action=list_all&offset=".
$prev_offset.
"&limit=".
$limit.
$tag_url.
"\"><<</a>";
}
$next_offset =
$offset +
$limit;
$next_url =
"";
if($next_offset <
$obj_count -
1) {
$next_url =
"<a href=\"".
$this->
href().
"&action=list_all&offset=".
$next_offset.
"&limit=".
$limit.
$tag_url.
"\">>></a>";
}
print "<div class=\"pagination\">";
print $prev_url.
" ".
$next_url;
print "</div>";
}
// List user bookmarks (ordered by most recent)
if(isset($_REQUEST['action']) &&
($_REQUEST['action']==
"list_yours")) {
$offset =
0;
if(isset($_REQUEST['offset'])) {
$offset =
mysql_real_escape_string($_REQUEST['offset']);
}
$limit =
25;
if(isset($_REQUEST['limit'])) {
$limit =
mysql_real_escape_string($_REQUEST['limit']);
}
$tag_offset =
0;
if(isset($_REQUEST['tag_offset'])) {
$tag_offset =
mysql_real_escape_string($_REQUEST['tag_offset']);
}
$tag_limit =
100;
if(isset($_REQUEST['tag_limit'])) {
$tag_limit =
mysql_real_escape_string($_REQUEST['tag_limit']);
}
// Output tag cloud
$url_opts =
$this->
href().
"&action=list_yours";
$search_term =
NULL;
$header =
"Your tags";
if(isset($_REQUEST['search_term'])) {
$search_term =
mysql_real_escape_string($_REQUEST['search_term']);
$header =
"Your tags by search";
}
output_tag_cloud
($freetag,
$url_opts,
$tagger_id,
$header,
$tag_offset,
$tag_limit,
$search_term);
$ids =
"";
$tag =
"";
if(isset($_REQUEST['tag']) &&
$_REQUEST['tag'] !=
"") {
$ids =
$freetag->
get_most_recent_objects($tagger_id,
$_REQUEST['tag'],
$offset,
$limit);
$tag =
mysql_real_escape_string($_REQUEST['tag']);
} else {
$ids =
$freetag->
get_most_recent_objects($tagger_id,
NULL,
$offset,
$limit);
}
foreach($ids as $key=>
$val) {
$tags =
$freetag->
get_tags_on_object($val['object_id']);
$obj =
$this->
LoadSingle("select title,uri,description,wikka_id from ".
$freetag_options['db_name'].
".freetag_bookmarks where bookmark_id = ".
$val['object_id'].
";");
print "<div class=\"bookmark_block\">\n";
print "<div class=\"bookmark_title\"><a href=\"".
$obj['uri'].
"\">".
$obj['title'].
"</a></div>\n";
print "<div class=\"bookmark_box\"><div class=\"bookmark_desc\">".
($obj['description'] ?
$obj['description'] :
" ").
"</div>\n";
print " <a href=\"".
$this->
href().
"&action=edit&object_id=".
$val['object_id'].
"\">edit</a>";
print "|";
print "<a href=\"".
$this->
href().
"&action=delete&object_id=".
$val['object_id'].
"\">delete</a><br/>";
$taglist =
"";
$link =
$url_opts.
"&tag_offset=".
$tag_offset.
"&tag_limit=".
$tag_limit;
foreach($tags as $idx=>
$res) {
$normtag =
trim($res['tag']);
$rawtag =
trim($res['raw_tag']);
$taglist .=
"<a href=\"".
$link.
"&tag=".
$normtag.
"\">".
$rawtag.
"</a> ";
}
print $taglist.
"by ".
$obj['wikka_id'].
" (created: ".
$val['tagged_on'].
")\n";
//print "<div class=\"clear\"> </div><hr/>";
print "</div></div>\n";
}
// Display pagination links
$obj_count =
0;
$tag_url =
"";
if($tag !=
"") {
$obj_count = count_tagged_objects
($wikka_id,
$tag,
$this,
$freetag_options,
$freetag);
$tag_url =
"&tag=".
$tag;
} else {
$obj_count = count_objects
($wikka_id,
$this,
$freetag_options);
}
$prev_offset =
$offset -
$limit;
$prev_url =
"";
if($prev_offset <
0) {
$prev_offset =
0;
}
if($offset >
0) {
$prev_url =
"<a href=\"".
$this->
href().
"&action=list_yours&offset=".
$prev_offset.
"&limit=".
$limit.
$tag_url.
"\"><<</a>";
}
$next_offset =
$offset +
$limit;
$next_url =
"";
if($next_offset <
$obj_count -
1) {
$next_url =
"<a href=\"".
$this->
href().
"&action=list_yours&offset=".
$next_offset.
"&limit=".
$limit.
$tag_url.
"\">>></a>";
}
print "<div class=\"center\">";
print $prev_url.
" ".
$next_url;
print "</div>";
}
?>