[LON-CAPA-cvs] cvs: loncom(loncapaMITrelate_1) /interface lonfeedback.pm

raeburn raeburn at source.lon-capa.org
Tue Mar 6 20:26:48 EST 2012


raeburn		Wed Mar  7 01:26:48 2012 EDT

  Modified files:              (Branch: loncapaMITrelate_1)
    /loncom/interface	lonfeedback.pm 
  Log:
  - Customization for MITrelate
    - Like/unlike discussion posts.
    - Backport 1.318, 1.319 (part), 1.321 (part), 1.322 (part), 1.323, 1.324 (part),
      1.325, 1.326, 1.330, 1.331 (part), 1.334 (part), 1.337.
  
  
-------------- next part --------------
Index: loncom/interface/lonfeedback.pm
diff -u loncom/interface/lonfeedback.pm:1.290.2.7.2.1 loncom/interface/lonfeedback.pm:1.290.2.7.2.2
--- loncom/interface/lonfeedback.pm:1.290.2.7.2.1	Tue Mar  6 21:24:01 2012
+++ loncom/interface/lonfeedback.pm	Wed Mar  7 01:26:48 2012
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Feedback
 #
-# $Id: lonfeedback.pm,v 1.290.2.7.2.1 2012/03/06 21:24:01 raeburn Exp $
+# $Id: lonfeedback.pm,v 1.290.2.7.2.2 2012/03/07 01:26:48 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -777,6 +777,17 @@
     return $discussion;
 }
 
+sub discussion_link {
+    my ($ressymb,$linktext,$cmd,$item,$flag,$prev,$adds,$title) = @_;
+    my $link = '<a href="/adm/feedback?'.$cmd.'='.&escape($ressymb).':::'.$item;
+    if ($flag) { $link .= '&previous='.$prev; }
+    if ($adds) { $link .= $adds; }
+    $link .= '"';
+    if ($title) { $link .= ' title="'.$title.'"'; }
+    $link .= '>'.$linktext.'</a>';
+    return $link;
+}
+
 sub send_feedback_link {
     my ($ressymb,$target) = @_;
     my $output = '<span class="LC_feedback_link">'.
@@ -933,10 +944,19 @@
     my $skip_group_check = 0;
     my $symb=&Apache::lonenc::check_decrypt($ressymb);
     my $escsymb=&escape($ressymb);
+# These are the discussion contributions
     my %contrib=&Apache::lonnet::restore($symb,$env{'request.course.id'},
 			  $env{'course.'.$env{'request.course.id'}.'.domain'},
 			  $env{'course.'.$env{'request.course.id'}.'.num'});
-
+# And these are the likes/unlikes
+    my %likes=&Apache::lonnet::dump('disclikes',
+                          $env{'course.'.$env{'request.course.id'}.'.domain'},
+                          $env{'course.'.$env{'request.course.id'}.'.num'},
+                          '^'.$symb.':');
+    my $thisuser=$env{'user.name'}.':'.$env{'user.domain'};
+# Array with likes to figure out averages, etc.
+    my @theselikes=();
+# Is the user allowed to see the real name behind anonymous postings?
     my $see_anonymous = 
 	&Apache::lonnet::allowed('rin',$env{'request.course.id'}.($env{'request.course.sec'}?'/'.$env{'request.course.sec'}:''));
 
@@ -966,7 +986,41 @@
             ($skiptest,$roleregexp,$secregexp,$statusregexp) = 
                      &filter_regexp($rolefilter,$sectionpick,$statusfilter);
             $rolematch = $roleregexp.':'.$secregexp.':'.$statusregexp;
-        } 
+        }
+# We need to go through this twice, first to get the likes/dislikes, then to actually build the display
+        for (my $id=1;$id<=$contrib{'version'};$id++) {
+            my $idx=$id;
+            next if ($contrib{$idx.':deleted'});
+            next if ($contrib{$idx.':hidden'});
+            unless ((($hiddens{$idx}) && (!$seeid)) || ($deletions{$idx}) || (!$contrib{$idx.':message'})) {
+                push(@theselikes,$likes{$symb.':'.$idx.':likes'});
+            }
+        }
+# Figure out average likes and standard deviation if there are enough discussions to warrant that
+        my $ave=0;
+        my $stddev=10000;
+        if ($#theselikes>1) {
+            my $sum=0;
+            my $num=$#theselikes+1;
+            foreach my $thislike (@theselikes) {
+                $sum+=$thislike;
+            }
+            $ave=$sum/$num;
+            my $sumsq=0;
+            foreach my $thislike (@theselikes) {
+                $sumsq+=($thislike-$ave)*($thislike-$ave);
+            }
+            $stddev=sqrt($sumsq/$num);
+        }
+# Now we know the average likes $ave and the standard deviation $stddev
+# Get the boundaries for markup
+        my $oneplus=$ave+$stddev;
+        my $twoplus=$ave+2.*$stddev;
+        my $oneminus=$ave-$stddev;
+        my $twominus=$ave-2.*$stddev;
+#
+# This is now the real loop. Go through all entries, pick up what we need
+#
 	for (my $id=1;$id<=$contrib{'version'};$id++) {
 	    my $idx=$id;
             next if ($contrib{$idx.':deleted'});
@@ -1317,8 +1371,41 @@
                                 $$discussionitems[$idx].='<td align="right">  '.
                                   $ctlink.'</td>';
                             }
+# Figure out size based on likes
+                            my $thislikes=$likes{$symb.':'.$idx.':likes'};
+                            my $likesize="100";
+                            if ($thislikes>$twoplus) {
+                                $likesize="200";
+                            } elsif ($thislikes>$oneplus) {
+                                $likesize="150";
+                            }
+                            if ($thislikes<$twominus) {
+                                $likesize="50";
+                            } elsif ($thislikes<$oneminus) {
+                                $likesize="75";
+                            }
+# Actually glue in the message itself
                             $$discussionitems[$idx].= '</tr></table><blockquote>'.
-                                    $message.'</blockquote>';
+                                    "<div style='font-size:$likesize%'>".
+                                    $message.
+                                    '</div></blockquote>';
+# Put in the like and unlike buttons
+                            unless ($likes{$symb.':'.$idx.':likers'}=~/\,\Q$thisuser\E\,/) {
+                                $$discussionitems[$idx].=' '.&discussion_link($symb,'<img border="0" src="/res/adm/pages/thumbsup.png" alt="'.&mt('Like').'" />','like',$idx,$$newpostsflag,$prevread,&group_args($group),&mt("Like this posting"));
+                            } else {
+                                $$discussionitems[$idx].='<img border="0" src="/res/adm/pages/thumbsup_gray.png" alt="'.&mt('You like this posting').'" />';
+                            }
+                            unless ($likes{$symb.':'.$idx.':unlikers'}=~/\,\Q$thisuser\E\,/) {
+                                $$discussionitems[$idx].=' '.&discussion_link($symb,'<img border="0" src="/res/adm/pages/thumbsdown.png" alt="'.&mt('Unlike').'" />','unlike',$idx,$$newpostsflag,$prevread,&group_args($group),&mt("Unlike this posting"));
+                            } else {
+                                $$discussionitems[$idx].='<img border="0" src="/res/adm/pages/thumbsdown_gray.png" alt="'.&mt('You unlike this posting').'" />';
+                            }
+                            my $thislikes=$likes{$symb.':'.$idx.':likes'};
+                            if ($thislikes>0) {
+                                $$discussionitems[$idx].=' ('.&mt("[_1] likes",$thislikes).')';
+                            } elsif ($thislikes<0) {
+                                $$discussionitems[$idx].=' ('.&mt("[_1] unlikes",abs($thislikes)).')';
+                            }
                             if ($contrib{$idx.':history'}) {
                                 my @postversions = ();
                                 $$discussionitems[$idx] .= &mt('This post has been edited by the author.');
@@ -2855,6 +2942,26 @@
     return ($status,$sendsomething);
 }
 
+# Store feedback "likes"
+
+sub storefeedbacklikes {
+    my ($likes,$uname,$udom,$course)=@_;
+    unless ($likes) { $likes=0; }
+    if ($likes>0) { $likes=1; }
+    if ($likes<0) { $likes=-1; }
+    unless ($uname) { $uname=$env{'user.name'}; }
+    unless ($udom)  { $udom=$env{'user.domain'}; }
+    unless ($course) { $course=$env{'request.course.id'}; }
+    my %record=&getfeedbackrecords($uname,$udom,$course);
+    my $totallikes=$record{'totallikes'};
+    $totallikes+=$likes;
+    my %newrecord=('likes_user'   => $env{'user.name'},
+                   'likes_domain' => $env{'user.domain'},
+                   'likes' => $likes,
+                   'totallikes' => $totallikes);
+    return &Apache::lonnet::cstore(\%newrecord,'_feedback',$course,$udom,$uname);
+}
+
 sub adddiscuss {
     my ($symb,$email,$anon,$attachmenturl,$subject,$group)=@_;
     my $status='';
@@ -2953,7 +3060,7 @@
                      $env{'course.'.$env{'request.course.id'}.'.domain'},
 		     $env{'course.'.$env{'request.course.id'}.'.num'});
     }
-    my %record=&Apache::lonnet::restore('_discussion');
+    my %record=&getdiscussionrecords();
     my ($temp)=keys(%record);
     unless ($temp=~/^error\:/) {
        my %newrecord=();
@@ -2968,6 +3075,41 @@
     return $status.'<br />';   
 }
 
+# Routine to get the complete discussion records
+
+sub getdiscussionrecords {
+    my ($uname,$udom,$course)=@_;
+    unless ($uname) { $uname=$env{'user.name'}; }
+    unless ($udom)  { $udom=$env{'user.domain'}; }
+    unless ($course) { $course=$env{'request.course.id'}; }
+    my %record=&Apache::lonnet::restore('_discussion',$course,$udom,$uname);
+    return %record;
+}
+
+# Store discussion "likes"
+
+sub storediscussionlikes {
+    my ($likes,$uname,$udom,$course)=@_;
+    unless ($likes) { $likes=0; }
+    if ($likes>0) { $likes=1; }
+    if ($likes<0) { $likes=-1; }
+    unless ($uname) { $uname=$env{'user.name'}; }
+    unless ($udom)  { $udom=$env{'user.domain'}; }
+    unless ($course) { $course=$env{'request.course.id'}; }
+    my %record=&getdiscussionrecords($uname,$udom,$course);
+    my $totallikes=$record{'totallikes'};
+    my $totalvotes=$record{'totalvotes'};
+    $totallikes+=$likes;
+    $totalvotes++;
+    my %newrecord=('likes_user'   => $env{'user.name'},
+                   'likes_domain' => $env{'user.domain'},
+                   'likes' => $likes,
+                   'totallikes' => $totallikes,
+                   'totalvotes' => $totalvotes);
+    my $status=&Apache::lonnet::cstore(\%newrecord,'_discussion',$course,$udom,$uname);
+    return $status;
+}
+
 sub get_discussion_info {
     my ($idx,%contrib) = @_;
     my $changelast = 0;
@@ -3494,7 +3636,7 @@
 # --------------------------- Get query string for limited number of parameters
 
   &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
-         ['hide','unhide','deldisc','postdata','preview','replydisc','editdisc','cmd','symb','onlyunread','allposts','onlyunmark','previous','markread','markonread','markondisp','toggoff','toggon','modifydisp','changes','navtime','navmaps','navurl','sortposts','applysort','rolefilter','statusfilter','sectionpick','groupick','posterlist','userpick','attach','origpage','currnewattach','deloldattach','keepold','allversions','export','sendmessageonly','group','ref']);
+         ['like','unlike','hide','unhide','deldisc','postdata','preview','replydisc','editdisc','cmd','symb','onlyunread','allposts','onlyunmark','previous','markread','markonread','markondisp','toggoff','toggon','modifydisp','changes','navtime','navmaps','navurl','sortposts','applysort','rolefilter','statusfilter','sectionpick','groupick','posterlist','userpick','attach','origpage','currnewattach','deloldattach','keepold','allversions','export','sendmessageonly','group','ref']);
   my $group = $env{'form.group'};
   my %attachmax = (
                     text => &mt('(128 KB max size)'),
@@ -3772,6 +3914,81 @@
 		     '0','0','','',$env{'form.previous'},undef,undef,undef,
                      undef,undef,undef,$group);
       return OK;
+  } elsif (($env{'form.like'}) || ($env{'form.unlike'})) {
+# ----------------------------------------------------------------- Like/unlike
+      my $entry=$env{'form.like'}?$env{'form.like'}:$env{'form.unlike'};
+      my ($symb,$idx)=split(/\:\:\:/,$entry);
+      ($symb,my $feedurl)=&get_feedurl_and_clean_symb($symb);
+#
+# Likes and unlikes are in db-file "disclikes" of the course
+# The prefix is the $symb to identify the resource discussion,
+# and the $idx to identify the entry
+#
+      my $prefix=$symb.':'.$idx.':';
+      my %contrib=&Apache::lonnet::dump('disclikes',
+                                        $env{'course.'.$env{'request.course.id'}.'.domain'},
+                                        $env{'course.'.$env{'request.course.id'}.'.num'},
+                                        '^'.$prefix);
+# Get all who like or unlike this
+      my $currentlikers=$contrib{$prefix.'likers'};
+      my $currentunlikers=$contrib{$prefix.'unlikers'};
+# Get the current "likes" count
+      my $likes=$contrib{$prefix.'likes'};
+# Find out if they already voted
+# Users cannot like a post twice, or unlike it twice. They can change their mind, though
+      my $alreadyflag=0;
+      my $thisuser=$env{'user.name'}.':'.$env{'user.domain'};
+      if ($env{'form.like'}) {
+          if ($currentlikers=~/\,\Q$thisuser\E\,/) {
+              $alreadyflag=1;
+          } else {
+              if ($currentunlikers=~/\,\Q$thisuser\E\,/) {
+                  $currentunlikers=~s/\,\Q$thisuser\E\,//g;
+              } else {
+                  $currentlikers.=','.$thisuser.',';
+              }
+              $likes++;
+          }
+      } else {
+          if ($currentunlikers=~/\,\Q$thisuser\E\,/) {
+              $alreadyflag=1;
+          } else {
+              if ($currentlikers=~/\,\Q$thisuser\E\,/) {
+                  $currentlikers=~s/\,\Q$thisuser\E\,//g;
+              } else {
+                  $currentunlikers.=','.$thisuser.',';
+              }
+              $likes--;
+          }
+      }
+      my $result;
+# $alreadyflag would be 1 if they tried to double-like or double-unlike
+      unless ($alreadyflag) {
+          my %newhash=($prefix.'likes'    => $likes,
+                       $prefix.'likers'   => $currentlikers,
+                       $prefix.'unlikers' => $currentunlikers);
+# Store data in db-file "disclikes"
+          if (&Apache::lonnet::put('disclikes',
+                                   \%newhash,
+                                   $env{'course.'.$env{'request.course.id'}.'.domain'},
+                                   $env{'course.'.$env{'request.course.id'}.'.num'}) eq 'ok') {
+# Also store with the person who posted the liked/unliked entry
+              if ($env{'form.like'}) {
+                  &storediscussionlikes(1,$contrib{$idx.':sendername'},$contrib{$idx.':senderdomain'});
+                  $result=&mt("Registered 'Like'");
+              } else {
+                  &storediscussionlikes(-1,$contrib{$idx.':sendername'},$contrib{$idx.':senderdomain'});
+                  $result=&mt("Registered 'Unlike'");
+              }
+          } else {
+# Oops, something went wrong
+              $result=&mt("Failed to register vote");
+          }
+      }
+      &redirect_back($r,$feedurl,$result.'<br />',
+                     '0','0','','',$env{'form.previous'},undef,undef,undef,
+                     undef,undef,undef,$group);
+      return OK;
   } elsif ($env{'form.cmd'}=~/^(threadedoff|threadedon)$/) {
       my ($symb,$feedurl)=&get_feedurl_and_clean_symb($env{'form.symb'});
       if ($env{'form.cmd'} eq 'threadedon') {


More information about the LON-CAPA-cvs mailing list