1960 lines
70 KiB
PHP
1960 lines
70 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Helper function to strip emoji characters from input text
|
|
* from https://stackoverflow.com/a/41831874/7638834
|
|
*/
|
|
function _booking_remove_emoji($text) {
|
|
$clean_text = "";
|
|
|
|
//don't try to strip emojis if that feature is disabled
|
|
if (variable_get('booking_enable_emoji_removal', 1) == 0) {
|
|
return $text;
|
|
}
|
|
else {
|
|
return preg_replace(
|
|
'/[\x{1F600}-\x{1F64F}]|' .
|
|
'[\x{1F300}-\x{1F5FF}]|' .
|
|
'[\x{1F680}-\x{1F6FF}]|' .
|
|
'[\x{2600}-\x{26FF}]|' .
|
|
'[\x{2700}-\x{27BF}]|' .
|
|
'[\x{1F1E6}-\x{1F1FF}]|' .
|
|
'[\x{1F910}-\x{1F95E}]|' .
|
|
'[\x{1F980}-\x{1F991}]|' .
|
|
'[\x{1F9C0}]|' .
|
|
'[\x{1F9F9}]/u', '', $text);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper function to convert text of any case to Title Case, specifically for names
|
|
* Taken from http://php.net/manual/en/function.ucwords.php
|
|
*/
|
|
function _booking_ucname($string) {
|
|
$all_uppercase = '';
|
|
$all_lowercase = 'De La|De Las|Der|Van De|Van Der|Vit De|Von|Or|And';
|
|
$prefixes = 'Mc';
|
|
$suffixes = "'S";
|
|
|
|
// captialize all first letters
|
|
$string = preg_replace_callback("/\b(\w)/", function ($m) { return strtoupper($m[1]); }, strtolower(trim($string)));
|
|
|
|
if ($all_uppercase) {
|
|
// capitalize acronymns and initialisms e.g. PHP
|
|
$string = preg_replace_callback("/\b($all_uppercase)\b/", function ($m) { return strtoupper($m[1]); }, $string);
|
|
}
|
|
if ($all_lowercase) {
|
|
// decapitalize short words e.g. and
|
|
// all occurences will be changed to lowercase
|
|
$string = preg_replace_callback("/\b($all_lowercase)\b/", function ($m) { return strtolower($m[1]); }, $string);
|
|
}
|
|
|
|
if ($prefixes) {
|
|
// capitalize letter after certain name prefixes e.g 'Mc'
|
|
$string = preg_replace_callback("/\b($prefixes)(\w)/", function ($m) {
|
|
//watchdog('booking_debug', "<pre>Prefixes match: \n@info</pre>", array('@info' => print_r( $m, true)));
|
|
return $m[1] . strtoupper($m[2]);
|
|
}, $string);
|
|
}
|
|
if ($suffixes) {
|
|
// decapitalize certain word suffixes e.g. 's
|
|
$string = preg_replace_callback("/(\w)($suffixes)\b/", function ($m) { return $m[1] . strtolower($m[2]); }, $string);
|
|
}
|
|
|
|
/*
|
|
$string = ucwords(strtolower($string));
|
|
foreach (array('-', '\'') as $delimiter) {
|
|
if (strpos($string, $delimiter) !== false) {
|
|
$string = implode($delimiter, array_map('ucfirst', explode($delimiter, $string)));
|
|
}
|
|
}
|
|
*/
|
|
return $string;
|
|
}
|
|
|
|
/**
|
|
* Helper function to perform some validity checking of email addresses
|
|
*/
|
|
function _valid_email_address($email) {
|
|
|
|
//strip any leading or trailing whitespace
|
|
$email = trim($email);
|
|
|
|
//firstly use the built-in function to validate the format
|
|
if (! valid_email_address($email)) {
|
|
watchdog('booking', "Drupal validation of email address '!email' returns false.", array('!email' => $email));
|
|
return false;
|
|
}
|
|
//now check the domain exists
|
|
|
|
if (preg_match('/^(.*?)\@(.*)/', $email, $matches)) {
|
|
//watchdog('booking', 'Email address checking: @info', array('@info' => var_export($matches, TRUE)));
|
|
if (! checkdnsrr($matches[2], "MX")) {
|
|
watchdog('booking', "No valid MX record found for email address '!email' with domain name !domain", array('!email' => $email, '!domain' => $matches[2]));
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
watchdog('booking', "Regular expression failed to detect domain portion of email address '!email'", array('!email' => $email));
|
|
//watchdog('booking', 'Email address checking doesnt match');
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Helper function to perform some validity checking of Medicare Numbers
|
|
* Based on http://dyball.wordpress.com/2007/12/05/validation-of-medicare-numbers/
|
|
*/
|
|
function _valid_medicare_number($input) {
|
|
//strip any whitespace
|
|
$medicare = preg_replace( '/\s+/', '', $input );
|
|
|
|
//for testing, use the fake medicare number 111111110
|
|
|
|
if (is_numeric($medicare) && strlen($medicare) >= 9 && $medicare > 0) {
|
|
$check_digit = $medicare[0] + (3 * $medicare[1]) + (7 * $medicare[2]) + (9 * $medicare[3])
|
|
+ $medicare[4] + (3 * $medicare[5]) + (7 * $medicare[6]) + (9 * $medicare[7]);
|
|
|
|
if (($check_digit % 10) == $medicare[8]) {
|
|
watchdog('booking', 'Medicare number (!mca) validates since check digit !check matches remainder from !remainder',
|
|
array('!mca' => $input, '!check' => $medicare[8], '!remainder' => $check_digit));
|
|
return TRUE;
|
|
}
|
|
else {
|
|
watchdog('booking', 'Medicare number (!mca) does not validate since check digit !check does not match remainder from !remainder',
|
|
array('!mca' => $input, '!check' => $medicare[8], '!remainder' => $check_digit));
|
|
return FALSE;
|
|
}
|
|
}
|
|
else {
|
|
watchdog('booking', 'Medicare number (!mca) does not validate since it is either non-numeric or too short',
|
|
array('!mca' => $input));
|
|
return FALSE;
|
|
}
|
|
}
|
|
/**
|
|
* Helper function to perform some validity checking of a passport number
|
|
* Based on http://dyball.wordpress.com/2007/04/12/validation-of-passport-numbers/
|
|
* @param $input string containing passport number to be verified
|
|
* @return boolean indicating if passport number is valid
|
|
*/
|
|
function _valid_passport_number($input) {
|
|
//strip whitespace
|
|
$passport = preg_replace( '/\s+/', '', $input );
|
|
//check for a match
|
|
if (preg_match('/^[a-zA-Z]{1,2}\d{7}$/', $input, $matches)) {
|
|
watchdog('booking', 'Passport number "!passnum" validates since it passed our regexp',
|
|
array('!passnum' => $input));
|
|
return TRUE;
|
|
}
|
|
watchdog('booking', 'Passport number "!passnum" fails to validate',
|
|
array('!passnum' => $input));
|
|
return FALSE;
|
|
}
|
|
|
|
function _valid_phone_number($input)
|
|
{
|
|
//strip any whitespace
|
|
$number = preg_replace( '/\s+/', '', $input );
|
|
//strip any non-numeric characters
|
|
$number = preg_replace('/\D+/','', $number);
|
|
|
|
if (is_numeric($number))
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
function _valid_australian_mobile_number($input)
|
|
{
|
|
if (preg_match('/^\s*(?:\+61|61|0061|0)(\d{3})\s*(\d{3})\s*(\d{3})\s*$/', $input, $matches))
|
|
{
|
|
//watchdog('booking', 'Australian Mobile Number "!passnum" validates since it passed our regexp', array('!passnum' => $input));
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/**
|
|
* Helper function to check whether the number of registrations for the current event have reached their defined maximum size
|
|
*/
|
|
function _booking_check_bookings_full()
|
|
{
|
|
global $event;
|
|
$waitinglist_query = db_query("SELECT count(*) as num_ppl FROM {booking_person} where booking_eventid = :eventid and booking_status = 1",
|
|
array(':eventid' => $event->eid))
|
|
->fetchObject();
|
|
//check the number of people registered against the defined max
|
|
if ($waitinglist_query->num_ppl >= variable_get('booking_regn_limit', 350))
|
|
{
|
|
watchdog('booking', 'There are !num people booked in, which is greater than or equal to the limit of !limit.',
|
|
array('!num' => $waitinglist_query->num_ppl, '!limit' => variable_get('booking_regn_limit', 350) ));
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
watchdog('booking', 'There are !num people booked in, which is less than the limit of !limit.',
|
|
array('!num' => $waitinglist_query->num_ppl, '!limit' => variable_get('booking_regn_limit', 350) ));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper function to check who is the first person on the waiting list
|
|
*/
|
|
function _booking_get_waitinglist_top()
|
|
{
|
|
global $event;
|
|
|
|
$result = db_query('SELECT p.nid, p.booking_firstname, p.booking_lastname, pay.booking_payment_date
|
|
FROM {booking_person} p, {booking_payment} pay
|
|
WHERE booking_status = 2 and p.booking_eventid = :eid and p.nid = pay.booking_person_nid
|
|
ORDER BY pay.booking_payment_date
|
|
LIMIT 1',
|
|
array(':eid' => $event->eid));
|
|
|
|
foreach ($result as $person) {
|
|
watchdog('booking', "First person on the waiting list: @info", array('@info' => var_export($person, TRUE)));
|
|
return $person->nid;
|
|
}
|
|
|
|
//in case there's no people with status waiting list, but there is some with missed payment deadline
|
|
$result = db_query('SELECT p.nid, p.booking_firstname, p.booking_lastname, pay.booking_payment_date
|
|
FROM {booking_person} p, {booking_payment} pay
|
|
WHERE booking_status = 4 and p.booking_eventid = :eid and p.nid = pay.booking_person_nid
|
|
ORDER BY pay.booking_payment_date
|
|
LIMIT 1',
|
|
array(':eid' => $event->eid));
|
|
|
|
foreach ($result as $person) {
|
|
watchdog('booking', "First person on the missed-payment-deadline list: @info", array('@info' => var_export($person, TRUE)));
|
|
return $person->nid;
|
|
}
|
|
|
|
//in case there was no one on the waiting list
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* Helper function to retrieve all the people on the waiting list
|
|
*/
|
|
function _booking_get_waitinglist()
|
|
{
|
|
global $event;
|
|
|
|
// This query doesn't work once someone on the waiting list has paid a deposit then a balance payment
|
|
// Since there are multiple results in the booking_payment table
|
|
// And only the most recent is returned
|
|
/*
|
|
//get a list of everyone on the waiting list
|
|
$db_or = db_or();
|
|
$db_or->condition('p.booking_status', 2, '=');
|
|
$db_or->condition('p.booking_status', 4, '=');
|
|
|
|
$db_and = db_and();
|
|
$db_and->condition('p.booking_eventid', $event->eid, '=');
|
|
$db_and->condition($db_or);
|
|
|
|
$query = db_select('booking_person', 'p')->distinct();
|
|
$query->join('booking_payment', 'y', 'p.nid = y.booking_person_nid');
|
|
$query->condition($db_and)
|
|
->fields('p', array('nid', 'booking_firstname', 'booking_lastname', 'booking_state', 'booking_readinggroup', 'booking_country', 'booking_status'))
|
|
->fields('y', array('booking_payment_date'))
|
|
->orderBy('p.booking_status')->orderBy('y.booking_payment_date');
|
|
$definition_result = $query->execute();
|
|
|
|
watchdog('booking_debug', "<pre>_booking_get_waitinglist\n@info</pre>", array('@info' => print_r($definition_result->queryString, true)));
|
|
return $definition_result;
|
|
*/
|
|
|
|
// Taken from the Waiting List page, not very optimised
|
|
$result = db_query('SELECT DISTINCT nid, booking_firstname, booking_lastname, booking_state, booking_readinggroup, booking_country, booking_status
|
|
FROM (
|
|
SELECT p.nid, p.booking_firstname, p.booking_lastname, p.booking_state, p.booking_country, p.booking_readinggroup, pay.booking_payment_date, p.booking_status
|
|
FROM {booking_person} p, {booking_payment} pay
|
|
WHERE p.booking_eventid = :eid and p.nid = pay.booking_person_nid and ( p.booking_status = 2 or p.booking_status = 4)
|
|
) AS booking
|
|
ORDER BY booking_status, booking_payment_date',
|
|
array(':eid' => $event->eid));
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Helper function to update the status of a registration
|
|
*/
|
|
function _booking_change_status($nid, $status_id)
|
|
{
|
|
db_update('booking_person')
|
|
->fields(array(
|
|
'booking_status' => $status_id,
|
|
))
|
|
->condition('nid', $nid)
|
|
->execute();
|
|
}
|
|
|
|
function _datearray_to_ts($date)
|
|
{
|
|
//watchdog('booking', 'Date Conversion: @info', array('@info' => var_export($date, TRUE)));
|
|
date_default_timezone_set(date_default_timezone(FALSE));
|
|
$tz = new DateTimeZone(date_default_timezone(FALSE));
|
|
|
|
if (empty($date) || ($date['month'] == '' && $date['day'] == '' && $date['year'] == '')) {
|
|
return 0;
|
|
}
|
|
//else
|
|
// watchdog('booking', "Date array to timestamp: @info", array('@info' => var_export($date, TRUE)));
|
|
|
|
$gmt_ts = mktime(0, 0, 0, $date['month'], $date['day'], $date['year']);
|
|
$ts = new DateTime("@$gmt_ts");
|
|
$ts->setTimezone($tz);
|
|
|
|
return $ts->format("U");
|
|
}
|
|
|
|
function _datetime_array_to_ts($date)
|
|
{
|
|
//watchdog('booking', 'Date-time Conversion: @info', array('@info' => var_export($date, TRUE)));
|
|
//watchdog('booking', "Date time conversion timezone configured as: @info", array('@info' => date_default_timezone(FALSE)));
|
|
date_default_timezone_set(date_default_timezone(FALSE));
|
|
$tz = new DateTimeZone(date_default_timezone(FALSE));
|
|
|
|
if (empty($date) || ($date['month'] == '' && $date['day'] == '' && $date['year'] == '')) {
|
|
return 0;
|
|
}
|
|
//else
|
|
// watchdog('booking', "Date array to timestamp: @info", array('@info' => var_export($date, TRUE)));
|
|
|
|
$gmt_ts = mktime($date['hour'], $date['minute'], 0, $date['month'], $date['day'], $date['year']);
|
|
$ts = new DateTime("@$gmt_ts");
|
|
$ts->setTimezone($tz);
|
|
//watchdog('booking', '<pre>Date-time Conversion: @info </pre>', array('@info' => print_r( $ts, true)));
|
|
return $ts->format("U");
|
|
}
|
|
|
|
|
|
function _date_to_ts($date) {
|
|
$date_split = _booking_split_date($date);
|
|
|
|
date_default_timezone_set(date_default_timezone(FALSE));
|
|
$tz = new DateTimeZone(date_default_timezone(FALSE));
|
|
|
|
if ($date_split[0] == '-1' ) {
|
|
return 0;
|
|
}
|
|
|
|
$gmt_ts = mktime(0, 0, 0, $date_split[2], $date_split[3], $date_split[1]);
|
|
$ts = new DateTime("@$gmt_ts");
|
|
$ts->setTimezone($tz);
|
|
|
|
return $ts->format("U");
|
|
//return mktime($date_split[5], $date_split[6], 0, $date_split[2], $date_split[3], $date_split[1]);
|
|
}
|
|
|
|
function _datetime_to_ts($date) {
|
|
$date_split = _booking_split_date($date);
|
|
|
|
date_default_timezone_set(date_default_timezone(FALSE));
|
|
$tz = new DateTimeZone(date_default_timezone(FALSE));
|
|
|
|
if ($date_split[0] == '-1' )
|
|
return 0;
|
|
|
|
$gmt_ts = mktime($date_split[5], $date_split[6], 0, $date_split[2], $date_split[3], $date_split[1]);
|
|
$ts = new DateTime("@$gmt_ts");
|
|
$ts->setTimezone($tz);
|
|
|
|
return $ts->format("U");
|
|
|
|
//return mktime($date_split[5], $date_split[6], 0, $date_split[2], $date_split[3], $date_split[1]);
|
|
}
|
|
|
|
/**
|
|
* Function to turn a loosely formatted date into a timestamp, with optional time
|
|
*
|
|
* @param $date in format DD/MM/YYYY HH:mm or just DD/MM/YYYY
|
|
* @return unix timestamp formatted for current time zone
|
|
*/
|
|
function _datetime_to_ts_nonstrict($date) {
|
|
$pattern = '/^(\d{1,2})\/(\d{1,2})\/(\d{4})(\s+(\d{1,2})\:(\d{1,2}))?/';
|
|
|
|
//check for a match
|
|
if (preg_match($pattern, $date, $matches))
|
|
{
|
|
//$date_split = $matches;
|
|
$hour = isset($matches[5]) ? $matches[5] : 0;
|
|
$minute = isset($matches[6]) ? $matches[6] : 0;
|
|
$second = 0;
|
|
$month = $matches[2];
|
|
$day = $matches[1];
|
|
$year = $matches[3];
|
|
}
|
|
//return zero now if no matches
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
date_default_timezone_set(date_default_timezone(FALSE));
|
|
$tz = new DateTimeZone(date_default_timezone(FALSE));
|
|
|
|
//$gmt_ts = mktime($date_split[5], $date_split[6], 0, $date_split[2], $date_split[1], $date_split[3]);
|
|
$gmt_ts = mktime($hour, $minute, $second, $month, $day, $year);
|
|
$ts = new DateTime("@$gmt_ts");
|
|
$ts->setTimezone($tz);
|
|
|
|
return $ts->format("U");
|
|
}
|
|
|
|
/**
|
|
* Function to split date into array
|
|
*
|
|
* @param $date in format YYYY-MM-DD
|
|
* @return array containing Year, Month, Day
|
|
*/
|
|
function _booking_split_date($date) {
|
|
$pattern = '/^(\d{4})-(\d{2})-(\d{2})(\s(\d{2})\:(\d{2}))?/';
|
|
if (preg_match($pattern, $date, $matches)) {
|
|
return $matches;
|
|
} else {
|
|
return array('-1');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Function to re-arrange date
|
|
*
|
|
* @param $date in format YYYY-MM-DD
|
|
* @return array containing Year, Month, Day
|
|
*/
|
|
function _arrange_date($date) {
|
|
$pattern = '/^(\d{4})-(\d{2})-(\d{2})/';
|
|
if (preg_match($pattern, $date, $matches)) {
|
|
return $matches;
|
|
} else {
|
|
return array('-1');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper function to ensure timestamp is converted to correct local time
|
|
*/
|
|
function _booking_convert_ts($timestamp)
|
|
{
|
|
//load the timestamp
|
|
date_default_timezone_set(date_default_timezone(FALSE));
|
|
$tz = new DateTimeZone(date_default_timezone(FALSE));
|
|
|
|
$date = new DateTime("@$timestamp");
|
|
$date->setTimezone($tz);
|
|
|
|
return $date;
|
|
}
|
|
|
|
|
|
/**
|
|
* Helper function to calculate the timestamp corresponding with the DOB requirements
|
|
*/
|
|
function _booking_max_dob_ts()
|
|
{
|
|
//calculate DOB limit as defined by configuration
|
|
$max_dob_matches = _booking_split_date(variable_get('booking_max_dob','0'));
|
|
return mktime(12, 0, 0, $max_dob_matches[2], $max_dob_matches[3], $max_dob_matches[1]);
|
|
}
|
|
|
|
/**
|
|
* Helper function to calculate the year offset between the start of event and a
|
|
*
|
|
* @param $datetime Date to compare from date_select field
|
|
* @return integer containing difference in years
|
|
*/
|
|
function _booking_year_offset($datetime)
|
|
{
|
|
global $event;
|
|
|
|
//set the time zone
|
|
date_default_timezone_set(date_default_timezone(FALSE));
|
|
$tz = new DateTimeZone(date_default_timezone(FALSE));
|
|
|
|
//try to load the date
|
|
try {
|
|
//$date = new DateTime(variable_get('booking_min_dob','1970-01-01 00:00:00'));
|
|
$date = new DateTime($datetime);
|
|
} catch (Exception $e) {
|
|
$date = new DateTime('1970-01-01 00:00:00');
|
|
}
|
|
|
|
//set the timezone for the date
|
|
$date->setTimezone($tz);
|
|
|
|
//watchdog('booking', '<pre>DateTime of minimum DOB:\n @info </pre>', array('@info' => print_r( $date, true)));
|
|
|
|
$reference_date = _booking_convert_ts($event->booking_event_start);
|
|
$difference = $date->diff($reference_date);
|
|
|
|
//watchdog('booking', '<pre>DateTime of difference in minimum DOB to start of event:\n @info </pre>', array('@info' => print_r( $difference, true)));
|
|
|
|
return $difference->y;
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* Helper function to calculate the average age in days, months and years at the start of the event
|
|
*/
|
|
function _booking_avg_age($sum, $count, $reference_ts)
|
|
{
|
|
//handle condition where count is zero
|
|
if ($count == 0)
|
|
{
|
|
return "Zero";
|
|
}
|
|
|
|
global $event;
|
|
//calculate the average age timestamp
|
|
$average = $sum / $count;
|
|
//get the difference between now and the average timestamp
|
|
$average_date = _booking_convert_ts(floor($average));
|
|
$now_date = _booking_convert_ts(floor($reference_ts));
|
|
$difference = $average_date->diff($now_date);
|
|
//convert the difference into english
|
|
return $difference->y . " years, " . $difference->m . " months, " . $difference->d . " days";
|
|
}
|
|
|
|
/**
|
|
* Helper function to calculate persons age in years at start of event
|
|
*/
|
|
function _booking_get_age_years($dob_ts)
|
|
{
|
|
global $event;
|
|
$reference_ts = _booking_convert_ts($event->booking_event_start);
|
|
$dob = _booking_convert_ts($dob_ts);
|
|
return $dob->diff($reference_ts)->y;
|
|
}
|
|
|
|
/**
|
|
* Helper function to create a string describing a date range
|
|
*/
|
|
function _date_range_to_string($date_start, $date_end) {
|
|
$start = _booking_split_date($date_start);
|
|
$end = _booking_split_date($date_end);
|
|
$final_string = '';
|
|
|
|
//check for correctly formatted dates
|
|
if ($start[0] == '-1' || $end[0] == '-1') {
|
|
//incorrect response
|
|
form_set_error('yc_date_endbeforestart', t('Invalid date format received from !date or !date_end.', array('!date' => $date_start, '!date_end' => $date_end)));
|
|
} else {
|
|
//start with the day field
|
|
//mktime uses format month, day, year
|
|
$end_string = strftime("%e", mktime(12, 0, 0, $end[2], $end[3], $end[1]));
|
|
$start_string = strftime("%e", mktime(12, 0, 0, $start[2], $start[3], $start[1]));
|
|
|
|
//now include the month in the comparison. Compare including the year.
|
|
if (mktime(12, 0, 0, $end[2], 1, $end[1]) > mktime(12, 0, 0, $start[2], 1, $start[1])) {
|
|
//use the textual version to make things more readable
|
|
//strftime ( string $format [, int $timestamp = time() ] )
|
|
//%B Full month name, based on the locale
|
|
$end_string .= ' ' . strftime("%B", mktime(12, 0, 0, $end[2], 1, $end[1]));
|
|
$start_string .= ' ' . strftime("%B", mktime(12, 0, 0, $start[2], 1, $start[1]));
|
|
} else {
|
|
$end_string .= ' ' . strftime("%B", mktime(12, 0, 0, $end[2], 1, $end[1]));
|
|
//no need to append anything to $start_string
|
|
}
|
|
|
|
//create a timestamp based on 1 Jan that year to compare
|
|
if (mktime(12, 0, 0, 1, 1, $end[1]) > mktime(12, 0, 0, 1, 1, $start[1])) {
|
|
//create two seperate strings, one to hold the last part of the date range
|
|
//the other to hold the first part
|
|
$end_string .= ' ' . $end[1];
|
|
$start_string .= ' ' . $start[1];
|
|
} else {
|
|
$end_string .= ' ' . $end[1];
|
|
//no need to append anything to $start_string
|
|
}
|
|
|
|
//put both parts together
|
|
$final_string = $start_string . ' to ' . $end_string;
|
|
}
|
|
return $final_string;
|
|
}
|
|
|
|
/**
|
|
* Function to correctly clone an associative array storing objects
|
|
* Taken from http://stackoverflow.com/questions/1532618/is-there-a-function-to-make-a-copy-of-a-php-array-to-another
|
|
*/
|
|
function _booking_clone_array($copied_array) {
|
|
return array_map(function($element) {
|
|
return (
|
|
((is_array($element))
|
|
? call_user_func(__FUNCTION__, $element)
|
|
: ((is_object($element))
|
|
? clone $element
|
|
: $element
|
|
)
|
|
)
|
|
);
|
|
}, $copied_array);
|
|
}
|
|
|
|
|
|
/**
|
|
* Function to randomise the ordering of an array
|
|
* taken from http://stackoverflow.com/questions/4102777/php-random-shuffle-array-maintaining-key-value
|
|
*/
|
|
function _booking_shuffle_assoc($list) {
|
|
if (!is_array($list)) return $list;
|
|
|
|
$keys = array_keys($list);
|
|
shuffle($keys);
|
|
$random = array();
|
|
foreach ($keys as $key) {
|
|
$random[$key] = $list[$key];
|
|
}
|
|
return $random;
|
|
}
|
|
|
|
/**
|
|
* Helper function to cycle through a list without getting in an endless loop
|
|
* Used for calculating study groups and maybe readings groups
|
|
*
|
|
* Each iteration through the list the maximum permitted size for a given entry will be increased by one
|
|
* until we find an available entry or we run out of cycle counts
|
|
*/
|
|
function _booking_loop_carefully(&$list, $field, &$i, $maximum, $list_size, $max_cycle_count, &$log_array)
|
|
{
|
|
$cycle = 0;
|
|
while ($list[$i][$field] >= $maximum)
|
|
{
|
|
$log_array[] = t("Field !field is !value for entry !index, which larger than maximum allowed size, !max. Moving to next entry in list.",
|
|
array('!field' => $field, '!value' => $list[$i][$field], '!max' => $maximum, '!index' => $i));
|
|
|
|
$i++;
|
|
//reset the counter if we go past the end
|
|
if ($i > $list_size)
|
|
{
|
|
$i = 1;
|
|
//make sure we don't get stuck in an infinite loop - only go past the end once
|
|
if ($cycle >= $max_cycle_count)
|
|
{
|
|
$log_array[] = t("Reached the end of !field list. Unable to find satisfactory entry after !num cycles.",
|
|
array('!field' => $field, '!num' => $cycle));
|
|
return;
|
|
}
|
|
elseif ($cycle > 0)
|
|
{
|
|
//temporarily increase the maximum size of our groups by one
|
|
$maximum++;
|
|
}
|
|
//always increment the cycle counter if we've reached the end
|
|
$cycle++;;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Function to mark an attendee as processed for group calculations
|
|
* @param $input string containing passport number to be verified
|
|
*/
|
|
function _booking_assign_attendee_group($nid, $session_id, $gender, $age, &$attendee_list, &$session_count, &$log_array)
|
|
{
|
|
$previous_session = 0;
|
|
|
|
//check for valid attendee
|
|
if (empty($nid))
|
|
{
|
|
drupal_set_message(t('Attempting to process a non-existent node id.'));
|
|
return;
|
|
}
|
|
|
|
//check if this person had already been processsed
|
|
if ($attendee_list[$nid]->processed == 1 && $attendee_list[$nid]->session > 0)
|
|
{
|
|
$log_array[] = t('Detected re-assignment of id !id previously assigned to session !session.',
|
|
array('!id' => $nid, '!session' => $attendee_list[$nid]->session)
|
|
);
|
|
|
|
$previous_session = $attendee_list[$nid]->session;
|
|
|
|
//update previous session totals
|
|
$session_count[$previous_session][$gender]--;
|
|
$session_count[$previous_session]['total']--;
|
|
if ($age < 20)
|
|
$session_count[$previous_session]['under20']--;
|
|
elseif($age >= 20 && $age < 25)
|
|
$session_count[$previous_session]['20to25']--;
|
|
else
|
|
$session_count[$previous_session]['over25']--;
|
|
}
|
|
|
|
//mark this person as processed in the working list
|
|
$attendee_list[$nid]->processed = 1;
|
|
$attendee_list[$nid]->session = $session_id;
|
|
|
|
//record the category of person
|
|
$session_count[$session_id][$gender]++;
|
|
$session_count[$session_id]['total']++;
|
|
|
|
//process ages
|
|
if ($age < 20)
|
|
$session_count[$session_id]['under20']++;
|
|
elseif($age >= 20 && $age < 25)
|
|
$session_count[$session_id]['20to25']++;
|
|
else
|
|
$session_count[$session_id]['over25']++;
|
|
}
|
|
|
|
|
|
/**
|
|
* Validate there is available capacity for the specified room and bed type
|
|
* @return TRUE if there is sufficient capacity, otherwise FALSE
|
|
*/
|
|
function _booking_room_capacity_check($room_id, $room_bedtype, $room_definition_object = NULL) {
|
|
global $event;
|
|
|
|
$bed_inputs = array(
|
|
1 => 'booking_room_singlebeds',
|
|
2 => 'booking_room_doublebeds',
|
|
3 => 'booking_room_queenbeds',
|
|
);
|
|
|
|
//make sure the value exists before validating it
|
|
if (!empty($room_bedtype))
|
|
{
|
|
//if we already have the object available, don't query for it again
|
|
if ($room_definition_object == NULL)
|
|
{
|
|
$details = db_query("SELECT * FROM {booking_room_definition} WHERE rid = :rid",
|
|
array(':rid' => $room_id))->fetchObject();
|
|
}
|
|
else
|
|
$details = $room_definition_object;
|
|
|
|
//get all person-to-room mappings relating to this room and bed type
|
|
$mappings = db_query("SELECT count(*) as num FROM {booking_room_mapping} " .
|
|
"WHERE booking_eventid = :eid AND booking_roomid = :rid AND booking_room_bedtype = :type",
|
|
array(':eid' => $event->eid, ':rid' => $room_id, ':type' => $room_bedtype))->fetchObject();
|
|
|
|
$db_field = $bed_inputs[$room_bedtype];
|
|
$max_beds = $details->$db_field;
|
|
|
|
//if the beds are dual occupency, pretend there's twice as many of them
|
|
if ($room_bedtype == 2 || $room_bedtype == 3)
|
|
{
|
|
$max_beds = $max_beds * 2;
|
|
}
|
|
|
|
//check that there is sufficient capacity to allocate another person to this room and bed type
|
|
if ($mappings->num < $max_beds)
|
|
{
|
|
//watchdog('booking','Sufficient capacity is available in location !id, room !room, with bed type !type. !count beds remaining of this type',
|
|
// array('!id' => $details->booking_room_location_id, '!room' => $details->booking_room_number,
|
|
// '!type' => _booking_room_bedtype_lookup($room_bedtype), '!count' => $max_beds - $mappings->num));
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
watchdog('booking',"Couldn't locate sufficient capacity in location !id, room !room, with bed type !type. !count beds remaining of this type",
|
|
array('!id' => $details->booking_room_location_id, '!room' => $details->booking_room_number,
|
|
'!type' => _booking_room_bedtype_lookup($room_bedtype), '!count' => $max_beds - $mappings->num));
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Function for cleaning up room allocations for people that have withdrawn their registration
|
|
* @param $nid - the node id for the person
|
|
* @return nothing
|
|
*/
|
|
function _booking_person_rooms_cleanup($nid)
|
|
{
|
|
global $event;
|
|
|
|
//first of all make sure we need to do anything
|
|
if (variable_get('booking_enable_roomallocations', 0) == 1)
|
|
{
|
|
//should only be one room allocation per person, so no need to loop over the results
|
|
$room_mapping = db_query("SELECT * FROM {booking_room_mapping} WHERE booking_eventid = :eid AND booking_nodeid = :nid",
|
|
array(':eid' => $event->eid, ':nid' => $nid))
|
|
->fetchObject();
|
|
|
|
if ($room_mapping)
|
|
{
|
|
$message = t("Removing id !nid from room id !room.",
|
|
array('!nid' => $nid, '!room' => $room_mapping->booking_roomid)
|
|
);
|
|
watchdog('booking', $message);
|
|
drupal_set_message($message, 'status', FALSE);
|
|
|
|
db_delete('booking_room_mapping')
|
|
->condition('booking_eventid', $event->eid)
|
|
->condition('booking_nodeid', $nid)
|
|
->execute();
|
|
|
|
|
|
} //for each room
|
|
} //end check for room allocations enabled
|
|
} //end function
|
|
|
|
/**
|
|
* Function for cleaning up study groups by removing people that have withdrawn their registration
|
|
* @param nothing - processes all defined study groups for the current event
|
|
* @return nothing
|
|
*/
|
|
function _booking_studygroup_cleanup()
|
|
{
|
|
global $event;
|
|
|
|
//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 m.booking_eventid = :eid AND p.booking_status = 3",
|
|
array(':eid' => $event->eid));
|
|
$to_remove = $to_remove_query->fetchAll();
|
|
|
|
//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));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Function for cleaning up study groups for a person that is no longer coming
|
|
* @param $nid - the node id for the person who has withdrawn their registration
|
|
* @return nothing
|
|
*/
|
|
function _booking_person_studygroups_cleanup($nid)
|
|
{
|
|
global $event;
|
|
|
|
//first of all make sure we need to do anything
|
|
if (variable_get('booking_enable_studygroups', 0) == 1)
|
|
{
|
|
//query for any groups this person is assigned to
|
|
$to_remove_query = db_query("SELECT m.* FROM {booking_studygroup_mapping} m WHERE booking_node_id = :nid",
|
|
array(':nid' => $nid));
|
|
$to_remove = $to_remove_query->fetchAll();
|
|
|
|
foreach ($to_remove as $group)
|
|
{
|
|
$message = t("Removing id !nid from group id !group, session !session with role !role",
|
|
array('!nid' => $nid, '!group' => $group->booking_studygroup_id, '!session' => $group->booking_session_id,
|
|
'!role' => _booking_studygroup_role_lookup($group->booking_studygroup_role)
|
|
)
|
|
);
|
|
watchdog('booking', $message);
|
|
drupal_set_message($message, 'status', FALSE);
|
|
|
|
db_delete('booking_studygroup_mapping')
|
|
->condition('booking_eventid', $event->eid)
|
|
->condition('booking_node_id', $nid)
|
|
->condition('booking_studygroup_id', $group->booking_studygroup_id)
|
|
->execute();
|
|
} //for each group
|
|
} //end check for study groups enabled
|
|
} //end function
|
|
|
|
/**
|
|
* Function for calculating statistics of attendees
|
|
*/
|
|
function _booking_generate_statistics($booking_list)
|
|
{
|
|
global $event;
|
|
|
|
$statistics = array(
|
|
'males' => 0,
|
|
'females' => 0,
|
|
'under20' => 0,
|
|
'20to25' => 0,
|
|
'over25' => 0,
|
|
);
|
|
|
|
foreach ($booking_list as $person)
|
|
{
|
|
//ignore people that havent paid or are no longer coming or missed the payment deadline
|
|
if ($person->booking_status == 0 || $person->booking_status == 3 || $person->booking_status == 4)
|
|
continue;
|
|
|
|
if ($person->booking_gender == 'M')
|
|
$statistics['males']++;
|
|
else
|
|
$statistics['females']++;
|
|
|
|
$age = _booking_get_age_years($person->booking_dob);
|
|
|
|
if ($age < 20)
|
|
$statistics['under20']++;
|
|
elseif($age >= 20 && $age < 25)
|
|
$statistics['20to25']++;
|
|
else
|
|
$statistics['over25']++;
|
|
}
|
|
|
|
return $statistics;
|
|
}
|
|
|
|
//figure out if we're in the right time period for discounted registration rates
|
|
function _booking_is_earlybird() {
|
|
global $event;
|
|
|
|
if ($event->booking_earlybird_close > time()) {
|
|
return TRUE;
|
|
}
|
|
else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//figure out if we're in the right time period for discounted registration rates
|
|
function _booking_is_earlyaccess() {
|
|
global $event;
|
|
|
|
if (variable_get('booking_enable_earlyaccess_codes', 0) == 1) {
|
|
$booking_times = db_query("SELECT booking_register_open, booking_register_close FROM {booking_event} where eid = :eid",
|
|
array(':eid' => $event->eid))->fetchObject();
|
|
|
|
//if we're now before the time that registrations open, then this registration must be from the early access time period
|
|
return ($booking_times->booking_register_open > time());
|
|
}
|
|
|
|
//if the feature isn't enabled then just return false
|
|
return FALSE;
|
|
}
|
|
|
|
function _booking_datepaid_ts($nid) {
|
|
$query = db_query("SELECT * FROM {booking_payment} where booking_person_nid = :nid", array(':nid' => $nid))
|
|
->fetchObject();
|
|
|
|
if ($query) {
|
|
return $query->booking_payment_date;
|
|
}
|
|
else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper function to return the amount for a booking deposit, if there is one
|
|
*/
|
|
function _booking_deposit_amount($person, $include_fees = TRUE) {
|
|
global $event;
|
|
|
|
$deposit = db_query("SELECT price.booking_price, price.booking_price_descrip " .
|
|
"FROM {booking_price} price WHERE booking_eventid = :eventid and booking_depositonly = 1 and booking_price_active = 1",
|
|
array(':eventid' => $event->eid))
|
|
->fetchObject();
|
|
|
|
if ($deposit) {
|
|
//if we're using paypal or stripe, add the transaction fee
|
|
$payment_processor_type = variable_get('booking_payment_processor', 0);
|
|
if ($include_fees == TRUE) {
|
|
//paypal is enabled
|
|
if ($payment_processor_type == 0) {
|
|
$amount_owing = _booking_add_paypal_fees($deposit->booking_price, $person->booking_country);
|
|
}
|
|
//stripe is enabled
|
|
elseif ($payment_processor_type == 1) {
|
|
$amount_owing = _booking_add_stripe_fees($deposit->booking_price, $person->booking_country);
|
|
}
|
|
}
|
|
//otherwise we're using manual payment processing so don't add any fees
|
|
else {
|
|
$amount_owing = $deposit->booking_price;
|
|
}
|
|
//return the calculated amount rounded to two decimal places
|
|
return number_format($amount_owing, 2, '.', '');
|
|
}
|
|
else {
|
|
//there is no deposit amount
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Calculate exactly how much a person has already paid
|
|
*/
|
|
function _booking_amount_paid($nid, $person = NULL) {
|
|
$amount_paid = 0;
|
|
|
|
//fetch details about the person if we don't already have them
|
|
if ($person == NULL) {
|
|
$person = db_query("SELECT price.booking_price, price.booking_late_price, person.booking_payment_id, " .
|
|
"person.booking_total_pay_reqd, person.booking_amount_paid, person.booking_partner_id " .
|
|
"FROM {booking_person} person, {booking_price} price " .
|
|
"WHERE person.nid = :nid " .
|
|
"AND person.booking_payment_id = price.pid",
|
|
array(':nid' => $nid))
|
|
->fetchObject();
|
|
}
|
|
|
|
//check for a spouse
|
|
if ($person->booking_partner_id > 0) {
|
|
//watchdog('booking', "Checking total paid for married person");
|
|
|
|
//look for payments in the payment transaction table
|
|
|
|
//if we're combining the payment for married couples
|
|
if (variable_get('booking_enable_combined_pricing', 0) == 1) {
|
|
//check for payments in the paypal transaction table from either spouse
|
|
$query = db_query("SELECT booking_mc_gross, booking_mc_fee FROM booking_payment " .
|
|
"WHERE booking_person_nid = :nid OR booking_person_nid = :spousenid",
|
|
array(':nid' => $nid, 'spousenid' => $person->booking_partner_id));
|
|
}
|
|
else {
|
|
//check for payments in the paypal transaction table from just this person
|
|
$query = db_query("SELECT booking_mc_gross, booking_mc_fee FROM booking_payment " .
|
|
"WHERE booking_person_nid = :nid",
|
|
array(':nid' => $nid));
|
|
}
|
|
|
|
//add up all the payments
|
|
foreach ($query as $payment) {
|
|
$amount_paid += ($payment->booking_mc_gross - $payment->booking_mc_fee);
|
|
}
|
|
|
|
//watchdog('booking', "Total amount paid according to paypal payments table is " . $amount_paid);
|
|
|
|
//there were no payment transactions, so rely on what the amount is set to in the individual registration records
|
|
if ($amount_paid == 0) {
|
|
//if we're combining the payment for married couples
|
|
if (variable_get('booking_enable_combined_pricing', 0) == 1) {
|
|
$spouse = db_query("SELECT person.booking_amount_paid " .
|
|
"FROM {booking_person} person " .
|
|
"WHERE person.nid = :nid ",
|
|
array(':nid' => $person->booking_partner_id))
|
|
->fetchObject();
|
|
$amount_paid = $person->booking_amount_paid + $spouse->booking_amount_paid;
|
|
//watchdog('booking', "Total combined payments for couple based on totals in booking_person table is " . $amount_paid);
|
|
}
|
|
else {
|
|
$amount_paid = $person->booking_amount_paid;
|
|
//watchdog('booking', "Total amount paid for individual based on totals in booking_person table is " . $amount_paid);
|
|
}
|
|
//end combined payments check
|
|
}
|
|
}
|
|
//no spouse found
|
|
else {
|
|
//Check if there are payment records in the paypal transaction table for this unmarried person
|
|
//if so, base their payments on the gross amount in there rather than what the person booking_person database says
|
|
$query = db_query("SELECT booking_mc_gross, booking_mc_fee FROM booking_payment " .
|
|
"WHERE booking_person_nid = :nid",
|
|
array(':nid' => $nid));
|
|
foreach ($query as $payment)
|
|
$amount_paid += ($payment->booking_mc_gross - $payment->booking_mc_fee);
|
|
|
|
//watchdog('booking', "Total amount paid according to paypal payments table is " . $amount_paid);
|
|
|
|
//if there were no results, $amount_paid will still be 0
|
|
if ($amount_paid == 0) {
|
|
$amount_paid = $person->booking_amount_paid;
|
|
}
|
|
//in case there has been some manual adjustment
|
|
//elseif ($amount_paid < $person->booking_amount_paid)
|
|
// $amount_paid = $person->booking_amount_paid;
|
|
}
|
|
|
|
//watchdog('booking', "Total amount already paid for this registration " . $nid . " is " . $amount_paid);
|
|
|
|
return $amount_paid;
|
|
}
|
|
|
|
/**
|
|
* Function to calculate the total amount a person is required to pay
|
|
*
|
|
* @param $person - the populated node object representing this person including related price information
|
|
* @return amount owing as a decimal value
|
|
*/
|
|
function _booking_total_due($person)
|
|
{
|
|
//watchdog('booking', "<pre>_booking_total_due person:\n @info</pre>", array('@info' => print_r( $person, true)));
|
|
$total_due = 0.00;
|
|
|
|
//check for a spouse
|
|
if ($person->booking_partner_id > 0 && variable_get('booking_enable_combined_pricing', 0) == 1)
|
|
{
|
|
//watchdog('booking', "Calculating total amount due for a married couple.");
|
|
|
|
//TODO: figure out if anything special is needed here
|
|
}
|
|
|
|
//determine what rate this person needs to pay
|
|
if ($person->booking_welfare_required == 'Y' || $person->booking_committee_member == 'Y')
|
|
{
|
|
//cater for any manual adjustment
|
|
//watchdog('booking', "This registration is eligible for welfare rates");
|
|
$total_due = $person->booking_total_pay_reqd;
|
|
}
|
|
//the early bird rate will be defined by default for the registration
|
|
elseif (_booking_is_earlybird() == TRUE || _booking_is_earlyaccess() == TRUE)
|
|
{
|
|
$total_due = $person->booking_total_pay_reqd;
|
|
}
|
|
//finally we must be in the late-fee period
|
|
else
|
|
{
|
|
//when first creating this node the price information won't all exist
|
|
//since we combine that with the booking_person table in the hook for node_load
|
|
if (!isset($person->booking_late_price)) {
|
|
//query the database based on the payment_id that is set when we first create the node
|
|
$query = db_select('booking_price', 'p');
|
|
$query->condition('p.pid', $person->booking_payment_id, '=')
|
|
->fields('p');
|
|
$result = $query->execute()->fetchObject();
|
|
//set the result
|
|
$total_due = $result->booking_late_price;
|
|
} else {
|
|
$total_due = $person->booking_late_price;
|
|
}
|
|
} //end payment type conditional
|
|
|
|
return $total_due;
|
|
}
|
|
|
|
|
|
/**
|
|
* Function to calculate the amount outstanding for a person/married couple
|
|
*
|
|
* @param $person - the object relating to the registration node
|
|
* @param $amount_paid - if we have previously calculated the amount paid, this can be passed as a value
|
|
* @param $include_fees - boolean to indicate whether we want the net amount or the amount owing including paypal or stripe fees
|
|
* @param $include_fees - boolean to indicate whether we want the fees for an international transaction
|
|
* @return amount owing as a decimal value
|
|
*/
|
|
function _booking_amount_owing($person, $amount_paid = 0, $include_fees = TRUE, $international_fees = FALSE) {
|
|
global $event;
|
|
//quick sanity check
|
|
if (! $person->nid) {
|
|
watchdog('booking', "Unable to find matching person relating to registration id. Details were '" . var_export($person, TRUE) . "' .");
|
|
return 0.00;
|
|
}
|
|
|
|
$total_due = _booking_total_due($person);
|
|
|
|
//if we didn't get the amount paid as a command line parameter, check it now
|
|
if ($amount_paid == 0) {
|
|
$amount_paid = _booking_amount_paid($person->nid, $person);
|
|
}
|
|
|
|
//check if there is anything outstanding
|
|
//use the original total amount required rather than the late-rate, to cater for people that paid before the late rate
|
|
if ($amount_paid >= $person->booking_total_pay_reqd) {
|
|
//watchdog('booking', "This person doesn't owe any money: @info", array('@info' => var_export($person, TRUE)));
|
|
return 0;
|
|
}
|
|
|
|
//if we're using paypal or stripe, add the transaction fee
|
|
$payment_processor_type = variable_get('booking_payment_processor', 0);
|
|
if ($include_fees == TRUE) {
|
|
if ($payment_processor_type == 0) {
|
|
$amount_owing = _booking_add_paypal_fees($total_due - $amount_paid, $person->booking_country);
|
|
}
|
|
elseif ($payment_processor_type == 1) {
|
|
if ($international_fees == FALSE) {
|
|
$amount_owing = _booking_add_stripe_fees($total_due - $amount_paid, $person->booking_country);
|
|
}
|
|
else {
|
|
$amount_owing = _booking_add_stripe_fees($total_due - $amount_paid, 'FakeCountry');
|
|
}
|
|
}
|
|
}
|
|
//otherwise we're using manual payment processing so don't add any fees
|
|
else {
|
|
$amount_owing = $total_due - $amount_paid;
|
|
}
|
|
return number_format($amount_owing, 2, '.', '');
|
|
}
|
|
|
|
/**
|
|
* Function to update the person object when a payment has been made
|
|
* payment details should be inserted into booking_payment prior to calling this function
|
|
*
|
|
* @param $person - the populated node object representing this person including related price information
|
|
* @param $payment_amount - the gross payment amount that is being processed
|
|
* @param $balance_payment - boolean to indicate if this transaction was to complete a payment
|
|
* @return nothing
|
|
*/
|
|
function _booking_process_person_payment($person, $payment_amount, $balance_payment) {
|
|
global $event;
|
|
|
|
//calculate their total payment amount
|
|
$total = $person->booking_amount_paid + $payment_amount;
|
|
|
|
//only recalculate their booking status if this is the initial payment, not a payment of the outstanding balance
|
|
if ($balance_payment == FALSE) {
|
|
watchdog('booking', 'Processing an initial payment. Booking status is currently ' . $person->booking_status);
|
|
if ($person->booking_status == 1) {
|
|
watchdog('booking', 'This registration has been manually assigned to the booked-in list.');
|
|
$status = 1;
|
|
}
|
|
elseif (_booking_check_bookings_full() == True || $person->booking_status == 2) {
|
|
watchdog('booking', 'This registration belongs on the waiting list.');
|
|
$status = 2;
|
|
}
|
|
else {
|
|
watchdog('booking', 'This registration made it to the booked-in list.');
|
|
$status = 1;
|
|
}
|
|
}
|
|
else {
|
|
//this is a balance payment
|
|
watchdog('booking', 'Processing a balance payment.');
|
|
//if this is a payment of outstanding balance, keep the booking_status the same
|
|
$status = $person->booking_status;
|
|
}
|
|
|
|
//update the database for this person
|
|
db_update('booking_person')
|
|
->fields(array(
|
|
'booking_amount_paid' => $total,
|
|
'booking_status' => $status,
|
|
))
|
|
->condition('nid', $person->nid)
|
|
->execute();
|
|
|
|
//handle workflow emails and spouse payment updates
|
|
_booking_postpayment_trigger($person->nid, $person, $balance_payment);
|
|
}
|
|
|
|
/**
|
|
* Function to handle any post-payment notification emails for either paypal or manual payment
|
|
* still a WIP
|
|
*
|
|
* @param $nid - the node ID relating to this person
|
|
* @param $person - the populated node object representing this person including related price information
|
|
* @param $balance_payment - boolean to indicate if this transaction was to complete a payment
|
|
* @return nothing
|
|
*/
|
|
function _booking_postpayment_trigger($nid, $person, $balance_payment)
|
|
{
|
|
global $event;
|
|
|
|
//If there is no outstanding balance, send a payment complete email
|
|
$amount_owing = _booking_amount_owing($person);
|
|
//if ($total >= $person->booking_total_pay_reqd)
|
|
if ($amount_owing == 0) {
|
|
//set the payment complete flag
|
|
db_update('booking_person')
|
|
->fields(array(
|
|
'booking_payment_complete' => 'Y',
|
|
))
|
|
->condition('nid', $nid)
|
|
->execute();
|
|
|
|
//this should always be a balance payment type email, since that tells the user that their payment is completed
|
|
_booking_registration_email($nid, TRUE);
|
|
|
|
//if we are combining payments, and this person has a linked spouse
|
|
if ((variable_get('booking_enable_combined_pricing', 0) == 1) && ($person->booking_partner_id > 0))
|
|
{
|
|
//check spouse booking_status and payment info
|
|
$spouse = db_select('booking_person', 'p')
|
|
->condition('p.nid', $person->booking_partner_id,'=')
|
|
->fields('p', array('booking_amount_paid', 'booking_status', 'booking_total_pay_reqd'))
|
|
->execute()
|
|
->fetchObject();
|
|
|
|
//update the spouse's status from "not paid" if required
|
|
$spouse_status = $spouse->booking_status == 0 ? 1 : $spouse->booking_status;
|
|
watchdog('booking', 'Setting status for spouse id !id to !new from !status', array('!id' => $person->booking_partner_id,
|
|
'!new' => $spouse_status, '!status' => $spouse->booking_status));
|
|
|
|
//set the spouse's payment required to be zero or equal to their previous payment total
|
|
$spouse_new_amount_reqd = $spouse->booking_amount_paid > 0 ? $spouse->booking_amount_paid : 0;
|
|
watchdog('booking', 'Setting amount owing for spouse id !id to !new from !old.', array('!id' => $person->booking_partner_id,
|
|
'!new' => $spouse_new_amount_reqd, '!old' => $spouse->booking_total_pay_reqd));
|
|
|
|
//update the database for this person
|
|
db_update('booking_person')
|
|
->fields(array(
|
|
'booking_total_pay_reqd' => $spouse_new_amount_reqd,
|
|
'booking_status' => $spouse_status,
|
|
'booking_payment_complete' => 'Y',
|
|
))
|
|
->condition('nid', $person->booking_partner_id)
|
|
->execute();
|
|
|
|
//send an email to the spouse
|
|
_booking_registration_email($person->booking_partner_id, TRUE);
|
|
}
|
|
/*
|
|
elseif (variable_get('booking_enable_combined_pricing', 0) == 1)
|
|
{
|
|
watchdog('booking', 'Combined pricing is enabled, but this person has a partner id of !id.', array('!id' => $person->booking_partner_id));
|
|
} //end spouse check
|
|
*/
|
|
}
|
|
//if this was an initial payment we might need to send a notification
|
|
elseif ($balance_payment == FALSE)
|
|
{
|
|
//send a notification email if we didn't automatically send one earlier
|
|
if (variable_get('booking_auto_confirm_email', 0) == 0)
|
|
{
|
|
_booking_registration_email($nid, FALSE);
|
|
}
|
|
}
|
|
else //this person still has an outstanding balance so just send a confirmation email
|
|
{
|
|
watchdog('booking', 'This balance payment was insufficient for !id to completely pay the total outstanding of !outstanding.',
|
|
array('!id' => $nid, '!outstanding' => $amount_owing));
|
|
//send the person an email thanking them for their partial payment
|
|
_booking_partialbalance_payment_email($nid);
|
|
//TODO: create an email specifically for partial-balance payments
|
|
//_booking_registration_email($nid, $balance_payment);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Function to process the amount to refund a person when they withdraw their registration
|
|
*
|
|
* @param $person - the populated node object representing this person including related price information
|
|
* @return amount to be refunded for this registration
|
|
*/
|
|
function _booking_process_refund($person)
|
|
{
|
|
global $event;
|
|
$refund = 0;
|
|
|
|
//calculate amount to be refunded
|
|
$paid = _booking_amount_paid($person->nid, $person);
|
|
if ($paid > 0)
|
|
{
|
|
//calculate the refund due
|
|
//don't include paypal fees in the deposit amount
|
|
$refund = $paid - _booking_deposit_amount($person, FALSE);
|
|
|
|
//if there is a spouse, subtract their deposit too
|
|
if (variable_get('booking_enable_combined_pricing', 0) == 1 && $person->booking_partner_id > 0) {
|
|
$refund = $refund - _booking_deposit_amount($person, FALSE);
|
|
}
|
|
|
|
}
|
|
|
|
watchdog('booking', "Processing refund due to !first !last. Calculated as $!refund",
|
|
array('!first' => $person->booking_firstname, '!last' => $person->booking_lastname, '!refund' => $refund));
|
|
|
|
//$refund_due = $person->booking_amount_paid - $refund;
|
|
if ($refund == 0)
|
|
{
|
|
//mark the refund as processed since no action is required and don't add an entry into the manual payments table
|
|
db_update('booking_person')
|
|
->fields(array(
|
|
'booking_refund_due' => 0,
|
|
'booking_refund_processed' => 'Y',
|
|
))
|
|
->condition('nid', $person->nid)
|
|
->execute();
|
|
}
|
|
else
|
|
{
|
|
//update booking_amount_paid
|
|
db_update('booking_person')
|
|
->fields(array(
|
|
'booking_refund_due' => $refund,
|
|
))
|
|
->condition('nid', $person->nid)
|
|
->execute();
|
|
|
|
//add manual payment entry for refund
|
|
$result = db_insert('booking_payment')
|
|
->fields(array(
|
|
'booking_person_nid' => $person->nid,
|
|
'booking_eventid' => $event->eid,
|
|
'booking_mc_gross' => $refund * -1,
|
|
'booking_mc_currency' => 'AUD',
|
|
'booking_mc_fee' => '0.00',
|
|
'booking_quantity' => 1,
|
|
'booking_invoice' => 'Refund',
|
|
'booking_payer_id' => '',
|
|
'booking_payment_date' => REQUEST_TIME,
|
|
'booking_payment_status' => '',
|
|
'booking_first_name' => $person->booking_firstname,
|
|
'booking_last_name' => $person->booking_lastname,
|
|
'booking_buyer_email' => '',
|
|
'booking_payer_status' => '',
|
|
'booking_item_name' => 'Refund',
|
|
'booking_ipn_track_id' => '',
|
|
))
|
|
->execute();
|
|
}
|
|
|
|
//return the amount to refund this person
|
|
return $refund;
|
|
}
|
|
|
|
/**
|
|
* Helper function to provide a list of columns in the booking_person table
|
|
* This will be used to select which fields to import/export to/from a CSV
|
|
*/
|
|
function _booking_get_person_fields() {
|
|
$list_of_columns = array();
|
|
$query = db_query('SHOW COLUMNS FROM {booking_person_view}');
|
|
$result = $query->fetchAll();
|
|
|
|
foreach ($result as $column) {
|
|
$field = $column->Field;
|
|
$list_of_columns[$field] = $field;
|
|
}
|
|
|
|
//watchdog('booking_debug', "<pre>Database columns for booking_person\n@info</pre>", array('@info' => print_r( $list_of_columns, true)));
|
|
return $list_of_columns;
|
|
}
|
|
|
|
/**
|
|
* Helper function to format registrations details for summary in the confirmation email
|
|
*/
|
|
function _booking_details_email_summary($node) {
|
|
|
|
//query for payment type description
|
|
$payment_description_query = db_select('booking_price', 'p')
|
|
->condition('p.pid', $node->booking_payment_id,'=')
|
|
->fields('p', array('booking_price_descrip'))
|
|
->execute()
|
|
->fetchObject();
|
|
|
|
//watchdog('booking', "Payment description: @info", array('@info' => var_export($payment_description_query, TRUE)));
|
|
|
|
$rows = array();
|
|
$rows[] = t('Registration Reference Number: !id', array('!id' => $node->nid));
|
|
$rows[] = t('Date/Time registered: !timestamp', array('!timestamp' => _booking_convert_ts($node->booking_timestamp)->format('j F, Y H:i')));
|
|
$rows[] = t('Name: !first !last', array('!first' => $node->booking_firstname, '!last' => $node->booking_lastname));
|
|
$rows[] = t('Gender: !gender', array('!gender' => $node->booking_gender == 'M' ? 'Male' : 'Female'));
|
|
$rows[] = t('Date of birth: !dob', array('!dob' => _booking_convert_ts($node->booking_dob)->format('d/m/Y')));
|
|
|
|
if (variable_get('booking_enable_earlyaccess_codes', 0) == 1) {
|
|
//look up the actual code since the booking_person node available at this time only has the primary key for that table
|
|
$earlyaccess_query = db_query("SELECT booking_earlyaccess_code FROM {booking_earlyaccess_codes} where cid = :code",
|
|
array(':code' => $node->booking_earlyaccess_code_id))
|
|
->fetchObject();
|
|
//only add the row if there was a result returned
|
|
if ($earlyaccess_query) {
|
|
$rows[] = t('Early Access Code: !code', array('!code' => $earlyaccess_query->booking_earlyaccess_code));
|
|
}
|
|
}
|
|
|
|
/*
|
|
if (variable_get('booking_enable_passport', 1) == 1) {
|
|
$rows[] = t('Passport Number: !value', array('!value' => $node->booking_passport_num));
|
|
$rows[] = t('Passport Expiry: !timestamp', array('!timestamp' => _booking_convert_ts($node->booking_passport_expiry_date)->format('d/m/Y')));
|
|
$rows[] = t('Passport Exact Issued Name: !value', array('!value' => $node->booking_passport_issue_name));
|
|
$rows[] = t('Passport Issue Location: !value', array('!value' => $node->booking_passport_issue_location));
|
|
}
|
|
*/
|
|
$rows[] = t('Email address: !email', array('!email' => $node->booking_email));
|
|
$rows[] = t('Home Phone Number: !home', array('!home' => $node->booking_phone));
|
|
$rows[] = t('Mobile Phone Number: !mob', array('!mob' => $node->booking_mobile));
|
|
$rows[] = t("Postal Address:\n!street\n!suburb !state !code\n!country",
|
|
array('!street' => $node->booking_street, '!suburb' => $node->booking_suburb,
|
|
'!state' => $node->booking_state, '!code' => $node->booking_postcode,
|
|
'!country' => $node->booking_country));
|
|
$rows[] = t('Ecclesia: !ecclesia', array('!ecclesia' => $node->booking_ecclesia));
|
|
$rows[] = t('Baptised: !ans', array('!ans' => ($node->booking_baptised == 'Y' ? 'Yes' : 'No')));
|
|
|
|
if (variable_get('booking_allow_couples', 1) == 1) {
|
|
$rows[] = t('Married: !ans', array('!ans' => ($node->booking_married == 'Y' ? 'Yes' : 'No')));
|
|
$rows[] = t("If married, attending partner's name: !name", array('!name' => $node->booking_partner_name));
|
|
}
|
|
|
|
if (variable_get('booking_enable_songchoice', 0) == 1) {
|
|
$rows[] = t('Song Choice: !song', array('!song' => $node->booking_song_choice));
|
|
}
|
|
if (variable_get('booking_enable_freestyle', 0) == 1) {
|
|
$rows[] = t('Freestyle: !text', array('!text' => $node->booking_freestyle_text));
|
|
}
|
|
if (variable_get('booking_enable_tshirts', 0) == 1) {
|
|
$rows[] = t('Hoodie Size: !size', array('!size' => $node->booking_shirt_size));
|
|
}
|
|
|
|
$rows[] = t('Emergency Contact Name: !contact', array('!contact' => $node->booking_guardian_name));
|
|
$rows[] = t('Emergency Contact Relationship: !relationship', array('!relationship' => $node->booking_guardian_type));
|
|
$rows[] = t('Emergency Contact Phone: !phone', array('!phone' => $node->booking_guardian_phone));
|
|
$rows[] = t('Emergency Contact Alternate Phone: !phone', array('!phone' => $node->booking_guardian_phone_alt));
|
|
//really don't need medicare number being emailed around
|
|
/*
|
|
if (variable_get('booking_enable_medicare', 1) == 1) {
|
|
$rows[] = t('Medicare Number: !medicare', array('!medicare' => $node->booking_medicare));
|
|
}
|
|
*/
|
|
if (variable_get('booking_enable_roommate', 0) == 1) {
|
|
$rows[] = t('Preferred room-mates: !room', array('!room' => $node->booking_room_mate1 . ' ' . $node->booking_room_mate2));
|
|
}
|
|
|
|
if (variable_get('booking_enable_helpareas', 1) == 1) {
|
|
$help_areas = '';
|
|
if ($node->booking_help_music)
|
|
$help_areas .= 'music: ' . $node->booking_help_music . ', ';
|
|
if ($node->booking_help_reading == 'Y')
|
|
$help_areas .= 'reading, ';
|
|
if ($node->booking_help_chairing == 'Y')
|
|
$help_areas .= 'chairing, ';
|
|
if ($node->booking_help_readgroup_lead == 'Y')
|
|
$help_areas .= 'reading group leading, ';
|
|
if ($node->booking_help_discussgroup_lead == 'Y')
|
|
$help_areas .= 'discussion group leading, ';
|
|
if ($node->booking_help_praying == 'Y')
|
|
$help_areas .= 'praying, ';
|
|
if ($node->booking_help_meditations == 'Y')
|
|
$help_areas .= 'meditations, ';
|
|
|
|
$rows[] = t('Help areas: !help', array('!help' => $help_areas));
|
|
}
|
|
|
|
if (variable_get('booking_enable_skills', 1) == 1) {
|
|
$skill_areas = '';
|
|
if ($node->booking_skills_builder == 'Y')
|
|
$skill_areas .= 'builder, ';
|
|
if ($node->booking_skills_cooking == 'Y')
|
|
$skill_areas .= 'cook, ';
|
|
if ($node->booking_skills_childminding == 'Y')
|
|
$skill_areas .= 'child minding, ';
|
|
if ($node->booking_skills_language == 'Y')
|
|
$skill_areas .= 'speaks languages: ' . $node->booking_skills_language_details . ', ';
|
|
if ($node->booking_skills_other == 'Y')
|
|
$skill_areas .= 'other skills: ' . $node->booking_skills_other_details . ', ';
|
|
$rows[] = t('Mission related skills: !value', array('!value' => $skill_areas));
|
|
$rows[] = t('Previous Mission Experience: !value', array('!value' => $node->booking_mission_experience_details));
|
|
}
|
|
|
|
$rows[] = t('Special Dietary Requirements: !dietary', array('!dietary' => $node->booking_dietary));
|
|
$rows[] = t('Special Medical Conditions: !medical', array('!medical' => $node->booking_medical_conditions));
|
|
$rows[] = t('Gross Amount Paid: !payment', array('!payment' => $node->booking_amount_paid));
|
|
$rows[] = t('Net Amount Due: !payment', array('!payment' => $node->booking_total_pay_reqd));
|
|
$rows[] = t('Payment Type: !payment', array('!payment' => $payment_description_query->booking_price_descrip));
|
|
|
|
foreach ($rows as $key => $value) {
|
|
$rows[$key] = wordwrap($value);
|
|
}
|
|
|
|
if(variable_get('booking_enable_html_mail', 0) == 1) {
|
|
return implode("\n<br />", $rows);
|
|
}
|
|
else {
|
|
return implode("\n", $rows);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper function to format travel form summary
|
|
*/
|
|
function _booking_travelform_email_summary($node) {
|
|
global $event;
|
|
$rows = array();
|
|
|
|
if (! empty($node->tid)) {
|
|
//look up the actual name if a boyfriend/girlfriend is defined
|
|
if ($node->booking_bf_gf_nid != 0) {
|
|
$query = db_query("Select booking_firstname, booking_lastname from {booking_person} where nid = :nid",
|
|
array(':nid' => $node->booking_bf_gf_nid))
|
|
->fetchObject();
|
|
$bf_gf = $query->booking_firstname . " " . $query->booking_lastname;
|
|
}
|
|
else {
|
|
$bf_gf = "N/A";
|
|
}
|
|
|
|
$rows[] = t('Name: !first !last', array('!first' => $node->booking_firstname, '!last' => $node->booking_lastname));
|
|
$rows[] = t('Transport Type: !transport', array('!transport' => $node->booking_transport_type));
|
|
|
|
if ($node->booking_transport_type == 'Flying') {
|
|
$rows[] = t('Catching the train to Study Week: !value',
|
|
array('!value' => $node->booking_transport_from_morriset_reqd == 1 ? 'Yes' : 'No'));
|
|
$rows[] = t('Inbound Flight Number: ' . $node->booking_flightnum_inbound);
|
|
$rows[] = t('Flight Arrival: !date', array('!date' => format_date($node->booking_flight_datetime_inbound, 'custom', 'd/m/Y H:i')));
|
|
$rows[] = t('Outbound Flight Number: ' . $node->booking_flightnum_outbound);
|
|
$rows[] = t('Flight Departure: !date', array('!date' => format_date($node->booking_flight_datetime_outbound, 'custom', 'd/m/Y H:i')));
|
|
}
|
|
|
|
$rows[] = t('Accommodation before Study Week Required: !value', array('!value' => $node->booking_accom_before_reqd == 1 ? 'Yes' : 'No'));
|
|
$rows[] = t('Accommodation after Study Week Required: !value', array('!value' => $node->booking_accom_after_reqd == 1 ? 'Yes' : 'No'));
|
|
|
|
//fields from booking_person
|
|
if (variable_get('booking_enable_dietary', 0) == 1) {
|
|
$rows[] = t('Special Dietary Requirements: ' . $node->booking_dietary);
|
|
}
|
|
|
|
if (variable_get('booking_enable_roommate', 0) == 1) {
|
|
$rows[] = t('Special Medical Conditions: ' . $node->booking_medical_conditions);
|
|
}
|
|
|
|
$rows[] = t('Boyfriend/Girlfriend: ' . $bf_gf);
|
|
$rows[] = t('Requested room mate(s): ' . $node->booking_room_mate1);
|
|
|
|
foreach ($rows as $key => $value) {
|
|
$rows[$key] = wordwrap($value);
|
|
}
|
|
} //end empty travel node check
|
|
//watchdog('booking_debug', "<pre>Travel form summary\n@info</pre>", array('@info' => print_r( $rows, true)));
|
|
|
|
if(variable_get('booking_enable_html_mail', 0) == 1) {
|
|
return implode("\n<br />", $rows);
|
|
}
|
|
else {
|
|
return implode("\n", $rows);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper function to format summary of reading group members, to be used as a token
|
|
*/
|
|
function _booking_readinggroup_email_listing($node) {
|
|
global $event;
|
|
$rows = array();
|
|
$header = array("First Name", "Last Name", "Phone Number");
|
|
$attributes = array("style" => "border-collapse: separate; border-spacing: 20px 0;");
|
|
|
|
//display study session data if enabled
|
|
if (variable_get('booking_enable_studygroups', 0) == 0) {
|
|
return implode("\n", $rows);
|
|
}
|
|
|
|
// Check for the reading group
|
|
$readinggroup_query = db_query("SELECT * FROM {booking_studygroup_list} WHERE booking_eventid = :eid AND booking_is_readinggroup = 'Y'",
|
|
array(':eid' => $event->eid));
|
|
$readinggroups = $readinggroup_query->fetchAllAssoc('sid');
|
|
|
|
if (! $readinggroups) {
|
|
return implode("\n", $rows);
|
|
}
|
|
|
|
foreach ($readinggroups as $readinggroup) {
|
|
//calculate the session references
|
|
$sessionid = "session" . $readinggroup->sid;
|
|
$roleid = $sessionid . "_role";
|
|
|
|
//check that this reading group session has been defined for this attendee and that they're a leader
|
|
if (!empty($node->$sessionid) && $node->$roleid == 1) {
|
|
watchdog('booking_debug', "<pre>Person is a leader of reading group @id \n@info</pre>",
|
|
array('@id' => $node->$sessionid, '@info' => print_r($readinggroup, true)));
|
|
|
|
$member_query = db_query("SELECT * FROM {booking_person_view} WHERE $sessionid = :sid ", array(':sid' => $node->$sessionid))->fetchAllAssoc('nid');
|
|
//watchdog('booking_debug', "<pre>Other people in reading group @id \n@info</pre>",
|
|
// array('@id' => $node->$sessionid, '@info' => print_r($member_query, true)));
|
|
|
|
foreach ($member_query as $member) {
|
|
$rows[] = array(
|
|
$member->booking_firstname,
|
|
$member->booking_lastname,
|
|
$member->booking_mobile,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Don't show an empty header row if there was no-one in the group
|
|
if (count($rows) < 1) {
|
|
return implode("\n", $rows);
|
|
}
|
|
|
|
// Use Drupal's table theming function to build the table if HTML email is enabled
|
|
if(variable_get('booking_enable_html_mail', 0) == 1) {
|
|
$table = theme('table', array('header' => $header, 'rows' => $rows, 'attributes' => $attributes));
|
|
watchdog('booking_debug', "<pre>Reading group table\n@info</pre>", array('@info' => print_r($table, true)));
|
|
return $table;
|
|
}
|
|
else {
|
|
return implode("\n", $rows);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper function to format summary of studygroup sessions to be used as a token
|
|
*/
|
|
function _booking_studygroup_email_summary($node) {
|
|
global $event;
|
|
$rows = array();
|
|
|
|
//display study session data if enabled
|
|
if (variable_get('booking_enable_studygroups', 0) == 0) {
|
|
return implode("\n", $rows);
|
|
}
|
|
|
|
//look up the titles of the study groups
|
|
$studygroups_query = db_query("SELECT * FROM {booking_studygroup_list} WHERE booking_eventid = :eid AND booking_is_readinggroup = 'N'",
|
|
array(':eid' => $event->eid));
|
|
$studygroups = $studygroups_query->fetchAllAssoc('sid');
|
|
|
|
foreach ($studygroups as $studygroup) {
|
|
//calculate the session references
|
|
$sessionid = "session" . $studygroup->sid;
|
|
$roleid = $sessionid . "_role";
|
|
|
|
//check that this study group session has been defined for this attendee
|
|
if (!empty($node->$sessionid)) {
|
|
//$rows[] = t($studygroup->booking_studygroup_descrip . ": Group " . $node->$sessionid . ", " . _booking_studygroup_role_lookup($node->$roleid));
|
|
|
|
$tokens = array(
|
|
'studygroup-descrip' => $studygroup->booking_studygroup_descrip,
|
|
'studygroup-weekday' => $studygroup->booking_studygroup_weekday,
|
|
'studygroup-explan' => $studygroup->booking_studygroup_explanation,
|
|
'studygroup-role' => _booking_studygroup_role_lookup($node->$roleid),
|
|
);
|
|
|
|
$list_element_text = variable_get('booking_studygroup_summary_li_text',
|
|
'You are a <b>[meta-booking:studygroup-role]</b> for group <b>[meta-booking:studygroup-descrip]</b>, which will occur on [meta-booking:studygroup-weekday]. ' .
|
|
'<br /><b>[meta-booking:studygroup-explan]</b>');
|
|
// Make sure there is only HTML in the admin-entered text
|
|
//$list_element_text = check_markup($list_element_text, 'full_html', '', FALSE);
|
|
$rows[] = token_replace($list_element_text, $tokens);
|
|
} // End checking for empty studygroup session
|
|
} // End foreach loop
|
|
|
|
foreach ($rows as $key => $value) {
|
|
$rows[$key] = wordwrap($value);
|
|
}
|
|
|
|
if(variable_get('booking_enable_html_mail', 0) == 1) {
|
|
// Turn the rows into an unordered list
|
|
$output = "\n<ul>\n";
|
|
foreach ($rows as $row) {
|
|
$output .= "\t<li>$row</li>\n";
|
|
}
|
|
$output .= "</ul>\n";
|
|
return $output;
|
|
}
|
|
else {
|
|
// Plain text so just separate by newline
|
|
return implode("\n", $rows);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper function to format information matching leaders and helpers, to be used as a token
|
|
*/
|
|
function _booking_leader_helper_email_summary($node) {
|
|
global $event;
|
|
$rows = array();
|
|
$tokens = array();
|
|
$found = FALSE;
|
|
|
|
//display study session data if enabled
|
|
if (variable_get('booking_enable_studygroups', 0) == 1) {
|
|
//look up the titles of the study groups
|
|
$studygroups_query = db_query("SELECT * FROM {booking_studygroup_list} WHERE booking_eventid = :eid AND booking_is_readinggroup = 'N'",
|
|
array(':eid' => $event->eid));
|
|
$studygroups = $studygroups_query->fetchAllAssoc('sid');
|
|
|
|
foreach ($studygroups as $studygroup) {
|
|
//don't print info about the readings groups
|
|
if ($studygroup->booking_is_readinggroup == 'Y') {
|
|
continue;
|
|
}
|
|
|
|
//calculate the session references
|
|
$sessionid = "session" . $studygroup->sid;
|
|
$roleid = $sessionid . "_role";
|
|
$otherperson_name = "TBA";
|
|
$otherperson_email = "";
|
|
$otherperson_phone = "";
|
|
|
|
//check that this study group session has been defined for this attendee and that they have a role to perform
|
|
if (!empty($node->$sessionid) && $node->$roleid > 0) {
|
|
//if they're a leader or reserve leader, then the matching person is the helper
|
|
if ($node->$roleid == 1 || $node->$roleid == 3) {
|
|
$role = "Leader";
|
|
$otherrole = "Helper";
|
|
$otherrole_id = 2;
|
|
}
|
|
//otherwise the matching person is the leader
|
|
else {
|
|
$role = "Helper";
|
|
$otherrole = "Leader";
|
|
$otherrole_id = 1;
|
|
}
|
|
|
|
//find the other person
|
|
$otherperson_query = db_query("SELECT m.*, p.* FROM {booking_studygroup_mapping} m " .
|
|
" INNER JOIN {booking_person} p on m.booking_node_id = p.nid " .
|
|
" WHERE p.booking_eventid = :eid " .
|
|
" AND booking_studygroup_id = :group AND booking_studygroup_role = :role AND booking_session_id = :session",
|
|
array(':eid' => $event->eid, ':group' => $studygroup->sid, ':role' => $otherrole_id, ':session' => $node->$sessionid,
|
|
));
|
|
$otherperson = $otherperson_query->fetchAll();
|
|
|
|
//watchdog('booking', "<pre>Other person for studygroup !group and role !role result:\n@info</pre>",
|
|
// array('!group' => $studygroup->sid, '!role' => $otherrole_id, '@info' => print_r( $otherperson, true)));
|
|
|
|
//create the text for the token
|
|
foreach ($otherperson as $other) {
|
|
$otherperson_name = $other->booking_firstname . ' ' . $other->booking_lastname;
|
|
$otherperson_email = $other->booking_email;
|
|
$otherperson_phone = $other->booking_mobile;
|
|
}
|
|
|
|
// Generate tokens
|
|
$tokens = array(
|
|
'studygroup-descrip' => $studygroup->booking_studygroup_descrip,
|
|
'studygroup-weekday' => $studygroup->booking_studygroup_weekday,
|
|
'studygroup-explan' => $studygroup->booking_studygroup_explanation,
|
|
'studygroup-role' => $role,
|
|
'studygroup-otherrole' => $otherrole,
|
|
'studygroup-othername' => $otherperson_name,
|
|
'studygroup-otheremail' => $otherperson_email,
|
|
'studygroup-otherphone' => $otherperson_phone,
|
|
);
|
|
|
|
$list_element_text = variable_get('booking_studygroup_leaderhelperpair_text',
|
|
'<b>[meta-booking:studygroup-role]</b> for <b>[meta-booking:studygroup-descrip]</b>. ' .
|
|
'Your [meta-booking:studygroup-otherrole] is <b>[meta-booking:studygroup-othername]</b>. ' .
|
|
'You can contact them on [meta-booking:studygroup-otherphone] or [meta-booking:studygroup-otheremail].'
|
|
);
|
|
// Make sure there is only HTML in the admin-entered text
|
|
//$list_element_text = check_markup($list_element_text, 'full_html', '', FALSE);
|
|
$rows[] = token_replace($list_element_text, $tokens);
|
|
}
|
|
}
|
|
}
|
|
|
|
//format the output to be used in an email
|
|
foreach ($rows as $key => $value) {
|
|
$rows[$key] = wordwrap($value);
|
|
}
|
|
if(variable_get('booking_enable_html_mail', 0) == 1) {
|
|
// Turn the rows into an unordered list
|
|
$output = "\n<ul>\n";
|
|
foreach ($rows as $row) {
|
|
$output .= "\t<li>$row</li>\n";
|
|
}
|
|
$output .= "</ul>\n";
|
|
return $output;
|
|
}
|
|
else {
|
|
// Plain text so just separate by newline
|
|
return implode("\n", $rows);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper function to format summary of room allocation to be used as a token
|
|
*/
|
|
function _booking_room_email_summary($node) {
|
|
global $event;
|
|
$rows = array();
|
|
|
|
//display study session data if enabled
|
|
if (variable_get('booking_enable_roomallocations', 0) == 1)
|
|
{
|
|
//check that this attendee has had a room allocated
|
|
if (! empty($node->rid))
|
|
{
|
|
//$rows[] = t("Room Location: " . _booking_room_location_lookup($node->booking_room_location_id));
|
|
$rows[] = t("Room Location: " . $node->booking_roomlocation_descrip);
|
|
$rows[] = t("Room Number: " . $node->booking_room_number);
|
|
$rows[] = t("Bed Type: " . _booking_room_bedtype_lookup($node->booking_room_bedtype));
|
|
}
|
|
else
|
|
$rows[] = t("\tNo room currently allocated.");
|
|
}
|
|
|
|
foreach ($rows as $key => $value) {
|
|
$rows[$key] = wordwrap($value);
|
|
}
|
|
|
|
if(variable_get('booking_enable_html_mail', 0) == 1) {
|
|
return implode("\n<br />", $rows);
|
|
}
|
|
else {
|
|
return implode("\n", $rows);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper function to create the mean, median, mode or average of an array
|
|
* @see http://www.phpsnips.com/45/Mean,-Median,-Mode,-Range-Of-An-Array
|
|
*/
|
|
function _booking_mmmr($array, $output = 'mean'){
|
|
if(!is_array($array)) {
|
|
return FALSE;
|
|
}
|
|
else {
|
|
switch($output){
|
|
case 'mean':
|
|
$count = count($array);
|
|
$sum = array_sum($array);
|
|
$total = $sum / $count;
|
|
break;
|
|
case 'median':
|
|
rsort($array);
|
|
$middle = round(count($array) / 2);
|
|
$total = $array[$middle-1];
|
|
break;
|
|
case 'mode':
|
|
$v = array_count_values($array);
|
|
arsort($v);
|
|
foreach($v as $k => $v){$total = $k; break;}
|
|
break;
|
|
case 'range':
|
|
sort($array);
|
|
$sml = $array[0];
|
|
rsort($array);
|
|
$lrg = $array[0];
|
|
$total = $lrg - $sml;
|
|
break;
|
|
}
|
|
return $total;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Generates a Universally Unique IDentifier, version 4.
|
|
*
|
|
* This function generates a truly random UUID. The built in CakePHP String::uuid() function
|
|
* is not cryptographically secure. You should uses this function instead.
|
|
*
|
|
* @see http://tools.ietf.org/html/rfc4122#section-4.4
|
|
* @see http://en.wikipedia.org/wiki/UUID
|
|
* @return string A UUID, made up of 32 hex digits and 4 hyphens.
|
|
*/
|
|
function _booking_uuidSecure() {
|
|
|
|
$pr_bits = null;
|
|
$fp = @fopen('/dev/urandom','rb');
|
|
if ($fp !== false) {
|
|
$pr_bits .= @fread($fp, 16);
|
|
@fclose($fp);
|
|
} else {
|
|
// If /dev/urandom isn't available (eg: in non-unix systems), use mt_rand().
|
|
$pr_bits = "";
|
|
for($cnt=0; $cnt < 16; $cnt++) {
|
|
$pr_bits .= chr(mt_rand(0, 255));
|
|
}
|
|
}
|
|
|
|
$time_low = bin2hex(substr($pr_bits,0, 4));
|
|
$time_mid = bin2hex(substr($pr_bits,4, 2));
|
|
$time_hi_and_version = bin2hex(substr($pr_bits,6, 2));
|
|
$clock_seq_hi_and_reserved = bin2hex(substr($pr_bits,8, 2));
|
|
$node = bin2hex(substr($pr_bits,10, 6));
|
|
|
|
/**
|
|
* Set the four most significant bits (bits 12 through 15) of the
|
|
* time_hi_and_version field to the 4-bit version number from
|
|
* Section 4.1.3.
|
|
* @see http://tools.ietf.org/html/rfc4122#section-4.1.3
|
|
*/
|
|
$time_hi_and_version = hexdec($time_hi_and_version);
|
|
$time_hi_and_version = $time_hi_and_version >> 4;
|
|
$time_hi_and_version = $time_hi_and_version | 0x4000;
|
|
|
|
/**
|
|
* Set the two most significant bits (bits 6 and 7) of the
|
|
* clock_seq_hi_and_reserved to zero and one, respectively.
|
|
*/
|
|
$clock_seq_hi_and_reserved = hexdec($clock_seq_hi_and_reserved);
|
|
$clock_seq_hi_and_reserved = $clock_seq_hi_and_reserved >> 2;
|
|
$clock_seq_hi_and_reserved = $clock_seq_hi_and_reserved | 0x8000;
|
|
|
|
return sprintf('%08s-%04s-%04x-%04x-%012s',
|
|
$time_low, $time_mid, $time_hi_and_version, $clock_seq_hi_and_reserved, $node);
|
|
}
|