You are here

starrating.module in Star Rating 7.2

Same filename and directory in other branches
  1. 8.4 starrating.module

Provides star rating field, formatter and widget using Field API. star rating field is based on integer value and convert it to the HTML code that displays series of icons. The formatter supports not only star rating field type but also regular integer (number) and list (number) field types.

Following hook functions are provided.

Field Type API: defines field type

Field Type API (Formatter): defines formatter (for displaying field)

Field Type API (Widget): defines widget (for entering value to field)

File

starrating.module
View source
<?php

/**
 * @file
 * Provides star rating field, formatter and widget using Field API.
 * star rating field is based on integer value and convert it to the HTML code
 * that displays series of icons.
 * The formatter supports not only star rating field type but also regular
 * integer (number) and list (number) field types.
 *
 * Following hook functions are provided.
 *
 * Field Type API: defines field type
 *  - hook_field_info()
 *  - hook_field_schema()
 *  - hook_field_is_empty()
 *  - hook_field_settings_form()
 *
 * Field Type API (Formatter): defines formatter (for displaying field)
 *  - hook_field_formatter_info()
 *  - hook_field_formatter_settings_form()
 *  - hook_field_formatter_settings_summary()
 *  - hook_field_formatter_view()
 *
 * Field Type API (Widget): defines widget (for entering value to field)
 *  - hook_field_widget_info()
 *  - hook_field_widget_form()
 */

/*
 ****************************************************************************
 * Field Type API: Formatter
 ****************************************************************************
 */

/**
 * Implements hook_field_formatter_info().
 */
function starrating_field_formatter_info() {
  return array(
    'starrating_rating_formatter' => array(
      'label' => t('Star rating'),
      'field types' => array(
        'list_integer',
      ),
      'settings' => array(
        'fill_blank' => 1,
        'icon_type' => 'star',
        'icon_color' => 1,
      ),
    ),
    'starrating_rating_value_formatted' => array(
      'label' => t('Star rating value'),
      'field types' => array(
        'list_integer',
      ),
    ),
    'starrating_rating_value_int' => array(
      'label' => t('Star rating value as int (especially for math calculations in views)'),
      'field types' => array(
        'list_integer',
      ),
    ),
  );
}

/**
 * Implements hook_field_formatter_settings_form().
 */
function starrating_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];
  $element = array();
  $element['fill_blank'] = array(
    '#type' => 'checkbox',
    '#title' => t('Fill with blank icons'),
    '#default_value' => $settings['fill_blank'],
  );
  $element['icon_type'] = array(
    '#type' => 'select',
    '#title' => t('Icon type'),
    '#options' => array(
      'star' => t('Star'),
      'star-line' => t('Star (outline)'),
      'check' => t('Check'),
      'heart' => t('Heart'),
      'dollar' => t('Dollar'),
      'smiley' => t('Smiley'),
      'food' => t('Food'),
      'coffee' => t('Coffee'),
      'movie' => t('Movie'),
      'music' => t('Music'),
      'human' => t('Human'),
      'thumbs-up' => t('Thumbs Up'),
      'car' => t('Car'),
      'airplane' => t('Airplane'),
      'fire' => t('Fire'),
      'drupalicon' => t('Drupalicon'),
      'custom' => t('Custom'),
    ),
    '#default_value' => $settings['icon_type'],
    '#prefix' => '<img src="' . base_path() . drupal_get_path('module', 'starrating') . '/icons/sample.png" />',
  );
  $element['icon_color'] = array(
    '#type' => 'select',
    '#title' => t('Icon color'),
    '#options' => array(
      1 => '1',
      2 => '2',
      3 => '3',
      4 => '4',
      5 => '5',
      6 => '6',
      7 => '7',
      8 => '8',
    ),
    '#default_value' => $settings['icon_color'],
  );
  return $element;
}

/**
 * Implements hook_field_formatter_settings_summary().
 * Displays infos here /admin/structure/types/manage/node_type_name/display
 */
function starrating_field_formatter_settings_summary($field, $instance, $view_mode) {

  //only display settings for starrating formatter
  if ($instance['display']['default']['type'] == 'starrating_rating_value_formatted') {
    $display = $instance['display'][$view_mode];
    $settings = $display['settings'];
    $options = array(
      'type' => 'file',
      'weight' => 10,
      'group' => CSS_DEFAULT,
    );
    $css_file = $settings['icon_type'] . '.css';
    drupal_add_css(drupal_get_path('module', 'starrating') . '/icons/' . $css_file, $options);

    //currently we only support list_integer
    if ($field['type'] == 'list_integer') {

      //get first array value as it is the minimum value
      reset($field['settings']['allowed_values']);
      $min = current($field['settings']['allowed_values']);
      $max = count($field['settings']['allowed_values']) - 1;
    }
    else {
      drupal_set_message("Something went wrong. Only list_inetger is crrently supported");
    }
    $rate = $max - 1;

    // sample data to be used for summary view so we remove one to see if fill blank setting works (visually)
    $summary = starrating_field_formatter_execute($rate, $min, $max, $settings['icon_type'], $settings['icon_color'], $settings['fill_blank']);
    return $summary;
  }
}

/**
 * Implements hook_field_formatter_view().
 */
function starrating_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  switch ($display['type']) {
    case 'starrating_rating_formatter':
      $settings = $display['settings'];
      $element = array();
      $options = array(
        'type' => 'file',
        'weight' => 10,
        'group' => CSS_DEFAULT,
      );
      $css_file = $settings['icon_type'] . '.css';
      drupal_add_css(drupal_get_path('module', 'starrating') . '/icons/' . $css_file, $options);

      //currently we only support list_integer
      if ($field['type'] == 'list_integer') {

        //get first array value as it is the minimum value
        reset($field['settings']['allowed_values']);
        $min = current($field['settings']['allowed_values']);

        //need to check if min is 0 or bigger to calculate correct maximum value
        if ($min > 0) {
          $max = count($field['settings']['allowed_values']);
        }
        else {
          $max = count($field['settings']['allowed_values']) - 1;
        }
      }
      else {
        drupal_set_message("Something went wrong. Only list_inetger is currently supported");
      }
      if (!isset($items[0]['value']) || $items[0]['value'] == NULL || $items[0]['value'] === NULL) {
        $rating_value = NULL;
      }
      else {
        $rating_value = $items[0]['value'];
      }
      $output = starrating_field_formatter_execute($rating_value, $min, $max, $settings['icon_type'], $settings['icon_color'], $settings['fill_blank']);
      $element[] = array(
        '#markup' => $output,
      );
      return $element;
    case 'starrating_rating_value_formatted':
      $element = array();
      $output = '<div class="starrating">' . intval($items[0]['value']) . '</div>';
      $element[] = array(
        '#markup' => $output,
      );
      return $element;
    case 'starrating_rating_value_int':
      $element = array();
      if (isset($items[0]['value'])) {
        $output = intval($items[0]['value']);
      }
      else {
        $output = 0;
      }
      $element[] = array(
        '#markup' => $output,
      );
      return $element;
  }
}

/**
 * Implements hook_field_attach_view_alter().
 *
 * Alter the output to include "items" on null valued fields to allow the "No rating" text to come through. Otherwise it would not be displayed
 *
 */
function starrating_field_attach_view_alter(&$output, $context) {
  foreach (element_children($output) as $field_name) {
    if ($output[$field_name]['#field_type'] == 'list_integer') {
      if (empty($output[$field_name]['#items'])) {
        $output[$field_name]['#items'] = array(
          array(
            'value' => NULL,
          ),
        );
      }
    }
  }
}

/**
 * Convert integer value to star rating HTML code
 *
 * @input
 *   $rate - integer value of rating
 *   $min - minimum possible value like 0 or 1 Stars
 *   $max - maximum possible value like 10 or 5 Stars
 * @output
 *   HTML code for star rating icons
 *   <div class="(icon_type)(icon_color)-on"></div> ...
 *
 *  it is possible that min is 0 or 1 and rate can be NULL or 0 1 2 3 4 ..
 *
 * //TODO use theme function for this?
 *
 */
function starrating_field_formatter_execute($rate, $min, $max, $icon_type, $icon_color, $fill_blank) {

  // if the rate value is not set meaning NULL, then return 'No Rating'
  if ($rate === NULL) {
    return "<span class='starrating-no-rating'>" . t('No rating') . "</span>";
  }

  //if the user has chosen 0-10 we have 11 values so we fix it for the for-loop to work correctly
  if ($min == 0) {
    $min = 1;
  }
  $out = "\n";
  $out .= '<div class="starrating">';

  // add hidden text to support copy/paste and voice reading
  $out .= '<span style="position:absolute;left:-9999px">' . $rate . '</span>';
  for ($i = $min; $i <= $max; $i++) {
    if ($i == $rate && !$fill_blank) {
      break;
    }
    if ($i > $rate) {
      $class = $icon_type . '-off';
    }
    else {
      $class = $icon_type . $icon_color . '-on';
    }
    if ($i % 2) {
      $class .= ' odd';
    }
    else {
      $class .= ' even';
    }
    $class .= ' s' . ($i + 1);
    $out .= '<div class="rate-image ' . $class . '"></div>';
  }
  $out .= "</div>\n";
  return $out;
}