From 9682743371a1ecd2c2bdcd0cd4285b32dc90f781 Mon Sep 17 00:00:00 2001 From: Glenn Rice Date: Sat, 12 Nov 2022 22:18:36 -0600 Subject: [PATCH 1/2] Remove WeBWorK::Constants and improve the webwork2 app configuration. The only constants still defined in the WeBWorK::Constants package were the WEBWORK_DIRECTORY and the PG_DIRECTORY. Furthermore, even those were not used much in the code, and they are even set several times in scripts to "avoid an error message" from not having them defined. The few places that these constants were used now either use WEBWORK_ROOT and PG_ROOT environment variables directory (from which the previous constants were set) or use values from the course environment. The CourseEnvironment constructor grabs webwork_dir and pg_dir from the %WeBWorK::SeedCE hash if those parameters are not passed in, and falls back as a last resort to WEBWORK_ROOT and PG_ROOT environment variables. This makes it so that within the webwork app, you do not need to pass the webwork_dir to construct a CourseEnvironment object. Scripts will either need to set the %WeBWorK::SeedCE webwork_dir and pg_dir values, or pass webwork_dir and pg_dir to the CourseEnvironment constructor in its now optional argument, or just ensure the WEBWORK_ROOT and PG_ROOT environment variables are set. Note the old four argument way of calling the CourseEnvironment constructor that has been marked as deprecated since 2004 is now removed entirely. One upshot of this is that the pg_dir is not needed in site.conf (and so is removed), and this now only needs to be set in one place, namely webwork2.mojolicious.yml. The other constants defined throughout the code that were previously set in WeBWorK::Constants are now set from configuration variables in webwork2.mojolicious.yml when the app initializes. The only such constants are the WeBWorK::Debug constants and one WeBWorK::Hardcopy constant. This means that to enable debug logging, you don't need to modify the code anymore. Just enable it in the webwork2.mojolicious.yml file. --- bin/OPL-update | 6 +- bin/OPL-update-legacy | 9 +- bin/addcourse | 2 +- bin/change_user_id | 3 +- bin/delcourse | 3 +- bin/download-OPL-metadata-release.pl | 2 +- bin/dump-OPL-tables.pl | 4 +- bin/dump_past_answers | 6 +- bin/generate-OPL-set-def-lists.pl | 2 +- bin/importClassList.pl | 1 + bin/integrity_check.pl | 3 +- bin/load-OPL-global-statistics.pl | 3 +- bin/newpassword | 1 + bin/remove_stale_images | 2 +- bin/restore-OPL-tables.pl | 3 +- bin/setfilepermissions | 2 +- bin/test_library_build.pl | 5 +- bin/update-OPL-statistics.pl | 3 +- bin/updateOPLextras.pl | 2 +- bin/upgrade-database-to-utf8mb4.pl | 2 +- bin/upgrade_admin_db.pl | 3 +- bin/upload-OPL-statistics.pl | 5 +- bin/webwork2 | 3 - bin/ww_purge_old_nonces | 3 +- bin/wwdb | 3 +- bin/wwsh | 3 +- clients/sendXMLRPC.pl | 1515 ----------------- conf/authen_LTI.conf.dist | 4 +- conf/site.conf.dist | 3 - conf/webwork2.mojolicious.dist.yml | 25 + lib/Caliper/Entity.pm | 5 +- lib/Caliper/ResourceIri.pm | 5 +- lib/Mojolicious/WeBWorK.pm | 9 +- .../WeBWorK/Tasks/LTIMassUpdate.pm | 2 +- .../WeBWorK/Tasks/SendInstructorEmail.pm | 2 +- lib/WeBWorK.pm | 6 +- lib/WeBWorK/Constants.pm | 68 - lib/WeBWorK/ContentGenerator/CourseAdmin.pm | 20 +- .../ContentGenerator/Instructor/Config.pm | 3 +- lib/WeBWorK/CourseEnvironment.pm | 77 +- lib/WeBWorK/Debug.pm | 52 +- lib/WeBWorK/Localize.pm | 2 +- lib/WeBWorK/Utils.pm | 6 +- lib/WeBWorK/Utils/CourseManagement.pm | 19 +- lib/WebworkSOAP.pm | 4 +- lib/WebworkWebservice/CourseActions.pm | 5 +- lib/WebworkWebservice/RenderProblem.pm | 1 - t/grab_course_environment.pl | 7 +- .../CourseAdmin/upgrade_course_form.html.ep | 2 +- .../Instructor/Config.html.ep | 2 +- 50 files changed, 158 insertions(+), 1770 deletions(-) delete mode 100755 clients/sendXMLRPC.pl delete mode 100644 lib/WeBWorK/Constants.pm diff --git a/bin/OPL-update b/bin/OPL-update index 2cc22468fc..6a70548ec1 100755 --- a/bin/OPL-update +++ b/bin/OPL-update @@ -18,10 +18,6 @@ use strict; use warnings; BEGIN { - die "WEBWORK_ROOT not found in environment.\n" - unless exists $ENV{WEBWORK_ROOT}; - # Unused variable, but define it to avoid an error message. - $WeBWorK::Constants::WEBWORK_DIRECTORY = ''; die "WEBWORK_ROOT not found in environment.\n" unless exists $ENV{WEBWORK_ROOT}; $ENV{PG_ROOT} //= "$ENV{WEBWORK_ROOT}/../pg"; die "The pg directory must be defined in PG_ROOT" unless (-e $ENV{PG_ROOT}); @@ -34,7 +30,7 @@ use lib "$ENV{WEBWORK_ROOT}/bin"; use WeBWorK::CourseEnvironment; use Helper 'runScript'; -my $ce = new WeBWorK::CourseEnvironment({webwork_dir=>$ENV{WEBWORK_ROOT}}); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, pg_dir => $ENV{PG_ROOT} }); print "\nDownloading the latest OPL release.\n"; runScript("$ENV{WEBWORK_ROOT}/bin/download-OPL-metadata-release.pl"); diff --git a/bin/OPL-update-legacy b/bin/OPL-update-legacy index 210098b95d..e599e2de05 100755 --- a/bin/OPL-update-legacy +++ b/bin/OPL-update-legacy @@ -25,10 +25,7 @@ use DBI; #You can increase path length to 4096 for mysql > 5.0.3) BEGIN { - die "WEBWORK_ROOT not found in environment.\n" - unless exists $ENV{WEBWORK_ROOT}; - # Unused variable, but define it to avoid an error message. - $WeBWorK::Constants::WEBWORK_DIRECTORY = ''; + die "WEBWORK_ROOT not found in environment.\n" unless exists $ENV{WEBWORK_ROOT}; } # Taxonomy global variables @@ -90,7 +87,7 @@ use WeBWorK::CourseEnvironment; use WeBWorK::Utils::Tags; use OPLUtils qw/build_library_directory_tree build_library_subject_tree build_library_textbook_tree writeJSONtoFile/; -my $ce = new WeBWorK::CourseEnvironment({webwork_dir=>$ENV{WEBWORK_ROOT}}); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, pg_dir => $pg_dir }); # decide whether the mysql installation can handle # utf8mb4 and that should be used for the OPL @@ -715,7 +712,7 @@ sub pgfiles { my $lang = $tags->{Language} || 'en'; my $mathobj = $tags->{MO} || 0; my $static = $tags->{Static} || 0; - + my @pgfile_ids = (); for my $DBsection_id (@DBsection_ids) { diff --git a/bin/addcourse b/bin/addcourse index f6cbb6a204..160f73ab9f 100755 --- a/bin/addcourse +++ b/bin/addcourse @@ -84,7 +84,7 @@ use lib "$pg_dir/lib"; use WeBWorK::CourseEnvironment; # Grab course environment (by reading webwork2/conf/defaults.config) -my $ce = new WeBWorK::CourseEnvironment({ webwork_dir => $webwork_dir }); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $webwork_dir, pg_dir => $pg_dir }); use WeBWorK::DB; use WeBWorK::File::Classlist; diff --git a/bin/change_user_id b/bin/change_user_id index a6337f1702..dc7c575f4a 100755 --- a/bin/change_user_id +++ b/bin/change_user_id @@ -45,7 +45,8 @@ my $new_user_id = shift; my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, - courseName => $courseID + pg_dir => $pg_dir, + courseName => $courseID }); my $db = new WeBWorK::DB($ce->{dbLayout}); diff --git a/bin/delcourse b/bin/delcourse index 5cdc33bb43..a7a21c8018 100755 --- a/bin/delcourse +++ b/bin/delcourse @@ -137,7 +137,8 @@ usage_error("must specify COURSEID.") unless $courseID; # bring up a minimal course environment my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, - courseName => $courseID, + pg_dir => $ENV{PG_ROOT}, + courseName => $courseID, }); my $dbLayout = $ce->{dbLayoutName}; diff --git a/bin/download-OPL-metadata-release.pl b/bin/download-OPL-metadata-release.pl index 227da0f688..2b787003e3 100755 --- a/bin/download-OPL-metadata-release.pl +++ b/bin/download-OPL-metadata-release.pl @@ -27,7 +27,7 @@ BEGIN use WeBWorK::CourseEnvironment; use Helper 'runScript'; -my $ce = new WeBWorK::CourseEnvironment({ webwork_dir => $ENV{WEBWORK_ROOT} }); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, pg_dir => $pg_dir }); my $rawData; my $releaseDataFF = diff --git a/bin/dump-OPL-tables.pl b/bin/dump-OPL-tables.pl index 4ff8979645..4e71169da3 100755 --- a/bin/dump-OPL-tables.pl +++ b/bin/dump-OPL-tables.pl @@ -37,9 +37,7 @@ BEGIN # get course environment and configured OPL path -my $ce = new WeBWorK::CourseEnvironment({ - webwork_dir => $ENV{WEBWORK_ROOT}, -}); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, pg_dir => $pg_dir }); my $configured_OPL_path = $ce->{problemLibrary}{root}; diff --git a/bin/dump_past_answers b/bin/dump_past_answers index 5d89ac16f1..9bb88cf603 100755 --- a/bin/dump_past_answers +++ b/bin/dump_past_answers @@ -126,8 +126,9 @@ my $csv = new Text::CSV->new({ binary => 1 }) or die "Cannot use CSV: " . Text::CSV->error_diag(); $csv->eol("\n"); -my $ce = new WeBWorK::CourseEnvironment({ +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, + pg_dir => $pg_dir, }); my @courses = listCourses($ce); @@ -140,8 +141,9 @@ my @row; foreach my $courseID (@courses) { next if $courseID eq 'admin' || $courseID eq 'modelCourse'; - $ce = new WeBWorK::CourseEnvironment({ + $ce = WeBWorK::CourseEnvironment->({ webwork_dir => $ENV{WEBWORK_ROOT}, + pg_dir => $pg_dir, courseName => $courseID, }); $db = new WeBWorK::DB($ce->{dbLayout}); diff --git a/bin/generate-OPL-set-def-lists.pl b/bin/generate-OPL-set-def-lists.pl index 17a71804a8..3397a881e0 100755 --- a/bin/generate-OPL-set-def-lists.pl +++ b/bin/generate-OPL-set-def-lists.pl @@ -43,7 +43,7 @@ BEGIN use OPLUtils qw/writeJSONtoFile/; use WeBWorK::CourseEnvironment; -my $ce = new WeBWorK::CourseEnvironment({ webwork_dir => $ENV{WEBWORK_ROOT} }); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, pg_dir => $pg_root }); my $libraryRoot = $ce->{problemLibrary}{root}; my $contribRoot = $ce->{contribLibrary}{root}; diff --git a/bin/importClassList.pl b/bin/importClassList.pl index b59f67fe94..723632f130 100755 --- a/bin/importClassList.pl +++ b/bin/importClassList.pl @@ -53,6 +53,7 @@ BEGIN my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, + pg_dir => $pg_dir, courseName => $courseID }); diff --git a/bin/integrity_check.pl b/bin/integrity_check.pl index 0c89273352..aa6b151325 100644 --- a/bin/integrity_check.pl +++ b/bin/integrity_check.pl @@ -44,8 +44,9 @@ BEGIN my $courseName = "tmp_course"; -my $ce = new WeBWorK::CourseEnvironment({ +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, + pg_dir => $pg_dir, courseName => $courseName }); diff --git a/bin/load-OPL-global-statistics.pl b/bin/load-OPL-global-statistics.pl index 5caf309671..12b56e1e73 100755 --- a/bin/load-OPL-global-statistics.pl +++ b/bin/load-OPL-global-statistics.pl @@ -38,8 +38,9 @@ BEGIN # get course environment and configured OPL path -my $ce = new WeBWorK::CourseEnvironment({ +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, + pg_dir => $pg_dir }); my $dbh = DBI->connect( diff --git a/bin/newpassword b/bin/newpassword index 915f93ff4d..6428a4f4f4 100755 --- a/bin/newpassword +++ b/bin/newpassword @@ -96,6 +96,7 @@ sub dopasswd { # bring up a minimal course environment my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, + pg_dir => $pg_dir, courseName => $courseID }); diff --git a/bin/remove_stale_images b/bin/remove_stale_images index 23f0be8aba..ef102eb345 100755 --- a/bin/remove_stale_images +++ b/bin/remove_stale_images @@ -217,7 +217,7 @@ sub count_report { # bring up a minimal course environment -my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT} }); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, pg_dir => $pg_dir }); my $dirHead = $ce->{webworkDirs}->{equationCache}; my $cachePath = $ce->{webworkFiles}->{equationCacheDB}; diff --git a/bin/restore-OPL-tables.pl b/bin/restore-OPL-tables.pl index 1fcedbc5d4..33f0bd7340 100755 --- a/bin/restore-OPL-tables.pl +++ b/bin/restore-OPL-tables.pl @@ -38,8 +38,9 @@ BEGIN # get course environment and configured OPL path -my $ce = new WeBWorK::CourseEnvironment({ +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, + pg_dir => $pg_dir }); my $configured_OPL_path = $ce->{problemLibrary}{root}; diff --git a/bin/setfilepermissions b/bin/setfilepermissions index 90cba77fbc..220a37582d 100755 --- a/bin/setfilepermissions +++ b/bin/setfilepermissions @@ -42,7 +42,7 @@ BEGIN { use lib "$ENV{WEBWORK_ROOT}/lib"; use lib "$pg_dir/lib"; use WeBWorK::CourseEnvironment; -my $ce = new WeBWorK::CourseEnvironment({ webwork_dir => $ENV{WEBWORK_ROOT} }); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, pg_dir => $pg_dir }); # who is really running this script (even if sudo'ed) # We set relevant directories so that script runner owns them diff --git a/bin/test_library_build.pl b/bin/test_library_build.pl index 91a21c2bd2..2d988a7493 100755 --- a/bin/test_library_build.pl +++ b/bin/test_library_build.pl @@ -6,9 +6,6 @@ BEGIN die "WEBWORK_ROOT not found in environment.\n" unless exists $ENV{WEBWORK_ROOT}; $pg_dir = $ENV{PG_ROOT} // "$ENV{WEBWORK_ROOT}/../pg"; die "The pg directory must be defined in PG_ROOT" unless (-e $pg_dir); - - # Unused variable, but define it to avoid an error message. - $WeBWorK::Constants::WEBWORK_DIRECTORY = ''; } # Get database connection @@ -19,7 +16,7 @@ BEGIN use OPLUtils qw/build_library_directory_tree build_library_subject_tree build_library_textbook_tree/; use DBI; -my $ce = new WeBWorK::CourseEnvironment({ webwork_dir => $ENV{WEBWORK_ROOT} }); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, pg_dir => $pg_dir }); my $dbh = DBI->connect( $ce->{database_dsn}, $ce->{database_username}, diff --git a/bin/update-OPL-statistics.pl b/bin/update-OPL-statistics.pl index cb8bdd19f7..b0529ca806 100755 --- a/bin/update-OPL-statistics.pl +++ b/bin/update-OPL-statistics.pl @@ -38,8 +38,9 @@ BEGIN my $time = time(); # get course environment and open up database -my $ce = new WeBWorK::CourseEnvironment({ +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, + pg_dir => $pg_dir }); # decide whether the mysql installation can handle diff --git a/bin/updateOPLextras.pl b/bin/updateOPLextras.pl index 876223d186..6433b75e34 100755 --- a/bin/updateOPLextras.pl +++ b/bin/updateOPLextras.pl @@ -83,7 +83,7 @@ BEGIN use WeBWorK::CourseEnvironment; use OPLUtils qw/build_library_directory_tree build_library_subject_tree build_library_textbook_tree/; -my $ce = new WeBWorK::CourseEnvironment({ webwork_dir => $ENV{WEBWORK_ROOT} }); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, pg_dir => $pg_dir }); # decide whether the mysql installation can handle # utf8mb4 and that should be used for the OPL diff --git a/bin/upgrade-database-to-utf8mb4.pl b/bin/upgrade-database-to-utf8mb4.pl index 92626fb6fa..de3f3ca8a4 100755 --- a/bin/upgrade-database-to-utf8mb4.pl +++ b/bin/upgrade-database-to-utf8mb4.pl @@ -154,7 +154,7 @@ BEGIN use WeBWorK::Utils::CourseManagement qw{listCourses}; # Load a minimal course environment. -my $ce = new WeBWorK::CourseEnvironment({ webwork_dir => $ENV{WEBWORK_ROOT} }); +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, pg_dir => $ENV{PG_ROOT} }); # Get DB connection settings. my $dbname = $ce->{database_name}; diff --git a/bin/upgrade_admin_db.pl b/bin/upgrade_admin_db.pl index fdef76c078..0ef3a6ba23 100755 --- a/bin/upgrade_admin_db.pl +++ b/bin/upgrade_admin_db.pl @@ -35,8 +35,9 @@ BEGIN ########################## my $upgrade_courseID = 'admin'; -my $ce = new WeBWorK::CourseEnvironment({ +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, + pg_dir => $pg_dir, courseName => $upgrade_courseID, }); #warn "do_upgrade_course: updating |$upgrade_courseID| from" , join("|",@upgrade_courseIDs); diff --git a/bin/upload-OPL-statistics.pl b/bin/upload-OPL-statistics.pl index 676d96a40c..56269f1607 100755 --- a/bin/upload-OPL-statistics.pl +++ b/bin/upload-OPL-statistics.pl @@ -32,8 +32,9 @@ BEGIN use Net::Domain qw/domainname/; use String::ShellQuote; -my $ce = new WeBWorK::CourseEnvironment({ +my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, + pg_dir => $pg_dir, }); # Get DB connection settings @@ -66,7 +67,7 @@ BEGIN * the average number of attempts made per user on the problem * the average completion percentage for each user who attempted the problem -Share OPL usage statistics with the WeBWorK community [Y/N]: +Share OPL usage statistics with the WeBWorK community [Y/N]: END_REQUEST $input = ; chomp $input; diff --git a/bin/webwork2 b/bin/webwork2 index 1319eb9032..e0bd74a2c5 100755 --- a/bin/webwork2 +++ b/bin/webwork2 @@ -33,9 +33,6 @@ BEGIN { $WeBWorK::SeedCE{webwork_dir} = $ENV{WEBWORK_ROOT}; $WeBWorK::SeedCE{pg_dir} = $ENV{PG_ROOT}; - # Define these twice to avoid annoying used only once warnings. - $WeBWorK::Constants::WEBWORK_DIRECTORY = $WeBWorK::Constants::WEBWORK_DIRECTORY = $ENV{WEBWORK_ROOT}; - $WeBWorK::Constants::PG_DIRECTORY = $WeBWorK::Constants::PG_DIRECTORY = $ENV{PG_ROOT}; } use Mojolicious::Commands; diff --git a/bin/ww_purge_old_nonces b/bin/ww_purge_old_nonces index 9ac0b0bc6e..2361d6ae6e 100755 --- a/bin/ww_purge_old_nonces +++ b/bin/ww_purge_old_nonces @@ -69,7 +69,8 @@ usage() unless $course ; my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, - courseName => $course, + pg_dir => $pg_dir, + courseName => $course, }); my $db = WeBWorK::DB->new($ce->{dbLayout}); diff --git a/bin/wwdb b/bin/wwdb index e5e5c82d32..f94f49a028 100755 --- a/bin/wwdb +++ b/bin/wwdb @@ -88,7 +88,8 @@ usage() unless $course and $command and $file; my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, - courseName => $course, + pg_dir => $pg_dir, + courseName => $course, }); my $db = WeBWorK::DB->new($ce->{dbLayout}); diff --git a/bin/wwsh b/bin/wwsh index bcea2a1d01..ff697e9a3a 100755 --- a/bin/wwsh +++ b/bin/wwsh @@ -51,7 +51,8 @@ die 'You must pass scriptFile in as a path to the file' unless -e $scriptFile; $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT}, - courseName => $courseID, + pg_dir => $pg_dir, + courseName => $courseID, }); diff --git a/clients/sendXMLRPC.pl b/clients/sendXMLRPC.pl deleted file mode 100755 index 84a652da8b..0000000000 --- a/clients/sendXMLRPC.pl +++ /dev/null @@ -1,1515 +0,0 @@ -#!/usr/bin/perl -w - -################################################################################ -# WeBWorK Online Homework Delivery System -# Copyright © 2000-2022 The WeBWorK Project, https://github.com/openwebwork -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of either: (a) the GNU General Public License as published by the -# Free Software Foundation; either version 2, or (at your option) any later -# version, or (b) the "Artistic License" which comes with this package. -# -# 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 either the GNU General Public License or the -# Artistic License for more details. -################################################################################ - -=head1 NAME - -webwork2/clients/sendXMLRPC.pl - -=head1 DESCRIPTION - - -This module provides functions for rendering html from files outside the normal -context of providing a webwork homework set user an existing problem set. - -It can be used to create a live version of a single problem, one that is not -part of any set, and can facilitate editing these problems outside of the -context of WeBWorK2. - -This script will take a list of files or directories -and send it to a WeBWorK daemon webservice -to have it rendered. For directories each .pg file under that -directory is rendered. - -The results can be displayed in a browser (use -b or -B switches) as was -done with renderProblem.pl, on the command line (Use -h or -H switches) as -was done with renderProblem_rawoutput.pl or summary information about whether the -problem was correctly rendered can be sent to a log file (use -c or C switches). - -The capital letter switches, -B, -H, and -C render the question twice. The first -time returns an answer hash which contains the correct answers. The question is -then resubmitted to the renderer with the correct answers filled in and displayed. - -IMPORTANT: Create a valid credentials file (a sample file ww_credentials.dist is provided). - (See below.) - Locations where this file can be located: - "$ENV{HOME}/.ww_credentials" - "$ENV{HOME}/ww_session_credentials" - 'ww_credentials' - 'ww_credentials.dist' - The file sets the remove server and the local display/edit commands. - -IMPORTANT: Remember to configure: - 1. the local output file (near the top of this script) - 2. the display commands (in the ww_credentials file) - 3. the remote server to contact (in the ww_credentials file) - Things will NOT work until the configuration is done. - -This script is similar to standalonePGproblemRenderer.pl. It does not require a local WeBWorK site -on the same computer but does require an internet connection to a remote WeBWorK site. - -=cut - -=head1 SYNOPSIS - - sendXMLRPC -vcCbB input.pg - -=head1 DETAILS - -=head2 credentials file - - These locations are searched, in order, for the credentials file. - ("$ENV{HOME}/.ww_credentials", "$ENV{HOME}/ww_session_credentials", 'ww_credentials', 'ww_credentials.dist') - - Place a credential file containing the following information at one of the locations above - or create a file with this information and specify it with the --credentials option. - - # Cut here - top ============================================= - - # The sample settings below should be customized for your server and local system - - %credentials = ( - # Set the URLs of the remote site and the site password - - # Test settings for the demo.webwork.rochester.edu site - site_url => 'https://demo.webwork.rochester.edu', - form_action_url => 'https://demo.webwork.rochester.edu/webwork2/html2xml', - site_password => 'xmlrpc', - - # Settings for use with a local webwork system (ex. via Docker) - # site_url => 'http://localhost:80', - # form_action_url => 'http://localhost:80/webwork2/html2xml', - # site_password => 'xmlrpc', - # forcePortNumber => '80', # A port number to be forced, when needed. - - # Set the identification credential used by the "daemon_course" on the remote site - courseID => "daemon_course", - userID => "daemon", - course_password => "daemon", - # Set the display mode to use - ww_display_mode => "MathJax", - # Set the path to the LOCAL log file (make sure to create an empty file) - # when commented out - no file is needed - # path_to_log_file =>"", - # Set the display commands which work on the machine on which you are - # running sendXMLRPC.pl - # Sample settings for Mac: - - # html_display_command => "open -a 'Google Chrome' ", # A web browser - # html_display_command => "open -a Firefox ", - # tex_display_command => "open -a 'TeXShop'", # Editor or TeX editor - # pdf_display_command => "open -a 'Preview'", # PDF viewer - # hash_display_command => "cat ", # to diplay file to STDOUT - - # ============================== - - # Sample settings for Linux: - - # html_display_command => "firefox", # A web browser - # html_display_command => "google-chrome", - # tex_display_command => "vim", # Editor or TeX editor - # tex_display_command => "emacs", - # pdf_display_command => "xpdf", # PDF viewer - # pdf_display_command => "evince", - # pdf_display_command => "acroread", # PDF viewer - # hash_display_command => "cat ", # to diplay file to STDOUT - ); - - # Cut here - bottom ============================================= - - -=cut - -=head2 Options - -=over 4 - -=item -a - - Displays the answer hashes returned by the question on the command line. - -=item -A - - Same as -a but renders the question with the correct answers submitted. - -=item -b - - Display the rendered question in a browser (specified by the DISPLAY_HTML_COMMAND variable). - -=item -B - - Same as -b but renders the question with the correct answers submitted. - The evaluation of the answer submitted is displayed as well as the correct - answer. - -=item -h - - Prints to STDOUT the entire object returned by - the webwork_client xmlrpc request. - This includes the answer information displayed by -a and -A and much more. - -=item -H - - Same as -h but renders the question with the correct answers submitted - -=item -c - - "check" -- Record success or failure of rendering the question to a log file. - -=item -C - - Same as -c but the question is rendered with the correct answers submitted. - This succeeds only if the correct answers, as determined from the answer hash, all succeed. - -=item -f formatName - - Specify the format used by the browser in displaying the question. - Choices for s are - standard - sticky - debug - simple - -=item -l lang - - Set a language for the HTML rendering to use. Should use a value which would be valid for a course. - -=item -v - - Verbose output. Used mostly for debugging. - In particular it displays explicitly the correct answers - which are (will be) submitted to the question. - -=item -e - - Open the source file in an editor. - -=item --tex - - Process question in TeX mode and output to the command line - -=item --pdf - - Process question in TeX mode, convert to PDF and display. - -=item --json - - Process question in JSON mode and save to file -=item - - The single letter options can be "bundled" e.g. -vcCbB - -=item --list pg_list - - Read and process a list of .pg files contained in the file C. C - consists of a sequence of lines each of which contains the full path to a pg - file that should be processed. (For example this might be the output from an - earlier run of sendXMLRPC using the -c flag. ) - -=item --pg - - Triggers the printing of the all of the variables available to the PG question. - The table appears within the question content. Use in conjunction with -b or -B. - -=item --anshash - - Prints the answer hash for each answer in the PG_debug output which appears below - the question content. Use in conjunction with -b or -B. - Similar to -a or -A but the output appears in the browser and - not on the command line. - -=item --ansgrp - - Prints the PGanswergroup for each answer evaluator. The information appears in - the PG_debug output which follows the question content. Use in conjunction with -b or -B. - This contains more information than printing the answer hash. (perhaps too much). - -=item --resource - - Prints the resources used by the question. The information appears in - the PG_debug output which follows the question content. Use in conjunction with -b or -B. - -=item --credentials=s - - Specifies a file s where the credential information can be found. - -=item --help - - Prints help information. - -=item --log - - Sets path to log file - -=item --seed=s - - Sets problemSeed to the number contained in string s - -=item --psvn=s - - Sets psvn to the number contained in string s - - - -=back -=cut - -use strict; -use warnings; - -####################################################### -# Find the webwork2 root directory -####################################################### -BEGIN { - use File::Basename; - $main::dirname = dirname(__FILE__); -} - -use lib "$main::dirname"; -print "home directory " . $main::dirname . "\n"; -#use lib "."; # is this needed? - -# some files such as FormatRenderedProblem.pm may need to be in the same directory - -BEGIN { - die "WEBWORK_ROOT not found in environment. \n - WEBWORK_ROOT can be defined in your .cshrc or .bashrc file\n - It should be set to the webwork2 directory (e.g. /opt/webwork/webwork2)" - unless exists $ENV{WEBWORK_ROOT}; - # Unused variable, but define it twice to avoid an error message. - $WeBWorK::Constants::WEBWORK_DIRECTORY = $ENV{WEBWORK_ROOT}; - $WeBWorK::Constants::PG_DIRECTORY = "$ENV{WEBWORK_ROOT}/../pg/"; - unless (-r $WeBWorK::Constants::WEBWORK_DIRECTORY) { - die "Cannot read webwork root directory at $WeBWorK::Constants::WEBWORK_DIRECTORY"; - } - unless (-r $WeBWorK::Constants::PG_DIRECTORY) { - die "Cannot read webwork pg directory at $WeBWorK::Constants::PG_DIRECTORY"; - } - -} -use lib "$WeBWorK::Constants::WEBWORK_DIRECTORY/lib"; - -use Carp; -use LWP::Protocol::https; -use Time::HiRes qw/time/; -use MIME::Base64 qw( encode_base64 decode_base64); -use Getopt::Long qw[:config no_ignore_case bundling]; -use File::Find; -use FileHandle; -use File::Path; -use File::Temp qw/tempdir/; -use String::ShellQuote; -use Cwd 'abs_path'; -use WebworkClient; -use FormatRenderedProblem; -#use Proc::ProcessTable; # use in standalonePGproblemRenderer - -use 5.10.0; -$Carp::Verbose = 1; - -### verbose output when UNIT_TESTS_ON =1; -our $UNIT_TESTS_ON = 0; - -############################################################ -# Read command line options -############################################################ - -my $display_ans_output1 = ''; -my $display_hash_output1 = ''; -my $display_html_output1 = ''; -my $record_ok1 = ''; # subroutine needs to be constructed -my $display_ans_output2 = ''; -my $display_hash_output2 = ''; -my $display_html_output2 = ''; -my $record_ok2 = ''; -my $verbose = ''; -my $credentials_path; -my $format = 'standard'; -my $lang = 'en'; -my $edit_source_file = ''; -my $display_tex_output = ''; -my $display_pdf_output = ''; -my $display_json_output = ''; -my $print_answer_hash; -my $print_answer_group; -my $print_pg_hash; -my $print_resource_hash; -my $print_help_message; -my $read_list_from_this_file; -my $path_to_log_file; -my $problemSeed; -my $psvn; - -our %credentials; -our @path_list; -my $credentials_string; - -GetOptions( - 'a' => \$display_ans_output1, - 'A' => \$display_ans_output2, - 'b' => \$display_html_output1, - 'B' => \$display_html_output2, - 'h' => \$display_hash_output1, - 'H' => \$display_hash_output2, - 'c' => \$record_ok1, # record_problem_ok1 needs to be written - 'C' => \$record_ok2, - 'v' => \$verbose, - 'e' => \$edit_source_file, - 'tex' => \$display_tex_output, - 'pdf' => \$display_pdf_output, - 'json' => \$display_json_output, - 'list=s' => \$read_list_from_this_file, # read file containing list of full file paths - 'pg' => \$print_pg_hash, - 'anshash' => \$print_answer_hash, - 'ansgrp' => \$print_answer_group, - 'resource' => \$print_resource_hash, - 'f=s' => \$format, - 'l=s' => \$lang, - 'credentials=s' => \$credentials_path, - 'help' => \$print_help_message, - 'log=s' => \$path_to_log_file, - 'seed=s' => \$problemSeed, - 'psvn=s' => \$psvn, -); - -print_help_message() if $print_help_message; - -############################################################ -# End Read command line options -############################################################ - -################################################################################ - -# Move up the reading of credential files to here in order to get -# WEBWORK_URL defined before it is needed. (For Docker installs when -# called from outside Docker, it may not be in the environment variables.) - -#################################################### -# get credentials -#################################################### - -# credentials are needed -# credentials file location -- search for one of these files - -@path_list = - ("$ENV{HOME}/.ww_credentials", "$ENV{HOME}/ww_session_credentials", 'ww_credentials', 'ww_credentials.dist'); - -$credentials_string = < 'https://demo.webwork.rochester.edu', - form_action_url => 'https://demo.webwork.rochester.edu/webwork2/html2xml', - site_password => 'xmlrpc', - - # Settings for use with a local webwork system (ex. via Docker) - # site_url => 'http://localhost:80', - # form_action_url => 'http://localhost:80/webwork2/html2xml', - # site_password => 'xmlrpc', - # forcePortNumber => '80', # A port number to be forced, when needed. - - - # Set the identification credential used by the "daemon_course" on the remote site - courseID => "daemon_course", - userID => "daemon", - course_password => "daemon", - # Set the display mode to use - ww_display_mode => "MathJax", - # Set the path to the LOCAL log file (make sure to create an empty file) - # when commented out - no file is needed - # path_to_log_file =>"", - # Set the display commands which work on the machine on which you are - # running sendXMLRPC.pl - # Sample settings for Mac: - - - # html_display_command => "open -a 'Google Chrome' ", # A web browser - - # html_display_command => "open -a Firefox ", - # tex_display_command => "open -a 'TeXShop'", # Editor or TeX editor - # pdf_display_command => "open -a 'Preview'", # PDF viewer - # hash_display_command => "cat ", # to diplay file to STDOUT - - # ============================== - - # Sample settings for Linux: - - # html_display_command => "firefox", # A web browser - # html_display_command => "google-chrome", - # tex_display_command => "vim", # Editor or TeX editor - # tex_display_command => "emacs", - # pdf_display_command => "xpdf", # PDF viewer - # pdf_display_command => "evince", - # pdf_display_command => "acroread", # PDF viewer - # hash_display_command => "cat ", # to diplay file to STDOUT - ); - -EOF -if (defined $credentials_path and (-r $credentials_path)) { - # we're all set -} elsif (defined $credentials_path) { #can't find credentials - die "Can't find credentials file $credentials_path searching\n"; -} - -if (defined $credentials_path and (-r $credentials_path)) { - # we're all set -} elsif (defined $credentials_path) { #can't find credentials - die "Can't find credentials file $credentials_path searching\n"; -} - -# if credentials_path not set explicitly go look for a credentials file. -unless (defined $credentials_path) { - foreach my $path (@path_list) { - print "looking for credentials file: $path. -- " . ((-r $path) ? 'found!' : '(not found)') . "\n" if $verbose; - next unless defined $path; - if (-r $path) { - $credentials_path = $path; - last; - } - } -} - -# verify that a credentials file has been found - -if ($credentials_path) { - print STDERR "Credentials taken from file $credentials_path\n" if $verbose; -} else { #failed to find credentials file - die <$credentials{$_} \n"; } -} - -################################################################################ - -use lib "$WeBWorK::Constants::WEBWORK_DIRECTORY/lib"; -use lib "$WeBWorK::Constants::PG_DIRECTORY/lib"; - -use WebworkClient; -use FormatRenderedProblem; -#use Proc::ProcessTable; # use in standalonePGproblemRenderer - -use 5.10.0; -$Carp::Verbose = 1; - -############################################# -# CONFIGURE -# -# Configure displays for local operating system -# This section will differ from on operating system to another -# The default code is for the macOS and applications commonly available on macOS. -############################################# - -#Default display commands. -use constant HTML_DISPLAY_COMMAND => "open -a 'Google Chrome' "; # (MacOS command) -use constant HASH_DISPLAY_COMMAND => ""; # display tempoutputfile to STDOUT - -### Path to a temporary file for storing the output of sendXMLRPC.pl -use constant TEMPOUTPUTDIR => "$ENV{WEBWORK_ROOT}/DATA/"; -die "You must make the directory " . TEMPOUTPUTDIR() . " writeable " unless -w TEMPOUTPUTDIR(); -use constant TEMPOUTPUTFILE => TEMPOUTPUTDIR() . "temporary_output.html"; - -### Default path to a temporary file for storing the output -### of sendXMLRPC.pl -use constant LOG_FILE => "$ENV{WEBWORK_ROOT}/DATA/xmlrpc_results.log"; - -### Command for editing the pg source file in the browswer -use constant EDIT_COMMAND => "bbedit"; # for Mac BBedit editor (used as `EDIT_COMMAND() . " $file_path") - -### Command for editing and viewing the tex output of the pg question. -use constant TEX_DISPLAY_COMMAND => "open -a 'TeXShop'"; - -### Command for editing and viewing the tex output of the pg question. -use constant PDF_DISPLAY_COMMAND => "open -a 'Preview'"; - -### set display mode -use constant DISPLAYMODE => 'MathJax'; -use constant PROBLEMSEED => '987654321'; - -############################################################ -# End configure displays for local operating system -############################################################ - -#allow credentials to overrride the default displayMode -#and the browser display -our $HTML_DISPLAY_COMMAND = $credentials{html_display_command} // HTML_DISPLAY_COMMAND(); -our $HASH_DISPLAY_COMMAND = $credentials{hash_display_command} // HASH_DISPLAY_COMMAND(); -our $DISPLAYMODE = $credentials{ww_display_mode} // DISPLAYMODE(); -our $TEX_DISPLAY_COMMAND = $credentials{tex_display_command} // TEX_DISPLAY_COMMAND(); -our $PDF_DISPLAY_COMMAND = $credentials{pdf_display_command} // PDF_DISPLAY_COMMAND(); - -################################################## -# END gathering credentials for client -################################################## - -################################################## -# create course environment and create log files -################################################## - -# course environment is provided by caller and credentials for sendXMLRPC - -$path_to_log_file = $path_to_log_file // $credentials{path_to_log_file} // LOG_FILE(); #set log file path. - -eval { # attempt to create log file - local (*FH); - open(FH, '>>:encoding(UTF-8)', $path_to_log_file) or die "Can't open file $path_to_log_file for writing"; - close(FH); -}; - -die "You must first create an output file at $path_to_log_file - with permissions 777 " unless -w $path_to_log_file; - -################################################## -# set default inputs for the problem -################################################## - -############################################ -# Build client defaults -############################################ - -my $default_input = { - userID => $credentials{userID} // '', - session_key => $credentials{session_key} // '', - courseID => $credentials{courseID} // '', - courseName => $credentials{courseID} // '', - course_password => $credentials{course_password} // '', -}; - -my $default_form_data = { - displayMode => $DISPLAYMODE, - outputformat => $format // 'standard', - problemSeed => $problemSeed // PROBLEMSEED(), - psvn => $psvn // '23456', - forcePortNumber => $credentials{forcePortNumber} // '', - language => $lang // 'en', -}; - -################################################## -# end build client -################################################## - -################################################## -# MAIN SECTION gather and process problem template files -################################################## -my $cg_start = time; # this is Time::HiRes's time, which gives floating point values - -our @files_and_directories = @ARGV; -# print "files ", join("|", @files_and_directories), "\n"; -if ($read_list_from_this_file) { - # read a datafile containing list of files to be processed - my $FH = FileHandle->new(" < $read_list_from_this_file"); - while (<$FH>) { - my $item = $_; - chomp($item); - my $file_path = abs_path($item); - unless (defined $file_path and -f $file_path) { - warn "skipping $item\n" unless defined $file_path; - warn "skipping $file_path\n" if defined $file_path; - next; - } - next if $file_path =~ /^\s*#/; # comment lines - next unless $file_path =~ /\.pg$/; - next if $file_path =~ /\-text\.pg$/; - next if $file_path =~ /header/i; - process_pg_file($file_path); - } - FileHandle::close($FH); - -} else { - foreach my $item (@files_and_directories) { - if (-d $item) { # if the item is a directory traverse the tree - my $dir = abs_path($item); - find(\&wanted, ($dir)); - } elsif ($item eq "-") { - process_pg_file($item); # process STDIN - } elsif (-f $item) { # if the item is a file process it. - my $file_path = abs_path($item); - next unless $file_path =~ /\.pg$/; # only process pg files - next if $file_path =~ /\-text\.pg$/; # don't process auxiliary include files - next if $file_path =~ /header/i; # don't process header files - process_pg_file($file_path); - } else { - print "$item cannot be found or read\n"; - } - } -} - -sub wanted { - return '' unless $File::Find::name =~ /\.pg$/; - return '' if $File::Find::name =~ /\-text\.pg$/; - return '' if $File::Find::name =~ /header/i; - eval { process_pg_file($File::Find::name) if -f $File::Find::name; }; - warn "Error in processing $File::Find::name: $@" if $@; -} - -########################################################## -# Subroutines -########################################################## - -####################################################################### -# Process the pg file -####################################################################### - -sub process_pg_file { - my $file_path = shift; - my $NO_ERRORS = ""; - my $ALL_CORRECT = ""; - my $form_data1 = { - %$default_form_data, - - }; - - if ($display_tex_output or $display_pdf_output) { - my $form_data2 = { - %$form_data1, - displayMode => 'tex', - outputformat => 'tex', - }; - print "process tex files\n" if $UNIT_TESTS_ON; - my ($error_flag, $formatter, $error_string) = process_problem($file_path, $default_input, $form_data2); - - # create tex file for both and tex and pdf output - my $tex_file_name = create_tex_output($file_path, $formatter); - # display tex file if --tex option is set - if ($display_tex_output) { - system($TEX_DISPLAY_COMMAND. " " . TEMPOUTPUTDIR() . $tex_file_name); - } elsif ($display_pdf_output) { # process tex file to create pdf file and display if --pdf option - my $pdf_path = create_pdf_output($tex_file_name); - system($PDF_DISPLAY_COMMAND. " " . $pdf_path); - } - } - if ($display_json_output) { - my $form_data2 = { - %$form_data1, - outputformat => 'json', - displayMode => 'MathJax', - }; - print "Creating json\n" if $UNIT_TESTS_ON; - my ($error_flag, $formatter, $error_string) = process_problem($file_path, $default_input, $form_data2); - my $json_file_name = create_json_output($file_path, $formatter); - print("Created JSON data in file ", TEMPOUTPUTDIR(), $json_file_name, "\n"); - exit; - } - my ($error_flag, $formatter, $error_string) = process_problem($file_path, $default_input, $form_data1); - # extract and display result - #print "display $file_path\n"; - edit_source_file($file_path) if $edit_source_file; - display_html_output($file_path, $formatter) if $display_html_output1; - display_hash_output($file_path, $formatter) if $display_hash_output1; - display_ans_output($file_path, $formatter) if $display_ans_output1; - $NO_ERRORS = record_problem_ok1($error_flag, $formatter, $file_path) if $record_ok1; - - unless ($display_html_output2 or $display_hash_output2 or $display_ans_output2 or $record_ok2) { - print "DONE -- $NO_ERRORS -- \n" if $verbose; - return; - } - ################################################################# - # Extract correct answers - ################################################################# - - my %correct_answers = (); - my $some_correct_answers_not_specified = 0; - foreach my $ans_id (keys %{ $formatter->return_object->{answers} }) { - my $ans_obj = $formatter->return_object->{answers}->{$ans_id}; - # the answergrps are in PG_ANSWERS_HASH - my $answergroup = $formatter->return_object->{PG_ANSWERS_HASH}->{$ans_id}; - my @response_order = @{ $answergroup->{response}->{response_order} }; - #print scalar(@response_order), " first response $response_order[0] $ans_id\n"; - $ans_obj->{type} = $ans_obj->{type} // ''; #make sure it's defined. - if ($ans_obj->{type} eq 'MultiAnswer') { - # singleResponse multianswer type - # an outrageous hack - print "handling MultiAnswer singleResponse type\n" if $verbose; - my $ans_str1 = $ans_obj->{correct_ans}; - my @ans_array1 = split(/\s*;\s*/, $ans_str1); - $correct_answers{$ans_id} = shift @ans_array1; - my $num_extra_elements = scalar(@ans_array1); - foreach my $i (1 .. $num_extra_elements) { # pick up the remaining blanks - my $response_id = "MuLtIaNsWeR_${ans_id}_${i}"; #MuLtIaNsWeR_AnSwEr0003_1 - $correct_answers{$response_id} = shift @ans_array1; - #print "\t\t $response_id => $correct_answers{$response_id}\n"; - } - } elsif ($ans_obj->{type} =~ /checkbox/i) { #type is probably checkbox_cmp - my $ans_str = $ans_obj->{correct_ans}; #an unseparated answer string - $ans_str =~ s/^\s*//; - $ans_str =~ s/\s*$//; #trim white space off ends (probably unnecessary) - my @temp = split("", $ans_str); #split into array of characters - my $new_ans_str = join("\0", @temp); # join them in "packed" form separated with nulls - $correct_answers{$ans_id} = $new_ans_str; - } elsif (1 == @response_order and $ans_id eq $response_order[0]) { - # only one response -- not MultiAnswer singleResponse - # most answers are of this type - # should we use correct answer or correct value? -- this seems to vary - #warn "just one answer blank for this answer evaluator"; - $correct_answers{$ans_id} = ($ans_obj->{correct_ans}) // ($ans_obj->{correct_value}); - } else { # more than one response - if ($ans_obj->{type} =~ /Matrix/) { - #FIXME -- another outrageous hackkkk but it works - #print "responding to matrix answer with several ans_blanks\n"; - #print "responses", join(" ", %{$answergroup->{response}->{responses}}),"\n"; - #print "correct answer ", $ans_obj->{correct_value}, "\n"; - my $ans_str = ($ans_obj->{correct_value}) - // ($ans_obj->{correct_ans}) - ; #(correct_ans can have html formatting -- not good) $ans_str =~ s/\[//g; - $ans_str =~ s/\]//g; - my @ans_array = split(/\s*,\s*/, $ans_str); - foreach my $response_id (@response_order) { - $correct_answers{$response_id} = shift @ans_array; - } - } else { - warn "responding to an answer evaluator of type |" - . $ans_obj->{type} - . "| with " - . scalar(@response_order) - . " ans_blanks: ", join(" ", @response_order), "\n" - if $UNIT_TESTS_ON; - $correct_answers{$ans_id} = ($ans_obj->{correct_ans}) // ($ans_obj->{correct_value}) // ''; - } - } - #FIXME hack to get rid of html protection of < and > for vectors - $correct_answers{$ans_id} =~ s/>/>/g; - $correct_answers{$ans_id} =~ s/</||g; # some answers have breaks in them for clarity - if ($correct_answers{$ans_id} eq "No correct answer specified") { - warn "this question has an answer blank with no correct answer specified"; - $some_correct_answers_not_specified++; - } - - } #end loop collecting correct answers. - # adjust input and reinitialize form_data - my $form_data2 = { - %$default_form_data, - answersSubmitted => 1, - WWsubmit => 1, # grade answers - WWcorrectAns => 1, # show correct answers - %correct_answers - }; - - my $pg_start = time; # this is Time::HiRes's time, which gives floating point values - - ($error_flag, $formatter, $error_string) = (); - ($error_flag, $formatter, $error_string) = process_problem($file_path, $default_input, $form_data2); - my $pg_stop = time; - my $pg_duration = $pg_stop - $pg_start; - - display_html_output($file_path, $formatter) if $display_html_output2; - display_hash_output($file_path, $formatter) if $display_hash_output2; - display_ans_output($file_path, $formatter) if $display_ans_output2; - $ALL_CORRECT = - record_problem_ok2($error_flag, $formatter, $file_path, $some_correct_answers_not_specified, $pg_duration) - if $record_ok2; - #print "display the correct answers here"; - display_inputs(%correct_answers) if $verbose; # choice of correct answers submitted - # should this information on what answers are being submitted have an option switch? - - print "DONE -- $NO_ERRORS -- $ALL_CORRECT\n" if $verbose; -} - -####################################################################### -# Auxiliary subroutines -####################################################################### - -sub process_problem { - my $file_path = shift; - my $input = shift; - my $form_data = shift; - # %credentials is global - - ### get source and correct file_path name so that it is relative to templates directory - - my ($adj_file_path, $source) = get_source($file_path); - #print "find file at $adj_file_path ", length($source), "\n"; - - ### build client - my $xmlrpc_client = new WebworkClient( - site_url => $credentials{site_url}, - form_action_url => $credentials{form_action_url}, - site_password => $credentials{site_password} // '', - courseID => $credentials{courseID}, - userID => $credentials{userID}, - session_key => $credentials{session_key} // '', - sourceFilePath => $adj_file_path, - ); - - ### update client - $xmlrpc_client->encodeSource($source); - $xmlrpc_client->form_data($form_data); - - ### update inputs - my $problemSeed = $form_data->{problemSeed}; - die "problem seed not defined in sendXMLRPC::process_problem" unless $problemSeed; - - my $local_psvn = $form_data->{psvn} // 34567; - my $updated_input = { - %$input, - envir => $xmlrpc_client->environment( - fileName => $adj_file_path, - sourceFilePath => $adj_file_path, - psvn => $local_psvn, - problemSeed => $problemSeed, - ), - }; - - $form_data->{showAnsGroupInfo} = $print_answer_group; - $form_data->{showAnsHashInfo} = $print_answer_hash; - $form_data->{showPGInfo} = $print_pg_hash; - $form_data->{showResourceInfo} = $print_resource_hash; - - ################################################## - # Process the pg file - ################################################## - ### store the time before we invoke the content generator - my $cg_start = time; # this is Time::HiRes's time, which gives floating point values - - ############################################ - # Call server via xmlrpc_client to render problem - ############################################ - - our ($return_object, $error_flag, $error_string); - $error_flag = 0; - $error_string = ''; - - $return_object = $xmlrpc_client->xmlrpcCall('renderProblem', $updated_input); - - ####################################################################### - # Handle errors - ####################################################################### - - unless ($xmlrpc_client->fault) { - print "\n\n Result of renderProblem \n\n" if $UNIT_TESTS_ON; - print pretty_print_rh($return_object) if $UNIT_TESTS_ON; - if (not defined $return_object) { #FIXME make sure this is the right error message if site is unavailable - $error_string = "0\t Could not connect to rendering site " . $xmlrpc_client->{url} . "\n"; - } elsif (defined($return_object->{flags}->{error_flag}) and $return_object->{flags}->{error_flag}) { - $error_string = "0\t $file_path has errors\n"; - } elsif (defined($return_object->{errors}) and $return_object->{errors}) { - $error_string = "0\t $file_path has syntax errors\n"; - } - $error_flag = 1 if $return_object->{errors}; - } else { - $error_flag = 1; - $error_string = $xmlrpc_client->return_object; # error report - } - -################################################## - # Create FormatRenderedProblems object -- not needed for sendXMLRPC -################################################## - - ################################################## - # log elapsed time - ################################################## - my $scriptName = 'sendXMLRPC'; - my $cg_end = time; - my $cg_duration = $cg_end - $cg_start; - WebworkClient::writeRenderLogEntry( - "", - "{script:$scriptName; file:$file_path; " - . sprintf("duration: %.3f sec;", $cg_duration) - . " site_url: $credentials{site_url}; }", - '' - ); - - ####################################################################### - # End processing of the pg file - ####################################################################### - my $formatter = $xmlrpc_client; ## for compatibility with standalonePGproblemRenderer - return $error_flag, $formatter, $error_string; -} - -sub create_pdf_output { - my $tex_file_name = shift; - my @errors = (); - print "pdf mode\n" if $UNIT_TESTS_ON; - my $pdf_file_name = $tex_file_name; - $pdf_file_name =~ s/\.\w+$/\.pdf/; # replace extension with pdf - - ########################################## - # create working directory - ########################################## - - # create a randomly-named working directory in the TEMPOUTPUTDIR() directory - my $working_dir_path = eval { tempdir("work.XXXXXXXX", DIR => TEMPOUTPUTDIR()) }; - if ($@) { - push @errors, "Couldn't create temporary working directory: $@"; - } - # make sure the directory can be read by other daemons e.g. lighttpd - chmod 0755, $working_dir_path; - - # do some error checking - unless (-e $working_dir_path) { - push @errors, - "Temporary directory " - . $working_dir_path - . " does not exist, but creation didn't fail. This shouldn't happen."; - } - unless (-w $working_dir_path) { - push @errors, "Temporary directory " . $working_dir_path . " is not writeable."; - - } - - # catch errors if directory is not made (should be global, outside subroutine) - if (@errors) { - print "There were errors in creating the working directory for processing tex to pdf. \n" . join("\n", @errors); - delete_temp_dir($working_dir_path); - return 0; # FAIL if no working directory - } - - ######################################## - # try to mv the tex file into the working directory - ######################################## - - my $src_path = TEMPOUTPUTDIR() . $tex_file_name; - my $dest_path = "$working_dir_path/$tex_file_name"; - my $mv_cmd = "2>&1 mv " . shell_quote("$src_path", "$dest_path"); - my $mv_out = readpipe $mv_cmd; - if ($?) { - push @errors, "Failed to rename $src_path to " . "$dest_path in directory \n" . "$mv_out"; - print join("\n", @errors); - } - - ########################################## - # process tex file to pdf (if working directory was created) - ########################################## - @errors = (); # reset errors - - my $tex_file_path = $dest_path; - my $pdf_path = "$working_dir_path/$pdf_file_name"; - print "pdflatex $tex_file_path\n" if $UNIT_TESTS_ON; - - # call pdflatex - we don't want to chdir in the mod_perl process, as - # that might step on the feet of other things (esp. in Apache 2.0) - my $pdflatex_cmd = "cd " - . shell_quote($working_dir_path) . " && " - . "pdflatex" - . " $tex_file_name >pdflatex.stdout 2>pdflatex.stderr hardcopy"; - if (my $rawexit = system $pdflatex_cmd) { - my $exit = $rawexit >> 8; - my $signal = $rawexit & 127; - my $core = $rawexit & 128; - push @errors, - "Failed to convert TeX to PDF with command $pdflatex_cmd))" . " (exit=$exit signal=$signal core=$core)."; - - # read hardcopy.log and report first error - my $hardcopy_log = "$working_dir_path/$tex_file_name"; - $hardcopy_log =~ s/\.tex$/\.log/; # replace extension - if (-e $hardcopy_log) { - if (open my $LOG, "<", $hardcopy_log) { - my $line; - while ($line = <$LOG>) { - last if $line =~ /^!\s+/; - } - my $first_error = $line; - while ($line = <$LOG>) { - last if $line =~ /^!\s+/; - $first_error .= $line; - } - close $LOG; - if (defined $first_error) { - push @errors, "First error in TeX log is: $first_error"; - } else { - push @errors, "No errors encoundered in TeX log."; - } - } else { - push @errors, "Could not read TeX log: $!"; - } - } else { - push @errors, "No TeX log was found."; - } - } - - ######################################## - # try to rename the pdf file - ######################################## - - my $src_path1 = $pdf_path; - my $final_pdf_path = TEMPOUTPUTDIR() . $pdf_file_name; - my $mv_cmd1 = "2>&1 mv " . shell_quote("$src_path1", "$final_pdf_path"); - my $mv_out1 = readpipe $mv_cmd1; - if ($?) { - push @errors, "Failed to rename $src_path to " . "$final_pdf_path in directory \n" . "$mv_out1"; - } - - ################################################## - # remove the temp directory if there are no errors - ################################################## - if (@errors) { - print "Errors in converting the tex file to pdf: " . join("\n", @errors); - return 0; - } - - unless (@errors or $UNIT_TESTS_ON) { - delete_temp_dir($working_dir_path); - } - - # return path to pdf file - print "pdflatex to $final_pdf_path DONE\n" if $UNIT_TESTS_ON; - # this is doable but will require changing directories - # look at the solution done using hardcopy - return $final_pdf_path; -} - -# helper function to remove temp dirs -sub delete_temp_dir { - my ($temp_dir_path) = @_; - - my $rm_cmd = "2>&1 rm -rf " . shell_quote($temp_dir_path); #can use perl command for this?? - my $rm_out = readpipe $rm_cmd; - if ($?) { - print "Failed to remove temporary directory '" . $temp_dir_path . "':\n$rm_out\n"; - return 0; - } else { - return 1; - } -} - -sub create_tex_output { - my $file_path = shift; - my $formatter = shift; - my $output_text = $formatter->formatRenderedProblem; - $file_path =~ s|/$||; # remove final / - $file_path =~ m|/?([^/]+)$|; - my $file_name = $1; - $file_name =~ s/\.\w+$/\.tex/; # replace extension with tex - my $output_file = TEMPOUTPUTDIR() . $file_name; - local (*FH); - open(FH, '>:encoding(UTF-8)', $output_file) or die "Can't open file $output_file for writing"; - print FH $output_text; - close(FH); - print "tex result sent to $output_file\n" if $UNIT_TESTS_ON; - # sleep 5; #wait 5 seconds - # unlink($output_file); - return $file_name; -} - -sub create_json_output { - my $file_path = shift; - my $formatter = shift; - my $output_text = $formatter->formatRenderedProblem; - $file_path =~ s|/$||; # remove final / - $file_path =~ m|/?([^/]+)$|; - my $file_name = $1; - $file_name =~ s/\.\w+$/\.json/; # replace extension with json - my $output_file = TEMPOUTPUTDIR() . $file_name; - local (*FH); - open(FH, '>:encoding(UTF-8)', $output_file) or die "Can't open file $output_file for writing"; - print FH $output_text; - close(FH); - print "json result sent to $output_file\n" if $UNIT_TESTS_ON; - # sleep 5; #wait 5 seconds - # unlink($output_file); - return $file_name; -} - -sub display_html_output { #display the problem in a browser - my $file_path = shift; - my $formatter = shift; - my $output_text = $formatter->formatRenderedProblem; - $file_path =~ s|/$||; # remove final / - $file_path =~ m|/?([^/]+)$|; - my $file_name = $1; - $file_name =~ s/\.\w+$/\.html/; # replace extension with html - my $output_file = TEMPOUTPUTDIR() . $file_name; - local (*FH); - open(FH, '>:encoding(UTF-8)', $output_file) or die "Can't open file $output_file for writing"; - print FH $output_text; - close(FH); - - system($HTML_DISPLAY_COMMAND. " " . $output_file); - sleep 5; #wait 1 seconds - unlink($output_file); -} - -sub display_hash_output { # print the entire hash output to the command line - my $file_path = shift; - my $formatter = shift; - my $output_text = $formatter->formatRenderedProblem; - $file_path =~ s|/$||; # remove final / - $file_path =~ m|/?([^/]+)$|; - my $file_name = $1; - $file_name =~ s/\.\w+$/\.txt/; # replace extension with html - my $output_file = TEMPOUTPUTDIR() . $file_name; - my $output_text2 = pretty_print_rh($output_text); - print STDOUT $output_text2; - - # local(*FH); - # open(FH, '>', $output_file) or die "Can't open file $output_file writing"; - # print FH $output_text2; - # close(FH); - # - # system($HASH_DISPLAY_COMMAND().$output_file."; rm $output_file;"); - #sleep 1; #wait 1 seconds - #unlink($output_file); -} - -sub display_ans_output { # print the collection of answer hashes to the command line - my $file_path = shift; - my $formatter = shift; - my $return_object = $formatter->return_object; - $file_path =~ s|/$||; # remove final / - $file_path =~ m|/?([^/]+)$|; - my $file_name = $1; - $file_name =~ s/\.\w+$/\.txt/; # replace extension with html - my $output_file = TEMPOUTPUTDIR() . $file_name; - my $output_text = pretty_print_rh($return_object->{answers}); - print STDOUT $output_text; - # local(*FH); - # open(FH, '>', $output_file) or die "Can't open file $output_file writing"; - # print FH $output_text; - # close(FH); - # - # system($HASH_DISPLAY_COMMAND().$output_file."; rm $output_file;"); - # sleep 1; #wait 1 seconds - # unlink($output_file); -} - -sub record_problem_ok1 { - my $error_flag = shift // ''; - my $formatter = shift; # for formatting - my $file_path = shift; - my $return_string = ''; - my $return_object = $formatter->return_object; - if (defined($return_object->{flags}->{DEBUG_messages})) { - my @debug_messages = @{ $return_object->{flags}->{DEBUG_messages} }; - $return_string .= (pop @debug_messages) || ''; #avoid error if array was empty - if (@debug_messages) { - $return_string .= join(" ", @debug_messages); - } else { - $return_string = ""; - } - } - if (defined($return_object->{errors})) { - $return_string = $return_object->{errors}; - } - if (defined($return_object->{flags}->{WARNING_messages})) { - my @warning_messages = @{ $return_object->{flags}->{WARNING_messages} }; - $return_string .= (pop @warning_messages) || ''; #avoid error if array was empty - $@ = undef; - if (@warning_messages) { - $return_string .= join(" ", @warning_messages); - } else { - $return_string = ""; - } - } - my $SHORT_RETURN_STRING = ($return_string) ? "has errors" : "ok"; - unless ($return_string) { - $return_string = "1\t $file_path is ok\n"; - } else { - $return_string = "0\t $file_path has errors\n"; - } - - local (*FH); - open(FH, '>>:encoding(UTF-8)', $path_to_log_file) or die "Can't open file $path_to_log_file for writing"; - print FH $return_string; - close(FH); - return $SHORT_RETURN_STRING; -} - -sub record_problem_ok2 { - my $error_flag = shift // ''; - my $formatter = shift; - my $file_path = shift; - my $some_correct_answers_not_specified = shift; - my $pg_duration = shift; #processing time - my $return_object = $formatter->return_object; - my %scores = (); - my $ALL_CORRECT = 0; - my $all_correct = ($error_flag) ? 0 : 1; - - foreach my $ans (keys %{ $return_object->{answers} }) { - $scores{$ans} = - $return_object->{answers}->{$ans}->{score}; - $all_correct = $all_correct && $scores{$ans}; - } - $all_correct = ".5" if $some_correct_answers_not_specified; - $ALL_CORRECT = ($all_correct == 1) ? 'All answers are correct' : 'Some answers are incorrect'; - local (*FH); - open(FH, '>>:encoding(UTF-8)', $path_to_log_file) or die "Can't open file $path_to_log_file for writing"; - print FH "$all_correct $file_path\n"; # do we need this? compile_errors=$error_flag\n"; - close(FH); - return $ALL_CORRECT; -} - -########################################### -# standalonePGproblemRenderer -- not needed for sendXMLRPC -########################################### - -################################################## -# utilities -################################################## - -sub display_inputs { - my %correct_answers = @_; - foreach my $key (sort keys %correct_answers) { - print "$key => $correct_answers{$key}\n"; - } -} - -sub edit_source_file { - my $file_path = shift; - system(EDIT_COMMAND() . " $file_path"); -} - -################################################## -# Get problem template source and adjust file_path name -################################################## - -sub get_source { - my $file_path = shift; - my $source; - die "Unable to read file $file_path \n" unless $file_path eq '-' or -r $file_path; - eval { #File::Slurp would be faster (see perl monks) - local $/ = undef; - if ($file_path eq '-') { - $source = ; - } else { - # To support proper behavior with UTF-8 files, we need to open them with "<:encoding(UTF-8)" - # as otherwise, the first HTML file will render properly, but when "Preview" "Submit answer" - # or "Show correct answer" is used it will make problems, as in process_problem() the - # encodeSource() method is called on a data which is still UTF-8 encoded, and leads to double - # encoding and gibberish. - # NEW: - open(FH, "<:encoding(UTF-8)", $file_path) or die "Couldn't open file $file_path: $!"; - # OLD: - #open(FH, "<" ,$file_path) or die "Couldn't open file $file_path: $!"; - $source = ; #slurp input - close FH; - } - }; - die "Something is wrong with the contents of $file_path\n" if $@; - ### adjust file_path so that it is relative to the rendering course directory - #$file_path =~ s|/opt/webwork/libraries/NationalProblemLibrary|Library|; - $file_path =~ s|^.*?/webwork-open-problem-library/OpenProblemLibrary|Library|; - print "file_path changed to $file_path\n" if $UNIT_TESTS_ON; - print $source if $UNIT_TESTS_ON; - return $file_path, $source; -} - -################################################## -# utilities -################################################## - -sub pretty_print_rh { - shift if UNIVERSAL::isa($_[0] => __PACKAGE__); - my $rh = shift; - my $indent = shift || 0; - my $out = ""; - my $type = ref($rh); - - if (defined($type) and $type) { - $out .= " type = $type; "; - } elsif (!defined($rh)) { - $out .= " type = UNDEFINED; "; - } - return $out . " " unless defined($rh); - - if (ref($rh) =~ /HASH/) { - $out .= "{\n"; - $indent++; - foreach my $key (sort keys %{$rh}) { - $out .= " " x $indent . "$key => " . pretty_print_rh($rh->{$key}, $indent) . "\n"; - } - $indent--; - $out .= "\n" . " " x $indent . "}\n"; - - } elsif (ref($rh) =~ /ARRAY/ or "$rh" =~ /ARRAY/) { - $out .= " ( "; - foreach my $elem (@{$rh}) { - $out .= pretty_print_rh($elem, $indent); - - } - $out .= " ) \n"; - } elsif (ref($rh) =~ /SCALAR/) { - $out .= "scalar reference " . ${$rh}; - } elsif (ref($rh) =~ /Base64/) { - $out .= "base64 reference " . $$rh; - } else { - $out .= $rh; - } - - return $out . " "; -} - -############################################ -# Help message -############################################ - -sub print_help_message { - print <<'EOT'; -NAME - webwork2/clients/sendXMLRPC.pl - -DESCRIPTION - This script will take a list of files or directories and send it to a - WeBWorK daemon webservice to have it rendered. For directories each .pg - file under that directory is rendered. - - The results can be displayed in a browser (use -b or -B switches) as was - done with renderProblem.pl, on the command line (Use -h or -H switches) - as was done with renderProblem_rawoutput.pl or summary information about - whether the problem was correctly rendered can be sent to a log file - (use -c or C switches). - - The capital letter switches, -B, -H, and -C render the question twice. - The first time returns an answer hash which contains the correct - answers. The question is then resubmitted to the renderer with the - correct answers filled in and displayed. - - IMPORTANT: Remember to configure the local output file and display - command near the top of this script. !!!!!!!! - - IMPORTANT: Create a valid credentials file. - -SYNOPSIS - sendXMLRPC -vcCbB input.pg - -DETAILS - credentials file - These locations are searched, in order, for the credentials file. - ("$ENV{HOME}/.ww_credentials", "$ENV{HOME}/ww_session_credentials", 'ww_credentials', 'ww_credentials.dist'); - - Place a credential file containing the following information at one of the locations above - or create a file with this information and specify it with the --credentials option. - - %credentials = ( - userID => "my login name for the webwork course", - course_password => "my password ", - courseID => "the name of the webwork course", - SITE_URL => "url of rendering site", - XML_PASSWORD => "site password", # preliminary access to site - form_action_url => 'http://localhost:80/webwork2/html2xml' #action url for form - ); - - Options - -a - Displays the answer hashes returned by the question on the command line. - - -A - Same as -a but renders the question with the correct answers submitted. - - -b - Display the rendered question in a browser (specified by the DISPLAY_HTML_COMMAND variable). - - -B - Same as -b but renders the question with the correct answers submitted. - - -h - Prints to STDOUT the entire object returned by - the webwork_client xmlrpc request. - This includes the answer information displayed by -a and -A and much more. - - -H - Same as -h but renders the question with the correct answers submitted - - -c - "check" -- Record success or failure of rendering the question to a log file. - - -C - Same as -c but the question is rendered with the correct answers submitted. - This succeeds only if the correct answers, as determined from the answer hash, all succeed. - - f=s - Specify the format used by the browser in displaying the question. - Choices for s are - standard - sticky - debug - simple - - -v - Verbose output. Used mostly for debugging. - In particular it displays explicitly the correct answers which are (will be) - submitted to the question and it specifies which credential file is used. - - -e - - Open the source file in an editor. - The single letter options can be "bundled" e.g. -vcCbB - --tex - Process question in TeX mode and output to the command line - --pdf - Process question in TeX mode, then by pdflatex and output - to the command line - - --list pg_list - Read and process a list of .pg files contained in the file C. C - consists of a sequence of lines each of which contains the full path to a pg - file that should be processed. (For example this might be the output from an - earlier run of sendXMLRPC using the -c flag. ) - - --pg - Triggers the printing of the all of the variables available to the PG question. - The table appears within the question content. Use in conjunction with -b or -B. - --anshash - Prints the answer hash for each answer in the PG_debug output which appears below - the question content. Use in conjunction with -b or -B. - Similar to -a or -A but the output appears in the browser and - not on the command line. - - --ansgrp - Prints the PGanswergroup for each answer evaluator. The information appears in - the PG_debug output which follows the question content. Use in conjunction with -b or -B. - This contains more information than printing the answer hash. (perhaps too much). - - --resource - - Prints the resources used by the question. The information appears in - the PG_debug output which follows the question content. Use in conjunction with -b or -B. - - - --credentials=s - - Specifies a file s where the credential information can be found. - - --help - Prints help information. - - --log - Sets path to log file - - --seed=s - Sets problemSeed to the number contained in string s - - -EOT -} - -1; diff --git a/conf/authen_LTI.conf.dist b/conf/authen_LTI.conf.dist index 6805215186..d31b9d9bb4 100644 --- a/conf/authen_LTI.conf.dist +++ b/conf/authen_LTI.conf.dist @@ -25,8 +25,8 @@ $debug_lti_grade_passback = 0; # The switches above can be set in course.conf to enable debugging for just one course. -# If you want even more information enable the debug facility for SubmitGrade.pm in the -# WeBWorK::Constants file. This will print extensive debugging messages for all courses. +# If you want even more information enable the debug facility in the webwork2.mojolicious.yml +# file. This will print extensive debugging messages for all courses. # Note that for LTI 1.3 not all debug message will make it back to the HTML page due to the # nature of how LTI 1.3 authentication works with automatic form submissions and redirects. diff --git a/conf/site.conf.dist b/conf/site.conf.dist index 9a3de60371..3c52d8f7f0 100644 --- a/conf/site.conf.dist +++ b/conf/site.conf.dist @@ -237,9 +237,6 @@ $database_password ='passwordRW'; # server. You may use the defaults unless you have things in different places. ################################################################################# -# Root directory of PG. -$pg_dir = "/opt/webwork/pg"; - # URL and path to htdocs directory. $webwork_htdocs_url = "/webwork2_files"; $webwork_htdocs_dir = "$webwork_dir/htdocs"; diff --git a/conf/webwork2.mojolicious.dist.yml b/conf/webwork2.mojolicious.dist.yml index b61e9b3656..29dca8a0ce 100644 --- a/conf/webwork2.mojolicious.dist.yml +++ b/conf/webwork2.mojolicious.dist.yml @@ -178,3 +178,28 @@ hypnotoad: # Comment out the line below if serving directly. proxy: 1 + +# The remainder of the settings in this file are primarily for developers, +# and you usually do not need to change anything below here. + +debug: + # If set to 1, WeBWorK::Debug will print extensive debugging output. + enabled: 0 + + # If set, debugging output will be sent to the file named rather than STDERR. + # Note that the server must have write access to this file's location. + #logfile: /opt/webwork/webwork2/logs/debug.log + + # Prevent subroutines matching the given regular expression from logging. + # For example to remove all messages from subroutines in a WeBWorK::Authen + # module uncomment the following example. + #deny_subroutine_output: ^WeBWorK::Authen::.*$ + + # Allow only subroutines matching the following regular expression to log. + # For example to only allow messages from subroutines in a WeBWorK::Authen + # module uncomment the following example. + #allow_subroutine_output: ^WeBWorK::Authen::.*$ + +hardcopy: + # If 1, don't delete temporary files created when a hardcopy is generated. + preserve_temp_files: 0 diff --git a/lib/Caliper/Entity.pm b/lib/Caliper/Entity.pm index d8749d46f6..11474f4ac3 100644 --- a/lib/Caliper/Entity.pm +++ b/lib/Caliper/Entity.pm @@ -20,9 +20,8 @@ sub webwork_app { my $resource_iri = Caliper::ResourseIri->new($ce); # $ce doesn't have WW_VERSION when doing login/logout for some reason - my $webwork_dir = $WeBWorK::Constants::WEBWORK_DIRECTORY; - my $seed_ce = new WeBWorK::CourseEnvironment({ webwork_dir => $webwork_dir }); - my $ww_version = $seed_ce->{WW_VERSION} || "unknown"; + my $seed_ce = WeBWorK::CourseEnvironment->new; + my $ww_version = $seed_ce->{WW_VERSION} || "unknown"; return { 'id' => $resource_iri->webwork(), diff --git a/lib/Caliper/ResourceIri.pm b/lib/Caliper/ResourceIri.pm index 6fe315ccc0..0aeab86bb6 100644 --- a/lib/Caliper/ResourceIri.pm +++ b/lib/Caliper/ResourceIri.pm @@ -13,9 +13,8 @@ sub new { my ($class, $ce) = @_; # need to use $seed_ce in case of logout - my $webwork_dir = $WeBWorK::Constants::WEBWORK_DIRECTORY; - my $seed_ce = new WeBWorK::CourseEnvironment({ webwork_dir => $webwork_dir }); - my $base_url = $seed_ce->{server_root_url} . $seed_ce->{webwork_url}; + my $seed_ce = WeBWorK::CourseEnvironment->new; + my $base_url = $seed_ce->{server_root_url} . $seed_ce->{webwork_url}; if (defined($seed_ce->{caliper}{base_url}) && $seed_ce->{caliper}{base_url} ne '') { $base_url = $seed_ce->{caliper}{base_url}; } diff --git a/lib/Mojolicious/WeBWorK.pm b/lib/Mojolicious/WeBWorK.pm index 20d1cf8feb..4f700a4b75 100644 --- a/lib/Mojolicious/WeBWorK.pm +++ b/lib/Mojolicious/WeBWorK.pm @@ -41,13 +41,20 @@ sub startup ($app) { # Configure the application $app->secrets($config->{secrets}); + # Set constants from the configuration. + $WeBWorK::Debug::Enabled = $config->{debug}{enabled} // 0; + $WeBWorK::Debug::Logfile = $config->{debug}{logfile} // ''; + $WeBWorK::Debug::DenySubroutineOutput = $config->{debug}{deny_subroutine_output}; + $WeBWorK::Debug::AllowSubroutineOutput = $config->{debug}{allow_subroutine_output}; + $WeBWorK::ContentGenerator::Hardcopy::PreserveTempFiles = $config->{hardcopy}{preserve_temp_files} // 0; + # Load the plugin that switches the server to the non-root server user and group # if the app is run as root and is in production mode. $app->plugin(SetUserGroup => { user => $config->{server_user}, group => $config->{server_group} }) if $app->mode eq 'production' && $> == 0; # Load a minimal course environment - my $ce = WeBWorK::CourseEnvironment->new({ webwork_dir => $ENV{WEBWORK_ROOT} }); + my $ce = WeBWorK::CourseEnvironment->new; # Set important configuration variables my $webwork_url = $ce->{webwork_url}; diff --git a/lib/Mojolicious/WeBWorK/Tasks/LTIMassUpdate.pm b/lib/Mojolicious/WeBWorK/Tasks/LTIMassUpdate.pm index 12683a8e61..d0ef1bc4b4 100644 --- a/lib/Mojolicious/WeBWorK/Tasks/LTIMassUpdate.pm +++ b/lib/Mojolicious/WeBWorK/Tasks/LTIMassUpdate.pm @@ -28,7 +28,7 @@ sub run ($job, $courseID, $userID = '', $setID = '') { # can start. New jobs retry every minute until they can aquire their own lock. return $job->retry({ delay => 60 }) unless my $guard = $job->minion->guard('lti_mass_update', 3600); - my $ce = eval { WeBWorK::CourseEnvironment->new({ %WeBWorK::SeedCE, courseName => $courseID }) }; + my $ce = eval { WeBWorK::CourseEnvironment->new({ courseName => $courseID }) }; return $job->fail("Could not construct course environment for $courseID.") unless $ce; my $db = WeBWorK::DB->new($ce->{dbLayout}); diff --git a/lib/Mojolicious/WeBWorK/Tasks/SendInstructorEmail.pm b/lib/Mojolicious/WeBWorK/Tasks/SendInstructorEmail.pm index 047d101f9a..cf8a694ab6 100644 --- a/lib/Mojolicious/WeBWorK/Tasks/SendInstructorEmail.pm +++ b/lib/Mojolicious/WeBWorK/Tasks/SendInstructorEmail.pm @@ -28,7 +28,7 @@ use WeBWorK::Utils qw/processEmailMessage createEmailSenderTransportSMTP/; # Send instructor email messages to students. # FIXME: This job currently allows multiple jobs to run at once. Should it be limited? sub run ($job, $mail_data) { - my $ce = eval { WeBWorK::CourseEnvironment->new({ %WeBWorK::SeedCE, courseName => $mail_data->{courseName} }) }; + my $ce = eval { WeBWorK::CourseEnvironment->new({ courseName => $mail_data->{courseName} }) }; return $job->fail("Could not construct course environment for $mail_data->{courseName}.") unless $ce; my $db = WeBWorK::DB->new($ce->{dbLayout}); diff --git a/lib/WeBWorK.pm b/lib/WeBWorK.pm index 07b06729f7..971a089ff9 100644 --- a/lib/WeBWorK.pm +++ b/lib/WeBWorK.pm @@ -40,10 +40,6 @@ the action of the content generator module for the designated route. use Time::HiRes qw/time/; use WeBWorK::Localize; - -# Load WeBWorK::Constants before anything else. This sets package variables in several packages. -use WeBWorK::Constants; - use WeBWorK::Authen; use WeBWorK::Authz; use WeBWorK::CourseEnvironment; @@ -165,7 +161,7 @@ async sub dispatch ($c) { # Create Course Environment debug("We need to get a course environment (with or without a courseID!)\n"); - my $ce = eval { WeBWorK::CourseEnvironment->new({ %SeedCE, courseName => $routeCaptures{courseID} }) }; + my $ce = eval { WeBWorK::CourseEnvironment->new({ courseName => $routeCaptures{courseID} }) }; $@ and die "Failed to initialize course environment: $@\n"; debug("Here's the course environment: $ce\n"); $c->ce($ce); diff --git a/lib/WeBWorK/Constants.pm b/lib/WeBWorK/Constants.pm deleted file mode 100644 index 208d81e039..0000000000 --- a/lib/WeBWorK/Constants.pm +++ /dev/null @@ -1,68 +0,0 @@ -################################################################################ -# WeBWorK Online Homework Delivery System -# Copyright © 2000-2022 The WeBWorK Project, https://github.com/openwebwork -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of either: (a) the GNU General Public License as published by the -# Free Software Foundation; either version 2, or (at your option) any later -# version, or (b) the "Artistic License" which comes with this package. -# -# 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 either the GNU General Public License or the -# Artistic License for more details. -################################################################################ - -package WeBWorK::Constants; - -=head1 NAME - -WeBWorK::Constants - provide constant values for other WeBWorK modules. - -=cut - -use strict; -use warnings; - -$WeBWorK::Constants::WEBWORK_DIRECTORY = $ENV{WEBWORK_ROOT} unless defined($WeBWorK::Constants::WEBWORK_DIRECTORY); -$WeBWorK::Constants::PG_DIRECTORY = $ENV{PG_ROOT} unless defined($WeBWorK::Constants::PG_DIRECTORY); - -################################################################################ -# WeBWorK::Debug -################################################################################ - -# If true, WeBWorK::Debug will print debugging output. -# -$WeBWorK::Debug::Enabled = 0; - -# If non-empty, debugging output will be sent to the file named rather than STDERR. -# -$WeBWorK::Debug::Logfile = $WeBWorK::Constants::WEBWORK_DIRECTORY . "/logs/debug.log"; - -# If defined, prevent subroutines matching the following regular expression from -# logging. -# -# For example, this pattern prevents the dispatch() function from logging: -# $WeBWorK::Debug::DenySubroutineOutput = qr/^WeBWorK::dispatch$/; -# -$WeBWorK::Debug::DenySubroutineOutput = undef; -#$WeBWorK::Debug::DenySubroutineOutput = qr/^WeBWorK::dispatch$/; - -# If defined, allow only subroutines matching the following regular expression -# to log. -# -# For example, this pattern allow only some function being worked on to log: -# $WeBWorK::Debug::AllowSubroutineOutput = qr/^WeBWorK::SomePkg::myFunc$/; -# -# $WeBWorK::Debug::AllowSubroutineOutput = undef; -# $WeBWorK::Debug::AllowSubroutineOutput =qr/^WeBWorK::Authen::get_credentials$/; - -################################################################################ -# WeBWorK::ContentGenerator::Hardcopy -################################################################################ - -# If true, don't delete temporary files -# -$WeBWorK::ContentGenerator::Hardcopy::PreserveTempFiles = 0; - -1; diff --git a/lib/WeBWorK/ContentGenerator/CourseAdmin.pm b/lib/WeBWorK/ContentGenerator/CourseAdmin.pm index 2fb94a5e4e..d8a07e5867 100644 --- a/lib/WeBWorK/ContentGenerator/CourseAdmin.pm +++ b/lib/WeBWorK/ContentGenerator/CourseAdmin.pm @@ -309,9 +309,7 @@ sub do_add_course ($c) { my $add_dbLayout = trim_spaces($c->param('add_dbLayout')) || ''; - my $ce2 = WeBWorK::CourseEnvironment->new({ - %WeBWorK::SeedCE, courseName => $add_courseID, - }); + my $ce2 = WeBWorK::CourseEnvironment->new({ courseName => $add_courseID }); my %courseOptions = (dbLayoutName => $add_dbLayout); @@ -499,7 +497,7 @@ sub rename_course_confirm ($c) { my $rename_newCourseTitle = $c->param('rename_newCourseTitle') || ''; my $rename_newCourseInstitution = $c->param('rename_newCourseInstitution') || ''; - my $ce2 = WeBWorK::CourseEnvironment->new({ %WeBWorK::SeedCE, courseName => $rename_oldCourseID }); + my $ce2 = WeBWorK::CourseEnvironment->new({ courseName => $rename_oldCourseID }); # Create strings confirming title and institution change. # Connect to the database to get old title and institution. @@ -647,7 +645,7 @@ sub do_retitle_course ($c) { $optional_arguments{courseInstitution} = $rename_newCourseInstitution if $institution_checkbox; my $ce2; - eval { $ce2 = WeBWorK::CourseEnvironment->new({ %WeBWorK::SeedCE, courseName => $rename_oldCourseID }); }; + eval { $ce2 = WeBWorK::CourseEnvironment->new({ courseName => $rename_oldCourseID }); }; warn "failed to create environment in do_retitle_course $@" if $@; eval { retitleCourse(courseID => $rename_oldCourseID, ce => $ce2, dbOptions => {}, %optional_arguments); }; @@ -740,7 +738,7 @@ sub do_rename_course ($c) { eval { renameCourse( courseID => $rename_oldCourseID, - ce => WeBWorK::CourseEnvironment->new({ %WeBWorK::SeedCE, courseName => $rename_oldCourseID }), + ce => WeBWorK::CourseEnvironment->new({ courseName => $rename_oldCourseID }), dbOptions => {}, newCourseID => $rename_newCourseID, %optional_arguments @@ -876,7 +874,7 @@ sub do_delete_course ($c) { eval { deleteCourse( courseID => $delete_courseID, - ce => WeBWorK::CourseEnvironment->new({ %WeBWorK::SeedCE, courseName => $delete_courseID }), + ce => WeBWorK::CourseEnvironment->new({ courseName => $delete_courseID }), dbOptions => {} ); }; @@ -1010,7 +1008,7 @@ sub archive_course_confirm ($c) { my $archive_courseID = $archive_courseIDs[0]; - my $ce2 = WeBWorK::CourseEnvironment->new({ %WeBWorK::SeedCE, courseName => $archive_courseID }); + my $ce2 = WeBWorK::CourseEnvironment->new({ courseName => $archive_courseID }); if ($ce2->{dbLayoutName}) { my $CIchecker = WeBWorK::Utils::CourseIntegrityCheck->new(ce => $ce2); @@ -1063,7 +1061,7 @@ sub do_archive_course ($c) { my @archive_courseIDs = $c->param('archive_courseIDs'); my $archive_courseID = $archive_courseIDs[0]; - my $ce2 = WeBWorK::CourseEnvironment->new({ %WeBWorK::SeedCE, courseName => $archive_courseID }); + my $ce2 = WeBWorK::CourseEnvironment->new({ courseName => $archive_courseID }); # Remove course specific temp files before archiving, but don't delete the temp directory itself. remove_tree($ce2->{courseDirs}{html_temp}, { keep_root => 1 }); @@ -1351,7 +1349,7 @@ sub upgrade_course_confirm ($c) { next unless $upgrade_courseID =~ /\S/; # skip empty values # Analyze one course - my $ce2 = WeBWorK::CourseEnvironment->new({ %WeBWorK::SeedCE, courseName => $upgrade_courseID }); + my $ce2 = WeBWorK::CourseEnvironment->new({ courseName => $upgrade_courseID }); # Create integrity checker my $CIchecker = WeBWorK::Utils::CourseIntegrityCheck->new(ce => $ce2); @@ -1467,7 +1465,7 @@ sub do_upgrade_course ($c) { next unless $upgrade_courseID =~ /\S/; # Omit blank course IDs # Update one course - my $ce2 = WeBWorK::CourseEnvironment->new({ %WeBWorK::SeedCE, courseName => $upgrade_courseID }); + my $ce2 = WeBWorK::CourseEnvironment->new({ courseName => $upgrade_courseID }); # Create integrity checker my $CIchecker = WeBWorK::Utils::CourseIntegrityCheck->new(ce => $ce2); diff --git a/lib/WeBWorK/ContentGenerator/Instructor/Config.pm b/lib/WeBWorK/ContentGenerator/Instructor/Config.pm index 8438104a91..6d9a4107e4 100644 --- a/lib/WeBWorK/ContentGenerator/Instructor/Config.pm +++ b/lib/WeBWorK/ContentGenerator/Instructor/Config.pm @@ -149,13 +149,12 @@ sub pre_header_initialize ($c) { my $ce = $c->ce; my $configValues = $c->getConfigValues($ce); # Get a course environment without course.conf - $c->{default_ce} = WeBWorK::CourseEnvironment->new({ %WeBWorK::SeedCE, }); + $c->{default_ce} = WeBWorK::CourseEnvironment->new; $c->{ce_file_dir} = $ce->{courseDirs}{root}; # Get a copy of the course environment which does not have simple.conf loaded my $ce3 = WeBWorK::CourseEnvironment->new({ - %WeBWorK::SeedCE, courseName => $ce->{courseName}, web_config_filename => 'noSuchFilePlease' }); diff --git a/lib/WeBWorK/CourseEnvironment.pm b/lib/WeBWorK/CourseEnvironment.pm index a5bf17aef7..2b138a0a19 100644 --- a/lib/WeBWorK/CourseEnvironment.pm +++ b/lib/WeBWorK/CourseEnvironment.pm @@ -51,73 +51,54 @@ safe compartment into a hash. This hash becomes the course environment. use strict; use warnings; + use Carp; +use Opcode qw(empty_opset); + use WWSafe; use WeBWorK::Utils qw(readFile); use WeBWorK::Debug; -use Opcode qw(empty_opset); =head1 CONSTRUCTION =over -=item new(HASHREF) +=item new($seedVars) -HASHREF is a reference to a hash containing scalar variables with which to seed -the course environment. It must contain at least a value for the key -C. +C<$seedVars> is an optional argument. If provided it must be a reference to a +hash containing scalar variables with which to seed the course environment. It +may contain values for the keys C, C, C, and +C. -The C method finds the file F relative to the given +If C or C are not given in C<$seedVars> they will be taken +from the C<%WeBWorK::SeedCE> hash. If they are still not found in that hash, +then they will be taken from the system environment variables C +and C. + +The C method finds the file F relative to the C directory. After reading this file, it uses the C<$courseFiles{environment}> variable, if present, to locate the course environment file. If found, the file is read and added to the environment. -=item new(ROOT URLROOT PGROOT COURSENAME) - -A deprecated form of the constructor in which four seed variables are given -explicitly: C, C, C, and C. - =cut -# NEW SYNTAX -# -# new($invocant, $seedVarsRef) -# $invocant implicitly set by caller -# $seedVarsRef reference to hash containing scalar variables with which to -# seed the course environment -# -# OLD SYNTAX -# -# new($invocant, $webworkRoot, $webworkURLRoot, $pgRoot, $courseName) -# $invocant implicitly set by caller -# $webworkRoot directory that contains the WeBWorK distribution -# $webworkURLRoot URL that points to the WeBWorK system -# $pgRoot directory that contains the PG distribution -# $courseName name of the course being used sub new { - my ($invocant, @rest) = @_; + my ($invocant, $seedVars) = @_; my $class = ref($invocant) || $invocant; - # contains scalar symbols/values with which to seed course environment - my %seedVars; + $seedVars //= {}; + croak __PACKAGE__ . ": The only argument for new must be a hash reference.\n" unless ref($seedVars) eq 'HASH'; + + # Get the webwork_dir and pg_dir from the SeedCE or the environment if not set. + $seedVars->{webwork_dir} //= $WeBWorK::SeedCE{webwork_dir} // $ENV{WEBWORK_ROOT}; + $seedVars->{pg_dir} //= $WeBWorK::SeedCE{pg_dir} // $ENV{PG_ROOT}; + + $seedVars->{courseName} ||= '___'; # prevents extraneous error messages - # where do we get the seed variables? - if (ref $rest[0] eq "HASH") { - %seedVars = %{ $rest[0] }; - } else { - debug __PACKAGE__, ": deprecated four-argument form of new() used.", caller(1), "\n", caller(2), "\n"; - $seedVars{webwork_dir} = $rest[0]; - $seedVars{webwork_url} = $rest[1]; - $seedVars{pg_dir} = $rest[2]; - $seedVars{courseName} = $rest[3]; - } - $seedVars{courseName} = $seedVars{courseName} || "___"; # prevents extraneous error messages my $safe = WWSafe->new; $safe->permit('rand'); - # to avoid error messages make sure that courseName is defined - $seedVars{courseName} = $seedVars{courseName} // "foobar_course"; # seed course environment with initial values - while (my ($var, $val) = each %seedVars) { + while (my ($var, $val) = each %$seedVars) { $val = "" if not defined $val; $safe->reval("\$$var = '$val';"); } @@ -125,7 +106,7 @@ sub new { # Compile the "include" function with all opcodes available. my $include = q[ sub include { my ($file) = @_; - my $fullPath = "] . $seedVars{webwork_dir} . q[/$file"; + my $fullPath = "] . $seedVars->{webwork_dir} . q[/$file"; # This regex matches any string that begins with "../", # ends with "/..", contains "/../", or is "..". if ($fullPath =~ m!(?:^|/)\.\.(?:/|$)!) { @@ -151,16 +132,14 @@ sub new { # determine location of globalEnvironmentFile my $globalEnvironmentFile; - if (-r "$seedVars{webwork_dir}/conf/defaults.config") { - $globalEnvironmentFile = "$seedVars{webwork_dir}/conf/defaults.config"; + if (-r "$seedVars->{webwork_dir}/conf/defaults.config") { + $globalEnvironmentFile = "$seedVars->{webwork_dir}/conf/defaults.config"; } else { croak "Cannot read global environment file $globalEnvironmentFile"; } # read and evaluate the global environment file my $globalFileContents = readFile($globalEnvironmentFile); - # warn "about to evaluate defaults.conf $seedVars{courseName}\n"; - # warn join(" | ", (caller(1))[0,1,2,3,4] ), "\n"; $safe->share_from('main', [qw(%ENV)]); $safe->reval($globalFileContents); # warn "end the evaluation\n"; @@ -174,7 +153,7 @@ sub new { # (we don't want to do the hash conversion yet) no strict 'refs'; my $courseEnvironmentFile = ${ *{ ${ $safe->root . "::" }{courseFiles} } }{environment}; - my $courseWebConfigFile = $seedVars{web_config_filename} + my $courseWebConfigFile = $seedVars->{web_config_filename} || ${ *{ ${ $safe->root . "::" }{courseFiles} } }{simpleConfig}; use strict 'refs'; diff --git a/lib/WeBWorK/Debug.pm b/lib/WeBWorK/Debug.pm index 4e90fde506..3e991d14df 100644 --- a/lib/WeBWorK/Debug.pm +++ b/lib/WeBWorK/Debug.pm @@ -14,8 +14,15 @@ ################################################################################ package WeBWorK::Debug; -use base qw(Exporter); +use parent qw(Exporter); + +use strict; +use warnings; + use Date::Format; +use Time::HiRes qw/gettimeofday/; +use WeBWorK::Utils qw/undefstr/; + our @EXPORT = qw(debug); =head1 NAME @@ -25,26 +32,16 @@ WeBWorK::Debug - Print (or don't print) debugging output. head1 SYNOPSIS use WeBWorK::Debug; - + # Enable debugging $WeBWorK::Debug::Enabled = 1; - + # Log to a file instead of STDERR $WeBWorK::Debug::Logfile = "/path/to/debug.log"; - + # log some debugging output debug("Generated 5 widgets."); -=cut - -use strict; -use warnings; -use Time::HiRes qw/gettimeofday/; -use WeBWorK::Constants; -use WeBWorK::Utils qw/undefstr/; - -################################################################################ - =head1 CONFIGURATION VARIABLES =over @@ -55,7 +52,7 @@ If true, debugging messages will be output. If false, they will be ignored. =cut -our $Enabled = 0 unless defined $Enabled; +our $Enabled = $Enabled // 0; =item $Logfile @@ -63,7 +60,7 @@ If non-empty, debugging output will be sent to the file named rather than STDERR =cut -our $Logfile = "" unless defined $Logfile; +our $Logfile = $Logfile // ''; =item $DenySubroutineOutput @@ -85,10 +82,6 @@ our $AllowSubroutineOutput; =back -=cut - -################################################################################ - =head1 FUNCTIONS =over @@ -100,11 +93,8 @@ Write @messages to the debugging log. =cut sub debug { - my (@message) = undefstr("###UNDEF###", @_); - - #print STDERR "in ww::debug\n"; - #print STDERR $WeBWorK::Constants::WEBWORK_DIRECTORY . "\n"; - #print STDERR $Logfile . "\n"; + my @message = @_; + @message = undefstr('###UNDEF###', @message); if ($Enabled) { my ($package, $filename, $line, $subroutine) = caller(1); @@ -113,11 +103,11 @@ sub debug { my ($sec, $msec) = gettimeofday; my $date = time2str("%a %b %d %H:%M:%S.$msec %Y", $sec); - my $finalMessage = "[$date] $subroutine: " . join("", @message); + my $finalMessage = "[$date] $subroutine: " . join('', @message); $finalMessage .= "\n" unless $finalMessage =~ m/\n$/; - if ($WeBWorK::Debug::Logfile ne "") { - if (open my $fh, ">>:encoding(UTF-8)", $Logfile) { + if ($WeBWorK::Debug::Logfile ne '') { + if (open my $fh, '>>:encoding(UTF-8)', $Logfile) { print $fh $finalMessage; close $fh; } else { @@ -128,14 +118,12 @@ sub debug { print STDERR $finalMessage; } } + + return; } =back -=cut - -################################################################################ - =head1 AUTHOR Written by Sam Hathaway, sh002i (at) math.rochester.edu. diff --git a/lib/WeBWorK/Localize.pm b/lib/WeBWorK/Localize.pm index 1f3811ac24..fad943e9de 100644 --- a/lib/WeBWorK/Localize.pm +++ b/lib/WeBWorK/Localize.pm @@ -6,7 +6,7 @@ use Locale::Maketext::Lexicon; use WeBWorK::Utils qw(x); -my $path = "$WeBWorK::Constants::WEBWORK_DIRECTORY/lib/WeBWorK/Localize"; +my $path = "$ENV{WEBWORK_ROOT}/lib/WeBWorK/Localize"; my $pattern = File::Spec->catfile($path, '*.[pm]o'); my $decode = 1; my $encoding = undef; diff --git a/lib/WeBWorK/Utils.pm b/lib/WeBWorK/Utils.pm index 3fe9cbfed7..dc695e3ce4 100644 --- a/lib/WeBWorK/Utils.pm +++ b/lib/WeBWorK/Utils.pm @@ -1990,11 +1990,11 @@ sub getAssetURL { } unless ($staticPGAssets) { - my $staticAssetsList = "$WeBWorK::Constants::PG_DIRECTORY/htdocs/static-assets.json"; + my $staticAssetsList = "$ce->{pg_dir}/htdocs/static-assets.json"; $staticPGAssets = readJSON($staticAssetsList); unless ($staticPGAssets) { warn "ERROR: '$staticAssetsList' not found or not readable!\n" - . "You may need to run 'npm install' from '$WeBWorK::Constants::PG_DIRECTORY/htdocs'."; + . "You may need to run 'npm install' from '$ce->{pg_dir}/htdocs'."; $staticPGAssets = {}; } } @@ -2008,7 +2008,7 @@ sub getAssetURL { } unless ($thirdPartyPGDependencies) { - my $packageJSON = "$WeBWorK::Constants::PG_DIRECTORY/htdocs/package.json"; + my $packageJSON = "$ce->{pg_dir}/htdocs/package.json"; my $data = readJSON($packageJSON); warn "ERROR: '$packageJSON' not found or not readable!\n" unless $data && defined $data->{dependencies}; $thirdPartyPGDependencies = $data->{dependencies} // {}; diff --git a/lib/WeBWorK/Utils/CourseManagement.pm b/lib/WeBWorK/Utils/CourseManagement.pm index 40cc085b07..dcefd4ddaa 100644 --- a/lib/WeBWorK/Utils/CourseManagement.pm +++ b/lib/WeBWorK/Utils/CourseManagement.pm @@ -340,11 +340,8 @@ sub addCourse { if (exists $options{templatesFrom}) { my $sourceCourse = $options{templatesFrom}; - my $sourceCE = new WeBWorK::CourseEnvironment({ - get_SeedCE($ce), - courseName => $sourceCourse, # override courseName - }); - my $sourceDir = $sourceCE->{courseDirs}->{templates}; + my $sourceCE = WeBWorK::CourseEnvironment->new({ get_SeedCE($ce), courseName => $sourceCourse }); + my $sourceDir = $sourceCE->{courseDirs}->{templates}; ## copy templates ## if (-d $sourceDir) { my $destDir = $ce->{courseDirs}{templates}; @@ -958,9 +955,7 @@ sub unarchiveCourse { ##### step 3: read the course environment for this course ##### - my $ce2 = new WeBWorK::CourseEnvironment({ - get_SeedCE($ce), courseName => $currCourseID, - }); + my $ce2 = WeBWorK::CourseEnvironment->new({ get_SeedCE($ce), courseName => $currCourseID }); # pull out some useful stuff my $course_dir = $ce2->{courseDirs}{root}; @@ -1038,9 +1033,7 @@ sub _unarchiveCourse_move_away { my ($ce, $courseID) = @_; # course environment for before the course is moved - my $ce2 = new WeBWorK::CourseEnvironment({ - get_SeedCE($ce), courseName => $courseID, - }); + my $ce2 = WeBWorK::CourseEnvironment->new({ get_SeedCE($ce), courseName => $courseID }); # if course directory doesn't exist, we don't have to do anything return unless -e $ce2->{courseDirs}{root}; @@ -1056,9 +1049,7 @@ sub _unarchiveCourse_move_away { ); # course environment for after the course is moved - my $ce3 = new WeBWorK::CourseEnvironment({ - get_SeedCE($ce), courseName => $tmpCourseID, - }); + my $ce3 = WeBWorK::CourseEnvironment->new({ get_SeedCE($ce), courseName => $tmpCourseID }); # data to pass to renameCourse when moving the course back to it's original name my $restore_course_data = { diff --git a/lib/WebworkSOAP.pm b/lib/WebworkSOAP.pm index dbbbcfd254..289c55f0b0 100644 --- a/lib/WebworkSOAP.pm +++ b/lib/WebworkSOAP.pm @@ -38,7 +38,7 @@ sub new { my ($self, $authenKey, $courseName) = @_; $self = {}; #Construct Course - my $ce = eval { new WeBWorK::CourseEnvironment({ %SeedCE, courseName => $courseName }) }; + my $ce = eval { WeBWorK::CourseEnvironment->new({ %SeedCE, courseName => $courseName }) }; $@ and soap_fault_major("Course Environment cannot be constructed.
$@"); #Authentication Check if ($ce->{soap_authen_key} != $authenKey) { @@ -103,7 +103,7 @@ sub hello { sub list_courses { my ($self, $authenKey) = @_; - my $ce = eval { new WeBWorK::CourseEnvironment({%WeBWorK::SeedCE}) }; + my $ce = eval { WeBWorK::CourseEnvironment->new }; $@ and soap_fault_major("Internal Course Environment cannot be constructed."); if ($authenKey != $WebworkSOAP::SeedCE{soap_authen_key}) { soap_fault_authen; diff --git a/lib/WebworkWebservice/CourseActions.pm b/lib/WebworkWebservice/CourseActions.pm index 88a172d334..917402cd14 100644 --- a/lib/WebworkWebservice/CourseActions.pm +++ b/lib/WebworkWebservice/CourseActions.pm @@ -46,10 +46,7 @@ sub createCourse { if length($params->{name}) > $admin_ce->{maxCourseIdLength}; # Bring up a minimal course environment for the new course. - my $ce = WeBWorK::CourseEnvironment->new({ - webwork_dir => $admin_ce->{webwork_dir}, - courseName => $params->{name} - }); + my $ce = WeBWorK::CourseEnvironment->new({ courseName => $params->{name} }); # Copy user from admin course. # Modified from do_add_course in WeBWorK::ContentGenerator::CourseAdmin. diff --git a/lib/WebworkWebservice/RenderProblem.pm b/lib/WebworkWebservice/RenderProblem.pm index dec555c485..15246f8faa 100644 --- a/lib/WebworkWebservice/RenderProblem.pm +++ b/lib/WebworkWebservice/RenderProblem.pm @@ -26,7 +26,6 @@ use WeBWorK::Debug; use WeBWorK::CourseEnvironment; use WeBWorK::PG; use WeBWorK::DB; -use WeBWorK::Constants; use WeBWorK::Utils qw(decode_utf8_base64); use WeBWorK::Utils::Rendering qw(renderPG); use WeBWorK::DB::Utils qw(global2user); diff --git a/t/grab_course_environment.pl b/t/grab_course_environment.pl index 259a5375d6..b759d2725b 100755 --- a/t/grab_course_environment.pl +++ b/t/grab_course_environment.pl @@ -43,10 +43,7 @@ BEGIN It should be set to the webwork2 directory (e.g. /opt/webwork/webwork2)" unless exists $ENV{WEBWORK_ROOT}; - # Unused variable, but define it twice to avoid an error message. - $WeBWorK::Constants::WEBWORK_DIRECTORY = $ENV{WEBWORK_ROOT}; - - print "Webwork root directory is $WeBWorK::Constants::WEBWORK_DIRECTORY\n\n"; + print "Webwork root directory is $ENV{WEBWORK_ROOT}\n"; } BEGIN { @@ -54,7 +51,7 @@ BEGIN my $courseName = 'daemon_course'; #Define the OpaqueServer static variables - my $topDir = $WeBWorK::Constants::WEBWORK_DIRECTORY; + my $topDir = $ENV{WEBWORK_ROOT}; $topDir =~ s|webwork2?$||; # remove webwork2 link my $root_dir = "$topDir/ww_opaque_server"; my $root_pg_dir = "$topDir/pg"; diff --git a/templates/ContentGenerator/CourseAdmin/upgrade_course_form.html.ep b/templates/ContentGenerator/CourseAdmin/upgrade_course_form.html.ep index da7c7ff978..25139f9476 100644 --- a/templates/ContentGenerator/CourseAdmin/upgrade_course_form.html.ep +++ b/templates/ContentGenerator/CourseAdmin/upgrade_course_form.html.ep @@ -23,7 +23,7 @@ % next if $courseID eq 'modelCourse'; # modelCourse isn't a real course so it can't be upgraded. % next unless $courseID =~ /\S/; # Skip empty courseIDs (there shouldn't be any) % - % my $tempCE = eval { WeBWorK::CourseEnvironment->new({ %WeBWorK::SeedCE, courseName => $courseID }) }; + % my $tempCE = eval { WeBWorK::CourseEnvironment->new({ courseName => $courseID }) }; % if ($@) { <%= maketext(q{Can't create course environment for [_1] because [_2]}, $courseID, $@) =%> % } diff --git a/templates/ContentGenerator/Instructor/Config.html.ep b/templates/ContentGenerator/Instructor/Config.html.ep index 7dd4e339bc..4183e17869 100644 --- a/templates/ContentGenerator/Instructor/Config.html.ep +++ b/templates/ContentGenerator/Instructor/Config.html.ep @@ -8,7 +8,7 @@ % my $configValues = $c->getConfigValues($ce); % % # Get the current course environment again in case changes were just saved. -% my $ce4 = WeBWorK::CourseEnvironment->new({ %WeBWorK::SeedCE, courseName => $ce->{courseName}, }); +% my $ce4 = WeBWorK::CourseEnvironment->new({ courseName => $ce->{courseName}, }); % % if (@$configValues == 0) {

From ba6f40282486831f927ee0230054e3585349a418 Mon Sep 17 00:00:00 2001 From: Glenn Rice Date: Fri, 12 May 2023 21:29:55 -0500 Subject: [PATCH 2/2] Delete the clients and t directories. I am tired of seeing matches on things in these directories when grepping for variables that are obsolete, and nothing in these directories works anymore. --- clients/README | 73 --- .../hello_world_soap_client.pl | 19 - .../hello_world_xmlrpc_client.pl | 16 - .../hello_world_apps/webwork_soap_client.pl | 260 ---------- .../hello_world_apps/webwork_xmlrpc_client.pl | 472 ------------------ clients/pr | 16 - clients/sendxmlrpc_bbedit.pl | 5 - clients/t/TestWW.html | 128 ----- clients/t/bad_input.pg | 108 ---- clients/t/input.pg | 100 ---- clients/t/labels.pg | 29 -- clients/t/matrixtest4.pg | 53 -- clients/t/show-psvn.pg | 19 - clients/t/test-utf8-hebrew.pg | 37 -- clients/t/test1.pg | 40 -- clients/t/testMultAnswer.pg | 117 ----- clients/t/test_embedded_problems.html | 327 ------------ clients/t/test_formats_WWproblems.html | 106 ---- clients/t/test_simpleFormat_WWproblem.html | 64 --- .../t/test_toggled_embedded_WWproblems.html | 202 -------- .../t/test_two_embedded_images_localhost.html | 126 ----- .../t/test_two_images_localhost_base64.html | 187 ------- clients/uribase64_encode.pl | 7 - clients/ww_credentials.dist | 69 --- t/TestWW.html.dist | 128 ----- t/alternate_templates.html.dist | 107 ---- t/grab_course_environment.pl | 127 ----- t/testAttemptsTable.pl | 283 ----------- t/test_fileManager.pl | 40 -- t/test_formats.pl | 33 -- t/test_library.t | 72 --- 31 files changed, 3370 deletions(-) delete mode 100644 clients/README delete mode 100755 clients/hello_world_apps/hello_world_soap_client.pl delete mode 100755 clients/hello_world_apps/hello_world_xmlrpc_client.pl delete mode 100755 clients/hello_world_apps/webwork_soap_client.pl delete mode 100755 clients/hello_world_apps/webwork_xmlrpc_client.pl delete mode 100755 clients/pr delete mode 100755 clients/sendxmlrpc_bbedit.pl delete mode 100644 clients/t/TestWW.html delete mode 100644 clients/t/bad_input.pg delete mode 100644 clients/t/input.pg delete mode 100644 clients/t/labels.pg delete mode 100644 clients/t/matrixtest4.pg delete mode 100644 clients/t/show-psvn.pg delete mode 100644 clients/t/test-utf8-hebrew.pg delete mode 100644 clients/t/test1.pg delete mode 100644 clients/t/testMultAnswer.pg delete mode 100644 clients/t/test_embedded_problems.html delete mode 100644 clients/t/test_formats_WWproblems.html delete mode 100644 clients/t/test_simpleFormat_WWproblem.html delete mode 100644 clients/t/test_toggled_embedded_WWproblems.html delete mode 100644 clients/t/test_two_embedded_images_localhost.html delete mode 100644 clients/t/test_two_images_localhost_base64.html delete mode 100755 clients/uribase64_encode.pl delete mode 100644 clients/ww_credentials.dist delete mode 100644 t/TestWW.html.dist delete mode 100644 t/alternate_templates.html.dist delete mode 100755 t/grab_course_environment.pl delete mode 100755 t/testAttemptsTable.pl delete mode 100644 t/test_fileManager.pl delete mode 100644 t/test_formats.pl delete mode 100644 t/test_library.t diff --git a/clients/README b/clients/README deleted file mode 100644 index 9c490b7bdc..0000000000 --- a/clients/README +++ /dev/null @@ -1,73 +0,0 @@ -2010.05.11 - -At this point renderProblem.pl is the most up to date and works with BBedit to -to send a local file to an xmlserver (mod_xmlrpc) to be rendered. In addition the returned' -file's question form action url is pointed to the same server with the path ending in xml2html. -This allows one to enter answers and test whether they work. - -There were changes to webwork2/lib/WebworkWebservice.pm to make it work with Apache2. -There were also changes to webwork2/lib/WeBWorK/URLpath.pm and a new -module webwork2/lib/WeBWorK/ContentGenerator/xmlViaHTTP.pm - -The webwork_xmplrp_client and webwork_soap_client.pl have not been updated, but may still work. - -to do: - •add facilities for inspecting libraries via xmlrpc and html2xml links - •figure out how to automate the configuration of these xmlrpc files - Apache2::ServerUtil should do this?? but I can't figure out how. - •I suspect that auxiliary html files and applets don't work yet. - - I'm pretty sure that there is no security checking to insure that only appropriate - people have access to the xmlrpc webservice. -############################################################################################## - - -These test clients will process these two commands: - -./webwork_xmlrpc_client.pl renderProblem input.txt >foo.txt -./webwork_xmlrpc_client.pl listLibraries -or - -./webwork_soap_client.pl renderProblem input.txt >foo.txt -./webwork_soap_client.pl listLibraries - - -You may need to adjust some hardwired parameters in the scripts so that -you are pointed at the correct servers. :-) - -The scripts hello_world_xmlrpc.pl and hello_world_soap.pl take no arguments -and can be used to test the connection with the chosen servers. - -The scripts renderProblem.pl and renderProblem_rawoutput.pl are versions of the -xmlrpc_xmlrp_client which can be used as filters. The were designed to be used with -bbedit (Mac editor) to send a PG problem file of to a webservice to be rendered. - -The renderProblem_rawoutput version decodes the xml response and prints it as perl structures -through "less". - -The renderProblem.pl pipes the HTML part of the response through safari (other browsers could -be used) for viewing. This is usually what is wanted for testing. Currently the error recovery -is minimal, so error messages sent from the server may totally confuse the client (which -will probably report a bad result type). The resulting web page is live and pointed -to a responder at webhost.math.rochester.edu. When that server is working you can -actually submit an answer and have it evaluated. It's a very old, tired PC running -Frontier as a server, so be patient with it. :-) - - -checkProblem.pl will take a problem source, send it to the webserver for checking -and record the result in a log file. It is very similar to renderProblem.pl. - -check_problems_in_dir.sh will apply checkProblem.pl to all .pg problems found -underneath the current directory in which the command is executed. I've used -it to check all the problems in a directory for warning errors. There are more -subtle checks that could be made, such as checking to see that correct -answers work. - -Typically one downloads a problem library from the SVN -and then uses check_problems_in_dir.sh to walk through it. By modifying -checkProblems and webwork_xmlrpc_inc.pl one could have the HTML version -of each problem dumped to a text file, or by changing the DISPLAYMODE to -"tex" instead of image one could dump the TeX version of each file. - - --- Mike Gage 1/1/2007 diff --git a/clients/hello_world_apps/hello_world_soap_client.pl b/clients/hello_world_apps/hello_world_soap_client.pl deleted file mode 100755 index 400c914e55..0000000000 --- a/clients/hello_world_apps/hello_world_soap_client.pl +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/perl -w - -use SOAP::Lite; -my $soap = SOAP::Lite - #-> uri('http://math.webwork.rochester.edu/WebworkXMLRPC') - #-> proxy('https://math.webwork.rochester.edu/mod_soap/WebworkWebservice'); - ->uri('http://localhost/WebworkXMLRPC')->proxy('http://localhost/mod_soap/WebworkWebservice'); - -#-> uri('https://devel.webwork.rochester.edu:8002/WebworkXMLRPC') -#-> proxy('https://devel.webwork.rochester.edu:8002/mod_soap/WebworkWebservice'); - -my $result = $soap->hi(); - -unless ($result->fault) { - print $result->result(); -} else { - print join ', ', $result->faultcode, $result->faultstring; -} - diff --git a/clients/hello_world_apps/hello_world_xmlrpc_client.pl b/clients/hello_world_apps/hello_world_xmlrpc_client.pl deleted file mode 100755 index a32a9da024..0000000000 --- a/clients/hello_world_apps/hello_world_xmlrpc_client.pl +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/perl -w - -# -use XMLRPC::Lite; -my $soap = XMLRPC::Lite - # -> proxy('https://math.webwork.rochester.edu/mod_xmlrpc/'); - #-> proxy('https://devel.webwork.rochester.edu:8002/mod_xmlrpc/'); - ->proxy('http://localhost/mod_xmlrpc/'); - -my $result = $soap->call("WebworkXMLRPC.hi"); - -unless ($result->fault) { - print $result->result(), "\n"; -} else { - print join ', ', $result->faultcode, $result->faultstring; -} diff --git a/clients/hello_world_apps/webwork_soap_client.pl b/clients/hello_world_apps/webwork_soap_client.pl deleted file mode 100755 index cc577d1e14..0000000000 --- a/clients/hello_world_apps/webwork_soap_client.pl +++ /dev/null @@ -1,260 +0,0 @@ -#!/usr/bin/perl -w - -use SOAP::Lite; - -# configuration section -use constant HOSTURL => 'localhost'; -use constant HOSTPORT => 80; -use constant TRANSPORT_METHOD => 'SOAP::Lite'; -use constant REQUEST_CLASS => 'WebworkXMLRPC'; # WebworkXMLRPC is used for soap also!! -use constant REQUEST_URI => 'mod_soap'; - -my @COMMANDS = qw( listLibraries renderProblem ); #listLib readFile tex2pdf - -# $pg{displayModes} = [ -# "plainText", # display raw TeX for math expressions -# "images", # display math expressions as images generated by dvipng -# "jsMath", # render TeX math expressions on the client side using jsMath -# ]; -use constant DISPLAYMODE => 'images'; - -# end configuration section -use MIME::Base64 qw( encode_base64 decode_base64); - -print STDERR "inputs are ", join(" | ", @ARGV), "\n"; -our $source; - -if (@ARGV) { - my $command = $ARGV[0]; - - warn "executing WebworkXMLRPC.$command"; - $source = (defined $ARGV[1]) ? `cat $ARGV[1]` : ''; - xmlrpcCall($command); - -} else { - - print STDERR "Useage: ./webwork_soap_client.pl command inputs\n"; - print STDERR "For example: ./webwork_soap_client renderProblem input.txt\n"; - print STDERR "For example: ./webwork_soap_client listLibraries \n"; - print STDERR "Commands are: ", join(" ", @COMMANDS), "\n"; - -} - -sub xmlrpcCall { - my $command = shift; - $command = 'listLibraries' unless $command; - - my $requestResult = TRANSPORT_METHOD->uri('http://' . HOSTURL . ':' . HOSTPORT . '/' . REQUEST_CLASS) - ->proxy('http://' . HOSTURL . ':' . HOSTPORT . '/' . REQUEST_URI); - - my $test = [ 3, 4, 5, 6 ]; - my $input = setInputTable(); - print "displayMode=", $input->{envir}->{displayMode}, "\n"; - local ($result); - # use eval to catch errors - eval { $result = $requestResult->call("$command", $input) }; - print STDERR "There were a lot of errors\n" if $@; - print "Errors: \n $@\n End Errors\n" if $@; - - print "result is|", ref($result), "|"; - - unless (ref($result) and $result->fault) { - - if (ref($result->result()) =~ /HASH/ and defined($result->result()->{text})) { - $result->result()->{text} = decode_base64($result->result()->{text}); - } - print pretty_print_rh($result->result()), "\n"; #$result->result() - } else { - print 'oops ', join ', ', $result->faultcode, $result->faultstring; - } -} - -sub source { - encode_base64($source); -} - -sub pretty_print_rh { - shift if UNIVERSAL::isa($_[0] => __PACKAGE__); - my $rh = shift; - my $indent = shift || 0; - my $out = ""; - my $type = ref($rh); - - if (defined($type) and $type) { - $out .= " type = $type; "; - } elsif (!defined($rh)) { - $out .= " type = UNDEFINED; "; - } - return $out . " " unless defined($rh); - - if (ref($rh) =~ /HASH/ or "$rh" =~ /HASH/) { - $out .= "{\n"; - $indent++; - foreach my $key (sort keys %{$rh}) { - $out .= " " x $indent . "$key => " . pretty_print_rh($rh->{$key}, $indent) . "\n"; - } - $indent--; - $out .= "\n" . " " x $indent . "}\n"; - - } elsif (ref($rh) =~ /ARRAY/ or "$rh" =~ /ARRAY/) { - $out .= " ( "; - foreach my $elem (@{$rh}) { - $out .= pretty_print_rh($elem, $indent); - - } - $out .= " ) \n"; - } elsif (ref($rh) =~ /SCALAR/) { - $out .= "scalar reference " . ${$rh}; - } elsif (ref($rh) =~ /Base64/) { - $out .= "base64 reference " . $$rh; - } else { - $out .= $rh; - } - - return $out . " "; -} - -sub setInputTable_for_listLib { - $out = { - #password => 'geometry', - pw => 'geometry', - set => 'set0', - library_name => 'rochesterLibrary', - command => 'all', - }; - - $out; -} - -sub setInputTable { - $out = { - #password => 'geometry', - pw => 'geometry', - set => 'set0', - library_name => 'rochesterLibrary', - command => 'all', - answer_form_submitted => 1, - course => 'daemon_course', - extra_packages_to_load => [ qw( AlgParserWithImplicitExpand Expr - ExprWithImplicitExpand AnswerEvaluator - AnswerEvaluatorMaker - ) ], - mode => 'HTML_dpng', - modules_to_evaluate => [ qw( - Exporter - - DynaLoader - - GD - WWPlot - Fun - Circle - Label - - PGrandom - Units - Hermite - - List - - Match - Multiple - Select - - AlgParser - - AnswerHash - - Fraction - VectorField - - Complex1 - Complex - - MatrixReal1 Matrix - - Distributions - - Regression - - ) ], - envir => environment(), - problem_state => { - - num_of_correct_ans => 2, - num_of_incorrect_ans => 4, - recorded_score => 1.0, - }, - source => source(), #base64 encoded - - }; - - $out; -} - -sub environment { - my $envir = { - answerDate => '4014438528', - CAPA_Graphics_URL => 'http://webwork-db.math.rochester.edu/capa_graphics/', - CAPA_GraphicsDirectory => '/ww/webwork/CAPA/CAPA_Graphics/', - CAPA_MCTools => '/ww/webwork/CAPA/CAPA_MCTools/', - CAPA_Tools => '/ww/webwork/CAPA/CAPA_Tools/', - cgiDirectory => 'Not defined', - cgiURL => 'Not defined', - classDirectory => 'Not defined', - courseName => 'Not defined', - courseScriptsDirectory => '/ww/webwork/system/courseScripts/', - displayMode => DISPLAYMODE, - dueDate => '4014438528', - externalGif2EpsPath => 'not defined', - externalPng2EpsPath => 'not defined', - fileName => 'set0/prob1a.pg', - formattedAnswerDate => '6/19/00', - formattedDueDate => '6/19/00', - formattedOpenDate => '6/19/00', - functAbsTolDefault => 0.0000001, - functLLimitDefault => 0, - functMaxConstantOfIntegration => 1000000000000.0, - functNumOfPoints => 5, - functRelPercentTolDefault => 0.000001, - functULimitDefault => 1, - functVarDefault => 'x', - functZeroLevelDefault => 0.000001, - functZeroLevelTolDefault => 0.000001, - htmlDirectory => '/ww/webwork/courses/gage_course/html/', - htmlURL => 'http://webwork-db.math.rochester.edu/gage_course/', - inputs_ref => { - AnSwEr1 => '', - AnSwEr2 => '', - AnSwEr3 => '', - }, - macroDirectory => '/ww/webwork/courses/gage_course/templates/macros/', - numAbsTolDefault => 0.0000001, - numFormatDefault => '%0.13g', - numOfAttempts => 0, - numRelPercentTolDefault => 0.0001, - numZeroLevelDefault => 0.000001, - numZeroLevelTolDefault => 0.000001, - openDate => '3014438528', - PRINT_FILE_NAMES_FOR => ['gage'], - probFileName => 'set0/prob1a.pg', - problemSeed => 1234, - problemValue => 1, - probNum => 13, - psvn => 54321, - psvn => 54321, - questionNumber => 1, - scriptDirectory => 'Not defined', - sectionName => 'Gage', - sectionNumber => 1, - sessionKey => 'Not defined', - setNumber => 'MAAtutorial', - studentLogin => 'gage', - studentName => 'Mike Gage', - tempDirectory => '/ww/htdocs/tmp/gage_course/', - templateDirectory => '/ww/webwork/courses/gage_course/templates/', - tempURL => 'http://webwork-db.math.rochester.edu/tmp/gage_course/', - webworkDocsURL => 'http://webwork.math.rochester.edu/webwork_gage_system_html', - }; - $envir; -} diff --git a/clients/hello_world_apps/webwork_xmlrpc_client.pl b/clients/hello_world_apps/webwork_xmlrpc_client.pl deleted file mode 100755 index c91abd345c..0000000000 --- a/clients/hello_world_apps/webwork_xmlrpc_client.pl +++ /dev/null @@ -1,472 +0,0 @@ -#!/usr/bin/perl -w - -=pod - -This script will take a command and an input -file. - -It will list available libraries, list the contents of libraries -or render the input file. - -All of this is done by contacting the webservice. - - - -=cut - -use feature ":5.10"; -use lib "/opt/webwork/webwork2/lib"; -use WebworkClient; -use XMLRPC::Lite; -use MIME::Base64 qw( encode_base64 decode_base64); - -# configuration section -use constant PROTOCOL => 'http'; # or 'http'; -use constant HOSTURL => 'localhost'; -use constant HOSTPORT => '80'; # or 80 -use constant TRANSPORT_METHOD => 'XMLRPC::Lite'; -use constant REQUEST_CLASS => 'WebworkXMLRPC'; # WebworkXMLRPC is used for soap also!! -use constant REQUEST_URI => 'mod_xmlrpc'; -use constant TEMPOUTPUTFILE => '/Users/gage/Desktop/renderProblemOutput.html'; - -our $SITE_URL = 'http://localhost:80'; -our $FORM_ACTION_URL = 'http://localhost:80/webwork2/html2xml'; -our $XML_PASSWORD = 'xmlwebwork'; -our $XML_COURSE = 'gage_course'; - -our $UNIT_TESTS_ON = 0; - -#################################################### -# get credentials -#################################################### - -my $credential_path; -my @path_list = ('.ww_credentials', '/Users/gage/.ww_credentials', '/Users/gage/ww_session_credentials'); -foreach my $path (@path_list) { - if (-r "$path") { - $credential_path = $path; - last; - } -} -unless ($credential_path) { - die < "my login name for the webwork course", - course_password => "my course_password ", - courseID => "the name of the webwork course", -); -1; ---------------------------------------------------------- -EOF -} - -eval { require $credential_path }; -if ($@ or not defined %credentials) { - - print STDERR < "my login name for the webwork course", - course_password => "my course_password ", - courseID => "the name of the webwork course", -); -1; ---------------------------------------------------------- -EOF - die; -} - -#print "credentials: ", join(" | ", %credentials), "\n"; - -my @COMMANDS = qw( listLibraries renderProblem listLib readFile tex2pdf ); - -use constant DISPLAYMODE => 'images'; - -# end configuration section - -our $courseID = $credentials{courseID}; - -print STDERR "inputs are ", join(" | ", @ARGV), "\n"; -our $source; - -############################################ -# Build client -############################################ -our $xmlrpc_client = new WebworkClient( - site_url => $SITE_URL, - form_action_url => $FORM_ACTION_URL, - displayMode => DISPLAYMODE(), - - site_password => $credentials{site_password}, - courseID => $credentials{courseID}, - userID => $credentials{userID}, - session_key => $credentials{session_key}, -); - -# prepare additional input values - -if (@ARGV) { - my $command = $ARGV[0]; - my $result; - print "executing WebworkXMLRPC.$command \n\n-----------------------\n\n"; - given ($command) { - when ('renderProblem') { - if (defined $ARGV[1]) { - if (-r $ARGV[1]) { - $source = `cat $ARGV[1]`; - $xmlrpc_client->encodeSource($source); - my $input = { - userID => $credentials{userID} || '', - session_key => $credentials{session_key} || '', - courseID => $credentials{courseID} || '', - courseName => $credentials{courseID} || '', - course_password => $credentials{course_password} || '', - site_password => $credentials{site_password} || '', - }; - #print STDERR "input is ", %$input,"\n"; - $result = $xmlrpc_client->xmlrpcCall($command, $input); - print "\n\n Result of renderProblem \n\n"; - print pretty_print_rh($result); - } else { - print STDERR "Can't read source file $ARGV[1]\n"; - } - } else { - print STDERR "Useage: ./webwork_xmlrpc_client.pl command \n"; - } - } - when ('listLibraries') { - my $input = { - userID => $credentials{userID} || '', - session_key => $credentials{session_key} || '', - courseID => $credentials{courseID} || '', - course_password => $credentials{course_password} || '', - site_password => $credentials{site_password} || '', - }; - # print STDERR "ww_xmlrpc_client: input for listLibraries command is ", %$input,"\n"; - eval { $result = $xmlrpc_client->xmlrpcCall($command, $input); }; - if (defined($result)) { - my @lib_array = @{ $result->{ra_out} }; - print STDOUT "ww_xmlrpc_client: The libraries available in course $courseID are:\n\t ", - join("\n\t ", @lib_array), "\n"; - } else { - print STDOUT "ww_xmlrpc_client: No libraries available for course $courseID\n"; - } - } - when ('listLib') { - $result = listLib(@ARGV); - my $command = $ARGV[1]; - print "listLib returned\n"; - print pretty_print_rh($result); - print "\n"; - - } - when ('listSets') { - $input = { - site_password => 'xmluser', - course_password => $credentials{course_password}, - userID => $credentials{userID}, - courseID => $credentials{courseID}, - }; - my $result = $xmlrpc_client->xmlrpcCall($command, $input); - print pretty_print_rh($result); - } - when ('readFile') { - print STDERR "Command $command not yet implemented\n" - } - when ('tex2pdf') { - print STDERR "Command $command not yet implemented\n" - } - default { - print STDERR "Command '$command' not recognized. Commands ", @COMMANDS; - } - } - -} else { - - print STDERR "Useage: ./webwork_xmlrpc_client.pl command [file_name]\n"; - print STDERR - "For example: ./webwork_xmlrpc_client.pl renderProblem \n"; - print STDERR "Commands are: ", join(" ", @COMMANDS), "\n"; - -} - -sub source { - return "" unless $source; - return encode_base64($source); -} - -sub listLib { - my @ARGS = @_; - #print "args for listLib are ", join(" ", @ARGS), "\n"; - my $result; - given ($ARGS[1]) { - when ("all") { - $input = { - site_password => 'xmluser', - course_password => $credentials{course_password}, - userID => $credentials{userID}, - courseID => $credentials{courseID}, - command => 'all', - }; - $result = $xmlrpc_client->xmlrpcCall("listLib", $input); - } - when ('dirOnly') { - my %options = @ARGS[ 2 .. $#ARGS ]; - my $path = $options{-path} || ''; - my $maxdepth = defined($options{-depth}) ? $options{-depth} : 10000; - $input = { - site_password => 'xmluser', - course_password => $credentials{course_password}, - userID => $credentials{userID}, - courseID => $credentials{courseID}, - command => 'dirOnly', - dirPath => $path, - maxdepth => $maxdepth, - }; - $result = $xmlrpc_client->xmlrpcCall("listLib", $input); - } - when ('files') { - if ($ARGS[2]) { - my %options = @ARGS[ 2 .. $#ARGS ]; - my $path = $options{-path} || ''; - $input = { - site_password => 'xmluser', - course_password => $credentials{course_password}, - userID => $credentials{userID}, - courseID => $credentials{courseID}, - command => 'files', - dirPath => $path, - }; - $result = $xmlrpc_client->xmlrpcCall("listLib", $input); - } else { - print STDERR "Usage: webwork_xmlrpc_client listLib files \n"; - $result = ""; - } - } - default { - print "The possible arguments for listLib are:" - . "\n\t all -- print all paths" - . "\n\t dirOnly [options]-- print only directories below Library/path" - . "\n\t\t options: -depth depth -path directoryPath" - . "\n\t\t\t depth counts the number of slashes in the relative path" - . "\n\t files -- print .pg files in the given directory \n" - . "\n\t\t options: -path directoryPath"; - $result = ""; - } - } - return $result; -} - -sub pretty_print_rh { - shift if UNIVERSAL::isa($_[0] => __PACKAGE__); - my $rh = shift; - my $indent = shift || 0; - my $out = ""; - my $type = ref($rh); - - if (defined($type) and $type) { - $out .= " type = $type; "; - } elsif (!defined($rh)) { - $out .= " type = UNDEFINED; "; - } - return $out . " " unless defined($rh); - - if (ref($rh) =~ /HASH/ or "$rh" =~ /HASH/) { - $out .= "{\n"; - $indent++; - foreach my $key (sort keys %{$rh}) { - $out .= " " x $indent . "$key => " . pretty_print_rh($rh->{$key}, $indent) . "\n"; - } - $indent--; - $out .= "\n" . " " x $indent . "}\n"; - - } elsif (ref($rh) =~ /ARRAY/ or "$rh" =~ /ARRAY/) { - $out .= " ( "; - foreach my $elem (@{$rh}) { - $out .= pretty_print_rh($elem, $indent); - - } - $out .= " ) \n"; - } elsif (ref($rh) =~ /SCALAR/) { - $out .= "scalar reference " . ${$rh}; - } elsif (ref($rh) =~ /Base64/) { - $out .= "base64 reference " . $$rh; - } else { - $out .= $rh; - } - - return $out . " "; -} - -sub pretty_print_json { - shift if UNIVERSAL::isa($_[0] => __PACKAGE__); - my $rh = shift; - my $indent = shift || 0; - my $out = ""; - my $type = ref($rh); - - if (defined($type) and $type) { - $out .= " type = $type; "; - } elsif (!defined($rh)) { - $out .= " type = UNDEFINED; "; - } - return $out . " " unless defined($rh); - - if (ref($rh) =~ /HASH/ or "$rh" =~ /HASH/) { - $out .= "{\n"; - $indent++; - foreach my $key (sort keys %{$rh}) { - $out .= " " x $indent . "$key => " . pretty_print_json($rh->{$key}, $indent) . "\n"; - } - $indent--; - $out .= "\n" . " " x $indent . "}\n"; - - } elsif (ref($rh) =~ /ARRAY/ or "$rh" =~ /ARRAY/) { - $out .= " ( "; - foreach my $elem (@{$rh}) { - $out .= pretty_print_json($elem, $indent); - - } - $out .= " ) \n"; - } elsif (ref($rh) =~ /SCALAR/) { - $out .= "scalar reference " . ${$rh}; - } elsif (ref($rh) =~ /Base64/) { - $out .= "base64 reference " . $$rh; - } else { - my $jsonString = $rh; - $jsonString =~ s/(\\|\/)/\./g; - $out .= "Library." . $jsonString . ";"; - } - - return $out . " "; -} - -sub standard_input { - $out = { - site_password => 'xmluser', - course_password => $credentials{course_password}, - userID => $credentials{userID}, - set => 'set0', - library_name => 'Library', - command => 'all', - answer_form_submitted => 1, - courseID => $credentials{courseID}, - , - extra_packages_to_load => [ qw( AlgParserWithImplicitExpand Expr - ExprWithImplicitExpand AnswerEvaluator - AnswerEvaluatorMaker - ) ], - mode => DISPLAYMODE(), - modules_to_evaluate => [ qw( - Exporter - DynaLoader - GD - WWPlot - Fun - Circle - Label - PGrandom - Units - Hermite - List - Match - Multiple - Select - AlgParser - AnswerHash - Fraction - VectorField - Complex1 - Complex - MatrixReal1 Matrix - Distributions - Regression - - ) ], - envir => environment(), - problem_state => { - - num_of_correct_ans => 2, - num_of_incorrect_ans => 4, - recorded_score => 1.0, - }, - source => source(), #base64 encoded - - }; - - $out; -} - -sub environment { - my $envir = { - answerDate => '4014438528', - CAPA_Graphics_URL => 'http://webwork-db.math.rochester.edu/capa_graphics/', - CAPA_GraphicsDirectory => '/ww/webwork/CAPA/CAPA_Graphics/', - CAPA_MCTools => '/ww/webwork/CAPA/CAPA_MCTools/', - CAPA_Tools => '/ww/webwork/CAPA/CAPA_Tools/', - cgiDirectory => 'Not defined', - cgiURL => 'Not defined', - classDirectory => 'Not defined', - courseName => 'Not defined', - courseScriptsDirectory => '/ww/webwork/system/courseScripts/', - displayMode => DISPLAYMODE, - dueDate => '4014438528', - externalGif2EpsPath => 'not defined', - externalPng2EpsPath => 'not defined', - fileName => 'set0/prob1a.pg', - formattedAnswerDate => '6/19/00', - formattedDueDate => '6/19/00', - formattedOpenDate => '6/19/00', - functAbsTolDefault => 0.0000001, - functLLimitDefault => 0, - functMaxConstantOfIntegration => 1000000000000.0, - functNumOfPoints => 5, - functRelPercentTolDefault => 0.000001, - functULimitDefault => 1, - functVarDefault => 'x', - functZeroLevelDefault => 0.000001, - functZeroLevelTolDefault => 0.000001, - htmlDirectory => '/ww/webwork/courses/gage_course/html/', - htmlURL => 'http://webwork-db.math.rochester.edu/gage_course/', - inputs_ref => { - AnSwEr1 => '', - AnSwEr2 => '', - AnSwEr3 => '', - }, - macroDirectory => '/ww/webwork/courses/gage_course/templates/macros/', - numAbsTolDefault => 0.0000001, - numFormatDefault => '%0.13g', - numOfAttempts => 0, - numRelPercentTolDefault => 0.0001, - numZeroLevelDefault => 0.000001, - numZeroLevelTolDefault => 0.000001, - openDate => '3014438528', - PRINT_FILE_NAMES_FOR => ['gage'], - probFileName => 'set0/prob1a.pg', - problemSeed => 1234, - problemValue => 1, - probNum => 13, - psvn => 54321, - psvn => 54321, - questionNumber => 1, - scriptDirectory => 'Not defined', - sectionName => 'Gage', - sectionNumber => 1, - sessionKey => 'Not defined', - setNumber => 'MAAtutorial', - studentLogin => 'gage', - studentName => 'Mike Gage', - tempDirectory => '/ww/htdocs/tmp/gage_course/', - templateDirectory => '/ww/webwork/courses/gage_course/templates/', - tempURL => 'http://webwork-db.math.rochester.edu/tmp/gage_course/', - webworkDocsURL => 'http://webwork.math.rochester.edu/webwork_gage_system_html', - }; - $envir; -} diff --git a/clients/pr b/clients/pr deleted file mode 100755 index 20036afe17..0000000000 --- a/clients/pr +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -# inside the docker container -# this can be called from vim with :w ! ./pr - -# it sends the contents of the buffer to /var/www/html/xmlrpc_out.html aka localhost:8080/xmlrpc_output.html - -./sendXMLRPC.pl -h - >/var/www/html/xmlrpc_out.html - -# process STDIN with sendXMLRPC.p and send it to /var/www/html/xmlrpc_out.html -# where it can be read at localhost:8080/xmlrpc_out.html - - -# Not sure how to get rid of the ./ - -# This can also be called from the command line with cat t/input.pg |./pr diff --git a/clients/sendxmlrpc_bbedit.pl b/clients/sendxmlrpc_bbedit.pl deleted file mode 100755 index 75e29b2617..0000000000 --- a/clients/sendxmlrpc_bbedit.pl +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/perl -w -die "BB_DOC_PATH is not present. You must first save the document\n" unless defined $ENV{BB_DOC_PATH}; -$command = - "/Volumes/WW_test/opt/local/bin/perl /Volumes/WW_test/opt/webwork/webwork2/clients/sendXMLRPC.pl -bB $ENV{BB_DOC_PATH}"; -system($command); diff --git a/clients/t/TestWW.html b/clients/t/TestWW.html deleted file mode 100644 index 393a04a816..0000000000 --- a/clients/t/TestWW.html +++ /dev/null @@ -1,128 +0,0 @@ - - - - - Embed WW in HTML page - - - - - - - - - -

Example of embedding WeBWorK problems in HTML pages.

-

Problem 1

-

-This problem will help you to understand averages. -

-
- Click here to show problem1 -
- - -

Problem 2

-

-This problem gives you practice finding tangents to curves in the plane. -

- -
- Click here to show problem 2 -
- - -

Problem 3

-

-This is for debugging and shows all the details of the hash returned by PG. -

- -
- Click here to show problem 3 -
- - -

Problem 4

-

-This contains embedded PG code in base64 format. -

-
- Click here to show problem 4 -
- - - \ No newline at end of file diff --git a/clients/t/test_formats_WWproblems.html b/clients/t/test_formats_WWproblems.html deleted file mode 100644 index 1f37c23dbf..0000000000 --- a/clients/t/test_formats_WWproblems.html +++ /dev/null @@ -1,106 +0,0 @@ - - - - - test formats for embedded problems - - - - -

Format: sticky

-

-

Format: standard (has error section -- but there should be no errors)

-

- -

Format: simple

-

- -

Format: body_text

-

- -

Format: PTX

-

- -

Format: JSON

-

- - - diff --git a/clients/t/test_simpleFormat_WWproblem.html b/clients/t/test_simpleFormat_WWproblem.html deleted file mode 100644 index 079cd45992..0000000000 --- a/clients/t/test_simpleFormat_WWproblem.html +++ /dev/null @@ -1,64 +0,0 @@ - - - - - Embed WW in HTML page - - - - - - - - - - -

Problem 1-- xmlrpc version of a simple template

-

-Problem is rendered at daemon_course -- no student information is retained. -

-
- - -
-

Problem 2 -- webwork2 version of a simple template

-

-Direct access using RESTful url. Sign in is necessary and score is recorded. -

-
- -
- - diff --git a/clients/t/test_toggled_embedded_WWproblems.html b/clients/t/test_toggled_embedded_WWproblems.html deleted file mode 100644 index 2587e2726f..0000000000 --- a/clients/t/test_toggled_embedded_WWproblems.html +++ /dev/null @@ -1,202 +0,0 @@ - - - - - Embedded WeBWorK Problems - - - - - - - - - - - - -

Embedded WeBWorK Problems

-

-Problem 1 -- interval notation -

- -
- Click here to toggle problem display -
- -

-Problem 2 -- integration. Contains a Geogebra applet -

- -
- Click here to toggle problem display -
- - -

-Problem 3 -- the pg code for this problem is embedded in the html text using base64 encoding -

- -
- Click here to toggle problem display -
- - -

-Problem 4 -- PG lab. Enter PG code to test out here. -

- -
- Click here to toggle problem display -
- - - - -

-Problem 5 -- debug -- This problem is useful for debugging and shows all the details of the hash returned by PG. -

- -
- Click here to toggle problem display -
- - -

-Problem 6 -- A logic problem contributed from Montana State University. There -is a link "contribLibrary" in the daemon course to the "Contrib" library. See -https://github.com/openwebwork/webwork-open-problem-library -to see which problems are available in the OpenProblemLibrary and in Contrib. You can -also use the library browser to find the problems available in the OPL. - -

- -
- Click here to toggle problem display -
- -
-
- Click here to toggle problem display: (PGinfo example) -
-