You are here

regcode_dynamic.module in Registration codes 6.2

The dynamic code module creates codes on the fly as they are used.

File

regcode_dynamic/regcode_dynamic.module
View source
<?php

/**
 * @file
 * The dynamic code module creates codes on the fly as they are used.
 */

/**
 * Implementation of hook_help().
 */
function regcode_dynamic_help($path, $arg) {
  $output = '';

  //declare your output variable
  switch ($path) {
    case 'admin/user/regcode/dynamic':
      $output = '<p>';
      $output .= t('In some systems where thousands or hundreds of thousands ' . 'of codes need to be created, it is impractical to store ' . 'the codes in the regcode system. The regcode_dynamic module ' . 'allows the operator to define an algorithm for validating a ' . 'code. If a user registers with a code that passes this algorithm, ' . 'that code is then created dynamically and assigned to the ' . 'new user.');
      $output .= '</p>';
      break;
  }
  return $output;
}

/**
 * Implementation of hook_menu().
 */
function regcode_dynamic_menu() {
  $items = array();
  $items['admin/user/regcode/dynamic'] = array(
    'title' => 'Dynamic',
    'description' => 'Dynamic codes',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'regcode_dynamic_create',
    ),
    'access arguments' => array(
      'administer registration codes',
    ),
    'type' => MENU_LOCAL_TASK,
    'weight' => 70,
  );
  $items['admin/user/regcode/dynamic/rule/%'] = array(
    'title' => 'Edit rule',
    'description' => 'Modify settings for this dynamic code rule',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'regcode_dynamic_settings',
      5,
    ),
    'access arguments' => array(
      'administer registration codes',
    ),
    'type' => MENU_CALLBACK,
  );
  $items['admin/user/regcode/dynamic/rule/%/delete'] = array(
    'title' => 'Delete rule',
    'description' => 'Delete settings for this dynamic code rule',
    'page callback' => 'regcode_dynamic_settings_delete',
    'page arguments' => array(
      5,
    ),
    'access arguments' => array(
      'administer registration codes',
    ),
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Implementation of hook_user().
 */
function regcode_dynamic_user($op, &$edit, &$account, $category = NULL) {
  switch ($op) {
    case 'validate':
      if ($category === 'account' && !empty($edit['regcode_code'])) {

        // Check this code isn't already a code
        $regcode = regcode_load(array(
          'code' => $edit['regcode_code'],
        ));
        if ($regcode !== FALSE) {
          return;
        }

        // Ensure this is a valid dynamic code
        $rules = regcode_dynamic_rules();
        $valid = FALSE;
        foreach ($rules as $rule) {
          $handler = regcode_dynamic_handlers($rule['handler']);
          $valid = call_user_func($handler['validator'], $edit['regcode_code'], $rule);
          if ($valid) {
            break;
          }
        }
        if (!$valid) {
          return;
        }

        // Create the code just in time for regcode to take over
        $code = new stdClass();
        $code->code = $edit['regcode_code'];
        $tags = $rule['terms'];
        regcode_save($code, $tags);
      }
      break;
  }
}

/**
 * Callback: Delete a rule
 */
function regcode_dynamic_settings_delete($rule_id) {
  variable_del('regcode_dynamic_settings_' . $rule_id);
  drupal_set_message(t('Rule deleted'));
  drupal_goto('admin/user/regcode/dynamic');
}

/**
 * Form: Settings form for dynamic codes
 */
function regcode_dynamic_settings($form_state, $rule_id) {
  $data = variable_get('regcode_dynamic_settings_' . $rule_id, array());
  $handler = regcode_dynamic_handlers($data['handler']);
  $form = array();
  $form['regcode_dynamic_rule_id'] = array(
    '#type' => 'value',
    '#value' => $rule_id,
  );
  $form['regcode_dynamic_handler'] = array(
    '#type' => 'fieldset',
    '#title' => $handler['title'],
    '#description' => $handler['description'],
  );
  $form['regcode_dynamic_handler']['handler'] = array(
    '#type' => 'value',
    '#default_value' => $data['handler'],
  );
  $form['regcode_dynamic_handler']['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Rule name'),
    '#required' => TRUE,
    '#default_value' => $data['name'],
  );
  $form['regcode_dynamic_handler']['terms'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Tags codes'),
    '#description' => t('Tag dynamically created codes as they are used.'),
    '#options' => regcode_get_vocab_terms(),
    '#default_value' => (array) $data['terms'],
  );
  $handler_form = 'regcode_dynamic_handler_' . $data['handler'];
  $form['regcode_dynamic_handler'] += $handler_form($data);
  $form['regcode_dynamic_save'] = array(
    '#type' => 'submit',
    '#value' => t('Save configuration'),
  );
  $form['regcode_dynamic_delete'] = array(
    '#type' => 'submit',
    '#value' => t('Delete configuration'),
  );
  return $form;
}

/**
 * Form submit: Save settings form
 */
function regcode_dynamic_settings_submit($form, $form_state) {
  foreach (element_children($form['regcode_dynamic_handler']) as $key) {
    $data[$key] = $form_state['values'][$key];
  }
  $rule_id = $form_state['values']['regcode_dynamic_rule_id'];
  variable_set('regcode_dynamic_settings_' . $rule_id, $data);
  drupal_set_message(t('Your settings have been saved.'));
  drupal_goto('admin/user/regcode/dynamic');
}

/**
 * Form: Create form for dynamic codes
 */
function regcode_dynamic_create() {
  $handlers = regcode_dynamic_handlers();
  $options = array();
  foreach ($handlers as $handler_key => $handler) {
    $options[$handler_key] = $handler['title'];
  }
  $form = array();
  $form['regcode_dynamic_settings'] = array(
    '#type' => 'fieldset',
    '#title' => t('Create new configuration'),
  );
  $form['regcode_dynamic_settings']['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Rule name'),
    '#description' => t('Name this rule for administration purposes.'),
    '#required' => TRUE,
  );
  $form['regcode_dynamic_settings']['handler'] = array(
    '#type' => 'select',
    '#title' => t('Handler'),
    '#options' => $options,
    '#description' => t('Select the handler used to validate codes.'),
    '#required' => TRUE,
  );
  $form['regcode_dynamic_settings']['save'] = array(
    '#type' => 'submit',
    '#value' => t('Create handler'),
  );
  $form['regcode_dynamic_rules_list'] = array(
    '#value' => regcode_dynamic_rules_list(),
  );
  return $form;
}

/**
 * Form submit: Create a new rule set
 */
function regcode_dynamic_create_submit($form, $form_state) {

  // Grab all of the existing handlers so we can know the next ID to create
  $res = db_query("SELECT name FROM {variable} WHERE name like 'regcode_dynamic_settings_%' ORDER BY name DESC");
  $count = db_affected_rows($res);
  if ($count === 0) {
    $id = 1;
  }
  else {
    $key = explode('_', db_result($res));

    // Strip the integer out of the key name
    $id = (int) $key[3] + 1;
  }
  $data = array(
    'name' => $form_state['values']['name'],
    'handler' => $form_state['values']['handler'],
  );
  variable_set(sprintf('regcode_dynamic_settings_%d', $id), $data);
  drupal_set_message('New dynamic rule created');
  drupal_goto('admin/user/regcode/dynamic/rule/' . $id);
}

/**
 * Return all of the rules
 */
function regcode_dynamic_rules() {
  $res = db_query("SELECT name FROM {variable} WHERE name like 'regcode_dynamic_settings_%'");
  $rows = array();
  while ($row = db_fetch_array($res)) {
    $key = explode('_', $row['name']);
    $id = $key[3];
    $data = variable_get($row['name'], array());
    $data['id'] = $id;
    $rows[] = $data;
  }
  return $rows;
}

/**
 * List all of the rules as a HTML table
 */
function regcode_dynamic_rules_list() {
  $rules = regcode_dynamic_rules();
  $rows = array();
  foreach ($rules as $row) {
    $actions = array();
    $actions[] = l('Edit', sprintf('admin/user/regcode/dynamic/rule/%d', $row['id']));
    $actions[] = l('Delete', sprintf('admin/user/regcode/dynamic/rule/%d/delete', $row['id']));
    $rows[] = array(
      $row['id'],
      $row['name'],
      $row['handler'],
      implode(' | ', $actions),
    );
  }
  $headers = array(
    t('Rule #'),
    t('Name'),
    t('Handler'),
  );
  return theme('table', $headers, $rows);
}

/**
 * Grab all available dynamic code handlers
 */
function regcode_dynamic_handlers($handler = NULL) {

  // Module defined handlers
  $handlers = array(
    'simple' => array(
      'title' => t('Simple handler'),
      'description' => t('This handler uses incremental numbers with a configurable offset. These numbers can be easily guessed if the pattern is known.'),
      'configuration' => 'regcode_dynamic_handler_simple',
      'validator' => 'regcode_dynamic_handler_simple_validate',
    ),
    'luhn' => array(
      'title' => t('Luhn handler (TODO)'),
      'description' => t('Uses the <a href="http://en.wikipedia.org/wiki/Luhn_algorithm">luhn algorithm</a> to validate registration codes.'),
      'configuration' => 'regcode_dynamic_handler_luhn',
      'validator' => 'regcode_dynamic_handler_luhn_validate',
    ),
  );

  // Check if we're loading a specific handler
  if ($handler !== NULL) {
    if (isset($handlers[$handler])) {
      return $handlers[$handler];
    }
    else {
      return FALSE;
    }
  }
  return $handlers;
}

/**
 * Grab the setting for the selected dynamic rule set
 */
function regcode_dynamic_variable_get($data, $parameter, $default) {
  return isset($data[$parameter]) ? $data[$parameter] : $default;
}

/**
 * Simple incremental number handler
 */
function regcode_dynamic_handler_simple($data) {
  $form = array();
  $form['startnumber'] = array(
    '#type' => 'textfield',
    '#title' => t('Start number'),
    '#description' => t('The number to start from.'),
    '#default_value' => regcode_dynamic_variable_get($data, 'startnumber', 1000000000),
    '#required' => TRUE,
  );
  $form['length'] = array(
    '#type' => 'textfield',
    '#title' => t('Code length'),
    '#description' => t('The length of the dynamic code.'),
    '#default_value' => regcode_dynamic_variable_get($data, 'length', 10),
    '#required' => TRUE,
  );
  $form['increment'] = array(
    '#type' => 'textfield',
    '#title' => t('Code increment'),
    '#description' => t('The difference between each dynamic code.'),
    '#default_value' => regcode_dynamic_variable_get($data, 'increment', 7),
    '#required' => TRUE,
  );
  return $form;
}

/**
 * Validate whether a code is a valid number
 */
function regcode_dynamic_handler_simple_validate($number, $settings) {
  $number = (int) $number;
  $startnumber = (int) $settings['startnumber'];
  $length = (int) $settings['length'];
  $increment = (int) $settings['increment'];

  // Check the number is big enough
  if ($number < $startnumber) {
    return FALSE;
  }
  if (strlen($number) !== $length) {
    return FALSE;
  }
  $number = $number - $startnumber;
  if ($number % $increment !== 0) {
    return FALSE;
  }
  return TRUE;
}

/**
 * Luhn number handler
 */
function regcode_dynamic_handler_luhn() {
  $form = array();
  $form['startnumber'] = array(
    '#type' => 'textfield',
    '#title' => t('Start number'),
    '#description' => t('The number to start from'),
    '#default_value' => variable_get('startnumber', 1000000000),
    '#required' => TRUE,
  );
  $form['length'] = array(
    '#type' => 'textfield',
    '#title' => t('Code length'),
    '#description' => t('The length of the dynamic code'),
    '#default_value' => variable_get('length', 10),
    '#required' => TRUE,
  );
  return $form;
}

/**
 * Validate a number against the luhn algorithm
 *
 * @see http://en.wikipedia.org/wiki/Luhn_algorithm
 */
function regcode_dynamic_handler_luhn_validate($number) {
  return FALSE;
}

Functions

Namesort descending Description
regcode_dynamic_create Form: Create form for dynamic codes
regcode_dynamic_create_submit Form submit: Create a new rule set
regcode_dynamic_handlers Grab all available dynamic code handlers
regcode_dynamic_handler_luhn Luhn number handler
regcode_dynamic_handler_luhn_validate Validate a number against the luhn algorithm
regcode_dynamic_handler_simple Simple incremental number handler
regcode_dynamic_handler_simple_validate Validate whether a code is a valid number
regcode_dynamic_help Implementation of hook_help().
regcode_dynamic_menu Implementation of hook_menu().
regcode_dynamic_rules Return all of the rules
regcode_dynamic_rules_list List all of the rules as a HTML table
regcode_dynamic_settings Form: Settings form for dynamic codes
regcode_dynamic_settings_delete Callback: Delete a rule
regcode_dynamic_settings_submit Form submit: Save settings form
regcode_dynamic_user Implementation of hook_user().
regcode_dynamic_variable_get Grab the setting for the selected dynamic rule set