# The LearningOnline Network with CAPA
# The LON-CAPA group sort handler
# Allows for sorting prior to import into RAT.
#
# $Id: groupsort.pm,v 1.62 2008/09/15 13:22:48 bisitz Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA 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.
#
# LON-CAPA 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.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
###
package Apache::groupsort;
use strict;
use Apache::Constants qw(:common);
use GDBM_File;
use Apache::loncommon;
use Apache::lonlocal;
use Apache::lonnet;
use LONCAPA;
my $iconpath; # variable to be accessible to multiple subroutines
my %hash; # variable to tie to user specific database
sub update_actions_hash {
my ($hash) = @_;
# be careful in here, there is also a global %hash
my $acts=$env{'form.acts'};
my @Acts=split(/b/,$acts);
my %ahash;
my %achash;
# some initial hashes for working with data
my $ac=0;
foreach (@Acts) {
my ($state,$ref)=split(/a/);
$ahash{$ref}=$state;
$achash{$ref}=$ac;
$ac++;
}
# sorting through the actions and changing the global database hash
foreach my $key (sort {$achash{$a}<=>$achash{$b}} (keys %ahash)) {
if ($ahash{$key} eq '1') {
$hash->{'store_'.$hash->{'pre_'.$key.'_link'}}=
$hash->{'pre_'.$key.'_title'};
$hash->{'storectr_'.$hash->{'pre_'.$key.'_link'}}=
$hash->{'storectr'}+0;
$hash->{'storectr'}++;
}
if ($ahash{$key} eq '0') {
if ($hash->{'store_'.$hash->{'pre_'.$key.'_link'}}) {
delete($hash->{'store_'.$hash->{'pre_'.$key.'_link'}});
delete($hash->{'storectr_'.$hash->{'pre_'.$key.'_link'}});
}
}
}
# deleting the previously cached listing
foreach my $key (keys(%{ $hash })) {
next if ($key !~ /^pre_(\d+)_link/);
my $which = $1;
delete($hash->{'pre_'.$which.'_title'});
delete($hash->{'pre_'.$which.'_link'});
}
}
sub readfromdb {
my ($r,$resources)=@_;
my $diropendb =
"/home/httpd/perl/tmp/$env{'user.domain'}_$env{'user.name'}_sel_res.db";
# ----------------------------- diropendb is now the filename of the db to open
if (tie(%hash,'GDBM_File',$diropendb,&GDBM_WRCREAT(),0640)) {
&update_actions_hash(\%hash);
my %temp_resources;
foreach my $key (keys(%hash)) {
next if ($key !~ /^store_/);
my ($url) = ($key =~ /^store_(.*)/);
$temp_resources{$hash{'storectr_'.$url}}{'url'}=$url;
$temp_resources{$hash{'storectr_'.$url}}{'title'}=
&Apache::lonnet::gettitle($url);
}
# use the temp, since there might be gaps in the counting
foreach my $item (sort {$a <=> $b} (keys(%temp_resources))) {
push(@{ $resources },$temp_resources{$item});
}
if ($env{'form.oldval'}) {
my $res = splice(@{$resources},$env{'form.oldval'}-1,1);
if ($env{'form.newval'} == 0) {
# picked 'discard'
my $url = $res->{'url'};
delete($hash{'storectr_'.$url});
delete($hash{'store_'.$url});
} else {
splice(@{$resources},$env{'form.newval'}-1,0,$res);
}
}
# store out new order
foreach my $which (0..$#$resources) {
my $url = $resources->[$which]{'url'};
$hash{'storectr_'.$url} = $which;
}
} else {
$r->print('Unable to tie hash to db file');
}
untie(%hash);
}
sub cleanup {
if (tied(%hash)){
&Apache::lonnet::logthis('Cleanup groupsort: hash');
unless (untie(%hash)) {
&Apache::lonnet::logthis('Failed cleanup groupsort: hash');
}
}
return OK;
}
# -------------------------------------------------------------- Read from file
sub readfromfile {
my ($r,$resources)=@_;
my $cont=&Apache::lonnet::getfile
(&Apache::lonnet::filelocation('',$env{'form.readfile'}));
if ($cont==-1) {
$r->print('Unable to read file: '.
&Apache::lonnet::filelocation('',$env{'form.readfile'}));
} else {
my $parser = HTML::TokeParser->new(\$cont);
my $token;
while ($token = $parser->get_token) {
if ($token->[0] eq 'S') {
if ($token->[1] eq 'resource') {
if ($env{'form.recover'}) {
if ($token->[2]->{'type'} ne 'zombie') { next; }
} else {
if ($token->[2]->{'type'} eq 'zombie') { next; }
}
my $name=$token->[2]->{'title'};
$name=~s/ \[\((\d+)\,($LONCAPA::username_re)\,($LONCAPA::domain_re)\)\]$//;
my $note;
if ($1) {
$note = ' '.&mt('Removed by ').
&Apache::loncommon::plainname($2,$3).', '.
&Apache::lonlocal::locallocaltime($1);
}
$name=~s/\&colon\;/\:/g;
push(@{$resources}, {'url' => $token->[2]->{'src'},
'title' => $name,
'note' => $note,
'id' => $token->[2]->{'id'},});
}
}
}
}
}
# --------------------------------------------------------- Read from bookmarks
sub readfrombookmarks {
my ($r,$resources)=@_;
my %bookmarks=&Apache::lonnet::dump('bookmarks');
# the bookmark "hash" is just one entry
# it's a javascript program code with arguments like ('title','url');
my @bookmarks=($bookmarks{'bookmarks'}=~/\((?:\'([^\']+)\'\,\'([^\']+)\'|\"([^\"]+)\"\,\"([^\"]+)\")\)\;/g);
for (my $index=0;$index<($#bookmarks+1)/2;$index++) {
if ($bookmarks[$index*2+1]) {
my $url = $bookmarks[$index*2+1];
my $name = $bookmarks[$index*2];
$name =~ s/^LON\-CAPA\s+//;
push(@{$resources},{'url' => $url, 'title' => $name});
}
}
}
# ---------------------------------------------------------------- Main Handler
sub handler {
my $r = shift;
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
['acts','mode','readfile','recover','bookmarks']);
&Apache::loncommon::content_type($r,'text/html');
$r->send_http_header;
return OK if $r->header_only;
# finish_import looks different for graphical or "simple" RAT
my $finishimport='';
my $begincondition='';
my $endcondition='';
if (($env{'form.readfile'}) || ($env{'form.bookmarks'})) {
$begincondition='if (eval("document.forms.groupsort.include"+num+".checked")) {';
$endcondition='}';
}
if ($env{'form.mode'} eq 'simple' || $env{'form.mode'} eq '') {
$finishimport=(<
function insertRowInLastRow() {
opener.insertrow(opener.maxrow);
opener.addobj(opener.maxrow,'e&2');
}
function placeResourceInLastRow (title,url,id,linkflag) {
opener.mostrecent=opener.newresource(opener.maxrow,2,opener.escape(title),
opener.escape(url),'false','normal',id);
opener.save();
if (linkflag) {
opener.joinres(opener.linkmode,opener.mostrecent,0);
}
opener.linkmode=opener.mostrecent;
}
$finishimport
function selectchange(val) {
var newval=0+eval("document.forms.groupsort.alt"+val+".selectedIndex");
orderchange(val,newval);
}
function move(val,newval) {
orderchange(val,newval);
}
function orderchange(val,newval) {
document.forms.groupsort.oldval.value=val;
document.forms.groupsort.newval.value=newval;
document.forms.groupsort.submit();
}
END
# read pertinent machine configuration
my $domain = $r->dir_config('lonDefDomain');
$iconpath = $r->dir_config('lonIconsURL') . "/";
my @resources;
if ($env{'form.readfile'}) {
&readfromfile($r,\@resources);
} elsif ($env{'form.bookmarks'}) {
&readfrombookmarks($r,\@resources);
} else {
&readfromdb($r,\@resources);
}
my $ctr = 0;
my $clen = scalar(@resources);
if (($clen > 1) || ($env{'form.readfile'}) || ($env{'form.bookmarks'})) {
my %lt=&Apache::lonlocal::texthash(
'fin'=> 'Finalize order of resources',
'ci' => 'Continue Import',
'cs' => 'Continue Search',
'fi' => 'Finish Import',
're' => 'Recover Checked',
'ca' => 'Cancel',
'co' => 'Change Order',
'ti' => 'Title',
'pa' => 'Path',
'in' => 'Include'
);
my $title = ($env{'form.recover'}) ? 'Recover Removed Resources'
: 'Sort Imported Resources';
$r->print(&Apache::loncommon::start_page($title, $js));
$r->print(<
END
$r->print(&Apache::loncommon::inhibit_menu_check('input'));
# ---
if ($env{'form.recover'}) {
$r->print(<
END
} else {
# --- Continue Buttons
my $resurl =
&Apache::loncommon::escape_single(&Apache::loncommon::lastresurl());
$r->print(<$lt{'fin'}
END
}
$r->print(&Apache::loncommon::start_data_table()
.&Apache::loncommon::start_data_table_header_row());
if (($env{'form.readfile'}) || ($env{'form.bookmarks'})) {
$r->print("
$lt{'in'}
\n");
} else {
$r->print("
$lt{'co'}
\n");
}
$r->print("
$lt{'ti'}
\n");
$r->print("
$lt{'pa'}
");
$r->print(&Apache::loncommon::end_data_table_header_row()
."\n");
} else {
$r->print(&Apache::loncommon::start_page(undef,$js,
{'only_body' => 1}));
$r->print(<
END
$r->print(&Apache::loncommon::inhibit_menu_check('input'));
}
foreach my $resource (@resources) {
$ctr++;
my $iconname=&Apache::loncommon::icon($resource->{'url'});
if (($clen > 1) || ($env{'form.readfile'}) || ($env{'form.bookmarks'})) {
$r->print(&Apache::loncommon::start_data_table_row()
."