diff --git a/booking.constants.inc b/booking.constants.inc index c42963b..5f38872 100644 --- a/booking.constants.inc +++ b/booking.constants.inc @@ -135,6 +135,38 @@ function _booking_room_bedtype_lookup($input = NULL) return $bed; } +/** + * Helper function to look up reading group colour based on group id + * @param $input integer containing group id + * @return string for corresponding reading group colour + */ +function _booking_readinggroup_colour_lookup($input = NULL) +{ + $group = array(); + $group[] = ''; + $group[] = t('Silver/Grey'); + $group[] = t('Stripes'); + $group[] = t('Spots'); + $group[] = t('Beige'); + $group[] = t('Maroon'); + $group[] = t('Pink'); + $group[] = t('Black'); + $group[] = t('Yellow'); + $group[] = t('Purple'); + $group[] = t('White'); + $group[] = t('Red'); + $group[] = t('Orange'); + $group[] = t('Checks'); + $group[] = t('Green'); + $group[] = t('Blue'); + $group[] = t('Brown'); + + if ($input != NULL) + return $group[$input]; + else + return $group; +} + /** * Helper function to reliably (without using any external APIs) provide a list of options for the country field used in the registration form */ diff --git a/booking.emails.inc b/booking.emails.inc index 80f889c..04f1e1a 100644 --- a/booking.emails.inc +++ b/booking.emails.inc @@ -396,7 +396,8 @@ function _booking_travelform_confirmation_email($nid) //calculate the remaining parameters $to = $node->booking_email; - $subject = t('!event Travel Details Received', array('!event' => $event->booking_eventname)); + $subject = token_replace(variable_get('booking_email_travel_complete_subject', t('!event', array('!event' => $event->booking_eventname))), $tokens); + //$subject = t('!event Travel Details Received', array('!event' => $event->booking_eventname)); $params['subject'] = $subject; $params['headers']['Bcc'] = "it@coadcorp.com, " . variable_get('booking_logistics_email', variable_get('site_mail', ini_get('sendmail_from'))); diff --git a/booking.module b/booking.module index dc94a47..ec49adc 100644 --- a/booking.module +++ b/booking.module @@ -381,6 +381,15 @@ function booking_menu() { 'access arguments' => array('edit study groups'), 'type' => MENU_LOCAL_ACTION, ); + + $items['admin/booking/studygroups/update'] = array( + 'title' => 'Update Study Groups', + 'description' => 'Calculate updated Study Group memberships', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('booking_studygroups_update'), + 'access arguments' => array('edit study groups'), + 'type' => MENU_LOCAL_ACTION, + ); } //configure rooms diff --git a/booking.register.inc b/booking.register.inc index e87534b..5c0cf51 100644 --- a/booking.register.inc +++ b/booking.register.inc @@ -1715,6 +1715,10 @@ function booking_view($node, $view_mode) { //add the travel info if it has been defined for this attendee if (! empty($node->tid)) { + $travel_heading = t("
!link
", + array('!link' => l(t('Edit Travel Details'), t('node/!id/edit', array('!id' => $node->tid))) + )); + $travel_rows[] = array(t('Transport Type:'), $node->booking_transport_type); $travel_rows[] = array(t('Catching the train to Study Week:'), $node->booking_transport_from_morriset_reqd == 1 ? 'Yes' : 'No'); $travel_rows[] = array(t('Inbound Flight Number:'), $node->booking_flightnum_inbound == '' ? 'N/A' : $node->booking_flightnum_inbound); @@ -1727,7 +1731,7 @@ function booking_view($node, $view_mode) { $travel_rows[] = array(t('Accommodation after Study Week Required:'), $node->booking_accom_after_reqd == 1 ? 'Yes' : 'No'); $node->content['travel-heading'] = array( - '#markup' => "Study group mappings to remove:\n@info", array('@info' => print_r( $to_remove, true))); - + //iterate over the attendee associative array and add some fields foreach ($attendees as $person) { @@ -721,6 +712,8 @@ function booking_studygroups_calculate() { { //if ($person->booking_studygroup_id == $group->sid && ($person->booking_is_leader == 'Y' || $person->booking_is_helper == 'Y' || // $person->booking_is_reserveleader == 'Y')) + + //if the study group id matches the group we're currently looking at, and they have a role defined if ($person->booking_studygroup_id == $group->sid && $person->booking_studygroup_role > 0) { drupal_set_message(t('Leader/helper with id !id assigned to session !session (currently with !num people).', @@ -749,15 +742,16 @@ function booking_studygroups_calculate() { elseif ($bf_gf_id > 0) { drupal_set_message(t('BF/GF with id !id assigned to session !session (currently with !num people).', - array('!id' => $spouse_id, '!session' => $person->booking_session_id, + array('!id' => $bf_gf_id, '!session' => $person->booking_session_id, '!num' => $session_count[$person->booking_session_id]['total']) )); //allocate the boyfriend/girlfriend to the same session - _booking_assign_attendee_group($bf_gf_id, $person->booking_session_id, $working_list[$bf_gf_id]->booking_gender == 'M' ? 'male' : 'female', - _booking_get_age_years($working_list[$bf_gf_id]->booking_dob), $working_list, $session_count); + $age = _booking_get_age_years($working_list[$bf_gf_id]->booking_dob); + $gender = $working_list[$bf_gf_id]->booking_gender == 'M' ? 'male' : 'female'; + _booking_assign_attendee_group($bf_gf_id, $person->booking_session_id, $gender, $age, $working_list, $session_count); } - } - } //end searching for leaders and helpers + } //end current group check + } //end searching for leaders and helpers //watchdog('booking', "Attendee list working copy after leader/helper spouse processing: @info", array('@info' => var_export($working_list, TRUE))); //watchdog('booking', "Attendee list session count after leader/helper spouse processing: @info", array('@info' => var_export($session_count, TRUE))); @@ -767,21 +761,17 @@ function booking_studygroups_calculate() { //watchdog('booking', "Attendee list: @info", array('@info' => var_export($attendees, TRUE))); //watchdog('booking', "Attendee list working copy: @info", array('@info' => var_export($working_list, TRUE))); + //watchdog('booking', "Attendee list distribution: @info", array('@info' => var_export($session_count, TRUE))); + //initialise our counters $session_id = 1; $rewound = FALSE; - - //watchdog('booking', "Attendee list: @info", array('@info' => var_export($session_count, TRUE))); - - //reset the iterator to starting position of the attendee list - //$it->rewind(); - - //set our counter $i = 1; //iterate over the attendee list while ( $it->valid() ) { + /* //go to the first unprocessed attendee while ($it->current()->processed == 1) { @@ -794,35 +784,37 @@ function booking_studygroups_calculate() { break; } } - + */ //cycle the session counter if we already reached the end if ($i > $group->booking_num_group_sessions) $i = 1; - //get the current attendee element and their stats + //get the current attendee element $current = $it->current(); - $gender = $current->booking_gender == 'M' ? 'male' : 'female'; - $age = _booking_get_age_years($current->booking_dob); - - if ($age < 20) - $age_type = 'under20'; - elseif($age >= 20 && $age < 25) - $age_type = '20to25'; - else - $age_type = 'over25'; - - //make sure this person is going to fit in with our calculated gender ratios - _booking_loop_carefully($session_count, $gender, $i, $maximums[$gender], $group->booking_num_group_sessions, 3); - - //make sure this person is going to fit in with our calculated age ratios - _booking_loop_carefully($session_count, $age_type, $i, $maximums[$age_type], $group->booking_num_group_sessions, 3); - - //check for maximum group size - _booking_loop_carefully($session_count, 'total', $i, $max_people, $group->booking_num_group_sessions, 3); //assign this attendee to this session if unprocessed so far if ($current->processed == 0) - { + { + //generate stats about this attendee + $gender = $current->booking_gender == 'M' ? 'male' : 'female'; + $age = _booking_get_age_years($current->booking_dob); + + if ($age < 20) + $age_type = 'under20'; + elseif($age >= 20 && $age < 25) + $age_type = '20to25'; + else + $age_type = 'over25'; + + //make sure this person is going to fit in with our calculated gender ratios + _booking_loop_carefully($session_count, $gender, $i, $maximums[$gender], $group->booking_num_group_sessions, 3); + + //make sure this person is going to fit in with our calculated age ratios + _booking_loop_carefully($session_count, $age_type, $i, $maximums[$age_type], $group->booking_num_group_sessions, 3); + + //check for maximum group size + _booking_loop_carefully($session_count, 'total', $i, $max_people, $group->booking_num_group_sessions, 3); + drupal_set_message(t('Assigning person with id !id with gender !gender and age group !age to session !session (currently with !num people).', array('!id' => $it->key(), '!session' => $i, '!num' => $session_count[$i]['total'], '!gender' => $gender, '!age' => $age_type ) )); @@ -853,8 +845,7 @@ function booking_studygroups_calculate() { _booking_assign_attendee_group($bf_gf_id, $i, $working_list[$bf_gf_id]->booking_gender == 'M' ? 'male' : 'female', _booking_get_age_years($working_list[$bf_gf_id]->booking_dob), $working_list, $session_count); } - } - + } //end processed check //move to the next unprocessed attendee in the list while ($it->valid() && $it->current()->processed == 1) @@ -945,6 +936,346 @@ function booking_studygroups_calculate() { } +/** + * Function for calculating who belongs to which study group + */ +function booking_studygroups_update() { + global $event; + + //master attendee list + $attendees = array(); + //temporary working copy of attendee list + $working_list = array(); + //create an array to keep track of the number of people in each session for each group + $session_count = array(); + + //select all the study groups for this event id + $studygroups_query = db_query("SELECT * FROM {booking_studygroup_list} WHERE booking_eventid = :eid", array(':eid' => $event->eid)); + $studygroups = $studygroups_query->fetchAllAssoc('sid'); + + //calculate the max number of attendees in a group + $firstgroup = reset($studygroups); + $limit = variable_get('booking_regn_limit','500'); + //be a bit more lenient with maximums to avoid excessive re-arrangement of groups + $fudge_factor = 3; + $max_people = (int) ($limit / $firstgroup->booking_num_group_sessions) + $fudge_factor; + + //select all the attendees booked in + $query = db_query("SELECT * FROM {booking_person} WHERE booking_event_id = :eid", + array(':eid' => $event->eid)); + $attendees = $query->fetchAllAssoc('nid'); + + //calculate the ratios of males to females, and various age groups + $statistics = _booking_generate_statistics($attendees); + $gender_ratio = ($statistics['males'] / $statistics['females']) * ($max_people / 2); + //store them in a nice easy to access array + $maximums = array( + 'male' => ceil($gender_ratio), + 'female' => ceil($max_people - $gender_ratio), + 'under20' => ceil(($statistics['under20'] / $limit) * ($max_people - $fudge_factor)), + '20to25' => ceil(($statistics['20to25'] / $limit) * ($max_people - $fudge_factor)), + 'over25' => ceil(($statistics['over25'] / $limit) * ($max_people - $fudge_factor)), + ); + + drupal_set_message(t('Aiming for !males males, !females females in group. Made up of !20s under 20, !low20s between 20 and 25, and !high20s over 25. Total count in group is !max.', + array('!20s' => $maximums['under20'], '!low20s' => $maximums['20to25'], '!high20s' => $maximums['over25'], + '!males' => $maximums['male'], '!females' => $maximums['female'], '!max' => $max_people) + )); + + //select any entries already in the mapping table + $group_mapping_query = db_query("SELECT * FROM {booking_studygroup_mapping} WHERE booking_eventid = :eid", array(':eid' => $event->eid)); + $group_mapping = $group_mapping_query->fetchAllAssoc('sid'); + + //TODO: Move this to a helper function + //search for entries already in the mapping table that have a booking_status of 3 (not coming) + $to_remove_query = db_query("SELECT m.* FROM {booking_studygroup_mapping} m + inner join {booking_person} p on p.nid = m.booking_node_id + WHERE booking_eventid = :eid AND p.booking_status = 3", + array(':eid' => $event->eid)); + $to_remove = $to_remove_query->fetchAll(); + + //watchdog('booking', "
Study group mappings to remove:\n@info", array('@info' => print_r( $to_remove, true))); + + //remove the mappings for these people no longer coming + foreach ($to_remove as $person) + { + $num_deleted = db_delete('booking_studygroup_mapping') + ->condition('booking_eventid', $event->eid) + ->condition('booking_node_id', $person->booking_node_id) + ->condition('booking_studygroup_id', $person->booking_studygroup_id) + ->execute(); + watchdog('booking', 'Removed person !nid from study group !sid, affected !num rows.', + array ('!nid' => $person->booking_node_id, '!sid' => $person->booking_studygroup_id, '!num' => $num_deleted)); + } + + //iterate over the attendee associative array and add some fields + foreach ($attendees as $person) + { + //flag that indicates processed or not + $person->processed = 0; + + //make sure we skip attendees that do not have the status of "booked in" + if ($person->booking_status <> 1) + $person->processed = 1; + + //field that indicates the session id the person is assigned to + $person->session = 0; + $person->booking_studygroup_role = 0; + } + + //watchdog('booking', "
Attendee list:\n@info", array('@info' => print_r( $attendees, true))); + //watchdog('booking', "Attendee list: @info", array('@info' => var_export($attendees, TRUE))); + + //process each study group (eg Monday Tuesday Wednesday etc) + foreach ($studygroups as $group) + { + drupal_set_message(t('Processing study group !group with !sessions sessions.', + array('!group' => $group->booking_studygroup_descrip, '!sessions' => $group->booking_num_group_sessions))); + + //create a temporary copy of the attendee list to work with for this study group + $working_list = array(); + $working_list = _booking_shuffle_assoc(_booking_clone_array($attendees)); + //set up the iterator + $obj = new ArrayObject( $working_list ); + $it = $obj->getIterator(); + + //clear the array keeping track of the number of people in each session for this group + for ($i = 1; $i <= $group->booking_num_group_sessions; $i++) + { + $session_count[$i] = array( + 'total' => 0, + 'male' => 0, + 'female' => 0, + 'under20' => 0, + '20to25' => 0, + 'over25' => 0, + ); + } + + //search for the leaders helpers, spouses and boyfriend/girlfriend for this study group to pre-allocate + foreach ($group_mapping as $person) + { + //get any potential spouse or boyfriend/girlfriend + $spouse_id = $working_list[$person->booking_node_id]->booking_partner_id; + $bf_gf_id = $working_list[$person->booking_node_id]->booking_bf_gf_nid; + $gender = $working_list[$person->booking_node_id]->booking_gender == 'M' ? 'male' : 'female'; + + //if the study group id matches the group we're currently looking at, and they have a role defined + if ($person->booking_studygroup_id == $group->sid && $person->booking_studygroup_role > 0) + { + drupal_set_message(t('Leader/helper with id !id assigned to session !session (currently with !num people).', + array('!id' => $person->booking_node_id, '!session' => $person->booking_session_id, + '!num' => $session_count[$person->booking_session_id]['total']) + )); + + //mark this position as being used + $age = _booking_get_age_years($working_list[$person->booking_node_id]->booking_dob); + _booking_assign_attendee_group($person->booking_node_id, $person->booking_session_id, 'male', $age, $working_list, $session_count); + } + //anyone else already assigned to this group previously + elseif ($person->booking_studygroup_id == $group->sid && $working_list[$person->booking_node_id]->processed == 0) + { + if ($spouse_id > 0) + { + //mark this person as allocated to this group + drupal_set_message(t('Married person with id !id assigned to session !session (currently with !num people).', + array('!id' => $person->booking_node_id, '!session' => $person->booking_session_id, + '!num' => $session_count[$person->booking_session_id]['total']) + )); + $age = _booking_get_age_years($working_list[$person->booking_node_id]->booking_dob); + _booking_assign_attendee_group($person->booking_node_id, $person->booking_session_id, $gender, $age, $working_list, $session_count); + + //also mark their spouse as allocated to this group + drupal_set_message(t('Spouse with id !id assigned to session !session (currently with !num people).', + array('!id' => $spouse_id, '!session' => $person->booking_session_id, + '!num' => $session_count[$person->booking_session_id]['total']) + )); + $age = _booking_get_age_years($working_list[$spouse_id]->booking_dob); + $spouse_gender = $working_list[$spouse_id]->booking_gender == 'M' ? 'male' : 'female'; + _booking_assign_attendee_group($spouse_id, $person->booking_session_id, $spouse_gender, $age, $working_list, $session_count); + } + elseif ($bf_gf_id > 0) + { + //mark this person as allocated to this group + drupal_set_message(t('Person with id !id in relationship assigned to session !session (currently with !num people).', + array('!id' => $person->booking_node_id, '!session' => $person->booking_session_id, + '!num' => $session_count[$person->booking_session_id]['total']) + )); + $age = _booking_get_age_years($working_list[$person->booking_node_id]->booking_dob); + _booking_assign_attendee_group($person->booking_node_id, $person->booking_session_id, $gender, $age, $working_list, $session_count); + + //also mark their boyfriend/girlfriend as allocated to this group + drupal_set_message(t('BF/GF with id !id assigned to session !session (currently with !num people).', + array('!id' => $bf_gf_id, '!session' => $person->booking_session_id, + '!num' => $session_count[$person->booking_session_id]['total']) + )); + $age = _booking_get_age_years($working_list[$bf_gf_id]->booking_dob); + $bfgf_gender = $working_list[$bf_gf_id]->booking_gender == 'M' ? 'male' : 'female'; + _booking_assign_attendee_group($bf_gf_id, $person->booking_session_id, $bfgf_gender, $age, $working_list, $session_count); + } + //for anyone else, just record what session they're currently in + else + { + $working_list[$person->booking_node_id]->session = $person->booking_session_id; + } + } //end looking at people with spouse or bf/gf + } //end searching for people to pre-allocate + + //watchdog('booking', "
Attendee list working copy after pre-processing:\n@info", array('@info' => print_r( $working_list, true))); + //watchdog('booking', "Attendee list working copy after leader/helper spouse processing: @info", array('@info' => var_export($working_list, TRUE))); + //watchdog('booking', "Attendee list session count after leader/helper spouse processing: @info", array('@info' => var_export($session_count, TRUE))); + + //reset the iterator to starting position + $it->rewind(); + + //watchdog('booking', "Attendee list: @info", array('@info' => var_export($attendees, TRUE))); + //watchdog('booking', "Attendee list working copy: @info", array('@info' => var_export($working_list, TRUE))); + //watchdog('booking', "Attendee list distribution: @info", array('@info' => var_export($session_count, TRUE))); + + //initialise our counters + $session_id = 1; + $rewound = FALSE; + $i = 1; + + //iterate over the attendee list + while ( $it->valid() ) + { + //cycle the session counter if we already reached the end + if ($i > $group->booking_num_group_sessions) + $i = 1; + + //get the current attendee element + $current = $it->current(); + + //assign this attendee to this session if unprocessed so far + if ($current->processed == 0) + { + //use their existing study group as a starting point, if already defined + if ($current->session > 0) + $start = $current->session; + else + $start = $i; + + //generate stats about this attendee + $gender = $current->booking_gender == 'M' ? 'male' : 'female'; + $age = _booking_get_age_years($current->booking_dob); + + if ($age < 20) + $age_type = 'under20'; + elseif($age >= 20 && $age < 25) + $age_type = '20to25'; + else + $age_type = 'over25'; + + //make sure this person is going to fit in with our calculated gender ratios + _booking_loop_carefully($session_count, $gender, $start, $maximums[$gender], $group->booking_num_group_sessions, 3); + + //make sure this person is going to fit in with our calculated age ratios + _booking_loop_carefully($session_count, $age_type, $start, $maximums[$age_type], $group->booking_num_group_sessions, 3); + + //check for maximum group size + _booking_loop_carefully($session_count, 'total', $start, $max_people, $group->booking_num_group_sessions, 4); + + drupal_set_message(t('Assigning person with id !id with gender !gender and age group !age to session !session (currently with !num people).', + array('!id' => $it->key(), '!session' => $start, '!num' => $session_count[$start]['total'], '!gender' => $gender, '!age' => $age_type ) + )); + + _booking_assign_attendee_group($it->key(), $start, $gender, $age, $working_list, $session_count); + + } //end processed check + + //move to the next unprocessed attendee in the list + while ($it->valid() && $it->current()->processed == 1) + { + //drupal_set_message(t("Skipping attendee ID !id, already processed.", array('!id' => $it->key()))); + $it->next(); + } + + //move to the next session + $i++; + } //finished looping through attendees for this study group + + + //iterate over the attendee list and write to the database the session they're assigned to + //use the multi-insert query type at https://drupal.org/node/310079 + $insert_query = db_insert('booking_studygroup_mapping')->fields(array('booking_eventid', 'booking_node_id', + 'booking_studygroup_id', 'booking_session_id', 'booking_is_leader', 'booking_is_helper', + 'booking_is_reserveleader', 'booking_studygroup_role')); + + foreach($working_list as $person) + { + //watchdog('booking', "
Working list person:\n@info", array('@info' => print_r( $person, true))); + + //check to update existing records rather than inserting new one + // if already in $group_mapping then just run an update query here + + $found = FALSE; + foreach ($group_mapping as $mapping) + { + //check if we can find a study group session already for this user and this study group (eg Monday Tuesday or Wednesday) + if ($person->nid == $mapping->booking_node_id && $group->sid == $mapping->booking_studygroup_id) + { + $found = TRUE; + + //if the existing session is not the same as our newly calculated session, run an update query + if ($mapping->booking_session_id !== $person->session) + { + drupal_set_message(t('Found existing study group session for user !id. Changing old session !old to !session. Role id is !role', + array('!id' => $person->nid, '!old' => $mapping->booking_session_id, '!session' => $person->session, '!role' => $person->booking_studygroup_role))); + + //update the entry + db_update('booking_studygroup_mapping') + ->fields(array( + 'booking_session_id' => $person->session, + 'booking_studygroup_role' => $person->booking_studygroup_role, + )) + ->condition('sid', $mapping->sid) + ->execute(); + + } + else + { + //drupal_set_message(t('Found existing study group session for user !id, but old session !old matches new value !session.', + // array('!id' => $person->nid, '!old' => $mapping->booking_session_id, '!session' => $person->session))); + } + + //stop looping through the list + break; + } + } + + //if we didn't find an existing record, add it to the list to insert + if (! $found && $person->session <> 0) + { + //drupal_set_message(t('Found no existing study group session for user id !id. Adding to list of inserts.', + // array('!id' => $person->nid, '!sid' => $mapping->sid, '!session' => $person->session))); + + $record = array( + 'booking_eventid' => $event->eid, + 'booking_node_id' => $person->nid, + 'booking_studygroup_id' => $group->sid, + 'booking_session_id' => $person->session, + 'booking_studygroup_role' => $person->booking_studygroup_role, + ); + $insert_query->values($record); + } + + } + //$insert_query->execute(); + + //watchdog('booking', "
Session statistics list:\n@info", array('@info' => print_r( $session_count, true))); + + //clear the arrays we've been using for this iteration + unset($session_count); + unset($working_list); + + drupal_set_message(t('Finished processing study group !group.', array('!group' => $group->booking_studygroup_descrip))); + + } //finished processing study groups + + //watchdog('booking', "Attendee list final version: @info", array('@info' => var_export($attendees, TRUE))); +} + /** * Function for viewing a printable format of who belongs to which study group */ diff --git a/booking.tokens.inc b/booking.tokens.inc index 9a7b4a1..a92c2c8 100644 --- a/booking.tokens.inc +++ b/booking.tokens.inc @@ -355,6 +355,13 @@ $booking_registration_intro_text = variable_get('booking_registration_intro_text '#description' => t(''), '#default_value' => variable_get('booking_email_waitinglist_text', $booking_email_waitinglist_text), ); + $form['emails']['booking_email_travel_complete_subject'] = array ( + '#type' => 'textfield', + '#title' => t('Subject line for email indicating a person has completed the travel form'), + '#size' => 150, + '#maxlength' => 300, + '#default_value' => variable_get('booking_email_travel_complete_subject','[booking:eventname] Travel Details Received'), + ); $form['emails']['booking_email_travel_complete_text'] = array( '#title' => t('Email text to indicate a person has completed the travel form.'), '#type' => 'textarea', diff --git a/booking.travel.inc b/booking.travel.inc index 720d46d..7565084 100644 --- a/booking.travel.inc +++ b/booking.travel.inc @@ -351,13 +351,6 @@ function travel_form_validate($form, &$form_state) { //check to make sure flight info is entered if it is selected if (isset($form_state['values']['booking_transport_type']) && $form_state['values']['booking_transport_type'] == 'Flying') { - $arrival_time = _datetime_to_ts($form_state['values']['booking_flight_datetime_inbound']); - $departure_time = _datetime_to_ts($form_state['values']['booking_flight_datetime_outbound']); - - watchdog('booking', "Travel form flying arrival ts !arrival, departing ts !depart", array('!arrival' => $arrival_time, '!depart' => $departure_time)); - watchdog('booking', "
Travel form raw data:\n@info", - array('@info' => print_r( $form_state['values'], true))); - if ( (! isset($form_state['values']['booking_flightnum_inbound'])) || ($form_state['values']['booking_flightnum_inbound'] == '') ) {