You are here

units.module in Units of Measurement 7

Same filename and directory in other branches
  1. 6 units.module
  2. 7.2 units.module

Provide API for managing and converting units of measurement.

File

units.module
View source
<?php

/**
 * @file
 * Provide API for managing and converting units of measurement.
 */

/**
 * Implements hook_entity_info().
 */
function units_entity_info() {
  $entity_info = array();
  $entity_info['units_unit'] = array(
    'label' => t('Unit measurement'),
    'entity class' => 'Entity',
    'controller class' => 'EntityAPIControllerExportable',
    'base table' => 'units_unit',
    'fieldable' => TRUE,
    'exportable' => TRUE,
    'entity keys' => array(
      'id' => 'umid',
      'bundle' => 'measure',
      'label' => 'label',
      'name' => 'machine_name',
    ),
    'bundles' => array(),
    'bundle keys' => array(
      'bundle' => 'measure',
    ),
    'module' => 'units',
    'access callback' => 'units_entity_access',
  );

  // We can't use here entity_load functions, nor EntityFieldQuery because
  // entity info is not exposed to core yet.
  $measures = db_select('units_measure', 'u_m')
    ->fields('u_m', array(
    'measure',
    'label',
  ))
    ->execute()
    ->fetchAllAssoc('measure');
  foreach ($measures as $measure) {
    $entity_info['units_unit']['bundles'][$measure->measure] = array(
      'label' => $measure->label,
    );
  }
  $entity_info['units_measure'] = array(
    'label' => t('Measure'),
    'entity class' => 'Entity',
    'controller class' => 'EntityAPIControllerExportable',
    'base table' => 'units_measure',
    'fieldable' => FALSE,
    'exportable' => TRUE,
    'bundle of' => 'units_unit',
    'entity keys' => array(
      'id' => 'mid',
      'label' => 'label',
      'name' => 'measure',
    ),
    'module' => 'units',
    'access callback' => 'units_entity_access',
  );
  return $entity_info;
}

/**
 * Implements hook_ctools_plugin_type().
 */
function units_ctools_plugin_type() {
  $plugins = array();
  $plugins['converters'] = array(
    'defaults' => array(
      'title' => NULL,
      'description' => NULL,
      'convert callback' => NULL,
    ),
  );
  return $plugins;
}

/**
 * Implements hook_ctools_plugin_directory().
 */
function units_ctools_plugin_directory($owner, $plugin_type) {
  switch ($owner) {
    case 'units':
      switch ($plugin_type) {
        case 'converters':
          return 'plugins/' . $plugin_type;
      }
      break;
  }
}

/**
 * Convert value measured in one unit into value measured in another unit.
 *
 * @param float $value
 *   Value to be converted
 * @param string $from
 *   Units in which $value is measured. Supply machine-readable name of the unit
 * @param string $to
 *   Units in which $value needs to be converted. Supply machine-readable name
 *   of the unit
 * @param string $measure
 *   Optional. Measure of value to be converted, normally the measure is looked
 *   up using the provided $form and $to, but in case the same unit measure is
 *   used in different measures, this parameter may narrow down unit measures
 *   to necessary scope of the supplied measure.
 *
 * @return float
 *   Value $value, converted from $from units into $to units
 */
function units_convert($value, $from, $to, $measure = NULL) {
  if ($from == $to) {

    // That's an easy one. Value converting from a unit into the same unit
    // always will be the same value.
    return $value;
  }
  $query = new EntityFieldQuery();
  $query
    ->entityCondition('entity_type', 'units_unit')
    ->propertyCondition('machine_name', array(
    $from,
    $to,
  ));
  if (!is_null($measure)) {
    $query
      ->entityCondition('bundle', $measure);
  }
  $result = $query
    ->execute();
  if (!isset($result['units_unit']) || count($result['units_unit']) != 2) {

    // Probably wrong $from and/or $to were supplied, otherwise we would have
    // got exactly 2 results.
    return FALSE;
  }

  // Loading entities.
  $entities = units_unit_load_multiple(array_keys($result['units_unit']));
  foreach ($entities as $entity) {
    switch ($entity->machine_name) {
      case $from:
        $from = $entity;
        break;
      case $to:
        $to = $entity;
        break;
    }
  }
  if ($from->measure != $to->measure) {

    // The found units are from different measures. That's not okay.
    return FALSE;
  }

  // Loading measure.
  $measure = units_measure_machine_name_load(field_extract_bundle('units_unit', $from));
  $plugin = units_get_converter($measure->converter);
  if (!$plugin) {
    return FALSE;
  }
  $function = ctools_plugin_get_function($plugin, 'convert callback');
  if (!$function) {
    return FALSE;
  }
  return $function($value, $from, $to);
}

/**
 * Access callback for entity types 'units_measure' and 'units_unit'.
 *
 * @param string $op
 *   The operation being performed. One of 'view', 'update', 'create' or
 *   'delete'
 * @param object $entity
 *   Entity object on which the operation is requested to be performed
 * @param object $account
 *   Fully loaded user object of the account who requests to perform the
 *   operation
 * @param string $entity_type
 *   Entity type on which the operation is requested to be performed
 *
 * @return bool
 *   Whether access has been granted
 */
function units_entity_access($op, $entity, $account, $entity_type) {

  // There is no reason why we would limit access to 'units_measure' or
  // 'units_unit' entities.
  return TRUE;
}

/**
 * Implements hook_ENTITY_TYPE_delete().
 */
function units_units_measure_delete($entity) {

  // Additionally delete units defined in the measure that is being deleted.
  $ids = array();
  foreach (units_unit_by_measure_load_multiple($entity) as $unit) {
    $tmp = entity_extract_ids('units_unit', $unit);
    $ids[] = $tmp[0];
  }
  units_unit_delete_multiple($ids);
}

/**
 * Implements hook_ENTITY_TYPE_update().
 */
function units_units_measure_update($entity) {
  if ($entity->measure != $entity->original->measure) {
    db_update('units_unit')
      ->condition('measure', $entity->original->measure)
      ->fields(array(
      'measure' => $entity->measure,
    ))
      ->execute();
  }
}

/**
 * Load an entity of entity type 'units_unit' by its ID.
 */
function units_unit_load($umid, $reset = FALSE) {
  $units = units_unit_load_multiple(array(
    $umid,
  ), array(), $reset);
  return reset($units);
}

/**
 * Load multiple entities of entity type 'units_unit'.
 */
function units_unit_load_multiple($umids = FALSE, $conditions = array(), $reset = FALSE) {
  return entity_load('units_unit', $umids, $conditions, $reset);
}

/**
 * Load a single entity of type 'units_unit' loading by its machine name.
 *
 * @param string $machine_name
 *   Machine name of entity to load
 *
 * @return object|bool
 *   Return fully loaded entity object if it was found, otherwise FALSE
 */
function units_unit_machine_name_load($machine_name) {
  $query = new EntityFieldQuery();
  $result = $query
    ->entityCondition('entity_type', 'units_unit')
    ->propertyCondition('machine_name', $machine_name)
    ->execute();
  if (isset($result['units_unit'])) {
    $keys = array_keys($result['units_unit']);
    $entity_id = array_pop($keys);
    return units_unit_load($entity_id);
  }

  // No entity was found.
  return FALSE;
}

/**
 * Load all units of the supplied measure.
 *
 * @param mixed $measure
 *   Either ID of the measure,
 *   or machine-readable name of the measure
 *   or fully loaded 'units_measure' entity object
 *
 * @return array
 *   Array of fully loaded 'units_unit' entity objects that belong to the
 *   supplied $measure
 */
function units_unit_by_measure_load_multiple($measure) {

  // Trying to load entity object of $measure, if we were not supplied with one.
  if (is_numeric($measure)) {
    $measure = units_measure_load($measure);
  }
  elseif (!is_object($measure)) {
    $measure = units_measure_machine_name_load($measure);
  }
  if (!is_object($measure)) {

    // Probably we were supplied with bad parameter $measure, because at this
    // point we are already supposed to have fully loaded 'units_measure' entity
    // object.
    return array();
  }
  $bundle = field_extract_bundle('units_unit', $measure);
  $efq = new EntityFieldQuery();
  $result = $efq
    ->entityCondition('entity_type', 'units_unit')
    ->entityCondition('bundle', $bundle)
    ->execute();
  return isset($result['units_unit']) ? units_unit_load_multiple(array_keys($result['units_unit'])) : array();
}

/**
 * Save an entity of type 'units_unit'.
 */
function units_unit_save($entity) {
  entity_save('units_unit', $entity);
}

/**
 * Delete a single entity of type 'units_unit'.
 */
function units_unit_delete($entity) {
  entity_delete('units_unit', entity_id('units_unit', $entity));
}

/**
 * Delete multiple entities of type 'units_unit'.
 *
 * @param array $umids
 *   Array of entity ids to be deleted
 */
function units_unit_delete_multiple($umids) {
  entity_delete_multiple('units_unit', $umids);
}

/**
 * Load an entity of entity type 'units_measure' by its ID.
 */
function units_measure_load($mid, $reset = FALSE) {
  $measures = units_measure_load_multiple(array(
    $mid,
  ), array(), $reset);
  return reset($measures);
}

/**
 * Load multiple entities of entity type 'units_unit'.
 */
function units_measure_load_multiple($mids = FALSE, $conditions = array(), $reset = FALSE) {
  return entity_load('units_measure', $mids, $conditions, $reset);
}

/**
 * Load a single entity of type 'units_measure' loading by its machine name.
 *
 * @param string $machine_name
 *   Machine name of entity to load
 *
 * @return object|bool
 *   Return fully loaded entity object if it was found, otherwise FALSE
 */
function units_measure_machine_name_load($machine_name) {
  $query = new EntityFieldQuery();
  $result = $query
    ->entityCondition('entity_type', 'units_measure')
    ->propertyCondition('measure', $machine_name)
    ->execute();
  if (isset($result['units_measure'])) {
    $keys = array_keys($result['units_measure']);
    $entity_id = array_pop($keys);
    return units_measure_load($entity_id);
  }

  // No entity was found.
  return FALSE;
}

/**
 * Save an entity of type 'units_measure'.
 */
function units_measure_save($entity) {
  entity_save('units_measure', $entity);
}

/**
 * Delete a single entity of type 'units_measure'.
 */
function units_measure_delete($entity) {
  entity_delete('units_measure', entity_id('units_measure', $entity));
}

/**
 * Delete multiple entities of type 'units_measure'.
 *
 * @param array $mids
 *   Array of entity ids to be deleted
 */
function units_measure_delete_multiple($mids) {
  entity_delete_multiple('units_measure', $mids);
}

/**
 * Retrieve information about a ctools plugin - units converter.
 *
 * @param string $converter
 *   Name of a particular units converter plugin to return. If skipped, an array
 *   of all available units converters plugins will be returned
 *
 * @return array
 *   Depending on whether $converter is provided it will be either a single
 *   array of information about provided $converter units converter plugin or
 *   array of information on all available units converter plugins
 */
function units_get_converter($converter = NULL) {
  ctools_include('plugins');
  return ctools_get_plugins('units', 'converters', $converter);
}

Functions

Namesort descending Description
units_convert Convert value measured in one unit into value measured in another unit.
units_ctools_plugin_directory Implements hook_ctools_plugin_directory().
units_ctools_plugin_type Implements hook_ctools_plugin_type().
units_entity_access Access callback for entity types 'units_measure' and 'units_unit'.
units_entity_info Implements hook_entity_info().
units_get_converter Retrieve information about a ctools plugin - units converter.
units_measure_delete Delete a single entity of type 'units_measure'.
units_measure_delete_multiple Delete multiple entities of type 'units_measure'.
units_measure_load Load an entity of entity type 'units_measure' by its ID.
units_measure_load_multiple Load multiple entities of entity type 'units_unit'.
units_measure_machine_name_load Load a single entity of type 'units_measure' loading by its machine name.
units_measure_save Save an entity of type 'units_measure'.
units_units_measure_delete Implements hook_ENTITY_TYPE_delete().
units_units_measure_update Implements hook_ENTITY_TYPE_update().
units_unit_by_measure_load_multiple Load all units of the supplied measure.
units_unit_delete Delete a single entity of type 'units_unit'.
units_unit_delete_multiple Delete multiple entities of type 'units_unit'.
units_unit_load Load an entity of entity type 'units_unit' by its ID.
units_unit_load_multiple Load multiple entities of entity type 'units_unit'.
units_unit_machine_name_load Load a single entity of type 'units_unit' loading by its machine name.
units_unit_save Save an entity of type 'units_unit'.