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

Annotation of /trunk/webwork2/lib/WeBWorK/URLPath.pm

Parent Directory Parent Directory | Revision Log Revision Log


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

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

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9