<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[929] sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer: Code Reference: add up/down voting to user contributed notes.</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="http://meta.trac.wordpress.org/changeset/929">929</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"http://meta.trac.wordpress.org/changeset/929","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>coffee2code</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2014-10-23 07:44:26 +0000 (Thu, 23 Oct 2014)</dd>
</dl>
<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Code Reference: add up/down voting to user contributed notes. Fixes <a href="http://meta.trac.wordpress.org/ticket/551">#551</a></pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgdeveloperfunctionsphp">sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/functions.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgdeveloperinctemplatetagsphp">sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/inc/template-tags.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgdeveloperscssmainscss">sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/scss/main.scss</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgdeveloperstylesheetsmaincss">sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/stylesheets/main.css</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgdeveloperincusercontentvotingphp">sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/inc/user-content-voting.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgdeveloperjsusernotesvotingjs">sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/js/user-notes-voting.js</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgdeveloperfunctionsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/functions.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/functions.php 2014-10-23 06:18:52 UTC (rev 928)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/functions.php 2014-10-23 07:44:26 UTC (rev 929)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -41,6 +41,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> require __DIR__ . '/inc/user-content.php';
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Voting for user-submitted content.
+ */
+require __DIR__ . '/inc/user-content-voting.php';
+
+/**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Redirects.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> require __DIR__ . '/inc/redirects.php';
</span></span></pre></div>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgdeveloperinctemplatetagsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/inc/template-tags.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/inc/template-tags.php 2014-10-23 06:18:52 UTC (rev 928)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/inc/template-tags.php 2014-10-23 07:44:26 UTC (rev 929)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -176,6 +176,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> <!-- .comment-content -->
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> <footer class="comment-meta">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ <?php DevHub_User_Submitted_Content_Voting::show_voting(); ?>
</ins><span class="cx" style="display: block; padding: 0 10px"> <div class="comment-author vcard">
</span><span class="cx" style="display: block; padding: 0 10px"> <span class="comment-author-attribution">
</span><span class="cx" style="display: block; padding: 0 10px"> <?php if ( 0 != $args['avatar_size'] ) {
</span></span></pre></div>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgdeveloperincusercontentvotingphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/inc/user-content-voting.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/inc/user-content-voting.php (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/inc/user-content-voting.php 2014-10-23 07:44:26 UTC (rev 929)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,473 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Code Reference voting for user contributed notes.
+ *
+ * Any user can vote once on any user contributed note.
+ *
+ * TODO:
+ * - If a user gets blocked as spam, any vote cast by that user should get removed.
+ *
+ * @package wporg-developer
+ */
+
+/**
+ * Class to handle voting for user contributed notes.
+ */
+class DevHub_User_Contributed_Notes_Voting {
+
+ /**
+ * Meta key name for list of all user IDs that submitted an upvote.
+ *
+ * @var array
+ * @access public
+ */
+ public static $meta_upvotes = 'devhub_up_votes';
+
+ /**
+ * Meta key name for list of all user IDs that submitted a downvote.
+ *
+ * @var array
+ * @access public
+ */
+ public static $meta_downvotes = 'devhub_down_votes';
+
+ /**
+ * Initializer
+ *
+ * @access public
+ */
+ public static function init() {
+ add_action( 'init', array( __CLASS__, 'do_init' ) );
+ }
+
+ /**
+ * Initialization
+ *
+ * @access public
+ */
+ public static function do_init() {
+ // Save a non-AJAX submitted vote.
+ add_action( 'template_redirect', array( __CLASS__, 'vote_submission' ) );
+
+ // Save AJAX submitted vote.
+ add_action( 'wp_ajax_note_vote', array( __CLASS__, 'ajax_vote_submission' ) );
+
+ // Enqueue scripts and styles.
+ add_action( 'wp_enqueue_scripts', array( __CLASS__, 'scripts_and_styles' ), 11 );
+ }
+
+ /**
+ * Enqueues scripts and styles.
+ *
+ * @access public
+ */
+ public static function scripts_and_styles() {
+ // Only need to enqueue voting-related resources if there are comments to vote on.
+ if ( self::user_can_vote() && is_singular() && '0' != get_comments_number() ) {
+ wp_register_script( 'wporg-developer-user-notes-voting', get_template_directory_uri() . '/js/user-notes-voting.js', array(), '20141022', true );
+ wp_localize_script( 'wporg-developer-user-notes-voting', 'ajaxurl', admin_url( 'admin-ajax.php' ) );
+ wp_enqueue_script( 'wporg-developer-user-notes-voting' );
+ }
+ }
+
+ /**
+ * Handles vote submission.
+ *
+ * @access public
+ *
+ * @return bool True if vote resulted in success or a change.
+ */
+ public static function vote_submission( $redirect = true ) {
+ $success = false;
+
+ if ( isset( $_REQUEST['comment'] ) && $_REQUEST['comment']
+ && isset( $_REQUEST['vote'] ) && $_REQUEST['vote'] && in_array( $_REQUEST['vote'], array( 'down', 'up' ) )
+ && isset( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'user-note-vote-' . $_REQUEST['comment'] )
+ && self::user_can_vote( get_current_user_id(), $_REQUEST['comment'] )
+ ) {
+ $success = ( 'down' == $_REQUEST['vote'] ) ?
+ self::vote_down( (int) $_REQUEST['comment'], get_current_user_id() ) :
+ self::vote_up( (int) $_REQUEST['comment'], get_current_user_id() );
+
+ // Redirect user back to comment unless this was an AJAX request.
+ if ( ! isset( $_REQUEST['is_ajax'] ) ) {
+ wp_redirect( get_comment_link( $_REQUEST['comment'] ) );
+ exit();
+ }
+
+ }
+
+ return $success;
+ }
+
+ /**
+ * Handles AJAX vote submission.
+ *
+ * @access public
+ *
+ * @return int|string Returns 0 on error or no change; else the markup to be used to replace .user-note-voting
+ */
+ public static function ajax_vote_submission() {
+ check_ajax_referer( 'user-note-vote-' . $_POST['comment'], $_POST['_wpnonce'] );
+
+ $_REQUEST['is_ajax'] = true;
+ // If voting succeeded and resulted in a change, send back full replacement
+ // markup.
+ if ( self::vote_submission( false ) ) {
+ self::show_voting( (int) $_POST['comment'] );
+ die();
+ }
+ die( 0 );
+ }
+
+ /**
+ * Returns the list of upvotes for a comment.
+ *
+ * @access public
+ *
+ * @param int $comment_id The comment ID.
+ * @return array
+ */
+ public static function get_comment_upvotes( $comment_id ) {
+ return self::get_comment_votes( $comment_id, self::$meta_upvotes );
+ }
+
+ /**
+ * Returns the list of downvotes for a comment.
+ *
+ * @access public
+ *
+ * @param int $comment_id The comment ID.
+ * @return array
+ */
+ public static function get_comment_downvotes( $comment_id ) {
+ return self::get_comment_votes( $comment_id, self::$meta_downvotes );
+ }
+
+ /**
+ * Returns the list of vote for a specific vote type for a comment.
+ *
+ * @access protected
+ *
+ * @param int $comment_id The comment ID.
+ * @param string $field
+ * @return array
+ */
+ protected static function get_comment_votes( $comment_id, $field ) {
+ $votes = get_comment_meta( $comment_id, $field, true );
+
+ if ( ! $votes ) {
+ $votes = array();
+ }
+
+ return $votes;
+ }
+
+ /**
+ * Determines if the user can vote on user contributed notes.
+ *
+ * By default, the only requirements are:
+ * - the user is logged in.
+ * - the comment must be approvedUse the
+ * filter 'devhub_user_can_vote' to configure custom permissions for the
+ * user and/or the comment.
+ *
+ * @access public
+ *
+ * @param int $user_id Optional. The user ID. If not defined, assumes current user.
+ * @param int $comment_id Optional. The comment ID. If not defined, assumes being able to comment generally.
+ * @return bool True if the user can vote.
+ */
+ public static function user_can_vote( $user_id = '', $comment_id = '' ) {
+ // If no user specified, assume current user.
+ if ( ! $user_id ) {
+ $user_id = get_current_user_id();
+ }
+
+ // Must be a user to vote.
+ if ( ! $user_id ) {
+ return false;
+ }
+
+ $can = true;
+
+ // Comment, if provided, must be approved.
+ if ( $comment_id ) {
+ $can = ( '1' == get_comment( $comment_id )->comment_approved );
+ }
+
+ return apply_filters( 'devhub_user_can_vote', $can, $user_id, $comment_id );
+ }
+
+ /**
+ * Has user upvoted the comment?
+ *
+ * @access public
+ *
+ * @param int $comment_id The comment ID
+ * @param int $user_id Optional. The user ID. If not defined, assumes current user.
+ * @return bool True if the user has upvoted the comment.
+ */
+ public static function has_user_upvoted_comment( $comment_id, $user_id = '' ) {
+ // If no user specified, assume current user.
+ if ( ! $user_id ) {
+ $user_id = get_current_user_id();
+ }
+
+ // Must be logged in to have voted.
+ if ( ! $user_id ) {
+ return false;
+ }
+
+ $upvotes = self::get_comment_upvotes( $comment_id );
+
+ return in_array( $user_id, $upvotes );
+ }
+
+ /**
+ * Has user downvoted the comment?
+ *
+ * @access public
+ *
+ * @param int $comment_id The comment ID
+ * @param int $user_id Optional. The user ID. If not defined, assumes current user.
+ * @return bool True if the user has downvoted the comment.
+ */
+ public static function has_user_downvoted_comment( $comment_id, $user_id = '' ) {
+ // If no user specified, assume current user.
+ if ( ! $user_id ) {
+ $user_id = get_current_user_id();
+ }
+
+ // Must be logged in to have voted.
+ if ( ! $user_id ) {
+ return false;
+ }
+
+ $downvotes = self::get_comment_downvotes( $comment_id );
+
+ return in_array( $user_id, $downvotes );
+ }
+
+ /**
+ * Outputs the voting markup for user contributed note.
+ *
+ * @access public
+ *
+ * @param int $comment_id The comment ID, or empty to use current comment.
+ */
+ public static function show_voting( $comment_id = '') {
+ if ( ! $comment_id ) {
+ global $comment;
+ $comment_id = $comment->comment_ID;
+ }
+
+ $can_vote = self::user_can_vote( get_current_user_id(), $comment_id );
+ $comment_link = get_comment_link( $comment_id );
+ $nonce = wp_create_nonce( 'user-note-vote-' . $comment_id );
+
+ echo '<div class="user-note-voting" data-nonce="' . esc_attr( $nonce ) . '">';
+
+ // Up vote link
+ $user_upvoted = self::has_user_upvoted_comment( $comment_id );
+ if ( $can_vote ) {
+ $title = $user_upvoted ?
+ __( 'You have voted to indicate this note was helpful', 'wporg' ) :
+ __( 'Vote up if this note was helpful', 'wporg' );
+ $tag = $user_upvoted ? 'span' : 'a';
+ } else {
+ $title = ! is_user_logged_in() ?
+ __( 'You must log in to vote on the helpfulness of this note', 'wporg' ) :
+ '';
+ $tag = 'span';
+ }
+ echo "<{$tag} "
+ . 'class="user-note-voting-up' . ( $user_upvoted ? ' user-voted' : '' )
+ . '" title="' . esc_attr( $title )
+ . '" data-id="' . esc_attr( $comment_id )
+ . '" data-vote="up';
+ if ( ! $user_upvoted ) {
+ echo '" href="'
+ . esc_url( add_query_arg( array( '_wpnonce' => $nonce , 'comment' => $comment_id, 'vote' => 'up' ), $comment_link ) );
+ }
+ echo '">';
+ echo '<span class="dashicons dashicons-arrow-up"></span>';
+ echo "</{$tag}>";
+
+ // Total count
+ // Don't indicate a like percentage if no one voted.
+ $title = ( 0 == self::count_votes( $comment_id, 'total' ) ) ?
+ '' :
+ sprintf( __( '%s like this', 'wporg' ), self::count_votes( $comment_id, 'like_percentage' ) . '%' );
+ $class = '';
+ echo '<span '
+ . 'class="user-note-voting-count ' . esc_attr( $class ) . '" '
+ . 'title="' . esc_attr( $title ) . '">'
+ . self::count_votes( $comment_id, 'difference' )
+ . '</span>';
+
+ // Down vote link
+ $user_downvoted = ( $user_upvoted ? false : self::has_user_downvoted_comment( $comment_id ) );
+ if ( $can_vote ) {
+ $title = $user_downvoted ?
+ __( 'You have voted to indicate this note was not helpful', 'wporg' ) :
+ __( 'Vote down if this note was not helpful', 'wporg' );
+ $tag = $user_downvoted ? 'span' : 'a';
+ } else {
+ $title = ! is_user_logged_in() ?
+ __( 'You must log in to vote on the helpfulness of this note', 'wporg' ) :
+ '';
+ $tag = 'span';
+ }
+ echo "<{$tag} "
+ . 'class="user-note-voting-down' . ( $user_downvoted ? ' user-voted' : '' )
+ . '" title="' . esc_attr( $title )
+ . '" data-id="' . esc_attr( $comment_id )
+ . '" data-vote="down';
+ if ( ! $user_downvoted ) {
+ echo '" href="'
+ . esc_url( add_query_arg( array( '_wpnonce' => $nonce , 'comment' => $comment_id, 'vote' => 'down' ), $comment_link ) );
+ }
+ echo '">';
+ echo '<span class="dashicons dashicons-arrow-down"></span>';
+ echo "</{$tag}>";
+
+ echo '</div>';
+ }
+
+ /**
+ * Returns a count relating to the voting.
+ *
+ * Supported $type values:
+ * 'up' : The total number of upvotes
+ * 'down' : The total number of downvotes
+ * 'total' : The total number of votes (upvotes + downvotes)
+ * 'difference' : The difference between upvotes and downvotes (upvotes - downvotes)
+ * 'like_percentage' : The percentage of total votes that upvoted
+ *
+ * @access public
+ *
+ * @param string $type The type of count to return.
+ * @return int The requested count.
+ */
+ public static function count_votes( $comment_id, $type ) {
+ // The 'up' count is needed in all cases except for 'down'.
+ if ( 'down' != $type ) {
+ $up = count( self::get_comment_upvotes( $comment_id ) );
+ }
+ // The 'down' count is needed in all cases except for 'up'.
+ if ( 'up' != $type ) {
+ $down = count( self::get_comment_downvotes( $comment_id ) );
+ }
+
+ switch ( $type ) {
+ case 'up':
+ return $up;
+ case 'down':
+ return $down;
+ case 'total':
+ return $up + $down;
+ case 'difference':
+ return $up - $down;
+ case 'like_percentage':
+ $total = $up + $down;
+ // If no votes have been cast, return 0 to avoid dividing by 0.
+ if ( 0 == $total ) {
+ return 0;
+ }
+ // More precise, and floatval() will drop ".00" when present
+ //return floatval( round( ( $up / $total ) * 100, 2 ) );
+ // Less precise; rounds to nearest integer
+ return round( ( $up / $total ) * 100 );
+ }
+ }
+
+ /**
+ * Records an up vote.
+ *
+ * @access public
+ *
+ * @param int $comment_id The comment ID
+ * @param int $user_id Optional. The user ID. Default is current user.
+ * @return bool Whether the up vote succeed (a new vote or a change in vote).
+ */
+ public static function vote_up( $comment_id, $user_id = '' ) {
+ return self::vote_handler( $comment_id, $user_id, 'up' );
+ }
+
+ /**
+ * Records a down vote.
+ *
+ * @access public
+ *
+ * @param int $comment_id The comment ID
+ * @param int $user_id Optional. The user ID. Default is current user.
+ * @return bool Whether the down vote succeed (a new vote or a change in vote).
+ */
+ public static function vote_down( $comment_id, $user_id = '' ) {
+ return self::vote_handler( $comment_id, $user_id, 'down' );
+ }
+
+ /**
+ * Handles abstraction between an up or down vote.
+ *
+ * @access protected
+ *
+ * @param int $comment_id The comment ID
+ * @param int $user_id Optional. The user ID. Default is current user.
+ * @param string $type Optional. 'up' for an up vote, 'down' for a down vote. Default is 'up'.
+ * @return bool Whether the vote succeed (a new vote or a change in vote).
+ */
+ protected static function vote_handler( $comment_id, $user_id = '', $type = 'up' ) {
+ if ( ! $user_id ) {
+ $user_id = get_current_user_id();
+ }
+
+ // See if the user can vote on this comment.
+ $votable = self::user_can_vote( $user_id, $comment_id );
+
+ if ( ! $votable ) {
+ return false;
+ }
+
+ // The difference between an up vote and a down vote is which meta list their
+ // vote was recorded in.
+ if ( 'up' == $type ) {
+ $add_to = self::$meta_upvotes;
+ $remove_from = self::$meta_downvotes;
+ } else {
+ $add_to = self::$meta_downvotes;
+ $remove_from = self::$meta_upvotes;
+ }
+
+ // Get list of people who cast the same vote.
+ $add_to_list = get_comment_meta( $comment_id, $add_to, true );
+
+ // Don't do anything if user is recasting the same vote as before.
+ if ( in_array( $user_id, (array) $add_to_list ) ) {
+ return false;
+ }
+
+ // If the user had previously cast the opposite vote, undo that older vote.
+ $remove_from_list = (array) get_comment_meta( $comment_id, $remove_from, true );
+ if ( in_array( $user_id, $remove_from_list ) ) {
+ unset( $remove_from_list[ array_search( $user_id, $remove_from_list ) ] );
+ update_comment_meta( $comment_id, $remove_from, $remove_from_list );
+ }
+
+ // Add user to the list of people casting the identical vote.
+ if ( $add_to_list ) {
+ $add_to_list[] = $user_id;
+ } else {
+ $add_to_list = array( $user_id );
+ }
+ update_comment_meta( $comment_id, $add_to, $add_to_list );
+
+ // TODO: Store some value (the like_percentage perhaps) in comment_karma so it can be custom sorted?
+
+ return true;
+ }
+
+} // DevHub_User_Contributed_Notes_Voting
+
+DevHub_User_Contributed_Notes_Voting::init();
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/inc/user-content-voting.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgdeveloperjsusernotesvotingjs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/js/user-notes-voting.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/js/user-notes-voting.js (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/js/user-notes-voting.js 2014-10-23 07:44:26 UTC (rev 929)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,25 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/**
+ * Dynamic functionality for voting on user submitted notes.
+ *
+ */
+
+( function( $ ) {
+ $( '.user-note-voting a' ).on( 'click', function(e) {
+ e.preventDefault();
+
+ var item = $(this);
+
+ $.post(ajaxurl, {
+ action: "note_vote",
+ comment: $(this).attr('data-id'),
+ vote: $(this).attr('data-vote'),
+ _wpnonce: $(this).parent().attr('data-nonce')
+ }, function(data) {
+ if ("0" != data) {
+ item.closest('.user-note-voting').replaceWith(data);
+ }
+ }, "text"
+ );
+ return false;
+ });
+} )( jQuery );
</ins></span></pre></div>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgdeveloperscssmainscss"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/scss/main.scss</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/scss/main.scss 2014-10-23 06:18:52 UTC (rev 928)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/scss/main.scss 2014-10-23 07:44:26 UTC (rev 929)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1203,6 +1203,35 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ .comment-author {
+ float: left;
+ }
+ .user-note-voting {
+ font-size: 1.5em;
+ clear: left;
+ float: left;
+ margin-top: -5px;
+ margin-right: 10px;
+ }
+ .user-note-voting-up .dashicons, .user-note-voting-down .dashicons {
+ font-size: 30px;
+ height: 30px;
+ width: 30px;
+ color: #000;
+ }
+ .user-note-voting-up {
+ margin-left: -9px;
+ }
+ .user-note-voting-count {
+ margin-right: -2px;
+ }
+ .user-voted.user-note-voting-up .dashicons {
+ color: green;
+ }
+ .user-voted.user-note-voting-down .dashicons {
+ color: red;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> @media ( max-width: 59.999999em ) {
</span></span></pre></div>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgdeveloperstylesheetsmaincss"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/stylesheets/main.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/stylesheets/main.css 2014-10-23 06:18:52 UTC (rev 928)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-developer/stylesheets/main.css 2014-10-23 07:44:26 UTC (rev 929)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1331,6 +1331,34 @@
</span><span class="cx" style="display: block; padding: 0 10px"> .devhub-wrap ul.items li a {
</span><span class="cx" style="display: block; padding: 0 10px"> color: #555 !important;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+.devhub-wrap .comment-author {
+ float: left;
+}
+.devhub-wrap .user-note-voting {
+ font-size: 1.5em;
+ clear: left;
+ float: left;
+ margin-top: -5px;
+ margin-right: 10px;
+}
+.devhub-wrap .user-note-voting-up .dashicons, .devhub-wrap .user-note-voting-down .dashicons {
+ font-size: 30px;
+ height: 30px;
+ width: 30px;
+ color: #000;
+}
+.devhub-wrap .user-note-voting-up {
+ margin-left: -9px;
+}
+.devhub-wrap .user-note-voting-count {
+ margin-right: -2px;
+}
+.devhub-wrap .user-voted.user-note-voting-up .dashicons {
+ color: green;
+}
+.devhub-wrap .user-voted.user-note-voting-down .dashicons {
+ color: red;
+}
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> @media (max-width: 60em) {
</span><span class="cx" style="display: block; padding: 0 10px"> .devhub-wrap {
</span></span></pre>
</div>
</div>
</body>
</html>