'admin/settings/karma', 'title' => t('karma'), 'callback' => 'drupal_get_form', 'callback arguments' => array('karma_admin_settings'), 'access' => user_access('administer comments'), 'type' => MENU_NORMAL_ITEM, ); if ($may_cache) { $items[] = array( 'path' => 'karma', 'title' => t('ratings'), 'callback' => 'karma_ratings_page', 'callback arguments' => array('karma_ratings_page'), 'access' => user_access('access comments'), 'type' => MENU_NORMAL_ITEM, ); $items[] = array( 'path' => 'karma/rate_js', 'callback' => 'karma_rate_js', 'access' => user_access('access comments'), 'type' => MENU_CALLBACK, ); } return $items; } function karma_admin_settings(){ $form = array(); $form['karma_minimum_rating'] = array( '#type' => 'select', '#title' => t('Minimum rating for displayed comments'), '#options' => array('0.0' => t('Show all comments')) + drupal_map_assoc(array('0.5', '1.0', '1.5', '2.0')), '#default_value' => variable_get('karma_minimum_rating', '0.0'), '#description' => t('Trusted users may choose to view comments with low ratings.'), ); $form['karma_trusted_karma'] = array( '#type' => 'select', '#title' => t('Minimum rating for trusted users'), '#options' => drupal_map_assoc(array('2.5', '3.0', '3.5')), '#default_value' => variable_get('karma_trusted_karma', '3.5'), '#description' => t('Trusted users may view low-rated comments.'), ); $karma_rating_titles = variable_get('karma_rating_titles', array()); $form['karma_rating_titles'] = array( '#type' => 'fieldset', '#title' => t('Rating titles'), '#tree' => TRUE, ); foreach (range(0, 5) as $rating) { $form['karma_rating_titles'][$rating] = array( '#type' => 'textfield', '#title' => t('Title for %rating', array('%rating' => $rating)), '#default_value' => $karma_rating_titles[$rating], ); } $form['karma_selector_type'] = array( '#type' => 'radios', '#title' => t('Selector type'), '#options' => array('select' => t('Drop down selection'), 'stars' => t('Stars')), '#default_value' => variable_get('karma_selector_type', 'select'), ); $form['karma_merge_widgets'] = array( '#type' => 'radios', '#title' => t('Rating widget display'), '#options' => array( 'normal' => t('Separate average rating and rating selection'), 'merged' => t('Show average rating on rating selection'), ), '#default_value' => variable_get('karma_merge_widgets', 'normal'), ); if (variable_get('karma_selector_type', 'select') == 'select') { $form['karma_merge_widgets']['#attributes'] = array('disabled' => 'disabled'); } return system_settings_form($form); } function karma_perm() { return array('rate comments', 'rate posts', 'user is always trusted', 'view user ratings', 'view comment ratings', 'view post ratings'); } /** * Determine if the current user is trusted. Trusted users have a karma above a * configurable threshold. * * @return * TRUE if the current user is trusted. */ function karma_user_is_trusted() { global $user; if (user_access('user is always trusted')) { return TRUE; } karma_user_load($user); if (!is_null($user->karma)) { return $user->karma >= variable_get('karma_trusted_karma', '3.5'); } return FALSE; } /** * Loads the user's karma rating. If karma is already added it will not be loaded again. * * @param $user * The user object to add karma to. */ function karma_user_load(&$user) { if (!isset($user->karma)) { $karma = db_fetch_object(db_query('SELECT karma FROM {karma_users} WHERE uid = %d', $user->uid)); $user->karma = (float) $karma->karma; } } /** * Returns the current user's rating for a comment or post. * * @param $type * Either 'comment' or 'node' * @param $object * A comment or node object. * @return * An integer or, if the user hasn't rated the comment, NULL. */ function karma_get_user_rating($type, $object) { global $user; static $ratings = array( 'comment' => array(), 'node' => array(), ); $id = ($type == 'comment' ? $object->cid : $object->nid); if (!isset($ratings[$type][$object->nid])) { $ratings[$type][$object->nid] = array(); switch ($type) { case 'comment': $result = db_query("SELECT r.id, r.rating FROM {karma_ratings} r LEFT JOIN {comments} c ON r.id = c.cid WHERE r.uid = %d AND c.nid = %d AND r.type = 'cid'", $user->uid, $object->nid); break; case 'node': $result = db_query("SELECT r.id, r.rating FROM {karma_ratings} r WHERE r.uid = %d AND r.id = %d AND r.type = 'nid'", $user->uid, $object->nid); break; } while ($rating = db_fetch_object($result)) { $ratings[$type][$object->nid][$rating->id] = $rating->rating; } } return $ratings[$type][$object->nid][$id]; } /** * Returns information about a comment's or post's rating. * * @param $type * Either 'comment' or 'node' * @param $object * A comment object. * @param $clear * TRUE to clear the internal cache. * @return * A numerically indexed (for use with list()) array containing the comment * rating and the number of users who have rated the comment. */ function karma_get_rating($type, $object, $clear = FALSE) { static $ratings = array( 'comment' => array(), 'node' => array(), ); if ($clear) { $ratings = array( 'comment' => array(), 'node' => array(), ); } if (!isset($ratings[$type][$object->nid])) { $ratings[$type][$object->nid] = array(); switch ($type) { case 'comment': $result = db_query("SELECT k.id, k.rating, k.count FROM {karma_objects} k LEFT JOIN {comments} c ON k.id = c.cid WHERE c.nid = %d AND k.type = 'cid'", $object->nid); break; case 'node': $result = db_query("SELECT k.id, k.rating, k.count FROM {karma_objects} k WHERE k.id = %d AND k.type = 'nid'", $object->nid); break; } while ($rating = db_fetch_object($result)) { $ratings[$type][$object->nid][$type == 'comment' ? $rating->id : 'node'] = array($rating->rating, $rating->count); } } return $ratings[$type][$object->nid][$type == 'comment' ? $object->cid : 'node']; } /** * Updates a user's karma rating. * * The karma calculation is a weighted average of individual comment ratings. * The weight is the number of ratings a comment has recieved multiplied by the * comment number (oldest comment is numbered 1). * * @param $uid * The user's uid. */ function karma_update_user_karma($uid) { if (!$uid) { // The anonymous user does not have karma. return; } $ratings = db_query_range("SELECT k.rating, k.count, GREATEST(c.timestamp, n.created) AS timestamp FROM {karma_objects} k LEFT JOIN {comments} c ON k.type = 'cid' AND k.id = c.cid AND c.uid = %d LEFT JOIN {node} n ON k.type = 'nid' AND k.id = n.nid AND n.uid = %d ORDER BY timestamp DESC, k.rating", $uid, $uid, 0, 30); $comment_num = 1; $sum = 0; $count = 0; while ($rating = db_fetch_object($ratings)) { $sum += $rating->rating * ($rating->count * $comment_num); $count += $rating->count * $comment_num; $comment_num++; } if ($count == 0) { // Users without any rated comments do not have karma. $karma = NULL; } else { $karma = $sum / $count; } // First delete any existing entry, then add the new entry db_query('DELETE FROM {karma_users} WHERE uid = %d', $uid); db_query('INSERT INTO {karma_users} (uid, karma) VALUES (%d, %f)', $uid, $karma); } function karma_comment(&$comment, $op) { if ($op == 'view' && arg(1) != 'reply' && user_access('view comment ratings')) { $rating_form = _karma_rating('comment', $comment); theme('add_style', drupal_get_path('module', 'karma') .'/karma.css'); drupal_add_js(drupal_get_path('module', 'karma') .'/karma.js'); // Display current rating. list($rating, $count) = karma_get_rating('comment', $comment); if (variable_get('karma_selector_type', 'select') == 'stars') { $comment = theme('karma_comment_rating_stars', $comment, (float) $rating, $count, 'karma/comment/'. $comment->cid, $rating_form); } else { $comment = theme('karma_comment_rating', $comment, (float) $rating, $count, 'karma/comment/'. $comment->cid, $rating_form); } } } function karma_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) { switch ($op) { case 'view': if (user_access('view post ratings') && variable_get('karma_enabled_'. $node->type, TRUE)) { $rating_form = _karma_rating('node', $node); theme('add_style', drupal_get_path('module', 'karma') .'/karma.css'); drupal_add_js(drupal_get_path('module', 'karma') .'/karma.js'); // Display current rating. list($rating, $count) = karma_get_rating('node', $node); if (variable_get('karma_selector_type', 'select') == 'stars') { $node = theme('karma_node_rating_stars', $node, (float) $rating, $count, 'karma/node/'. $node->nid, $rating_form); } else { $node = theme('karma_node_rating', $node, (float) $rating, $count, 'karma/node/'. $node->nid, $rating_form); } } break; } } function karma_rate_validate($form_id, $form_values) { global $user; if (!is_numeric($form_values['rating']) || $form_values['rating'] > 5 || $form_values['rating'] < -1) { form_set_error('rating', t('Invalid rating.')); } if ($form_values['rating'] == 0 && !karma_user_is_trusted()) { form_set_error('rating', t('Only trusted users may give a 0 rating.')); } } function _karma_rating_form_submit($form_id, $form_values) { global $user; $type = 'comment'; switch ($form_values['type']) { case 'comment': $id_type = 'cid'; break; case 'node': $id_type = 'nid'; break; } // Remove any existing rating and insert the new rating db_query("DELETE FROM {karma_ratings} WHERE uid = %d AND id = %d AND type = '%s'", $user->uid, $form_values['id'], $id_type); if ($form_values['rating'] != -1) { // -1 is not rated db_query("INSERT INTO {karma_ratings} (uid, id, type, rating) VALUES (%d, %d, '%s', %d)", $user->uid, $form_values['id'], $id_type, $form_values['rating']); } // Update the comment rating db_query("DELETE FROM {karma_objects} WHERE id = %d AND type = '%s'", $form_values['id'], $id_type); db_query("INSERT INTO {karma_objects} (id, type, rating, count) SELECT id, '%s', avg(rating), count(uid) FROM {karma_ratings} WHERE id = %d AND type = '%s' GROUP BY id", $id_type, $form_values['id'], $id_type); if ($id_type = 'cid') { } // Update the comment owner's karma switch ($form_values['type']) { case 'comment': $object = db_fetch_object(db_query('SELECT uid FROM {comments} WHERE cid = %d', $form_values['id'])); break; case 'node': $object = db_fetch_object(db_query('SELECT uid FROM {node} WHERE nid = %d', $form_values['id'])); break; } karma_update_user_karma($object->uid); // todo ?? //drupal_goto('node/'. $comment->nid, NULL, 'comment-'. $comment->cid); return FALSE; } function karma_rate_js($type, $id) { switch ($type) { case 'comment': $object = _comment_load($id); break; case 'node': $object = node_load($id); break; } _karma_rating($type, $object); list($rating, $count) = karma_get_rating($type, $object, TRUE); if (variable_get('karma_selector_type', 'select') == 'stars') { $rating_text = theme('karma_comment_rating_stars_content', (float) $rating, $count, 'karma/'. $type .'/'. $id); } else { $rating_text = theme('karma_comment_rating_text', (float) $rating, $count, 'karma/'. $type .'/'. $id); } switch (variable_get('karma_merge_widgets', 'normal')) { case 'normal': $current_rating = karma_get_user_rating($type, $object); break; case 'merged': $current_rating = $rating; break; } print drupal_to_js(array('status' => TRUE, 'data' => $rating_text, 'current_rating' => $current_rating)); exit; } function _karma_rating($type, $object) { switch ($type) { case 'comment': if (!user_access('rate comments')) { return NULL; } $id = $object->cid; break; case 'node': if (!user_access('rate posts')) { return NULL; } $id = $object->nid; break; } $output = drupal_get_form('_karma_rating_form'. '_'. $type .'_'. $id, $type, $object, $id); return $output; } function _karma_rating_form($type, $object) { global $user; switch ($type) { case 'comment': if (!user_access('rate comments')) { return NULL; } $id = $object->cid; break; case 'node': if (!user_access('rate posts')) { return NULL; } $id = $object->nid; break; } // Rating form. The user must be logged in, have permission to rate // comments, and not be the author of the comment. if (isset($user->uid) && $object->uid != $user->uid) { $form = array('#attributes' => array('class' => 'karma-rate-comment')); $rating_options = array(-1 => t('Not rated')); $rating_titles = variable_get('karma_rating_titles', array()); foreach (range(karma_user_is_trusted() ? 0 : 1, 4) as $rating) { if (isset($rating_titles[$rating]) && strlen($rating_titles[$rating]) > 0) { $rating_options[$rating] = $rating .': '. $rating_titles[$rating]; } else { $rating_options[$rating] = $rating; } } $form['rating'] = array( '#type' => 'select', '#options' => $rating_options, '#default_value' => karma_get_user_rating($type, $object), '#id' => 'edit-rating-'. $type .'-'. $id, '#attributes' => array('class' => 'karma-rating-select'), ); if (!is_null(karma_get_user_rating($type, $object))) { switch ($type) { case 'comment': $form['rating']['#description'] = t('You have already rated this comment. Selecting a new rating will replace your old rating.'); break; case 'node': $form['rating']['#description'] = t('You have already rated this post. Selecting a new rating will replace your old rating.'); break; } } else { $form['rating']['#default_value'] = -1; } // Stars, if enabled. if (variable_get('karma_selector_type', 'select') == 'stars') { $form['rating']['#attributes']['class'] .= ' has-stars'; switch ($type) { case 'comment': $output = ''. t('Rate this comment') .''; break; case 'node': $output = ''. t('Rate this post') .''; break; } if (karma_user_is_trusted()) { $output .= ' '; } $output .= '
'. t('Average rating: %average', array('%average' => $rating_sum / db_num_rows($ratings))) .'
'; } else { $output .= ''. t('No ratings.') . '
'; } switch ($type) { case 'comment': // $output .= theme('links', array(l(t('Back to %title', array('%title' => theme('placeholder', $object->node_title))), 'node/'. $object->nid, array(), NULL, 'comment-'. $object->cid, FALSE, TRUE))); break; case 'node': //$output .= theme('links', array(l(t('Back to %title', array('%title' => theme('placeholder', $object->node_title))), 'node/'. $object->nid, array(), NULL, NULL, FALSE, TRUE))); break; } return $output; } function karma_forms($args) { list($form_id, $type, $object, $id) = $args; $forms['_karma_rating_form_'. $type .'_'. $id] = array('callback' => '_karma_rating_form', $type, $object); return $forms; }