< 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.++ - ++[[http://wikkawiki.org/BookmarkManager?show_comments=1&showall=1#comment_4505 | Move markup to their own div tags]]++ - ++[[http://wikkawiki.org/BookmarkManager?show_comments=1&showall=1#comment_4507 | 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 [[http://code.google.com/p/freetag/ | 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** %%(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) * @copyright Copyright (c) 2006, Brian Koontz * @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 "href()."&action=list_all"."\">List all (".$all_obj_count.") | ". "href()."&action=list_yours"."\">List yours (".$your_obj_count.") | ". "href()."&action=add"."\">Add". $this->FormOpen(). "". "Search: ". "". "Tags". "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()); ?>
Title:
URI:
Description:
Format("Use blank space between tags, include \"@private\" for private bookmark"); ?>
Tags:
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()); ?> get_tags_on_object($object_id); $taglist = ""; foreach($tags as $idx=>$res) { $taglist .= trim($res['raw_tag'])." "; } ?>
Title:
URI:
Description:
Format("Use blank space between tags, include \"@private\" for private bookmark"); ?>
Tags:
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 "
\n"; print "\n"; print "
".($obj['description'] ? $obj['description'] : " ")."
\n"; $taglist = ""; $link = $url_opts."&tag_offset=".$tag_offset."&tag_limit=".$tag_limit; foreach($tags as $idx=>$res) { $temp_tag = trim($res['tag']); $taglist .= "".$temp_tag." "; } print $taglist."by ".$obj['wikka_id']." (created: ".$val['tagged_on'].")\n"; //print "

"; print "
\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 = "href()."&action=list_all&offset=".$prev_offset."&limit=".$limit.$tag_url."\"><<"; } $next_offset = $offset + $limit; $next_url = ""; if($next_offset < $obj_count - 1) { $next_url = "href()."&action=list_all&offset=".$next_offset."&limit=".$limit.$tag_url."\">>>"; } print "
"; print $prev_url." ".$next_url; print "
"; } // 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 "
\n"; print "\n"; print "
".($obj['description'] ? $obj['description'] : " ")."
\n"; print " href()."&action=edit&object_id=".$val['object_id']."\">edit"; print "|"; print "href()."&action=delete&object_id=".$val['object_id']."\">delete
"; $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 .= "".$rawtag." "; } print $taglist."by ".$obj['wikka_id']." (created: ".$val['tagged_on'].")\n"; //print "

"; print "
\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 = "href()."&action=list_yours&offset=".$prev_offset."&limit=".$limit.$tag_url."\"><<"; } $next_offset = $offset + $limit; $next_url = ""; if($next_offset < $obj_count - 1) { $next_url = "href()."&action=list_yours&offset=".$next_offset."&limit=".$limit.$tag_url."\">>>"; } print "
"; print $prev_url." ".$next_url; print "
"; } ?> %% - Save the following file as ##libs/Wikka.freetag.lib.php##: **Wikka.freetag.lib.php** %%(php) * @copyright Copyright (c) 2006, Brian Koontz * @name Wikka.freetag.lib.php * @package Actions {@link http://www.wikkawiki.org/BookmarkManager} * @filesource * @license http://www.gnu.org/copyleft/gpl.html * @since Wikka 1.1.6.1 * @version $Id: Wikka.freetag.lib.php,v 1.3 2006/08/10 04:03:17 brian Exp brian $ * */ /*********************************************************************/ /* 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; } $wikka_id = mysql_real_escape_string($wikka_id); $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! * * NOTES: * Set $tagger_id to NULL for all tags (except those marked * private) * * If $search_term is not NULL, $tag_offset will return the offset * of the first matching term */ function output_tag_cloud($freetag,$tag_page_url,$tagger_id=NULL,$header=NULL,$tag_offset=0,$tag_limit=100,$search_term=NULL) { // Output tag cloud $tag_count = $freetag->count_unique_tags($tagger_id,$search_term); print "
"; if($header) { print $header." (".$tag_count."):
"; } print $freetag->get_tag_cloud_html_with_limits($tag_offset,$tag_limit,10,20,'px','cloud_tag',$tag_page_url,$tagger_id,$search_term); // Display pagination links $tag_url = ""; $prev_offset = $tag_offset - $tag_limit; $prev_url = ""; if($prev_offset < 0) { $prev_offset = 0; } $search_tag = ""; if(isset($search_term)) { $search_tag = "&search_term=".$search_term; } if($tag_offset > 0) { $prev_url = "<<"; } $next_offset = $tag_offset + $tag_limit; $next_url = ""; if($next_offset < $tag_count - 1) { $next_url = ">>"; } print "
"; print $prev_url." ".$next_url; print "
"; print "
"; // print "
"; } /********************************************************************/ /** * count_objects() * * Returns a count of objects (bookmarks, links, etc.) * * NOTE: Set $wikka_id to NULL for all objects (except those marked * private) */ function count_objects($wikka_id, $obj, $freetag_options) { if(isset($wikka_id)) { $wikka_sql = "AND wikka_id = '".mysql_real_escape_string($wikka_id)."'"; } else { $wikka_sql = "AND private = 0"; } $res = $obj->LoadSingle("select COUNT(*) as count from ".$freetag_options['db_name'].".freetag_bookmarks where 1 ".$wikka_sql.";"); $count = $res['count']; return $count; } /********************************************************************/ /** * count_tagged_objects() * * Returns a count of tagged objects (bookmarks, links, etc.) * * NOTE: Set $wikka_id to NULL for all taggedobjects regardless of * owner (except those marked private) */ function count_tagged_objects($wikka_id, $tag, $obj, $freetag_options, $freetag) { $num_objs = count_objects($wikka_id, $obj, $freetag_options); $tagger_id = wikka_id_to_tagger_id($wikka_id, $obj, $freetag_options); $ids = $freetag->get_most_recent_objects($tagger_id, $tag, 0, $num_objs); return count($ids); } /********************************************************************/ /** * save_to_current_session() * * Save various fields to the current session * * Input: Associative array of session tags->values * * Return: Name of session * */ function save_to_current_session($values) { foreach($values as $tag=>$value) { $_SESSION[$tag] = $value; } return $_SESSION['name']; } /********************************************************************/ ?> %% - Save the following file as ##libs/Wikka.freetag.class.php##: **Wikka.freetag.class.php** %%(php) * * 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 * *********************************************************************/ // Check for freetag library $freetag_lib = '3rdparty/plugins/freetag/freetag.class.php'; if(!is_file($freetag_lib)) { print("

".$this->Format("Can't find $freetag_lib!")."

\n"); die(); } include_once($freetag_lib); /********************************************************************/ /* Freetag subclass (defines additional support methods) */ /********************************************************************/ class wikka_freetag extends freetag { function wikka_freetag($freetag_options) { parent::freetag($freetag_options); $this->_normalized_valid_chars = '@_a-zA-Z0-9'; } /******************************************************************* * get_tag_cloud_html_with_limits * * Extension to get_tag_cloud_html() that permits specifying * an offset and limit (useful for presenting more tags than * can be displayed at one time). * * See get_tag_cloud_html() comments for description of this * function. * * @param int Specify starting record (default: 0). Will be set to * offset of first matching term if $search_term is not NULL * @param int The maximum number of tags to return. (default: 100) * @param int The minimum font size in the cloud. (default: 10) * @param int The maximum number of tags to return. (default: 20) * @param string The "units" for the font size (i.e. 'px', 'pt', * 'em') (default: px) * @param string The class to use for all spans in the cloud. * (default: cloud_tag) * @param string The tag page URL (default: /tag/) * @param int The tagger ID (default: NULL) * @param string Optional search term (default: NULL) * * @return string Returns an HTML snippet that can be used * directly as a tag cloud. */ function get_tag_cloud_html_with_limits($offset = 0, $limit = 100, $min_font_size = 10, $max_font_size = 20, $font_units = 'px', $span_class = 'cloud_tag', $tag_page_url = '/tag/', $tagger_id = NULL, $search_term = NULL) { $tag_list = $this->get_tag_cloud_tags_with_limits($offset, $limit, $tagger_id,$search_term); // Get the maximum qty of tagged objects in the set $max_qty = max(array_values($tag_list)); // Get the min qty of tagged objects in the set $min_qty = min(array_values($tag_list)); // For ever additional tagged object from min to max, we add // $step to the font size. $spread = $max_qty - $min_qty; if (0 == $spread) { // Divide by zero $spread = 1; } $step = ($max_font_size - $min_font_size)/($spread); // Since the original tag_list is alphabetically ordered, // we can now create the tag cloud by just putting a span // on each element, multiplying the diff between min and qty // by $step. $cloud_html = ''; $cloud_spans = array(); foreach ($tag_list as $tag => $qty) { //if(strpos($tag, "private") !== false) continue; $size = $min_font_size + ($qty - $min_qty) * $step; $search_tag = ""; if(isset($search_term)) { $search_tag = "&search_term=".$search_term; } $cloud_span[] = '' . htmlspecialchars(stripslashes($tag)) . ''; } // Remove
from the following line to get a "tag // cloud" rather than a "tag list" $cloud_html = join("
\n ", $cloud_span); return $cloud_html; } /* * get_tag_cloud_tags_with_limits * * Extension to get_tag_cloud_tags() that permits specifying * an offset and limit (useful for presenting more tags than * can be displayed at one time). Also, tags are returned * in true alphanumeric sequence across the entire record set, * rather than across the most popular tags. * * See get_tag_cloud_tags() comments for description of this * function. * @param int Specify starting record (default: 0). Will be set to * offset of first matching tag if $search_term is not NULL. * @param int The maximum number of tags to return (default: 100) * @param int Tag owner (default: NULL) * @param string Optional search term (default: NULL) * * @return array Returns an array where the keys are normalized * tags, and the * values are numeric quantity of objects tagged with that tag. */ function get_tag_cloud_tags_with_limits($offset = 0, $limit = 100, $tagger_id = NULL, $search_term = NULL) { $db = $this->db; $limit_sql = "LIMIT ".$offset.", ".$limit; if(isset($tagger_id) && ($tagger_id > 0)) { $tagger_sql = "AND tagger_id = $tagger_id"; } else { $tagger_sql = ""; } $search_sql = ""; if(isset($search_term)) { $search_sql = "AND tag LIKE \"".$search_term."%\""; //$limit_sql = "LIMIT ".$limit; //$offset = 0; } $prefix = $this->_table_prefix; $sql = "SELECT tag, COUNT(object_id) AS quantity FROM ${prefix}freetags INNER JOIN ${prefix}freetagged_objects ON (${prefix}freetags.id = tag_id) WHERE 1 $tagger_sql $search_sql GROUP BY tag ORDER BY tag ASC $limit_sql "; $rs = $db->Execute($sql) or die("Syntax Error: $sql"); while(!$rs->EOF) { $retarr[$rs->fields['tag']] = $rs->fields['quantity']; $rs->MoveNext(); if($search_term) { //$offset++; } } ksort($retarr); return $retarr; } /** * count_unique_tags * Returns the total number of unique tags in the system. * * @param int The unique ID of the person to restrict results to. * @param string Optional search string (default: NULL) * * @return int Returns the count */ function count_unique_tags($tagger_id = NULL, $search_term = NULL) { $db = $this->db; if(isset($tagger_id) && ($tagger_id > 0)) { $tagger_sql = "AND tagger_id = $tagger_id"; } else { $tagger_sql = ""; } $search_sql = ""; if(isset($search_term)) { $search_sql = "AND tag LIKE \"".$search_term."%\""; //$limit_sql = "LIMIT ".$limit; //$offset = 0; } $prefix = $this->_table_prefix; $sql = "SELECT DISTINCT tag, tag_id, COUNT(*) as count FROM ${prefix}freetags INNER JOIN ${prefix}freetagged_objects ON (id = tag_id) $tagger_sql $search_sql GROUP BY NULL "; $rs = $db->Execute($sql) or die("Syntax Error: $sql"); if(!$rs->EOF) { return $rs->fields['count']; } return false; } } /********************************************************************/ ?> %% - Adjust the DB connection parameters for your own installation (only necessary if you deviate from the DB instructions above) - Create the CSS stylesheet for the action, ##css/bookmarkmgr.css##: %%(php) .bookmark_floatr { float: right; text-align: left; width: 10%; margin-left: 15px; padding: 4px; background: #EEE; border: 1px solid #CCC; line-height: 95%; } .bookmark_box { width: 85%; font-size: 85%; padding: 0px 5px; color: #666; background: #EEE; border: 1px solid #CCC; } .bookmark_block { width: 85%; border-bottom: 3px solid #DDD; padding: 8px; } .bookmark_desc { font-size: 100%; font-weight: bold; margin: 0px; padding: 0px; } .bookmark_title { font-size: 150%; font-weight: bold; padding: 5px 0px; } .pagination { text-align: center; margin: 20px auto; } %% - In order to use the stylesheet, add the following lines to the files indicated (click [[http://wush.net/trac/wikka/ticket/246 | here]] for a justification as to why these changes are necessary to the core): **wikka.config.php:** %%(php) 'additional_stylesheets' => 'bookmarkmgr.css', %% **actions/header.php:** %%(php) // Locate this line... " /> // ...and add the following codeblock: GetConfigValue("additional_stylesheets") != NULL) { $sheets = preg_split("/[\s]+/", $this->GetConfigValue("additional_stylesheets")); foreach($sheets as $sheet) { echo "\n"; } } ?> %% - Add the ""{{bookmarks}}"" action code to a new page ==Bookmarklet support== BookmarkManager now supports "bookmarklets," which is a small snippet of Javascript saved as a browser bookmark that allows you to bookmark a webpage "on the fly." The following patch must be applied to ##actions/usersettings.php## if you want to restrict bookmarklets to registered users (recommended): %%(sh) =================================================================== RCS file: RCS/usersettings.php,v retrieving revision 1.1 diff -u -r1.1 usersettings.php --- usersettings.php 2006/06/18 06:03:03 1.1 +++ usersettings.php 2006/06/24 06:40:13 @@ -1,5 +1,7 @@ LoadUser($_POST['name'])) { @@ -349,7 +358,11 @@ break; default: $this->SetUser($existingUser); - $this->Redirect($this->href()); + if($referrer == null) + $this->Redirect($this->href()); + else { + $this->Redirect($referrer); + } } } else // otherwise, proceed to registration @@ -417,7 +430,11 @@ // log in $this->SetUser($this->LoadUser($name)); - $this->Redirect($this->href('', '', 'registered=true')); + if($referrer == null) + $this->Redirect($this->href('', '', 'registered=true')); + else { + $this->Redirect($referrer); + } } } } @@ -542,4 +559,4 @@ FormClose()); } %% Save the following as a bookmark in your browser: %% javascript:location.href='http://your.site.com/wiki/wikka.php?wakka=BookmarkPage&action=add&uri='+escape(location.href)+'&title='+encodeURIComponent(document.title)+'&wikka_bookmarklet=1' (Don't forget to change "your.site.com" as appropriate for your installation!) %% TODO: Implement as a popup: %% post bookmarklet (with popup): javascript:void(open('http://de.lirio.us/rubric/post?uri='+escape(location.href)+'&title='+encodeURIComponent(document.title)+'&when_done=close','Rubric','toolbar=no,width=700,height=325,scrollbars')); %% ==Other stuff== - [[BookmarkManagerImportScripts | Import scripts]] ==Category== CategoryDevelopmentDiscussion CategoryDevelopmentActions CategoryUserContributions