function merci_node_validate in MERCI (Manage Equipment Reservations, Checkout and Inventory) 6
Same name and namespace in other branches
- 6.2 merci.module \merci_node_validate()
Implementation of hook_validate().
1 string reference to 'merci_node_validate'
- merci_form_alter in ./
merci.module - Implementation of hook_form_alter().
File
- ./
merci.module, line 2188 - MERCI - Managed Equipment Reservation Checkout and Inventory
Code
function merci_node_validate($form, &$form_state) {
if (user_access('suspend MERCI access') && !user_access('administer MERCI')) {
form_set_error('merci_status', t('Your access to make new Reservations or edit existing Reservations has been suspended.'));
}
else {
$node = (object) $form_state['values'];
// No validation necessary on deletion.
if ($form_state['clicked_button']['#id'] != 'edit-delete') {
// Reservations with a checked out status.
if ($node->merci_status == MERCI_STATUS_CHECKED_OUT) {
// Make sure all existing bucket reservations have an item assigned.
if (isset($node->existing_items['items'])) {
foreach ($node->existing_items['items'] as $did => $item_nid) {
if (!$item_nid) {
form_set_error("existing_items][items][{$did}", t("The bucket reservation must have an item associated with it for finalized reservations."));
}
}
}
else {
form_set_error('merci_status', t('You can not finalize a reservation that has no reserved items.'));
}
// Can't add a bucket item and finalize at the same time.
foreach ($node->choice as $num => $choice) {
$item = $choice['item'];
if ($item && !is_numeric($item)) {
form_set_error("choice][{$num}][item", t("You cannot finalize a reservation while adding a bucket item."));
}
}
}
// Build date objects we'll need for our different validations.
$start = $node->field_merci_date[0]['value'];
$end = $node->field_merci_date[0]['value2'];
$start_object = merci_create_local_date_object($start);
$end_object = merci_create_local_date_object($end);
$hours_of_operation = merci_load_hours_of_operation();
$start_day_of_week = (int) date_format($start_object, 'w');
$end_day_of_week = (int) date_format($end_object, 'w');
$start_month_day = date_format($start_object, 'm-d');
$end_month_day = date_format($end_object, 'm-d');
$start_hours = $hours_of_operation[$start_day_of_week];
$end_hours = $hours_of_operation[$end_day_of_week];
$start_date = date_format($start_object, 'm-d-Y');
$max_days = variable_get("merci_max_days_advance_reservation", '0');
//Users in role with Administer MERCI permssion are exempt from content type and hours of operation restrictions
if (user_access('administer MERCI') || user_access('create reservations outside hours of operation')) {
drupal_set_message(t('You may be making a Reservation outside the normal hours of operation. This may impact access to the items you are reserving.'));
}
else {
// Reservation start date cannot exceed the max advance
if ($max_days) {
$max_date = new DateTime("+{$max_days} day");
if ($start_object > $max_date) {
form_set_error('merci_status', t('You cannot make a Reservation more than %days days in advance. Start the Reservation before %date.', array(
'%days' => $max_days,
'%date' => date_format($max_date, 'm-d-Y'),
)));
}
}
// Can't start or end a reservation on days that are
// closed dates.
if (in_array($start_month_day, $hours_of_operation['closed_days'])) {
$name = date_format($start_object, 'F jS');
form_set_error('field_merci_date][0][value][date', t('Sorry, but we are closed on %day for a holiday or special event.', array(
'%day' => $name,
)));
}
if (in_array($end_month_day, $hours_of_operation['closed_days'])) {
$name = date_format($end_object, 'F jS');
form_set_error('field_merci_date][0][value2][date', t('Sorry, but we are closed on %day for a holiday or special event.', array(
'%day' => $name,
)));
}
// Can't start or end a reservation on a day the facility
// has no hours of operation, or outside hours of operation.
$start_name = date_format($start_object, 'l');
if (!$hours_of_operation[$start_day_of_week]) {
form_set_error('field_merci_date][0][value][date', t('Reservations cannot start on a %day.', array(
'%day' => $start_name,
)));
}
else {
$start_time = date_format($start_object, 'H:i');
if ($start_time < $start_hours['open']) {
form_set_error('field_merci_date][0][value][time', t('Reservations cannot start on a %day before %start.', array(
'%day' => $start_name,
'%start' => merci_format_time($start_hours['open']),
)));
}
elseif ($start_time > $start_hours['close']) {
form_set_error('field_merci_date][0][value][time', t('Reservations cannot start on a %day after %end.', array(
'%day' => $start_name,
'%end' => merci_format_time($start_hours['close']),
)));
}
}
$end_name = date_format($end_object, 'l');
if (!$hours_of_operation[$end_day_of_week]) {
form_set_error('field_merci_date][0][value2][date', t('Reservations cannot end on a %day.', array(
'%day' => $end_name,
)));
}
else {
$end_time = date_format($end_object, 'H:i');
if ($end_time < $end_hours['open']) {
form_set_error('field_merci_date][0][value2][time', t('Reservations cannot end on a %day before %start.', array(
'%day' => $end_name,
'%start' => merci_format_time($end_hours['open']),
)));
}
elseif ($end_time > $end_hours['close']) {
form_set_error('field_merci_date][0][value2][time', t('Reservations cannot end on a %day after %end.', array(
'%day' => $end_name,
'%end' => merci_format_time($end_hours['close']),
)));
}
}
}
// Tests for existing items.
if (isset($node->nid)) {
// For saved reservations, include the items already reserved
// in the available list.
$options = merci_build_reservable_items($node, $form_state, $node->nid);
}
else {
$options = merci_build_reservable_items($node, $form_state);
}
$flat_options = $options['flat_options'];
if (isset($node->existing_items)) {
// Check each reserved item.
foreach ($node->existing_items['bucket_resource'] as $did => $value) {
// The item is no longer reservable, so figure out why.
if (!in_array($value, $flat_options)) {
// Resource.
if (is_numeric($value)) {
$new_item = db_fetch_object(db_query("SELECT title, type FROM {node} WHERE nid = %d", $value));
$title = $new_item->title;
$type = $new_item->type;
}
elseif ($value) {
$title = db_result(db_query("SELECT name FROM {node_type} WHERE type = '%s'", $value));
$type = $value;
}
// Make sure the item still passes content type restrictions.
$restrictions = merci_check_content_type_restrictions($type, $start, $end);
if (!empty($restrictions)) {
$message = '';
foreach ($restrictions as $restriction) {
$message .= '<div>' . strtr($restriction, array(
'%name' => theme('placeholder', $title),
)) . '</div>';
}
}
else {
$message = t("The existing reservation for %name is no longer reservable with your current date settings.", array(
'%name' => $title,
));
}
form_set_error("existing_items][placeholders][{$did}", $message);
}
elseif (!is_numeric($value)) {
$bucket_items = array_keys(merci_get_available_bucket_items($node, $value));
$assigned_item = (int) $node->existing_items['items'][$did];
if ($assigned_item && !in_array($assigned_item, $bucket_items)) {
$title_name = db_fetch_object(db_query("SELECT n.title, nt.name FROM {node} n INNER JOIN {node_type} nt ON n.type = nt.type WHERE n.nid = %d", $assigned_item));
form_set_error("existing_items][placeholders][{$did}", t("The assignment of %item for the %bucket reservation is no longer reservable with your current date settings.", array(
'%item' => $title_name->title,
'%bucket' => $title_name->name,
)));
}
}
}
}
// Tests for new items.
if (isset($node->nid)) {
// Only need to rebuild this again for existing nodes.
$options = merci_build_reservable_items($node, $form_state);
$flat_options = $options['flat_options'];
}
// Check each new item.
foreach ($node->choice as $num => $choice) {
// The item is no longer reservable, so figure out why.
if ($choice['item'] && !in_array($choice['item'], $flat_options)) {
// Resource.
if (is_numeric($choice['item'])) {
$new_item = db_fetch_object(db_query("SELECT title, type FROM {node} WHERE nid = %d", $choice['item']));
$title = $new_item->title;
$type = $new_item->type;
}
elseif ($choice['item']) {
$title = db_result(db_query("SELECT name FROM {node_type} WHERE type = '%s'", $choice['item']));
$type = $choice['item'];
}
// Make sure the item still passes content type restrictions.
$restrictions = merci_check_content_type_restrictions($type, $start, $end);
if (!empty($restrictions)) {
$message = '';
foreach ($restrictions as $restriction) {
$message .= '<div>' . strtr($restriction, array(
'%name' => theme('placeholder', $title),
)) . '</div>';
}
}
else {
$count_sql = "SELECT COUNT(n.nid) \n FROM {node} n \n JOIN {merci_node_type} t\n ON t.type = n.type\n WHERE n.status = 1 AND\n (\n (\n t.type_setting = 'bucket'\n AND n.type = '%s'\n ) OR\n (\n t.type_setting = 'resource'\n AND n.title = '%s'\n )\n )";
$count = db_result(db_query($count_sql, $type, $title));
$start_mysql = date('Y-m-d', strtotime($start));
$end_mysql = date('Y-m-d', strtotime($end . ' +1 day'));
$reservations = merci_load_reservations_for_type_in_timespan($type, $start_mysql, $end_mysql);
$reservations_by_date = array();
$hours = merci_load_hours_of_operation();
$message = '<div> ' . t("The dates and times for %name conflict with one or more existing reservations", array(
'%name' => $title,
)) . '</div>';
$message .= '<div class="merci-availability-key"><span class="available"></span> = available <span class="unavailable"></span> = unavailable</div>';
foreach ($reservations as $date => $times) {
$date_timestamp = strtotime($date);
$hours_date = $hours[date('w', $date_timestamp)];
if (user_access('administer MERCI') || user_access('create reservations outside hours of operation')) {
$adminhours = explode('-', variable_get('merci_hours_admin', '07:00-23:00'));
$hours_date['open'] = $adminhours[0];
$hours_date['close'] = $adminhours[1];
}
if (isset($hours_date['open'])) {
$message .= '<table class="merci-availability-schedule"><thead><tr>';
$message .= '<th>' . date('m/d/Y', $date_timestamp) . '</th>';
$time = $hours_date['open'];
while ($time < $hours_date['close']) {
$message .= '<th colspan="4">' . date('g:i a', strtotime($time)) . '</th>';
$time = date('H:i', strtotime($time . ' +1 hour'));
}
$message .= '</tr></thead><tbody>';
for ($i = 1; $i <= $count; $i++) {
$message .= '<tr><th>' . htmlspecialchars($title);
if ($count > 1) {
$message .= ' ' . $i . '/' . $count;
}
$message .= '</th>';
$time = $hours_date['open'];
while ($time < $hours_date['close']) {
if ($times[$time . ':00'] >= $i) {
$message .= '<td class="unavailable"></td>';
}
else {
$message .= '<td class="available"></td>';
}
$time = date('H:i', strtotime($time . ' +15 minutes'));
}
// while
$message .= '</tr>';
}
// for
$message .= '</tbody></table>';
}
// if
}
// foreach
}
form_set_error("choice][{$num}][item", $message);
}
}
//if message wasn't set by a validation function
if (!$message) {
drupal_set_message(t('There are no conflicts with this Reservation.'));
}
// Prevent status changes on reservations that have past.
$current_status = db_result(db_query("SELECT m.status FROM {node} n INNER JOIN {merci_reservation} m ON n.vid = m.vid WHERE n.nid = %d", $node->nid));
if ($current_status && $current_status != $node->merci_status && time() > strtotime($node->field_merci_date[0]['value2']) && !in_array((int) $node->merci_status, array(
MERCI_STATUS_CANCELLED,
MERCI_STATUS_CHECKED_IN,
MERCI_STATUS_DENIED,
))) {
$statuses = merci_record_status();
form_set_error('merci_status', t('You cannot change the status to %status for a reservation that has past.', array(
'%status' => $statuses[$node->merci_status],
)));
}
}
}
}