Diff for /loncom/interface/lonnavmaps.pm between versions 1.351 and 1.373

version 1.351, 2005/11/22 16:39:45 version 1.373, 2006/03/19 19:50:40
Line 57  my %statusIconMap = Line 57  my %statusIconMap =
      $resObj->CLOSED       => '',       $resObj->CLOSED       => '',
      $resObj->OPEN         => 'navmap.open.gif',       $resObj->OPEN         => 'navmap.open.gif',
      $resObj->CORRECT      => 'navmap.correct.gif',       $resObj->CORRECT      => 'navmap.correct.gif',
      $resObj->PARTIALLY_CORRECT      => 'navmap.ellipsis.gif',       $resObj->PARTIALLY_CORRECT      => 'navmap.partial.gif',
      $resObj->INCORRECT    => 'navmap.wrong.gif',       $resObj->INCORRECT    => 'navmap.wrong.gif',
      $resObj->ATTEMPTED    => 'navmap.ellipsis.gif',       $resObj->ATTEMPTED    => 'navmap.ellipsis.gif',
      $resObj->ERROR        => ''       $resObj->ERROR        => ''
Line 194  MENU Line 194  MENU
 MENU  MENU
  }   }
         $r->send_http_header;          $r->send_http_header;
  my $html=&Apache::lonxml::xmlbegin();   my $js =<<"ENDSUBM";
  $r->print(<<"ENDSUBM");  
  $html  
         <head>  
   <script type="text/javascript">    <script type="text/javascript">
      function submitthis() {       function submitthis() {
     $menu      $menu
Line 205  MENU Line 202  MENU
     }      }
   
    </script>     </script>
         </head>  
  <body bgcolor="#FFFFFF" onLoad="submitthis()"></body>  
         </html>  
 ENDSUBM  ENDSUBM
           $r->print(&Apache::lonxml::xmlbegin().
     &Apache::loncommon::head(undef,$js).
     '<body bgcolor="#FFFFFF" onLoad="submitthis()">'.
     &Apache::loncommon::end_page(undef,$js));
   
         return OK;          return OK;
     }      }
     if ($ENV{QUERY_STRING} =~ /^launchExternal/) {      if ($ENV{QUERY_STRING} =~ /^launchExternal/) {
Line 239  MENU Line 238  MENU
         return HTTP_NOT_ACCEPTABLE;          return HTTP_NOT_ACCEPTABLE;
     }      }
     $r->send_http_header;      $r->send_http_header;
     my $html=&Apache::lonxml::xmlbegin();  
     $r->print("$html<head>\n");  
     $r->print("<title>".&mt('Navigate Course Contents')."</title>");  
 # ------------------------------------------------------------ Get query string  # ------------------------------------------------------------ Get query string
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['register','sort','showOnlyHomework','postsymb']);      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['register','sort','showOnlyHomework','postsymb']);
           
Line 249  MENU Line 246  MENU
     my $addentries='';      my $addentries='';
     my $more_unload;      my $more_unload;
     my $body_only='';      my $body_only='';
       my $js;
     if ($env{'environment.remotenavmap'} eq 'on') {      if ($env{'environment.remotenavmap'} eq 'on') {
  $r->print('<script type="text/javascript">   $js='<script type="text/javascript">
                       function collapse() {                  function collapse() {
                          this.document.location="/adm/navmaps?collapseExternal";                     this.document.location="/adm/navmaps?collapseExternal";
                       }                  }
                    </script>');               </script>';
 # FIXME need to be smarter to only catch window close events  # FIXME need to be smarter to only catch window close events
 # $more_unload="collapse()"  # $more_unload="collapse()"
  $body_only=1;   $body_only=1;
Line 269  MENU Line 267  MENU
     }      }
   
     # Header      # Header
     $r->print('</head>'.      $r->print(&Apache::lonxml::xmlbegin().
         &Apache::loncommon::head('Navigate Course Contents',$js).
               &Apache::loncommon::bodytag('Navigate Course Contents','',                &Apache::loncommon::bodytag('Navigate Course Contents','',
   $addentries,$body_only,'',    $addentries,$body_only,'',
   $env{'form.register'}));    $env{'form.register'}));
Line 281  MENU Line 280  MENU
     if (!($navmap->courseMapDefined())) {      if (!($navmap->courseMapDefined())) {
  $r->print(&Apache::loncommon::help_open_menu('','Navigation Screen','Navigation_Screen','',undef,'RAT'));   $r->print(&Apache::loncommon::help_open_menu('','Navigation Screen','Navigation_Screen','',undef,'RAT'));
         $r->print('<font size="+2" color="red">Coursemap undefined.</font>' .          $r->print('<font size="+2" color="red">Coursemap undefined.</font>' .
                   '</body></html>');                    &Apache::loncommon::end_page());
         return OK;          return OK;
     }      }
   
Line 434  MENU Line 433  MENU
     #my $td=&tv_interval($t0);      #my $td=&tv_interval($t0);
     #$r->print("<br />$td");      #$r->print("<br />$td");
   
     $r->print("</body></html>");      $r->print(&Apache::loncommon::end_page());
     $r->rflush();      $r->rflush();
   
     return OK;      return OK;
Line 530  sub getDescription { Line 529  sub getDescription {
     if ($status == $res->PAST_DUE_NO_ANSWER) {      if ($status == $res->PAST_DUE_NO_ANSWER) {
         return &mt("Was due")." " . timeToHumanString($res->duedate($part),'end');          return &mt("Was due")." " . timeToHumanString($res->duedate($part),'end');
     }      }
     if ($status == $res->ANSWER_OPEN || $status == $res->PARTIALLY_CORRECT) {      if (($status == $res->ANSWER_OPEN || $status == $res->PARTIALLY_CORRECT)
    && $res->handgrade($part) ne 'yes') {
         return &mt("Answer available");          return &mt("Answer available");
     }      }
     if ($status == $res->EXCUSED) {      if ($status == $res->EXCUSED) {
Line 1094  sub render_resource { Line 1094  sub render_resource {
           
     if ($resource->is_problem()) {      if ($resource->is_problem()) {
         if ($part eq '0' || $params->{'condensed'}) {          if ($part eq '0' || $params->{'condensed'}) {
             $icon ='<img src="'.$location.'/problem.gif" alt="&nbsp;&nbsp;" border="0" />';              $icon ='<img src="'.$location.'/problem.gif" alt="'.&mt('Problem').'" border="0" />';
         } else {          } else {
             $icon = $params->{'indentString'};              $icon = $params->{'indentString'};
         }          }
Line 1111  sub render_resource { Line 1111  sub render_resource {
         }          }
   
  my $folderType = $resource->is_sequence() ? 'folder' : 'page';   my $folderType = $resource->is_sequence() ? 'folder' : 'page';
           my $title=$resource->title;
           $title=~s/\"/\&quot;/g;
         if (!$params->{'resource_no_folder_link'}) {          if (!$params->{'resource_no_folder_link'}) {
             $icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') . '.gif';              $icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') . '.gif';
     $icon = "<img src='$location/$icon' alt='".      $icon = "<img src='$location/$icon' alt=\"".
  ($nowOpen ? 'Open Folder' : 'Close Folder')."' border='0' />";   ($nowOpen ? &mt('Open Folder') : &mt('Close Folder')).' '.$title."\" border='0' />";
   
             $linkopen = "<a href=\"" . $params->{'url'} . '?' .               $linkopen = "<a href=\"" . $params->{'url'} . '?' . 
                 $params->{'queryString'} . '&filter=';                  $params->{'queryString'} . '&filter=';
Line 1133  sub render_resource { Line 1134  sub render_resource {
             # Don't allow users to manipulate folder              # Don't allow users to manipulate folder
             $icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') .              $icon = "navmap.$folderType." . ($nowOpen ? 'closed' : 'open') .
                 '.nomanip.gif';                  '.nomanip.gif';
             $icon = "<img src='$location/$icon' alt='".              $icon = "<img src='$location/$icon' alt=\"".
  ($nowOpen ? 'Open Folder' : 'Close Folder')."' border='0' />";   ($nowOpen ? &mt('Open Folder') : &mt('Close Folder')).' '.$title."\" border='0' />";
   
             $linkopen = "";              $linkopen = "";
             $linkclose = "";              $linkclose = "";
Line 1142  sub render_resource { Line 1143  sub render_resource {
     }      }
   
     if ($resource->randomout()) {      if ($resource->randomout()) {
         $nonLinkedText .= ' <i>(hidden)</i> ';          $nonLinkedText .= ' <i>('.&mt('hidden').')</i> ';
     }      }
     if (!$resource->condval()) {      if (!$resource->condval()) {
         $nonLinkedText .= ' <i>(conditionally hidden)</i> ';          $nonLinkedText .= ' <i>('.&mt('conditionally hidden').')</i> ';
     }      }
           
     # We're done preparing and finally ready to start the rendering      # We're done preparing and finally ready to start the rendering
Line 1177  sub render_resource { Line 1178  sub render_resource {
     if ($resource->is_problem() && $part ne '0' &&       if ($resource->is_problem() && $part ne '0' && 
         !$params->{'condensed'}) {          !$params->{'condensed'}) {
  my $displaypart=$resource->part_display($part);   my $displaypart=$resource->part_display($part);
         $partLabel = " (Part: $displaypart)";          $partLabel = " (".&mt('Part: [_1]', $displaypart).")";
  if ($link!~/\#/) { $link.='#'.&Apache::lonnet::escape($part); }   if ($link!~/\#/) { $link.='#'.&Apache::lonnet::escape($part); }
         $title = "";          $title = "";
     }      }
   
     if ($params->{'condensed'} && $resource->countParts() > 1) {      if ($params->{'condensed'} && $resource->countParts() > 1) {
         $nonLinkedText .= ' (' . $resource->countParts() . ' parts)';          $nonLinkedText .= ' ('.&mt('[_1] parts', $resource->countParts()).')';
     }      }
   
     my $target;      my $target;
Line 1471  sub render { Line 1472  sub render {
             $navmap = Apache::lonnavmaps::navmap->new();              $navmap = Apache::lonnavmaps::navmap->new();
     if (!defined($navmap)) {      if (!defined($navmap)) {
  # no londer in course   # no londer in course
  return '<font color="red">No course selected</font><br />   return '<font color="red">'.&mt('No course selected').'</font><br />
                         <a href="/adm/roles">Select a course</a><br />';                          <a href="/adm/roles">'.&mt('Select a course').'</a><br />';
     }      }
  }   }
   
Line 2065  In order of increasing complexity and po Line 2066  In order of increasing complexity and po
   
 =over 4  =over 4
   
 =item * C<$navmap-E<gt>getByX>, where X is B<Id>, B<Symb>, B<Url> or B<MapPc>. This provides  =item * C<$navmap-E<gt>getByX>, where X is B<Id>, B<Symb> or B<MapPc> and getResourceByUrl. This provides
     various ways to obtain resource objects, based on various identifiers.      various ways to obtain resource objects, based on various identifiers.
     Use this when you want to request information about one object or       Use this when you want to request information about one object or 
     a handful of resources you already know the identities of, from some      a handful of resources you already know the identities of, from some
     other source. For more about Ids, Symbs, and MapPcs, see the      other source. For more about Ids, Symbs, and MapPcs, see the
     Resource documentation. Note that Url should be a B<last resort>,      Resource documentation. Note that Url should be a B<last resort>,
     not your first choice; it only works when there is only one      not your first choice; it only really works when there is only one
     instance of the resource in the course, which only applies to      instance of the resource in the course, which only applies to
     maps, and even that may change in the future.      maps, and even that may change in the future (see the B<getResourceByUrl>
       documentation for more details.)
   
 =item * C<my @resources = $navmap-E<gt>retrieveResources(args)>. This  =item * C<my @resources = $navmap-E<gt>retrieveResources(args)>. This
     retrieves resources matching some criterion and returns them      retrieves resources matching some criterion and returns them
Line 2265  sub get_user_data { Line 2267  sub get_user_data {
     $self->{RETRIEVED_USER_DATA} = 1;      $self->{RETRIEVED_USER_DATA} = 1;
 }  }
   
   sub get_discussion_data {
       my $self = shift;
       if ($self->{RETRIEVED_DISCUSSION_DATA}) {
    return $self->{DISCUSSION_DATA};
       }
   
       $self->generate_email_discuss_status();    
   
       my $cid=$env{'request.course.id'};
       my $cdom=$env{'course.'.$cid.'.domain'};
       my $cnum=$env{'course.'.$cid.'.num'};
       # Retrieve discussion data for resources in course
       my %discussion_data = &Apache::lonnet::dumpstore($cid,$cdom,$cnum);
   
   
       $self->{DISCUSSION_DATA} = \%discussion_data;
       $self->{RETRIEVED_DISCUSSION_DATA} = 1;
       return $self->{DISCUSSION_DATA};
   }
   
   
 # Internal function: Takes a key to look up in the nav hash and implements internal  # Internal function: Takes a key to look up in the nav hash and implements internal
 # memory caching of that key.  # memory caching of that key.
 sub navhash {  sub navhash {
Line 2320  sub hasDiscussion { Line 2343  sub hasDiscussion {
     }      }
 }  }
   
   sub last_post_time {
       my $self = shift;
       my $symb = shift;
       my $ressymb = $self->wrap_symb($symb);
       return $self->{DISCUSSION_TIME}->{$ressymb};
   }
   
   sub unread_discussion {
       my $self = shift;
       my $symb = shift;
   
       $self->get_discussion_data();
   
       my $ressymb = $self->wrap_symb($symb);
       # keys used to store bulletinboard postings use 'unwrapped' symb. 
       my $discsymb = $self->unwrap_symb($ressymb);
       my $version = $self->{DISCUSSION_DATA}{'version:'.$discsymb};
       if (!$version) { return; }
   
       my $prevread = $self->{LAST_READ}{$ressymb};
   
       my $unreadcount = 0;
       my $hiddenflag = 0;
       my $deletedflag = 0;
       my ($hidden,$deleted);
   
       my %subjects;
   
       for (my $id=$version; $id>0; $id--) {
    my $vkeys=$self->{DISCUSSION_DATA}{$id.':keys:'.$discsymb};
    my @keys=split(/:/,$vkeys);
    if (grep(/^hidden$/ ,@keys)) {
       if (!$hiddenflag) {
    $hidden = $self->{DISCUSSION_DATA}{$id.':'.$discsymb.':hidden'};
    $hiddenflag = 1;
       }
    } elsif (grep(/^deleted$/,@keys)) {
       if (!$deletedflag) {
    $deleted = $self->{DISCUSSION_DATA}{$id.':'.$discsymb.':deleted'};
    $deletedflag = 1;
       }
    } else {
       if (($hidden !~/\.$id\./) && ($deleted !~/\.$id\./)
    && $prevread < $self->{DISCUSSION_DATA}{$id.':'.$discsymb.':timestamp'}) {
       $unreadcount++;
       $subjects{$unreadcount}=
    $id.': '.$self->{DISCUSSION_DATA}{$id.':'.$discsymb.':subject'};
    }
    }
       }
       if (wantarray) {
    return ($unreadcount,\%subjects);
       }
       return $unreadcount
   }
   
 sub wrap_symb {  sub wrap_symb {
     my $self = shift;      my $self = shift;
     my $symb = shift;      my $symb = shift;
     if ($symb =~ m-___(adm/\w+/\w+/)(\d+)(/bulletinboard)$-) {      if ($symb =~ m-___(adm/[^/]+/[^/]+/)(\d+)(/bulletinboard)$-) {
         unless ($symb =~ m|adm/wrapper/adm|) {          unless ($symb =~ m|adm/wrapper/adm|) {
             $symb = 'bulletin___'.$2.'___adm/wrapper/'.$1.$2.$3;              $symb = 'bulletin___'.$2.'___adm/wrapper/'.$1.$2.$3;
         }          }
Line 2331  sub wrap_symb { Line 2410  sub wrap_symb {
     return $symb;      return $symb;
 }  }
   
   sub unwrap_symb {
       my $self = shift;
       my $ressymb = shift;
       my $discsymb = $ressymb;
       if ($ressymb =~ m-^(bulletin___\d+___)adm/wrapper/(adm/[^/]+/[^/]+/\d+/bulletinboard)$-) {
            $discsymb = $1.$2;
       }
       return $discsymb;
   }
   
 # Private method: Does the given resource (as a symb string) have  # Private method: Does the given resource (as a symb string) have
 # current feedback? Returns the string in the feedback hash, which  # current feedback? Returns the string in the feedback hash, which
 # will be false if it does not exist.  # will be false if it does not exist.
Line 2578  sub parmval_real { Line 2667  sub parmval_real {
   
 =pod  =pod
   
 =item * B<getResourceByUrl>(url):  =item * B<getResourceByUrl>(url,multiple):
   
 Retrieves a resource object by URL of the resource. If passed a  Retrieves a resource object by URL of the resource, unless the optional
 resource object, it will simply return it, so it is safe to use this  multiple parameter is included in wahich caes an array of resource 
 method in code like "$res = $navmap->getResourceByUrl($res)", if  objects is returned. If passed a resource object, it will simply return  
 you're not sure if $res is already an object, or just a URL. If the  it, so it is safe to use this method in code like
 resource appears multiple times in the course, only the first instance  "$res = $navmap->getResourceByUrl($res)"
 will be returned. As a result, this is probably useful only for maps.  if you're not sure if $res is already an object, or just a URL. If the
   resource appears multiple times in the course, only the first instance 
   will be returned (useful for maps), unless the multiple parameter has
   been included, in which case all instances are returned in an array.
   
 =item * B<retrieveResources>(map, filterFunc, recursive, bailout, showall):  =item * B<retrieveResources>(map, filterFunc, recursive, bailout, showall):
   
Line 2620  Convience method for Line 2712  Convience method for
 which will tell whether the map has resources matching the description  which will tell whether the map has resources matching the description
 in the filter function.  in the filter function.
   
   =item * B<usedVersion>(url):
   
   Retrieves version infomation for a url. Returns the version (a number, or 
   the string "mostrecent") for resources which have version information in  
   the big hash.
       
 =cut  =cut
   
   
 sub getResourceByUrl {  sub getResourceByUrl {
     my $self = shift;      my $self = shift;
     my $resUrl = shift;      my $resUrl = shift;
       my $multiple = shift;
   
     if (ref($resUrl)) { return $resUrl; }      if (ref($resUrl)) { return $resUrl; }
   
     $resUrl = &Apache::lonnet::clutter($resUrl);      $resUrl = &Apache::lonnet::clutter($resUrl);
     my $resId = $self->{NAV_HASH}->{'ids_' . $resUrl};      my $resId = $self->{NAV_HASH}->{'ids_' . $resUrl};
     if ($resId =~ /,/) {  
         $resId = (split (/,/, $resId))[0];  
     }  
     if (!$resId) { return ''; }      if (!$resId) { return ''; }
     return $self->getById($resId);      if ($multiple) {
           my @resources = ();
           my @resIds = split (/,/, $resId);
           foreach my $id (@resIds) {
               my $resourceId = $self->getById($id);
               if ($resourceId) { 
                   push(@resources,$resourceId);
               }
           }
           return @resources;
       } else {
           if ($resId =~ /,/) {
               $resId = (split (/,/, $resId))[0];
           }
           return $self->getById($resId);
       }
 }  }
   
 sub retrieveResources {  sub retrieveResources {
Line 2703  sub hasResource { Line 2814  sub hasResource {
     return scalar($self->retrieveResources($map, $filterFunc, $recursive, 1, $showall)) > 0;      return scalar($self->retrieveResources($map, $filterFunc, $recursive, 1, $showall)) > 0;
 }  }
   
   sub usedVersion {
       my $self = shift;
       my $linkurl = shift;
       return $self->navhash("version_$linkurl");
   }
   
 1;  1;
   
 package Apache::lonnavmaps::iterator;  package Apache::lonnavmaps::iterator;
 use WeakRef;  use Scalar::Util qw(weaken);
 use Apache::lonnet;  use Apache::lonnet;
   
 =pod  =pod
Line 3187  sub populateStack { Line 3304  sub populateStack {
 1;  1;
   
 package Apache::lonnavmaps::DFSiterator;  package Apache::lonnavmaps::DFSiterator;
 use WeakRef;  use Scalar::Util qw(weaken);
 use Apache::lonnet;  use Apache::lonnet;
   
 # Not documented in the perldoc: This is a simple iterator that just walks  # Not documented in the perldoc: This is a simple iterator that just walks
Line 3371  sub populateStack { Line 3488  sub populateStack {
 1;  1;
   
 package Apache::lonnavmaps::resource;  package Apache::lonnavmaps::resource;
 use WeakRef;  use Scalar::Util qw(weaken);
 use Apache::lonnet;  use Apache::lonnet;
   
 =pod  =pod
Line 3550  sub kind { my $self=shift; return $self- Line 3667  sub kind { my $self=shift; return $self-
 sub randomout { my $self=shift; return $self->navHash("randomout_", 1); }  sub randomout { my $self=shift; return $self->navHash("randomout_", 1); }
 sub randompick {   sub randompick { 
     my $self = shift;      my $self = shift;
     return $self->{NAV_MAP}->{PARM_HASH}->{$self->symb .      return $self->parmval('randompick');
                                                '.0.parameter_randompick'};  
 }  }
 sub link {  sub link {
     my $self=shift;      my $self=shift;
Line 3609  sub condition { Line 3725  sub condition {
 }  }
 sub condval {  sub condval {
     my $self=shift;      my $self=shift;
     my $uri=&Apache::lonnet::deversion(&Apache::lonnet::declutter($self->src()));      my ($pathname,$filename) = 
     my ($pathname,$filename)=($uri=~m|(.*)/([^/]*)|);   &Apache::lonnet::split_uri_for_cond($self->src());
     $pathname=~s/^adm\/wrapper\///;      
   
     my $match=($env{'acc.res.'.$env{'request.course.id'}.'.'.$pathname}=~      my $match=($env{'acc.res.'.$env{'request.course.id'}.'.'.$pathname}=~
        /\&\Q$filename\E\:([\d\|]+)\&/);         /\&\Q$filename\E\:([\d\|]+)\&/);
Line 3670  sub retrieveResources { Line 3785  sub retrieveResources {
    return $self->{NAV_MAP}->retrieveResources(@_);     return $self->{NAV_MAP}->retrieveResources(@_);
 }  }
   
   sub is_exam {
       my ($self,$part) = @_;
       if ($self->parmval('type',$part) eq 'exam') {
           return 1;
       }
       if ($self->src() =~ /\.(exam)$/) {
           return 1;
       }
       return 0;
   }
 sub is_html {  sub is_html {
     my $self=shift;      my $self=shift;
     my $src = $self->src();      my $src = $self->src();
Line 3682  sub is_page { Line 3807  sub is_page {
     return $self->navHash("is_map_", 1) &&       return $self->navHash("is_map_", 1) && 
  $self->navHash("map_type_" . $self->map_pc()) eq 'page';   $self->navHash("map_type_" . $self->map_pc()) eq 'page';
 }  }
   sub is_practice {
       my $self=shift;
       my ($part) = @_;
       if ($self->parmval('type',$part) eq 'practice') {
           return 1;
       }
       return 0;
   }
 sub is_problem {  sub is_problem {
     my $self=shift;      my $self=shift;
     my $src = $self->src();      my $src = $self->src();
     return ($src =~ /\.(problem|exam|quiz|assess|survey|form|library|task)$/)      if ($src =~ /\.(problem|exam|quiz|assess|survey|form|library|task)$/) {
    return !($self->is_practice());
       }
       return 0;
 }  }
 sub contains_problem {  sub contains_problem {
     my $self=shift;      my $self=shift;
Line 3712  sub is_survey { Line 3848  sub is_survey {
     }      }
     return 0;      return 0;
 }  }
   sub is_task {
       my $self=shift;
       my $src = $self->src();
       return ($src =~ /\.(task)$/)
   }
   
 sub is_empty_sequence {  sub is_empty_sequence {
     my $self=shift;      my $self=shift;
Line 3996  Returns a false value if there has been Line 4137  Returns a false value if there has been
 logged in, true if there has. Always returns false if the discussion  logged in, true if there has. Always returns false if the discussion
 data was not extracted when the nav map was constructed.  data was not extracted when the nav map was constructed.
   
   =item * B<last_post_time>:
   
   Returns a false value if there hasn't been discussion otherwise returns
   unix timestamp of last time a discussion posting (or edit) was made.
   
   =item * B<unread_discussion>:
   
   returns in scalar context the count of the number of unread discussion
   postings
   
   returns in list context both the count of postings and a hash ref
   containing the subjects of all unread postings
   
 =item * B<getFeedback>:  =item * B<getFeedback>:
   
 Gets the feedback for the resource and returns the raw feedback string  Gets the feedback for the resource and returns the raw feedback string
Line 4016  sub hasDiscussion { Line 4170  sub hasDiscussion {
     return $self->{NAV_MAP}->hasDiscussion($self->symb());      return $self->{NAV_MAP}->hasDiscussion($self->symb());
 }  }
   
   sub last_post_time {
       my $self = shift;
       return $self->{NAV_MAP}->last_post_time($self->symb());
   }
   
   sub unread_discussion {
       my $self = shift;
       return $self->{NAV_MAP}->unread_discussion($self->symb());
   }
   
 sub getFeedback {  sub getFeedback {
     my $self = shift;      my $self = shift;
     my $source = $self->src();      my $source = $self->src();
Line 4113  sub countResponses { Line 4277  sub countResponses {
 sub responseTypes {  sub responseTypes {
     my $self = shift;      my $self = shift;
     my %responses;      my %responses;
     foreach my $part ($self->parts()) {      foreach my $part (@{$self->parts()}) {
         foreach my $responsetype ($self->responseType($part)) {          foreach my $responsetype ($self->responseType($part)) {
             $responses{$responsetype}++ if (defined($responsetype));              $responses{$responsetype}++ if (defined($responsetype));
         }          }
Line 4225  sub extractParts { Line 4389  sub extractParts {
         # where the part names begin and end, and even then, it is possible          # where the part names begin and end, and even then, it is possible
         # to construct ambiguous situations.          # to construct ambiguous situations.
         foreach (split /,/, $metadata) {          foreach (split /,/, $metadata) {
             if ($_ =~ /^([a-zA-Z]+)response_(.*)/) {              if ($_ =~ /^([a-zA-Z]+)response_(.*)/
    || $_ =~ /^(Task)_(.*)/) {
                 my $responseType = $1;                  my $responseType = $1;
                 my $partStuff = $2;                  my $partStuff = $2;
                 my $partIdSoFar = '';                  my $partIdSoFar = '';

Removed from v.1.351  
changed lines
  Added in v.1.373


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>