Revision [14368]
This is an old revision of BookmarkManager made by BrianKoontz on 2006-05-26 12:34:26.
Bookmark Manager
An integrated bookmark manager in the spirit of de.lirio.us.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
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 have a beta up and running here, and would appreciate your comments and suggestions! Keep in mind this is still quite rough around the edges, but I was aiming more towards proof-of-concept. I think something like this would be a cool addition (as a 100% modular plugin) to Wikka...
TODO
- This code is most likely not yet safe for a production environment! There is still some user data validation that needs to be done.
- 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?
- 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
Installation
- Install a copy of Freetag in 3rdparty/plugins Check for freetag library
$freetag_lib = '3rdparty/plugins/freetag/freetag.class.php';
if(!is_file($freetag_lib)) {
print("<br/><br/><div class=\"error\">".$this->Format("Can't find $freetag_lib!")."<br/><br/>\n");
die();
}
include_once($freetag_lib);
$freetag_options = array(
'db_user' => 'root',
'db_pass' => ,
'db_host' => 'localhost',
'db_name' => 'freetag',
'PCONNECT' => true,
);
class wikka_freetag extends freetag {
function wikka_freetag($freetag_options) {
parent::freetag($freetag_options);
}
function get_most_recent_objects($tagger_id = NULL, $offset = 0, $limit = 25) {
$db = $this->db;
if(isset($tagger_id)) {
$tagger_sql = "AND tagger_id = $tagger_id";
} else {
$tagger_sql = ;
}
$prefix = $this->_table_prefix;
$sql = "SELECT DISTINCT object_id, tagged_on FROM
${prefix}freetagged_objects
WHERE 1
$tagger_sql
ORDER BY tagged_on DESC
LIMIT $offset, $limit ";
$rs = $db->Execute($sql) or die("Syntax Error: $sql");
$retarr = array();
while(!$rs->EOF) {
$retarr[] = array(
'object_id' => $rs->fields['object_id'],
'tagged_on' => $rs->fields['tagged_on']
);
$rs->MoveNext();
}
return $retarr;
}
}
/********************************************************************/
/*********************************************************************/
/* Helper functions */
/*********************************************************************/
/* wikka_id_to_tagger_id
*
* Converts Wikka id (returned from GetUserName()) to
* tagger_id. Adds Wikka id to table if not already present.
* Maps NULL -> NULL.
*
*/
function wikka_id_to_tagger_id ($wikka_id, $obj, $freetag_options) {
if(!isset($wikka_id)) {
return NULL;
}
$res = $obj->LoadSingle("select tagger_id from ".$freetag_options['db_name'].".freetag_wikka_id_map where wikka_id = '".$wikka_id."';");
$tagger_id = $res['tagger_id'];
if(!$tagger_id) {
$obj->Query("insert ".$freetag_options['db_name'].".freetag_wikka_id_map set "."wikka_id = '".$wikka_id."';");
$res = $obj->LoadSingle("select last_insert_id();");
$tagger_id = $res['last_insert_id()'];
}
return $tagger_id;
}
/********************************************************************/
/* output_tag_cloud
*
* Create a cloud of tags!
*
* NOTE: Set $tagger_id to NULL for all tags (except those marked
* private)
*/
function output_tag_cloud($freetag,$tag_page_url,$tagger_id=NULL) {
// Output tag cloud
print " ";
}
/********************************************************************/
echo "
";
print
$freetag->get_tag_cloud_html(100,10,20,'px','cloud_tag',$tag_page_url,$tagger_id);
print "
";
print "BookmarkTest
"; echo ".$this->href()."&action=list_all"."\">List all</a> | ".
"<a href=\.$this->href()."&action=list_yours"."\">List yours
"; $wikka_id = $this->GetUserName(); $tagger_id = wikka_id_to_tagger_id($wikka_id, $this, $freetag_options); $freetag = new wikka_freetag($freetag_options); // Add new entry to DB if(isset($_REQUEST['action']) && ($_REQUEST['action']=="add") && trim($_POST['tags']) != ) {
"; $wikka_id = $this->GetUserName(); $tagger_id = wikka_id_to_tagger_id($wikka_id, $this, $freetag_options); $freetag = new wikka_freetag($freetag_options); // Add new entry to DB if(isset($_REQUEST['action']) && ($_REQUEST['action']=="add") && trim($_POST['tags']) != ) {
Private bookmark?
$private = 0;
if(strpos(trim($_POST['tags']), "@private") ! false)
false)
$private = 1;
$this->Query("insert ".$freetag_options['db_name'].".freetag_bookmarks set ".
"title = '".mysql_real_escape_string($_POST['title'])."', ".
"uri = '".mysql_real_escape_string($this->cleanUrl($_POST['uri']))."', ".
"wikka_id = '".$wikka_id."', ".
"private = '".$private."', ".
"description = '".mysql_real_escape_string($_POST['desc'])."';");
$last_id = $this->LoadSingle("select last_insert_id();");
$freetag->tag_object($tagger_id, $last_id['last_insert_id()'], $_POST['tags']);
}
List all bookmarks (ordered by most recent)
if(isset($_REQUEST['action']) && ($_REQUEST['action']
"list_all")) {
Output tag cloud
$url_opts = $this->href()."&action=get_tag&tag=";
output_tag_cloud($freetag,$url_opts);
$ids = $freetag->get_most_recent_objects();
foreach($ids as $key=>$val) {
$tags = $freetag->get_tags_on_object($val['object_id']);
$objs = $this->LoadAll("select title,uri,description,wikka_id from ".$freetag_options['db_name'].".freetag_bookmarks where bookmark_id = ".$val['object_id']." and private = 0;");
foreach($objs as $idx=>$obj) {
print "<a href=\.$obj['uri']."\">".$obj['title']."
"; print "
"; print "
foreach($tags as $idx=>$res) {
$taglist .= trim($res['tag'])." ";
}
print $taglist."by ".$obj['wikka_id']." (created: ".$val['tagged_on'].")</div>";
print "<div class=\"clear\"> </div>";
}
}
}
List user bookmarks (ordered by most recent)
if(isset($_REQUEST['action']) && ($_REQUEST['action']"list_yours")) {
"list_yours")) {
Output tag cloud
$url_opts =
$this->href()."&action=get_tag&tagger_id=".$tagger_id."&tag=";
output_tag_cloud($freetag,$url_opts,$tagger_id);
$ids = $freetag->get_most_recent_objects($tagger_id);
foreach($ids as $key=>$val) {
$tags = $freetag->get_tags_on_object($val['object_id']);
foreach($objs as $idx=>$obj) {
print "<a href=\.$obj['uri']."\">".$obj['title']."
"; print "
"; print "
".$obj['description']."
"; $taglist =
;"; $taglist =
foreach($tags as $idx=>$res) {
$taglist .= trim($res['raw_tag'])." ";
}
print $taglist."by ".$obj['wikka_id']." (created: ".$val['tagged_on'].")</div>";
print "<div class=\"clear\"> </div>";
}
}
}
List bookmarks with specific tags (ordered by most recent)
if(isset($_REQUEST['action']) && ($_REQUEST['action']
"get_tag")) {
if(isset($_REQUEST['tag'])) {
$valid_id = NULL;
if(isset($_REQUEST['tagger_id']) && ($tagger_id $_REQUEST['tagger_id'])) {
$_REQUEST['tagger_id'])) {
$valid_id = $tagger_id;
}
Output tag cloud
if($valid_id) {
$url_opts = $this->href()."&action=get_tag&tagger_id=".$valid_id."&tag=";
} else {
$url_opts = $this->href()."&action=get_tag&tag=";
}
output_tag_cloud($freetag,$url_opts,$valid_id);
$ids = $freetag->get_objects_with_tag($_REQUEST['tag'],0,100,$valid_id);
foreach($ids as $id) {
$tags = $freetag->get_tags_on_object($id);
$private = ;
if(!$valid_id) {
$private = " AND private = 0";
}
foreach($objs as $idx=>$obj) {
print "<a href=\.$obj['uri']."\">".$obj['title']."
"; print "
"; print "
".$obj['description']."
"; $taglist =
;"; $taglist =
$tag_type = "raw_tag";
if(!$valid_id)
$tag_type = "tag";
foreach($tags as $idx=>$res) {
$taglist .= trim($res[$tag_type])." ";
}
print $taglist."by ".$obj['wikka_id']." (created: ".$val['tagged_on'].")</div>";
print "<div class=\"clear\"> </div>";
}
}
}
}
?>
<?php print($this->FormOpen()); ?>
<input type="hidden" name="action" value="add" />
<table>
<tr>
<td align="right">Title:</td>
<td><input name="title" size="40"/></td>
</tr>
<tr>
<td align="right">URI:
<td><input name="uri" size="40"/></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()); ?>
- Adjust the DB connection parameters for your own installation - (Optional) After line 918 in ##freetag.class.php##, add the following line to prevent @private tags from cluttering up the landscape:
foreach ($tag_list as $tag => $qty) {
Add the following line:
if(strpos($tag, "private") !
false) continue;
$size = $min_font_size + ($qty - $min_qty) * $step;
- Add the {{bookmarks}} handler code to a new page
"; $taglist =