Skip to content

Commit

Permalink
Item1918: adding rename and merge
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.foswiki.org/trunk/TagsPlugin@4673 0b4bb1d4-4e5a-0410-9cc4-b2b747904278
  • Loading branch information
OliverKrueger authored and OliverKrueger committed Aug 16, 2009
1 parent 1a6e17b commit 002781e
Show file tree
Hide file tree
Showing 4 changed files with 352 additions and 3 deletions.
16 changes: 14 additions & 2 deletions lib/Foswiki/Plugins/TagsPlugin.pm
Expand Up @@ -54,9 +54,11 @@ sub initPlugin {

Foswiki::Func::registerRESTHandler( 'tag', \&tagCall );
Foswiki::Func::registerRESTHandler( 'untag', \&untagCall );
Foswiki::Func::registerRESTHandler( 'delete', \&deleteCall );
# Foswiki::Func::registerRESTHandler('updateGeoTags', \&updateGeoTags);
Foswiki::Func::registerRESTHandler( 'delete', \&deleteCall );
Foswiki::Func::registerRESTHandler( 'rename', \&renameCall );
Foswiki::Func::registerRESTHandler( 'merge', \&mergeCall );
Foswiki::Func::registerRESTHandler( 'initialiseDatabase', \&initialiseDatabase );
# Foswiki::Func::registerRESTHandler('updateGeoTags', \&updateGeoTags);

#TODO: augment the IfParser and the QuerySearch Parsers to add Tags?

Expand Down Expand Up @@ -325,6 +327,16 @@ sub deleteCall {
return Foswiki::Plugins::TagsPlugin::Delete::rest( @_ );
}

sub renameCall {
use Foswiki::Plugins::TagsPlugin::Rename;
return Foswiki::Plugins::TagsPlugin::Rename::rest( @_ );
}

sub mergeCall {
use Foswiki::Plugins::TagsPlugin::Merge;
return Foswiki::Plugins::TagsPlugin::Merge::rest( @_ );
}

sub getUserId {
my $session = shift;

Expand Down
2 changes: 1 addition & 1 deletion lib/Foswiki/Plugins/TagsPlugin/Config.spec
Expand Up @@ -13,5 +13,5 @@ $Foswiki::cfg{TagsPlugin}{EnableCategories} = 1;
$Foswiki::cfg{TagsPlugin}{EnableDataForms} = 1;

# **STRING**
# Name of the TagAdminGroup (which is allowed to delete and merge tags)
# Name of the TagAdminGroup (which is allowed to delete, rename and merge tags)
$Foswiki::cfg{TagsPlugin}{TagAdminGroup} = "AdminGroup";
192 changes: 192 additions & 0 deletions lib/Foswiki/Plugins/TagsPlugin/Merge.pm
@@ -0,0 +1,192 @@
# 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::Merge;

use strict;
use warnings;
use Error qw(:try);

=begin TML
---++ rest( $session )
This is the REST wrapper for merge.
Takes the following url parameters:
tag1 : name of the tag to be renamed
tag2 : new name for the old tag
It checks the prerequisites and sets the following status codes:
200 : Ok
400 : url parameter(s) are missing
403 : the user is not allowed to rename
Return:
In case of an error (!=200) just the status code incl. short description is returned.
Otherwise a 200 and the number of affected tags (usually 0 or 1) is returned.
TODO:
force http POST method
=cut

sub rest {
my $session = shift;
my $query = Foswiki::Func::getCgiQuery();

my $tag1 = $query->param('tag1') || '';
my $tag2 = $query->param('tag2') || '';

$tag1 = Foswiki::Sandbox::untaintUnchecked($tag1);
$tag2 = Foswiki::Sandbox::untaintUnchecked($tag2);

#
# checking prerequisites
#

# first check the existence of all necessary url parameters
#
if ( !$tag1 ) {
$session->{response}->status(400);
return "<h1>400 'tag1' parameter missing</h1>";
}
if ( !$tag2 ) {
$session->{response}->status(400);
return "<h1>400 'tag2' parameter missing</h1>";
}

# check if current user is allowed to do so
#
my $tagAdminGroup = $Foswiki::cfg{TagsPlugin}{TagAdminGroup} || "AdminGroup";
if ( !Foswiki::Func::isGroupMember( $tagAdminGroup, Foswiki::Func::getWikiName()) ) {
$session->{response}->status(403);
return "<h1>403 Forbidden</h1>";
}

#
# actioning
#
$session->{response}->status(200);

# returning 0 on failure and some other positive number on success
return Foswiki::Plugins::TagsPlugin::Merge::do( $tag1, $tag2 );

}

=begin TML
---++ do( $tag1, $tag2 )
This does the merging. Updates both Stat tables and deletes unused entries for obsolete tag2.
Takes the following parameters:
tag1 : name of the tag which remains
tag2 : name of the tag which will be merged into tag1
This routine does not check any prerequisites and/or priviledges. It returns 0, if
tag1 or tag2 was not found.
Return:
0 on failure, any other positive number on success.
=cut

sub do {
my ( $tag1, $tag2 ) = @_;
my $db = new Foswiki::Contrib::DbiContrib;

# determine tag_id for given tag1 and exit if its not there
#
my $tag_id1;
my $statement = sprintf( 'SELECT %s from %s WHERE %s = ? AND %s = ?',
qw( item_id Items item_name item_type) );
my $arrayRef = $db->dbSelect( $statement, $tag1, 'tag' );
if ( defined( $arrayRef->[0][0] ) ) {
$tag_id1 = $arrayRef->[0][0];
}
else { return " 0"; }

# determine tag_id for given tag2 and exit if its not there
#
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' );
if ( defined( $arrayRef->[0][0] ) ) {
$tag_id2 = $arrayRef->[0][0];
}
else { return " 0"; }

# now we are ready to actually merge
#

# merge the usage of the tags (in UserItemTag)
# IGNOREing duplicate entries, which usually occur (may leave some garbage behind)
$statement =
sprintf( 'UPDATE IGNORE %s SET %s = ? WHERE %s = ?',
qw( UserItemTag tag_id tag_id ) );
my $affected_rows = $db->dbInsert( $statement, $tag_id1, $tag_id2 );
Foswiki::Func::writeDebug("Merge: $statement; ($tag_id1, $tag_id2) -> $affected_rows");
if ( $affected_rows eq "0E0" ) { $affected_rows=0; };
# DELETEing the garbage (usually tags on topics, which were tagged with tag1 and tag2)
$statement =
sprintf( 'DELETE from %s WHERE %s = ?',
qw( UserItemTag tag_id) );
my $modified = $db->dbDelete( $statement, $tag_id2 );
Foswiki::Func::writeDebug("Merge: $statement; ($tag_id2) -> $modified");

# update stats in TagStat (rebuild it actually)
my $tagstat = 0;
$statement = sprintf( 'SELECT count(*) as count from %s WHERE %s = ?',
qw( UserItemTag tag_id ) );
$arrayRef = $db->dbSelect( $statement, $tag_id1 );
if ( defined( $arrayRef->[0][0] ) ) {
$tagstat = $arrayRef->[0][0];
}
$statement =
sprintf( 'UPDATE %s SET %s=? WHERE %s = ?',
qw( TagStat num_items tag_id) );
$modified = $db->dbInsert( $statement, $tagstat, $tag_id1 );
Foswiki::Func::writeDebug("Merge: $statement; ($tagstat, $tag_id1) -> $modified");
unless ( $modified ) {
$statement =
sprintf( 'INSERT INTO %s (%s, %s) VALUES (?, ?)',
qw( TagStat tag_id num_items ) );
$modified = $db->dbInsert( $statement, $tag_id1, $tagstat );
Foswiki::Func::writeDebug("Merge: $statement; ($tag_id1, $tagstat) -> $modified");
}
$statement =
sprintf( 'DELETE from %s WHERE %s = ?',
qw( TagStat tag_id) );
$modified = $db->dbDelete( $statement, $tag_id2 );
Foswiki::Func::writeDebug("Merge: $statement; ($tag_id2) -> $modified");

# update stats in UserTagStat
### TODO: implement rebuilding UserTagStat rebuild

# delete (empty) tag2
$statement =
sprintf( 'DELETE from %s WHERE %s = ?',
qw( Items item_id) );
$modified = $db->dbDelete( $statement, $tag_id2 );
Foswiki::Func::writeDebug("Merge: $statement; ($tag_id2) -> $modified");

# flushing data to dbms
#
$db->commit();

# add extra space, so that zero affected rows does not clash with returning "0" from rest invocation
return " $affected_rows";
}

1;
145 changes: 145 additions & 0 deletions lib/Foswiki/Plugins/TagsPlugin/Rename.pm
@@ -0,0 +1,145 @@
# 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::Rename;

use strict;
use warnings;
use Error qw(:try);

=begin TML
---++ rest( $session )
This is the REST wrapper for rename.
Takes the following url parameters:
oldtag : name of the tag to be renamed
newtag : new name for the old tag
It checks the prerequisites and sets the following status codes:
200 : Ok
400 : url parameter(s) are missing
403 : the user is not allowed to rename
Return:
In case of an error (!=200) just the status code incl. short description is returned.
Otherwise a 200 and the number of affected tags (usually 0 or 1) is returned.
TODO:
force http POST method
=cut

sub rest {
my $session = shift;
my $query = Foswiki::Func::getCgiQuery();

my $tag_old = $query->param('oldtag') || '';
my $tag_new = $query->param('newtag') || '';

$tag_old = Foswiki::Sandbox::untaintUnchecked($tag_old);
$tag_new = Foswiki::Sandbox::untaintUnchecked($tag_new);

#
# checking prerequisites
#

# first check the existence of all necessary url parameters
#
if ( !$tag_old ) {
$session->{response}->status(400);
return "<h1>400 'oldtag' parameter missing</h1>";
}
if ( !$tag_new ) {
$session->{response}->status(400);
return "<h1>400 'newtag' parameter missing</h1>";
}

# check if current user is allowed to do so
#
my $tagAdminGroup = $Foswiki::cfg{TagsPlugin}{TagAdminGroup} || "AdminGroup";
if ( !Foswiki::Func::isGroupMember( $tagAdminGroup, Foswiki::Func::getWikiName()) ) {
$session->{response}->status(403);
return "<h1>403 Forbidden</h1>";
}

#
# actioning
#
$session->{response}->status(200);

# returning the number of affected tags
return Foswiki::Plugins::TagsPlugin::Rename::do( $tag_old, $tag_new );

}

=begin TML
---++ do( $tag_old, $tag_new )
This does untagging.
Takes the following parameters:
tag_old : name of tag to be renamed
tag_new : new name for the old tag
This routine does not check any prerequisites and/or priviledges. It returns 0, if
the old tagname was not found or the new tagname already exists.
Return:
number of affected tags.
=cut

sub do {
my ( $tag_old, $tag_new ) = @_;
my $db = new Foswiki::Contrib::DbiContrib;

# determine tag_id for given tag_old and exit if its not there
#
my $tag_id;
my $statement = sprintf( 'SELECT %s from %s WHERE %s = ? AND %s = ?',
qw( item_id Items item_name item_type) );
my $arrayRef = $db->dbSelect( $statement, $tag_old, 'tag' );
if ( defined( $arrayRef->[0][0] ) ) {
$tag_id = $arrayRef->[0][0];
}
else { return " 0"; }

# check if new tagname already exists by probing for an tag_id
#
$statement = sprintf( 'SELECT %s from %s WHERE %s = ? AND %s = ?',
qw( item_id Items item_name item_type) );
$arrayRef = $db->dbSelect( $statement, $tag_new, 'tag' );
if ( defined( $arrayRef->[0][0] ) ) {
return " 0";
}

# now we are ready to actually rename
#
$statement =
sprintf( 'UPDATE %s SET %s = ? WHERE %s = ?',
qw( Items item_name item_id ) );
Foswiki::Func::writeDebug("Rename: $statement; ($tag_new, $tag_id)");
my $affected_rows = $db->dbInsert( $statement, $tag_new, $tag_id );
if ( $affected_rows eq "0E0" ) { $affected_rows=0; };

# flushing data to dbms
#
$db->commit();

# add extra space, so that zero affected rows does not clash with returning "0" from rest invocation
return " $affected_rows";
}

1;

0 comments on commit 002781e

Please sign in to comment.