You are here

registration.forms.inc in Entity Registration 7.2

Form definitions and callbacks for Registration.

File

includes/registration.forms.inc
View source
<?php

/**
 * @file
 * Form definitions and callbacks for Registration.
 */

/**
 * Form callback: create or edit a registration.
 *
 * @param Registration $registration
 *   The registration object to edit or for a create form an empty registration
 *   object with a node defined.
 */
function registration_form($form, &$form_state, Registration $registration, $new = TRUE) {
  global $user;
  $wrapper = entity_metadata_wrapper('registration', $registration);
  $host = $wrapper->entity
    ->value();
  $state = $wrapper->state
    ->value();
  $type = $wrapper
    ->getBundle();
  $registrant_mail = $wrapper->registrant_mail
    ->value();
  $form_state['registration'] = $registration;
  $form['#registration_is_new'] = $new;
  $settings = registration_entity_settings($registration->entity_type, $registration->entity_id);
  if (!registration_has_room($registration->entity_type, $registration->entity_id)) {
    if ($settings['settings']['registration_waitlist_enable'] == 1 && $settings['settings']['registration_waitlist_message_enable'] == 1) {
      drupal_set_message(t($settings['settings']['registration_waitlist_message']), 'warning');
    }
  }

  // Options for who is registering.
  $who_options = array();
  if (!empty($user->mail) && user_access("create own {$type} registration")) {
    $who_options[REGISTRATION_REGISTRANT_TYPE_SELF] = t('Myself');
  }
  if (user_access("create {$type} registration")) {
    $who_options[REGISTRATION_REGISTRANT_TYPE_OTHER] = t('Other person');
  }

  // Default value for who is registering.
  $who_default = NULL;
  if (isset($registration->registration_id) && $registrant_mail) {
    if (!empty($user->mail) && $user->mail === $registrant_mail) {
      $who_default = REGISTRATION_REGISTRANT_TYPE_SELF;
    }
    else {
      $who_default = REGISTRATION_REGISTRANT_TYPE_OTHER;
    }
  }
  elseif (count($who_options) == 1) {
    $keys = array_keys($who_options);
    $who_default = reset($keys);
  }
  $form['who_is_registering'] = array(
    '#type' => 'select',
    '#title' => t('This registration is for:'),
    '#options' => $who_options,
    '#default_value' => $who_default,
    '#required' => TRUE,
    '#access' => count($who_options) > 1,
  );
  if (isset($who_options[REGISTRATION_REGISTRANT_TYPE_SELF])) {

    // Show a message for registering yourself.
    $form['registrant_self'] = array(
      '#type' => 'container',
      '#states' => array(
        'visible' => array(
          ':input[name="who_is_registering"]' => array(
            'value' => REGISTRATION_REGISTRANT_TYPE_SELF,
          ),
        ),
      ),
    );
    $form['registrant_self']['content'] = array(
      '#markup' => '<div class="form-item registration-registrant-self">' . t('You are registering: %mail', array(
        '%mail' => $user->mail,
      )) . '</div>',
    );
  }
  $form['registrant_mail'] = array(
    '#type' => 'textfield',
    '#title' => t('Email'),
    '#description' => t('The email to associate with this registration.'),
    '#default_value' => $registrant_mail,
    '#size' => 40,
    '#maxlength' => 255,
    '#access' => isset($who_options[REGISTRATION_REGISTRANT_TYPE_OTHER]),
    '#states' => array(
      'visible' => array(
        ':input[name="who_is_registering"]' => array(
          'value' => REGISTRATION_REGISTRANT_TYPE_OTHER,
        ),
      ),
      'required' => array(
        ':input[name="who_is_registering"]' => array(
          'value' => REGISTRATION_REGISTRANT_TYPE_OTHER,
        ),
      ),
    ),
  );

  // Add a container to hold registrant form fields.
  $form['registrant_fields'] = array(
    '#type' => 'container',
    '#access' => !empty($settings['settings']['upsert_registrants']),
    '#attributes' => array(
      'class' => array(
        'registrant-fields',
      ),
    ),
  );
  $capacity = $settings['capacity'];
  $limit = isset($settings['settings']['maximum_spaces']) ? $settings['settings']['maximum_spaces'] : 1;

  // Just in case it was unset:
  $settings['settings']['maximum_spaces'] = $limit;
  $remaining = $capacity - registration_event_count($registration->entity_type, $registration->entity_id);
  if ($capacity && $limit) {
    $description = t('The number of spaces you wish to reserve. @spaces_remaining spaces remaining. You may register up to @max spaces.', array(
      '@spaces_remaining' => $remaining,
      '@max' => min($limit, $remaining),
    ));
  }
  elseif ($capacity) {
    $description = t('The number of spaces you wish to reserve. @spaces_remaining spaces remaining.', array(
      '@spaces_remaining' => $remaining,
    ));
  }
  elseif ($limit) {
    $description = t('The number of spaces you wish to reserve. You may register up to @max spaces.', array(
      '@max' => $limit,
    ));
  }
  else {
    $description = t('The number of spaces you wish to reserve.');
  }
  $form['count'] = array(
    '#type' => 'textfield',
    '#title' => t('Spaces'),
    '#description' => $description,
    '#default_value' => isset($registration->count) ? $registration->count : 1,
    '#size' => drupal_strlen($remaining),
    '#access' => isset($settings['settings']['maximum_spaces']) && $settings['settings']['maximum_spaces'] == 1 ? FALSE : TRUE,
    '#element_validate' => array(
      'element_validate_integer_positive',
      '_registration_validate_space_request',
    ),
  );
  $default_state = registration_get_default_state($type);
  $states = registration_get_states_options(array(
    'show_on_form' => TRUE,
  ));

  // Ensure default state is in options or it won't be set.
  if (!isset($states[$default_state->name])) {
    $states[$default_state->name] = t('@state', array(
      '@state' => entity_label('registration_state', $default_state),
    ));
  }
  $form['state'] = array(
    '#type' => 'select',
    '#title' => t('State'),
    '#description' => t('State of this registration'),
    '#default_value' => $state ? $state
      ->identifier() : $default_state
      ->identifier(),
    '#options' => $states,
    '#access' => !empty($states) && user_access('edit ' . $registration->type . ' registration state'),
  );
  field_attach_form('registration', $registration, $form, $form_state);
  $form['actions'] = array(
    '#type' => 'actions',
  );
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save Registration'),
  );

  // Add a delete button for existing registration:
  if (isset($registration->registration_id) && entity_access('delete', 'registration', $registration)) {
    $form['actions']['delete'] = array(
      '#type' => 'submit',
      '#value' => t('Delete'),
      '#submit' => array(
        'registration_form_delete_submit',
      ),
      "#limit_validation_errors" => array(),
    );
  }
  if ($host && entity_access('view', $registration->entity_type, $host)) {
    $uri = entity_uri($registration->entity_type, $host);
    $form['actions']['cancel'] = array(
      '#type' => 'link',
      '#title' => t('Cancel'),
      '#href' => $uri['path'],
    );
  }
  $form['#registration_settings'] = $settings;
  return $form;
}

/**
 * Validation callback for registration_form().
 */
function registration_form_validate($form, &$form_state) {
  global $user;
  $registration = $form_state['registration'];
  $count = $form_state['values']['count'];
  $label = entity_label($registration->entity_type, entity_load_single($registration->entity_type, $registration->entity_id));

  // Test status on new registrations.
  if (isset($registration->is_new) && $registration->is_new) {
    $errors = array();
    $registration_status = registration_status($registration->entity_type, $registration->entity_id, TRUE, $count, $registration->registration_id, $errors);
    if (!$registration_status) {
      form_set_error('', t('Sorry, unable to register for %label due to: %errors.', array(
        '%label' => $label,
        '%errors' => implode(', ', $errors),
      )));
    }
  }
  elseif (in_array($registration->state, registration_get_active_states())) {
    $has_room = registration_has_room($registration->entity_type, $registration->entity_id, $count, $registration->registration_id);
    if (!$has_room) {
      form_set_error('', t('Sorry, unable to register for %label due to: insufficient spaces remaining.', array(
        '%label' => $label,
      )));
    }
  }
  $settings = registration_entity_settings($registration->entity_type, $registration->entity_id);
  $allow_multiple = !empty($settings['settings']['multiple_registrations']) && $settings['settings']['multiple_registrations'];

  // Validate according to who's registering.
  switch ($form_state['values']['who_is_registering']) {
    case REGISTRATION_REGISTRANT_TYPE_SELF:
      if (!$allow_multiple && registration_is_registered($registration, $user->mail)) {
        form_set_error('registrant_self', t('You are already registered for this event.'));
      }
      break;
    case REGISTRATION_REGISTRANT_TYPE_OTHER:
      $form_state['values']['registrant_mail'] = trim($form_state['values']['registrant_mail']);
      if (!valid_email_address($form_state['values']['registrant_mail'])) {
        form_set_error('registrant_mail', t('The email address is invalid.'));
      }
      if (!$allow_multiple && registration_is_registered($registration, $form_state['values']['registrant_mail'])) {
        form_set_error('registrant_mail', t('%mail is already registered for this event.', array(
          '%mail' => $form_state['values']['registrant_mail'],
        )));
      }
      break;
  }

  // Notify field widgets to validate their data.
  field_attach_form_validate('registration', $registration, $form, $form_state);
}

/**
 * Submit callback for registration_form().
 */
function registration_form_submit($form, &$form_state) {
  global $user;
  $registration = $form_state['registration'];
  $registration_type = registration_get_types($registration->type);
  $settings = registration_entity_settings($registration->entity_type, $registration->entity_id);
  $registrant_entity_type = $registration_type->registrant_entity_type;
  $registrant_bundle = $registration_type->registrant_bundle;
  $registrant_entity_info = entity_get_info($registrant_entity_type);

  // Set the registration's author uid:
  if (!isset($registration->registration_id)) {
    $registration->author_uid = $user->uid;
  }
  $registration->count = $form_state['values']['count'];
  if (!empty($form_state['values']['state'])) {
    $registration->state = $form_state['values']['state'];
  }
  $registrant_mail = NULL;
  switch ($form_state['values']['who_is_registering']) {
    case REGISTRATION_REGISTRANT_TYPE_SELF:
      $registrant_mail = $user->mail;
      break;
    case REGISTRATION_REGISTRANT_TYPE_OTHER:
      $registrant_mail = $form_state['values']['registrant_mail'];
      break;
  }

  // Look up entity by $registrant_mail.
  $registrant_wrapper = registration_registrant_load_by_mail($registration_type, $registrant_mail);
  if (!empty($settings['settings']['upsert_registrants'])) {
    if (!$registrant_wrapper) {
      $registrant_wrapper = registration_registrant_create($registration_type, $registrant_mail);
    }
    $registrant = $registrant_wrapper
      ->value();
    $values_excluding_fields = $form_state['values'];
    if ($registrant_entity_info['fieldable']) {
      $values_excluding_fields = array_diff_key($form_state['values'], field_info_instances($registrant_entity_type, $registrant_bundle));
    }
    $values_in_sub_form = array_intersect_key($values_excluding_fields, $form['registrant_fields']);
    foreach ($values_in_sub_form as $key => $value) {
      $registrant->{$key} = $value;
    }
    if ($registrant_entity_info['fieldable']) {
      field_attach_submit($registrant_entity_type, $registrant, $form, $form_state);
    }
    $registrant_wrapper = entity_metadata_wrapper($registrant_entity_type, $registrant);
    $registrant_wrapper
      ->save();
  }

  // Set registrant_id if possible. Otherwise, store just the email.
  if ($registrant_wrapper) {
    $registration->registrant_id = $registrant_wrapper
      ->getIdentifier();
  }
  else {
    $registration->anon_mail = $registrant_mail;
  }

  // Notify field widgets.
  field_attach_submit('registration', $registration, $form, $form_state);

  // Save the registration and redirect.
  if (registration_save($registration)) {
    $reg_config = registration_entity_settings($registration->entity_type, $registration->entity_id);
    if (!empty($reg_config['settings']['confirmation']) && strlen($reg_config['settings']['confirmation'])) {
      drupal_set_message(t($reg_config['settings']['confirmation']));
    }
    $wrapper = entity_metadata_wrapper('registration', $registration);
    $host = $wrapper->entity
      ->value();

    // Set redirect to configured value, if there is one.
    if (!empty($reg_config['settings']['confirmation_redirect']) && strlen($reg_config['settings']['confirmation_redirect'])) {
      if (module_exists('token')) {
        $form_state['redirect'] = token_replace($reg_config['settings']['confirmation_redirect'], array(
          $host->type => $host,
          'registration' => $registration,
        ));
      }
      else {
        $form_state['redirect'] = $reg_config['settings']['confirmation_redirect'];
      }
    }
    else {

      // Redirect to registration:
      if (entity_access('view', 'registration', $registration)) {
        $uri = entity_uri('registration', $registration);
        $form_state['redirect'] = $uri['path'];
      }
      else {
        if (entity_access('view', $registration->entity_type, $host)) {
          $uri = entity_uri($registration->entity_type, $host);
          $form_state['redirect'] = $uri['path'];
        }
      }
    }

    // Make sure to Start a Session and save the registration info so we
    // can check it for anonymous user access.
    drupal_session_start();
    $_SESSION['registration_ids'][$registration
      ->identifier()] = $wrapper->anon_access_hash
      ->value();
  }
  else {
    drupal_set_message(t('There was a problem submitting your registration.'));
  }
}

/**
 * Button submit function: handle the 'Delete' button on the node form.
 */
function registration_form_delete_submit($form, &$form_state) {
  $destination = array();
  if (isset($_GET['destination'])) {
    $destination = drupal_get_destination();
    unset($_GET['destination']);
  }
  $registration = $form_state['registration'];
  $form_state['redirect'] = array(
    'registration/' . $registration->registration_id . '/delete',
    array(
      'query' => $destination,
    ),
  );
}

/**
 * Menu callback -- ask for confirmation of node deletion.
 */
function registration_delete_confirm($form, &$form_state, $registration) {

  // Always provide entity id in the same form key as in the entity edit form.
  $form['registration'] = array(
    '#type' => 'value',
    '#value' => $registration,
  );
  return confirm_form($form, t('Are you sure you want to delete registration %title?', array(
    '%title' => $registration->registration_id,
  )), 'registration/' . $registration->registration_id, t('This action cannot be undone.'), t('Delete'), t('Cancel'));
}

/**
 * Execute node deletion.
 */
function registration_delete_confirm_submit($form, &$form_state) {
  if ($form_state['values']['confirm']) {
    $registration = $form_state['values']['registration'];
    registration_delete_multiple(array(
      $registration->registration_id,
    ));
    watchdog('registration', 'Registration %id deleted.', array(
      '%id' => $registration->registration_id,
    ));
    drupal_set_message(t('Registration %id has been deleted.', array(
      '%id' => $registration->registration_id,
    )));
    $wrapper = entity_metadata_wrapper('registration', $registration);
    $host = $wrapper->entity
      ->value();
    $uri = entity_uri($registration->entity_type, $host);
    $form_state['redirect'] = $uri['path'];
  }
}

/**
 * Return a form for sending a broadcast email to participants.
 */
function registration_registrations_broadcast_form($form, &$form_state, $entity_type, $entity) {

  // We'll need this info when we submit the form.
  list($entity_id) = entity_extract_ids($entity_type, $entity);
  $form_state['entity'] = array(
    'entity_id' => $entity_id,
    'entity_type' => $entity_type,
  );
  $form['subject'] = array(
    '#type' => 'textfield',
    '#title' => t('Subject'),
    '#description' => t('The subject of the message.'),
    '#required' => TRUE,
    '#size' => 40,
    '#maxlength' => 40,
  );
  $form['message'] = array(
    '#type' => 'textarea',
    '#title' => t('Message'),
    '#description' => t('Enter the message you want to send to %name registrants. Tokens are supported if the module is enabled, E.g., [node:title].', array(
      '%name' => entity_label($entity_type, $entity),
    )),
    '#required' => TRUE,
    '#cols' => 60,
    '#rows' => 5,
  );

  // Message preview:
  if (isset($form_state['registration_broadcast_preview'])) {
    $form['preview'] = array(
      '#type' => 'textarea',
      '#title' => t('Message preview'),
      '#value' => $form_state['registration_broadcast_preview'],
      '#resizable' => FALSE,
      '#disabled' => TRUE,
    );
  }

  // Add token support:
  if (module_exists('token')) {
    $form['token_tree'] = array(
      '#theme' => 'token_tree_link',
      '#token_types' => array(
        $entity_type,
        'registration',
      ),
      '#global_types' => FALSE,
    );
  }
  $form['actions']['preview'] = array(
    '#type' => 'submit',
    '#value' => t('Preview'),
    '#weight' => 10,
    '#submit' => array(
      'registration_broadcast_preview',
    ),
  );
  $form['actions']['send'] = array(
    '#type' => 'submit',
    '#value' => t('Send'),
  );
  return $form;
}
function registration_broadcast_preview($form, &$form_state) {
  $entity_type = $form_state['entity']['entity_type'];
  $entity_id = $form_state['entity']['entity_id'];
  $message_template = $form_state['values']['message'];
  $entity = entity_load_single($entity_type, $entity_id);
  if (module_exists('token')) {
    $message = token_replace($message_template, array(
      $entity_type => $entity,
    ));
  }
  $form_state['registration_broadcast_preview'] = $message;
  $form_state['rebuild'] = TRUE;
}

/**
 * Submit handler for registration_registrations_broadcast_form.
 */
function registration_registrations_broadcast_form_submit($form, &$form_state) {
  registration_send_broadcast($form_state['entity']['entity_type'], $form_state['entity']['entity_id'], $form_state['values']['subject'], $form_state['values']['message']);
}

/**
 * Return a form for an entity's registration settings.
 *
 * @param array $form
 * @param array $form_state
 * @param object $entity_type
 * @param object $entity
 *
 * @return array $form
 *
 * @see hook_registration_entity_settings()
 */
function registration_entity_settings_form($form, &$form_state, $settings, $entity_type = NULL, $entity_id = NULL) {
  if ($entity_id) {

    // We'll need this info when we submit the form:
    $form_state['entity'] = array(
      'entity_id' => $entity_id,
      'entity_type' => $entity_type,
    );
  }

  // Check to see if date_popup is installed so we can provide a friendlier UI.
  $date_popup_installed = FALSE;
  if (module_exists('date_popup')) {
    $date_popup_installed = TRUE;
  }
  $form['status'] = array(
    '#type' => 'checkbox',
    '#title' => t('Enable'),
    '#description' => t('Check to enable registrations.'),
    '#default_value' => isset($settings['status']) ? $settings['status'] : -1,
  );
  $form['capacity'] = array(
    '#type' => 'textfield',
    '#title' => t('Capacity'),
    '#description' => t('The maximum number of registrants. Leave at 0 for no limit.'),
    '#size' => 5,
    '#maxlength' => 10,
    '#required' => TRUE,
    '#default_value' => isset($settings['capacity']) ? $settings['capacity'] : 0,
  );
  $form['scheduling'] = array(
    '#type' => 'fieldset',
    '#title' => t('Scheduling'),
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
    '#tree' => TRUE,
  );
  $form['scheduling']['open'] = array(
    '#type' => 'textfield',
    '#title' => t('Open Date'),
    '#maxlength' => 25,
    '#description' => t('When to automatically open registrations. Format: %time. The date format is YYYY-MM-DD and %timezone is the time zone offset from UTC. Leave blank to disable.', array(
      '%time' => !empty($settings['open']) ? date_format(date_create($settings['open']), 'Y-m-d H:i:s O') : format_date(time(), 'custom', 'Y-m-d H:i:s O'),
      '%timezone' => !empty($settings['open']) ? date_format(date_create($settings['open']), 'O') : format_date(time(), 'custom', 'O'),
    )),
    '#default_value' => !empty($settings['open']) ? $settings['open'] : '',
    '#weight' => 0,
  );
  if ($date_popup_installed) {
    $form['scheduling']['open']['#type'] = 'date_popup';
    $form['scheduling']['open']['#date_format'] = 'Y-m-d H:i:s O';
    $form['scheduling']['open']['#description'] = t('When to automatically open registrations. (This uses the !timezone.)', array(
      '!timezone' => l(t('site default time zone'), 'admin/config/regional/settings'),
    ));
    unset($form['scheduling']['open']['#maxlength']);
  }
  $form['scheduling']['close'] = array(
    '#type' => 'textfield',
    '#title' => t('Close Date'),
    '#maxlength' => 25,
    '#description' => t('When to automatically close registrations. Format: %time. The date format is YYYY-MM-DD and %timezone is the time zone offset from UTC. Leave blank to disable.', array(
      '%time' => !empty($settings['close']) ? date_format(date_create($settings['close']), 'Y-m-d H:i:s O') : format_date(time(), 'custom', 'Y-m-d H:i:s O'),
      '%timezone' => !empty($settings['close']) ? date_format(date_create($settings['close']), 'O') : format_date(time(), 'custom', 'O'),
    )),
    '#default_value' => !empty($settings['close']) ? $settings['close'] : '',
    '#weight' => 2,
  );
  if ($date_popup_installed) {
    $form['scheduling']['close']['#type'] = 'date_popup';
    $form['scheduling']['close']['#date_format'] = 'Y-m-d H:i:s O';
    $form['scheduling']['close']['#description'] = t('When to automatically close registrations.. (This uses the !timezone.)', array(
      '!timezone' => l(t('site default time zone'), 'admin/config/regional/settings'),
    ));
    unset($form['scheduling']['close']['#maxlength']);
  }

  // Allow for setting open and close date based on tokens:
  if (module_exists('token')) {
    $date_fields = array(
      array(
        'name' => 'open',
        'label' => 'Open Date',
        'set' => 'scheduling',
      ),
      array(
        'name' => 'close',
        'label' => 'Close Date',
        'set' => 'scheduling',
      ),
    );
    foreach ($date_fields as $field) {
      $input_root = $entity_id ? $field['set'] . '[' : 'instance[settings][default_registration_settings][' . $field['set'] . '][';
      $base_weight = isset($form[$field['set']][$field['name']]['#weight']) ? $form[$field['set']][$field['name']]['#weight'] : 0;
      $form[$field['set']][$field['name'] . '_use_token'] = array(
        '#type' => 'checkbox',
        '#title' => t('Use a token to set the @label.', array(
          '@label' => $field['label'],
        )),
        '#default_value' => !empty($settings[$field['name'] . '_date_token']) ? TRUE : FALSE,
        '#weight' => $base_weight - 0.5,
      );
      $form[$field['set']][$field['name'] . '_date_token'] = array(
        '#type' => 'textfield',
        '#title' => t('@label Source', array(
          '@label' => $field['label'],
        )),
        '#description' => $form[$field['set']][$field['name']]['#description'] . t(". <i>Choose a token that will return the time in 'Y-m-d H:i:s' format.</i>"),
        '#default_value' => isset($settings[$field['name'] . '_date_token']) ? $settings[$field['name'] . '_date_token'] : NULL,
        '#states' => array(
          'visible' => array(
            ':input[name="' . $input_root . $field['name'] . '_use_token]"]' => array(
              'checked' => TRUE,
            ),
          ),
        ),
        '#weight' => $base_weight,
      );
      $form[$field['set']][$field['name']]['#states'] = array(
        'visible' => array(
          ':input[name="' . $input_root . $field['name'] . '_use_token]"]' => array(
            'checked' => FALSE,
          ),
        ),
      );
      if ($entity_id) {

        // Only add this validation when on an actual entity: allows for setting
        // defaults on the field configuration page.
        $form[$field['set']][$field['name'] . '_date_token']['#element_validate'] = array(
          'token_element_validate',
        );
        $form[$field['set']][$field['name'] . '_date_token']['#token_types'] = array(
          $entity_type,
        );
      }
    }
    if ($entity_id) {

      // Add the UI for browsing tokens.
      $form['scheduling']['_tokens'] = array(
        '#theme' => 'token_tree_link',
        '#token_types' => array(
          $entity_type,
        ),
        '#global_types' => FALSE,
        '#click_insert' => TRUE,
        '#weight' => 3,
      );
    }
  }
  $form['reminder'] = array(
    '#type' => 'fieldset',
    '#title' => t('Reminder'),
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
    '#tree' => TRUE,
  );
  $form['reminder']['send_reminder'] = array(
    '#type' => 'checkbox',
    '#title' => t('Send Reminder'),
    '#description' => t('If checked, a reminder will be sent to registrants on the following date.'),
    '#default_value' => isset($settings['send_reminder']) ? $settings['send_reminder'] : -1,
  );
  $form['reminder']['reminder_settings'] = array(
    '#type' => 'fieldset',
    '#title' => t('Settings'),
    '#collapsible' => FALSE,
    '#states' => array(
      'visible' => array(
        ':input[name="send_reminder"]' => array(
          'checked' => TRUE,
        ),
      ),
    ),
  );
  $form['reminder']['reminder_settings']['reminder_date'] = array(
    '#type' => 'textfield',
    '#title' => t('Reminder Date'),
    '#maxlength' => 25,
    '#description' => t('When to send reminders. Format: %time. The date format is YYYY-MM-DD and %timezone is the time zone offset from UTC.', array(
      '%time' => !empty($settings['open']) ? date_format(date_create($settings['reminder_date']), 'Y-m-d H:i:s O') : format_date(time(), 'custom', 'Y-m-d H:i:s O'),
      '%timezone' => !empty($settings['open']) ? date_format(date_create($settings['reminder_date']), 'O') : format_date(time(), 'custom', 'O'),
    )),
    '#default_value' => !empty($settings['reminder_date']) ? $settings['reminder_date'] : '',
  );
  if ($date_popup_installed) {
    $form['reminder']['reminder_settings']['reminder_date']['#type'] = 'date_popup';
    $form['reminder']['reminder_settings']['reminder_date']['#date_format'] = 'Y-m-d H:i:s O';
    $form['reminder']['reminder_settings']['reminder_date']['#description'] = t('When to send reminders. (This uses the !timezone.)', array(
      '!timezone' => l(t('site default time zone'), 'admin/config/regional/settings'),
    ));
    unset($form['reminder']['reminder_settings']['reminder_date']['#maxlength']);
  }
  $form['reminder']['reminder_settings']['reminder_template'] = array(
    '#type' => 'textarea',
    '#title' => t('Template'),
    '#default_value' => isset($settings['reminder_template']) ? $settings['reminder_template'] : '',
    '#description' => t('The reminder message sent to registrants. Tokens are supported if the module is enabled, E.g., [node:title].'),
  );

  // Add token support:
  if (module_exists('token')) {
    $form['reminder']['reminder_settings']['token_tree'] = array(
      '#theme' => 'token_tree_link',
      '#token_types' => array(
        $entity_type,
        'registration',
      ),
      '#global_types' => FALSE,
    );
  }
  $form['settings'] = array(
    '#type' => 'fieldset',
    '#title' => t('Additional Settings'),
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
    '#tree' => TRUE,
  );
  $form['settings']['upsert_registrants'] = array(
    '#type' => 'checkbox',
    '#title' => t('Automatically create and update registrant entities'),
    '#description' => t('If selected, anonymous registrants will have a registrant entity automatically created and attached when the registration is saved. Additionally, if a module exposes registrant form fields on the registration form, those values will be set on the registrant entity.'),
    '#default_value' => isset($settings['settings']['upsert_registrants']) ? $settings['settings']['upsert_registrants'] : NULL,
  );
  $form['settings']['multiple_registrations'] = array(
    '#type' => 'checkbox',
    '#title' => t('Allow multiple registrations'),
    '#description' => t('If selected, each person can create multiple registrations for this event.'),
    '#default_value' => isset($settings['settings']['multiple_registrations']) ? $settings['settings']['multiple_registrations'] : -1,
  );
  $form['settings']['maximum_spaces'] = array(
    '#type' => 'textfield',
    '#title' => t('Spaces allowed'),
    '#size' => 5,
    '#maxlength' => 10,
    '#required' => TRUE,
    '#description' => t('The maximum number of spaces allowed for each registrations. For no limit, use 0. (Default is 1)'),
    '#default_value' => isset($settings['settings']['maximum_spaces']) ? $settings['settings']['maximum_spaces'] : 1,
  );
  $form['settings']['from_address'] = array(
    '#type' => 'textfield',
    '#title' => t('From Address'),
    '#description' => t('From email address to use for confirmations, reminders, and broadcast emails.'),
    '#required' => TRUE,
    '#default_value' => isset($settings['settings']['from_address']) ? $settings['settings']['from_address'] : variable_get('site_mail', ini_get('sendmail_from')),
  );
  $form['settings']['confirmation'] = array(
    '#type' => 'textfield',
    '#title' => t('Confirmation Message'),
    '#description' => t('The message to display when someone registers. Leave blank for none.'),
    '#size' => 60,
    '#maxlength' => 120,
    '#required' => FALSE,
    '#default_value' => isset($settings['settings']['confirmation']) ? $settings['settings']['confirmation'] : 'Registration has been saved.',
  );
  $form['settings']['confirmation_redirect'] = array(
    '#type' => 'textfield',
    '#title' => t('Confirmation redirect path'),
    '#description' => t('Optional path to redirect to when someone registers. Leave blank to redirect to the registration itself if the user has permission or the host entity if they do not.'),
    '#size' => 60,
    '#maxlength' => 120,
    '#required' => FALSE,
    '#default_value' => isset($settings['settings']['confirmation_redirect']) ? $settings['settings']['confirmation_redirect'] : '',
  );

  // Display the list of available placeholders if token module is installed.
  if (module_exists('token')) {
    $form['settings']['confirmation_redirect']['#description'] .= ' ' . t('Tokens may be used.');
    $form['settings']['token_help'] = array(
      '#type' => 'fieldset',
      '#title' => t('Available Tokens'),
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
      '#tree' => TRUE,
      'token_help_details' => array(
        '#theme' => 'token_tree',
        '#token_types' => array(
          $entity_type,
          'registration',
        ),
      ),
    );
  }

  // Allow other modules to add their own custom settings:
  $form['settings'] += module_invoke_all('registration_entity_settings', $settings);

  // Only show save if we're not on the field instance defaults:
  if ($entity_id) {
    $form['save'] = array(
      '#type' => 'submit',
      '#value' => t('Save Settings'),
    );
  }
  return $form;
}

/**
 * Submit handler for registration_entity_settings_form().
 *
 * @array $form
 * @array $form_state
 */
function registration_entity_settings_form_validate($form, &$form_state) {

  // Ensure capacity is a non-negative integer.
  $capacity = $form_state['values']['capacity'];
  if (!is_numeric($capacity) || (int) $capacity != $capacity || $capacity < 0) {
    form_set_error('capacity', t('"Capacity" must be a positive integer or 0 for unlimited.'));
  }

  // Ensure slot limit is a non-negative integer.
  $slot_limit = $form_state['values']['settings']['maximum_spaces'];
  if (!is_numeric($slot_limit) || (int) $slot_limit != $slot_limit || $slot_limit < 0) {
    form_set_error('maximum_spaces', t('"Spaces allowed" must be a positive integer or 0 for unlimited.'));
  }

  // Validate from address:
  if (!valid_email_address($form_state['values']['settings']['from_address'])) {
    form_set_error('settings][from_address', t('From email address is invalid.'));
  }

  // Validate open date:
  if (!empty($form_state['values']['scheduling']['open']) && is_string($form_state['values']['scheduling']['open']) && strtotime($form_state['values']['scheduling']['open']) === FALSE) {
    form_set_error('scheduling][open', t('Date is invalid.'));
  }

  // Validate close date:
  if (!empty($form_state['values']['scheduling']['close']) && is_string($form_state['values']['scheduling']['close']) && strtotime($form_state['values']['scheduling']['close']) === FALSE) {
    form_set_error('scheduling][close', t('Date is invalid.'));
  }

  // If sending a reminder, ensure date and template are set.
  $reminder = $form_state['values']['reminder'];
  if ($reminder['send_reminder'] && (empty($reminder['reminder_settings']['reminder_date']) || empty($reminder['reminder_settings']['reminder_template']))) {
    form_set_error('reminder][send_reminder', t('If sending a reminder, provide a date and template.'));
  }

  // If reminder date or template are set, ensure we're sending a reminder.
  if (empty($reminder['send_reminder'])) {
    if (!empty($reminder['reminder_settings']['reminder_template'])) {
      form_set_error('reminder][reminder_settings][reminder_template', t('You have provided a reminder template, but not opted to send a reminder. Either check the box to send a reminder, or do not provide a reminder template.'));
    }
    if (!empty($reminder['reminder_settings']['reminder_date'])) {
      form_set_error('reminder][reminder_settings][reminder_date', t('You have provided a reminder date, but not opted to send a reminder. Either check the box to send a reminder, or do not provide a reminder date.'));
    }
  }

  // Validate reminder date:
  if (!empty($reminder['reminder_settings']['reminder_date']) && strtotime($reminder['reminder_settings']['reminder_date']) === FALSE) {
    form_set_error('reminder][reminder_settings][reminder_date', t('Reminder date is invalid.'));
  }

  // Ensure reminder date is not in the past when "send_reminder" is TRUE:
  if ($reminder['send_reminder'] && !empty($reminder['reminder_settings']['reminder_date'])) {
    if (strtotime($reminder['reminder_settings']['reminder_date']) <= time()) {
      form_set_error('reminder][reminder_settings][reminder_date', t('Reminder must be in the future.'));
    }
  }
}

/**
 * Submit handler for registration_entity_settings_form().
 *
 * @array $form
 * @array $form_state
 */
function registration_entity_settings_form_submit($form, &$form_state) {
  $entity = $form_state['entity'];
  $fields = registration_convert_form_settings($form_state['values']);
  registration_update_entity_settings($entity['entity_type'], $entity['entity_id'], $fields);
  $uri = entity_uri($entity['entity_type'], entity_load_single($entity['entity_type'], $entity['entity_id']));
  $form_state['redirect'] = $uri['path'];
}

/**
 * Helper to convert registration entity settings form values into fields.
 *
 * @param $values
 *
 * @return array
 */
function registration_convert_form_settings($values) {
  $fields = array(
    'status' => $values['status'],
    'capacity' => $values['capacity'],
    'send_reminder' => isset($values['reminder']['send_reminder']) ? $values['reminder']['send_reminder'] : 0,
    'reminder_date' => NULL,
    'reminder_template' => isset($values['reminder']['reminder_settings']['reminder_template']) ? $values['reminder']['reminder_settings']['reminder_template'] : NULL,
    'settings' => $values['settings'],
    'open' => NULL,
    'close' => NULL,
  );
  if (module_exists('token')) {
    $open_token = isset($values['scheduling']['open_date_token']) ? $values['scheduling']['open_date_token'] : '';
    $close_token = isset($values['scheduling']['close_date_token']) ? $values['scheduling']['close_date_token'] : '';
    $fields['open_date_token'] = $open_token;
    $fields['close_date_token'] = $close_token;
  }
  $date_fields = array(
    array(
      'name' => 'open',
      'label' => 'Open Date',
      'set' => 'scheduling',
    ),
    array(
      'name' => 'close',
      'label' => 'Close Date',
      'set' => 'scheduling',
    ),
  );
  foreach ($date_fields as $field) {
    if (!empty($values[$field['set']][$field['name']])) {
      $fields[$field['name']] = date('Y-m-d H:i:s', strtotime($values[$field['set']][$field['name']]));
    }
  }

  // Reminder: Reminder Date:
  if (!empty($values['reminder']['reminder_settings']['reminder_date'])) {
    $fields['reminder_date'] = date('Y-m-d H:i:s', strtotime($values['reminder']['reminder_settings']['reminder_date']));
  }
  $fields['settings'] = serialize($fields['settings']);
  return $fields;
}

/**
 * Generates the Registration state editing form.
 */
function registration_state_form($form, &$form_state, $registration_state, $op = 'edit') {
  $form['label'] = array(
    '#title' => t('Label'),
    '#type' => 'textfield',
    '#default_value' => $registration_state->label,
    '#description' => t('The human-readable name of this registration state.'),
    '#required' => TRUE,
    '#size' => 30,
  );

  // Machine-readable type name.
  $form['name'] = array(
    '#type' => 'machine_name',
    '#default_value' => $registration_state
      ->identifier(),
    '#maxlength' => 32,
    //'#disabled' => $registration_state->locked && $op != 'clone',
    '#machine_name' => array(
      'exists' => 'registration_get_states',
      'source' => array(
        'label',
      ),
    ),
    '#description' => t('A unique machine-readable name for
    this registration state. It must only contain lowercase letters,
     numbers, and underscores.'),
  );
  $form['default_state'] = array(
    '#title' => t('Default'),
    '#type' => 'checkbox',
    '#default_value' => isset($registration_state->default_state) ? $registration_state->default_state : 0,
    '#attributes' => array(
      'class' => array(
        'reg-default',
      ),
    ),
  );
  $form['weight'] = array(
    '#title' => t('Weight'),
    '#type' => 'weight',
    '#default_value' => isset($registration_state->weight) ? $registration_state->weight : 0,
    '#delta' => 15,
    '#attributes' => array(
      'class' => array(
        'registration-state-weight',
      ),
    ),
  );
  $form['description'] = array(
    '#title' => t('Description'),
    '#type' => 'textfield',
    '#default_value' => isset($registration_state->description) ? $registration_state->description : '',
    '#maxlength' => 128,
    '#size' => 50,
  );
  $form['active'] = array(
    '#title' => t('Active'),
    '#type' => 'checkbox',
    '#default_value' => isset($registration_state->active) ? $registration_state->active : 0,
  );
  $form['held'] = array(
    '#title' => t('Held'),
    '#type' => 'checkbox',
    '#default_value' => isset($registration_state->held) ? $registration_state->held : 0,
  );
  $form['show_on_form'] = array(
    '#title' => t('Show on form'),
    '#type' => 'checkbox',
    '#default_value' => isset($registration_state->show_on_form) ? $registration_state->show_on_form : 0,
  );
  $form['actions'] = array(
    '#type' => 'actions',
  );
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save Registration state'),
    '#weight' => 40,
  );
  return $form;
}

/**
 * Form API submit callback for the type form.
 */
function registration_state_form_submit(&$form, &$form_state) {
  $registration_state = entity_ui_form_submit_build_entity($form, $form_state);
  $registration_state
    ->save();
  $form_state['redirect'] = 'admin/structure/registration/registration_states';
}

/**
 * Registration states setting form.
 */
function registration_state_overview_form($form, &$form_state) {
  $registration_states = registration_states();

  // Form elements for existing states .
  $form['state']['#tree'] = TRUE;
  if (!empty($registration_states)) {
    foreach ($registration_states as $sid => $state) {
      $form['state'][$sid]['sid'] = array(
        '#type' => 'hidden',
        '#default_value' => $sid,
      );
      $form['state'][$sid]['label'] = array(
        '#title' => t('Label'),
        '#type' => 'textfield',
        '#default_value' => $state->label,
        '#maxlength' => 128,
        '#size' => 20,
        '#required' => TRUE,
      );
      $form['state'][$sid]['default_state'] = array(
        '#type' => 'radio',
        '#name' => 'default_state',
        '#return_value' => $sid,
        '#tree' => FALSE,
        '#default_value' => $state->default_state ? $sid : FALSE,
      );
      $form['state'][$sid]['attended'] = array(
        '#type' => 'radio',
        '#name' => 'attended',
        '#return_value' => $sid,
        '#tree' => FALSE,
        '#default_value' => $state->attended ? $sid : FALSE,
      );
      $form['state'][$sid]['weight'] = array(
        '#title' => t('Weight'),
        '#type' => 'weight',
        '#default_value' => $state->weight,
        '#delta' => 15,
        '#attributes' => array(
          'class' => array(
            'registration-state-weight',
          ),
        ),
      );
      $form['state'][$sid]['description'] = array(
        '#title' => t('Description'),
        '#type' => 'textfield',
        '#default_value' => $state->description,
        '#maxlength' => 128,
        '#size' => 50,
      );
      $form['state'][$sid]['active'] = array(
        '#title' => t('Active'),
        '#type' => 'checkbox',
        '#default_value' => $state->active,
      );
      $form['state'][$sid]['held'] = array(
        '#title' => t('Held'),
        '#type' => 'checkbox',
        '#default_value' => $state->held,
      );
      $form['state'][$sid]['show_on_form'] = array(
        '#title' => t('Show on form'),
        '#type' => 'checkbox',
        '#default_value' => $state->show_on_form,
      );
      $form['state'][$sid]['delete'] = array(
        '#type' => 'item',
        '#markup' => l(t('delete'), 'admin/structure/registration/registration_states/manage/' . $state
          ->identifier() . '/delete', array(
          'query' => drupal_get_destination(),
        )),
      );
      $form['state'][$sid]['export'] = array(
        '#type' => 'item',
        '#markup' => l(t('export'), 'admin/structure/registration/registration_states/manage/' . $state
          ->identifier() . '/export'),
      );
    }
  }
  $form['help'] = array(
    '#type' => 'item',
    '#description' => t("This table defines the registration states available on this site. A default is required and will be used if no states are marked as 'Show on Form'."),
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save configuration'),
  );
  return $form;
}

/**
 * Validation handler for the registration states form.
 */
function registration_state_overview_form_validate($form, &$form_state) {

  // Ensure each state is only "active" or "pending" – not both.
  foreach ($form_state['input']['state'] as $state) {
    if ($state['active'] && $state['held']) {
      form_set_error('state', 'A state can only be "active" or "held" – not both. Update the "' . $state['label'] . '" state to resolve this warning.');
    }
  }
}

/**
 * Submit handler for the registration states form.
 */
function registration_state_overview_form_submit($form, &$form_state) {
  $default_state = $form_state['values']['default_state'];
  foreach ($form_state['input']['state'] as $state) {
    $registration_state = entity_load_single('registration_state', $state['sid']);
    $registration_state->label = $state['label'];
    $registration_state->default_state = $state['sid'] == $default_state;
    $registration_state->active = isset($state['active']) ? $state['active'] : 0;
    $registration_state->held = isset($state['held']) ? $state['held'] : 0;
    $registration_state->show_on_form = isset($state['show_on_form']) ? $state['show_on_form'] : 0;
    $registration_state->weight = $state['weight'];
    $registration_state->description = $state['description'];
    $registration_state
      ->save();
  }
  drupal_set_message(t('Your registration states have been saved.'));
}

/**
 * Theme handler for registration states form.
 */
function theme_registration_state_overview_form($variables) {
  $form = $variables['form'];
  drupal_add_tabledrag('registration-state-admin-settings-table', 'order', 'self', 'registration-state-weight');
  $header = array(
    array(
      'data' => t('Label !required', array(
        '!required' => '<span class="form-required" title="' . t('This field is required.') . '">*</span>',
      )),
    ),
    array(
      'data' => t('Description'),
    ),
    array(
      'data' => t('Default'),
    ),
    array(
      'data' => t('Attended'),
    ),
    array(
      'data' => t('Active'),
    ),
    array(
      'data' => t('Held'),
    ),
    array(
      'data' => t('Show on form'),
    ),
    array(
      'data' => t('Weight'),
    ),
    array(
      'data' => t('Operations'),
      'colspan' => 2,
    ),
  );
  foreach (element_children($form['state']) as $key) {
    $row = array();
    foreach (array(
      'label',
      'description',
      'default_state',
      'attended',
      'active',
      'held',
      'show_on_form',
      'weight',
      'delete',
      'export',
    ) as $element) {

      // Since we're rendering these in a table, remove any #title attributes.
      if (!empty($form['state'][$key][$element]['#title'])) {
        unset($form['state'][$key][$element]['#title']);
      }
      $row[] = drupal_render($form['state'][$key][$element]);
    }
    $rows[] = array(
      'class' => array(
        'draggable',
      ),
      'data' => $row,
    );
  }
  $output = theme('table', array(
    'header' => $header,
    'rows' => $rows,
    'attributes' => array(
      'id' => 'registration-state-admin-settings-table',
    ),
  ));
  $output .= drupal_render_children($form);
  return $output;
}

/**
 * Validation helper function to confirm the spaces requested are within limits.
 */
function _registration_validate_space_request($element, &$form_state, $form) {
  if (isset($form_state['input']['count']) && $form['#registration_settings']['settings']['maximum_spaces'] && $form_state['input']['count'] > $form['#registration_settings']['settings']['maximum_spaces']) {
    form_error($element, t('You may not register for more than @count spaces.', array(
      '@count' => $form['#registration_settings']['settings']['maximum_spaces'],
    )));
  }
}

Functions

Namesort descending Description
registration_broadcast_preview
registration_convert_form_settings Helper to convert registration entity settings form values into fields.
registration_delete_confirm Menu callback -- ask for confirmation of node deletion.
registration_delete_confirm_submit Execute node deletion.
registration_entity_settings_form Return a form for an entity's registration settings.
registration_entity_settings_form_submit Submit handler for registration_entity_settings_form().
registration_entity_settings_form_validate Submit handler for registration_entity_settings_form().
registration_form Form callback: create or edit a registration.
registration_form_delete_submit Button submit function: handle the 'Delete' button on the node form.
registration_form_submit Submit callback for registration_form().
registration_form_validate Validation callback for registration_form().
registration_registrations_broadcast_form Return a form for sending a broadcast email to participants.
registration_registrations_broadcast_form_submit Submit handler for registration_registrations_broadcast_form.
registration_state_form Generates the Registration state editing form.
registration_state_form_submit Form API submit callback for the type form.
registration_state_overview_form Registration states setting form.
registration_state_overview_form_submit Submit handler for the registration states form.
registration_state_overview_form_validate Validation handler for the registration states form.
theme_registration_state_overview_form Theme handler for registration states form.
_registration_validate_space_request Validation helper function to confirm the spaces requested are within limits.