home | career | drupal | java | mac | mysql | perl | php | scala | uml | unix

Drupal example source code file (number.module)

This example Drupal source code file (number.module) is included in the DevDaily.com "Drupal Source Code Warehouse" project. The intent of this project is to help you "Learn Drupal by Example".

PHP - Drupal tags/keywords

array, default_value, element, field, function, if, in, number_decimal, php, return, the, title, type, value

The number.module Drupal example source code

<?php
// $Id: number.module,v 1.46 2010/10/31 12:11:59 dries Exp $

/**
 * @file
 * Defines numeric field types.
 */

/**
 * Implements hook_help().
 */
function number_help($path, $arg) {
  switch ($path) {
    case 'admin/help#number':
      $output = '';
      $output .= '<h3>' . t('About') . '</h3>';
      $output .= '<p>' . t('The Number module defines various numeric field types for the Field module. Numbers can be in integer, decimal, or floating-point form, and they can be formatted when displayed. Number fields can be limited to a specific set of input values or to a range of values. See the <a href="@field-help">Field module help page</a> for more information about fields.', array('@field-help' => url('admin/help/field'))) . '</p>';
      return $output;
  }
}

/**
 * Implements hook_field_info().
 */
function number_field_info() {
  return array(
    'number_integer' => array(
      'label' => t('Integer'),
      'description' => t('This field stores a number in the database as an integer.'),
      'instance_settings' => array('min' => '', 'max' => '', 'prefix' => '', 'suffix' => ''),
      'default_widget' => 'number',
      'default_formatter' => 'number_integer',
    ),
    'number_decimal' => array(
      'label' => t('Decimal'),
      'description' => t('This field stores a number in the database in a fixed decimal format.'),
      'settings' => array('precision' => 10, 'scale' => 2, 'decimal_separator' => '.'),
      'instance_settings' => array('min' => '', 'max' => '', 'prefix' => '', 'suffix' => ''),
      'default_widget' => 'number',
      'default_formatter' => 'number_decimal',
    ),
    'number_float' => array(
      'label' => t('Float'),
      'description' => t('This field stores a number in the database in a floating point format.'),
      'settings' => array('decimal_separator' => '.'),
      'instance_settings' => array('min' => '', 'max' => '', 'prefix' => '', 'suffix' => ''),
      'default_widget' => 'number',
      'default_formatter' => 'number_decimal',
    ),
  );
}

/**
 * Implements hook_field_settings_form().
 */
function number_field_settings_form($field, $instance, $has_data) {
  $settings = $field['settings'];
  $form = array();

  if ($field['type'] == 'number_decimal') {
    $form['precision'] = array(
      '#type' => 'select',
      '#title' => t('Precision'),
      '#options' => drupal_map_assoc(range(10, 32)),
      '#default_value' => $settings['precision'],
      '#description' => t('The total number of digits to store in the database, including those to the right of the decimal.'),
      '#disabled' => $has_data,
    );
    $form['scale'] = array(
      '#type' => 'select',
      '#title' => t('Scale'),
      '#options' => drupal_map_assoc(range(0, 10)),
      '#default_value' => $settings['scale'],
      '#description' => t('The number of digits to the right of the decimal.'),
      '#disabled' => $has_data,
    );
  }
  if ($field['type'] == 'number_decimal' || $field['type'] == 'number_float') {
    $form['decimal_separator'] = array(
      '#type' => 'select',
      '#title' => t('Decimal marker'),
      '#options' => array('.' => t('Decimal point'), ',' => t('Comma')),
      '#default_value' => $settings['decimal_separator'],
      '#description' => t('The character users will input to mark the decimal point in forms.'),
    );
  }

  return $form;
}

/**
 * Implements hook_field_instance_settings_form().
 */
function number_field_instance_settings_form($field, $instance) {
  $settings = $instance['settings'];

  $form['min'] = array(
    '#type' => 'textfield',
    '#title' => t('Minimum'),
    '#default_value' => $settings['min'],
    '#description' => t('The minimum value that should be allowed in this field. Leave blank for no minimum.'),
    '#element_validate' => array('_element_validate_number'),
  );
  $form['max'] = array(
    '#type' => 'textfield',
    '#title' => t('Maximum'),
    '#default_value' => $settings['max'],
    '#description' => t('The maximum value that should be allowed in this field. Leave blank for no maximum.'),
    '#element_validate' => array('_element_validate_number'),
  );
  $form['prefix'] = array(
    '#type' => 'textfield',
    '#title' => t('Prefix'),
    '#default_value' => $settings['prefix'],
    '#size' => 60,
    '#description' => t("Define a string that should be prefixed to the value, like '$ ' or '&euro; '. Leave blank for none. Separate singular and plural values with a pipe ('pound|pounds')."),
  );
  $form['suffix'] = array(
    '#type' => 'textfield',
    '#title' => t('Suffix'),
    '#default_value' => $settings['suffix'],
    '#size' => 60,
    '#description' => t("Define a string that should be suffixed to the value, like ' m', ' kb/s'. Leave blank for none. Separate singular and plural values with a pipe ('pound|pounds')."),
  );

  return $form;
}

/**
 * Implements hook_field_validate().
 *
 * Possible error codes:
 * - 'number_min': The value is less than the allowed minimum value.
 * - 'number_max': The value is greater than the allowed maximum value.
 */
function number_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
  foreach ($items as $delta => $item) {
    if ($item['value'] != '') {
      if (is_numeric($instance['settings']['min']) && $item['value'] < $instance['settings']['min']) {
        $errors[$field['field_name']][$langcode][$delta][] = array(
          'error' => 'number_min',
          'message' => t('%name: the value may be no less than %min.', array('%name' => t($instance['label']), '%min' => $instance['settings']['min'])),
        );
      }
      if (is_numeric($instance['settings']['max']) && $item['value'] > $instance['settings']['max']) {
        $errors[$field['field_name']][$langcode][$delta][] = array(
          'error' => 'number_max',
          'message' => t('%name: the value may be no greater than %max.', array('%name' => t($instance['label']), '%max' => $instance['settings']['max'])),
        );
      }
    }
  }
}

/**
 * Implements hook_field_presave().
 */
function number_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
  if ($field['type'] == 'number_decimal') {
    // Let PHP round the value to ensure consistent behavior across storage
    // backends.
    foreach ($items as $delta => $item) {
      if (isset($item['value'])) {
        $items[$delta]['value'] = round($item['value'], $field['settings']['scale']);
      }
    }
  }
}

/**
 * Implements hook_field_is_empty().
 */
function number_field_is_empty($item, $field) {
  if (empty($item['value']) && (string) $item['value'] !== '0') {
    return TRUE;
  }
  return FALSE;
}

/**
 * Implements hook_field_formatter_info().
 */
function number_field_formatter_info() {
  return array(
    'number_integer' => array(
      'label' => t('Default'),
      'field types' => array('number_integer'),
      'settings' =>  array(
        'thousand_separator' => ' ',
        'decimal_separator' => '.',
        'scale' => 0,
        'prefix_suffix' => TRUE,
      ),
    ),
    'number_decimal' => array(
      'label' => t('Default'),
      'field types' => array('number_decimal', 'number_float'),
      'settings' =>  array(
        'thousand_separator' => ' ',
        'decimal_separator' => '.',
        'scale' => 2,
        'prefix_suffix' => TRUE,
      ),
    ),
    'number_unformatted' => array(
      'label' => t('Unformatted'),
      'field types' => array('number_integer', 'number_decimal', 'number_float'),
    ),
  );
}

/**
 * Implements hook_field_formatter_settings_form().
 */
function number_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];

  $options = array(
    ''  => t('<none>'),
    '.' => t('Decimal point'),
    ',' => t('Comma'),
    ' ' => t('Space'),
  );
  $element['thousand_separator'] = array(
    '#type' => 'select',
    '#title' => t('Thousand marker'),
    '#options' => $options,
    '#default_value' => $settings['thousand_separator'],
  );

  if ($display['type'] == 'number_decimal' || $display['type'] == 'number_float') {
    $element['decimal_separator'] = array(
      '#type' => 'select',
      '#title' => t('Decimal marker'),
      '#options' => array('.' => t('Decimal point'), ',' => t('Comma')),
      '#default_value' => $settings['decimal_separator'],
    );
    $element['scale'] = array(
      '#type' => 'select',
      '#title' => t('Scale'),
      '#options' => drupal_map_assoc(range(0, 10)),
      '#default_value' => $settings['scale'],
      '#description' => t('The number of digits to the right of the decimal.'),
    );
  }

  $element['prefix_suffix'] = array(
    '#type' => 'checkbox',
    '#title' => t('Display prefix and suffix.'),
    '#default_value' => $settings['prefix_suffix'],
  );

  return $element;
}

/**
 * Implements hook_field_formatter_settings_summary().
 */
function number_field_formatter_settings_summary($field, $instance, $view_mode) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];

  $summary = array();
  $summary[] = number_format(1234.1234567890, $settings['scale'], $settings['decimal_separator'], $settings['thousand_separator']);
  if ($settings['prefix_suffix']) {
    $summary[] = t('Display with prefix and suffix.');
  }

  return implode('<br />', $summary);
}

/**
 * Implements hook_field_formatter_view().
 */
function number_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $element = array();
  $settings = $display['settings'];

  switch ($display['type']) {
    case 'number_integer':
    case 'number_decimal':
      foreach ($items as $delta => $item) {
        $output = number_format($item['value'], $settings['scale'], $settings['decimal_separator'], $settings['thousand_separator']);
        if ($settings['prefix_suffix']) {
          $prefixes = isset($instance['settings']['prefix']) ? array_map('field_filter_xss', explode('|', $instance['settings']['prefix'])) : array('');
          $suffixes = isset($instance['settings']['suffix']) ? array_map('field_filter_xss', explode('|', $instance['settings']['suffix'])) : array('');
          $prefix = (count($prefixes) > 1) ? format_plural($item['value'], $prefixes[0], $prefixes[1]) : $prefixes[0];
          $suffix = (count($suffixes) > 1) ? format_plural($item['value'], $suffixes[0], $suffixes[1]) : $suffixes[0];
          $output = $prefix . $output . $suffix;
        }
        $element[$delta] = array('#markup' => $output);
      }
      break;

    case 'number_unformatted':
      foreach ($items as $delta => $item) {
        $element[$delta] = array('#markup' => $item['value']);
      }
      break;
  }

  return $element;
}

/**
 * Implements hook_field_widget_info().
 */
function number_field_widget_info() {
  return array(
    'number' => array(
      'label' => t('Text field'),
      'field types' => array('number_integer', 'number_decimal', 'number_float'),
    ),
  );
}

/**
 * Implements hook_field_widget_form().
 */
function number_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  $value = isset($items[$delta]['value']) ? $items[$delta]['value'] : '';
  // Substitute the decimal separator.
  if ($field['type'] == 'number_decimal' || $field['type'] == 'number_float') {
    $value = strtr($value, '.', $field['settings']['decimal_separator']);
  }

  $element += array(
    '#type' => 'textfield',
    '#default_value' => $value,
    // Allow a slightly larger size that the field length to allow for some
    // configurations where all characters won't fit in input field.
    '#size' => $field['type'] == 'number_decimal' ? $field['settings']['precision'] + 4 : 12,
    // Allow two extra characters for signed values and decimal separator.
    '#maxlength' => $field['type'] == 'number_decimal' ? $field['settings']['precision'] + 2 : 10,
    // Extract the number type from the field type name for easier validation.
    '#number_type' => str_replace('number_', '', $field['type']),
  );

  // Add prefix and suffix.
  if (!empty($instance['settings']['prefix'])) {
    $prefixes = explode('|', $instance['settings']['prefix']);
    $element['#field_prefix'] = field_filter_xss(array_pop($prefixes));
  }
  if (!empty($instance['settings']['suffix'])) {
    $suffixes = explode('|', $instance['settings']['suffix']);
    $element['#field_suffix'] = field_filter_xss(array_pop($suffixes));
  }

  $element['#element_validate'][] = 'number_field_widget_validate';

  return array('value' => $element);
}

/**
 * FAPI validation of an individual number element.
 */
function number_field_widget_validate($element, &$form_state) {
  $field = field_widget_field($element, $form_state);
  $instance = field_widget_instance($element, $form_state);

  $type = $element['#number_type'];
  $value = $element['#value'];

  // Reject invalid characters.
  if (!empty($value)) {
    switch ($type) {
      case 'float':
      case 'decimal':
        $regexp = '@[^-0-9\\' . $field['settings']['decimal_separator'] . ']@';
        $message = t('Only numbers and the decimal separator (@separator) allowed in %field.', array('%field' => t($instance['label']), '@separator' => $field['settings']['decimal_separator']));
        break;

      case 'integer':
        $regexp = '@[^-0-9]@';
        $message = t('Only numbers are allowed in %field.', array('%field' => t($instance['label'])));
        break;
    }
    if ($value != preg_replace($regexp, '', $value)) {
      form_error($element, $message);
    }
    else {
      // Substitute the decimal separator,
      if ($type == 'decimal' || $type == 'float') {
        $value = strtr($value, $field['settings']['decimal_separator'], '.');
      }
      form_set_value($element, $value, $form_state);
    }
  }
}

/**
 * Implements hook_field_widget_error().
 */
function number_field_widget_error($element, $error, $form, &$form_state) {
  form_error($element['value'], $error['message']);
}

Other Drupal examples (source code examples)

Here is a short list of links related to this Drupal number.module source code file:

new blog posts

"Drupal" is a registered trademark of Dries Buytaert.

my drupal tutorials and examples  

Copyright 1998-2016 Alvin Alexander, alvinalexander.com
All Rights Reserved.

Beginning in 2016, a portion of the proceeds from pages under the '/drupal-code-examples/' URI will be donated to charity.