| 1 | #!/usr/bin/env perl |
1 | #!/usr/bin/env perl |
| 2 | |
|
|
| 3 | ################################################################################ |
2 | ################################################################################ |
| 4 | # WeBWorK mod_perl (c) 1995-2002 WeBWorK Team, Univeristy of Rochester |
3 | # WeBWorK Online Homework Delivery System |
| 5 | # $Id: addcourse,v 1.1 2003-12-04 06:03:25 sh002i Exp $ |
4 | # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/ |
|
|
5 | # $CVSHeader: webwork-modperl/bin/addcourse,v 1.4 2003/12/27 21:41:56 sh002i Exp $ |
|
|
6 | # |
|
|
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. |
| 6 | ################################################################################ |
16 | ################################################################################ |
| 7 | |
17 | |
| 8 | =head1 NAME |
18 | =head1 NAME |
| 9 | |
19 | |
| 10 | addcourse - add a course |
20 | addcourse - add a course |
| 11 | |
21 | |
| 12 | =head1 SYNOPSIS |
22 | =head1 SYNOPSIS |
| 13 | |
23 | |
| 14 | addcourse [B<--users>=I<FILE> [B<--professors>=I<USERID>[,I<USERID>]...] ] |
24 | addcourse [options] COURSEID |
| 15 | [B<--templates>=I<DIR>] I<COURSEID> |
|
|
| 16 | |
25 | |
| 17 | =head1 DESCRIPTION |
26 | =head1 DESCRIPTION |
| 18 | |
27 | |
| 19 | Add a course to the courses directory. The required directories will be |
28 | Add a course to the courses directory. The required directories will be |
| 20 | created. Optionally, a database can be populated with users and the |
29 | created. Optionally, a database can be populated with users and the |
| … | |
… | |
| 23 | |
32 | |
| 24 | =head1 OPTIONS |
33 | =head1 OPTIONS |
| 25 | |
34 | |
| 26 | =over |
35 | =over |
| 27 | |
36 | |
|
|
37 | =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 | F<global.conf>. |
|
|
46 | |
| 28 | =item B<--users>=I<FILE> |
47 | =item B<--users>=I<FILE> |
| 29 | |
48 | |
| 30 | The users listed in the comma-separated text file I<FILE> will be added to the |
49 | The users listed in the comma-separated text file I<FILE> will be added to the |
| 31 | user list of the new course. |
50 | user list of the new course. The format of this file is the same as user lists |
|
|
51 | exported from WeBWorK. |
| 32 | |
52 | |
| 33 | =item B<--professors>=I<USERID>[,I<USERID>]... |
53 | =item B<--professors>=I<USERID>[,I<USERID>]... |
| 34 | |
54 | |
| 35 | Each I<USERID>, if it is present in the new course's user list, will be granted |
55 | Each I<USERID>, if it is present in the new course's user list, will be granted |
| 36 | professor privileges (i.e. a permission level of 10). Requires B<--users>. |
56 | professor privileges (i.e. a permission level of 10). Requires B<--users>. |
| 37 | |
57 | |
| 38 | =item B<--templates>=I<DIR> |
|
|
| 39 | |
|
|
| 40 | The contents of the directory I<DIR> will be copied to the F<templates> |
|
|
| 41 | directory of the new course. |
|
|
| 42 | |
|
|
| 43 | =item I<COURSEID> |
58 | =item I<COURSEID> |
| 44 | |
59 | |
| 45 | The name of the course to create. |
60 | The name of the course to create. |
|
|
61 | |
|
|
62 | =back |
| 46 | |
63 | |
| 47 | =cut |
64 | =cut |
| 48 | |
65 | |
| 49 | use strict; |
66 | use strict; |
| 50 | use warnings; |
67 | use warnings; |
| 51 | use FindBin; |
|
|
| 52 | use Getopt::Long; |
68 | use Getopt::Long; |
| 53 | use lib "$FindBin::Bin/../lib"; |
69 | |
|
|
70 | BEGIN { |
|
|
71 | die "WEBWORK_ROOT not found in environment.\n" |
|
|
72 | unless exists $ENV{WEBWORK_ROOT}; |
|
|
73 | } |
|
|
74 | |
|
|
75 | use lib "$ENV{WEBWORK_ROOT}/lib"; |
| 54 | use WeBWorK::CourseEnvironment; |
76 | use WeBWorK::CourseEnvironment; |
| 55 | use WeBWorK::DB; |
77 | use WeBWorK::DB; |
| 56 | use WeBWorK::Utils qw/readFile/; |
78 | use WeBWorK::Utils qw(readFile cryptPassword); |
| 57 | |
79 | |
| 58 | sub usage { |
80 | sub usage { |
|
|
81 | print STDERR "$0 [options] COURSEID\n"; |
|
|
82 | print STDERR " [--templates=DIR] [--db-layout=LAYOUT]\n"; |
| 59 | print STDERR "$0 [--users=FILE [--professors=USERID[,USERID]...] ]\n"; |
83 | print STDERR " [--users=FILE [--professors=USERID[,USERID]...] ]\n"; |
| 60 | print STDERR "[--templates=DIR] COURSEID\n"; |
|
|
| 61 | exit; |
84 | exit; |
| 62 | } |
85 | } |
| 63 | |
86 | |
|
|
87 | my $templates = ""; |
|
|
88 | my $dbLayout = ""; |
| 64 | my $users = ""; |
89 | my $users = ""; |
| 65 | my @professors = (); |
90 | my @professors = (); |
| 66 | my $templates = ""; |
|
|
| 67 | |
91 | |
| 68 | GetOptions( |
92 | GetOptions( |
|
|
93 | "templates=s" => \$templates, |
|
|
94 | "db-layout=s" => \$dbLayout, |
| 69 | "users=s" => \$users, |
95 | "users=s" => \$users, |
| 70 | "professors=s" => \@professors, |
96 | "professors=s" => \@professors, |
| 71 | "templates=s" => \$templates, |
|
|
| 72 | ); |
97 | ); |
| 73 | my %professors = map { $_ => 1 } map { split /,/ } @professors; |
98 | my %professors = map { $_ => 1 } map { split /,/ } @professors; |
| 74 | my $courseID = shift; |
99 | my $courseID = shift; |
| 75 | |
|
|
| 76 | #print "users=$users\n"; |
|
|
| 77 | #print "professors=@professors\n"; |
|
|
| 78 | #print "templates=$templates\n"; |
|
|
| 79 | #print "courseID=$courseID\n"; |
|
|
| 80 | |
|
|
| 81 | unless ($ENV{WEBWORK_ROOT}) { |
|
|
| 82 | die "WEBWORK_ROOT not found in environment.\n"; |
|
|
| 83 | } |
|
|
| 84 | |
100 | |
| 85 | unless ($courseID) { |
101 | unless ($courseID) { |
| 86 | print STDERR "$0: must specify COURSEID.\n"; |
102 | print STDERR "$0: must specify COURSEID.\n"; |
| 87 | usage(); |
103 | usage(); |
| 88 | }; |
104 | }; |
| … | |
… | |
| 94 | |
110 | |
| 95 | # bring up a minimal course environment |
111 | # bring up a minimal course environment |
| 96 | my $ce = WeBWorK::CourseEnvironment->new($ENV{WEBWORK_ROOT}, "FAKE_URL_ROOT", |
112 | my $ce = WeBWorK::CourseEnvironment->new($ENV{WEBWORK_ROOT}, "FAKE_URL_ROOT", |
| 97 | "FAKE_PG_ROOT", $courseID); |
113 | "FAKE_PG_ROOT", $courseID); |
| 98 | |
114 | |
|
|
115 | if ($dbLayout) { |
|
|
116 | die "Database layout $dbLayout does not exist in the course environment.", |
|
|
117 | " (It must be defined in global.conf.)\n" |
|
|
118 | unless exists $ce->{dbLayouts}->{$dbLayout}; |
|
|
119 | } |
|
|
120 | |
| 99 | # collect some data |
121 | # collect some data |
| 100 | my $coursesDir = $ce->{webworkDirs}->{courses}; |
122 | my $coursesDir = $ce->{webworkDirs}->{courses}; |
| 101 | my $courseDir = "$coursesDir/$courseID"; |
123 | my $courseDir = "$coursesDir/$courseID"; |
| 102 | |
124 | |
|
|
125 | # make sure the course doesn't already exist |
|
|
126 | if (-e $courseDir) { |
|
|
127 | die "$courseID: course exists\n"; |
|
|
128 | } |
|
|
129 | |
| 103 | # create course directory |
130 | # create required directories |
| 104 | #print "mkdir $courseDir\n"; |
|
|
| 105 | #mkdir $courseDir or die "Failed to create course directory: $!\n"; |
|
|
| 106 | |
|
|
| 107 | # populate it with some subdirectories |
|
|
| 108 | my @subDirs = sort values %{ $ce->{courseDirs} }; |
131 | my @subDirs = sort values %{ $ce->{courseDirs} }; |
| 109 | foreach my $subDir (@subDirs) { |
132 | foreach my $subDir (@subDirs) { |
| 110 | print "mkdir $subDir\n"; |
133 | print "mkdir $subDir\n"; |
| 111 | mkdir "$subDir" |
134 | mkdir "$subDir" |
| 112 | or die "Failed to create course directory $subDir: $!\n"; |
135 | or die "Failed to create course directory $subDir: $!\n"; |
| 113 | } |
136 | } |
| 114 | |
137 | |
|
|
138 | if ($templates) { |
|
|
139 | unless (-d "$courseDir/templates") { |
|
|
140 | warn "$courseDir/templates: not found, creating:\n"; |
|
|
141 | print "mkdir $courseDir/templates\n"; |
|
|
142 | mkdir "$courseDir/templates" |
|
|
143 | or die "Failed to mkdir $courseDir/templates: $!\n"; |
|
|
144 | } |
|
|
145 | print "copy $templates/* -> $courseDir/templates\n"; |
|
|
146 | system "/bin/cp -r $templates/* $courseDir/templates/" |
|
|
147 | and die "Failed to copy $templates/* to $courseDir/templates: $!\n"; |
|
|
148 | } |
|
|
149 | |
| 115 | if ($users) { |
150 | if ($users) { |
| 116 | # import users - much of this code is burgled from UserList.pm |
151 | # import users - much of this code is burgled from UserList.pm |
| 117 | |
152 | |
|
|
153 | my $db; |
|
|
154 | if ($dbLayout) { |
|
|
155 | # use the specified layout |
|
|
156 | $db = WeBWorK::DB->new($ce->{dbLayouts}->{$dbLayout}); |
|
|
157 | } else { |
|
|
158 | # use the default layout |
| 118 | my $db = WeBWorK::DB->new($ce); |
159 | $db = WeBWorK::DB->new($ce->{dbLayout}); |
|
|
160 | } |
|
|
161 | |
| 119 | my @contents = split /\n/, readFile($users); |
162 | my @contents = split /\n/, readFile($users); |
| 120 | |
163 | |
| 121 | foreach my $string (@contents) { |
164 | foreach my $string (@contents) { |
| 122 | $string =~ s/^\s+//; |
165 | $string =~ s/^\s+//; |
| 123 | $string =~ s/\s+$//; |
166 | $string =~ s/\s+$//; |
| … | |
… | |
| 145 | $PermissionLevel->permission(0); |
188 | $PermissionLevel->permission(0); |
| 146 | } |
189 | } |
| 147 | |
190 | |
| 148 | my $Password = $db->newPassword; |
191 | my $Password = $db->newPassword; |
| 149 | $Password->user_id($user_id); |
192 | $Password->user_id($user_id); |
| 150 | $Password->password($student_id); |
193 | $Password->password(cryptPassword($student_id)); |
| 151 | |
194 | |
| 152 | $db->addUser($User); |
195 | $db->addUser($User); |
| 153 | $db->addPermissionLevel($PermissionLevel); |
196 | $db->addPermissionLevel($PermissionLevel); |
| 154 | $db->addPassword($Password); |
197 | $db->addPassword($Password); |
| 155 | |
198 | |
| … | |
… | |
| 164 | if (my @ids = keys %professors) { |
207 | if (my @ids = keys %professors) { |
| 165 | print STDERR "warning: @ids not in imported user list.\n"; |
208 | print STDERR "warning: @ids not in imported user list.\n"; |
| 166 | } |
209 | } |
| 167 | } |
210 | } |
| 168 | |
211 | |
| 169 | if ($templates) { |
|
|
| 170 | unless (-d "$courseDir/templates") { |
|
|
| 171 | warn "$courseDir/templates: not found, creating:\n"; |
|
|
| 172 | print "mkdir $courseDir/templates\n"; |
|
|
| 173 | mkdir "$courseDir/templates" |
|
|
| 174 | or die "Failed to mkdir $courseDir/templates: $!\n"; |
|
|
| 175 | } |
|
|
| 176 | print "copy $templates/* -> $courseDir/templates\n"; |
|
|
| 177 | system "/bin/cp -r $templates/* $courseDir/templates/" |
|
|
| 178 | and die "Failed to copy $templates/* to $courseDir/templates: $!\n"; |
|
|
| 179 | } |
|
|
| 180 | |
|
|
| 181 | =head1 BUGS |
212 | =head1 BUGS |
| 182 | |
213 | |
| 183 | Databases are created using the database layout specified in the global |
214 | Databases are created using the database layout specified in the global |
| 184 | configuration file (F<global.conf>), which requires users to temporarily modify |
215 | configuration file (F<global.conf>), which requires users to temporarily modify |
| 185 | their system's configuration in order to create a course with a nonstandard |
216 | their system's configuration in order to create a course with a nonstandard |