You are here

function webform_serial_webform_submission_presave in Webform Serial 7

Implements hook_webform_submission_presave().

File

components/serial.inc, line 178
Webform module serial component.

Code

function webform_serial_webform_submission_presave($node, &$submission) {
  foreach ($node->webform['components'] as $cid => $component) {

    // If component is a serial number with no value, generate a value.
    if ($component['type'] === 'serial' && empty($submission->data[$cid][0])) {

      // Calculate the increment (default to 1).
      $increment = empty($component['extra']['increment']) ? 1 : (int) $component['extra']['increment'];

      // Get largest serial number in the database to ensure the new one is larger.
      $query = db_select('webform_submitted_data')
        ->condition('nid', $node->nid)
        ->condition('cid', $cid);

      // CAST() is needed because value is stored as text but must be sorted as a number.
      // Must CAST() to "decimal" because MySQL does not support "integer".
      $query
        ->addExpression('MAX(CAST(data AS decimal))');
      $current_max = (int) $query
        ->execute()
        ->fetchField();

      // Use a transaction with SELECT ... FOR UPDATE to lock the row between
      // the SELECT and the UPDATE, ensuring that multiple Webform submissions
      // at the same time do not have duplicate numbers.
      $txn = db_transaction();

      // Get the next serial number as configured in the component.
      $component_extra = db_select('webform_component', 'wc')
        ->forUpdate()
        ->fields('wc', array(
        'extra',
      ))
        ->condition('nid', $node->nid)
        ->condition('cid', $cid)
        ->execute()
        ->fetchField();
      $component_extra = unserialize($component_extra);
      $next_value = empty($component['extra']['initial']) ? 1 : $component['extra']['initial'];

      // If the next value is smaller than the largest value currently in the
      // database, increment the largest value and use that as the next value.
      if ($next_value <= $current_max) {
        $next_value = $current_max + $increment;
      }

      // Increment the next value and save it in the database.
      $component_extra['initial'] = $next_value + $increment;
      db_update('webform_component')
        ->fields(array(
        'extra' => serialize($component_extra),
      ))
        ->condition('nid', $node->nid)
        ->condition('cid', $cid)
        ->execute();
      $submission->data[$cid] = array(
        $next_value,
      );
    }
  }
}