You are here

rate.admin.inc in Rate 6.2

Same filename and directory in other branches
  1. 7 rate.admin.inc

Rating admin

File

rate.admin.inc
View source
<?php

/**
 * @file
 * Rating admin
 */

/**
 * Menu callback.
 *
 * Generates the admin page which contains the widget listing.
 */
function rate_admin_page() {
  $widgets = variable_get(RATE_VAR_WIDGETS, array());
  uasort($widgets, '_rate_sort');
  $header = array(
    t('Title'),
    t('Name'),
    t('Operations'),
  );
  $rows = array();
  foreach ($widgets as $id => $widget) {
    $edit = l(t('Edit'), str_replace('%', $id, RATE_PATH_ADMIN_PAGE_EDIT));
    $delete = l(t('Delete'), str_replace('%', $id, RATE_PATH_ADMIN_PAGE_DELETE));
    $rows[] = array(
      $widget->title,
      $widget->name,
      "{$edit} {$delete}",
    );
  }
  $output = '';
  $output .= '<h3>' . t('Add widget') . '</h3>';
  $output .= drupal_get_form('rate_choose_template_form');
  if ($rows) {
    $output .= theme('table', $header, $rows);
  }
  else {
    $text = t('You do not have any rate widgets defined yet.');
    $output .= '<p>' . check_plain($text) . '</p>';
  }
  return $output;
}

/**
 * Callback for uasort().
 *
 * @see rate_admin_page()
 * @see http://php.net/uasort
 */
function _rate_sort($a, $b) {
  if ($a->title == $b->title) {
    return 0;
  }
  return $a->title < $b->title ? -1 : 1;
}

/**
 * Form for choosing a template before the user goes to the add widget form.
 */
function rate_choose_template_form(&$form_state, $id = NULL) {
  $form = array();
  if ($id) {
    $form['#widget_id'] = $id;
    $widgets = variable_get(RATE_VAR_WIDGETS, array());
    $widget = $widgets[$id];
    isset($widget->template) or $widget->template = 'custom';
    $selected = $widget->template;
  }
  else {
    $selected = 'custom';
  }
  $options = array(
    'custom' => t('Custom'),
  );
  foreach (module_implements('rate_templates') as $module) {
    foreach (module_invoke($module, 'rate_templates') as $name => $widget) {
      $options[$name] = $widget->template_title;
    }
  }
  $form['template'] = array(
    '#type' => 'select',
    '#title' => t('Widget type'),
    '#options' => $options,
    '#default_value' => $selected,
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Next'),
  );
  return $form;
}

/**
 * Form submit callback for the choose_template_form.
 */
function rate_choose_template_form_submit($form, &$form_state) {
  $template = $form_state['values']['template'];
  $query = 'template=' . urlencode($template);
  if (isset($form['#widget_id'])) {

    /**
     * @todo: Copy over the options array from the template to the widget.
     */
    $path = str_replace('%', $form['#widget_id'], RATE_PATH_ADMIN_PAGE_EDIT);
  }
  else {
    $path = RATE_PATH_ADMIN_PAGE_ADD;
  }
  drupal_goto($path, $query);
}

/**
 * Form for adding and editing widgets.
 */
function rate_widget_form(&$form_state, $id = NULL) {
  $form = array();

  // Workaround core issue #591696 in AHAH forms.
  // See http://drupal.org/node/591696#comment-3369036 for details.
  if ($id) {
    $form['#action'] = url(str_replace('%', $id, RATE_PATH_ADMIN_PAGE_EDIT));
  }
  else {
    $form['#action'] = url(RATE_PATH_ADMIN_PAGE_ADD);
  }
  if ($id) {
    $widgets = variable_get(RATE_VAR_WIDGETS, array());
    if (!isset($widgets[$id])) {
      drupal_not_found();
      module_invoke_all('exit') & exit;
    }
    $widget = $widgets[$id];
  }
  else {
    $widget = new stdClass();
    $widget->name = '';
    $widget->tag = 'vote';
    $widget->title = '';
    $widget->node_types = array();
    $widget->comment_types = array();
    $widget->value_type = 'percent';
    $widget->options = array();
    $widget->template = 'custom';
    $widget->node_display = RATE_DISPLAY_BELOW_CONTENT;
    $widget->teaser_display = FALSE;
    $widget->node_display_mode = RATE_FULL;
    $widget->teaser_display_mode = RATE_FULL;
    $widget->comment_display_mode = RATE_FULL;
    $widget->comment_display = RATE_DISPLAY_BELOW_CONTENT;
    $widget->roles = array();
    $widget->allow_voting_by_author = TRUE;
    $widget->noperm_behaviour = RATE_NOPERM_REDIRECT_WITH_MESSAGE;
    $widget->displayed = RATE_AVERAGE;
    $widget->displayed_just_voted = RATE_USER;
  }

  // Determine the template from GET (which is only available before the form
  // was post) or from post values (only available after the form was posted).
  if (isset($form_state['post']['widget_template'])) {
    $widget->template = $form_state['post']['widget_template'];
  }
  elseif (isset($_GET['template'])) {

    // The template can be overridden (also used for changing templates).
    $widget->template = $_GET['template'];
  }

  // Check widget for missing values (legacy).
  _rate_check_widget($widget);
  if ($widget->template != 'custom') {
    if (!($template = _rate_get_template($widget->template))) {
      $form['error'] = array(
        '#value' => t('You cannot edit this widget because it was built using the template %template which does not exists anymore.', array(
          '%template' => $widget->template,
        )),
      );
      return $form;
    }
    $widget->customizable = isset($template->customizable) ? $template->customizable : TRUE;
    if ($widget->customizable && !$id) {
      $widget->options = $template->options;
      $widget->value_type = $template->value_type;
    }
  }
  if ($id) {
    $form['#widget_id'] = $id;
  }

  // The GET value for the template is not available anymore after posting,
  // so we need to add the template as a hidden value.
  $form['widget_template'] = array(
    '#type' => 'hidden',
    '#value' => $widget->template,
  );
  $form['#widget_customizable'] = $widget->customizable;
  if ($id) {
    $link = l(t('change the widget type'), str_replace('%', $id, RATE_PATH_ADMIN_PAGE_TEMPLATE));
    if ($widget->template == 'custom') {
      $text = t('This is a custom widget. You may !change.', array(
        '!change' => $link,
      ));
    }
    else {
      $template = _rate_get_template($widget->template);
      $text = t('This is a %type widget. You may !change.', array(
        '%type' => $template->template_title,
        '!change' => $link,
      ));
    }
    $text = filter_xss($text);
    $form['template'] = array(
      '#type' => 'fieldset',
      '#title' => t('Widget type'),
    );
    $form['template']['switch'] = array(
      '#value' => $text,
    );
  }
  $form['title'] = array(
    '#type' => 'textfield',
    '#title' => t('Title'),
    '#default_value' => $widget->title,
    '#required' => TRUE,
  );

  /**
   * @todo Implement http://drupal.org/node/302054#comment-1110505
   */
  $form['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Machine readable name'),
    '#default_value' => $widget->name,
    '#required' => TRUE,
  );
  $form['tag'] = array(
    '#type' => 'textfield',
    '#title' => t('Tag'),
    '#default_value' => $widget->tag,
    '#description' => t('Tag used for VotingAPI. Widgets with the same tag share their voting results.'),
    '#required' => TRUE,
  );
  if ($widget->customizable) {
    $options = array(
      'percent' => t('Percentage'),
      'points' => t('Points'),
      'option' => t('Options'),
    );
    $form['value_type'] = array(
      '#type' => 'radios',
      '#title' => t('Value type'),
      '#options' => $options,
      '#default_value' => $widget->value_type,
      '#required' => TRUE,
    );
    $form['options'] = array(
      '#type' => 'fieldset',
      '#title' => t('Options'),
      '#description' => t('Define the available voting buttons.'),
      '#collapsible' => TRUE,
      '#collapsed' => FALSE,
    );
    $form['options']['options'] = array(
      '#theme' => 'rate_admin_options',
      '#prefix' => "<div id=\"rate-options\">",
      '#suffix' => '</div>',
    );
    if ($form_state['submitted']) {
      $option_count = (int) $form_state['values']['option_count'];
      if ($form_state['clicked_button']['#id'] == 'edit-add-another') {
        ++$option_count;
      }
    }
    else {
      $option_count = max(2, count($widget->options));
    }
    $id = 0;
    $c = $option_count;
    for ($i = 0; $i < $c; $i++) {
      if ($form_state['submitted'] && !empty($form_state['values']['delete' . $i])) {
        --$option_count;
        continue;
      }
      $form['options']['options']['option' . $id] = array();
      if (isset($form_state['values']['value' . $i])) {
        $default_value = $form_state['values']['value' . $i];
        $default_label = $form_state['values']['label' . $i];
      }
      elseif (isset($widget->options[$i]) && !$form_state['submitted']) {
        $default_value = $widget->options[$i][0];
        $default_label = $widget->options[$i][1];
      }
      else {
        $default_value = '';
        $default_label = '';
      }
      $form['options']['options']['option' . $id]['value' . $id] = array(
        '#type' => 'textfield',
        '#title' => t('Value'),
        '#default_value' => $default_value,
        '#size' => 16,
      );
      $form['options']['options']['option' . $id]['label' . $id] = array(
        '#type' => 'textfield',
        '#title' => t('Label'),
        '#default_value' => $default_label,
        '#size' => 40,
      );
      $form['options']['options']['option' . $id]['delete' . $id] = array(
        '#type' => 'checkbox',
        '#title' => t('Delete'),
        '#default_value' => FALSE,
      );
      ++$id;
    }
    $form['options']['option_count'] = array(
      '#type' => 'hidden',
      '#value' => $option_count,
    );
    $form['options']['add_another'] = array(
      '#type' => 'submit',
      '#value' => t('Add another option'),
      '#ahah' => array(
        'path' => RATE_PATH_ADMIN_AHAH,
        'wrapper' => 'rate-options',
        'method' => 'replace',
        'effect' => 'none',
      ),
    );
    $form['translate'] = array(
      '#type' => 'checkbox',
      '#title' => t('Translate options'),
      '#default_value' => $widget->translate,
    );
  }
  $form['types'] = array(
    '#type' => 'fieldset',
    '#title' => t('Node types'),
    '#description' => t('Select the node types on which to enable this widget.'),
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
    '#theme' => 'rate_admin_types',
  );
  $sql = 'SELECT type, name FROM {node_type} ORDER BY name ASC';
  $res = db_query($sql);
  while ($rec = db_fetch_array($res)) {
    $form['types'][$rec['type']] = array(
      '#type' => 'fieldset',
      '#title' => $rec['name'],
    );
    $form['types'][$rec['type']]['node_type_' . $rec['type']] = array(
      '#type' => 'checkbox',
      '#title' => $rec['name'],
      '#default_value' => in_array($rec['type'], $widget->node_types),
    );
    $form['types'][$rec['type']]['comment_type_' . $rec['type']] = array(
      '#type' => 'checkbox',
      '#title' => $rec['name'],
      '#default_value' => in_array($rec['type'], $widget->comment_types),
    );
  }
  $form['display'] = array(
    '#type' => 'fieldset',
    '#title' => t('Display settings'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
  );
  $display_options = array(
    RATE_DISPLAY_DISABLE => t('Do not add automatically'),
    RATE_DISPLAY_ABOVE_CONTENT => t('Above the content'),
    RATE_DISPLAY_BELOW_CONTENT => t('Below the content'),
    RATE_DISPLAY_LINKS => t('Within the Links'),
  );
  $form['display']['node_display'] = array(
    '#type' => 'radios',
    '#title' => t('Node display'),
    '#options' => $display_options,
    '#default_value' => $widget->node_display,
  );
  $form['display']['teaser_display'] = array(
    '#type' => 'checkbox',
    '#title' => t('Display in teaser'),
    '#default_value' => $widget->teaser_display,
  );
  $display_mode_options = array(
    RATE_FULL => t('Full widget'),
    RATE_DISABLED => t('Display only'),
    RATE_COMPACT_DISABLED => t('Display only, compact'),
    RATE_COMPACT => t('Compact'),
  );
  $form['display']['node_display_mode'] = array(
    '#type' => 'select',
    '#title' => t('Appearance in full node'),
    '#options' => $display_mode_options,
    '#default_value' => $widget->node_display_mode,
  );
  $form['display']['teaser_display_mode'] = array(
    '#type' => 'select',
    '#title' => t('Appearance in teaser'),
    '#options' => $display_mode_options,
    '#default_value' => $widget->teaser_display_mode,
  );
  $form['display']['comment_display'] = array(
    '#type' => 'radios',
    '#title' => t('Comment display'),
    '#options' => $display_options,
    '#default_value' => $widget->comment_display,
  );
  $form['display']['comment_display_mode'] = array(
    '#type' => 'select',
    '#title' => t('Appearance in comments'),
    '#options' => $display_mode_options,
    '#default_value' => $widget->comment_display_mode,
  );
  $form['interaction'] = array(
    '#type' => 'fieldset',
    '#title' => t('Interaction'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
    '#description' => t('Note that these settings do not apply for rate widgets inside views. Widgets in views will display the average voting when a relationship to the voting results is used and the users vote in case of a relationship to the votes.'),
  );
  $options = array(
    RATE_AVERAGE => t('Average rating'),
    RATE_USER => t('Users vote if available, empty otherwise'),
    RATE_USER_OR_AVERAGE => t('Users vote if available, average otherwise'),
  );
  $form['interaction']['displayed'] = array(
    '#type' => 'radios',
    '#title' => t('Which rating should be displayed?'),
    '#options' => $options,
    '#default_value' => $widget->displayed,
  );
  $options = array(
    RATE_AVERAGE => t('Average rating'),
    RATE_USER => t('Users vote'),
  );
  $form['interaction']['displayed_just_voted'] = array(
    '#type' => 'radios',
    '#title' => t('Which rating should be displayed when the user just voted?'),
    '#options' => $options,
    '#default_value' => $widget->displayed_just_voted,
  );
  $form['permissions'] = array(
    '#type' => 'fieldset',
    '#title' => t('Permissions'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
  );
  $sql = 'SELECT rid, name FROM {role} ORDER BY name ASC';
  $res = db_query($sql);
  $options = array();
  while ($rec = db_fetch_array($res)) {
    $options[$rec['rid']] = $rec['name'];
  }
  $form['permissions']['roles'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Roles'),
    '#options' => $options,
    '#default_value' => $widget->roles,
    '#description' => t('Allow voting only for the selected role(s). If you select no roles, all users are allowed to vote.'),
  );
  $form['permissions']['allow_voting_by_author'] = array(
    '#type' => 'checkbox',
    '#title' => t('Allow author to rate his / her own content'),
    '#default_value' => $widget->allow_voting_by_author,
    '#description' => t('Will change the state to disabled. Always true for anonymous users.'),
  );
  $options = array(
    RATE_NOPERM_REDIRECT_WITH_MESSAGE => t('Redirect to login and show message'),
    RATE_NOPERM_REDIRECT_WITHOUT_MESSAGE => t('Redirect to login but do not show a message'),
    RATE_NOPERM_SHOW_DISABLED_WIDGET => t('Show a disabled widget (with non clickable buttons)'),
    RATE_NOPERM_HIDE_WIDGET => t('Hide widget'),
  );
  $form['permissions']['noperm_behaviour'] = array(
    '#type' => 'radios',
    '#title' => t('Behaviour when user has no permission to vote'),
    '#options' => $options,
    '#default_value' => $widget->noperm_behaviour,
    '#description' => t('Choose an action what will happen if a user clicks on the widget but doesn\'t have the permission to vote.'),
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
    '#weight' => 50,
  );
  return $form;
}

/**
 * Form validate.
 */
function rate_widget_form_validate($form, &$form_state) {

  // Validate machine readable name
  if (!preg_match('/^[a-z\\_0-9]+$/i', $form_state['values']['name'])) {
    form_set_error('name', t('The machine readable name may only contain alphanumeric characters and underscores.'));
  }

  // Validate vote tag
  if (!preg_match('/^[a-z\\_0-9]+$/i', $form_state['values']['tag'])) {
    form_set_error('tag', t('The vote tag may only contain alphanumeric characters and underscores.'));
  }
  if ($form['#widget_customizable']) {

    // Validate option values
    $used_values = array();
    foreach ($form_state['values'] as $name => $value) {
      if (preg_match('/^value([0-9]+)$/', $name, $match)) {
        if (empty($value)) {
          continue;
        }
        if (!preg_match('/^\\-?[0-9]+$/', $value)) {
          form_set_error($name, t('Values must be integers'));
          continue;
        }
        if (in_array($value, $used_values)) {
          form_set_error($name, t('You may not use the same value twice.'));
        }
        $used_values[] = $value;
        if ($form_state['values']['value_type'] == 'percent') {
          if ($value < 0 || $value > 100) {
            form_set_error($name, t('Percentages must be between 0 and 100'));
          }
        }
      }
    }
    if (!count($used_values)) {
      form_set_error('', t('Each widget must have at least one option.'));
    }
  }
}

/**
 * Form submit handler.
 */
function rate_widget_form_submit($form, &$form_state) {
  if ($form_state['clicked_button']['#id'] == 'edit-add-another') {
    $form_state['rebuild'] = TRUE;
    return $form_state['values'];
  }
  $widget = new stdClass();
  $widget->name = $form_state['values']['name'];
  $widget->tag = $form_state['values']['tag'];
  $widget->title = $form_state['values']['title'];
  $widget->node_types = array();
  $widget->comment_types = array();
  $widget->options = array();
  $widget->template = $form_state['values']['widget_template'];
  $widget->node_display = $form_state['values']['node_display'];
  $widget->teaser_display = (bool) $form_state['values']['teaser_display'];
  $widget->comment_display = $form_state['values']['comment_display'];
  $widget->node_display_mode = $form_state['values']['node_display_mode'];
  $widget->teaser_display_mode = $form_state['values']['teaser_display_mode'];
  $widget->comment_display_mode = $form_state['values']['comment_display_mode'];
  $widget->roles = $form_state['values']['roles'];
  $widget->allow_voting_by_author = $form_state['values']['allow_voting_by_author'];
  $widget->noperm_behaviour = $form_state['values']['noperm_behaviour'];
  $widget->displayed = $form_state['values']['displayed'];
  $widget->displayed_just_voted = $form_state['values']['displayed_just_voted'];
  if ($widget->template != 'custom') {

    // Take over the values from the template.
    $template = _rate_get_template($widget->template);
    if (!$template->customizable) {
      $widget->options = $template->options;
    }
    $widget->value_type = $template->value_type;
    !isset($template->theme) or $widget->theme = $template->theme;
    !isset($template->css) or $widget->css = $template->css;
    !isset($template->js) or $widget->js = $template->js;
    $widget->translate = $template->translate;
    if (isset($form_state['values']['translate'])) {
      $widget->translate = (bool) $form_state['values']['translate'];
    }
  }
  else {
    $widget->value_type = $form_state['values']['value_type'];
    $widget->translate = (bool) $form_state['values']['translate'];
  }
  foreach ($form_state['values'] as $name => $value) {
    if (preg_match('/^value([0-9]+)$/', $name, $match) && preg_match('/^\\-?[0-9]+$/', $value)) {
      $widget->options[] = array(
        $value,
        $form_state['values']['label' . $match[1]],
      );
    }
    if (preg_match('/^node_type_(.+)$/', $name, $match) && $value) {
      $widget->node_types[] = $match[1];
    }
    if (preg_match('/^comment_type_(.+)$/', $name, $match) && $value) {
      $widget->comment_types[] = $match[1];
    }
  }

  // Let other modules alter the rate widget.
  foreach (module_implements('rate_widget') as $module) {
    $hook = "{$module}_rate_widget";
    $op = empty($form['#widget_id']) ? 'insert' : 'update';
    $hook($op, $widget, $form_state['values']);
  }

  // Save the widget.
  $widgets = variable_get(RATE_VAR_WIDGETS, array());
  if (!empty($form['#widget_id'])) {
    $id = (int) $form['#widget_id'];
  }
  else {
    $id = 1;
    while (isset($widgets[$id])) {
      ++$id;
    }
  }
  $widgets[$id] = $widget;
  variable_set(RATE_VAR_WIDGETS, $widgets);
  drupal_set_message(t('The widget has been saved.'));
  $form_state['redirect'] = RATE_PATH_ADMIN_PAGE;
}

/**
 * AHAH callback for widget form.
 */
function rate_widget_form_ahah() {
  $form_state = array(
    'storage' => NULL,
    'submitted' => FALSE,
  );
  $form_build_id = $_POST['form_build_id'];
  $form = form_get_cache($form_build_id, $form_state);
  $args = $form['#parameters'];
  $form_id = array_shift($args);
  $form['#post'] = $_POST;
  $form['#redirect'] = FALSE;
  $form['#programmed'] = FALSE;
  $form_state['post'] = $_POST;
  drupal_process_form($form_id, $form, $form_state);
  $form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
  $container = $form['options']['options'];
  unset($container['#prefix'], $container['#suffix']);

  // Prevent duplicate wrappers.
  $javascript = drupal_add_js(NULL, NULL, 'header');
  drupal_json(array(
    'status' => TRUE,
    'data' => theme('status_messages') . drupal_render($container),
    'settings' => call_user_func_array('array_merge_recursive', $javascript['setting']),
  ));
}

/**
 * Theming function for the node / comment types list in the widget form.
 *
 * @ingroup themeable
 */
function theme_rate_admin_types($element) {
  $header = array(
    t('Name'),
    t('Node'),
    t('Comment'),
  );
  $rows = array();
  foreach ($element as $name => $subelement) {
    if ($name[0] != '#') {
      unset($subelement['node_type_' . $name]['#title']);
      unset($subelement['comment_type_' . $name]['#title']);
      $rows[] = array(
        check_plain($subelement['#title']),
        drupal_render($subelement['node_type_' . $name]),
        drupal_render($subelement['comment_type_' . $name]),
      );
    }
  }
  return theme('table', $header, $rows);
}

/**
 * Theme the options list in the widget form.
 *
 * @ingroup themeable
 */
function theme_rate_admin_options($element) {
  $header = array(
    t('Value'),
    t('Label'),
    t('Delete'),
  );
  $rows = array();
  foreach ($element as $name => $subelement) {
    if (preg_match('/^option([0-9]+)$/', $name, $match)) {
      $id = $match[1];
      unset($subelement['value' . $id]['#title']);
      unset($subelement['label' . $id]['#title']);
      unset($subelement['delete' . $id]['#title']);
      $rows[] = array(
        drupal_render($subelement['value' . $id]),
        drupal_render($subelement['label' . $id]),
        drupal_render($subelement['delete' . $id]),
      );
    }
  }
  return theme('table', $header, $rows);
}

/**
 * Form for deleting widgets.
 */
function rate_widget_delete_form(&$form_state, $id) {
  $form = array();
  $widgets = variable_get(RATE_VAR_WIDGETS, array());
  $form['#widget_id'] = $id;
  if (!($title = $widgets[$id]->title)) {
    drupal_not_found();
    module_invoke_all('exit') & exit;
  }
  $form['info'] = array(
    '#value' => '<p>' . t('Are you sure you want to delete widget %title?', array(
      '%title' => $title,
    )) . '</p>',
  );
  $form['buttons']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Delete'),
  );
  $form['buttons']['cancel'] = array(
    '#value' => l('Cancel', RATE_PATH_ADMIN_PAGE),
  );
  return $form;
}

/**
 * Submit handler.
 */
function rate_widget_delete_form_submit($form, &$form_state) {
  $widgets = variable_get(RATE_VAR_WIDGETS, array());
  if ($title = $widgets[$form['#widget_id']]->title) {
    unset($widgets[$form['#widget_id']]);
    variable_set(RATE_VAR_WIDGETS, $widgets);
    drupal_set_message(t('Widget %title has been deleted.', array(
      '%title' => $title,
    )));

    // Let other modules act on this action.
    foreach (module_implements('rate_widget') as $module) {
      $hook = "{$module}_rate_widget";
      $hook('delete', $widgets[$form['#widget_id']], $form_state['values']);
    }
  }
  $form_state['redirect'] = RATE_PATH_ADMIN_PAGE;
}

Functions

Namesort descending Description
rate_admin_page Menu callback.
rate_choose_template_form Form for choosing a template before the user goes to the add widget form.
rate_choose_template_form_submit Form submit callback for the choose_template_form.
rate_widget_delete_form Form for deleting widgets.
rate_widget_delete_form_submit Submit handler.
rate_widget_form Form for adding and editing widgets.
rate_widget_form_ahah AHAH callback for widget form.
rate_widget_form_submit Form submit handler.
rate_widget_form_validate Form validate.
theme_rate_admin_options Theme the options list in the widget form.
theme_rate_admin_types Theming function for the node / comment types list in the widget form.
_rate_sort Callback for uasort().