[system] / trunk / webwork2 / bin / addcourse Repository:
ViewVC logotype

Annotation of /trunk/webwork2/bin/addcourse

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1806 - (view) (download)

1 : sh002i 1653 #!/usr/bin/env perl
2 :     ################################################################################
3 : sh002i 1663 # WeBWorK Online Homework Delivery System
4 :     # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
5 : sh002i 1806 # $CVSHeader: webwork-modperl/bin/addcourse,v 1.7 2004/02/14 00:56:00 sh002i Exp $
6 : sh002i 1663 #
7 :     # This program is free software; you can redistribute it and/or modify it under
8 :     # the terms of either: (a) the GNU General Public License as published by the
9 :     # Free Software Foundation; either version 2, or (at your option) any later
10 :     # version, or (b) the "Artistic License" which comes with this package.
11 :     #
12 :     # This program is distributed in the hope that it will be useful, but WITHOUT
13 :     # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 :     # FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the
15 :     # Artistic License for more details.
16 : sh002i 1653 ################################################################################
17 :    
18 :     =head1 NAME
19 :    
20 :     addcourse - add a course
21 :    
22 :     =head1 SYNOPSIS
23 :    
24 : sh002i 1696 addcourse [options] COURSEID
25 : sh002i 1653
26 :     =head1 DESCRIPTION
27 :    
28 :     Add a course to the courses directory. The required directories will be
29 :     created. Optionally, a database can be populated with users and the
30 :     F<templates> directory can be populated with the contents of another directory.
31 :     Also, one or more users can be granted professor privileges.
32 :    
33 :     =head1 OPTIONS
34 :    
35 :     =over
36 :    
37 : sh002i 1696 =item B<--templates>=I<DIR>
38 :    
39 :     The contents of the directory I<DIR> will be copied to the F<templates>
40 :     directory of the new course.
41 :    
42 :     =item B<--db-layout>=I<LAYOUT>
43 :    
44 :     The specified database layout will be used in place of the default specified in
45 : sh002i 1698 F<global.conf>. Please note that if you specify a layout other than the default
46 :     given in F<global.conf>, you will need to manually create a F<course.conf> file
47 :     in the new course's directory containing the following line:
48 : sh002i 1696
49 : sh002i 1698 *dbLayout = $dbLayouts{layoutName};
50 :    
51 :     This is described in greater detail in the F<global.conf> and F<database.conf>
52 :     files.
53 :    
54 : sh002i 1805 =item B<--global-user>=I<USERID>
55 :    
56 :     Specifies that the user ID of the global user will be I<USERID>, overriding the
57 :     value set in F<database.conf>.
58 :    
59 : sh002i 1653 =item B<--users>=I<FILE>
60 :    
61 :     The users listed in the comma-separated text file I<FILE> will be added to the
62 : sh002i 1696 user list of the new course. The format of this file is the same as user lists
63 :     exported from WeBWorK.
64 : sh002i 1653
65 :     =item B<--professors>=I<USERID>[,I<USERID>]...
66 :    
67 :     Each I<USERID>, if it is present in the new course's user list, will be granted
68 :     professor privileges (i.e. a permission level of 10). Requires B<--users>.
69 :    
70 :     =item I<COURSEID>
71 :    
72 :     The name of the course to create.
73 :    
74 : sh002i 1689 =back
75 :    
76 : sh002i 1653 =cut
77 :    
78 :     use strict;
79 :     use warnings;
80 :     use Getopt::Long;
81 : sh002i 1696
82 :     BEGIN {
83 :     die "WEBWORK_ROOT not found in environment.\n"
84 :     unless exists $ENV{WEBWORK_ROOT};
85 :     }
86 :    
87 :     use lib "$ENV{WEBWORK_ROOT}/lib";
88 : sh002i 1653 use WeBWorK::CourseEnvironment;
89 :     use WeBWorK::DB;
90 : sh002i 1696 use WeBWorK::Utils qw(readFile cryptPassword);
91 : sh002i 1653
92 :     sub usage {
93 : sh002i 1698 print STDERR "usage: $0 [options] COURSEID\n";
94 :     print STDERR "Options:\n";
95 :     print STDERR " [--templates=DIR]\n";
96 :     print STDERR " [--db-layout=LAYOUT]\n";
97 : sh002i 1805 print STDERR " [--global-user=USERID]\n";
98 : sh002i 1696 print STDERR " [--users=FILE [--professors=USERID[,USERID]...] ]\n";
99 : sh002i 1653 exit;
100 :     }
101 :    
102 : sh002i 1696 my $templates = "";
103 :     my $dbLayout = "";
104 : sh002i 1653 my $users = "";
105 : sh002i 1805 my $globalUserID = "";
106 : sh002i 1653 my @professors = ();
107 :    
108 :     GetOptions(
109 : sh002i 1696 "templates=s" => \$templates,
110 :     "db-layout=s" => \$dbLayout,
111 : sh002i 1653 "users=s" => \$users,
112 : sh002i 1805 "global-user=s" => \$globalUserID,
113 : sh002i 1653 "professors=s" => \@professors,
114 :     );
115 :     my %professors = map { $_ => 1 } map { split /,/ } @professors;
116 :     my $courseID = shift;
117 :    
118 :     unless ($courseID) {
119 :     print STDERR "$0: must specify COURSEID.\n";
120 :     usage();
121 :     };
122 :    
123 :     if (@professors and not $users) {
124 :     print STDERR "$0: can't specify --professors without also specifying --users.\n";
125 :     usage();
126 :     }
127 :    
128 :     # bring up a minimal course environment
129 :     my $ce = WeBWorK::CourseEnvironment->new($ENV{WEBWORK_ROOT}, "FAKE_URL_ROOT",
130 :     "FAKE_PG_ROOT", $courseID);
131 :    
132 : sh002i 1696 if ($dbLayout) {
133 :     die "Database layout $dbLayout does not exist in the course environment.",
134 :     " (It must be defined in global.conf.)\n"
135 :     unless exists $ce->{dbLayouts}->{$dbLayout};
136 :     }
137 :    
138 : sh002i 1653 # collect some data
139 :     my $coursesDir = $ce->{webworkDirs}->{courses};
140 :     my $courseDir = "$coursesDir/$courseID";
141 :    
142 : sh002i 1696 # make sure the course doesn't already exist
143 :     if (-e $courseDir) {
144 :     die "$courseID: course exists\n";
145 :     }
146 : sh002i 1653
147 : sh002i 1805 umask 0002;
148 :    
149 : sh002i 1696 # create required directories
150 : sh002i 1653 my @subDirs = sort values %{ $ce->{courseDirs} };
151 :     foreach my $subDir (@subDirs) {
152 :     print "mkdir $subDir\n";
153 :     mkdir "$subDir"
154 :     or die "Failed to create course directory $subDir: $!\n";
155 :     }
156 :    
157 : sh002i 1696 if ($templates) {
158 :     unless (-d "$courseDir/templates") {
159 :     warn "$courseDir/templates: not found, creating:\n";
160 :     print "mkdir $courseDir/templates\n";
161 :     mkdir "$courseDir/templates"
162 :     or die "Failed to mkdir $courseDir/templates: $!\n";
163 :     }
164 :     print "copy $templates/* -> $courseDir/templates\n";
165 :     system "/bin/cp -r $templates/* $courseDir/templates/"
166 :     and die "Failed to copy $templates/* to $courseDir/templates: $!\n";
167 :     }
168 :    
169 : sh002i 1653 if ($users) {
170 :     # import users - much of this code is burgled from UserList.pm
171 :    
172 : sh002i 1696 my $db;
173 :     if ($dbLayout) {
174 :     # use the specified layout
175 :     $db = WeBWorK::DB->new($ce->{dbLayouts}->{$dbLayout});
176 :     } else {
177 :     # use the default layout
178 :     $db = WeBWorK::DB->new($ce->{dbLayout});
179 :     }
180 :    
181 : sh002i 1653 my @contents = split /\n/, readFile($users);
182 :    
183 : sh002i 1805 my $globalUserPresent = 0;
184 :    
185 : sh002i 1653 foreach my $string (@contents) {
186 :     $string =~ s/^\s+//;
187 :     $string =~ s/\s+$//;
188 :     my (
189 :     $student_id, $last_name, $first_name, $status, $comment,
190 :     $section, $recitation, $email_address, $user_id
191 :     ) = split /\s*,\s*/, $string;
192 :    
193 :     my $User = $db->newUser;
194 :     $User->user_id($user_id);
195 :     $User->first_name($first_name);
196 :     $User->last_name($last_name);
197 :     $User->email_address($email_address);
198 :     $User->student_id($student_id);
199 :     $User->status($status);
200 :     $User->section($section);
201 :     $User->recitation($recitation);
202 :     $User->comment($comment);
203 :    
204 :     my $PermissionLevel = $db->newPermissionLevel;
205 :     $PermissionLevel->user_id($user_id);
206 :     if (exists $professors{$user_id}) {
207 :     $PermissionLevel->permission(10);
208 :     } else {
209 :     $PermissionLevel->permission(0);
210 :     }
211 :    
212 :     my $Password = $db->newPassword;
213 :     $Password->user_id($user_id);
214 : sh002i 1654 $Password->password(cryptPassword($student_id));
215 : sh002i 1653
216 :     $db->addUser($User);
217 :     $db->addPermissionLevel($PermissionLevel);
218 :     $db->addPassword($Password);
219 :    
220 : sh002i 1805 if ($user_id eq $globalUserID) {
221 :     $globalUserPresent = 1;
222 :     }
223 :    
224 : sh002i 1653 if (exists $professors{$user_id}) {
225 :     print "add professor $user_id\n";
226 :     delete $professors{$user_id};
227 :     } else {
228 :     print "add user $user_id\n";
229 :     }
230 :     }
231 :    
232 :     if (my @ids = keys %professors) {
233 :     print STDERR "warning: @ids not in imported user list.\n";
234 :     }
235 : sh002i 1805
236 :     unless ($globalUserPresent) {
237 :     warn "warning: global user $globalUserID not in imported user list.\n",
238 :     " please add a user with this user ID manually.\n";
239 :     }
240 : sh002i 1653 }
241 :    
242 : sh002i 1805 my $courseEnvFile = $ce->{courseFiles}->{environment};
243 :     print "writing $courseEnvFile... ";
244 :     open my $fh, ">", $courseEnvFile
245 :     or die "failed to open $courseEnvFile for writing.\n";
246 :    
247 :     print $fh <<EOF;
248 :     #!perl
249 :     ################################################################################
250 :     # WeBWorK Online Homework Delivery System
251 :     # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
252 :     #
253 :     # This program is free software; you can redistribute it and/or modify it under
254 :     # the terms of either: (a) the GNU General Public License as published by the
255 :     # Free Software Foundation; either version 2, or (at your option) any later
256 :     # version, or (b) the "Artistic License" which comes with this package.
257 :     #
258 :     # This program is distributed in the hope that it will be useful, but WITHOUT
259 :     # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
260 :     # FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the
261 :     # Artistic License for more details.
262 :     ################################################################################
263 :    
264 :     # This file is used to override the global WeBWorK course environment for
265 :     # requests to this course. All package variables set in this file are added to
266 :     # the course environment. If you wish to set a variable here but omit it from
267 :     # the course environment, use the "my" keyword. Commonly changed configuration
268 :     # options are noted below. The commented-out values are the values which were
269 :     # set in the global configuration file at the time this course was created.
270 :    
271 :     EOF
272 :    
273 :     print $fh <<EOF;
274 :     # Database layout -- if this course uses a different database layout than the
275 :     # one defined in the global configuration file, set it here.
276 :     #
277 :     # Example: \$dbLayoutName = "sql";
278 :     # \*dbLayout = \$dbLayouts{sql};
279 :     #
280 :     EOF
281 :    
282 : sh002i 1698 if ($dbLayout) {
283 : sh002i 1805 print $fh "\$dbLayoutName = '$dbLayout';\n";
284 :     print $fh "\*dbLayout = \$dbLayouts{$dbLayout};\n";
285 :     } else {
286 :     my $defaultLayoutName = $ce->{dbLayoutName};
287 :     if ($defaultLayoutName) {
288 :     print $fh "#\$dbLayoutName = '$defaultLayoutName';\n";
289 :     print $fh "#\*dbLayout = \$dbLayouts{\$dbLayoutName};\n";
290 :     } else {
291 :     print $fh "#\$dbLayoutName = '#NOT#FOUND#';\n";
292 :     print $fh "#\*dbLayout = \$dbLayouts#NOT#FOUND#;\n";
293 :     warn "default database layout name (\$dbLayoutName) not found in course environment.\n";
294 :     }
295 : sh002i 1698 }
296 :    
297 : sh002i 1805 print $fh <<EOF;
298 :    
299 :     # Global user ID - denotes the ID of the user that the GlobalTableEmulator will
300 :     # use to store data for the set and problem tables. only applicable when using
301 :     # the GDBM database layout.
302 :     #
303 :     # Example: \$dbLayouts{gdbm}->{set}->{params}->{globalUserID} = 'some_user';
304 : sh002i 1806 # \$dbLayouts{gdbm}->{problem}->{params}->{globalUserID} = 'some_user';
305 : sh002i 1805 #
306 :     EOF
307 :    
308 :     if ($globalUserID) {
309 : sh002i 1806 print $fh "\$dbLayouts{gdbm}->{set}->{params}->{globalUserID} = '$globalUserID';\n";
310 :     print $fh "\$dbLayouts{gdbm}->{problem}->{params}->{globalUserID} = '$globalUserID';\n";
311 : sh002i 1805 } else {
312 :     my $defaultGlobalUserID = $ce->{dbLayouts}->{gdbm}->{set}->{params}->{globalUserID};
313 :     if (defined $defaultGlobalUserID) {
314 :     print $fh "#\$dbLayouts{gdbm}->{set}->{params}->{globalUserID} = '$defaultGlobalUserID';\n";
315 : sh002i 1806 print $fh "#\$dbLayouts{gdbm}->{problem}->{params}->{globalUserID} = '$defaultGlobalUserID';\n";
316 : sh002i 1805 } else {
317 :     print $fh "#\$dbLayouts{gdbm}->{set}->{params}->{globalUserID} = '#NOT#FOUND#';\n";
318 : sh002i 1806 print $fh "#\$dbLayouts{gdbm}->{problem}->{params}->{globalUserID} = '#NOT#FOUND#';\n";
319 : sh002i 1805 warn "default GDBM global user ID not found in course environment.\n";
320 :     }
321 :     }
322 :    
323 :     print $fh <<EOF;
324 :    
325 :     # Allowed mail recipients - list of email addresses that the PG system is
326 :     # allowed to send mail to. (This prevents subtle PG exploits.) If this is not
327 :     # set somewhere, mail from the PG system (i.e. questionaires, essay questions)
328 :     # will fail.
329 :     #
330 :     # Example: \$mail->{allowedRecipients} = [ 'gage\@math.rochester.edu', 'apizer\@math.rochester.edu' ];
331 :     #
332 :     EOF
333 :    
334 :     if (defined $ce->{mail}->{allowedRecipients}) {
335 :     my $value = join ", ", map { "'$_'" } @{ $ce->{mail}->{allowedRecipients} };
336 :     print $fh "#\$mail->{allowedRecipients} = [ $value ];\n";
337 :     } else {
338 :     print $fh "#\$mail->{allowedRecipients} = [ ];\n";
339 :     }
340 :    
341 :     print $fh <<EOF;
342 :    
343 :     # Feedback recipients - list of email addresses to send feedback to. If not
344 :     # defined, mail is sent to all professors and TAs.
345 :     #
346 :     # Example: \$mail->{allowedRecipients} = [ 'gage\@math.rochester.edu', 'apizer\@math.rochester.edu', 'feedback-list\@lists.webwork.rochester.edu' ];
347 :     #
348 :     EOF
349 :    
350 :     if (defined $ce->{mail}->{feedbackRecipients}) {
351 :     my $value = join ", ", map { "'$_'" } @{ $ce->{mail}->{feedbackRecipients} };
352 :     print $fh "#\$mail->{feedbackRecipients} = [ $value ];\n";
353 :     } else {
354 :     print $fh "#\$mail->{allowedRecipients} = [ ];\n";
355 :     }
356 :    
357 :     print $fh <<EOF;
358 :    
359 :     # Special PG environment variable: PRINT_FILE_NAMES_FOR - List the user IDs of
360 :     # users who should get PG source file names in their rendered problems. This is
361 :     # usually set to the list of professors and TAs in the course.
362 :     #
363 :     # Example: \$pg->{specialPGEnvironmentVars}->{PRINT_FILE_NAMES_FOR} = [ 'gage', 'apizer', 'voloshin' ];
364 :     #
365 :     EOF
366 :    
367 :     if (defined $ce->{pg}->{specialPGEnvironmentVars}->{PRINT_FILE_NAMES_FOR}) {
368 :     my $value = join ", ", map { "'$_'" }
369 :     @{ $ce->{pg}->{specialPGEnvironmentVars}->{PRINT_FILE_NAMES_FOR} };
370 :     print $fh "#\$pg->{specialPGEnvironmentVars}->{PRINT_FILE_NAMES_FOR} = [ $value ];\n";
371 :     } else {
372 :     print $fh "#\$pg->{specialPGEnvironmentVars}->{PRINT_FILE_NAMES_FOR} = [ ];\n";
373 :     }
374 :    
375 :     close $fh;
376 :     print "done.\n";
377 :    
378 : sh002i 1653 =head1 BUGS
379 :    
380 : sh002i 1805 Some database drivers are unable to create storage for their data. The GDBM
381 :     backend can do this, but the SQL backend cannot (currently). If you wish to
382 :     create a course using the SQL database layout, you must create a
383 : sh002i 1653
384 :     =head1 AUTHOR
385 :    
386 :     Written by Sam Hathaway, hathaway at users.sourceforge.net.
387 :    
388 :     =cut

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9