*/
/**
 * Implementation of hook_menu().
 */
function moderation_menu($may_cache) {
  $items = array();
  
  if ($may_cache) {
    $items[] = array(
      'path' => 'admin/content/node/moderation',
      'title' => t('Moderation'),
      'callback' => 'moderation_node_queue',
      'access' => user_access('administer nodes'),
      'type' => MENU_LOCAL_TASK,
    );
    $items[] = array(
      'path' => 'admin/content/comment/list/moderation',
      'title' => t('Moderation'),
      'callback' => 'moderation_comment_queue',
      'access' => user_access('administer comments'),
      'type' => MENU_LOCAL_TASK,
    );
    $items[] = array(
      'path' => 'admin/content/node/log',
      'title' => t('Log'),
      'callback' => 'moderation_log',
      'callback arguments' => array('node'),
      'access' => user_access('administer nodes'),
      'type' => MENU_LOCAL_TASK,
      'weight' => 1,
    );
    $items[] = array(
      'path' => 'admin/content/comment/list/log',
      'title' => t('Log'),
      'callback' => 'moderation_log',
      'callback arguments' => array('comment'),
      'access' => user_access('administer comments'),
      'type' => MENU_LOCAL_TASK,
      'weight' => 1,
    );
    $items[] = array(
      'path' => 'admin/settings/moderation',
      'title' => 'Content moderation',
      'description' => 'Configure the moderation queue.',
      'callback' => 'drupal_get_form',
      'callback arguments' => array('moderation_admin_settings'),
      'access' => user_access('administer site configuration'),
    );
  }
  else {
    if (arg(0) == 'node' AND is_numeric(arg(1))) {
      $items[] = array(
        'path' => 'node/' . arg(1) . '/log',
        'title' => 'Log',
        'description' => 'Configure the moderation queue.',
        'callback' => 'moderation_log',
        'callback arguments' => array('node', arg(1)),
        'access' => user_access('administer nodes'),
        'type' => MENU_LOCAL_TASK,
      );
    }
    
    $access = (arg(1) == 'node' AND user_access('administer nodes')) || (arg(1) == 'comment' AND user_access('administer comments')) ? TRUE : FALSE;
    $items[] = array(
      'path' => 'moderation',
      'callback' => 'moderation_callback_switch',
      'callback arguments' => array(arg(1), arg(2), arg(3), arg(4)),
      'access' => $access,
      'type' => MENU_CALLBACK,
    );
  }
  return $items;
}
/**
 * 
 */
function moderation_callback_switch($obj_type, $obj_id, $op, $attribute) {
  $js = isset($_REQUEST['js']);
  $token = $_REQUEST['token'];
  // Check for valid token
  // We don't need a token if $op is get
  if (!drupal_valid_token($token, $obj_type .'-'. $obj_id) && $op != 'get') {
    drupal_access_denied();
    exit();
  }
  $attributes = array('status', 'promote', 'sticky', 'moderate', 'preview');
  $types      = array('node', 'comment');
  
  if (!is_numeric($obj_id) OR !in_array($obj_type, $types) OR !in_array($attribute, $attributes)) {
    return drupal_not_found();
  }
  
  if ($op == 'get') {
    if ($attribute == 'preview') {
      if ($js) {
        // Return content for preview if js is available
        moderation_get_preview($obj_id, $obj_type);
      }
      else {
        // Redirect to node/comment if js is not available
        moderation_goto($obj_id, $obj_type);
      }
    }
    else {
      // Return the current value for an attribute
      moderation_get_attribute($obj_id, $obj_type, $attribute);
    }
    exit();
  }
  
  if ($op == 'set') {
    switch ($attribute) {
      case 'status':
      case 'promote':
      case 'sticky':
        $result = moderation_switch_attribute($obj_id, $obj_type, $attribute);
        break;
      case 'moderate':
        $result = moderation_switch_moderation($obj_id, $obj_type);
        break;
    }
    if ($js) {
      print drupal_to_js($result);
      exit();
    }
    else {
      drupal_set_message(t('The changes have been saved.'));
      drupal_goto();
    }
  }
  
  return drupal_not_found();
}
/**
 * Implementation of hook_nodeapi
 */
function moderation_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
  switch ($op) {
    case 'load':
      if (in_array($node->type, variable_get('moderation_moderated_types', array()))) {
        return db_fetch_array(db_query("SELECT status as moderate FROM {moderation_moderation} mm WHERE mm.obj_type = 'node' AND mm.obj_id = %d", $node->nid)); 
      }
    case 'update' :
    case 'insert' :
      if (moderation_is_moderated_type($node->type)) {
        db_query("DELETE FROM {moderation_moderation} WHERE obj_id=%d AND obj_type='node'", $node->nid);
        db_query("INSERT INTO {moderation_moderation} SET obj_id=%d, obj_type='node', status=%d", $node->nid, $node->moderate);
      }
      break;
    case 'delete':
      db_query("DELETE FROM {moderation} WHERE obj_type='node' AND obj_id=%d", $node->nid);
      db_query("DELETE FROM {moderation_moderation} WHERE obj_type='node' AND obj_id=%d", $node->nid);
      break;
  }
}
/**
 * Implementation of hook_comment().
 */
function moderation_comment(&$a1, $op) {
  switch ($op) {
    case 'insert':
    case 'update':
      db_query("DELETE FROM {moderation_moderation} WHERE obj_id=%d AND obj_type='comment'", $a1['cid']);
      db_query("INSERT INTO {moderation_moderation} SET obj_id=%d, obj_type='comment', status=%d", $a1['cid'], $a1['moderate']);
      break;
    case 'delete':
      db_query("DELETE FROM {moderation} WHERE obj_type='comment' AND obj_id=%d", $a1['cid']);
      db_query("DELETE FROM {moderation_moderation} WHERE obj_type='comment' AND obj_id=%d", $a1['cid']);
      break;
  }
}
/**
 * Implementation of hook_form_alter().
 */
function moderation_form_alter($form_id, &$form) {
  if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id)  {
    if (moderation_is_moderated_type($form['type']['#value'])) {
      if (user_access('administer nodes')) {
        $form['options']['moderate'] = array(
          '#type' => 'checkbox', 
          '#title' => t('Has been moderated'), 
          '#default_value' => $form['#node']->moderate,
          '#weight' => -10,
          '#description' => t('Check to remove from moderation queue, uncheck to add it to the queue.'),
        );
      }
    }
  }
  if ($form_id == 'comment_form') {
    if (user_access('administer nodes')) {
      $status = db_result(db_query("SELECT status FROM {moderation_moderation} WHERE obj_id=%d AND obj_type='comment'", $form['cid']['#value']));
      $form['admin']['moderate'] = array(
        '#type' => 'checkbox',
        '#title' => 'Has been moderated',
        '#default_value' => $status,
        '#weight' => -10,
        '#description' => t('Check to remove from moderation queue, uncheck to add it to the queue.'),
      );
    }
  }
}
/**
 * Menu callback: content administration.
 */
function moderation_node_queue() {
  global $base_path;
  
  drupal_add_css(drupal_get_path('module', 'moderation') .'/moderation.css');
  $settings = array('moderationType' => 'node', 'moderationBasePath' => $base_path);
  drupal_add_js('jQuery.extend(Drupal, '. drupal_to_js($settings) .')', 'inline');
  drupal_add_js(drupal_get_path('module', 'moderation') .'/moderation.js');
  $query = "SELECT n.*, u.name, u.uid, mm.status as moderate FROM {node} n  
              INNER JOIN {users} u ON n.uid = u.uid
              LEFT JOIN {moderation_moderation} mm ON n.nid = mm.obj_id
                WHERE mm.obj_type = 'node'
                  AND (mm.status IS NULL OR mm.status=0)
                  AND n.type IN ('" . implode('\' ,\'', variable_get('moderation_moderated_types', array())) ."')
                ORDER BY n.created DESC, n.title ASC";
  $result = pager_query(db_rewrite_sql($query), 50);
  
  $destination = drupal_get_destination();
  
  while ($node = db_fetch_object($result)) {
    $query = "SELECT m.*, u.name FROM {moderation} m  
                LEFT JOIN {users} u ON m.uid = u.uid
                WHERE m.obj_id=%d
                  AND m.obj_type='node'
                ORDER BY m.created DESC
                LIMIT 1";
    $moderation = db_fetch_object(db_query($query, $node->nid));
    $token = drupal_get_token('node-'. $node->nid);
    
    $item = '
';
    $item .= '
';
    $item .= format_date($node->created, 'small') .' ';
    $item .= l($node->title, 'moderation/node/'. $node->nid .'/get/preview');
    $item .= theme('mark', node_mark($node->nid, $node->changed));
    if ($moderation) {
      $item .= ' 
'. t('(!user - !action - !date)', array('!user' => theme('username', (object) array('uid' => $moderation->uid, 'name' => $moderation->name)), '!action' => moderation_log_message($moderation->attribute, $moderation->status, $moderation->obj_type), '!date' => format_date($moderation->created, 'small'))) .'
';
    }
    $item .= '
';
    $item .= '
 ';
    
    $item .= '';
    $item .= '  '. l(t('edit'), 'node/'. $node->nid .'/edit', array(), drupal_get_destination()) .'';
    $item .= '  '. t('By !user', array('!user' => theme('username', $node))) .'';
    $item .= '  '. check_plain(node_get_types('name', $node)) .'';
    $item .= '  '. l(($node->status   ? t('published') : t('not published')), 'moderation/node/'. $node->nid .'/set/status', array('id' => 'moderation-status-link-'. $node->nid, 'class' => 'moderation-status-link'), drupal_get_destination() .'&token='. $token) .'';
    $item .= '  '. l(($node->promote  ? t('promoted')  : t('not promoted')), 'moderation/node/'. $node->nid .'/set/promote', array('id' => 'moderation-promote-link-'. $node->nid, 'class' => 'moderation-promote-link'), drupal_get_destination() .'&token='. $token) .'';
    $item .= '  '. l(($node->sticky   ? t('sticky')    : t('not sticky')), 'moderation/node/'. $node->nid .'/set/sticky', array('id' => 'moderation-sticky-link-'. $node->nid, 'class' => 'moderation-sticky-link'), drupal_get_destination() .'&token='. $token) .'';
    $item .= '  '. l(($node->moderate ? t('moderated') : t('not moderated')), 'moderation/node/'. $node->nid .'/set/moderate', array('id' => 'moderation-moderate-link-'. $node->nid, 'class' => 'moderation-moderate-link'), drupal_get_destination() .'&token='. $token) .'';
    $item .= '
';
    
    $rows[] = array('data' => 
      array(
        array(
          'data' => $item,
        ), 
      )
    );
  }
  
  if (!db_num_rows($result)) {
    $output = t('No posts available.');
  }
  
  $output .= theme('table', array(), $rows);
  $output .= theme('pager', NULL, 50);
  
  return $output;
}
/**
 * Menu callback; present an administrative comment listing.
 */
function moderation_comment_queue() {
  global $base_path;
  
  drupal_add_css(drupal_get_path('module', 'moderation') .'/moderation.css');
  $settings = array('moderationType' => 'comment', 'moderationBasePath' => $base_path);
  drupal_add_js('jQuery.extend(Drupal, '. drupal_to_js($settings) .')', 'inline');
  drupal_add_js(drupal_get_path('module', 'moderation') .'/moderation.js');
  
  $query = "SELECT c.*, mm.status as moderate FROM {comments} c
              LEFT JOIN {moderation_moderation} mm ON c.cid = mm.obj_id
              WHERE mm.obj_type = 'comment'
                AND (mm.status IS NULL OR mm.status=0)
              ORDER BY c.timestamp DESC, c.subject ASC";
  $result = pager_query(db_rewrite_sql($query), 50);
  $destination = drupal_get_destination();
  
  while ($comment = db_fetch_object($result)) {
    $query = "SELECT m.*, u.name FROM {moderation} m  
                LEFT JOIN {users} u ON m.uid = u.uid
                WHERE m.obj_id=%d
                  AND m.obj_type='comment'
                ORDER BY m.created DESC
                LIMIT 1";
    $moderation = db_fetch_object(db_query($query, $comment->cid));
    $token = drupal_get_token('comment-'. $comment->cid);
    
    $item = '';
    
    $item .= '';
    
    $rows[] = array('data' => 
      array(
        array(
          'data' => $item,
        ), 
      )
    );
  }
  
  if (!db_num_rows($result)) {
    $output = t('No comments available.');
  }
  
  $output .= theme('table', array(), $rows);
  $output .= theme('pager', NULL, 50);
  return $output;
}
/**
 * Switch moderation flag
 *
 * @param string $obj_type one of 'node', 'comment'
 * @param integer $obj_id
 */
function moderation_switch_moderation($obj_id, $obj_type) {
  global $user;
    
  $status = db_result(db_query("SELECT status FROM {moderation_moderation} WHERE obj_id=%d AND obj_type='%s'", $obj_id, $obj_type));
  db_query("INSERT INTO {moderation} SET obj_id=%d, obj_type='%s', uid=%d, attribute='%s', status=%d, created=%d", $obj_id, $obj_type, $user->uid, 'moderate', !$status, time());
  db_query("DELETE FROM {moderation_moderation} WHERE obj_id=%d AND obj_type='%s'", $obj_id, $obj_type);
  return array(db_query("INSERT INTO {moderation_moderation} SET obj_id=%d, obj_type='%s', status=%d", $obj_id, $obj_type, !$status), !$status, 'moderate');
}
/**
 * Switch an attribute
 *
 * @param integer $obj_id
 * @param string $obj_type one of 'node', 'comment'
 * @param string $attribute one of 'status', 'promote', 'sticky'
 */
function moderation_switch_attribute($obj_id, $obj_type, $attribute) {
  global $user;
  
  if ($obj_type == 'node') {
    $status_new = !db_result(db_query("SELECT %s FROM {node} WHERE nid=%d", $attribute, $obj_id));
    $success = db_query("UPDATE {node} SET %s=%d WHERE nid=%d", $attribute, $status_new, $obj_id);
  }
  else if ($obj_type == 'comment') {
    $status_new = !db_result(db_query("SELECT %s FROM {comments} WHERE cid=%d", $attribute, $obj_id));
    $success = db_query("UPDATE {comments} SET %s=%d WHERE cid=%d", $attribute, $status_new, $obj_id);
  }
  db_query("INSERT INTO {moderation} SET obj_id=%d, obj_type='%s', uid=%d, attribute='%s', status=%d, created=%d", $obj_id, $obj_type, $user->uid, $attribute, $status_new, time());
  return array($success, $status_new, $attribute);
}
/**
 * Get the preview markup for a node or a comment
 * 
 * @param integer $obj_id
 * @param string $obj_type
 */
function moderation_get_preview($obj_id, $obj_type) {
  if ($obj_type == 'node') { 
    if ($node = node_load($obj_id)) {
      $data = theme('moderation_node_preview', $node);
    }
  }
  else if ($obj_type == 'comment') {
    if ($comment = _comment_load($obj_id)) {
      $_GET['q'] = 'node/'. $comment->nid;
      $data = theme('comment_preview', $comment);
    }
  }
  print drupal_to_js($data);
  exit();
}
/**
 * Get an objects attribute
 *
 * @param integer $obj_id
 * @param string $obj_type
 * @param string $attribute one of 'status', 'promote', 'sticky', 'moderate'
 */
function moderation_get_attribute($obj_id, $obj_type, $attribute) {
  $table = ($obj_type == 'comment') ? 'comments' : 'node';
  $id    = ($obj_type == 'comment') ? 'cid'      : 'nid';
  
  if ($attribute == 'moderate') {
    print drupal_to_js(array(db_result(db_query("SELECT status FROM {moderation_moderation} WHERE obj_id=%d AND obj_type='%s'", $obj_id, $obj_type))));
  }
  else {
    print drupal_to_js(array(db_result(db_query("SELECT %s FROM {%s} WHERE %s=%d", $attribute , $table, $id, $obj_id))));
  }
  
  exit();
}
/**
 * Display a node preview for display during node creation and editing.
 *
 * @param $node
 *   The node object which is being previewed.
 */
function theme_moderation_node_preview($node) {
  $output = '';
  if ($node->teaser && $node->teaser != $node->body) {
    $output .= '
'. t('Preview trimmed version') .'
';
    $output .= node_view(drupal_clone($node), 1, FALSE, 0);
    $output .= ''. t('Preview full version') .'
';
    $output .= node_view($node, 0, FALSE, 0);
  }
  else {
    $output .= node_view($node, 0, FALSE, 0);
  }
  $output .= "\n";
  return $output;
}
function moderation_admin_settings() {
  $form['moderation_moderated_types'] = array(
    '#type' => 'checkboxes',
    '#options' => node_get_types('names'),
    '#default_value' => variable_get('moderation_moderated_types', array()),
    '#title' => t('Set nodetypes shown which are moderated'),
  );
  return system_settings_form($form);
}
function moderation_is_moderated_type($type) {
  $types = variable_get('moderation_moderated_types', array());
  return ($types[$type]);
}
function moderation_log($type = 'node', $obj_id = NULL) {
  switch ($type) {
    case 'comment':
      $sql = "SELECT m.*, c.nid, c.cid, c.subject, u.uid, u.name FROM {moderation} m 
                LEFT JOIN {comments} c ON c.cid = m.obj_id 
                LEFT JOIN {users} u ON u.uid = m.uid 
                WHERE m.obj_type = 'comment' " . ($obj_id ? 'AND m.obj_id = ' . $obj_id : '') . " ORDER BY m.created DESC";
      break;
    case 'node':
      $sql = "SELECT m.*, n.title, n.nid, u.uid, u.name FROM {moderation} m 
                LEFT JOIN {node} n ON n.nid = m.obj_id 
                LEFT JOIN {users} u ON u.uid = m.uid
                WHERE m.obj_type = 'node' " . ($obj_id ? 'AND m.obj_id = ' . $obj_id : '') . " ORDER BY m.created DESC";
      break;
  }
  $result = pager_query($sql, 25, 0, NULL);
  while ($moderation = db_fetch_object($result)) {
    $title = $moderation->subject ? $moderation->subject : $moderation->title;
    $fragment = $moderation->cid ? 'comment-' . $moderation->cid : NULL;
    
    $user->uid = $moderation->uid;
    $user->name = $moderation->name;
    
    $moderations[] = array(
      l($title, 'node/' . $moderation->nid, array(), NULL, $fragment),
      theme('username', $user),
      moderation_log_message($moderation->attribute, $moderation->status, $type),
      format_date($moderation->created),
    );
  }
  $header = array(
    t('Title'), t('User'), t('Action'), t('Date'),
  );
  $output = theme('table', $header, $moderations);
  $output .= theme('pager');
  return $output;
}
function moderation_log_message($attribute, $status, $type) {
  switch ($attribute) {
    case 'status':
      $message = $status ? t('Published') : t('Unpublished');
      break;
    case 'moderate':
      $message = $status ? t('Moderated') : t('Unmoderated');
      break;
    case 'sticky':
      $message = $status ? t('Made sticky') : t('Removed stickyness');
      break;
    case 'promote':
      $message = $status ? t('Promoted') : t('Not promoted');
      break;
  }
  return $message;
}
/**
 * Redirect to a node/comment
 */
function moderation_goto($obj_id, $obj_type) {
  if ($obj_type == 'node') {
    drupal_goto('node/'. $obj_id);
  }
  else {
    if ($comment = _comment_load($obj_id)) {
      drupal_goto('node/'. $comment->nid, NULL, 'comment-'. $comment->cid);
    }
  }
}