[system] / branches / dg_dev / webwork2 / lib / WeBWorK / URLPath.pm Repository:
ViewVC logotype

Annotation of /branches/dg_dev/webwork2/lib/WeBWorK/URLPath.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6724 - (view) (download) (as text)

1 : sh002i 1842 ################################################################################
2 :     # WeBWorK Online Homework Delivery System
3 : sh002i 5319 # Copyright © 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/
4 : gage 6227 # $CVSHeader: webwork2/lib/WeBWorK/URLPath.pm,v 1.36 2008/04/29 19:27:34 sh002i Exp $
5 : sh002i 1842 #
6 :     # This program is free software; you can redistribute it and/or modify it under
7 :     # the terms of either: (a) the GNU General Public License as published by the
8 :     # Free Software Foundation; either version 2, or (at your option) any later
9 :     # version, or (b) the "Artistic License" which comes with this package.
10 :     #
11 :     # This program is distributed in the hope that it will be useful, but WITHOUT
12 :     # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 :     # FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the
14 :     # Artistic License for more details.
15 :     ################################################################################
16 :    
17 :     package WeBWorK::URLPath;
18 :    
19 :     =head1 NAME
20 :    
21 :     WeBWorK::URLPath - the WeBWorK virtual URL heirarchy.
22 :    
23 :     =cut
24 :    
25 :     use strict;
26 :     use warnings;
27 : sh002i 3775 use Carp;
28 : sh002i 3485 use WeBWorK::Debug;
29 : sh002i 1842
30 : sh002i 3485 {
31 :     no warnings "redefine";
32 :    
33 :     sub debug {
34 :     my ($label, $indent, @message) = @_;
35 :     my $header = " "x$indent;
36 :     $header .= "$label: " if $label ne "";
37 :     WeBWorK::Debug::debug($header, @message);
38 :     }
39 : sh002i 1865 }
40 :    
41 : sh002i 1842 =head1 VIRTUAL HEIRARCHY
42 :    
43 : sh002i 1891 PLEASE FOR THE LOVE OF GOD UPDATE THIS IF YOU CHANGE THE HEIRARCHY BELOW!!!
44 :    
45 : sh002i 1842 root /
46 :    
47 : sh002i 1945 course_admin /admin/ -> logout, options, instructor_tools
48 : gage 6227 html2xml /html2xml/
49 : sh002i 1842 set_list /$courseID/
50 :    
51 :     equation_display /$courseID/equation/
52 :     feedback /$courseID/feedback/
53 :     gateway_quiz /$courseID/quiz_mode/$setID/
54 : glarose 3377 proctored_gateway_quiz /$courseID/proctored_quiz_mode/$setID/
55 :     proctored_gateway_proctor_login /$courseID/proctored_quiz_mode/$setID/proctor_login/
56 : sh002i 1865 grades /$courseID/grades/
57 : sh002i 1842 hardcopy /$courseID/hardcopy/
58 :     hardcopy_preselect_set /$courseID/hardcopy/$setID/
59 :     logout /$courseID/logout/
60 :     options /$courseID/options/
61 : sh002i 4435 #test /$courseID/test/
62 : sh002i 5649 #render /$courseID/render/
63 : sh002i 1842
64 :     instructor_tools /$courseID/instructor/
65 :    
66 :     instructor_user_list /$courseID/instructor/users/
67 :     instructor_user_detail /$courseID/instructor/users/$userID/
68 :     instructor_sets_assigned_to_user /$courseID/instructor/users/$userID/sets/
69 :    
70 :     instructor_set_list /$courseID/instructor/sets/
71 :     instructor_set_detail /$courseID/instructor/sets/$setID/
72 :     instructor_users_assigned_to_set /$courseID/instructor/sets/$setID/users/
73 :    
74 :     instructor_add_users /$courseID/instructor/add_users/
75 :     instructor_set_assigner /$courseID/instructor/assigner/
76 :     instructor_file_transfer /$courseID/instructor/files/
77 : sh002i 2906 instructor_file_manager /$courseID/instructor/file_manager/
78 : jj 1995 instructor_set_maker /$courseID/instructor/setmaker/
79 : david gage 6488 instructor_set_maker2 /$courseID/instructor/setmaker2/
80 : david gage 6724 instructor_get_target_set_problems /$courseID/instructor/GetTargetSetProblems/
81 :     instructor_get_library_set_problems /$courseID/instructor/GetLibrarySetProblems/
82 : jj 3682 instructor_config /$courseID/instructor/config/
83 : jj 3301 instructor_compare /$courseID/instructor/compare/
84 : sh002i 1842
85 :     instructor_problem_editor /$courseID/instructor/pgProblemEditor/
86 :     instructor_problem_editor_withset /$courseID/instructor/pgProblemEditor/$setID/
87 :     instructor_problem_editor_withset_withproblem
88 :     /$courseID/instructor/pgProblemEditor/$setID/$problemID/
89 :    
90 :     instructor_scoring /$courseID/instructor/scoring/
91 :     instructor_scoring_download /$courseID/instructor/scoringDownload/
92 :     instructor_mail_merge /$courseID/instructor/send_mail/
93 :     instructor_answer_log /$courseID/instructor/show_answers/
94 : gage 2238 instructor_preflight /$courseID/instructor/preflight/
95 : sh002i 1912
96 : sh002i 1842 instructor_statistics /$courseID/instructor/stats/
97 : sh002i 1912 instructor_set_statistics /$courseID/instructor/stats/set/$setID/
98 :     instructor_user_statistics /$courseID/instructor/stats/student/$userID/
99 : sh002i 1842
100 : apizer 2162 instructor_progress /$courseID/instructor/StudentProgress/
101 :     instructor_set_progress /$courseID/instructor/StudentProgress/set/$setID/
102 :     instructor_user_progress /$courseID/instructor/StudentProgress/student/$userID/
103 :    
104 : sh002i 1842 problem_list /$courseID/$setID/
105 :     problem_detail /$courseID/$setID/$problemID/
106 : sh002i 2955
107 : sh002i 1842 =cut
108 :    
109 :     ################################################################################
110 :     # tree of path types
111 :     ################################################################################
112 :    
113 :     our %pathTypes = (
114 :     root => {
115 :     name => 'WeBWorK',
116 :     parent => '',
117 : gage 6227 kids => [ qw/course_admin html2xml set_list / ],
118 : sh002i 1842 match => qr|^/|,
119 :     capture => [ qw// ],
120 :     produce => '/',
121 :     display => 'WeBWorK::ContentGenerator::Home',
122 :     },
123 : sh002i 1945 course_admin => {
124 :     name => 'Course Administration',
125 :     parent => 'root',
126 :     kids => [ qw/logout options instructor_tools/ ],
127 :     match => qr|^(admin)/|,
128 :     capture => [ qw/courseID/ ],
129 :     produce => 'admin/',
130 :     display => 'WeBWorK::ContentGenerator::CourseAdmin',
131 :     },
132 : sh002i 1842
133 :     ################################################################################
134 : gage 6227 html2xml => {
135 :     name => 'html2xml',
136 :     parent => 'root', # 'set_list',
137 :     kids => [ qw// ],
138 :     match => qr|^html2xml/|,
139 :     capture => [ qw// ],
140 :     produce => 'html2xml/',
141 :     display => 'WeBWorK::ContentGenerator::renderViaXMLRPC',
142 :     },
143 :    
144 : sh002i 1842 set_list => {
145 : sh002i 2886 name => '$courseID',
146 : sh002i 1842 parent => 'root',
147 : glarose 3377 kids => [ qw/equation_display feedback gateway_quiz proctored_gateway_quiz grades hardcopy
148 : sh002i 1865 logout options instructor_tools problem_list
149 : sh002i 1842 / ],
150 :     match => qr|^([^/]+)/|,
151 :     capture => [ qw/courseID/ ],
152 :     produce => '$courseID/',
153 :     display => 'WeBWorK::ContentGenerator::ProblemSets',
154 :     },
155 :    
156 :     ################################################################################
157 :    
158 :     equation_display => {
159 :     name => 'Equation Display',
160 :     parent => 'set_list',
161 :     kids => [ qw// ],
162 :     match => qr|^equation/|,
163 :     capture => [ qw// ],
164 :     produce => 'equation/',
165 :     display => 'WeBWorK::ContentGenerator::EquationDisplay',
166 :     },
167 :     feedback => {
168 :     name => 'Feedback',
169 :     parent => 'set_list',
170 :     kids => [ qw// ],
171 :     match => qr|^feedback/|,
172 :     capture => [ qw// ],
173 :     produce => 'feedback/',
174 :     display => 'WeBWorK::ContentGenerator::Feedback',
175 :     },
176 :     gateway_quiz => {
177 :     name => 'Gateway Quiz $setID',
178 :     parent => 'set_list',
179 :     kids => [ qw// ],
180 :     match => qr|^quiz_mode/([^/]+)/|,
181 :     capture => [ qw/setID/ ],
182 :     produce => 'quiz_mode/$setID/',
183 :     display => 'WeBWorK::ContentGenerator::GatewayQuiz',
184 :     },
185 : glarose 3377 proctored_gateway_quiz => {
186 :     name => 'Proctored Gateway Quiz $setID',
187 :     parent => 'set_list',
188 :     kids => [ qw/proctored_gateway_proctor_login/ ],
189 :     match => qr|^proctored_quiz_mode/([^/]+)/|,
190 :     capture => [ qw/setID/ ],
191 :     produce => 'proctored_quiz_mode/$setID/',
192 :     display => 'WeBWorK::ContentGenerator::GatewayQuiz',
193 :     },
194 :     proctored_gateway_proctor_login => {
195 :     name => 'Proctored Gateway Quiz $setID Proctor Login',
196 :     parent => 'proctored_gateway_quiz',
197 :     kids => [ qw// ],
198 :     match => qr|^proctored_quiz_mode/([^/]+)/|,
199 :     capture => [ qw/setID/ ],
200 :     produce => 'proctored_quiz_mode/$setID/proctor_login',
201 :     display => 'WeBWorK::ContentGenerator::LoginProctor',
202 :     },
203 : sh002i 1865 grades => {
204 : sh002i 2847 name => 'Grades',
205 : sh002i 1865 parent => 'set_list',
206 :     kids => [ qw// ],
207 :     match => qr|^grades/|,
208 :     capture => [ qw// ],
209 :     produce => 'grades/',
210 :     display => 'WeBWorK::ContentGenerator::Grades',
211 :     },
212 : sh002i 1842 hardcopy => {
213 :     name => 'Hardcopy Generator',
214 :     parent => 'set_list',
215 : sh002i 1890 kids => [ qw/hardcopy_preselect_set/ ],
216 : sh002i 1842 match => qr|^hardcopy/|,
217 :     capture => [ qw// ],
218 :     produce => 'hardcopy/',
219 :     display => 'WeBWorK::ContentGenerator::Hardcopy',
220 :     },
221 :     hardcopy_preselect_set => {
222 :     name => 'Hardcopy Generator',
223 :     parent => 'hardcopy',
224 :     kids => [ qw// ],
225 :     match => qr|^([^/]+)/|,
226 :     capture => [ qw/setID/ ],
227 :     produce => '$setID/',
228 :     display => 'WeBWorK::ContentGenerator::Hardcopy',
229 :     },
230 :     logout => {
231 : sh002i 2847 name => 'Logout',
232 : sh002i 1842 parent => 'set_list',
233 :     kids => [ qw// ],
234 :     match => qr|^logout/|,
235 :     capture => [ qw// ],
236 :     produce => 'logout/',
237 :     display => 'WeBWorK::ContentGenerator::Logout',
238 :     },
239 :     options => {
240 : sh002i 2847 name => 'Password/Email',
241 : sh002i 1842 parent => 'set_list',
242 :     kids => [ qw// ],
243 :     match => qr|^options/|,
244 :     capture => [ qw// ],
245 :     produce => 'options/',
246 :     display => 'WeBWorK::ContentGenerator::Options',
247 :     },
248 : sh002i 4435 #test => {
249 :     # name => 'Test',
250 :     # parent => 'set_list',
251 :     # kids => [ qw// ],
252 :     # match => qr|^test/|,
253 :     # capture => [ qw// ],
254 :     # produce => 'test/',
255 :     # display => 'WeBWorK::ContentGenerator::Test',
256 :     #},
257 : sh002i 5649 #render => {
258 :     # name => 'Render',
259 :     # parent => 'set_list',
260 :     # kids => [ qw// ],
261 :     # match => qr|^render/|,
262 :     # capture => [ qw// ],
263 :     # produce => 'render/',
264 :     # display => 'WeBWorK::ContentGenerator::ProblemRenderer',
265 :     #},
266 : sh002i 1842
267 :     ################################################################################
268 :    
269 :     instructor_tools => {
270 :     name => 'Instructor Tools',
271 :     parent => 'set_list',
272 :     kids => [ qw/instructor_user_list instructor_set_list instructor_add_users
273 : sh002i 4536 instructor_set_assigner instructor_file_manager
274 : david gage 6724 instructor_problem_editor instructor_set_maker instructor_set_maker2 instructor_get_target_set_problems instructor_get_library_set_problems instructor_compare
275 : jj 3682 instructor_config
276 : sh002i 1842 instructor_scoring instructor_scoring_download instructor_mail_merge
277 : gage 2238 instructor_answer_log instructor_preflight instructor_statistics
278 : apizer 2162 instructor_progress
279 : sh002i 1842 / ],
280 :     match => qr|^instructor/|,
281 :     capture => [ qw// ],
282 :     produce => 'instructor/',
283 :     display => 'WeBWorK::ContentGenerator::Instructor::Index',
284 :     },
285 :    
286 :     ################################################################################
287 :    
288 :     instructor_user_list => {
289 : sh002i 2847 name => 'Classlist Editor',
290 : sh002i 1842 parent => 'instructor_tools',
291 :     kids => [ qw/instructor_user_detail/ ],
292 :     match => qr|^users/|,
293 :     capture => [ qw// ],
294 :     produce => 'users/',
295 :     display => 'WeBWorK::ContentGenerator::Instructor::UserList',
296 :     },
297 :     instructor_user_detail => {
298 : gage 3858 name => 'Sets assigned to $userID',
299 : sh002i 1842 parent => 'instructor_user_list',
300 :     kids => [ qw/instructor_sets_assigned_to_user/ ],
301 :     match => qr|^([^/]+)/|,
302 :     capture => [ qw/userID/ ],
303 :     produce => '$userID/',
304 :     display => 'WeBWorK::ContentGenerator::Instructor::UserDetail',
305 :     },
306 :     instructor_sets_assigned_to_user => {
307 :     name => 'Sets Assigned to User',
308 : sh002i 1912 parent => 'instructor_user_detail',
309 :     kids => [ qw// ],
310 : sh002i 1842 match => qr|^sets/|,
311 :     capture => [ qw// ],
312 :     produce => 'sets/',
313 :     display => 'WeBWorK::ContentGenerator::Instructor::SetsAssignedToUser',
314 :     },
315 :    
316 :     ################################################################################
317 :    
318 :     instructor_set_list => {
319 : sh002i 2847 name => 'Hmwk Sets Editor',
320 : sh002i 1842 parent => 'instructor_tools',
321 :     kids => [ qw/instructor_set_detail/ ],
322 :     match => qr|^sets/|,
323 :     capture => [ qw// ],
324 :     produce => 'sets/',
325 :     display => 'WeBWorK::ContentGenerator::Instructor::ProblemSetList',
326 :     },
327 :     instructor_set_detail => {
328 : toenail 2804 name => 'Set Detail for set $setID',
329 : sh002i 1842 parent => 'instructor_set_list',
330 : toenail 2804 kids => [ qw/instructor_users_assigned_to_set/ ],
331 : sh002i 1842 match => qr|^([^/]+)/|,
332 :     capture => [ qw/setID/ ],
333 :     produce => '$setID/',
334 : toenail 2804 display => 'WeBWorK::ContentGenerator::Instructor::ProblemSetDetail',
335 : sh002i 1842 },
336 :     instructor_users_assigned_to_set => {
337 : sh002i 3695 name => 'Users Assigned to Set $setID',
338 : sh002i 1842 parent => 'instructor_set_detail',
339 :     kids => [ qw// ],
340 :     match => qr|^users/|,
341 :     capture => [ qw// ],
342 :     produce => 'users/',
343 :     display => 'WeBWorK::ContentGenerator::Instructor::UsersAssignedToSet',
344 :     },
345 :    
346 :     ################################################################################
347 :    
348 :     instructor_add_users => {
349 :     name => 'Add Users',
350 :     parent => 'instructor_tools',
351 :     kids => [ qw// ],
352 :     match => qr|^add_users/|,
353 :     capture => [ qw// ],
354 :     produce => 'add_users/',
355 :     display => 'WeBWorK::ContentGenerator::Instructor::AddUsers',
356 :     },
357 :     instructor_set_assigner => {
358 :     name => 'Set Assigner',
359 :     parent => 'instructor_tools',
360 :     kids => [ qw// ],
361 :     match => qr|^assigner/|,
362 :     capture => [ qw// ],
363 :     produce => 'assigner/',
364 :     display => 'WeBWorK::ContentGenerator::Instructor::Assigner',
365 :     },
366 : jj 3682 instructor_config => {
367 :     name => 'Course Configuration',
368 :     parent => 'instructor_tools',
369 :     kids => [ qw// ],
370 :     match => qr|^config/|,
371 :     capture => [ qw// ],
372 :     produce => 'config/',
373 :     display => 'WeBWorK::ContentGenerator::Instructor::Config',
374 :     },
375 : jj 3301 instructor_compare => {
376 :     name => 'File Compare',
377 :     parent => 'instructor_tools',
378 :     kids => [ qw// ],
379 :     match => qr|^compare/|,
380 :     capture => [ qw// ],
381 :     produce => 'comp/',
382 :     display => 'WeBWorK::ContentGenerator::Instructor::Compare',
383 :     },
384 : jj 1995 instructor_set_maker => {
385 : sh002i 2847 name => 'Library Browser',
386 : jj 1995 parent => 'instructor_tools',
387 :     kids => [ qw// ],
388 :     match => qr|^setmaker/|,
389 :     capture => [ qw// ],
390 :     produce => 'setmaker/',
391 :     display => 'WeBWorK::ContentGenerator::Instructor::SetMaker',
392 :     },
393 : david gage 6488 instructor_set_maker2 => {
394 :     name => 'Library Browser 2',
395 :     parent => 'instructor_tools',
396 :     kids => [ qw// ],
397 :     match => qr|^setmaker2/|,
398 :     capture => [ qw// ],
399 :     produce => 'setmaker2/',
400 :     display => 'WeBWorK::ContentGenerator::Instructor::SetMaker2',
401 :     },
402 : david gage 6724 instructor_get_target_set_problems => {
403 :     name => 'Get Target Set Problems',
404 :     parent => 'instructor_tools',
405 :     kids => [ qw// ],
406 :     match => qr|^GetTargetSetProblems/|,
407 :     capture => [ qw// ],
408 :     produce => 'GetTargetSetProblems/',
409 :     display => 'WeBWorK::ContentGenerator::Instructor::GetTargetSetProblems',
410 :     },
411 :     instructor_get_library_set_problems => {
412 :     name => 'Get Library Set Problems',
413 :     parent => 'instructor_tools',
414 :     kids => [ qw// ],
415 :     match => qr|^GetLibrarySetProblems/|,
416 :     capture => [ qw// ],
417 :     produce => 'GetLibrarySetProblems/',
418 :     display => 'WeBWorK::ContentGenerator::Instructor::GetLibrarySetProblems',
419 :     },
420 : sh002i 2906 instructor_file_manager => {
421 :     name => 'File Manager',
422 :     parent => 'instructor_tools',
423 :     kids => [ qw// ],
424 :     match => qr|^file_manager/|,
425 :     capture => [ qw// ],
426 :     produce => 'file_manager/',
427 :     display => 'WeBWorK::ContentGenerator::Instructor::FileManager',
428 :     },
429 : sh002i 1842 instructor_problem_editor => {
430 :     name => 'Problem Editor',
431 :     parent => 'instructor_tools',
432 :     kids => [ qw/instructor_problem_editor_withset/ ],
433 :     match => qr|^pgProblemEditor/|,
434 :     capture => [ qw// ],
435 :     produce => 'pgProblemEditor/',
436 : sh002i 1899 display => 'WeBWorK::ContentGenerator::Instructor::PGProblemEditor',
437 : sh002i 1842 },
438 :     instructor_problem_editor_withset => {
439 : sh002i 1922 name => '$setID',
440 : sh002i 1842 parent => 'instructor_problem_editor',
441 :     kids => [ qw/instructor_problem_editor_withset_withproblem/ ],
442 :     match => qr|^([^/]+)/|,
443 :     capture => [ qw/setID/ ],
444 :     produce => '$setID/',
445 : sh002i 4491 display => undef,
446 : sh002i 1842 },
447 :     instructor_problem_editor_withset_withproblem => {
448 : sh002i 1922 name => '$problemID',
449 : sh002i 1842 parent => 'instructor_problem_editor_withset',
450 :     kids => [ qw// ],
451 :     match => qr|^([^/]+)/|,
452 :     capture => [ qw/problemID/ ],
453 :     produce => '$problemID/',
454 :     display => 'WeBWorK::ContentGenerator::Instructor::PGProblemEditor',
455 :     },
456 :     instructor_scoring => {
457 :     name => 'Scoring Tools',
458 :     parent => 'instructor_tools',
459 :     kids => [ qw// ],
460 :     match => qr|^scoring/|,
461 :     capture => [ qw// ],
462 :     produce => 'scoring/',
463 :     display => 'WeBWorK::ContentGenerator::Instructor::Scoring',
464 :     },
465 :     instructor_scoring_download => {
466 :     name => 'Scoring Download',
467 :     parent => 'instructor_tools',
468 :     kids => [ qw// ],
469 :     match => qr|^scoringDownload/|,
470 :     capture => [ qw// ],
471 :     produce => 'scoringDownload/',
472 :     display => 'WeBWorK::ContentGenerator::Instructor::ScoringDownload',
473 :     },
474 :     instructor_mail_merge => {
475 : sh002i 2847 name => 'Email',
476 : sh002i 1842 parent => 'instructor_tools',
477 :     kids => [ qw// ],
478 :     match => qr|^send_mail/|,
479 :     capture => [ qw// ],
480 :     produce => 'send_mail/',
481 :     display => 'WeBWorK::ContentGenerator::Instructor::SendMail',
482 :     },
483 :     instructor_answer_log => {
484 :     name => 'Answer Log',
485 :     parent => 'instructor_tools',
486 :     kids => [ qw// ],
487 :     match => qr|^show_answers/|,
488 :     capture => [ qw// ],
489 :     produce => 'show_answers/',
490 :     display => 'WeBWorK::ContentGenerator::Instructor::ShowAnswers',
491 :     },
492 : gage 2238 instructor_preflight => {
493 :     name => 'Preflight Log',
494 :     parent => 'instructor_tools',
495 :     kids => [ qw// ],
496 :     match => qr|^preflight/|,
497 :     capture => [ qw// ],
498 :     produce => 'preflight/',
499 :     display => 'WeBWorK::ContentGenerator::Instructor::Preflight',
500 :     },
501 : sh002i 1842
502 :     ################################################################################
503 :    
504 :     instructor_statistics => {
505 :     name => 'Statistics',
506 :     parent => 'instructor_tools',
507 :     kids => [ qw/instructor_set_statistics instructor_user_statistics/ ],
508 :     match => qr|^stats/|,
509 :     capture => [ qw// ],
510 :     produce => 'stats/',
511 :     display => 'WeBWorK::ContentGenerator::Instructor::Stats',
512 :     },
513 :     instructor_set_statistics => {
514 :     name => 'Statistics',
515 :     parent => 'instructor_statistics',
516 :     kids => [ qw// ],
517 :     match => qr|^(set)/([^/]+)/|,
518 :     capture => [ qw/statType setID/ ],
519 :     produce => 'set/$setID/',
520 :     display => 'WeBWorK::ContentGenerator::Instructor::Stats',
521 :     },
522 :     instructor_user_statistics => {
523 :     name => 'Statistics',
524 :     parent => 'instructor_statistics',
525 :     kids => [ qw// ],
526 :     match => qr|^(student)/([^/]+)/|,
527 :     capture => [ qw/statType userID/ ],
528 :     produce => 'student/$userID/',
529 :     display => 'WeBWorK::ContentGenerator::Instructor::Stats',
530 :     },
531 :    
532 :     ################################################################################
533 :    
534 : apizer 2162 instructor_progress => {
535 : jj 2223 name => 'Student Progress',
536 : apizer 2162 parent => 'instructor_tools',
537 :     kids => [ qw/instructor_set_progress instructor_user_progress/ ],
538 :     match => qr|^progress/|,
539 :     capture => [ qw// ],
540 :     produce => 'progress/',
541 :     display => 'WeBWorK::ContentGenerator::Instructor::StudentProgress',
542 :     },
543 :     instructor_set_progress => {
544 : jj 2223 name => 'Student Progress',
545 : apizer 2162 parent => 'instructor_progress',
546 :     kids => [ qw// ],
547 :     match => qr|^(set)/([^/]+)/|,
548 :     capture => [ qw/statType setID/ ],
549 :     produce => 'set/$setID/',
550 :     display => 'WeBWorK::ContentGenerator::Instructor::StudentProgress',
551 :     },
552 :     instructor_user_progress => {
553 : jj 2223 name => 'Student Progress',
554 : apizer 2162 parent => 'instructor_progress',
555 :     kids => [ qw// ],
556 :     match => qr|^(student)/([^/]+)/|,
557 :     capture => [ qw/statType userID/ ],
558 :     produce => 'student/$userID/',
559 :     display => 'WeBWorK::ContentGenerator::Instructor::StudentProgress',
560 :     },
561 :    
562 :     ################################################################################
563 :    
564 : sh002i 1842 problem_list => {
565 :     name => '$setID',
566 :     parent => 'set_list',
567 :     kids => [ qw/problem_detail/ ],
568 :     match => qr|^([^/]+)/|,
569 :     capture => [ qw/setID/ ],
570 :     produce => '$setID/',
571 :     display => 'WeBWorK::ContentGenerator::ProblemSet',
572 :     },
573 :     problem_detail => {
574 :     name => '$problemID',
575 :     parent => 'problem_list',
576 :     kids => [ qw// ],
577 :     match => qr|^([^/]+)/|,
578 :     capture => [ qw/problemID/ ],
579 :     produce => '$problemID/',
580 :     display => 'WeBWorK::ContentGenerator::Problem',
581 :     },
582 :    
583 :     );
584 :    
585 :     =for comment
586 :    
587 :     a handy template:
588 :    
589 :     id => {
590 :     name => '',
591 :     parent => '',
592 :     kids => [ qw// ],
593 :     match => qr|^/|,
594 :     capture => [ qw// ],
595 :     produce => '',
596 :     display => '',
597 :     },
598 :    
599 :     =cut
600 :    
601 :     ################################################################################
602 :    
603 : sh002i 1865 =head1 CONSTRUCTORS
604 : sh002i 1842
605 : sh002i 1865 =over
606 : sh002i 1842
607 : sh002i 1865 =item new(%fields)
608 : sh002i 1842
609 : sh002i 1865 Creates a new WeBWorK::URLPath. %fields may contain the following:
610 : sh002i 1842
611 : sh002i 1865 type => the internal path type associated with this
612 :     args => a reference to a hash associating path arguments with values
613 : sh002i 1842
614 : sh002i 1865 This constructor is used internally. Refer to newFromPath() and newFromModule()
615 :     for more useful constructors.
616 : sh002i 1842
617 :     =cut
618 :    
619 :     sub new {
620 :     my ($invocant, %fields) = @_;
621 :     my $class = ref $invocant || $invocant;
622 :     my $self = {
623 :     type => undef,
624 :     args => {},
625 :     %fields,
626 :     };
627 :     return bless $self, $class;
628 :     }
629 :    
630 : sh002i 1865 =item newFromPath($path)
631 : sh002i 1842
632 : sh002i 1865 Creates a new WeBWorK::URLPath by parsing the path given in $path. It the path
633 :     is invalid, an exception is thrown.
634 : sh002i 1842
635 :     =cut
636 :    
637 : sh002i 1865 sub newFromPath {
638 :     my ($invocant, $path) = @_;
639 :    
640 :     my ($type, %args) = getPathType($path);
641 : sh002i 3775 croak "no type matches path $path" unless $type;
642 : sh002i 1865
643 : sh002i 1842 return $invocant->new(
644 :     type => $type,
645 :     args => \%args,
646 :     );
647 :     }
648 :    
649 : sh002i 1865 =item newFromModule($module, %args)
650 : sh002i 1842
651 : sh002i 1865 Creates a new WeBWorK::URLPath by finding a path type which matches the module
652 :     and path arguments given. If no type matches, an exception is thrown.
653 : sh002i 1842
654 :     =cut
655 :    
656 : sh002i 1865 sub newFromModule {
657 :     my ($invocant, $module, %args) = @_;
658 :    
659 :     my $type = getModuleType($module, keys %args);
660 : sh002i 3775 croak "no type matches module $module with args", map { " $_=>$args{$_}" } keys %args unless $type;
661 : sh002i 1865
662 : sh002i 1842 return $invocant->new(
663 :     type => $type,
664 : sh002i 1865 args => \%args
665 : sh002i 1842 );
666 :     }
667 :    
668 :     =back
669 :    
670 : sh002i 1865 =cut
671 :    
672 :     ################################################################################
673 :    
674 : sh002i 1842 =head1 METHODS
675 :    
676 : sh002i 1865 =head2 Methods that return information from the object itself
677 :    
678 : sh002i 1842 =over
679 :    
680 : sh002i 1865 =item type()
681 :    
682 :     Returns the path type of the WeBWorK::URLPath.
683 :    
684 :     =cut
685 :    
686 :     sub type {
687 :     my ($self) = @_;
688 :     my $type = $self->{type};
689 :    
690 :     return $type;
691 :     }
692 :    
693 :     =item args()
694 :    
695 :     Returns a hash of arguments derived from the WeBWorK::URLPath.
696 :    
697 :     =cut
698 :    
699 :     sub args {
700 :     my ($self) = @_;
701 :     my %args = %{ $self->{args} };
702 :    
703 :     return %args;
704 :     }
705 :    
706 :     =item arg($name)
707 :    
708 :     Returns the named argument, as derived from the WeBWorK::URLPath.
709 :    
710 :     =cut
711 :    
712 :     sub arg {
713 :     my ($self, $name) = @_;
714 :     my %args = %{ $self->{args} };
715 :    
716 :     return $args{$name};
717 :     }
718 :    
719 :     =back
720 :    
721 :     =cut
722 :    
723 :     # ------------------------------------------------------------------------------
724 :    
725 :     =head2 Methods that return information from path node associated with the object
726 :    
727 :     =over
728 :    
729 :     =item name()
730 :    
731 :     Returns the human-readable name of this WeBWorK::URLPath.
732 :    
733 :     =cut
734 :    
735 :     sub name {
736 :     my ($self) = @_;
737 :     my $type = $self->{type};
738 :     my %args = $self->args;
739 :    
740 :     my $name = $pathTypes{$type}->{name};
741 :     $name = interpolate($name, %args);
742 :    
743 :     return $name;
744 :     }
745 :    
746 :     =item module()
747 :    
748 :     Returns the name of the module that will handle this WeBWorK::URLPath.
749 :    
750 :     =cut
751 :    
752 :     sub module {
753 :     my ($self) = @_;
754 :     my $type = $self->{type};
755 :    
756 :     return $pathTypes{$type}->{display};
757 :     }
758 :    
759 :     =back
760 :    
761 :     =cut
762 :    
763 :     # ------------------------------------------------------------------------------
764 :    
765 :     =head2 Methods that search the virtual heirarchy
766 :    
767 :     =over
768 :    
769 : sh002i 1842 =item parent()
770 :    
771 :     Returns a new WeBWorK::URLPath representing the parent of the current URLPath.
772 :     Returns an undefined value if the URLPath has no parent.
773 :    
774 :     =cut
775 :    
776 :     sub parent {
777 :     my ($self) = @_;
778 :     my $type = $self->{type};
779 :    
780 :     my $newType = $pathTypes{$self->{type}}->{parent};
781 :     return undef unless $newType;
782 :    
783 :     # remove any arguments added by the current node (and therefore not needed by the parent)
784 :     my @currArgs = @{ $pathTypes{$type}->{capture} };
785 :     my %newArgs = %{ $self->{args} };
786 :     delete @newArgs{@currArgs} if @currArgs;
787 :    
788 : sh002i 1865 return $self->new(type => $newType, args => \%newArgs);
789 : sh002i 1842 }
790 :    
791 :     =item child($module, %newArgs)
792 :    
793 :     Returns a new WeBWorK::URLPath representing the child of the current URLPath
794 :     whose module is C<$module>. If no child matches, an undefined value is returned.
795 :     Pass additional arguments needed by the child in C<%newArgs>.
796 :    
797 :     =cut
798 :    
799 :     sub child {
800 :     my ($self, $module, %newArgs) = @_;
801 :     my $type = $self->{type};
802 :    
803 :     my @kids = @{ $pathTypes{$type}->{kids} };
804 :     my $newType;
805 :     foreach my $kid (@kids) {
806 :     if ($pathTypes{$kid}->{module} eq $module) {
807 :     $newType = $kid;
808 :     last;
809 :     }
810 :     }
811 :    
812 :     if ($newType) {
813 : sh002i 1865 return $self->new(type => $newType, args => \%newArgs);
814 : sh002i 1842 } else {
815 :     return undef;
816 :     }
817 :     }
818 :    
819 : sh002i 1865 =item path()
820 : sh002i 1842
821 : sh002i 1865 Reconstructs the path string from a WeBWorK::URLPath.
822 : sh002i 1842
823 :     =cut
824 :    
825 : sh002i 1865 sub path {
826 : sh002i 1842 my ($self) = @_;
827 : sh002i 1865 my $type = $self->type;
828 :     my %args = %{ $self->{args} };
829 :    
830 :     my $path = buildPathFromType($type);
831 :     $path = interpolate($path, %args);
832 :    
833 :     return $path;
834 : sh002i 1842 }
835 :    
836 : sh002i 1865 =back
837 : sh002i 1842
838 : sh002i 1865 =cut
839 : sh002i 1842
840 : sh002i 1865 ################################################################################
841 :    
842 :     =head1 UTILITY FUNCTIONS
843 :    
844 :     =over
845 :    
846 : sh002i 4491 =item all_modules()
847 :    
848 :     Return a list of the display modules associated with all possible path types.
849 :    
850 :     =cut
851 :    
852 :     sub all_modules {
853 :     my @modules = grep { defined } map { $pathTypes{$_}{display} } keys %pathTypes;
854 :     my %modules; @modules{@modules} = (); # remove duplicates
855 :     return keys %modules;
856 :     }
857 :    
858 : sh002i 1865 =item interpolate($string, %symbols)
859 :    
860 :     Replaces simple scalars (\$\w+) in $string with values in %symbols. If a scalar
861 :     does not exist in %symbols, it is left alone.
862 :    
863 : sh002i 1842 =cut
864 :    
865 : sh002i 1865 sub interpolate {
866 :     my ($string, %symbols) = @_;
867 :    
868 :     $string =~ s/\$(\w+)/exists $symbols{$1} ? $symbols{$1} : "\$$1"/eg;
869 :    
870 :     return $string;
871 : sh002i 1842 }
872 :    
873 : sh002i 1865 =back
874 : sh002i 1842
875 : sh002i 1865 =cut
876 : sh002i 1842
877 : sh002i 1865 # ------------------------------------------------------------------------------
878 :    
879 :     =over
880 :    
881 :     =item getPathType($path)
882 :    
883 :     Parse the string $path, determining the path type. Returns ($type, %args), where
884 :     $type is the type of the path and %args contains any extracted path arguments.
885 :     If conversion fails, a false value is returned.
886 :    
887 : sh002i 1842 =cut
888 :    
889 : sh002i 1865 sub getPathType($) {
890 :     my ($path) = @_;
891 :    
892 :     my %args;
893 :     my $context = visitPathTypeNode("root", $path, \%args, 0);
894 :    
895 :     return $context, %args;
896 : sh002i 1842 }
897 :    
898 : sh002i 1865 =item getModuleType($module, @args)
899 : sh002i 1842
900 : sh002i 1865 Returns the path type matching the given module and argument names, or a false
901 :     value if no type matches.
902 : sh002i 1842
903 :     =cut
904 :    
905 : sh002i 1865 sub getModuleType {
906 :     my ($module, @args) = @_;
907 :     @args = sort @args;
908 :     my %args;
909 :     @args{@args} = ();
910 :    
911 :     NODE: foreach my $nodeID (keys %pathTypes) {
912 :     my $node = $pathTypes{$nodeID};
913 :    
914 :     # module name matches?
915 : sh002i 1945 next NODE unless defined $node->{display} and $node->{display} eq $module;
916 : sh002i 1865
917 :     # collect all captures from here to root
918 :     my @captures;
919 :     my $tmpNodeID = $nodeID;
920 :     while ($tmpNodeID) {
921 :     my $tmpNode = $pathTypes{$tmpNodeID};
922 :     push @captures, @{ $tmpNode->{capture} };
923 :     $tmpNodeID = $tmpNode->{parent};
924 :     }
925 :    
926 :     # same number of captures?
927 :     next NODE unless @captures == @args;
928 :    
929 :     # same captures?
930 :     @captures = sort @captures;
931 :     for (my $i = 0; $i < @args; $i++) {
932 :     next NODE unless $args[$i] eq $captures[$i];
933 :     }
934 :    
935 :     # if we got here, this node matches
936 :     return $nodeID;
937 :     }
938 :    
939 :     return 0; # no node matches
940 : sh002i 1842 }
941 :    
942 : sh002i 1865 =item buildPathFromType($type)
943 : sh002i 1842
944 : sh002i 1865 Returns a string path for the given path type. Since arguments are not supplied,
945 :     the string may contain scalar variables ripe for interpolation.
946 : sh002i 1842
947 :     =cut
948 :    
949 : sh002i 1865 sub buildPathFromType($) {
950 :     my ($type) = @_;
951 : sh002i 1842
952 : sh002i 1865 my $path = "";
953 : sh002i 1842
954 : sh002i 1865 while ($type) {
955 :     $path = $pathTypes{$type}->{produce} . $path;
956 :     $type = $pathTypes{$type}->{parent};
957 :     };
958 :    
959 : sh002i 1842 return $path;
960 :     }
961 :    
962 : sh002i 1865 =item visitPathTypeNode($nodeID, $path, $argsRef, $indent)
963 :    
964 :     Internal search function. See getPathType().
965 :    
966 : sh002i 1945 Returns the nodeID of the node that consumed the final characters in $path, or
967 :     the following failure conditions:
968 :    
969 :     Returns 0 if $nodeID doesn't match $path.
970 :    
971 :     Returns -1 if $nodeID matched $path, but no children of $nodeID consumed the
972 :     remaining path. In this case, the stack is unwound immediately.
973 :    
974 : sh002i 1865 =cut
975 :    
976 :     sub visitPathTypeNode($$$$);
977 :    
978 :     sub visitPathTypeNode($$$$) {
979 :     my ($nodeID, $path, $argsRef, $indent) = @_;
980 : sh002i 3485 debug("visitPathTypeNode", $indent, "visiting node $nodeID with path $path");
981 : sh002i 1865
982 :     unless (exists $pathTypes{$nodeID}) {
983 : sh002i 3485 debug("visitPathTypeNode", $indent, "node $nodeID doesn't exist in node list: failed");
984 : sh002i 1865 die "node $nodeID doesn't exist in node list: failed";
985 :     }
986 :    
987 :     my %node = %{ $pathTypes{$nodeID} };
988 :     my $match = $node{match};
989 :     my @capture_names = @{ $node{capture} };
990 :    
991 : sh002i 1945 # attempt to match $path against $match.
992 : sh002i 1865 debug("visitPathTypeNode", $indent, "trying to match $match: ");
993 :     if ($path =~ s/($match)//) {
994 : sh002i 1945 # it matches! store captured strings in $argsRef and remove the matched
995 :     # characters from $path. waste a lot of lines on sanity checking... ;)
996 : sh002i 3485 debug("", 0, "success!");
997 : sh002i 1865 my @capture_values = $1 =~ m/$match/;
998 :     if (@capture_names) {
999 :     my $nexpected = @capture_names;
1000 :     my $ncaptured = @capture_values;
1001 :     my $max = $nexpected > $ncaptured ? $nexpected : $ncaptured;
1002 :     warn "captured $ncaptured arguments, expected $nexpected." unless $ncaptured == $nexpected;
1003 :     for (my $i = 0; $i < $max; $i++) {
1004 :     my $name = $capture_names[$i];
1005 :     my $value = $capture_values[$i];
1006 :     if ($i > $nexpected) {
1007 :     warn "captured an unexpected argument: $value -- ignoring it.";
1008 :     next;
1009 :     }
1010 :     if ($i > $ncaptured) {
1011 :     warn "expected an uncaptured argument named: $name -- ignoring it.";
1012 :     next;
1013 :     }
1014 :     if (exists $argsRef->{$name}) {
1015 :     my $old = $argsRef->{$name};
1016 : sh002i 1945 warn "encountered argument $name again, old value: $old new value: $value -- replacing.";
1017 : sh002i 1865 }
1018 : sh002i 3485 debug("visitPathTypeNode", $indent, "setting argument $name => $value.");
1019 : sh002i 1865 $argsRef->{$name} = $value;
1020 :     }
1021 :     }
1022 :     } else {
1023 : sh002i 1945 # it doesn't match. bail out now with return value 0
1024 : sh002i 3485 debug("", 0, "failed.");
1025 : sh002i 1865 return 0;
1026 :     }
1027 :    
1028 : sh002i 1945 ##### if we're here we matched #####
1029 :    
1030 :     # if there's no more path left, then this node is the one! return $nodeID
1031 : sh002i 1865 if ($path eq "") {
1032 : sh002i 3485 debug("visitPathTypeNode", $indent, "no path left, type is $nodeID");
1033 : sh002i 1865 return $nodeID;
1034 :     }
1035 :    
1036 : sh002i 1945 # otherwise, we have to send the remaining path to the node's children
1037 : sh002i 3485 debug("visitPathTypeNode", $indent, "but path remains: $path");
1038 : sh002i 1865 my @kids = @{ $node{kids} };
1039 :     if (@kids) {
1040 :     foreach my $kid (@kids) {
1041 : sh002i 3485 debug("visitPathTypeNode", $indent, "trying child $kid:");
1042 : sh002i 1865 my $result = visitPathTypeNode($kid, $path, $argsRef, $indent+1);
1043 : sh002i 1945 # we return in two situations:
1044 :     # if $result is -1, then the kid matched but couldn't consume the rest of the path
1045 :     # if $result is the ID of a node, then the kid matched and consumed the rest of the path
1046 :     # these are all true values (assuming that "0" isn't a valid node ID), so we say:
1047 : sh002i 1865 return $result if $result;
1048 :     }
1049 : sh002i 3485 debug("visitPathTypeNode", $indent, "no children claimed the remaining path: failed.");
1050 : sh002i 1865 } else {
1051 : sh002i 3485 debug("visitPathTypeNode", $indent, "no children to claim the remaining path: failed.");
1052 : sh002i 1865 }
1053 : sh002i 1945
1054 :     # in both of the above cases, we matched but couldn't provide children that
1055 :     # would consume the rest of the path. so we return -1, causing the whole
1056 :     # stack to unwind. WHEEEEEEE!
1057 :     return -1;
1058 : sh002i 1865 }
1059 :    
1060 :     =back
1061 :    
1062 :     =cut
1063 :    
1064 : sh002i 1842 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9