<?php
// $Id: ajaxsubmit.module,v 1.6.2.1 2006/05/30 04:30:13 nedjo Exp $

/**
 * @file
 * Make designated forms submit via AJAX.
 *
 * Usage:
 *
 * <code>
 * $form['#ajaxsubmit'] = TRUE;
 * </code>
 *
 * Optional settings
 *
 * Progress: ajaxsubmit can monitor for progress of a form submit.
 * Trigger this behavior as follows:
 *
 * <code>
 * $form['#ajaxsubmit_progress'] = TRUE;
 * </code>
 */

/**
 * Implementation of hook_help().
 */
function ajaxsubmit_help($section) {
  switch ($section) {
    case 'admin/modules#description':
      return t('Makes designated forms submit via AJAX.');
  }
}

/**
 * Implementation of hook_form_alter().
 */
function ajaxsubmit_form_alter($form_id, &$form) {
  if ($form['#ajaxsubmit']) {
    // If we're using ajaxsubmit and the form's already been submitted, redirect.
    if (!empty($_POST['ajaxsubmit']) && !empty($_POST['edit']) && ($_POST['edit']['form_id'] == $form_id)) {
      // Redirect on successful submit, i.e., if there are no errors.
      $form['#redirect'] = 'ajaxsubmit/dispatch';
      if (is_array($form['#pre_render'])) {
        $form['#pre_render'][] = 'ajaxsubmit_dispatch';
      }
      else {
        $form['#pre_render'] = array('ajaxsubmit_dispatch');
      }
    }
    else {
      // In case a destination was set by a previous transaction, unset it
      // so that this one can set its own as needed.
      unset($_SESSION['ajaxsubmit_destination']);
      ajaxsubmit_load();
      $form['#attributes']['class'] .= ' ajaxsubmit';
      if ($form['#ajaxsubmit_progress']) {
        // Value is the path to the progress monitoring.
        $form['ajaxsubmit_progress'] = array(
          '#type' => 'hidden',
          '#value' => url(drupal_get_path('module', 'ajaxsubmit') . '/ajaxsubmit_update')
        );
      }
      if ($form['#ajaxsubmit_error_message']) {
        $form['ajaxsubmit_error_message'] = array(
          '#type' => 'hidden',
          '#value' => $form['#ajaxsubmit_error_message']
        );
      }
      if ($form['#ajaxsubmit_error_redirect']) {
        $form['ajaxsubmit_error_redirect'] = array(
          '#type' => 'hidden',
          '#value' => $form['#ajaxsubmit_error_redirect']
        );
      }
    }
  }
}

/**
 * Implementation of hook_menu().
 */
function ajaxsubmit_menu($may_cache) {
  $items = array();
  if ($may_cache) {
    $items[] = array(
      'path' => 'ajaxsubmit/dispatch',
      'title' => t('ajaxsubmit'),
      'access' => user_access('access content'),
      'type' => MENU_CALLBACK,
      'callback' => 'ajaxsubmit_dispatch'
     );
    $items[] = array(
      'path' => 'ajaxsubmit/progress',
      'title' => t('ajaxsubmit progress'),
      'access' => user_access('access content'),
      'type' => MENU_CALLBACK,
      'callback' => 'ajaxsubmit_progress'
     );
  }
  return $items;
}

/**
 * Load needed files.
 */
function ajaxsubmit_load($lib_locale = NULL) {
  $path = drupal_get_path('module', 'ajaxsubmit');
  module_invoke('jstools', 'add_js', array($path . '/ajaxsubmit.js'));
}

/**
 * Return form submit result.
 */
function ajaxsubmit_dispatch($form_id = NULL, $form = NULL) {
  $result = array(
    'status' => TRUE,
    'data' =>  array(
      'errors' => form_get_errors(),
      'message' => theme('status_messages'),
      'preview' => isset($form[arg(0) . '_preview']) && !empty($form[arg(0) . '_preview']['#value']) ? $form[arg(0) . '_preview']['#value'] : NULL,
      'destination' => $_SESSION['ajaxsubmit_destination'] ? $_SESSION['ajaxsubmit_destination'] : NULL
    )
  );
  print drupal_to_js($result);
  exit();
}

/**
 * Return progress percentage and message.
 *
 * The _submit function must set two session variables:
 * - $_SESSION['{form_id}_total'], the total number of actions to be taken during this submit, and
 * - $_SESSION['{form_id}_remaining'], the number of actions remaining.
 * In each of these, the 'form_id' value should be the id of the form in question.
 */
function ajaxsubmit_progress() {
  $form_id = $_REQUEST['form_id'];
  $percentage = floor(($_SESSION[$form_id . '_total'] - $_SESSION[$form_id . '_remaining']) / $_SESSION[$form_id . '_total'] * 100);
  $message = ($percentage == 100) ? t('Submit complete') : t('Submit in progress');
  print drupal_to_js(array('status' => TRUE, 'percentage' => $percentage, 'message' => $message));
}