You are here

comment_goodness.module in Comment goodness 7

Comment goodness provides newest to oldest comment sorting

This module extends the sort_comments module by blackice78

File

comment_goodness.module
View source
<?php

/**
 * @file
 *
 * Comment goodness provides newest to oldest comment sorting
 *
 * This module extends the sort_comments module by blackice78
 * @see http://drupal.org/project/sort_comments
 */

/**
 *  Constants
 */
define('comment_goodness_OLDER_FIRST', 1);

// default
define('comment_goodness_NEWER_FIRST', 2);
define('comment_goodness_FORM_PLACEMENT_SORT', 1);
define('comment_goodness_FORM_PLACEMENT_TOP', 2);
define('comment_goodness_FORM_PLACEMENT_BOTTOM', 3);
define('comment_goodness_COMMENT_SECTION_LABEL', t('Comments'));
define('comment_goodness_COMMENT_FORM_LABEL', t('Post new comment'));

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Provide additional comment configurations on the content type edit form.
 */
function comment_goodness_form_node_type_form_alter(&$form, $form_state) {
  $form['comment']['comment_created_date_format'] = array(
    '#title' => t('Post date format'),
    '#type' => 'select',
    '#options' => comment_goodness_date_format_type_options(),
    '#default_value' => variable_get('comment_created_date_format_' . $form['#node_type']->type, 'medium'),
  );
  $form['comment']['comment_changed_date_format'] = array(
    '#title' => t('Update date format'),
    '#type' => 'select',
    '#options' => comment_goodness_date_format_type_options(),
    '#default_value' => variable_get('comment_changed_date_format_' . $form['#node_type']->type, 'medium'),
  );
  $form['comment']['comment_default_sorting'] = array(
    '#title' => t('Sort order'),
    '#type' => 'select',
    '#options' => array(
      1 => t('Older first'),
      2 => t('Newer first'),
    ),
    '#default_value' => variable_get('comment_default_sorting_' . $form['#node_type']->type, comment_goodness_OLDER_FIRST),
  );
  $form['comment']['comment_form_placement'] = array(
    '#title' => t('Comment form location'),
    '#type' => 'select',
    '#options' => array(
      1 => t('Depending on sort order'),
      2 => t('Above existing comments'),
      3 => t('Below existing comments'),
    ),
    '#default_value' => variable_get('comment_form_placement_' . $form['#node_type']->type, comment_goodness_FORM_PLACEMENT_BOTTOM),
  );
  $form['comment']['comment_section_label'] = array(
    '#title' => t('Comment section label'),
    '#type' => 'textfield',
    '#default_value' => variable_get('comment_section_label_' . $form['#node_type']->type, comment_goodness_COMMENT_SECTION_LABEL),
  );
  $form['comment']['comment_form_label'] = array(
    '#title' => t('New comment form label'),
    '#type' => 'textfield',
    '#default_value' => variable_get('comment_form_label_' . $form['#node_type']->type, comment_goodness_COMMENT_FORM_LABEL),
  );

  // Set "Comments per page" setting to textfield so it allows more gradual
  // control over the number of comments to show.
  $form['comment']['comment_default_per_page']['#type'] = 'textfield';
  $form['comment']['comment_default_per_page']['#required'] = TRUE;
  $form['comment']['comment_default_per_page']['#element_validate'] = array(
    'element_validate_integer_positive',
  );
  unset($form['comment']['comment_default_per_page']['#options']);
  $comment_expose_fields_value = variable_get('comment_expose_fields_' . $form['#node_type']->type, 0);
  $form['comment']['comment_expose_fields'] = array(
    '#title' => t('Expose comment properties as pseudo-fields'),
    '#description' => t('Allow comment properties to be managed on the "Comment display" form.'),
    '#type' => 'checkbox',
    '#default_value' => $comment_expose_fields_value,
  );
  $form['#submit'][] = 'comment_goodness_node_type_form_submit';
}

/**
 * Custom submit handler for node_type_form: clears fields cache if needed.
 */
function comment_goodness_node_type_form_submit($form, &$form_state) {
  if ($form['comment']['comment_expose_fields']['#default_value'] != $form_state['values']['comment_expose_fields']) {
    cache_clear_all('field_info_fields', 'cache_field');
  }
}

/**
 * Implements hook_query_TAG_alter().
 *
 * Alter comments query to order by DESC as well as the default ASC.
 *
 * The default ASC ordering of threaded comments looks like this
 * where 1 is older than 2.
 *
 * 1
 * 1.1
 * 1.1.1
 * 1.2
 * 2
 * 2.1
 * 2.1.1
 * 2.1.2
 * 2.2
 *
 * DESC ordering of threaded comments (newest to oldest) should look like this.
 *
 * 2
 * 2.2
 * 2.1
 * 2.1.2
 * 2.1.1
 * 1
 * 1.2
 * 1.1
 * 1.1.1
 *
 */
function comment_goodness_query_comment_filter_alter(QueryAlterableInterface $query) {
  if (($node = $query
    ->getMetaData('node')) && get_class($query) == 'PagerDefault') {

    // Get the configured default sort ordering for this node type.
    $sort = variable_get('comment_default_sorting_' . $node->type, comment_goodness_OLDER_FIRST);

    // The default ordering is ASC (older on top). If the configured sorting is
    // newer on top, change the ordering to DESC.
    if ($sort == comment_goodness_NEWER_FIRST) {
      $orderby =& $query
        ->getOrderBy();
      $expressions =& $query
        ->getExpressions();

      // Sorting for threaded comments.
      if (isset($orderby['torder'])) {

        // Get rid of the expressions that prepare the threads for ASC ordering.
        unset($expressions['torder']);
        unset($orderby['torder']);

        // Simply order by the thread field.
        $orderby['c.thread'] = 'DESC';
      }
      else {
        $direction = 'DESC';
        if (isset($orderby['c.cid'])) {
          unset($orderby['c.cid']);
        }
        $orderby['c.created'] = $direction;
        $orderby['c.cid'] = $direction;
      }
    }
  }
}

/**
 * Options callback: get available date types with human readable labels.
 *
 * @return array
 *   date type => date type title (example date)
 */
function comment_goodness_date_format_type_options() {
  $options = array();
  $format_types = system_get_date_types();
  if (!empty($format_types)) {
    foreach ($format_types as $type => $type_info) {
      $options[$type] = $type_info['title'] . ' (' . format_date(REQUEST_TIME, $type) . ')';
    }
  }
  return $options;
}

/**
 * Implements hook_menu().
 */
function comment_goodness_menu() {
  $items = array();
  $items['comment/%comment/delete-own'] = array(
    'title' => 'Delete',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'comment_goodness_confirm_delete',
      1,
    ),
    'access callback' => 'comment_goodness_delete_comment_access',
    'access arguments' => array(
      1,
    ),
    'type' => MENU_CALLBACK,
    'weight' => 2,
  );
  return $items;
}

/**
 * Implements hook_menu_alter().
 *
 * Override the comment_permalink function. The comment module assumes ASC order
 * and because of this, permalinks do not work with DESC sorted comments.
 */
function comment_goodness_menu_alter(&$items) {
  if (isset($items['comment/%'])) {
    $items['comment/%']['page callback'] = 'comment_goodness_permalink';
  }
}

/**
 * Implements hook_theme_registry_alter().
 *
 * Override the core comment-wrapper and comment template with the template in
 * this module.
 */
function comment_goodness_theme_registry_alter(&$theme_registry) {
  if (isset($theme_registry['comment_wrapper'])) {
    $comment_wrapper = $theme_registry['comment_wrapper'];

    // If the current template belongs to the core comment module, replace it.
    if (isset($comment_wrapper['template']) && $comment_wrapper['template'] === 'modules/comment/comment-wrapper') {
      $path = drupal_get_path('module', 'comment_goodness');
      $theme_registry['comment_wrapper']['template'] = $path . '/templates/comment-wrapper';
    }
  }
  if (isset($theme_registry['comment'])) {
    $comment = $theme_registry['comment'];

    // If the current template belongs to the core comment module, replace it.
    if (isset($comment['template']) && $comment['template'] === 'modules/comment/comment') {
      $path = drupal_get_path('module', 'comment_goodness');
      $theme_registry['comment']['template'] = $path . '/templates/comment';
    }
  }
}

/**
 * Implements hook_permission().
 */
function comment_goodness_permission() {
  return array(
    'delete own comments' => array(
      'title' => t('Delete own comments'),
      'description' => t('Allows a user to delete own comments that have no replies (e.g. all if in flat mode).'),
    ),
  );
}

/**
 * Access callback for deleting own comment.
 */
function comment_goodness_delete_comment_access($comment) {
  global $user;
  $access = $user->uid && $user->uid == $comment->uid && $comment->status == COMMENT_PUBLISHED && (user_access('delete own comments') || user_access('administer comments'));

  // Deletion is not allowed if any comment has this comment as a parent.
  return $access && 0 == db_query("SELECT COUNT(cid) FROM {comment} WHERE pid = :cid", array(
    ':cid' => $comment->cid,
  ))
    ->fetchField();
}

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

  // We only need to add the delete link if it's not there.
  if (!isset($comment->content['links']['comment']['#links']['comment-delete']) && comment_goodness_delete_comment_access($comment)) {
    $comment->content['links']['comment']['#links']['comment-delete'] = array(
      'title' => t('delete'),
      'href' => "comment/{$comment->cid}/delete-own",
      'html' => TRUE,
    );
  }
  $node = node_load($comment->nid);
  if (variable_get('comment_expose_fields_' . $node->type, FALSE)) {
    $account = user_load($comment->uid);
    $uri = entity_uri('comment', $comment);
    $uri['options'] += array(
      'attributes' => array(
        'class' => 'permalink',
        'rel' => 'bookmark',
      ),
    );
    if (variable_get('comment_subject_field_' . $node->type, 1) == 1) {
      if (!isset($comment->content['subject'])) {
        $comment->content['subject'] = array(
          '#type' => 'link',
          '#title' => $comment->subject,
          '#href' => $uri['path'],
          '#options' => $uri['options'],
        );
      }
    }
    if (!isset($comment->content['author'])) {
      $comment->content['author'] = array(
        '#type' => 'item',
        '#theme' => 'username',
        '#account' => $account,
      );
    }
    if (variable_get('user_signatures', 1) == 1 && !isset($comment->content['signature'])) {
      $comment->content['signature'] = array(
        '#type' => 'item',
        '#markup' => !empty($comment->signature_format) ? check_markup($comment->signature, $comment->signature_format, $langcode) : check_plain($comment->signature),
      );
    }
    if (theme_get_setting('toggle_comment_user_picture') && !isset($comment->content['picture'])) {
      $comment->content['picture'] = array(
        '#type' => 'item',
        '#theme' => 'user_picture',
        '#account' => $account,
      );
    }
    if (!isset($comment->content['created'])) {
      $comment->content['created'] = array(
        '#type' => 'item',
        '#markup' => format_date($comment->created, variable_get('comment_created_date_format_' . $node->type, 'medium')),
      );
    }
    if (!isset($comment->content['changed'])) {
      $comment->content['changed'] = array(
        '#type' => 'item',
        '#markup' => format_date($comment->created, variable_get('comment_changed_date_format_' . $node->type, 'medium')),
      );
    }
    if (!isset($comment->content['new'])) {
      $comment->content['new'] = array(
        '#type' => 'item',
        '#markup' => !empty($comment->new) ? t('new') : '',
      );
    }
    if (!isset($comment->content['permalink'])) {
      $comment->content['permalink'] = array(
        '#type' => 'link',
        '#title' => t('Permalink'),
        '#href' => $uri['path'],
        '#options' => $uri['options'],
      );
    }
    if (!isset($comment->content['submitted'])) {
      $date_type = variable_get('comment_created_date_format_' . $node->type, 'medium');
      $submitted_string = _comment_goodness_get_submitted_string($date_type);
      $comment->content['submitted'] = array(
        '#type' => 'item',
        '#markup' => t($submitted_string, array(
          '!username' => theme('username', array(
            'account' => $account,
          )),
          '!datetime' => format_date($comment->created, $date_type),
        )),
      );
    }
  }
}

/**
 * Confirm form for deleting own comment.
 *
 * We can't use the core comment_confirm_delete() because it talks about
 * deleting replies, and also mollom hooks into that form which is not
 * appropriate for end-users.
 */
function comment_goodness_confirm_delete($form, &$form_state, $comment) {
  $form['#comment'] = $comment;

  // Always provide entity id in the same form key as in the entity edit form.
  $form['cid'] = array(
    '#type' => 'value',
    '#value' => $comment->cid,
  );
  return confirm_form($form, t('Are you sure you want to delete the comment %title?', array(
    '%title' => $comment->subject,
  )), 'node/' . $comment->nid, t('This action cannot be undone.'), t('Delete'), t('Cancel'), 'comment_goodness_confirm_delete');
}

/**
 * Form submit function copied from comment_confirm_delete_submit().
 *
 * The user-visible and watchdog messages are different from core.
 */
function comment_goodness_confirm_delete_submit($form, &$form_state) {
  global $user;
  $comment = $form['#comment'];

  // Delete the comment and its replies.
  comment_delete($comment->cid);
  drupal_set_message(t('The comment has been deleted.'));
  watchdog('content', 'User %name (@uid) deleted own comment @cid.', array(
    '%name' => $user->name,
    '@uid' => $user->uid,
    '@cid' => $comment->cid,
  ));

  // Clear the cache so an anonymous user sees that his comment was deleted.
  cache_clear_all();
  $form_state['redirect'] = "node/{$comment->nid}";
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * When a new comment is submitted, the core comment module calculates that new
 * comment's position in the list of comments and then provides a redirect URL
 * to the new comment on the subsequent page load. Because the comment module
 * assumes ASC sort ordering, the redirect URL for paged comments is incorrect
 * when the comments are DESC sort ordered. So this module overrides much of the
 * core comment module code for calculating the position of a new comment in the
 * paged list of DESC sorted comments.
 *
 * The overriding starts with adding an additional new comment form submit
 * handler.
 *
 * Disabling the submit actions while the comment body is empty also happens
 * here.
 */
function comment_goodness_form_comment_form_alter(&$form, &$form_state, $form_id) {
  $form['#submit'][] = 'comment_goodness_form_submit';

  // Disable preview button.
  _comment_goodness_disable_actions($form);
}

/**
 * Helper function to disable the form submit actions while the comment body is
 * empty.
 */
function _comment_goodness_disable_actions(&$form) {
  $node_language = $form['#node']->language;
  $disable_button_state = array(
    'disabled' => array(
      "textarea[name=\"comment_body[{$node_language}][0][value]\"]" => array(
        'empty' => TRUE,
      ),
    ),
  );
  foreach (array(
    'submit',
    'preview',
  ) as $button) {
    if (!isset($form['actions']['preview']['#states'])) {
      $form['actions'][$button]['#states'] = array();
    }
    $form['actions'][$button]['#states'] += $disable_button_state;
  }

  // Add css to indicate that the buttons are disabled.
  $module_path = drupal_get_path('module', 'comment_goodness');
  drupal_add_css("{$module_path}/css/disabled_actions.css");
  drupal_add_js("{$module_path}/comment_goodness.js");
}

/**
 * Form submit handler.
 *
 * @see comment_goodness_form_comment_form_alter().
 */
function comment_goodness_form_submit($form, &$form_state) {
  $node = $form['#node'];
  $comment = $form_state['comment'];
  if (user_access('post comments') && (user_access('administer comments') || $node->comment == COMMENT_NODE_OPEN)) {

    // Find the current display page for this comment.
    $query = array();
    $page = comment_goodness_get_display_page($comment->cid, $node->type);
    if ($page > 0) {
      $query['page'] = $page;
    }

    // Redirect to the newly posted comment.
    $form_state['redirect'] = array(
      'node/' . $node->nid,
      array(
        'query' => $query,
        'fragment' => 'comment-' . $comment->cid,
      ),
    );
  }
}

/**
 * Implements hook_preprocess_HOOK().
 *
 * Provide template variables to change the comment created, changed and
 * submitted by dates.
 */
function comment_goodness_preprocess_comment(&$variables) {
  $comment = $variables['elements']['#comment'];
  $variables['created'] = format_date($comment->created, variable_get('comment_created_date_format_' . $variables['node']->type, 'medium'));
  $variables['changed'] = format_date($comment->changed, variable_get('comment_changed_date_format_' . $variables['node']->type, 'medium'));
  $date_type = variable_get('comment_created_date_format_' . $variables['node']->type, 'medium');
  $submitted_string = _comment_goodness_get_submitted_string($date_type);
  $variables['submitted'] = t($submitted_string, array(
    '!username' => theme('username', array(
      'account' => $variables['author'],
    )),
    '!datetime' => $variables['created'],
  ));
}

/**
 * Implements hook_preprocess_HOOK().
 *
 * Provide a template variable to vary the placement of the comment form; either
 * above or below the comments dependent on the sort order. For ASC sorted
 * comments, the comment form is placed at the bottom of the list, near the
 * newest comment. For DESC sorted comments, the comment form is placed above
 * the comments, again, near the newest comment.
 */
function comment_goodness_preprocess_comment_wrapper(&$variables) {

  // Get the configured form placement for this node type.
  $form_placement = variable_get('comment_form_placement_' . $variables['node']->type, comment_goodness_FORM_PLACEMENT_BOTTOM);
  switch ($form_placement) {
    case comment_goodness_FORM_PLACEMENT_TOP:
      $variables['comment_form_placement'] = 'top';
      break;
    case comment_goodness_FORM_PLACEMENT_BOTTOM:
      $variables['comment_form_placement'] = 'bottom';
      break;
    case comment_goodness_FORM_PLACEMENT_SORT:
    default:

      // Bottom placement of the comment form is the Drupal default.
      $variables['comment_form_placement'] = 'bottom';

      // Get the configured default sort ordering for this node type.
      $sort = variable_get('comment_default_sorting_' . $variables['node']->type, comment_goodness_OLDER_FIRST);

      // Indicate that the comment form should be rendered above the comments
      // if the sort order is newest to oldest (ASC).
      if ($sort == comment_goodness_NEWER_FIRST) {
        $variables['comment_form_placement'] = 'top';
      }
      break;
  }

  // Get the section labels
  $comment_section_label = variable_get('comment_section_label_' . $variables['node']->type, comment_goodness_COMMENT_SECTION_LABEL);
  $comment_form_label = variable_get('comment_form_label_' . $variables['node']->type, comment_goodness_COMMENT_FORM_LABEL);

  // Add the labels to the page variables
  $variables['labels'] = array(
    'section_label' => check_plain($comment_section_label),
    'form_label' => check_plain($comment_form_label),
  );
}

/**
 * Return the page number for a comment.
 *
 * Finds the correct page number for a comment taking into account display,
 * paging settings and sort order.
 *
 * @param $cid
 *   The comment ID.
 * @param $node_type
 *   The node type the comment is attached to.
 * @return
 *   The page number.
 * @see comment_get_display_page
 */
function comment_goodness_get_display_page($cid, $node_type) {
  $ordinal = comment_goodness_get_display_ordinal($cid, $node_type);
  $comments_per_page = variable_get('comment_default_per_page_' . $node_type, 50);
  return floor($ordinal / $comments_per_page);
}

/**
 * Redirects comment links to the correct page depending on comment settings.
 *
 * Since comments are paged there is no way to guarantee which page a comment
 * appears on. Comment paging and threading settings may be changed at any time.
 * With threaded comments, an individual comment may move between pages as
 * comments can be added either before or after it in the overall discussion.
 * Therefore we use a central routing function for comment links, which
 * calculates the page number based on current comment settings and returns
 * the full comment view with the pager set dynamically.
 *
 * @param $cid
 *   A comment identifier.
 * @return
 *   The comment listing set to the page on which the comment appears.
 *
 * @see comment_permalink()
 */
function comment_goodness_permalink($cid) {
  if (($comment = comment_load($cid)) && ($node = node_load($comment->nid))) {

    // Find the current display page for this comment.
    $page = comment_goodness_get_display_page($comment->cid, $node->type);

    // Set $_GET['q'] and $_GET['page'] ourselves so that the node callback
    // behaves as it would when visiting the page directly.
    $_GET['q'] = 'node/' . $node->nid;
    $_GET['page'] = $page;

    // Return the node view, this will show the correct comment in context.
    return menu_execute_active_handler('node/' . $node->nid, FALSE);
  }
  return MENU_NOT_FOUND;
}

/**
 * Get the display ordinal for a comment, starting from 0.
 *
 * Count the number of comments which appear before the comment we want to
 * display, taking into account display settings, threading and sort order.
 *
 * @param $cid
 *   The comment ID.
 * @param $node_type
 *   The node type of the comment's parent.
 * @return
 *   The display ordinal for the comment.
 *
 * @see comment_get_display_ordinal()
 */
function comment_goodness_get_display_ordinal($cid, $node_type) {

  // Count how many comments (c1) are before $cid (c2) in display order. This is
  // the 0-based display ordinal.
  $query = db_select('comment', 'c1');
  $query
    ->innerJoin('comment', 'c2', 'c2.nid = c1.nid');
  $query
    ->addExpression('COUNT(*)', 'count');
  $query
    ->condition('c2.cid', $cid);
  if (!user_access('administer comments')) {
    $query
      ->condition('c1.status', COMMENT_PUBLISHED);
  }

  // Get the configured default sort ordering for this node type.
  $sort = variable_get('comment_default_sorting_' . $node_type, comment_goodness_OLDER_FIRST);
  $operation = $sort == comment_goodness_NEWER_FIRST ? '>' : '<';
  $mode = variable_get('comment_default_mode_' . $node_type, COMMENT_MODE_THREADED);
  if ($mode == COMMENT_MODE_FLAT) {

    // For flat comments, cid is used for ordering comments due to
    // unpredicatable behavior with timestamp, so we make the same assumption
    // here.
    $query
      ->condition('c1.cid', $cid, $operation);
  }
  else {

    // For threaded comments, the c.thread column is used for ordering.
    if ($sort == comment_goodness_NEWER_FIRST) {

      // For newer to older sorted comments, we look for how many comments have
      // a higher thread value than the current comment.
      $query
        ->where('c1.thread ' . $operation . ' c2.thread');
    }
    else {

      // We can use the vancode for comparison, but must remove the
      // trailing slash.
      // See comment_view_multiple().
      $query
        ->where('SUBSTRING(c1.thread, 1, (LENGTH(c1.thread) -1)) ' . $operation . ' SUBSTRING(c2.thread, 1, (LENGTH(c2.thread) -1))');
    }
  }
  return $query
    ->execute()
    ->fetchField();
}

/**
 * Implements hook_field_extra_fields().
 */
function comment_goodness_field_extra_fields() {
  $return = array();
  foreach (node_type_get_types() as $type) {
    $comment_bundle = 'comment_node_' . $type->type;
    if (variable_get('comment_expose_fields_' . $type->type, FALSE)) {
      $return['comment'][$comment_bundle]['display']['author'] = array(
        'label' => t('Author'),
        'description' => t('Author of comment'),
        'weight' => -10,
      );
      if (variable_get('comment_subject_field_' . $type->type, 1) == 1) {
        $return['comment'][$comment_bundle]['display']['subject'] = array(
          'label' => t('Subject'),
          'description' => t('Subject of comment'),
          'weight' => -9,
        );
      }
      if (variable_get('user_signatures', 1) == 1) {
        $return['comment'][$comment_bundle]['display']['signature'] = array(
          'label' => t('Signature'),
          'description' => t('Signature of author'),
          'weight' => -8,
        );
      }
      if (theme_get_setting('toggle_comment_user_picture')) {
        $return['comment'][$comment_bundle]['display']['picture'] = array(
          'label' => t('Picture'),
          'description' => t('Avatar image of author'),
          'weight' => -7,
        );
      }
      $return['comment'][$comment_bundle]['display']['created'] = array(
        'label' => t('Created'),
        'description' => t('Comment creation date'),
        'weight' => -6,
      );
      $return['comment'][$comment_bundle]['display']['changed'] = array(
        'label' => t('Changed'),
        'description' => t('Comment update date'),
        'weight' => -5,
      );
      $return['comment'][$comment_bundle]['display']['new'] = array(
        'label' => t('New'),
        'description' => t('String showing if comment is new'),
        'weight' => -4,
      );
      $return['comment'][$comment_bundle]['display']['permalink'] = array(
        'label' => t('Permalink'),
        'description' => t('Permalink to comment'),
        'weight' => -3,
      );
      $return['comment'][$comment_bundle]['display']['submitted'] = array(
        'label' => t('Submitted by'),
        'description' => t('Information about who and when submitted the comment'),
        'weight' => -2,
      );
      $return['comment'][$comment_bundle]['display']['links'] = array(
        'label' => t('Links'),
        'description' => t('Comment action links'),
        'weight' => -1,
      );
    }
  }
  return $return;
}

/**
 * Checks if $date_type uses a Timeago date format.
 *
 * @param string $date_type
 *   The name of an existing date type.
 *
 * @return bool
 *   If $date_type uses a Timeago date format.
 */
function _comment_goodness_uses_timeago_format($date_type) {
  if (module_exists('timeago')) {
    $date_type_format = variable_get('date_format_' . $date_type);
    $timeago_formats = array(
      TIMEAGO_FORMAT_SHORT_US,
      TIMEAGO_FORMAT_SHORT,
      TIMEAGO_FORMAT_MEDIUM_US,
      TIMEAGO_FORMAT_MEDIUM,
      TIMEAGO_FORMAT_LONG_US,
      TIMEAGO_FORMAT_LONG,
    );
    return in_array($date_type_format, $timeago_formats);
  }
  else {
    return FALSE;
  }
}

/**
 * Returns the proper format of the 'Submitted' string.
 *
 * Checks if Timeago is used by $date_type and returns the correct 'Submitted'
 * string.
 *
 * @param $date_type
 *   Date type to check.
 *
 * @return string
 *   'Submitted' string.
 *
 * @see _comment_goodness_uses_timeago_format()
 */
function _comment_goodness_get_submitted_string($date_type) {
  if (_comment_goodness_uses_timeago_format($date_type)) {
    $submitted_string = 'Submitted by !username !datetime';
  }
  else {
    $submitted_string = 'Submitted by !username on !datetime';
  }
  return $submitted_string;
}

Functions

Namesort descending Description
comment_goodness_comment_view Implements hook_comment_view().
comment_goodness_confirm_delete Confirm form for deleting own comment.
comment_goodness_confirm_delete_submit Form submit function copied from comment_confirm_delete_submit().
comment_goodness_date_format_type_options Options callback: get available date types with human readable labels.
comment_goodness_delete_comment_access Access callback for deleting own comment.
comment_goodness_field_extra_fields Implements hook_field_extra_fields().
comment_goodness_form_comment_form_alter Implements hook_form_FORM_ID_alter().
comment_goodness_form_node_type_form_alter Implements hook_form_FORM_ID_alter().
comment_goodness_form_submit Form submit handler.
comment_goodness_get_display_ordinal Get the display ordinal for a comment, starting from 0.
comment_goodness_get_display_page Return the page number for a comment.
comment_goodness_menu Implements hook_menu().
comment_goodness_menu_alter Implements hook_menu_alter().
comment_goodness_node_type_form_submit Custom submit handler for node_type_form: clears fields cache if needed.
comment_goodness_permalink Redirects comment links to the correct page depending on comment settings.
comment_goodness_permission Implements hook_permission().
comment_goodness_preprocess_comment Implements hook_preprocess_HOOK().
comment_goodness_preprocess_comment_wrapper Implements hook_preprocess_HOOK().
comment_goodness_query_comment_filter_alter Implements hook_query_TAG_alter().
comment_goodness_theme_registry_alter Implements hook_theme_registry_alter().
_comment_goodness_disable_actions Helper function to disable the form submit actions while the comment body is empty.
_comment_goodness_get_submitted_string Returns the proper format of the 'Submitted' string.
_comment_goodness_uses_timeago_format Checks if $date_type uses a Timeago date format.

Constants