This room reservation system was designed for a bed and breakfast. It is written on top of FuelPHP and builds out a reservation form, email template system, and vacancy dates. The email system notifies the owner of a reservation request, the owner can then follow links with authentication tokens to approve or deny the request, which sends a templated email to the requester. The approved requests are tallied and provide date availability feedback for full occupancy factoring in the number of rooms requested. It is designed to keep the owner interaction with the system at a minimal, intentionally lacking a login and calendar management system, these tasks should be automated as much as possible.

app/classes/controller/booking.php

<?php

/**
 * The Booking Controller.
 *
 * Handles all aspects of the room reservation request system.
 * 
 * 
 * @package  app
 * @extends  Controller
 */
class Controller_Booking extends Controller {
	
	
	/**
	 * The index action.
	 * 
	 * @access  public
	 * @return  void
	 */
	public function action_index()
	{	
		$showform = 1;
		if(Input::post()){
			$post = Input::post();
			$showform = 0;
			$post['auth_key'] = sha1(microtime(true).mt_rand(10000,90000));
			$stored = $post;
			
			//store the reservation request
			unset($stored['submit']);
			$stored['approved'] = '0';
			$stored['checkin'] = strtotime($stored['checkin']);
			$stored['checkout'] = strtotime($stored['checkout']);
			$this->store_reservations($stored);
			
			//notify the user of reservation request
			$this->send_notify((object) $post);
		}
		//create the view
        $view = View::factory('booking/index');

        //assign views as variables
        $view->header = View::factory('default/header',array('page_title'=>'Express Reservation System'));
        if($showform == 1){
       		$view->booking_form = View::factory('booking/forms/booking');
        }
        else{
        	$view->booking_form = 'Thank you, your request will be reviewed and you will be contacted shortly.';
        }
		$view->footer = View::factory('default/footer');
		$view->fullnights = $this->get_full_nights(1);	
        //assign to browser output
        $this->response->body = $view;	
	
	}
	
	public function action_approve(){
		$requests = $this->get_future();
		foreach($requests as $k=>$r){
			if($r['auth_key']==Input::get('auth_key')){
				$requests[$k]['approved'] = 1;
				$match = $requests[$k];
			}
		}
		File::update(APPPATH.'tmp/', 'reservations.json', json_encode($requests), $area = null);
		
		if(isset($match)){
			$from = array('someone@somewhere.tld'=>'Name');
			$to = array($match['email']=>$match['name']);
			$subject = "Online reservation request";
			
			$body = View::factory('booking/emails/approve');
			$body->post = $match;
			
			$email = Email::forge();
			$email->to($to);
			$email->from($from);
			$email->subject($subject);
			$email->body($body->render());
			$email->send();	
			
			$reminders = View::factory('booking/tables/future');
			$reminders->pending = $this->get_future();
			$this->response->body = $reminders;
		}
	}
	
	public function action_deny(){
		$requests = $this->get_future();
		foreach($requests as $k=>$r){
			if($r['auth_key']==Input::get('auth_key')){
				$requests[$k]['approved'] = -1;
				$match = $requests[$k];
			}
		}
		File::update(APPPATH.'tmp/', 'reservations.json', json_encode($requests), $area = null);
		if(isset($match)){		
			$from = array('someone@somewhere.tld'=>'Name');
			$to = array($match['email']=>$match['name']);
			$subject = "Online reservation request";
			
			$body = View::factory('booking/emails/deny');
			$body->post = $match;
			
			$email = Email::forge();
			$email->to($to);
			$email->from($from);
			$email->subject($subject);
			$email->body($body->render());
			$email->send();	
			
			$reminders = View::factory('booking/tables/future');
			$reminders->pending = $this->get_future();
			$this->response->body = $reminders;
		}
	}
	
	private function send_notify($post){
		$from = array($post->email=>$post->name);
		$to = array("someone@somewhere.tld"=>"Name",'someone2@somewhere.tld'=>'Name2');
		$subject = "Online reservation request";
		
		$body = View::factory('booking/emails/notify');
		$body->post = $post;
		
		$reminders = View::factory('booking/tables/future');
		$reminders->pending = $this->get_future();
		$body->reminders = $reminders;
		
		$email = Email::forge();
		$email->to($to);
		$email->from($from);
		$email->subject($subject);
		$email->body($body->render());
		$email->send();		
		return true;
	}
	
	private function get_future(){
		$resarray = array();
		if(is_file(APPPATH.'tmp/reservations.json')){
			$reservations = File::read(APPPATH.'tmp/reservations.json',true);
			$resarray = json_decode($reservations,true);
		}
		
		foreach($resarray as $key=>$row){
			if($row['checkout']<s;date('U')){
				unset($resarray[$key]);
			}
		}
		$new = json_encode($resarray);
		File::update(APPPATH.'tmp/', 'reservations.json', $new, $area = null);
		return $resarray;
	}
	
	private function store_reservations($data){
		$resarray = array();
		if(is_file(APPPATH.'tmp/reservations.json')){
			$reservations = File::read(APPPATH.'tmp/reservations.json',true);
			$resarray = json_decode($reservations,true);
		}
		$resarray[] = $data;
		$new = json_encode($resarray);

		return File::update(APPPATH.'tmp/', 'reservations.json', $new, $area = null);
	}
	
	public function action_getoccupancy(){
		$rooms = Input::get('rooms');
		if(!$rooms){
			$rooms = 1;
		}
		$occupancy = $this->get_full_nights((int)$rooms);
		$this->response->body = json_encode($occupancy);
	}
	
	public function get_full_nights($rooms = 1){
		$bookings = $this->get_future();
		$checkins = $checkouts = $fullnights = array();
		foreach($bookings as $b){
			
			if($b['approved']=='1'){
				$checkdate = date('Ymd',$b['checkin']);
				while((int)$checkdate < (int) date('Ymd',$b['checkout'])){
					if(isset($checkins[$checkdate])){
						$checkins[$checkdate] = $b['rooms'] + $checkins[$checkdate];
					}
					else{
						$checkins[$checkdate] = $b['rooms'];
					}
					
					$checkdate++;
				}
			}
			
		}
		foreach($bookings as $b){
			
			if($b['approved']=='1'){
				$checkdate = date('Ymd',$b['checkout']);
				while((int)$checkdate > (int) date('Ymd',$b['checkin'])){
					if(isset($checkouts[$checkdate])){
						$checkouts[$checkdate] = $b['rooms'] + $checkouts[$checkdate];
					}
					else{
						$checkouts[$checkdate] = $b['rooms'];
					}
					
					$checkdate--;
				}
			}
			
		}		
		$fullnights['in'] = array();
		foreach($checkins as $k=>$c){
			if($c >= (4-$rooms)){

				$fullnights['in'][] = (string)$k;
				
			}
		}
		$fullnights['out'] = array();
		foreach($checkouts as $k=>$c){
			if($c >= (4-$rooms)){

				$fullnights['out'][] = (string)$k;
				
			}
		}
		return $fullnights;
	}
	
}