$GLOBALS['base_url']),
'setting'
);
// add vatiable used for jquery submit
drupal_add_js(array('slashdot' =>
array('error_status' => t("Error moderationg comment"),
'load_image_path' => $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'slashcomments') . 'images/loading.gif')), 'setting');
}
/**
* Implementation of hook_views_api().
*/
function slashcomments_views_api() {
return array('api' => 2.0);
}
/**
* Implementation of hook_perm().
*/
function slashcomments_perm() {
return array('moderate comments','administer slashcomments');
}
/**
* Implementation of hook_menu().
*/
function slashcomments_menu() {
$items = array();
// Add the callback for AJAX moderation
$items['slashdot/moderate'] = array(
'title' => 'Slashcomments - AJAX moderation',
'page callback' => 'slashdotcomments_moderate',
'access callback' => 'slashcomments_moderate_access',
'type' => MENU_CALLBACK,
);
// Add the callback for settings menĂ¹
$items['admin/settings/slashcomments'] = array(
'title' => 'Slashcomments',
'page callback' => 'drupal_get_form',
'page arguments' => array('slashcomments_admin_settings'),
'access arguments' => array('administer slashcomments'),
'type' => MENU_NORMAL_ITEM,
'file' => 'slashcomments.admin.inc',
);
return $items;
}
/**
* Implementation of access callback
*/
function slashcomments_moderate_access() {
return user_access('access content') && user_access('moderate comments');
}
/**
* Implemente the callback for slashdot/moderate menu entry responsible
* of hnandling AJAX modration
*/
function slashdotcomments_moderate() {
global $user;
// Check needed variable has been sent
if (empty($_POST['js']) || !is_numeric($_POST['cid'])
|| !is_numeric($_POST['uid']) || !is_numeric($_POST['vote']) ) {
return;
}
// save the vote
if (!slashcomments_store_vote($_POST['cid'], $_POST['vote'])) {
return;
}
// Get the new rating for the moderated comment
$rating = slashcomments_get_comment_rating($_POST['cid'], $_POST['uid']);
// Create the string representation of the rating
$description = isset($rating['description']) ? ' '. $rating['description'] : '';
$rating_str = '(' . t('Score') . ':' . $rating['rating'] . $description . ')';
// Set variable to be used by ajax success hander
drupal_json(array(
'rating' => $rating_str,
'status' => t('Comment moderated!')
));
exit();
}
/**
* Submit function for comment moderation form, called if AJAX moderation is off
*/
function slashcomments_moderation_form_submit($form, &$form_state) {
slashcomments_store_vote($form_state['values']['cid'], $form_state['values']['vote']);
}
/**
* Store a moderation vote
*/
function slashcomments_store_vote($cid, $vote) {
global $user;
$author_uid = db_result(db_query("SELECT uid FROM {comments} WHERE cid=%d", $cid));
// Check if user is allowed to vote
if (!slashcomments_user_can_vote($user->uid, $cid)) {
return FALSE;
}
// Build vote object
$vote = array(
'content_type' => 'comment',
'content_id' => $cid,
'value_type' => 'option',
'value' => $vote,
'tag' => 'slashcomments',
);
// Cast the vote and recalculate score and rating for the comment
votingapi_add_votes($vote);
votingapi_recalculate_results('comment', $cid, TRUE);
slashcomments_update_rating($cid, $author_uid);
// If karma is enabled updated its value
if (variable_get('slashcomments_enable_karma', SLASHCOMMENTS_ENABLE_KARMA) == 1) {
slashcomments_update_karma($author_uid);
}
return TRUE;
}
/**
* Implementation of hook_theme().
*/
function slashcomments_theme() {
$items['slashcomments_comment'] = array(
'template' => 'slashcomments-comment',
);
$items['slashcomments_moderation_form'] = array(
'arguments' => array('form' => NULL),
);
return $items;
}
/**
* Implementation of hook_theme_registry_alter().
*/
function slashcomments_theme_registry_alter($theme_registry) {
// replace the theme function for comment_view */
if (!empty($theme_registry['comment_view'])) {
$theme_registry['comment_view']['function'] = 'slashcomments_comment_view';
}
// replace the theme function for collapsed view with expanded view */
if (!empty($theme_registry['comment_flat_collapsed'])) {
$theme_registry['comment_flat_collapsed']['function'] = 'theme_comment_flat_expanded';
}
if (!empty($theme_registry['comment_thread_collapsed'])) {
$theme_registry['comment_thread_collapsed']['function'] = 'theme_comment_thread_expanded';
}
// Code ported from the advanced forum module
// --- The following section manipulates the theme registry so the .tpl files
// --- for the given templates can be found first in the (sub)theme directory
// --- then in ancestor themes, if any, and finally in the slashcomments folder.
// Affected templates
$templates = array('comment', 'author_pane');
// Find all our ancestor themes and put them in an array.
global $theme;
$themes = list_themes();
$ancestor_paths = array();
$ancestor = $theme;
while ($ancestor && isset($themes[$ancestor]->base_theme)) {
array_unshift($ancestor_paths, dirname($themes[$themes[$ancestor]->base_theme]->filename));
$ancestor = $themes[$ancestor]->base_theme;
}
$module_path = drupal_get_path('module', 'slashcomments') . '/templates';
foreach ($templates as $template) {
// Sanity check in case the template is not being used.
if (is_array($theme_registry[$template])) {
// If there was a path in there, store it.
$existing_path = array_shift($theme_registry[$template]['theme paths']);
array_unshift($theme_registry[$template]['theme paths'], $existing_path, $module_path);
// If there are any ancestor paths (ie: we are in a subtheme, add those)
foreach ($ancestor_paths as $ancestor_path) {
$theme_registry[$template]['theme paths'][] = $ancestor_path;
}
//Put the active theme's path last since that takes precidence.
$theme_registry[$template]['theme paths'][] = path_to_theme();
}
}
}
/**
* Preprocesses template variables for the comment template.
*/
function slashcomments_preprocess_comment(&$variables) {
// get current tpl_file
$tpl_file = $variables['template_files'][count($variables['template_files'])-1];
// Replace the template file with the version provided by slashcomments
if ($tpl_file == 'advf-forum-post') {
$variables['template_files'][] = "slashcomments-advf-forum-post";
}
else {
$variables['template_files'][] = "slashcomments-comment";
}
$comment = $variables['comment'];
// get score and rating
$rating = slashcomments_get_comment_rating($comment->cid, $comment->uid);
$description = isset($rating['description']) ? ' '. $rating['description'] : '';
$variables['rating'] = '(' . t('Score') . ':' . $rating['rating'] . $description . ')';
// get default threshold for the content type
$threshold = _slashcomments_get_display_setting('threshold', $variables['node']);
// fill out template variables
if ($rating['rating'] >= $threshold) {
$variables['collapsed'] = '';
$variables['toggle_label'] = 'non_toggle_label';
$variables['toggle_area'] = 'non_toggle_area';
}
else {
$variables['collapsed'] = 'collapsed';
$variables['toggle_label'] = 'toggle_label';
$variables['toggle_area'] = 'toggle_area';
}
$variables['toggle_label'] .= ' ' . $comment->own;
$variables['toggle_area'] .= ' ' . $comment->own;
// generate permalink
$page_number = $_GET['page'];
if (!$page_number) {
$page_number = 0;
}
$fragment = 'comment-' . $variables['comment']->cid;
$query = ($page_number) ? 'page=' . $page_number : NULL;
$img_path = drupal_get_path('module', 'slashcomments') . '/images';
$linktext = '';
$linkpath = 'node/' . $variables['node']->nid;
$variables['comment_link'] = l($linktext, $linkpath, array('query' => $query, 'fragment' => $fragment, 'html' => TRUE));
// Link to page created by Comment Page module, if it exists
$variables['page_link'] = '';
if (!empty($variables['comment']->page_url) && !(arg(0) == 'comment' && arg(1) == $variables['comment']->cid)) {
$variables['page_link'] = l(t('(permalink)'), $variables['comment']->page_url);
}
}
/**
* Provides implementation for theme_comment_view() override
*/
function slashcomments_comment_view($comment, $node, $links = array(), $visible = TRUE) {
static $first_new = TRUE;
$output = '';
$comment->new = node_mark($comment->nid, $comment->timestamp);
if ($first_new && $comment->new != MARK_READ) {
// Assign the anchor only for the first new comment. This avoids duplicate
// id attributes on a page.
$first_new = FALSE;
$output .= "\n";
}
//$output .= "cid\">\n";
$comment->comment = check_markup($comment->comment, $comment->format, FALSE);
// Comment API hook
comment_invoke_comment($comment, 'view');
$output .= theme('comment', $comment, $node, $links);
return $output;
}
/**
* Implementation of hook_comment().
*/
function slashcomments_comment($comment, $op) {
switch ($op) {
case 'view':
// Add javascript and CSS File
// TODO Move in a different place so that are not called for each comments
drupal_add_js(drupal_get_path('module', 'slashcomments') .'/slashcomments.js');
drupal_add_css(drupal_get_path('module', 'slashcomments') .'/slashcomments.css');
global $user;
$reply = arg(0) == 'comment' && (arg(1) == 'reply' || arg(1) == 'edit');
// Hide moderation module if user can't moderate or is on the edit or reply page
if (!$reply && slashcomments_user_can_vote($user->uid, $comment->cid)) {
$comment->comment = $comment->comment . drupal_get_form('slashcomments_moderation_form', $comment->cid, $comment->uid);
}
// marke comments of the user in order to theme them differently
if ($user->uid == $comment->uid && $user->uid != 0) {
$comment->own = "own";
}
break;
case 'insert':
// if the user has moderated comments for this node before posting ots previous
// moderation are removed
if (variable_get('slashcomments_delete_takepart', SLASHCOMMENTS_DELETE_TAKEPART) == 1) {
slashcomments_delete_user_comment_moderation($comment['nid'], $comment['uid']);
}
// if karma is enable apply a modifier to the initial comment rating
if (variable_get('slashcomments_enable_karma', SLASHCOMMENTS_ENABLE_KARMA) == 1) {
slashcomments_init_rating($comment['cid'], $comment['uid']);
}
break;
// If the comment has been removed, delete infos about
// is score and rating and update author karma
case 'delete':
$delete_votes = "DELETE FROM {votingapi_vote}
WHERE content_id = %d
AND tag = 'slashcomments'";
db_query($delete_votes, $comment->cid);
if (db_affected_rows() < 1) {
break;
}
votingapi_recalculate_results('comment', $comment->cid, TRUE);
slashcomments_delete_rating($comment->cid);
slashcomments_update_karma($comment->uid);
break;
}
}
/**
* Delete ratings for a single comment
*/
function slashcomments_delete_rating($cid) {
db_query("DELETE FROM {slashcomments_ratings} WHERE cid = %d", $cid);
}
/**
* Add threshold to comments control forms
*/
function slashcomments_form_alter(&$form, $form_state, $form_id) {
if ($form_id == 'comment_form') {
unset($form['comment_filter']['comment']['#title']);
}
if ($form_id == 'node_type_form' && isset($form['identity']['type'])) {
$form['comment']['comment_default_threshold'] = array(
'#type' => 'select',
'#title' => t('Default comments threshold'),
'#default_value' => variable_get('comment_default_threshold_'. $form['#node_type']->type, SLASHCOMMENTS_DEFAULT_THRESHOLD),
'#options' => _slashcomments_thresholds(),
'#description' => t('Default threshold for comments. Comments with lower score will be collapsed.'),
'#weight' => -5,
);
$form['comment']['comment_default_mode'] = array(
'#type' => 'select',
'#title' => t('Default display mode'),
'#default_value' => variable_get('comment_default_mode_'. $form['#node_type']->type, SLASHCOMMENTS_MODE_FLAT),
'#options' => _slashcomments_modes(),
'#description' => t('The default view for comments.'),
'#weight' => -4,
);
$form['comment']['comment_default_per_page']['#weight'] = -3;
//order is always oldest first
unset($form['comment']['comment_default_order']);
}
if ($form_id == 'comment_controls') {
// WARNING: we cannot get node type from form info, so, we have to load from arg(1)
$node = node_load(arg(1));
$form['threshold'] = array(
'#type' => 'select',
'#title' => t('Threshold'),
'#options' => _slashcomments_thresholds($node),
'#default_value' => _slashcomments_get_display_setting('threshold', $node),
'#weight' => 0,
);
$form['mode'] = array(
'#type' => 'select',
'#default_value' => _slashcomments_get_display_setting('mode', $node),
'#options' => _slashcomments_modes(),
'#weight' => 1,
);
//order is always oldest first
$form['order'] = array(
'#type' => 'hidden',
'#value' => COMMENT_ORDER_OLDEST_FIRST,
);
$form['comments_per_page'] = array(
'#type' => 'select',
'#default_value' => _slashcomments_get_display_setting('comments_per_page', $node),
'#options' => _slashcomments_per_page(),
'#weight' => 3,
);
$form['#submit'][] = 'slashcomments_comment_control_submit';
}
}
/**
* Convertratings numeric options to descriptions
*/
function slashcomments_rating2description($rating) {
static $descriptions;
$descriptions = _slashcomments_moderation_options();
if ($descriptions[$rating]) {
return $descriptions[$rating];
}
}
/**
* Submit function for comment control form
*/
function slashcomments_comment_control_submit($form, &$form_state) {
global $user;
$threshold = $form_state['values']['threshold'];
$mode = $form_state['values']['mode'];
$order = $form_state['values']['order'];
$comments_per_page = $form_state['values']['comments_per_page'];
if ($user->uid) {
$account = user_save($user, array('threshold' => $threshold, 'mode' => $mode, 'sort' => $order, 'comments_per_page' => $comments_per_page));
// Terminate if an error occured during user_save().
if (!$account) {
drupal_set_message(t("Error saving user account."), 'error');
return;
}
}
$_SESSION['comment_threshold'] = $threshold;
$_SESSION['comment_mode'] = $mode;
$_SESSION['comment_sort'] = $order;
$_SESSION['comment_comments_per_page'] = $comments_per_page;
}
/**
* Get display settings for a given content
*/
function _slashcomments_get_display_setting($setting, $node) {
global $user;
if (isset($_GET[$setting])) {
$value = $_GET[$setting];
}
else {
// get the setting's site default
switch ($setting) {
case 'threshold':
$default = variable_get('comment_default_threshold_'. $node->type, SLASHCOMMENTS_DEFAULT_THRESHOLD);
break;
case 'mode':
$default = variable_get('comment_default_mode_'. $node->type, COMMENT_MODE_THREADED_EXPANDED);
break;
case 'sort':
$default = variable_get('comment_default_order_'. $node->type, COMMENT_ORDER_OLDEST_FIRST);
break;
case 'comments_per_page':
$default = variable_get('comment_default_per_page_'. $node->type, 50);
}
if (variable_get('comment_controls_'. $node->type, COMMENT_CONTROLS_HIDDEN) == COMMENT_CONTROLS_HIDDEN) {
// if comment controls are disabled use site default
$value = $default;
}
else {
// otherwise use the user's setting if set
if (isset($user->$setting) && $user->$setting) {
$value = $user->$setting;
}
elseif (isset($_SESSION['comment_'. $setting]) && $_SESSION['comment_'. $setting]) {
$value = $_SESSION['comment_'. $setting];
}
else {
$value = $default;
}
}
}
return $value;
}
/**
* Determine whether a given user can vote on a given comment
*/
function slashcomments_user_can_vote($uid, $cid) {
if (user_access('administer')) {
return TRUE;
}
// keeps the status for checks which are comment independent
// to avoid executing them multiple times during comment rendering
static $can_vote = -1;
// check user has the needed permission
if (!(user_access('moderate comments') && user_access('moderate comments'))) {
return FALSE;
}
if ($can_vote == 0) {
return FALSE;
}
if ($can_vote == -1) {
global $user;
// check if required days has paased for new users
if ($uid <> 1 && strtotime("-" . variable_get('slashcomments_limit_newbie', SLASHCOMMENTS_LIMIT_NEWBIE) . " day") < $user->created) {
$can_vote = 0;
return FALSE;
}
// check if user has the needed karma
if ($uid <> 1 && variable_get('slashcomments_enable_karma', SLASHCOMMENTS_ENABLE_KARMA) == 1
&& slashcomments_get_user_karma($uid) < variable_get('slashcomments_limit_karma', SLASHCOMMENTS_LIMIT_KARMA)) {
$can_vote = 0;
return FALSE;
}
}
$can_vote = 1;
// check if the user has already moderated this comment
if (votingapi_select_votes(array('content_type' => 'comment', 'content_id' => $cid, 'uid' => $uid))) {
return FALSE;
}
// check if user is participating in the discussion
$participating = slashcomments_user_participating_in_discussion($uid, $cid);
return !$participating;
}
/**
* Implementation of hook_preprocess_author_pane().
*/
function slashcomments_preprocess_author_pane(&$variables) {
$tpl_file = $variables['template_files'][count($variables['template_files'])-1];
// Replace the template file with the version provided by slashcomments
if (module_exists('advanced_forum')) {
if ($tpl_file == 'advf-author-pane') {
if (strpos(advanced_forum_get_current_style(), 'stacked') == FALSE) {
$variables['template_files'][] = "slashcomments-advf-author-pane";
}
else {
$variables['template_files'][] = "slashcomments-advf-author-pane-stacked";
}
}
}
else {
$variables['template_files'][] = "slashcomments-author-pane";
}
// Add karma to template variables
$variables['slashcomments_karma'] = slashcomments_get_user_karma($variables['account']->uid);
}
/**
* Check whether user is participating in a given discussion
*/
function slashcomments_user_participating_in_discussion($uid, $cid) {
// keeps this variable to avoid executing all the checks during
// multiple comments rendering
static $participating = -1;
// result has already been estabilished return it
if ($participating != -1) {
return $participating;
}
if (variable_get('slashcomments_limit_takepart', SLASHCOMMENTS_LIMIT_TAKEPART) == 1) {
// get nid of the discussion
$result = db_query("SELECT n.nid, n.uid FROM {comments} c, {node} n WHERE c.cid=%d AND c.nid = n.nid", $cid);
$node_info = db_fetch_array($result);
if ($node_info['uid'] == $uid) {
return TRUE;
}
// get user's comments with nid
$user_cid = db_result(db_query("SELECT count(*) FROM {comments} WHERE nid=%d AND uid=%d", $node_info['nid'], $uid));
$participating = ($user_cid == 0) ? 0 : 1;
return (boolean)$participating;
}
else {
// get nid of the discussion
$nid = db_result(db_query("SELECT count(*) FROM {comments} WHERE cid=%d AND uid=%d", $cid, $uid));
return ($nid == 0) ? FALSE : TRUE;
}
}
/**
* FAPI definition for the comment moderation form.
*
* @ingroup forms
* @see slashcomments_moderation_form_submit()
*/
function slashcomments_moderation_form($form_state, $cid, $uid) {
$form['cid'] = array('#type' => 'hidden', '#default_value' => $cid);
$form['uid'] = array('#type' => 'hidden', '#default_value' => $uid);
$form['vote'] = array(
'#title' => '',
'#type' => 'select',
'#options' => _slashcomments_moderation_options(),
'#default_value' => 0,
'#weight' => 30
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Moderate'),
'#weight' => 50
);
$form['#submit'][] = 'slashcomments_moderation_form_submit';
return $form;
}
/**
* Theme the moderation form
*/
function theme_slashcomments_moderation_form($form) {
$output = '