File:  [LON-CAPA] / loncom / homework / outputtags.pm
Revision 1.62: download - view: text, annotated - select for diffs
Sat Mar 25 18:38:25 2023 UTC (12 months ago) by raeburn
Branches: MAIN
CVS tags: version_2_12_X, HEAD
- Typo: height not heigth

# The LearningOnline Network with CAPA 
# tags that create controlled output
#
# $Id: outputtags.pm,v 1.62 2023/03/25 18:38:25 raeburn 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::outputtags; 

use strict;
use Apache::lonlocal;
use Apache::lonnet;
use LONCAPA::LWPReq;
use POSIX qw(strftime);

BEGIN {
    &Apache::lonxml::register('Apache::outputtags',('displayduedate','displaytitle','displayweight','displaystudentphoto'));
}

################################ utilities ###########################

# 
#  Does a simple substitution of a tab when the opening tag can
#  be replaced by a fixed string.. and same for the closing tag.
#  Parameters:
#    $input   - String in in which to do the substitutions.
#    $tag     - name of tag without the <>'s e.g. sub for <sub></sub>
#    $opening - What to replace <$tag> with
#    $closing - What to replace </$tag> with.
#  Returns:
#    Input string appropriately substituted.
#
sub substitute_tag {
    my ($input,
	$tag,
	$opening,
	$closing) = @_;

    $input =~ s/<$tag>/$opening/gi;
    $input =~ s/<\/$tag>/$closing/gi;

    return $input;
}  

#
#  Substitutes the simple formatting tags in a string
#  Parameters:
#    $string - input string.
#  Returns
#    Result of string after simple substitutions
#  Tags we handle are:
#    <sub>, <sup> <em>
#
sub substitute_simple_tags_latex {
    my ($string)  = @_;

    # restore the <>'s:

    $string =~ s/\\ensuremath\{<}/</g;
    $string =~ s/\\ensuremath\{>}/>/g;


    # Substitute the tags:

    $string = &substitute_tag($string, "sub", '\ensuremath{_', '}');
    $string = &substitute_tag($string, 'sup', '\ensuremath{^', '}');
    $string = &substitute_tag($string, 'em', '\em{', '}');


    # Escape the remaining <>'s again:

    $string =~ s/</\\ensuremath{<}/g;
    $string =~ s/>/\\ensuremath{>}/g;



    return $string;
}

################################ The parser ##########################

sub initialize_outputtags {
    %Apache::outputtags::showonce=();
}



sub start_displayduedate {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
    my $result;

    # Different parts can have different due dates... so we keep a list
    # of the parts for which we've displayed the duedate:

    if (exists($Apache::outputtags::showonce{'displayduedate'})) {
	if (grep(/^\Q$Apache::inputtags::part\E$/,
		 @{$Apache::outputtags::showonce{'displayduedate'}})) {
	    return '';		# Already shown the duedate for this part.
	}
    }
    # since we will show the duedate for this part, remember it.

    push (@{$Apache::outputtags::showonce{'displayduedate'}},
	  $Apache::inputtags::part);

    #  Determine the due date format:
    #
    my $status=$Apache::inputtags::status['-1'];
    &Apache::lonxml::debug("got a $status in duedatebox");
    my $style = &Apache::lonxml::get_param('style',$parstack,$safeeval);
    my $format = &Apache::lonxml::get_param('format', $parstack, $safeeval);
    if (!$format) {
	$format = undef;
    }
    if (($status =~ /CAN.*_ANSWER/)) {
	my $id = $Apache::inputtags::part;
	my $date = &Apache::lonhomework::due_date($id);
	&Apache::lonxml::debug("duedatebox found $date for $id");

	# Only show the due date if the current date is 
	# different from due date of the previous part.  I think
	# this is probably the best way to avoid due date clutter.

       	my $showduedate = 1;
	my $part_count  = scalar(@{$Apache::outputtags::showonce{'displayduedate'}});
	if ($part_count > 1) {
	    my $prev_part_id = $Apache::outputtags::showonce{'displayduedate'}->[$part_count-2];
	    my $prev_due_date = &Apache::lonnet::EXT("resource.$prev_part_id.duedate");
	    if ($prev_due_date == $date) {
		$showduedate = 0;
	    }
	}

	if ($showduedate) {
	    my $duetext = &Apache::lonnavmaps::timeToHumanString($date, '', $format);
	    if ($target eq 'web') {
		if (lc($style) !~ 'plain') { 
		    $result ='<table border="on"><tr><td>Due '.$duetext.'</td></tr></table>';
		} else {
		    $result=&mt('Due').' '.$duetext;
		}
	    } elsif ($target eq 'tex') {
		# For TeX we'll make the duedate tag work exactly like the 
		# duedate tag for web.

		my $duetext = &Apache::lonnavmaps::timeToHumanString($date, '', $format);
		if (lc($style) !~ 'plain') {
		    # The due date will be put in a box.
		    # at the start of the line to ensure it won't overlap
		    # the 1 col boundary.

		    $result = '\vspace{1.0 ex} \framebox{'
    			       .&mt('Due').' '.$duetext.'}';
		} else {
		    $result = &mt('Due') . ' '.$duetext;
		}
	    }
	}
     
    } 
    if ( $target eq 'edit' ) {
	$result=&Apache::edit::tag_start($target,$token);
	$result.='</td></tr>';
	$result.=&Apache::edit::end_table();
	
    }
    return $result;
}

sub end_displayduedate {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
    my @result;
    if ($target eq 'edit') { $result[1]='no'; }
    return @result;
}

sub start_displaytitle {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
    my $result='';
    if (exists($Apache::outputtags::showonce{'displayduetitle'})) {
	return '';
    } else {
	$Apache::outputtags::showonce{'displayduetitle'}=1;
    }
    my $name=&Apache::structuretags::get_resource_name();
    my $style = &Apache::lonxml::get_param('style',$parstack,$safeeval);
    if ($target eq 'web') {
	$result=$name;
	if (lc($style) !~ 'plain') { $result="<h1>$name</h1>"; }
    } elsif ($target eq 'edit') {
	$result=&Apache::edit::tag_start($target,$token);
	$result.='</td></tr>';
	$result.=&Apache::edit::end_table();
    } elsif ($target eq 'tex' and $Apache::lonhomework::type ne 'exam') {
	$name=&Apache::lonxml::latex_special_symbols($name);
	$name = &substitute_simple_tags_latex($name);
	if (lc($style) !~ 'plain') { 
	    $result='\vskip 0 mm\noindent\textbf{'.$name.'}\vskip 0 mm';
	} else {
	    $result=$name;
	}
    }
    return $result;
}

sub end_displaytitle {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
    my @result;
    if ($target eq 'edit') { $result[1]='no'; }
    return @result;
}

sub multipart {
    my ($uri)=@_;
    if (!defined($uri)) { $uri=$env{'request.uri'}; }
    my ($symb)=&Apache::lonnet::whichuser();

    my @parts;
    my $metadata = &Apache::lonnet::metadata($uri,'packages');
    foreach (split(/\,/,$metadata)) {
	if ($_ =~ /^part_(.*)$/) {
	    my $part = $1;
	    if ($part ne '0' 
		&& !&Apache::loncommon::check_if_partid_hidden($part, 
							       $symb)) {
		push(@parts,$part);
	    }
	}
    }
    return @parts;
}

sub start_displayweight {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
    my $result;
    if (exists($Apache::outputtags::showonce{'displayweight'})) {
	if(grep(/^\Q$Apache::inputtags::part\E$/,
		@{$Apache::outputtags::showonce{'displayweight'}})) {
	    return '';
	}
    }
    push(@{$Apache::outputtags::showonce{'displayweight'}},
	 $Apache::inputtags::part);
    if ($target eq 'web' || $target eq 'tex') {
	my $id = $Apache::inputtags::part;
	if ($id ne '0') {
	    my $weight = &Apache::lonnet::EXT("resource.$id.weight");
	    if (!defined($weight) || ($weight eq '')) { $weight=1; }
	    $result.=$weight;
	} else {
	    my @parts=&multipart($env{'request.uri'});
	    my $weight;
	    if (@parts) {
	        foreach my $part (@parts) {
		    my $pweight=&Apache::lonnet::EXT("resource.$part.weight");
		    if (!defined($pweight) || ($pweight eq '')) { $pweight=1; }
		    $weight+=$pweight;
	        }
	    } else {
		$weight = &Apache::lonnet::EXT("resource.$id.weight");
                if (!defined($weight) || ($weight eq '')) { $weight=1; }
	    }
	    $result=$weight;
	}
    } elsif ( $target eq 'edit' ) {
	$result=&Apache::edit::tag_start($target,$token);
	$result.='</td></tr>';
	$result.=&Apache::edit::end_table();
    }
    return $result;
}

sub end_displayweight {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
    my @result;
    if ($target eq 'edit') { $result[1]='no'; }
    return @result;
}

sub start_displaystudentphoto {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
    my $result;
    my (undef,undef,$domain,$user) = &Apache::lonnet::whichuser();
    if ($target eq 'web' && $user eq $env{'user.name'}) {
	my $url=&Apache::lonnet::studentphoto($domain,$user,"gif");
	my $args;
	my $width=&Apache::lonxml::get_param('width',$parstack,$safeeval);
	if ($width) { $args.=" width=\"$width\" "; }
	my $height=&Apache::lonxml::get_param('height',$parstack,$safeeval);
	if ($height) { $args.=" height=\"$height\" "; }
	my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval);
	if ($align) { $args.=" align=\"$align\" "; }
	$result.=" <img $args src=\"$url\" alt=\"$user\@$domain\" />";
    }
    if ($target eq 'tex' && $env{'request.role'} =~ /^cc/) {
	my $url=&Apache::lonnet::studentphoto($domain,$user,"eps");
        my $uhome=&Apache::lonnet::homeserver($user,$domain);
	my $request=new HTTP::Request('GET',$url);
        my $response=&LONCAPA::LWPReq::makerequest($uhome,$request,'','','',1);
	if ($response->is_success) {
	    my $file=$user."_".$domain."_studentphoto.eps";
	    open(FILE,">",$Apache::lonnet::perlvar{'lonPrtDir'}."/$file");
	    print FILE $response->content;
	    close(FILE);
	    my $width_param=&Apache::londefdef::image_size($Apache::lonnet::perlvar{'lonPrtDir'}."/$file",'0.3',$parstack,$safeeval);
	    $result.=' \graphicspath{{'.$Apache::lonnet::perlvar{'lonPrtDir'}.
		'}}\includegraphics[width='.$width_param.' mm]{'.$file.'} ';
	} else {
	    $result="$user\@$domain";
	}
    }
    return $result;
}

sub end_displaystudentphoto {
    my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
    my @result;
    if ($target eq 'edit') { $result[1]='no'; }
    return @result;
}

1;
__END__


=head1 NAME

Apache::outputtags;

=head1 SYNOPSIS

Handles tags associated with output. Seems to
relate to due dates of the assignment.

This is part of the LearningOnline Network with CAPA project
described at http://www.lon-capa.org.

=head1 SUBROUTINES

=over

=item start_displayduedate()

=item initialize_outputtags()

Empties the hash of tags that have already been displayed that should only be displayed once.

=item end_displayduedate()

=item start_displaytitle()

=item end_displaytitle()

=item multipart()

=item start_displayweight()

=item end_displayweight()

=item start_displaystudentphoto()

=item end_displaystudentphoto()


=back

=cut

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>