You are here

comment_alter.module in Comment Alter 7

Same filename and directory in other branches
  1. 8 comment_alter.module

Provides UI to alter nodes' parameters from comment forms.

@author CSÉCSY László <boobaa@kybest.hu>

File

comment_alter.module
View source
<?php

/**
 * @file
 * Provides UI to alter nodes' parameters from comment forms.
 *
 * @author
 * CSÉCSY László <boobaa@kybest.hu>
 */

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * @see comment_alter_form_field_ui_field_edit_form_alter_submit()
 */
function comment_alter_form_field_ui_field_edit_form_alter(&$form, &$form_state, $form_id) {

  // Image fields fields are not supported by now, peroid.
  // Field collection not currently supported by Diff module.
  // @see http://drupal.org/node/1897196
  if ($form['#field']['type'] == 'image' || $form['#field']['type'] == 'field_collection') {
    return;
  }
  if (isset($form['instance']) && $form['instance']['entity_type']['#value'] == 'node') {
    $bundle_name = $form['instance']['bundle']['#value'];
    $field_name = $form['instance']['field_name']['#value'];
    $comment_fields = field_info_instances('comment', 'comment_node_' . $bundle_name);

    // Additional custom field values will be automatically stored in the
    // database, so custom save mechanism is not necessary.
    $form['instance']['comment_alter'] = array(
      '#type' => 'checkbox',
      '#title' => t('Enable altering this field from comments.'),
      '#weight' => $form['instance']['required']['#weight'] + 0.5,
      '#default_value' => !empty($form['#instance']['comment_alter']),
    );
    $form['instance']['comment_alter_hide'] = array(
      '#type' => 'checkbox',
      '#title' => t('Hide alterations of this field from diffs.'),
      '#weight' => $form['instance']['required']['#weight'] + 0.7,
      '#default_value' => !empty($form['#instance']['comment_alter_hide']),
      '#states' => array(
        'invisible' => array(
          ':input[name="instance[comment_alter]"]' => array(
            'checked' => FALSE,
          ),
        ),
      ),
    );

    // Make sure the field isn't already on the Comment entity.
    if (!empty($comment_fields[$field_name])) {
      $form['instance']['comment_alter']['#default_value'] = FALSE;
      $form['instance']['comment_alter']['#disabled'] = TRUE;
      $form['instance']['comment_alter']['#description'] = '<span class="error">' . t('This field also exists on the comment. You must remove it from the comment in order to enable altering this field from comments.') . '</span>';
    }
  }
}

/**
 * Returns the comment-alterable fields for a content type.
 *
 * @param string $content_type
 *   Node object, at least with the type property.
 * @return array
 *   Array of the comment-alterable fields for that content type.
 */
function comment_alter_get_alterable_fields($content_type) {
  $comment_alter_fields =& drupal_static(__FUNCTION__);
  if (!isset($comment_alter_fields[$content_type])) {
    $field_infos = field_info_instances('node', $content_type);
    $comment_fields = field_info_instances('comment', 'comment_node_' . $content_type);
    $comment_alter_fields[$content_type] = array();
    foreach ($field_infos as $field_name => $value) {
      if (!empty($value['comment_alter']) && empty($comment_fields[$field_name])) {
        $comment_alter_fields[$content_type][] = $field_name;
      }
    }
  }
  return $comment_alter_fields[$content_type];
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Don't allow users to add existing fields if they are alterable from comment
 * on the parent node bundle.
 */
function comment_alter_form_field_ui_field_overview_form_alter(&$form, &$form_state) {
  if ($form['#entity_type'] == 'comment') {

    // Remove 'comment_node_' from the beginning of the bundle name to get the
    // node bundle name.
    $node_bundle_name = substr($form['#bundle'], 13);
    $comment_alter_fields = comment_alter_get_alterable_fields($node_bundle_name);
    if (!empty($comment_alter_fields)) {
      $field_options =& $form['fields']['_add_existing_field']['field_name']['#options'];
      foreach ($field_options as $field_name => $field_label) {
        if (in_array($field_name, $comment_alter_fields)) {

          // Remove fields that are alterable from comment on the parent node.
          unset($field_options[$field_name]);
        }
      }
    }
  }
}

/**
 * Implements hook_requirements().
 *
 * If somehow a field is added to a comment bundle which is also alterable from
 * comment on the parent node bundle, put a message on the system status report.
 *
 * We've made it impossible to do this via the UI, but it's still possible via
 * low-level trickery, so this is a fallback to alert site administrators of a
 * problem.
 */
function comment_alter_requirements($phase) {
  $requirements = array();
  if ($phase == 'runtime') {
    foreach (node_type_get_types() as $bundle_name => $type_obj) {

      // Get the comment alter fields directly, rather than via
      // comment_alter_get_alterable_fields(), because it will remove the fields
      // which are on the comment.
      $field_infos = field_info_instances('node', $bundle_name);
      $comment_alter_fields = array();
      foreach ($field_infos as $field_name => $value) {
        if (!empty($value['comment_alter'])) {
          $comment_alter_fields[] = $field_name;
        }
      }
      if (!empty($comment_alter_fields)) {
        $comment_fields = field_info_instances('comment', 'comment_node_' . $bundle_name);
        foreach ($comment_fields as $field_name => $field_instance) {
          if (in_array($field_name, $comment_alter_fields)) {
            $requirements[] = array(
              'title' => t('Comment alter'),
              'value' => t('Invalid fields error'),
              'description' => t('The %field_name field exists on the comment and is alterable from comment on the parent node. Please remove it from the comment or disable altering it from comment!', array(
                '%field_name' => $field_name,
              )),
              'severity' => REQUIREMENT_ERROR,
            );
          }
        }
      }
    }
  }
  return $requirements;
}

/**
 * Implements hook_form_BASE_FORM_ID_alter().
 *
 * @see _comment_alter_submit_node_fields()
 */
function comment_alter_form_comment_form_alter(&$form, &$form_state, $form_id) {

  // Check if we are on the reply-to-comment form and if it should contain
  // comment_alterable fields at all (bail out early if needed).
  if ($form['pid']['#value'] && variable_get('comment_alter_root_only_' . $form['#node']->type, 0)) {
    return;
  }

  // Load the latest revision instead of the current if asked for.
  if (variable_get('comment_alter_' . $form['#node']->type, 0)) {
    $vid = db_select('node_revision', 'nr')
      ->fields('nr', array(
      'vid',
    ))
      ->condition('nid', $form['#node']->nid)
      ->orderBy('timestamp', 'DESC')
      ->range(0, 1)
      ->execute()
      ->fetchField();
  }
  else {
    $vid = NULL;
  }
  $node = node_load($form['#node']->nid, $vid);
  $comment_alter_fields = comment_alter_get_alterable_fields($node->type);

  // Add widgets to comment form if comment form is new, and if comment alter
  // fields are available.
  if (empty($form['cid']['#value']) && !empty($comment_alter_fields)) {

    // Every comment alter field goes to the root of the comment form so this
    // enables that other modules can re-order or group the fields.
    $field_infos = field_info_extra_fields('comment', 'comment_node_' . $node->type, 'form');

    // The _comment_alter_submit_node_fields() function needs these two arrays.
    // This one is a list of comment_alterable fields.
    $alterable_fields = array();

    // This one informs about comment_alterable columns per comment_alterable
    // fields. First-level key is the field name, second-level keys (and values)
    // are the columns which do have their form elements.
    $alterable_columns = array();
    foreach ($comment_alter_fields as $field_name) {

      // Attach the node field to the comment form. We do it on a copy of the
      // $form, so that we know we are only getting the field element itself and
      // no other side-effects (for example, the field_groups from the node
      // entity).
      $node_form = $form;
      field_attach_form('node', $node, $node_form, $form_state, $node->language, array(
        'field_name' => $field_name,
      ));
      if (!empty($node_form[$field_name])) {
        $form[$field_name] = $node_form[$field_name];
        $field_language = $form[$field_name]['#language'];
        $field_value = array();

        // Not sure that there is a language key in the field if the field value
        // is empty.
        if (!empty($node->{$field_name}[$field_language])) {
          $field_value[$field_language] = $node->{$field_name}[$field_language];
        }

        // Comment_alterable node fields must be amongst the comment fields
        // themselves in order to be able to properly weight/reorder them, put
        // them into a field_group, etc. on the manage comment fields form.
        $form[$field_name . '_old'] = array(
          '#type' => 'value',
          '#value' => $field_value,
        );

        // TODO: This doesn't seem to be working properly: if the extra field is
        // set to last, it even gets displayed above comment subject.
        $form[$field_name]['#weight'] = $field_infos[$field_name]['weight'];

        // Remember that this field is alterable.
        $alterable_fields[$field_name] = $field_name;

        // Fetch the alterable columns from field items themselves. If the
        // #column info is available at the top-level (eg. in the case of a
        // select), grab it from there; in other cases, grab it from the first
        // item.
        // Note: weight changes (changes in order of multivalue fields' values)
        // are not tracked.
        $field_items = $form[$field_name][$field_language];
        if (isset($field_items['#columns'])) {
          $columns = $field_items['#columns'];
        }
        else {
          $field_item = $field_items[0];
          if (isset($field_item['#columns'])) {
            $columns = $field_item['#columns'];
          }
          else {
            $field_item = reset($field_item);
            $columns = $field_item['#columns'];
          }
        }
        foreach ($columns as $column) {
          $alterable_columns[$field_name][$column] = $column;
        }
      }
    }
    if (!empty($alterable_fields)) {

      // Push down the information gathered so far to
      // _comment_alter_submit_node_fields().
      $form['comment_alter'] = array(
        '#type' => 'value',
        '#value' => array(
          'fields' => $alterable_fields,
          'old_vid' => $node->vid,
          'alterable_columns' => $alterable_columns,
        ),
      );

      // Put the node entity in $form_state so can get it in submit/validate
      // without loading it again.
      $form_state['node'] = $node;

      // Add submit/validate function so we can call
      // field_attach_form_validate() and field_attach_submit().
      $form['#validate'][] = '_comment_alter_validate_node_fields';
      $form['#submit'][] = '_comment_alter_submit_node_fields';
    }
  }
}

/**
 * Helper function to clean up field values for comparison.
 *
 * Removes 'add_more' and non-alterable columns (like _weight) so we can compare
 * the old and new field values and find changes.
 *
 * @param array $values
 *   Array whose elements should be cleaned up.
 * @param string $field_name
 *   Clean up this field of the array.
 * @param string $old = ''
 *   Suffix for old value cleanup.
 */
function _comment_alter_cleanup_field_values(&$values, $field_name, $old = '') {
  $field_value =& $values[$field_name . $old];
  $alterable_columns = $values['comment_alter']['alterable_columns'][$field_name];

  // Multiple-value fields should not have an 'add_more' delta (this comes from
  // the Field API's Form API stuff: 'add_more' delta is the 'Add more' button.
  foreach ($field_value as $language => $deltas) {
    foreach ($field_value[$language] as $delta => $columns) {
      if ($delta === 'add_more') {
        unset($field_value[$language][$delta]);
        continue;
      }

      // Non-alterable columns (eg. _weight) should be removed (from
      // comparison).
      foreach ($field_value[$language][$delta] as $column => $value) {
        if (!isset($alterable_columns[$column])) {
          unset($field_value[$language][$delta][$column]);
        }
      }
    }
  }
  _comment_alter_cleanup_arrays($field_value);
}

/**
 * Helper function to recursively clean up semi-empty arrays.
 *
 * Eg. array('foo' => array('bar' => array('baz' => ''))) becomes array().
 *
 * @param array $a
 *   Array whose empty elements should be removed.
 */
function _comment_alter_cleanup_arrays(&$a) {
  if (is_array($a)) {
    foreach ($a as $key => &$value) {
      if (is_array($value)) {
        _comment_alter_cleanup_arrays($value);
      }
      if (empty($value)) {
        unset($a[$key]);
      }
    }
  }
}

/**
 * Validation callback for the altered comment form.
 *
 * Calls form_attach_form_validate() for each of the alterable node fields.
 *
 * @see form_attach_form_validate()
 * @see comment_alter_form_comment_form_alter()
 */
function _comment_alter_validate_node_fields($form, &$form_state) {
  $node = clone $form_state['node'];
  foreach ($form_state['values']['comment_alter']['fields'] as $field_name) {
    field_attach_form_validate('node', $node, $form, $form_state, array(
      'field_name' => $field_name,
    ));
  }
}

/**
 * Submit callback for the altered comment form.
 *
 * Determines which fields have actually changed, then calls
 * form_attach_submit() on each of them, and saves the resulting node.
 *
 * @see form_attach_submit()
 * @see comment_alter_form_comment_form_alter()
 */
function _comment_alter_submit_node_fields($form, &$form_state) {
  $values = $form_state['values'];

  // Do not try to save anything if there is nothing that was allowed to be
  // changed from the comment form.
  if (isset($values['comment_alter'])) {
    $changed_fields = array();
    foreach ($values['comment_alter']['fields'] as $field_name) {
      _comment_alter_cleanup_field_values($values, $field_name);
      _comment_alter_cleanup_field_values($values, $field_name, '_old');

      // If field values have changed, add it to the list.
      if ($values[$field_name . '_old'] != $values[$field_name]) {
        $changed_fields[$field_name] = $field_name;
      }
    }
    if (!empty($changed_fields)) {
      $node = $form_state['node'];

      // Run field_attach_submit for all the changed fields.
      foreach ($form_state['values']['comment_alter']['fields'] as $field_name) {
        field_attach_submit('node', $node, $form, $form_state, array(
          'field_name' => $field_name,
        ));
      }

      // Special support for the Title field via the Title module.
      if (module_exists('title') && isset($form_state['values']['comment_alter']['fields']['title_field'])) {

        // Calling this should be enough:
        //   title_entity_sync('node', $node, $node->language);
        // But it isn't. That function uses a static variable to make sure it is
        // only run once per request, however, under certain conditions observed
        // when using Panels, title_entity_sync() can be called several times
        // before ever reaching this point. So, the following code was copied
        // from title_entity_sync() to avoid the static variable.
        $fr_info = title_field_replacement_info('node');
        if ($fr_info) {
          foreach ($fr_info as $legacy_field => $info) {
            if (title_field_replacement_enabled('node', $node->type, $legacy_field)) {
              title_field_sync_get('node', $node, $legacy_field, $info, $node->language);
            }
          }
        }
      }

      // Creating a new node revision regardless the node type settings.
      $node->revision = TRUE;

      // Disable node updated notifications that caused by comment_alter. New
      // comment notifications should be enough - this happens when submitting a
      // comment, not when editing a node, after all. This disabling is
      // unconditional: there may be other modules than notifications_content
      // that wants these notifications be disabled; reusing the same key seems
      // to be a non-issue here as it won't get stored anywhere.
      $node->notifications_content_disable = TRUE;
      node_save($node);

      // Fire the comment_alter_node_postsave hook with the $node and $comment
      // objects; though $node does not have a $node->original property, all the
      // affected fields' information (both previous and current values) are
      // available in the comment object.
      $node->original = node_load($node->nid, $values['comment_alter']['old_vid']);
      module_invoke_all('comment_alter_node_postsave', $node, $form_state['comment']);
      $comment_alter = array(
        'old_vid' => $values['comment_alter']['old_vid'],
        'new_vid' => $node->vid,
        'cid' => $values['cid'],
      );
      drupal_write_record('comment_alter', $comment_alter);
    }
  }
}

/**
 * Implements hook_comment_load().
 */
function comment_alter_comment_load($comments) {
  $result = db_select('comment_alter', 'ca')
    ->fields('ca', array(
    'cid',
    'old_vid',
    'new_vid',
  ))
    ->condition('cid', array_keys($comments), 'IN')
    ->execute();
  foreach ($result as $row) {
    $comments[$row->cid]->comment_alter['old_vid'] = $row->old_vid;
    $comments[$row->cid]->comment_alter['new_vid'] = $row->new_vid;
  }
}

/**
 * Returns the differences committed with a particular comment.
 *
 * Uses the 'Diff' module to actually generate the differences.
 *
 * @param object $comment
 *   The comment object.
 * @param string $langcode
 *   The language code used for rendering the fields.
 *
 * @return array
 *   An associative array with keys being the changed field names and values
 *   being lists of associative arrays with 3 keys:
 *   - name: field's name being changed (only for the first field value).
 *   - old: array of old field values.
 *   - new: array of new field values.
 *
 * @see diff_compare_entities()
 */
function comment_alter_get_changed_fields($comment, $langcode) {
  $changed_fields = array();
  if (isset($comment->comment_alter) && isset($comment->comment_alter['new_vid'])) {
    $node = node_load($comment->nid);
    module_load_include('inc', 'diff', 'diff.pages');
    $old_node = node_load($comment->nid, $comment->comment_alter['old_vid']);
    $new_node = node_load($comment->nid, $comment->comment_alter['new_vid']);
    $context = array(
      'entity_type' => 'node',
      'states' => array(
        'raw',
      ),
      'view_mode' => 'diff_standard',
      'language' => $langcode,
    );
    $comment_alter_fields = comment_alter_get_alterable_fields($node->type);

    // Because the 'title_field' is 'hidden' on all display modes, the Diff
    // module will skip over it. However, the diff module has special support
    // for the 'title' property, so we swap 'title_field' for 'title'.
    if (($title_field_index = array_search('title_field', $comment_alter_fields)) !== FALSE) {
      $comment_alter_fields[$title_field_index] = 'title';
    }
    $diffs = diff_compare_entities($old_node, $new_node, $context);
    foreach ($diffs as $field_name => $diff) {

      // Only compare fields that belong to us.
      $field = field_info_field($field_name);
      if (field_access('view', $field, 'node') && in_array($field_name, $comment_alter_fields)) {
        $instance = field_info_instance('node', $field_name, $node->type);
        list($old, $new) = diff_extract_state($diff, $context['states'][0]);
        if ($old != $new) {
          if (!empty($instance['comment_alter_hide'])) {
            if (diff_node_revision_access($node)) {
              $changed_fields[$field_name][] = array(
                'name' => $diff['#name'],
                'changes' => l(t('View changes'), 'node/' . $node->nid . '/revisions/view/' . $old_node->vid . '/' . $new_node->vid),
              );
            }
            else {
              $changed_fields[$field_name][] = array(
                'name' => $diff['#name'],
                'old' => array(
                  '&hellip;',
                ),
                'new' => array(
                  '&hellip;',
                ),
              );
            }
            continue;
          }
          $rows = diff_get_rows($old, $new);
          $line = 0;
          foreach ($rows as $row) {
            $changed_fields[$field_name][] = array(
              'name' => $line ? '' : $diff['#name'],
              'old' => array(
                empty($row[1]['data']) ? '' : $row[1]['data'],
              ),
              'new' => array(
                empty($row[3]['data']) ? '' : $row[3]['data'],
              ),
            );
            $line++;
          }
        }
      }
    }
  }
  return $changed_fields;
}

/**
 * Implements hook_comment_view().
 *
 * @see diff_diffs_show()
 */
function comment_alter_comment_view($comment, $view_mode, $langcode) {

  // Strip 'comment_node_' to get the node type machine name.
  $type = substr($comment->node_type, 13);
  if ($view_mode == 'full' && isset($comment->comment_alter) && user_access('view comment alterations in ' . $type)) {
    $comment->content['comment_alter'] = array(
      '#theme' => 'comment_alter_diff',
      '#changed_fields' => comment_alter_get_changed_fields($comment, $langcode),
      '#comment' => $comment,
      '#langcode' => $langcode,
    );
  }

  // Add the link if needed AND current user has access to it.
  if (isset($comment->comment_alter) && isset($comment->comment_alter['new_vid'])) {
    $path = 'node/' . $comment->nid . '/revisions/view/' . $comment->comment_alter['old_vid'] . '/' . $comment->comment_alter['new_vid'];
    if (variable_get('comment_alter_diff_link_' . $type, 0) && drupal_valid_path($path)) {
      $comment->content['links']['comment']['#links']['comment-alter'] = array(
        'title' => t('diff'),
        'href' => $path,
        'html' => TRUE,
      );
    }
  }
}

/**
 * Implements hook_theme().
 */
function comment_alter_theme() {
  $return = array();
  $return['comment_alter_diff'] = array(
    'variables' => array(
      'changed_fields' => array(),
      'comment' => NULL,
      'langcode' => NULL,
    ),
  );
  return $return;
}

/**
 * Returns HTML for changes made by comment_alter.
 *
 * @param array $variables
 *   An associative array containing:
 *   - changed_fields: a list of arrays of changed fields, with these indexes:
 *     - name: field's name being changed.
 *     - old: array of old field values.
 *     - new: array of new field values.
 *   - comment: Full comment object, for context.
 *   - langcode: The language code used for rendering the fields, for context.
 *
 * @ingroup themeable
 */
function theme_comment_alter_diff(&$variables) {
  if ($variables['changed_fields']) {
    $rows = array();
    foreach ($variables['changed_fields'] as $field) {
      foreach ($field as $value) {
        $row = array(
          empty($value['name']) ? '' : $value['name'] . ':',
        );
        if (!empty($value['changes'])) {
          $row[] = array(
            'data' => $value['changes'],
            'colspan' => 3,
          );
        }
        else {
          $row[] = implode(', ', $value['old']);
          $row[] = '&raquo;';
          $row[] = implode(', ', $value['new']);
        }
        $rows[] = $row;
      }
    }
    drupal_add_css(drupal_get_path('module', 'comment_alter') . '/comment_alter.css');
    $build = array(
      '#theme' => 'table__comment_alter__diff',
      '#rows' => $rows,
      '#attributes' => array(
        'class' => array(
          'comment-alter-diff',
        ),
      ),
      '#sticky' => FALSE,
    );
    return drupal_render($build);
  }
}

/**
 * Implements hook_comment_delete().
 */
function comment_alter_comment_delete($comment) {
  db_delete('comment_alter')
    ->condition('cid', $comment->cid)
    ->execute();
}

/**
 * No need to implement hook_comment_update(), hook_comment_presave(),
 * hook_comment_publish(), hook_comment_unpublish() nor
 * hook_comment_view_alter().
 */

/**
 * Implements hook_field_extra_fields().
 */
function comment_alter_field_extra_fields() {
  $return = array();
  foreach (node_type_get_types() as $type) {
    $comment_alter_fields = comment_alter_get_alterable_fields($type->type);
    $weight = 0;
    foreach ($comment_alter_fields as $field_name) {
      $field = field_info_instance('node', $field_name, $type->type);

      // Comment_alterable node fields must be amongst the comment fields
      // themselves in order to be able to properly weight/reorder them, put
      // them into a field_group, etc. on the manage comment fields form.
      $return['comment']['comment_node_' . $type->type]['form'][$field_name] = array(
        'label' => $field['label'],
        'description' => $field['description'],
        'weight' => $weight,
      );
      $weight++;
    }
    if (!empty($comment_alter_fields)) {
      $return['comment']['comment_node_' . $type->type]['display']['comment_alter'] = array(
        'label' => t('Comment changes'),
        'description' => t('Changes made to the parent node\'s fields in this comment.'),
        'weight' => -1,
      );
    }
  }
  return $return;
}

/**
 * Implements hook_permission().
 */
function comment_alter_permission() {
  $return = array();
  foreach (node_type_get_types() as $type) {
    $return['view comment alterations in ' . $type->type] = array(
      // TODO: I18n support.
      'title' => t('View comment alterations of %type nodes', array(
        '%type' => $type->name,
      )),
    );
  }
  return $return;
}

/**
 * Implements hook_node_presave().
 */
function comment_alter_node_presave($node) {
  if (!isset($node->notifications_content_disable) && module_exists('rules')) {
    rules_invoke_event('comment_alter_node_presave', $node);
  }
}

/**
 * Implements hook_node_update().
 */
function comment_alter_node_update($node) {
  if (!isset($node->notifications_content_disable) && module_exists('rules')) {
    rules_invoke_event('comment_alter_node_update', $node);
  }
}

/**
 * Implements hook_comment_alter_node_postsave().
 */
function comment_alter_comment_alter_node_postsave($node, $comment) {
  if (module_exists('rules')) {
    rules_invoke_event('comment_alter_node_postsave', $node, $comment);
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function comment_alter_form_node_type_form_alter(&$form, &$form_state, $form_id) {
  $node_type =& $form['#node_type']->type;
  $form['comment']['comment_alter'] = array(
    '#type' => 'checkbox',
    '#title' => t('Use the latest revision as the default values for comment alterable fields (if any)'),
    '#description' => t('If you want to load the field values from the latest revision of the node (instead of the current revision) when the comment form is displayed (eg. when the <a href="!url">Revisioning</a> module is being used), tick this.', array(
      '!url' => 'https://drupal.org/project/revisioning',
    )),
    '#default_value' => variable_get('comment_alter_' . $node_type, 0),
  );
  $form['comment']['comment_alter_diff_link'] = array(
    '#type' => 'checkbox',
    '#title' => t('Add a link to the usual diff of the two revisions to the links area of the comment'),
    '#default_value' => variable_get('comment_alter_diff_link_' . $node_type, 0),
  );
  $form['comment']['comment_alter_root_only'] = array(
    '#type' => 'checkbox',
    '#title' => t('Allow altering fields only when submitting root-level comments'),
    '#description' => t('Ie. disallow comment altering when replying to comments.'),
    '#default_value' => variable_get('comment_alter_root_only_' . $node_type, 0),
    '#states' => array(
      'visible' => array(
        // action to take.
        ':input[name=comment_default_mode]' => array(
          'checked' => TRUE,
        ),
      ),
    ),
  );
}

/**
 * Implements hook_node_revision_delete().
 */
function comment_alter_node_revision_delete($node) {
  db_delete('comment_alter')
    ->condition(db_or()
    ->condition('old_vid', $node->vid)
    ->condition('new_vid', $node->vid))
    ->execute();
}

Functions

Namesort descending Description
comment_alter_comment_alter_node_postsave Implements hook_comment_alter_node_postsave().
comment_alter_comment_delete Implements hook_comment_delete().
comment_alter_comment_load Implements hook_comment_load().
comment_alter_comment_view Implements hook_comment_view().
comment_alter_field_extra_fields Implements hook_field_extra_fields().
comment_alter_form_comment_form_alter Implements hook_form_BASE_FORM_ID_alter().
comment_alter_form_field_ui_field_edit_form_alter Implements hook_form_FORM_ID_alter().
comment_alter_form_field_ui_field_overview_form_alter Implements hook_form_FORM_ID_alter().
comment_alter_form_node_type_form_alter Implements hook_form_FORM_ID_alter().
comment_alter_get_alterable_fields Returns the comment-alterable fields for a content type.
comment_alter_get_changed_fields Returns the differences committed with a particular comment.
comment_alter_node_presave Implements hook_node_presave().
comment_alter_node_revision_delete Implements hook_node_revision_delete().
comment_alter_node_update Implements hook_node_update().
comment_alter_permission Implements hook_permission().
comment_alter_requirements Implements hook_requirements().
comment_alter_theme Implements hook_theme().
theme_comment_alter_diff Returns HTML for changes made by comment_alter.
_comment_alter_cleanup_arrays Helper function to recursively clean up semi-empty arrays.
_comment_alter_cleanup_field_values Helper function to clean up field values for comparison.
_comment_alter_submit_node_fields Submit callback for the altered comment form.
_comment_alter_validate_node_fields Validation callback for the altered comment form.