diff --git a/data/System/TagsPluginTagEntrySearch.txt b/data/System/TagsPluginTagEntrySearch.txt new file mode 100644 index 0000000..2c896a9 --- /dev/null +++ b/data/System/TagsPluginTagEntrySearch.txt @@ -0,0 +1,7 @@ +%META:TOPICINFO{author="BaseUserMapping_333" date="1250720173" format="1.1" reprev="1.1" version="1.1"}% +%TAGSEARCH{ + query="tag" + tag="%URLPARAM{"q"}%%" + format="$tag" + sep="$n" +}% diff --git a/data/System/TagsPluginViewsTagSearch.txt b/data/System/TagsPluginViewsTagSearch.txt new file mode 100644 index 0000000..cae5392 --- /dev/null +++ b/data/System/TagsPluginViewsTagSearch.txt @@ -0,0 +1,26 @@ +%META:TOPICINFO{author="BaseUserMapping_333" date="1250703240" format="1.1" reprev="1.4" version="1.4"}% + + +---+++ list of everyone's tags on the current topic +%TAGSEARCH{ web="%BASEWEB%" topic="%BASETOPIC%" }% + +---+++ list of %NOP%%WIKINAME%'s tags on the current topic +%TAGSEARCH{ web="%BASEWEB%" topic="%BASETOPIC%" user="%WIKINAME%" }% + +---+++ tag cloud of everyone's tags +%TAGCLOUD{ terms="$percntTAGSEARCH{ query=\"tag\" format=\"$tag:$count\" sep=\", \" }$percnt" }% + +---+++ tag cloud of everyone's tags on topic ?mytopic=%URLPARAM{"mytopic" default="undef"}% +%TAGCLOUD{ terms="$percntTAGSEARCH{ query=\"tag\" topic=\"$percntURLPARAM{mytopic}$percnt\" format=\"$tag:$count\" sep=\", \" }$percnt" }% + +---+++ List of topics tagged with ?tag=%URLPARAM{tag}% (inverse tag lookup) +%TAGSEARCH{ query="topic" tag="%URLPARAM{tag}%" }% + +---+++ Complete list by topics +%TAGSEARCH{ + query="topic" + header="|*Tag*|*Topic*|*User*|$n" + format="| $tag | [[$item][$item]] | $user |" + sep="$n" +}% + diff --git a/lib/Foswiki/Plugins/TagsPlugin.pm b/lib/Foswiki/Plugins/TagsPlugin.pm index 1670ba1..bb68bc2 100644 --- a/lib/Foswiki/Plugins/TagsPlugin.pm +++ b/lib/Foswiki/Plugins/TagsPlugin.pm @@ -21,7 +21,7 @@ use vars qw( $VERSION $RELEASE $SHORTDESCRIPTION $debug $pluginName $NO_PREFS_IN_TOPIC $doneLoadTemplate ); $VERSION = '$Rev$'; $RELEASE = 'Foswiki-1.0.0'; -$SHORTDESCRIPTION = ' Full strength Tagging system '; +$SHORTDESCRIPTION = 'Full strength Tagging system '; $NO_PREFS_IN_TOPIC = 1; $pluginName = 'TagsPlugin'; @@ -45,12 +45,12 @@ sub initPlugin { return 0; } - my $setting = $Foswiki::cfg{Plugins}{TagsPlugin}{ExampleSetting} || 0; - $debug = $Foswiki::cfg{Plugins}{TagsPlugin}{Debug} || 0; + # $debug = $Foswiki::cfg{Plugins}{TagsPlugin}{Debug} || 0; - Foswiki::Func::registerTagHandler( 'TAGLIST', \&_TAGLIST ); - Foswiki::Func::registerTagHandler( 'TAGENTRY', \&_TAGENTRY ); - Foswiki::Func::registerTagHandler( 'TAGCLOUD', \&_TAGCLOUD ); + Foswiki::Func::registerTagHandler( 'TAGLIST', \&_TAGLIST ); + Foswiki::Func::registerTagHandler( 'TAGENTRY', \&_TAGENTRY ); + Foswiki::Func::registerTagHandler( 'TAGCLOUD', \&_TAGCLOUD ) if ( defined($Foswiki::cfg{TagsPlugin}{EnableTagCloud}) && $Foswiki::cfg{TagsPlugin}{EnableTagCloud} ); + Foswiki::Func::registerTagHandler( 'TAGSEARCH', \&_TAGSEARCH ); Foswiki::Func::registerRESTHandler( 'tag', \&tagCall ); Foswiki::Func::registerRESTHandler( 'untag', \&untagCall ); @@ -99,6 +99,26 @@ sub afterSaveHandler { return; } +sub afterRenameHandler { + my ( $oldWeb, $oldTopic, $oldAttachment, + $newWeb, $newTopic, $newAttachment ) = @_; + + # ignore attachment renamings + # TODO: we should not ignore web renamings + if ( $oldTopic && $newTopic ) { + my $oldLocation = "$oldWeb.$oldTopic"; + my $newLocation = "$newWeb.$newTopic"; + + my $db = new Foswiki::Contrib::DbiContrib; + my $statement = sprintf( 'UPDATE %s SET %s = ? WHERE %s = ? AND %s = ?', qw(Items item_name item_name item_type) ); + my $rowCount = $db->dbInsert( $statement, $newLocation, $oldLocation, "topic" ); + $db->disconnect(); + Foswiki::Func::writeDebug("- ${pluginName}::afterSaveHandler( SQL: $statement, $newLocation, $oldLocation, topic -> $rowCount )"); + } + + return ""; +} + sub _loadTemplate { return if $doneLoadTemplate; $doneLoadTemplate = 1; @@ -267,6 +287,11 @@ sub _TAGCLOUD { return _TAGLIST( $session, $params, $theTopic, $theWeb ); } +sub _TAGSEARCH { + use Foswiki::Plugins::TagsPlugin::TAGSEARCH; + return Foswiki::Plugins::TagsPlugin::TAGSEARCH::do( @_ ); +} + =pod ---++ tagCall($session) -> $text @@ -313,9 +338,9 @@ sub mergeCall { sub getUserId { my $session = $_[0]; - my $user = $_[1]; + my $user_id = $_[1]; - my $FoswikiCuid = $user || $session->{user}; + my $FoswikiCuid = $user_id || $session->{user}; # if ($session->{users}->isAdmin($FoswikiCuid)) { # $FoswikiCuid = '333'; @@ -358,10 +383,12 @@ update the tags for this topic sub updateTopicTags { my ( $item_type, $web, $topic, $user_id ) = @_; - my $session = $Foswiki::Plugins::SESSION; - + use Foswiki::Plugins::TagsPlugin::Tag; - Foswiki::Plugins::TagsPlugin::Tag::do( $item_type, "$web.$topic", $web, $user_id ); + + if ( defined($Foswiki::cfg{TagsPlugin}{EnableWebTags}) && $Foswiki::cfg{TagsPlugin}{EnableWebTags} ) { + Foswiki::Plugins::TagsPlugin::Tag::do( $item_type, "$web.$topic", $web, Foswiki::Func::getCanonicalUserID("AdminUser") ); + } my ( $meta, $text ); if ( $Foswiki::cfg{TagsPlugin}{EnableDataForms} || $Foswiki::cfg{TagsPlugin}{EnableCategories} ) { diff --git a/lib/Foswiki/Plugins/TagsPlugin/Config.spec b/lib/Foswiki/Plugins/TagsPlugin/Config.spec index c3ef34e..6725074 100644 --- a/lib/Foswiki/Plugins/TagsPlugin/Config.spec +++ b/lib/Foswiki/Plugins/TagsPlugin/Config.spec @@ -4,6 +4,10 @@ # setting use to allow you to replace Webs with Tags $Foswiki::cfg{TagsStore}{FilterByTags} = 0; +# **BOOLEAN** +# automatically create a "web" tag on each topic +$Foswiki::cfg{TagsPlugin}{EnableWebTags} = 1; + # **BOOLEAN** # automatically create tags for links to topics ending in Category $Foswiki::cfg{TagsPlugin}{EnableCategories} = 1; @@ -12,6 +16,10 @@ $Foswiki::cfg{TagsPlugin}{EnableCategories} = 1; # automatically create tags for attached DataForms $Foswiki::cfg{TagsPlugin}{EnableDataForms} = 1; +# **BOOLEAN** +# enable the built-in TAGCLOUD macro +$Foswiki::cfg{TagsPlugin}{EnableTagCloud} = 1; + # **STRING** # Name of the TagAdminGroup (which is allowed to delete, rename and merge tags) $Foswiki::cfg{TagsPlugin}{TagAdminGroup} = "AdminGroup"; \ No newline at end of file diff --git a/lib/Foswiki/Plugins/TagsPlugin/DEPENDENCIES b/lib/Foswiki/Plugins/TagsPlugin/DEPENDENCIES index 2bf3f43..88f2274 100644 --- a/lib/Foswiki/Plugins/TagsPlugin/DEPENDENCIES +++ b/lib/Foswiki/Plugins/TagsPlugin/DEPENDENCIES @@ -1,3 +1,6 @@ # Dependencies for TagsPlugin Geo::GeoNames,,cpan,Optional Foswiki::Contrib::DbiContrib,,perl,Required +Foswiki::Contrib::FamFamFamContrib,,perl,Optional +Foswiki::Plugin::JQueryPlugin,,perl,Optional +Foswiki::Plugin::TagCloudPlugin,,perl,Optional diff --git a/lib/Foswiki/Plugins/TagsPlugin/MANIFEST b/lib/Foswiki/Plugins/TagsPlugin/MANIFEST index ca0f394..3717634 100644 --- a/lib/Foswiki/Plugins/TagsPlugin/MANIFEST +++ b/lib/Foswiki/Plugins/TagsPlugin/MANIFEST @@ -1,7 +1,15 @@ # Release manifest for TagsPlugin data/System/TagsPlugin.txt 0644 Documentation data/System/TagsPluginViews.txt 0644 Documentation +data/System/TagsPluginTagEntrySearch.txt 0644 Topic +data/System/TagsPluginViewsTagSearch.txt 0644 Topic lib/Foswiki/Plugins/TagsPlugin.pm 0644 Perl module +lib/Foswiki/Plugins/TagsPlugin/Tag.pm 0644 Perl module +lib/Foswiki/Plugins/TagsPlugin/Untag.pm 0644 Perl module +lib/Foswiki/Plugins/TagsPlugin/Delete.pm 0644 Perl module +lib/Foswiki/Plugins/TagsPlugin/Rename.pm 0644 Perl module +lib/Foswiki/Plugins/TagsPlugin/Merge.pm 0644 Perl module +lib/Foswiki/Plugins/TagsPlugin/TAGSEARCH.pm 0644 Perl module templates/tagsplugin.tmpl templates/view.tagsplugin.tmpl diff --git a/lib/Foswiki/Plugins/TagsPlugin/Merge.pm b/lib/Foswiki/Plugins/TagsPlugin/Merge.pm index 892cea0..86d1f80 100644 --- a/lib/Foswiki/Plugins/TagsPlugin/Merge.pm +++ b/lib/Foswiki/Plugins/TagsPlugin/Merge.pm @@ -122,7 +122,7 @@ sub do { my $tag_id2; $statement = sprintf( 'SELECT %s from %s WHERE %s = ? AND %s = ?', qw( item_id Items item_name item_type) ); - my $arrayRef = $db->dbSelect( $statement, $tag2, 'tag' ); + $arrayRef = $db->dbSelect( $statement, $tag2, 'tag' ); if ( defined( $arrayRef->[0][0] ) ) { $tag_id2 = $arrayRef->[0][0]; } diff --git a/lib/Foswiki/Plugins/TagsPlugin/TAGSEARCH.pm b/lib/Foswiki/Plugins/TagsPlugin/TAGSEARCH.pm new file mode 100644 index 0000000..cfa0224 --- /dev/null +++ b/lib/Foswiki/Plugins/TagsPlugin/TAGSEARCH.pm @@ -0,0 +1,222 @@ +# This script Copyright +# (c) 2009 Oliver Krueger, (wiki-one.net) +# and distributed under the GPL (see below) +# +# 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 License for more details, published at +# http://www.gnu.org/copyleft/gpl.html +# +# Author(s): Oliver Krueger + +package Foswiki::Plugins::TagsPlugin::TAGSEARCH; + +use strict; +use warnings; +use Error qw(:try); + +=begin TML + +---++ do( $session, $params, $topic, $web ) +Taghandler for TAGSEARCH. + +Return: + Formatted search result. +=cut + +sub do { + my ( $session, $params, $topic, $web ) = @_; + + my $theHeader = $params->{header} || ''; + my $theSep = $params->{separator} || $params->{sep} || ', '; + my $theFooter = $params->{footer} || ''; + my $theUser = $params->{user} || 'all'; + my $theWeb = $params->{web} || 'all'; + my $theTag = $params->{tag} || 'all'; + my $theTopic = $params->{topic} || ''; + my $theQuery = $params->{query} || 'tag'; + my $theFormat = $params->{format}; + + # determine default format based on query type + unless( $theFormat ) { + if ( $theQuery eq "user" ) { + $theFormat = '$user'; + } elsif ( $theQuery eq "topic" ) { + $theFormat = '[[$item][$topic]]'; + } else { + $theFormat = '$tag'; + }; + }; + + my $isTagAdmin = Foswiki::Func::isGroupMember($Foswiki::cfg{TagsPlugin}{TagAdminGroup} || "AdminGroup") ? 1 : 0; + + my $output = ''; + my $statement = ''; + my @whereClauses; + + my $db = new Foswiki::Contrib::DbiContrib; + + # resolve the cUID from the database and exit with "" if it does not exist + # + if ( lc($theUser) ne 'all' ) { + my $cuid; + my $statement = + sprintf( 'SELECT %s from %s WHERE %s = ? ', qw( CUID Users FoswikicUID) ); + my $arrayRef = $db->dbSelect( $statement, Foswiki::Func::getCanonicalUserID( $theUser ) ); + if ( defined( $arrayRef->[0][0] ) ) { + $cuid = $arrayRef->[0][0]; + } + return '' unless ( defined($cuid) ); + push @whereClauses, " i2t.user_id = '$cuid' "; + } + + # filter for webs + # + if ( $theWeb ne 'all' ) { + my @webs = split( /,/, $theWeb ); + my @clauses; + foreach my $w (@webs) { + push @clauses, " i.item_name like '$w%' "; + } + push @whereClauses, join( ' OR ', @clauses ); + } + + # filter for topics + # + if ( $theTopic ) { + my @topics = split( /,/, $theTopic ); + my @clauses; + foreach my $t (@topics) { + push @clauses, " i.item_name like '%.$t' "; + } + push @whereClauses, join( ' OR ', @clauses ); + } + + # filter for tags + # + if ( lc($theTag) ne "all" ) { + my @tags = split( /,/, $theTag ); + my @clauses; + foreach my $t (@tags) { + push @clauses, " t.item_name like '$t' "; + } + push @whereClauses, join( ' OR ', @clauses ); + } + + # build the WHERE clause + # + push @whereClauses, " i.item_type = 'topic' "; + my $where = join( ' AND ', @whereClauses ); + $where = 'WHERE ' . $where if ( $#whereClauses >= 0 ); + + + # build the GROUP BY clause + # + my %groupbyhash = ( "tag", 1, "topic", 1, "user", 1 ); + my @groupbyClauses = (); + if ( $theFormat !~ m/\$(item|web|topic)/ ) { $groupbyhash{"topic"} = 0; }; + if ( $theFormat !~ m/\$(cuid|user)/ ) { $groupbyhash{"user"} = 0; }; + if ( $theFormat !~ m/\$tag/ ) { $groupbyhash{"tag"} = 0; }; + while( my ($key, $value) = each( %groupbyhash ) ) { + if ( $value ) { push @groupbyClauses, " $key " }; + } + my $groupby = join( ',', @groupbyClauses ); + $groupby = "GROUP BY " . $groupby if ( $#groupbyClauses >= 0 ); + + # build ORDER BY + # + my $order = ""; + if ( lc($theQuery) eq "tag" ) { + $order = "ORDER BY t.item_name"; + } elsif ( lc($theQuery) eq "topic" ) { + $order = "ORDER BY i.item_name"; + } elsif ( lc($theQuery) eq "user" ) { + $order = "ORDER BY u.FoswikicUID"; + } + + # create the final SELECT statement + # + $statement = " +SELECT + t.item_name as tag, + i.item_name as topic, + u.FoswikicUID as user, + ts.num_items as count +FROM Items t +INNER JOIN UserItemTag i2t ON i2t.tag_id=t.item_id +INNER JOIN Items i ON i.item_id=i2t.item_id AND i.item_type='topic' +INNER JOIN TagStat ts ON t.item_id = ts.tag_id +INNER JOIN Users u ON i2t.user_id = u.CUID +$where +$groupby +$order"; + + # Foswiki::Func::writeDebug("TAGSEARCH: $statement"); + + # get the data from the db and rotate through it + my $arrayRef = $db->dbSelect($statement); + foreach my $row ( @{$arrayRef} ) { + my $entry = $theFormat; + + my $tag = $row->[0]; + my $item = $row->[1]; + my $cuid = $row->[2]; + my $tag_count = $row->[3]; + + # replace all variable occurrences + if ( $entry =~ m/\$(item|topic|web)/ ) { + my ($item_web, $item_topic) = Foswiki::Func::normalizeWebTopicName("", $item); + $entry =~ s/\$item/$item/g; + $entry =~ s/\$topic/$item_topic/g; + $entry =~ s/\$web/$item_web/g; + } + + if ( $entry =~ m/\$(cuid|user)/ ) { + $entry =~ s/\$cuid/$cuid/g; + $entry =~ s/\$user/Foswiki::Func::getWikiName($cuid)/ge; + } + + $entry =~ s/\$tag/$tag/g; + $entry =~ s/\$count/$tag_count/g; + + # flag this entry as renameable (useful for css classes) + if ( $isTagAdmin ) { + $entry =~ s/\$renameable/tagsplugin_renameable/g; + } else { + $entry =~ s/\$renameable//g; + } + + # flag this entry as untaggable + if ( $isTagAdmin || $cuid eq $session->{user} || Foswiki::Func::isGroupMember($cuid) ) { + $entry =~ s/\$untaggable/tagsplugin_untaggable/g; + } else { + $entry =~ s/\$untaggable//g; + } + + # insert seperator only if needed + if ( $output ne '' ) { + $output .= $theSep . $entry; + } + else { + $output = $entry; + } + } + + $output = $theHeader . $output . $theFooter; + + # expand standard escapes + $output =~ s/\$n/\n/g; + $output =~ s/\$percnt/\%/g; + $output =~ s/\$quot/"/g; + $output =~ s/\$dollar/\$/g; + + return $output; +} + +1; \ No newline at end of file diff --git a/lib/Foswiki/Plugins/TagsPlugin/Tag.pm b/lib/Foswiki/Plugins/TagsPlugin/Tag.pm index b3b9d95..763a7b8 100644 --- a/lib/Foswiki/Plugins/TagsPlugin/Tag.pm +++ b/lib/Foswiki/Plugins/TagsPlugin/Tag.pm @@ -112,7 +112,7 @@ sub rest { $session->{response}->status(200); # returning nothing of interest - my $user_id = Foswiki::Plugins::TagsPlugin::getUserId($session, $user); + my $user_id = Foswiki::Plugins::TagsPlugin::getUserId($session, Foswiki::Func::getCanonicalUserID( $user ) ); my $retval = Foswiki::Plugins::TagsPlugin::Tag::do( $item_type, $item_name, $tag_text, $user_id ); # redirect on request @@ -121,7 +121,6 @@ sub rest { } return $retval; - } =begin TML diff --git a/lib/Foswiki/Plugins/TagsPlugin/Untag.pm b/lib/Foswiki/Plugins/TagsPlugin/Untag.pm index 48d2c81..cf0f28e 100644 --- a/lib/Foswiki/Plugins/TagsPlugin/Untag.pm +++ b/lib/Foswiki/Plugins/TagsPlugin/Untag.pm @@ -104,7 +104,8 @@ sub rest { $session->{response}->status(200); # returning the number of affected tags - return Foswiki::Plugins::TagsPlugin::Untag::do( $item_name, $tag_text, $user ); + my $user_id = Foswiki::Plugins::TagsPlugin::getUserId($session, Foswiki::Func::getCanonicalUserID( $user ) ); + return Foswiki::Plugins::TagsPlugin::Untag::do( $item_name, $tag_text, $user_id ); } =begin TML @@ -125,7 +126,7 @@ Return: =cut sub do { - my ( $item_name, $tag_text, $user ) = @_; + my ( $item_name, $tag_text, $cuid ) = @_; my $db = new Foswiki::Contrib::DbiContrib; # determine item_id for given item_name and exit if its not there @@ -152,16 +153,6 @@ sub do { } else { return " -2"; } - # determine cuid for given user_id and exit if its not there - # - my $cuid; - $statement = - sprintf( 'SELECT %s from %s WHERE %s = ? ', qw( CUID Users FoswikicUID) ); - $arrayRef = $db->dbSelect( $statement, $user ); - if ( defined( $arrayRef->[0][0] ) ) { - $cuid = $arrayRef->[0][0]; - } - else { return " -3"; } # now we are ready to actually untag # diff --git a/templates/tagsplugin2.tmpl b/templates/tagsplugin2.tmpl new file mode 100644 index 0000000..2fac278 --- /dev/null +++ b/templates/tagsplugin2.tmpl @@ -0,0 +1,40 @@ + + +%TMPL:DEF{tagsplugin:tagentry}%
+ + + + +
%TMPL:END% + +%{ TAGLIST }% +%TMPL:DEF{tagsplugin:taglist:header}%%TMPL:END% +%TMPL:DEF{tagsplugin:taglist:format}%$tag%TMPL:END% +%TMPL:DEF{tagsplugin:taglist:separator}%, %TMPL:END% +%TMPL:DEF{tagsplugin:taglist:footer}%%TMPL:END% + +%{ TAGCLOUD }% +%TMPL:DEF{tagsplugin:tagcloud:css}% + + %TMPL:END% +%TMPL:DEF{tagsplugin:tagcloud:header}%%TMPL:P{tagsplugin:tagcloud:css}%
    %TMPL:END% +%TMPL:DEF{tagsplugin:tagcloud:format}%
  1. $count items are tagged with $tag ($count)
  2. %TMPL:END% +%TMPL:DEF{tagsplugin:tagcloud:separator}% +%TMPL:END% +%TMPL:DEF{tagsplugin:tagcloud:footer}%
%TMPL:END% diff --git a/templates/view.tagsplugin2.tmpl b/templates/view.tagsplugin2.tmpl new file mode 100644 index 0000000..0ba2dd0 --- /dev/null +++ b/templates/view.tagsplugin2.tmpl @@ -0,0 +1,37 @@ +%TMPL:INCLUDE{view}% + +%TMPL:DEF{"contentheader"}% + Tags: + %TAGENTRY% %TAGLIST{ + show="all" + type="topic" + item="%BASEWEB%.%BASETOPIC%" + separator=" " + format="[[%SCRIPTURL{view}%/$percntURLENCODE{$tag}$percnt][$tag]]" + }% + %JQREQUIRE{"autocomplete"}% + + %TMPL:END%