diff --git a/lib/PGalias.pm b/lib/PGalias.pm
index 6b4ec6e028..26593aec8a 100644
--- a/lib/PGalias.pm
+++ b/lib/PGalias.pm
@@ -14,682 +14,378 @@
################################################################################
package PGalias;
+use parent PGcore; # This is so that a PGalias object can call the PGcore warning_message and debug_message methods.
+
use strict;
-use Exporter;
+use warnings;
+
use UUID::Tiny ':std';
use PGcore;
use PGresource;
-our @ISA = qw ( PGcore ); # look up features in PGcore -- in this case we want the environment.
-
-=head2 new
-
- Create one alias object per question (and per PGcore object since there is a unique PGcore per question.)
- Check that information is intact
- Construct unique id stub seeds -- the id stub seed is for this PGalias object which is
- attached to all the resource files (except equations) for this question.
- Maintain list of links to external resources
-
-=cut
-
sub new {
- my $class = shift;
- my $envir = shift; #pointer to environment hash
- my %options = @_;
- warn "PGlias must be called with an environment" unless ref($envir) =~ /HASH/;
- my $self = {
- envir => $envir,
- search_list => [ { url => 'foo', dir => '.' } ], # for subclasses -> list of url/directories to search
- resource_list => {},
- %options,
-
- };
- bless $self, $class;
- $self->initialize;
- $self->check_parameters;
- return $self;
-}
-
-sub add_resource {
- my $self = shift;
- my ($aux_file_id, $resource) = @_;
- if (ref($resource) =~ /PGresource/) {
- $self->{resource_list}->{$aux_file_id} = $resource;
- #$self->debug_message("$aux_file_id resource added");
- } else {
- $self->warning_message("$aux_file_id does not refer to a a valid resource $resource");
- }
-}
+ my ($class, $envir, %options) = @_;
+ warn 'PGlias must be called with an environment' unless ref($envir) =~ /HASH/;
+ my $self = bless { envir => $envir, resource_list => {}, %options }, $class;
-sub get_resource {
- my $self = shift;
- my $aux_file_id = shift;
- $self->{resource_list}->{$aux_file_id};
-}
-
-# methods
-# make_alias -- outputs url and does what needs to be done
-# normalize paths (remove extra precursors to the path)
-# search directories for item
-# make_links -- in those cases where links need to be made
-# create_files -- e.g. when printing hardcopy
-# dispatcher -- decides what needs to be done based on displayMode and file type
-# alias_for_html
-# alias_for_image_in_html image includes gif, png, jpg, swf, svg, flv?? ogg??, js
-# alias_for_image_in_tex
-
-sub initialize {
- my $self = shift;
- my $envir = $self->{envir};
-
- $self->{pgFileName} = $envir->{probFileName} // '';
+ $self->{probFileName} = $envir->{probFileName} // '';
$self->{htmlDirectory} = $envir->{htmlDirectory};
$self->{htmlURL} = $envir->{htmlURL};
$self->{tempDirectory} = $envir->{tempDirectory};
$self->{templateDirectory} = $envir->{templateDirectory};
$self->{tempURL} = $envir->{tempURL};
- $self->{psvn} = $envir->{psvn};
$self->{displayMode} = $envir->{displayMode};
- $self->{problemSeed} = $envir->{problemSeed};
- $self->{problemUUID} = $envir->{problemUUID} // 0;
- # Find auxiliary files even when the main file is in templates/tmpEdit
- # FIXME: This shouldn't be done here. Instead the front end should pass in the problem source with the file name.
+ # Find auxiliary files even when the main file is in templates/tmpEdit.
+ # FIXME: This shouldn't be done here. Instead the front end should pass in the problem source with the file name.
# The other instance of this in PGloadfiles.pm needs to be removed.
- $self->{pgFileName} =~ s!(^|/)tmpEdit/!$1!;
-
- $self->{ext} = '';
+ $self->{probFileName} =~ s!(^|/)tmpEdit/!$1!;
- # Create an ID which is unique for the given psvn, problemSeed, and problemUUID.
- # It is the responsibility of the caller to pass in a problemUUID that will provide the required uniqueness.
- # That could include a course name, a student login name, etc.
+ # Create an ID which is unique for the given psvn, problemSeed, and problemUUID. It is the responsibility of the
+ # caller to pass in a problemUUID that will provide the required uniqueness. That could include a course name, a
+ # student login name, etc.
$self->{unique_id_stub} = create_uuid_as_string(UUID_V3, UUID_NS_URL,
- join('-', $self->{psvn}, $self->{problemSeed}, $self->{problemUUID}));
-}
+ join('-', $envir->{psvn} // (), $envir->{problemSeed}, $envir->{problemUUID} // ()));
+
+ # Check the parameters.
+ $self->warning_message('The displayMode is not defined') unless $self->{displayMode};
+ $self->warning_message('The htmlDirectory is not defined.') unless $self->{htmlDirectory};
+ $self->warning_message('The htmlURL is not defined.') unless $self->{htmlURL};
+ $self->warning_message('The tempURL is not defined.') unless $self->{tempURL};
-sub check_parameters {
- my $self = shift;
+ return $self;
+}
- # Problem specific data
- $self->warning_message('The current problem set version number (psvn) is not defined')
- unless defined $self->{psvn};
- $self->warning_message('The displayMode is not defined') unless $self->{displayMode};
+# This cache's auxiliary files within a single PG problem.
+sub add_resource {
+ my ($self, $aux_file_id, $resource) = @_;
+ if (ref($resource) =~ /PGresource/) {
+ $self->{resource_list}{$aux_file_id} = $resource;
+ } else {
+ $self->warning_message(qq{"$aux_file_id" does not refer to a valid resource.});
+ }
+ return;
+}
- # required directory addresses (and URL address)
- warn 'htmlDirectory is not defined.' unless $self->{htmlDirectory};
- warn 'htmlURL is not defined.' unless $self->{htmlURL};
- warn 'tempURL is not defined.' unless $self->{tempURL};
+sub get_resource {
+ my ($self, $aux_file_id) = @_;
+ return $self->{resource_list}{$aux_file_id};
}
sub make_resource_object {
- my $self = shift;
- my $aux_file_id = shift;
- my $ext = shift;
- my $resource = PGresource->new(
- $self, #parent alias of resource
+ my ($self, $aux_file_id, $ext) = @_;
+ return PGresource->new(
+ $self, # parent alias of resource
$aux_file_id, # resource file name
$ext, # resource type
- WARNING_messages => $self->{WARNING_messages}, #connect warning message channels
+ WARNING_messages => $self->{WARNING_messages}, # connect warning message channels
DEBUG_messages => $self->{DEBUG_messages},
);
- return $resource;
}
-=head2 make_alias
-
-This is the workhorse of the PGalias module. It's front end is alias() in PG.pl.
-
-make_alias magically takes a name of an external resource ( html file, png file, etc.)
-and creates full directory addresses and uri's appropriate to the current displayMode.
-It also does any necessary conversions behind the scenes.
-
-Returns the uri of the resource.
-
-=cut
-
sub make_alias {
- my $self = shift;
- my $aux_file_id = shift;
- #$self->debug_message("make alias for file $aux_file_id");
- $self->warning_message("Empty string used as input into the function alias") unless $aux_file_id;
-
- my $displayMode = $self->{displayMode};
-
- # $adr_output is a url in HTML mode
- # and a complete directory path in TEX mode.
- my $adr_output;
- my $ext = '';
-
-#######################################################################
- # determine file type
- # determine display mode
- # dispatch
-#######################################################################
- # determine extension, if there is one
- # if extension exists use the value for $ext
- # files without extensions are flagged with errors.
- # The extension is retained as part of aux_file_id
-
- #$self->debug_message("This auxiliary file id is $aux_file_id" );
+ my ($self, $aux_file_id) = @_;
+ $self->warning_message('Empty string used as input into the function alias') unless $aux_file_id;
+
+ # Determine the file extension, if there is one. Files without extensions are flagged with errors.
+ my $ext;
if ($aux_file_id =~ m/\.([^\.]+)$/) {
$ext = $1;
} else {
- $self->warning_message("The file name $aux_file_id did not have an extension.
"
- . "Every file name used as an argument to alias must have an extension.
"
- . "The permissable extensions are .jpg, .pdf, .gif, .png, .mpg, .mp4, .ogg, .webm and .html .
");
- $ext = undef;
- return undef; #quit;
+ $self->warning_message(qq{The file name "$aux_file_id" does not have an extension. }
+ . 'Every file name used as an argument to alias must have an extension. The permissable extensions are '
+ . '.gif, .jpg, .png, .svg, .pdf, .mp4, .mpg, .ogg, .webm, .css, .js, .nb, .csv, .tgz, and .html.');
+ return;
}
- # $self->debug_message("This auxiliary file id is $aux_file_id of type $ext" );
-
-###################################################################
- # Create resource object
-###################################################################
- #$self->debug_message("creating resource with id $aux_file_id");
-
- ###################################################################
- # This section checks to see if a resource exists (in this question)
- # for this particular aux_file_id.
- # If so, we simply return the appropriate uri for the file.
- # The displayMode will be the same throughout the processing of the .pg file
- # This effectively cache's auxiliary files within a single PG question.
- ###################################################################
- unless (defined $self->get_resource($aux_file_id)) {
- $self->add_resource(
- $aux_file_id,
- $self->make_resource_object(
- $aux_file_id, # resource file name
- $ext # resource type
- )
-
- );
+ # Checks to see if a resource exists for this particular aux_file_id.
+ # If not, then create one. Otherwise, return the URI for the existing resource.
+ unless (defined $self->get_resource($aux_file_id)) {
+ $self->add_resource($aux_file_id, $self->make_resource_object($aux_file_id, $ext));
} else {
- #$self->debug_message( "found existing resource_object $aux_file_id");
- return $self->get_resource($aux_file_id)->uri();
+ return $self->get_resource($aux_file_id)->uri;
}
- ###################################################################
+
+ # $output_location is a URL in HTML mode and a complete directory path in TeX mode.
+ my $output_location;
if ($ext eq 'html') {
- $adr_output = $self->alias_for_html($aux_file_id, $ext);
- } elsif ($ext =~ /^(gif|jpg|png|svg|pdf|mp4|mpg|ogg|webm|css|js|nb|tgz)$/) {
- if ($displayMode =~ /^HTML/ or $displayMode eq 'PTX') {
- $adr_output = $self->alias_for_html($aux_file_id, $ext);
- } elsif ($displayMode eq 'TeX') {
- ################################################################################
- # .gif FILES in TeX mode
- ################################################################################
- $adr_output = $self->alias_for_tex($aux_file_id, $ext);
+ $output_location = $self->alias_for_html($aux_file_id, $ext);
+ } elsif ($ext =~ /^(gif|jpg|png|svg|pdf|mp4|mpg|ogg|webm|css|js|nb|csv|tgz)$/) {
+ if ($self->{displayMode} =~ /^HTML/ or $self->{displayMode} eq 'PTX') {
+ $output_location = $self->alias_for_html($aux_file_id, $ext);
+ } elsif ($self->{displayMode} eq 'TeX') {
+ $output_location = $self->alias_for_tex($aux_file_id, $ext);
} else {
- die "Error in alias: PGalias.pm: unrecognizable displayMode = $displayMode";
+ $self->warning_message("Error creating resource alias. Unrecognizable displayMode: $self->{displayMode}");
}
- # } elsif ($ext eq 'svg') {
- # if ($displayMode =~/HTML/) {
- # $self->warning_message("The image $aux_file_id of type $ext cannot yet be displayed in HTML mode");
- # # svg images need an embed tag not an image tag -- need to modify image for this also
- # # an alternative (not desirable) is to convert svg to png
- # } elsif ($displayMode eq 'TeX') {
- # $self->warning_message("The image $aux_file_id of type $ext cannot yet be displayed in TeX mode");
- # } else {
- # die "Error in alias: PGalias.pm: unrecognizable displayMode = $displayMode";
- # }
-
- } else { # $ext is not recognized
- ################################################################################
- # FILES with unrecognized file extensions in any display modes
- ################################################################################
-
- warn "Error in the macro alias. Alias does not understand how to process files with extension $ext.
- (Path to problem file is " . $self->{pgFileName} . ") ";
+ } else {
+ # $ext is not recognized
+ $self->warning_message(qq{Error creating resource alias. Files with extension "$ext" are not allowed.\n}
+ . qq{(Path to problem file is "$self->{probFileName}".)});
}
- $self->warning_message(
- "The macro alias was unable to form a URL for the auxiliary file |$aux_file_id| used in this problem.")
- unless $adr_output;
+ $self->warning_message(qq{Unable to form a URL for the auxiliary file "$aux_file_id" used in this problem.})
+ unless $output_location;
- # $adr_output is a url in HTML modes
- # and a complete path in TEX mode.
- my $resource_object = $self->get_resource($aux_file_id);
- # TEXT(alias() ) is expecting only a single item not an array
- # so the code immediately below for adding extra information to alias is a bad idea.
- #return (wantarray) ? ($adr_output, $resource_object): $adr_output;
- # Instead we'll implement a get_resource() command in PGcore and PG
- return ($adr_output);
+ return $output_location;
}
sub alias_for_html {
- my $self = shift; #handed alias object
- my $aux_file_id = shift; #handed the name of the resource object
- # case 1: aux_file_id is complete or relative path to file
- # case 2: aux_file_id is file name alone relative to the templates directory.
- my $ext = shift;
- #$self->debug_message("handling $aux_file_id of type $ext");
-#######################
- # gather needed data and declare it locally
-#######################
- my $htmlURL = $self->{htmlURL};
- my $htmlDirectory = $self->{htmlDirectory};
- my $pgFileName = $self->{pgFileName};
- my $tempURL = $self->{tempURL};
- my $tempDirectory = $self->{tempDirectory};
- my $templateDirectory = $self->{templateDirectory};
-
-#######################
- # retrieve PGresponse resource object
-#######################
- my ($resource_uri);
- my $resource_object = $self->get_resource($aux_file_id);
- # $self->debug_message( "\nresource for $aux_file_id is ", ref($resource_object), $resource_object );
+ my ($self, $aux_file_id, $ext) = @_;
-##############################################
- # Find complete path to the original files
-##############################################
+ my $resource_object = $self->get_resource($aux_file_id);
- # get the directories that might contain html files
- my $dirPath = '';
- if ($ext eq 'html') {
- $dirPath = 'htmlPath';
- } else {
- $dirPath = 'imagesPath';
+ if ($aux_file_id =~ /https?:/) {
+ # External URL.
+ $resource_object->uri($aux_file_id);
+ return $resource_object->uri; # External URLs need no further processing.
}
- my @aux_files_directories = @{ $self->{envir}->{$dirPath} };
- if ($pgFileName) {
+ # Get the directories that might contain auxiliary files.
+ my @aux_files_directories = @{ $self->{envir}{ $ext eq 'html' ? 'htmlPath' : 'imagesPath' } };
+ if ($self->{probFileName}) {
# Replace "." with the current pg problem file directory.
- my $current_pg_directory = $self->directoryFromPath($pgFileName);
- $current_pg_directory = $self->{templateDirectory} . $current_pg_directory;
- @aux_files_directories = map { $_ eq '.' ? $current_pg_directory : $_ } @aux_files_directories;
+ @aux_files_directories =
+ map { $_ eq '.' ? $self->{templateDirectory} . $self->directoryFromPath($self->{probFileName}) : $_ }
+ @aux_files_directories;
} else {
@aux_files_directories = grep { $_ ne '.' } @aux_files_directories;
}
- # Find complete path to the original file
- my $file_path;
- if ($aux_file_id =~ /https?:/) { #external link_file
- $resource_object->uri($aux_file_id); #no unique id is needed -- external link doc
- $resource_object->{copy_link}->{type} = 'external';
- $resource_object->{uri}{is_accessible} = 1; # Assume a url is accessible.
- return $resource_object->uri; # external links need no further processing
- } elsif ($aux_file_id =~ m|^/|) {
- $file_path = $aux_file_id;
- } else {
- $file_path = $self->find_file_in_directories($aux_file_id, \@aux_files_directories);
+ # Find the complete path to the original file.
+ my $file_path =
+ $aux_file_id =~ m|^/| ? $aux_file_id : $self->find_file_in_directories($aux_file_id, \@aux_files_directories);
+
+ unless ($file_path) {
+ $self->warning_message(qq{Unable to find file "$aux_file_id".});
+ return;
}
- # $self->debug_message("file path is $file_path");
-
-##################### Case1: we've got a full pathname to a file in either the temp directory or the htmlDirectory
-##################### Case2: we assume the file is in the same directory as the problem source file
-##################### Case3: the file could have an external url
-
-##############################################
- # store the complete path to the original file
- # calculate the uri (which is a url suitable for the browser relative to the current site)
- # store the uri.
- # record status of the resource
-##############################################
- if ($file_path =~ m|^$tempDirectory|) { #case: file is stored in the course temporary directory
- $resource_uri = $file_path;
- $resource_uri =~ s|$tempDirectory|$tempURL|;
- $resource_object->uri($resource_uri); #no unique id is needed -- public doc
+
+ # Store the complete path to the original file, and calculate and store the URI (which is a URL suitable for the
+ # browser relative to the current site).
+ if ($file_path =~ m|^$self->{tempDirectory}|) {
+ # File is in the course temporary directory.
+ $resource_object->uri($file_path =~ s|$self->{tempDirectory}|$self->{tempURL}|r);
$resource_object->path($file_path);
- $resource_object->{copy_link}->{type} = 'orig';
- $resource_object->{path}->{is_complete} = (-r $resource_object->path);
- } elsif ($file_path =~ m|^$htmlDirectory|) { #case: file is under the course html directory
- $resource_uri = $file_path;
- $resource_uri =~ s|$htmlDirectory|$htmlURL|;
- $resource_object->uri($resource_uri);
+ } elsif ($file_path =~ m|^$self->{htmlDirectory}|) {
+ # File is in the course html directory.
+ $resource_object->uri($file_path =~ s|$self->{htmlDirectory}|$self->{htmlURL}|r);
$resource_object->path($file_path);
- $resource_object->{copy_link}->{type} = 'orig';
- $resource_object->{path}->{is_complete} = (-r $resource_object->path);
- ####################################################
- # one can add more public locations such as the site htdocs directory here in the elsif chain
- ####################################################
- } else { #case: resource is in a directory which is not public
- # most often this is the directory containing the .pg file
- # these files require a link to the temp Directory
- # $self->debug_message("source file path ", $sourceFilePath);
+ } else {
+ # Resource is in a directory which is not public.
+ # Most often this is the directory containing the .pg file.
+ # These files need to be linked to from the public html temporary directory.
$resource_object->path($file_path);
- $resource_object->{copy_link}->{type} = 'link';
- $resource_object->{path}->{is_complete} = 0;
- $resource_object->{uri}->{is_complete} = 0;
- warn "$ext not defined" unless $ext;
+ $self->warning_message("File extension for resource $file_path is not defined") unless $ext;
$resource_object->create_unique_id($ext);
- # notice the resource uri is not yet defined -- we have to make the link first
- }
-##############################################
- # Create links for objects of "link" type.
- # between private directories such as myCourse/template
- # and public directories (such as wwtmp/courseName or myCourse/html
- # The location of the links depends on the type and location of the file
-##############################################
- # create_link_to_tmp_file()
- #input: resource object, ext, (html) (tempURL),
- #return: uri
- if ($resource_object->{copy_link}->{type} eq 'link') {
- # this creates a link from the original file to an alias in the tmp/html directory
- # and places information about the path and the uri in the PGresponse object $resource_object
- my $subdir = '';
- if ($ext eq 'html') {
- $subdir = 'html';
- } else {
- $subdir = 'images';
- }
- $self->create_link_to_tmp_file(resource => $resource_object, subdir => $subdir);
+ # Create a link from the original file to an alias in the temporary public html directory.
+ $self->create_link_to_tmp_file($resource_object, $ext eq 'html' ? 'html' : 'images');
}
-################################################################################
- # Return full url to image file (resource_id)
-################################################################################
- $resource_object->uri(); # return the uri of the resource -- in this case the URL for the file in the temp directory
+ # Return the URI of the resource.
+ return $resource_object->uri;
}
-################################################################################
-# alias for image in tex mode
-################################################################################
-
sub alias_for_tex {
- my $self = shift; #handed alias object
- my $aux_file_id = shift; #handed the name of the resource object
- # case 1: aux_file_id is complete or relative path to file
- # case 2: aux_file_id is file name alone relative to the templates directory.
- my $ext = shift;
-
- my $from_file_type = $ext;
- my $to_file_type = "png"; # needed for conversion cases
-
- my $convert_fileQ = (
- $ext eq 'gif' # gif files need to be converted
- # or $ext eq 'pdf' # other image types for tex
- # or $ext eq 'jpg'
- # or $ext eq 'svg'
- # or $ext eq 'html'
- ) ? 1 : 0; # does this file need conversion
-
- my $link_fileQ = 0; # does this file need to be linked?
- my $targetDirectory = ($ext eq 'html') ? 'html' : 'images'; # subdirectory of tmp directory
-
-#######################
- # gather needed data and declare it locally
-#######################
- my $htmlURL = $self->{htmlURL};
- my $htmlDirectory = $self->{htmlDirectory};
- my $pgFileName = $self->{pgFileName};
- my $tempURL = $self->{tempURL};
- my $tempDirectory = $self->{tempDirectory};
- my $templateDirectory = $self->{templateDirectory};
-
-#######################
- # retrieve PGresponse resource object
-#######################
- my ($resource_uri);
- my $resource_object = $self->get_resource($aux_file_id);
- #warn ( "\nresource for $aux_file_id is ", ref($resource_object), $resource_object );
+ my ($self, $aux_file_id, $ext) = @_;
-##############################################
- # Find complete path to the original files
-##############################################
+ my $resource_object = $self->get_resource($aux_file_id);
- # get the directories that might contain html files
- my $dirPath = '';
- if ($ext eq 'html') {
- $dirPath = 'htmlPath';
- } else {
- $dirPath = 'imagesPath';
+ if ($aux_file_id =~ /https?:/) {
+ # External URL.
+ $resource_object->uri($aux_file_id);
+ return $resource_object->uri; # External URLs need no further processing.
}
- my @aux_files_directories = @{ $self->{envir}->{$dirPath} };
- if ($pgFileName) {
+ # Get the directories that might contain auxiliary files.
+ my @aux_files_directories = @{ $self->{envir}{ $ext eq 'html' ? 'htmlPath' : 'imagesPath' } };
+ if ($self->{probFileName}) {
# Replace "." with the current pg problem file directory.
- my $current_pg_directory = $self->directoryFromPath($pgFileName);
+ my $current_pg_directory = $self->directoryFromPath($self->{probFileName});
$current_pg_directory = $self->{templateDirectory} . $current_pg_directory;
@aux_files_directories = map { $_ eq '.' ? $current_pg_directory : $_ } @aux_files_directories;
} else {
@aux_files_directories = grep { $_ ne '.' } @aux_files_directories;
}
- # Find complete path to the original file
- my $file_path;
- if ($aux_file_id =~ /https?:/) { # external link_file
- $resource_object->uri($aux_file_id); #no unique id is needed -- external link doc
- $resource_object->{copy_link}->{type} = 'external';
- $resource_object->{uri}{is_accessible} = 1; # Assume a url is accessible.
- return $resource_object->uri; # external links need no further processing
- } elsif ($aux_file_id =~ m|^/|) {
- $file_path = $aux_file_id;
- } else {
- $file_path = $self->find_file_in_directories($aux_file_id, \@aux_files_directories);
+ # Find complete path to the original file.
+ my $file_path =
+ $aux_file_id =~ m|^/| ? $aux_file_id : $self->find_file_in_directories($aux_file_id, \@aux_files_directories);
+
+ unless ($file_path) {
+ $self->warning_message(qq{Unable to find "$aux_file_id" in any of the allowed auxiliary file directories.});
+ return;
}
- #warn ("file path is $file_path");
-
-##################### Case1: we've got a full pathname to a file in either the temp directory or the htmlDirectory
-##################### Case2: we assume the file is in the same directory as the problem source file
-##################### Case3: the file could have an external url
-
-##############################################
- # store the complete path to the original file
- # calculate the uri (which is a url suitable for the browser relative to the current site)
- # store the uri.
- # record status of the resource
-##############################################
-
- if ($file_path =~ m|^$tempDirectory|) { #case: file is stored in the course temporary directory
-
- my $sourceFilePath = $file_path;
- $resource_object->path($sourceFilePath);
- $resource_object->{path}->{is_complete} = 1;
- #warn("tempDir filePath ",$resource_object->path, "\n");
- # Gif files always need to be converted to png files for inclusion in pdflatex documents.
-
- $resource_object->{convert}->{needed} = $convert_fileQ;
- $resource_object->{convert}->{from_path} = $sourceFilePath;
- $resource_object->{convert}->{from_type} = $from_file_type;
- $resource_object->{convert}->{to_path} = ''; #define later
- $resource_object->{convert}->{to_type} = $to_file_type;
- } elsif ($file_path =~ m|^$htmlDirectory|) { #case: file is under the course html directory
-
- my $sourceFilePath = $aux_file_id;
- $resource_object->path($sourceFilePath);
- $resource_object->{path}->{is_complete} = 1;
-
- $resource_object->{convert}->{needed} = $convert_fileQ;
- $resource_object->{convert}->{from_path} = $sourceFilePath;
- $resource_object->{convert}->{from_type} = $from_file_type;
- $resource_object->{convert}->{to_path} = ''; #define later
- $resource_object->{convert}->{to_type} = $to_file_type;
- #warn ("htmlDir filePath ",$resource_object->path, "\n");
+ # Store the complete path to the original file.
+ if ($file_path =~ m|^$self->{tempDirectory}|) {
+ # File is in the course temporary directory.
+ $resource_object->path($file_path);
+ } elsif ($file_path =~ m|^$self->{htmlDirectory}|) {
+ # File is in the course html directory.
+ $resource_object->path($aux_file_id);
} else {
-
$resource_object->path($file_path);
- $resource_object->{path}->{is_complete} = (-r $resource_object->path);
-
- $resource_object->{convert}->{needed} = $convert_fileQ;
- $resource_object->{convert}->{from_path} = $resource_object->path();
- $resource_object->{convert}->{from_type} = $from_file_type;
- $resource_object->{convert}->{to_path} = ''; #define later
- $resource_object->{convert}->{to_type} = $to_file_type;
- #warn ("templateDir filePath ",$resource_object->path, "\n");
- # notice the resource uri is not yet defined -- we have to make the link first
}
-################################################################################
- # Convert images to .png files if needed
-################################################################################
- if ($resource_object->{convert}->{needed}) { #convert .gif to .png
-
- $self->convert_file_to_png_for_tex(
- resource => $resource_object,
- targetDirectory => $targetDirectory
- );
- } else { # no conversion needed
- $resource_object->uri($resource_object->path()); #path and uri are the same in this case.
- $resource_object->{uri}->{is_complete} = 1;
- $resource_object->{uri}->{is_accessible} = (-r $resource_object->uri());
+ if ($ext eq 'gif' || $ext eq 'svg') {
+ # Convert gif and svg files to png files.
+ $self->convert_file_to_png_for_tex($resource_object, $ext eq 'html' ? 'html' : 'images');
+ } else {
+ # Path and URI are the same in this case.
+ $resource_object->uri($resource_object->path);
}
-################################################################################
- # Don't need to create aliases in this case because nothing is being served over the web
-################################################################################
- # Return full path to image file (resource_id)
-################################################################################
- #warn ("final filePath ", $resource_object->uri(), "\n");
- #warn "file is a accessible ", $resource_object->{uri}->{is_accessible},"\n";
- # returns a file path
- ($resource_object->{uri}->{is_accessible} == 1) ? $resource_object->uri() : "";
+ # An alias is not needed in this case because nothing is being served over the web.
+ # Return the full path to the image file.
+ return $resource_object->uri && -r $resource_object->uri ? $resource_object->uri : '';
}
-############################################################################
-# Utility for creating link from original file to alias in publically accessible temp directory
-############################################################################
sub create_link_to_tmp_file {
- my $self = shift;
- my %args = @_;
- my $resource_object = $args{resource};
- # warn "resource_object =", ref($resource_object);
- my $unique_id = $resource_object->{unique_id};
- my $ext = $resource_object->{type};
- my $subdir = $args{subdir};
- my $link = "$subdir/$unique_id";
- #################
- # construct resource uri
- #################
- my $resource_uri = $self->{tempURL};
- $resource_uri =~ s|/$||; #remove trailing slash, if any
- $resource_uri = "$resource_uri/$link";
- #################
- # insure that linkPath exists and all intermediate directories have been created
- #################
+ my ($self, $resource_object, $subdir) = @_;
+
+ my $ext = $resource_object->{type};
+ my $link = "$subdir/$resource_object->{unique_id}";
+
+ # Insure that link path exists and all intermediate directories have been created.
my $linkPath = $self->surePathToTmpFile($link);
- if (-e $resource_object->path()) {
- # if resource file exists
- #################
- # destroy the old link.
- #################
+ if (-e $resource_object->path) {
if (-e $linkPath) {
- unlink($linkPath) || $self->warning_message("Unable to unlink alias file at |$linkPath|");
+ # Destroy the old link.
+ unlink($linkPath) or $self->warning_message(qq{Unable to unlink alias file at "$linkPath".});
}
- #################
- # create new link.
- # create uri to this link
- #################
- if (symlink($resource_object->path(), $linkPath)) { #create the symlink
- $resource_object->{path}->{is_accessible} = 1;
- $resource_object->{copy_link}->{link_to_path} = $linkPath;
- $resource_object->{path}->{is_accessible} = (-r $linkPath);
-
- $resource_object->uri($resource_uri);
- $resource_object->{uri}{is_accessible} = 1; # Assume a url is accessible.
- $resource_object->{path}->{is_complete} = 1;
- $resource_object->{uri}->{is_complete} = 1;
+
+ # Create a new link, and the URI to this link.
+ if (symlink($resource_object->path, $linkPath)) {
+ $resource_object->uri(($self->{tempURL} =~ s|/$||r) . "/$link");
} else {
$self->warning_message(
- "The macro alias cannot create a link from |$linkPath| to |" . $resource_object->path() . "|
");
+ qq{The macro alias cannot create a link from "$linkPath" to "} . $resource_object->path . '"');
}
} else {
- # if the resource file doesn't exist
- my $message = ($resource_object->path()) ? " at |" . $resource_object->path() . "|" : " anywhere";
- $self->warning_message(
- "The macro alias cannot find the file: |" . ($resource_object->fileName) . '|' . $message);
- $resource_object->{path}->{is_accessible} = 0;
- $resource_object->{uri}->{is_accessible} = 0;
- # we should delete the resource object in this case?
+ $self->warning_message('Cannot find the file: "'
+ . $resource_object->fileName . '" '
+ . ($resource_object->path ? ' at "' . $resource_object->path . '"' : ' anywhere'));
}
+ return;
}
-############################################################################
-# Utility for converting .gif files to .png for tex
-############################################################################
-
sub convert_file_to_png_for_tex {
- my $self = shift;
- my %args = @_;
- my $resource_object = $args{resource};
- my $targetDirectory = $args{targetDirectory};
- my $conversion_command = WeBWorK::PG::IO::externalCommand('gif2png');
- ################################################################################
- # Create path to new .png file
- # Create new .png file
- # We may not have permission to do this in the template directory
- # so we create the file in the course temp directory.
- ################################################################################
- my $ext = $resource_object->{type};
- $resource_object->create_unique_id($ext);
- my $unique_id = $resource_object->{unique_id};
- $unique_id =~ s|\.[^/\.]*$|.png|;
- my $link = "$targetDirectory/$unique_id";
- my $targetFilePath = $self->surePathToTmpFile($link);
- $resource_object->{convert}->{to_path} = $targetFilePath;
- $self->debug_message("target filePath ", $targetFilePath, "\n");
- my $sourceFilePath = $resource_object->{convert}->{from_path};
- $self->debug_message("convert filePath ", $sourceFilePath, "\n");
- # conversion_command is imported into this subroutine from the config files.
- #$self->debug_message("cat $sourceFilePath | $conversion_command > $targetFilePath");
- my $returnCode = system "cat $sourceFilePath | $conversion_command > $targetFilePath";
- #$resource_object->debug_message( "FILE path $targetFilePath created =", -e $targetFilePath );
- #$resource_object->debug_message( "return Code $returnCode from cat $sourceFilePath | $command > $targetFilePath");
- if ($returnCode or not -e $targetFilePath) {
+ my ($self, $resource_object, $target_directory) = @_;
+
+ $resource_object->create_unique_id($resource_object->{type});
+ my $targetFilePath =
+ $self->surePathToTmpFile("$target_directory/" . ($resource_object->{unique_id} =~ s|\.[^/\.]*$|.png|r));
+ $self->debug_message('target filePath ', $targetFilePath, "\n");
+ my $sourceFilePath = $resource_object->path;
+ $self->debug_message('convert filePath ', $sourceFilePath, "\n");
+
+ my $conversion_command = WeBWorK::PG::IO::externalCommand('convert');
+ my $returnCode = system "$conversion_command '${sourceFilePath}[0]' $targetFilePath";
+ if ($returnCode || !-e $targetFilePath) {
$resource_object->warning_message(
- "returnCode $returnCode: failed to convert $sourceFilePath to $targetFilePath using gif->png with $conversion_command: $!"
- );
+ qq{Failed to convert "$sourceFilePath" to "$targetFilePath" using "$conversion_command": $!});
}
- $resource_object->uri($resource_object->{convert}->{to_path});
- $resource_object->{uri}->{is_complete} = 1;
- $resource_object->{uri}->{is_accessible} = (-r $resource_object->uri());
-}
-################################################
-
-# More resource search macros
-
-################################################
+ $resource_object->uri($targetFilePath);
-#
-# Look for a macro file in the directories specified in the macros path
-#
-
-# ^variable my $macrosPath
-our (
- $macrosPath,
- # ^variable my $pwd
- $pwd,
-);
-
-# ^function findMacroFile
-# ^uses $macrosPath
-# ^uses $pwd
-sub findMacroFile {
- my $self = shift;
- my $fileName = shift;
- my $filePath;
- foreach my $dir (@{$macrosPath}) {
- $filePath = "$dir/$fileName";
- $filePath =~ s!^\.\.?/!$pwd/!; # defined for PGloadFiles but not here
- #FIXME? where is $pwd defined? why did it want to replace ../ with current directory
- return $filePath if (-r $filePath);
- }
- return; # no file found
+ return;
}
sub find_file_in_directories {
- my $self = shift;
- my $file_name = shift;
- my $directories = shift;
- my $file_path;
- foreach my $dir (@$directories) {
- $dir =~ s|/$||; # remove final / if present
- $file_path = "$dir/$file_name";
- return $file_path if (-r $file_path);
+ my ($self, $file_name, $directories) = @_;
+ for my $dir (@$directories) {
+ $dir =~ s|/$||; # Remove final / if present.
+ my $file_path = "$dir/$file_name";
+ return $file_path if -r $file_path;
}
- return; # no file found
-}
-
-# This is a stub for deprecated problems that call this method. Some of the Geogebra problems that do so actually work
-# even though this method fails.
-sub findAppletCodebase {
- return '';
+ return; # No file found.
}
1;
+
+=head1 NAME
+
+PGalias - Create aliases for auxiliary resources.
+
+=head2 new
+
+Usage: C<< PGalias->new($envir, %options) >>
+
+The C constructor. The C<$envir> hash containing the problem
+environment is required. The C<%options> can contain C and
+C which should be array references. These are passed on to all
+C objects constructed for each problem resource and are used by both
+modules to store warning and debug messages.
+
+One C object is created for each C object (which is unique for
+each problem). This object is used to construct unique ids for problem
+resources and maintain a list of the resources used by a problem. A
+unique_id_stub is generated for this C object which is the basis for
+the unique ids generated for resource files (except equation images for the
+"images" display mode) used by the problem.
+
+=head2 get_resource
+
+Usage: C<< $pgAlias->get_resource($aux_file_id) >>
+
+Returns the C object corresponding to C<$aux_file_id>.
+
+=head2 make_alias
+
+Usage: C<< $pgAlias->make_alias($aux_file_id) >>
+
+This is the workhorse of the C module. Its front end is C in
+L.
+
+C takes the name of an auxiliary resource (html file, png file,
+etc.) and creates a file name or URL appropriate to the current display mode.
+It also does any necessary conversions behind the scenes.
+
+It returns the URL of the resource if the display mode is HTML or PTX, and the
+full file path if the display mode is TeX.
+
+=head2 alias_for_html
+
+Usage: C<< $pgAlias->alias_for_html($aux_file_id, $ext) >>
+
+Returns the URL alias for the resource identified by C<$aux_file_id> with the
+file name extension C<$ext>.
+
+=head2 alias_for_tex
+
+Usage: C<< $pgAlias->alias_for_tex($aux_file_id, $ext) >>
+
+Returns the full file path alias for the resource identified by C<$aux_file_id>
+with the file name extension C<$ext>.
+
+=head2 create_link_to_tmp_file
+
+Usage: C<< $pgAlias->create_link_to_tmp_file($resource_object, $subdir) >>
+
+Creates a symbolic link in the subdirectory C<$subdir> of the publicly
+accessible temporary directory to the file (usually in a course's templates
+directory) represented by the C referenced by C<$resource_object>.
+The link name is the file unique id alias.
+
+=head2 convert_file_to_png_for_tex
+
+Usage: C<< $pgAlias->convert_file_to_png_for_tex($resource_object, $target_directory) >>
+
+Converts a "gif" or "svg" file to a "png" file. The "png" file is saved in
+C<$target_directory> and the file name is the unique id alias for the
+C referenced by C<$resource_object>.
+
+=head2 find_file_in_directories
+
+Usage: C<< $pgAlias->find_file_in_directories($file_name, $directories) >>
+
+Finds the first directory in the array of directory names referenced to by
+C<$directories> that contains a readable file named C<$file_name>, and returns
+the full path of that file.
+
+=cut
diff --git a/lib/PGcore.pm b/lib/PGcore.pm
index 75f0d15eec..ade9a9fb8c 100755
--- a/lib/PGcore.pm
+++ b/lib/PGcore.pm
@@ -782,8 +782,7 @@ sub get_debug_messages {
sub warning_message {
my ($self, @str) = @_;
- # Mark the start of each message.
- push @{ $self->{WARNING_messages} }, '------', @str;
+ push @{ $self->{WARNING_messages} }, @str;
}
sub get_warning_messages {
diff --git a/lib/PGloadfiles.pm b/lib/PGloadfiles.pm
index f410c8eeea..9cf76e944e 100644
--- a/lib/PGloadfiles.pm
+++ b/lib/PGloadfiles.pm
@@ -84,7 +84,6 @@ sub new {
my $self = {
envir => $envir,
macroFileList => {}, # records macros used in compilation
- pgFileName => '', # current pg file being processed
macrosPath => '',
pwd => '', # current directory -- defined in initialize
};
diff --git a/lib/PGresource.pm b/lib/PGresource.pm
index 4494392d5e..bdac8a51ef 100644
--- a/lib/PGresource.pm
+++ b/lib/PGresource.pm
@@ -14,110 +14,137 @@
################################################################################
package PGresource;
+use parent PGcore; # This is so that a PGresource object can call the PGcore warning_message and debug_message methods.
+
use strict;
-use Exporter;
+use warnings;
+
use Scalar::Util;
use UUID::Tiny ':std';
-use PGcore;
-our @ISA = qw( PGcore );
sub new {
- my $class = shift;
- my $parent_alias = shift;
- my $id = shift;
- my $type = shift;
- my %options = @_;
- $type =~ s/^\.//; # remove initial period if included in type.
- my $self = {
-
- id => $id, #auxiliary file name
- parent_alias => $parent_alias,
- type => $type, # gif eps pdf html pg (macro: pl) (applets: java js fla geogebra (ggb) swf )
- parent_file_id => $parent_alias->{pgFileName}, # file id for the file requesting the resource
-
- path => {
- content => undef, # complete file path to resource
- is_complete => 0,
- is_accessible => 0,
- },
- uri => {
- content => undef, # usually url path to resource
- is_complete => 0,
- is_accessible => 0,
- },
- return_uri => '',
- recorded_uri => '',
- convert => {
- needed => 0,
- from_type => undef,
- from_path => undef,
- to_type => undef,
- to_path => undef,
- },
- copy_link => {
- type => undef, # copy or link or orig (original file, no copy or link needed)
- link_to_path => undef, # the path of the alias
- copy_to_path => undef, # the path of the duplicate file
- },
- cache_info => {},
- unique_id => undef,
- %options,
- };
- bless $self, $class;
+ my ($class, $parent_alias, $id, $type, %options) = @_;
+ warn "PGresource must be called with a PGalias parent object."
+ unless ref($parent_alias) =~ /PGalias/;
+
+ my $self = bless {
+ id => $id, # auxiliary file name
+ parent_alias => $parent_alias,
+ type => $type =~ s/^\.//r, # file extension
+ probFileName => $parent_alias->{probFileName},
+ unique_id => undef,
+ path => undef, # complete file path to resource
+ uri => undef, # URL path (or complete file path for TeX) to resource
+ %options
+ }, $class;
+
Scalar::Util::weaken($self->{parent_alias});
- $self->warning_message("PGresource must be called with an alias object") unless ref($parent_alias) =~ /PGalias/;
- $self->warning_message("PGresource must be called with a name") unless $id;
- $self->warning_message("PGresource must be called with a type") unless $type;
- # $self->warning_message( "Test warning message from resource object");
- # Use this to check if the warning and debug channels have been hooked up to PGcore and PGalias correctly.
- return $self;
-}
-sub uri {
- my $self = shift;
- my $uri = shift;
- $self->{uri}->{content} = $uri if $uri;
- $self->{uri}->{content};
-}
+ $self->warning_message("PGresource must be called with a name.") unless $id;
+ $self->warning_message("PGresource must be called with a type.") unless $type;
-sub path {
- my $self = shift;
- my $url = shift;
- $self->{path}->{content} = $url if $url;
- $self->{path}->{content};
+ # Use this to check if the warning and debug channels have been hooked up to PGcore and PGalias correctly.
+ #$self->warning_message("Test warning message from resource object");
+ #$self->debug_message("Test debug message from resource object");
+
+ return $self;
}
sub create_unique_id {
- my $self = shift;
- my $ext = shift;
+ my ($self, $ext) = @_;
my $fileName = $self->fileName;
+
if ($self->{unique_id}) {
$self->warning_message("unique id already exists for $fileName.");
return $self->{unique_id};
}
- $self->warning_message("auxiliary file $fileName missing resource path ") unless $self->path;
- $self->warning_message("auxiliary file $fileName missing problem psvn") unless $self->{parent_alias}->{psvn};
- $self->warning_message("auxiliary file $fileName missing unique_id_stub")
- unless $self->{parent_alias}->{unique_id_stub};
- my $unique_id_seed = $self->path() . $self->{parent_file_id} . $self->{id};
+
+ $self->warning_message(qq{Auxiliary file "$fileName" missing resource path.}) unless $self->path;
+ $self->warning_message(qq{Auxiliary file "$fileName" missing unique_id_stub.})
+ unless $self->{parent_alias}{unique_id_stub};
+
+ my $unique_id_seed = $self->path . $self->{probFileName} . $self->{id};
$self->{unique_id} =
- $self->{parent_alias}->{unique_id_stub} . '___' . create_uuid_as_string(UUID_V3, UUID_NS_URL, $unique_id_seed);
+ $self->{parent_alias}{unique_id_stub} . '___' . create_uuid_as_string(UUID_V3, UUID_NS_URL, $unique_id_seed);
$self->{unique_id} .= ".$ext" if $ext;
- $self->{unique_id};
+ return $self->{unique_id};
+}
+
+sub uri {
+ my ($self, $uri) = @_;
+ $self->{uri} = $uri if $uri;
+ return $self->{uri};
+}
+
+sub path {
+ my ($self, $path) = @_;
+ $self->{path} = $path if $path;
+ return $self->{path};
}
sub unique_id {
- my $self = shift;
- my $unique_id = shift;
- $self->{unique_id} = $unique_id if $unique_id;
- $self->{unique_id};
+ my $self = shift;
+ return $self->{unique_id};
}
sub fileName {
- my $self = shift;
- my $fileName = shift;
+ my ($self, $fileName) = @_;
$self->{id} = $fileName if $fileName;
- $self->{id};
+ return $self->{id};
}
+
1;
+
+=head1 NAME
+
+PGresource - Store information for an auxiliary resource.
+
+=head2 new
+
+Usage: C<< PGresource->new($parent_alias, $id, $type, %options) >>
+
+The C constructor. The C<$parent_alias>, C<$id>, and C<$type>
+parameters are required. The C<$parent_alias> must be the parent C
+object that calls this constructor (and this is the only situation where this
+object should be constructed). The C<$id> should be the file name (or external
+URL) of the auxiliary resource to be represented by this C object.
+The C<$type> should be the file extension. The C<%options> should contain
+C and C which should be array references.
+These are used to store warning and debug messages.
+
+=head2 create_unique_id
+
+Usage: C<< $pgResource->create_unique_id($ext) >>
+
+This is the primary method of the C module. This generates a unique
+id for the auxiliary resource that it represents. That id takes into account the
+unique id stub of the parent C object, the full path to the resource,
+the problem file name, and the resource file name.
+
+=head2 uri
+
+Usage: C<< $pgResource->uri($uri) >>
+
+Get or set the URI of the resource.
+
+=head2 path
+
+Usage: C<< $pgResource->path($path) >>
+
+Get or set the path of the resource.
+
+=head2 unique_id
+
+Usage: C<< $pgResource->unique_id >>
+
+Get the unique id of the resource. Note that the unique id is set by calling
+C.
+
+=head2 fileName
+
+Usage: C<< $pgResource->fileName($fileName) >>
+
+Get or set the file name (or id) of the resource.
+
+=cut
diff --git a/macros/PG.pl b/macros/PG.pl
index 9ec9de88cb..2037f1de8a 100644
--- a/macros/PG.pl
+++ b/macros/PG.pl
@@ -1486,11 +1486,13 @@ sub ENDDOCUMENT {
}
sub alias {
- $PG->{PG_alias}->make_alias(@_);
+ my $aux_file_id = shift;
+ return $PG->{PG_alias}->make_alias($aux_file_id);
}
sub get_resource {
- $PG->{PG_alias}->get_resource(@_);
+ my $aux_file_id = shift;
+ return $PG->{PG_alias}->get_resource($aux_file_id);
}
sub maketext {
@@ -1502,21 +1504,17 @@ sub insertGraph {
}
sub findMacroFile {
- $PG->{PG_alias}->findMacroFile(@_);
-}
-
-sub findAppletCodebase {
- my $appletName = shift;
- my $url = eval { $PG->{PG_alias}->findAppletCodebase($appletName) };
- # warn is already trapped under the old system
- $PG->warning_message("While using findAppletCodebase to search for applet$appletName: $@") if $@;
- $url;
+ $PG->{PG_loadMacros}->findMacroFile(@_);
}
sub loadMacros {
$PG->{PG_loadMacros}->loadMacros(@_);
}
+# This is a stub for deprecated problems that call this method. Some of the GeoGebra
+# problems that do so actually work even though this method does nothing.
+sub findAppletCodebase { return ''; }
+
## Problem Grader Subroutines
#####################################