<?php

/**
 * @file
 * This module provides control and sending complaints to the comments.
 */

define('COMMENT_ABUSE_MODULE_PATH', drupal_get_path('module', 'comment_abuse'));
define('COMMENT_ABUSE_DEFAULT_COMPLAINTS_ON_PAGE', 50);
define('COMMENT_ABUSE_LISTING_PATH', 'admin/content/comment-abuse/list');

require_once 'comment_abuse.form.inc';

/**
 * Implements hook_menu().
 */
function comment_abuse_menu() {
  $items = array();

  $items['comment-abuse/comment/%'] = array(
    'page callback' => 'comment_abuse_content',
    'page arguments' => array(2),
    'access arguments' => array('send complaints on comments'),
    'delivery callback' => 'ajax_deliver',
    'type' => MENU_CALLBACK,
    'file' => 'comment_abuse.pages.inc',
  );

  $items['comment-abuse/%ctools_js/complaint-popup/%'] = array(
    'page callback' => 'comment_abuse_complaint_popup',
    'page arguments' => array(1,3),
    'access arguments' => array('send complaints on comments'),
    'type' => MENU_CALLBACK,
    'file' => 'comment_abuse.pages.inc',
  );

  $items[COMMENT_ABUSE_LISTING_PATH] = array(
    'title' => 'Complaints to the comments',
    'page callback' => 'comment_abuse_admin',
    'access arguments' => array('administer complaints'),
    'type' => MENU_LOCAL_TASK | MENU_NORMAL_ITEM,
    'file' => 'comment_abuse.admin.inc',
  );

  $items['admin/config/content/comment-abuse/options'] = array(
    'title' => 'Comment abuse',
    'description' => 'Options of comment abuse module.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('comment_abuse_options_form'),
    'access arguments' => array('administer complaints'),
    'file' => 'comment_abuse.admin.inc',
  );

  return $items;
}

/**
 * Implements hook_theme().
 */
function comment_abuse_theme() {
  $items = array();

  $items['comment_abuse_complaint_popup'] = array(
    'variables' => array(
      'form' => NULL,
    ),
    'path' => COMMENT_ABUSE_MODULE_PATH,
    'template' => 'comment-abuse-complaint-popup',
  );

  $items['comment_abuse_complaint_popup_result'] = array(
    'variables' => array(
      'message' => NULL,
      'result' => NULL,
    ),
    'path' => COMMENT_ABUSE_MODULE_PATH,
    'template' => 'comment-abuse-complaint-popup-result',
  );

  return $items;
}

/**
 * Implements hook_comment_view().
 */
function comment_abuse_comment_view($comment, $view_mode, $langcode) {

  // Check what complaint link is alowed.
  if (user_access('send complaints on comments')
      && !variable_get('comment_abuse_' . $comment->node_type, FALSE)) {
    global $user;
    static $modal_init;
    static $comment_allow = array();
    static $comments_hosts = array();    

    // Init modal windows.
    if (empty($modal_init)) {
      $modal_init = 'processed';
      comment_abuse_init_modal();
    }

    // Get data for build links.
    if (empty($comment_allow)) {
      $comment_allow = comment_abuse_get_allowed_comment_links_by_nid($comment->nid);

      // Load ip adresses of comments  for anonymous users.
      if ($user->uid == 0) {
        $comments_hosts = comment_abuse_load_comments_hosts($comment->nid);
      }
    }

    if (isset($comment_allow[$comment->cid])) {

      // Check owner of comment.
      $allow_complaint = TRUE;
      // User logged in and he is owner of current comment.
      if ($user->uid != 0 && $comment->uid == $user->uid) {
        $allow_complaint = FALSE;
      }
      // Annonymous user.
      if ($user->uid == 0 && isset($comments_hosts[$comment->cid])
          && $comments_hosts[$comment->cid] == ip_address()) {
        $allow_complaint = FALSE;
      }

      if ($allow_complaint) {
        $text = comment_abuse_get_text_for('link');
        $output = comment_abuse_get_link($text, $comment->cid);
        $comment->content['links']['comment']['#links']['comment-complaint'] = array('title' => $output, 'html' => TRUE);
      }
    }
  }
}

/**
 * Implements hook_comment_delete().
 */
function comment_abuse_comment_delete($comment) {

  // Remove complaints of deleted comment.
  db_delete('comment_abuse')
    ->condition('cid', $comment->cid)
    ->execute();
}

/**
 * Implements hook_action_info().
 */
function comment_abuse_action_info() {
  return array(
    'comment_abuse_remove_abuses' => array(
      'type' => 'comment',
      'label' => t('Remove abuses from a comment'),
      'configurable' => FALSE,
      'behavior' => array('changes_property'),
    ),
  );
}

/**
 * Delete all abuses from a comment.
 */
function comment_abuse_remove_abuses($comment, $context = array()) {
  if (!empty($comment->cid)) {
    db_delete('comment_abuse')
      ->condition('cid', $comment->cid)
      ->execute();
  }
}

/**
 * Add new abuse for a comment.
 */
function comment_abuse_add_comment_abuse($cid, $form_state) {
  
  global $user;
  $data = $form_state['values'];
  $result = '';
  $user_ip = ip2long(ip_address());
  if ($user_ip <= 0) $user_ip = 0;

  $query = db_select('comment', 'c')
    ->fields('c', array('nid'));

  // Check what abuse is not double for anonymous.
  if (user_is_anonymous()) {
    $query->leftJoin(
      'comment_abuse', 'ca', 'ca.cid = c.cid AND ca.ip = :ip',
      array(':ip' => $user_ip)
    );
  }
  // Check what abuse is not double for registered user.
  else {
    $query->leftJoin(
      'comment_abuse', 'ca', 'ca.cid = c.cid AND ca.uid = :uid',
      array(':uid' => $user->uid)
    );
  }
  $result = $query->condition('c.cid', $cid)
      ->isNull('ca.aid')
      ->execute()
      ->fetch();

  if ($result->nid != NULL) {
    // Insert new abuse in database.
    $aid = db_insert('comment_abuse')
      ->fields(
        array(
          'nid' => $result->nid,
          'cid' => $cid,
          'timestamp' => REQUEST_TIME,
          'message' => isset($data['comment_abuse_complaint_message']) ? $data['comment_abuse_complaint_message'] : '',
          'reason' => isset($data['comment_abuse_complaint_reason']) ? $data['comment_abuse_complaint_reason'] : '',
          'uid' => $user->uid,
          'ip' => $user_ip,
        )
      )
      ->execute();

    // Build abuse object.
    $abuse = new stdClass();
    $abuse->aid = $aid;
    $abuse->cid = $cid;
    $abuse->nid = $result->nid;
    $abuse->timestamp = REQUEST_TIME;
    $abuse->uid = $user->uid;
    $abuse->ip = ip_address();
    $abuse->reason_id = isset($data['comment_abuse_complaint_reason']) ? $data['comment_abuse_complaint_reason'] : '';
    $abuse->message = isset($data['comment_abuse_complaint_message']) ? $data['comment_abuse_complaint_message'] : '';
    // Invoke hook comment_abuse.
    module_invoke_all('comment_abuse', $abuse);

    return TRUE;
  }
  return FALSE;
}

/**
 * Implements hook_comment_abuse().
 */
function comment_abuse_comment_abuse($abuse) {

  // Send email about complaint on comment.
  if (variable_get('comment_abuse_email_notification', FALSE)) {
    global $language;
    $emails = explode(',', variable_get('comment_abuse_email_list', ''));
    foreach ($emails as $email) {
      drupal_mail('comment_abuse', 'abuse', $email, $language->language, $abuse);
    }
  }
}

/**
 * Implements hook_mail().
 */
function comment_abuse_mail($key, &$message, $abuse) {

  if ($key == 'abuse') {
    $langcode = $message['language']->language;
    $reasons = comment_abuse_get_complaint_reasons();
    $message['subject'] = t('Comment abuse notification.', array('langcode' => $langcode));
    $message['body'][] = t("On your site came a new complaint on a comment.\n
      Reason : !reason \n
      Message: !message \n
      Page url: !node_url \n
      Moderation page: !moderation_url",
      array(
        '!reason' => $reasons[$abuse->reason_id],
        '!message' => $abuse->message,
        '!node_url' => url("node/$abuse->nid", array('absolute' => TRUE)),
        '!moderation_url' => url('admin/content/comment-abuse/list', array('absolute' => TRUE)),
      ),
      array('langcode' => $langcode));
  }
}

/**
 * Build link for complaint comment.
 */
function comment_abuse_get_link($text, $cid, $popup = NULL) {

  if (empty($popup)) {
    $popup = variable_get('comment_abuse_use_popup', 1);
  }

  // Use popup for complaint on comment.
  if ($popup) {
    $output = ctools_modal_text_button(
      $text,
      'comment-abuse/nojs/complaint-popup/' . $cid,
      $text,
      'ctools-modal-comment-abuse-modal-style comment-abuse-' . $cid
    );
    $output .= '<div id="modal-message">&nbsp</div>';
    return $output;
  }
  // Use simple link for complaint on comment.
  else {
    return l(
      $text,
      "comment-abuse/comment/$cid",
      array(
        'attributes' => array(
          'title' => $text,
          'class' => array('use-ajax', 'comment-abuse-' . $cid),
        )
      )
    );
  }
}


/**
 * This function returns the ID of the comments are available to the complaints
 * of the current user.
 */
function comment_abuse_get_allowed_comment_links_by_nid($nid) {

  global $user;
  // Load comments that do not have complaints from the corresponding user ID
  // and IP address.
  $query = db_select('comment', 'c');

  // Check for registered users.
  if (!user_is_anonymous()) {
    $query->leftJoin(
    'comment_abuse', 'ca', 'c.cid = ca.cid AND ca.nid = :nid AND ca.uid = :uid',
      array(
        ':nid' => $nid,
        ':uid' => $user->uid,
      )
    );
  }
  // Check for anonymous.
  else {
    $query->leftJoin(
      'comment_abuse', 'ca', 'c.cid = ca.cid AND ca.nid = :nid AND ca.ip = :ip',
      array(
        ':nid' => $nid,
        ':ip' => ip2long(ip_address()),
      )
    );
  }

  $result = $query
    ->fields('c', array('cid'))
    ->isNull('ca.cid')
    ->condition('c.nid', $nid)
    ->execute();

  $allow_links = array();
  foreach ($result as $row) {
    $allow_links[$row->cid] = $row->cid;
  }

  return $allow_links;
}

/**
 * Implements hook_permission().
 */
function comment_abuse_permission() {
  return array(
    'administer complaints' => array(
      'title' => t('Administer complaints'),
      'description' => t('Allow for role administer list of complaints and options of module.'),
    ),
    'send complaints on comments' => array(
      'title' => t('Send complaints on comments'),
      'description' => t('Allow for role sending complaints on comments.'),
    ),
  );
}


/**
 * Load comments that do not have complaints from the corresponding user ID and IP address.
 */
function comment_abuse_load_comments_hosts($nid) {

  $result = db_select('comment', 'c')
    ->fields('c', array('cid', 'hostname'))
    ->condition('c.uid', 0)
    ->condition('c.nid', $nid)
    ->execute();

  $hosts = array();
  foreach ($result as $row) {
    $hosts[$row->cid] = $row->hostname;
  }

  return $hosts;
}

/**
 * Implements hook_views_api().
 */
function comment_abuse_views_api() {
  return array(
    'api' => 3,
    'path' => drupal_get_path('module', 'comment_abuse'),
  );
}

/**
 * Return complaint reasons.
 */
function comment_abuse_get_complaint_reasons() {
  $reasons = array(
    t('Rudeness'),
    t('Spam'),
    t('Other'),
  );

  // Invoke hook comment_abuse.
  drupal_alter('complaint_reason', $reasons);

  return $reasons;
}

/**
 * Init libraries for process ctools modal windows.
 */
function comment_abuse_init_modal() {

  ctools_include('ajax');
  ctools_include('modal');
  ctools_modal_add_js();

  drupal_add_css(COMMENT_ABUSE_MODULE_PATH . '/misc/comment_abuse.css');
  drupal_add_js(COMMENT_ABUSE_MODULE_PATH . '/misc/comment_abuse.js');

  $custom_style = array(
    'comment-abuse-modal-style' => array(
      'modalSize' => array(
        'type' => 'fixed',
        'width' => variable_get('comment_abuse_modal_width', 500),
        'height' => variable_get('comment_abuse_modal_height', 300),
        'addWidth' => 20,
        'addHeight' => 50,
      ),
      'modalOptions' => array(
        'opacity' => .5,
        'background-color' => '#000',
      ),
      'animation' => 'fadeIn',
      'modalTheme' => 'CommentAbuse',
      'throbber' => theme('image',
        array(
          'path' => ctools_image_path('ajax-loader.gif', 'ctools_ajax_sample'),
          'alt' => t('Loading...'),
          'title' => t('Loading')
        )
      ),
    ),
  );
  drupal_add_js($custom_style, 'setting');

  ctools_include('plugins');
}

/**
 * Return text for comment abuse elements.
 */
function comment_abuse_get_text_for($text = 'link') {

  switch ($text) {

    case 'link':
      return comment_abuse_translate('complaint_text',
        variable_get('comment_abuse_complaint_text', ''));
      break;

    case 'popup_title':
      return comment_abuse_translate('complaint_popup_title',
        variable_get('comment_abuse_complaint_popup_title', ''));
      break;

    case 'success':
      return comment_abuse_translate('complaint_success_message',
        variable_get('comment_abuse_complaint_success_message', ''));
      break;

    case 'fail':
      return comment_abuse_translate('complaint_fail_message',
        variable_get('comment_abuse_complaint_fail_message', ''));
      break;
  }
}

/**
 * Wrapper function for i18nstrings() if i18nstrings enabled.
 */
function comment_abuse_translate($name, $string, $langcode = NULL, $textgroup = 'comment_abuse') {
  if (function_exists('i18n_string_translate')) {
    return i18n_string_translate($textgroup . ':' . $name, $string, $langcode);
  }
  else {
    return $string;
  }
}

/**
 * Implements hook_i18n_string_info()
 */
function comment_abuse_i18n_string_info() {
  $groups['comment_abuse'] = array(
    'title' => t('Comment Abuse'),
    'description' => t('Interface texts for Comment Abuse.'),
    'format' => FALSE, // This group doesn't have strings with format
    'list' => FALSE, // This group cannot list all strings
    'refresh callback' => 'comment_abuse_locale_refresh',
  );
  return $groups;
}

/**
 * Update / create translation source for user defined strings.
 *
 * @return $bool
 *   TRUE if update successful, FALSE if not.
 */
function comment_abuse_locale_refresh($textgroup = 'comment_abuse') {
  if (function_exists('i18n_string_update')) {
    i18n_string_update("$textgroup:complaint_text",
      variable_get('comment_abuse_complaint_text', ''));
    i18n_string_update("$textgroup:complaint_popup_title",
      variable_get('comment_abuse_complaint_popup_title', ''));
    i18n_string_update("$textgroup:complaint_success_message",
      variable_get('comment_abuse_complaint_success_message', ''));
    i18n_string_update("$textgroup:complaint_fail_message",
      variable_get('comment_abuse_complaint_fail_message', ''));
  }
  return TRUE; // Update completed with no issues
}
