# The LearningOnline Network with CAPA # Edit Handler for RAT Maps # # $Id: lonratedt.pm,v 1.39 2002/10/25 13:40:52 www 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/ # # (TeX Content Handler # # 05/29/00,05/30 Gerd Kortemeyer) # 7/1,6/30 Gerd Kortemeyer package Apache::lonratedt; use strict; use Apache::Constants qw(:common); use Apache::lonnet; use Apache::lonratsrv; use Apache::lonsequence; use Apache::loncommon; use File::Copy; use vars qw(@order @resources); # Mapread read maps into global arrays @links and @resources, determines status # sets @order - pointer to resources in right order # sets @resources - array with the resources with correct idx # sub mapread { my $fn=shift; my @links; undef @links; undef @resources; undef @order; @resources=(''); @order=(); my ($outtext,$errtext)=&Apache::lonratsrv::loadmap($fn,''); if ($errtext) { return ($errtext,2); } # -------------------------------------------------------------------- Read map foreach (split(/\<\&\>/,$outtext)) { my ($command,$number,$content)=split(/\<\:\>/,$_); if ($command eq 'objcont') { $resources[$number]=$content; } if ($command eq 'objlinks') { $links[$number]=$content; } if ($command eq 'objparms') { return('Map has resource parameters. Use advanced editor.',1); } } # ------------------------------------------------------- Is this a linear map? my @starters=(); my @endings=(); undef @starters; undef @endings; foreach (@links) { if (defined($_)) { my ($start,$end,$cond)=split(/\:/,$_); if ((defined($starters[$start])) || (defined($endings[$end]))) { return ('Map has branchings. Use advanced editor.',1); } $starters[$start]=1; $endings[$end]=1; if ($cond) { return ('Map has conditions. Use advanced editor.',1); } } } for (my $i=1; $i<=$#resources; $i++) { if (defined($resources[$i])) { unless (($starters[$i]) || ($endings[$i])) { return ('Map has unconnected resources. Use advanced editor.',1); } } } # ---------------------------------------------- Did we just read an empty map? if ($#resources<1) { undef $resources[0]; $resources[1]=':::start'; $resources[2]=':::finish'; } # -------------------------------------------------- This is a linear map, sort my $startidx=0; my $endidx=0; for (my $i=0; $i<=$#resources; $i++) { if (defined($resources[$i])) { my ($title,$url,$ext,$type)=split(/\:/,$resources[$i]); if ($type eq 'start') { $startidx=$i; } if ($type eq 'finish') { $endidx=$i; } } } my $k=0; my $currentidx=$startidx; $order[$k]=$currentidx; for (my $i=0; $i<=$#resources; $i++) { foreach (@links) { my ($start,$end)=split(/\:/,$_); if ($start==$currentidx) { $currentidx=$end; $k++; $order[$k]=$currentidx; last; } } if ($currentidx==$endidx) { last; } } return $errtext; } # ---------------------------------------------- Read a map as well as possible # Also used by the sequence handler # Call lonsequence::attemptread to read from resource space # sub attemptread { my $fn=shift; my @links; undef @links; my @theseres; undef @theseres; my ($outtext,$errtext)=&Apache::lonratsrv::loadmap($fn,''); if ($errtext) { return @theseres } # -------------------------------------------------------------------- Read map foreach (split(/\<\&\>/,$outtext)) { my ($command,$number,$content)=split(/\<\:\>/,$_); if ($command eq 'objcont') { $theseres[$number]=$content; } if ($command eq 'objlinks') { $links[$number]=$content; } } # --------------------------------------------------------------- Sort, sort of my @objsort=(); undef @objsort; my @data1=(); my @data2=(); undef @data1; undef @data2; my $k; my $kj; my $j; my $ij; for ($k=1;$k<=$#theseres;$k++) { if (defined($theseres[$k])) { $objsort[$#objsort+1]=$k; } } for ($k=1;$k<=$#links;$k++) { if (defined($links[$k])) { @data1=split(/\:/,$links[$k]); $kj=-1; for (my $j=0;$j<=$#objsort;$j++) { if ((split(/\:/,$objsort[$j]))[0]==$data1[0]) { $kj=$j; } } if ($kj!=-1) { $objsort[$kj].=':'.$data1[1]; } } } for ($k=0;$k<=$#objsort;$k++) { for ($j=0;$j<=$#objsort;$j++) { if ($k!=$j) { @data1=split(/\:/,$objsort[$k]); @data2=split(/\:/,$objsort[$j]); my $dol=$#data1+1; my $dtl=$#data2+1; if ($dol+$dtl<1000) { for ($kj=1;$kj<$dol;$kj++) { if ($data1[$kj]==$data2[0]) { for ($ij=1;$ij<$dtl;$ij++) { $data1[$#data1+1]=$data2[$ij]; } } } for ($kj=1;$kj<$dtl;$kj++) { if ($data2[$kj]==$data1[0]) { for ($ij=1;$ij<$dol;$ij++) { $data2[$#data2+1]=$data1[$ij]; } } } $objsort[$k]=join(':',@data1); $objsort[$j]=join(':',@data2); } } } } # ---------------------------------------------------------------- Now sort out @objsort=sort { my @data1=split(/\:/,$a); my @data2=split(/\:/,$b); my $rvalue=0; my $k; for ($k=1;$k<=$#data1;$k++) { if ($data1[$k]==$data2[0]) { $rvalue--; } } for ($k=1;$k<=$#data2;$k++) { if ($data2[$k]==$data1[0]) { $rvalue++; } } if ($rvalue==0) { $rvalue=$#data2-$#data1; } $rvalue; } @objsort; my @outres=(); undef @outres; for ($k=0;$k<=$#objsort;$k++) { $outres[$k]=$theseres[(split(/\:/,$objsort[$k]))[0]]; } return @outres; } # --------------------------------------------------------- Build up RAT screen sub ratedt { my ($r,$url)=@_; $r->print(< ENDDOCUMENT } # ---------------------------------------------------------------- Make buttons sub buttons { my $adv=shift; my $output='
'; if ($adv==1) { $output.=''; } else { unless ($adv==2) { $output.=''; } $output.=''; } return $output.'

'; } # ----------------------------------------------------------- Paste into target # modifies @order, @resources sub pastetarget { my ($after,@which)=@_; my @insertorder=(); foreach (@which) { if (defined($_)) { my ($name,$url)=split(/\=/,$_); $name=&Apache::lonnet::unescape($name); $url=&Apache::lonnet::unescape($url); if ($url) { my $idx=$#resources+1; $insertorder[$#insertorder+1]=$idx; my $ext='false'; if ($url=~/^http\:\/\//) { $ext='true'; } $url=~s/\:/\:/g; $name=~s/\:/\:/g; $resources[$idx]=$name.':'.$url.':'.$ext.':normal:res'; } } } my @oldorder=splice(@order,$after); @order=(@order,@insertorder,@oldorder); } # ------------------------------------------------ Get start and finish correct # modifies @resources sub startfinish { foreach (@order) { my ($name,$url,$ext)=split(/\:/,$resources[$_]); if ($url=~/http\&colon\:\/\//) { $ext='true'; } $resources[$_]=$name.':'.$url.':'.$ext.':normal:res'; } my ($name,$url,$ext)=split(/\:/,$resources[$order[0]]); $resources[$order[0]]=$name.':'.$url.':'.$ext.':start:res'; if ($#order==0) { $resources[$#resources+1]='::false'; $order[1]=$#resources; } my ($name,$url,$ext)=split(/\:/,$resources[$order[$#order]]); $resources[$order[$#order]]=$name.':'.$url.':'.$ext.':finish:res'; } # ------------------------------------------------------------------- Store map sub storemap { my $realfn=shift; my $fn=$realfn; # unless this is forced to work from the original file, use a temporary file # instead unless (shift) { $fn=$realfn.'.tmp'; unless (-e $fn) { copy($realfn,$fn); } } # store data either into tmp or real file &startfinish(); my $output='graphdef<:>no'; my $k=1; for (my $i=0; $i<=$#order; $i++) { if (defined($resources[$order[$i]])) { $output.='<&>objcont<:>'.$order[$i].'<:>'.$resources[$order[$i]]; } if (defined($order[$i+1])) { if (defined($resources[$order[$i+1]])) { $output.='<&>objlinks<:>'.$k.'<:>'. $order[$i].':'.$order[$i+1].':0'; $k++; } } } $output=~s/http\&colon\;\/\///g; $ENV{'form.output'}=$output; return &Apache::lonratsrv::loadmap($fn,&Apache::lonratsrv::savemap($fn,'')); } sub editscript { my $mode=shift; return(<0) { my $movethis=$order[$_-1]; $order[$_-1]=$order[$_-2]; $order[$_-2]=$movethis; } } &storemap(&Apache::lonnet::filelocation('',$url)); # ------------------------------------------------------------------ Move down } elsif ($ENV{'form.movedown'}) { foreach (reverse sort @targetselect) { if ($_-1<$#order) { my $movethis=$order[$_-1]; $order[$_-1]=$order[$_]; $order[$_]=$movethis; } } &storemap(&Apache::lonnet::filelocation('',$url)); # --------------------------------------------------------------------- Rename } elsif ($ENV{'form.renameres'}) { my $residx=$Apache::lonratedt::order[$ENV{'form.renameidx'}-1]; my ($name,@resrest)=split(/\:/,$Apache::lonratedt::resources[$residx]); $name=&Apache::lonnet::escape($ENV{'form.renametitle'}); $Apache::lonratedt::resources[$residx]=$name.':'.join(':'.@resrest); &storemap(&Apache::lonnet::filelocation('',$url)); } # ------------------------------------------------------------ Assemble windows my $idx=-1; $importdetail='&'.$importdetail; $importdetail=~s/^\&+/\&/; my $importwindow= ''. join("\n",map { $idx++; if ($_) { my ($name,$url)=split(/\=/,$_); unless ($name) { $name=(split(/\//,$url))[-1]; } unless ($name) { $name='EMPTY'; } ''; } } split(/\&/,$importdetail)); $idx=0; $targetdetail=''; my $targetwindow= ''. join("\n",map { my ($name,$url)=split(/\:/,$resources[$_]); unless ($name) { $name=(split(/\//,$url))[-1]; } unless ($name) { $name='EMPTY'; } $targetdetail.='&'.&Apache::lonnet::escape($name).'='. &Apache::lonnet::escape($url); $idx++; $name=~s/\:/\:/g; ''; } @order); # ----------------------------------------------------- Start simple RAT screen my $editscript=&editscript('simple'); my $bodytag=&Apache::loncommon::bodytag(undef,undef,undef,1); $r->print(< $bodytag $buttons $errtext
Temporary Assembly Workspace   File: $url
after selected

  after selected

$targetmsg
Cut selected


Copy selected


Paste after selected
ENDSMPHEAD } # ----------------------------------------------------------------- No such dir sub nodir { my ($r,$dir)=@_; $dir=~s/^\/home\/\w+\/public\_html//; $r->print(<

No such directory: $dir

ENDNODIR } # ---------------------------------------------------------------- View Handler sub viewmap { my ($r,$url,$adv,$errtext)=@_; $r->print(''. &Apache::loncommon::bodytag('Edit Content of a Map'). &buttons($adv)); if ($errtext) { $r->print($errtext.'
'); } my $idx=0; $r->print('

'.$url.'

'); foreach (&attemptread(&Apache::lonnet::filelocation('',$url))) { if (defined($_)) { $idx++; my ($title,$url)=split(/\:/,$_); $title=~s/\&colon\;/\:/g; $url=~s/\&colon\;/\:/g; unless ($title) { $title=(split(/\//,$url))[-1] }; unless ($title) { $title='Empty'; } if ($url) { $r->print(''); } $r->print(&Apache::lonratsrv::qtescape($title)); if ($url) { $r->print(''); } $r->print('
'); } } $r->print(''); } # ================================================================ Main Handler sub handler { my $r=shift; $r->content_type('text/html'); $r->send_http_header; return OK if $r->header_only; my $url=$r->uri; my $fn=&Apache::lonnet::filelocation('',$url); my ($dir)=($fn=~/^(.+)\/[^\/]+$/); unless (-e $dir) { &nodir($r,$dir); return OK; } # ------------------------------------------- Determine which tools can be used my $adv=0; unless ($ENV{'form.forcesmp'}) { if ($ENV{'form.forceadv'}) { $adv=1; } elsif (my $fh=Apache::File->new($fn)) { my $allmap=join('',<$fh>); $adv=($allmap=~/\]+mode\s*\=\s*(\'|\")rat/is); } } my $errtext=''; my $fatal=0; # -------------------------------------------------------------------- Load map ($errtext,$fatal)=&mapread($fn,$errtext); if ($fatal==1) { $adv=1; } # ----------------------------------- adv==1 now means "graphical MUST be used" if ($ENV{'form.forceadv'}) { &ratedt($r,$url); } elsif ($ENV{'form.forcesmp'}) { &smpedt($r,$url,$errtext); } else { &viewmap($r,$url,$adv,$errtext); } return OK; } 1; __END__