$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 = '