class/Floor.php
<?php
namespace Homestead;
use \Homestead\Exception\DatabaseException;
use \PHPWS_Error;
use \PHPWS_DB;
/**
* HMS Floor class
*
* @author Jeremy Booker <jbooker at tux dot appstate dot edu>
* Some code copied from:
* @author Kevin Wilcox <kevin at tux dot appstate dot edu>
*/
class Floor extends HMS_Item
{
public $term;
public $floor_number;
public $residence_hall_id;
public $is_online;
public $gender_type;
public $f_movein_time_id;
public $t_movein_time_id;
public $rt_movein_time_id;
public $rlc_id;
public $floor_plan_image_id;
/**
* List of rooms associated with this floor
* @vary array
*/
public $_rooms = null;
/**
* Holds the parent residence hall object of this floor
*/
public $_hall = null;
/**
* Constructor
*/
public function __construct($id = 0)
{
parent::__construct($id, 'hms_floor');
}
public function getDb()
{
return new PHPWS_DB('hms_floor');
}
/********************
* Instance Methods *
*******************/
/**
* Saves a new or updated floor hall object
*/
public function save()
{
$db = new PHPWS_DB('hms_floor');
$result = $db->saveObject($this);
if(!$result || PHPWS_Error::logIfError($result)) {
throw new DatabaseException($result->toString());
}
}
/**
* Copies this floor object to a new term, then calls copy on all
* 'this' floor's rooms
*
* Setting $assignments to 'true' causes the copy public function to copy
* the assignments as well as the hall structure.
*
* @return bool False if unsuccessful.
*/
public function copy($to_term, $hall_id, $assignments = false, $roles = false)
{
if(!$this->id) {
return false;
}
//echo "in hms_floor, copying this floor id: $this->id <br>";
// Create a clone of the current floor object
// Set id to 0, set term, and save
$new_floor = clone($this);
$new_floor->reset();
$new_floor->term = $to_term;
$new_floor->residence_hall_id = $hall_id;
$new_floor->f_movein_time_id = null;
$new_floor->t_movein_time_id = null;
$new_floor->rt_movein_time_id = null;
try{
$new_floor->save();
}catch(\Exception $e) {
throw $e;
}
// Copy any roles related to this floor.
if($roles) {
// Get memberships by object instance.
$membs = HMS_Permission::getUserRolesForInstance($this);
// Add each user to new floor
foreach($membs as $m) {
// Lookup the username
$user = new \PHPWS_User($m['user_id']);
// Load role and add user to new instance
$role = new HMS_Role();
$role->id = $m['role'];
$role->load();
$role->addUser($user->getUsername(), get_class($new_floor), $new_floor->id);
}
}
// Load all the rooms for this floor
if(empty($this->_rooms)) {
try{
$this->loadRooms();
}catch(\Exception $e) {
throw $e;
}
}
/**
* Rooms exist. Start making copies.
* Further copying is needed at the room level.
*/
if(!empty($this->_rooms)) {
foreach ($this->_rooms as $room) {
try{
$room->copy($to_term, $new_floor->id, null, $assignments);
}catch(\Exception $e) {
throw $e;
}
}
}
}
public function getLink($prependText = null)
{
$floorCmd = CommandFactory::getCommand('EditFloorView');
$floorCmd->setFloorId($this->id);
if(!is_null($prependText)) {
$text = $prependText . ' ' . $this->floor_number;
} else {
$text = $this->floor_number;
}
return $floorCmd->getLink($text);
}
/**
* Loads the parent hall object of this floor
*/
public function loadHall()
{
$result = new ResidenceHall($this->residence_hall_id);
if(PHPWS_Error::logIfError($result)) {
throw new DatabaseException($result->toString());
}
$this->_hall = & $result;
return true;
}
/**
* Pulls all the rooms associated with this floor and stores
* them in the _room variable.
*/
public function loadRooms()
{
$db = PdoFactory::getPdoInstance();
$sql = "SELECT *
FROM hms_room
WHERE floor_id = :id
ORDER BY room_number ASC";
$sth = $db->prepare($sql);
$sth->execute(array('id' => $this->id));
$this->_rooms = $sth->fetchAll(\PDO::FETCH_CLASS, '\Homestead\RoomRestored');
return true;
}
/**
* Creates the rooms and beds for a new floor
*/
public function create_child_objects($rooms_per_floor, $beds_per_room)
{
for ($i = 0; $i < $rooms_per_floor; $i++) {
$room = new Room;
$room->floor_id = $this->id;
$room->term = $this->term;
$room->gender_type = $this->gender_type;
if($room->save()) {
$room->create_child_objects($beds_per_room);
} else {
// Decide on bad Result.
}
}
}
/**
* Returns true or false.
*
* This public function uses the following logic:
*
* When ignore_upper = true (a hall is trying to see if this floor can be changed to a target gender):
* If the target gender is COED: always return true, since it doesn't matter what the rooms are (or what the hall is)
* If the target gender is MALE: return false if any room is female and non-empty
* If the target gender is FEMALE: return false if any room is male and non-empty
* If all thsoe checks pass, then return true
*
* When ignore_upper = false (we're trying to change *this* floor to a target gender):
* If the target gender is COED: return true only if the hall is COED (but it doesn't matter what the rooms are)
* If the target gender is MALE: return false if the hall is female, or if there are any female rooms on the floor
* If the target gender is FEMALE: return false if the hall is male, or if there are any male rooms on the floor
*
* @param int target_gender
* @param bool ignore_upper
* @return bool
*/
public function can_change_gender($target_gender, $ignore_upper = false)
{
// Ignore upper is true, we're trying to change a hall's gender
if($ignore_upper) {
// If ignore upper is true and the target gender is coed, then
// we can always return true.
if($target_gender == COED) {
return true;
}
// Can only change to male/female if there are no rooms of the opposite sex on this hall
// TODO: This should check for rooms that are of the opposite sex AND not empty
if($target_gender == MALE) {
$check_for_gender = FEMALE;
} else {
$check_for_gender = MALE;
}
// If a check for rooms of the opposite gender returns true, then return false
if($this->check_for_rooms_of_gender($check_for_gender)) {
return false;
}
} else {
// Ignore upper is false, load the hall and compare
if(!$this->loadHall()) {
// an error occured loading the hall
return false;
}
// The target gender must match the hall's gender, unless the hall is COED
if($this->_hall->gender_type != COED && $this->_hall->gender_type != $target_gender) {
return false;
}
// Additionally, we need to check for rooms of the oppsite sex, unless the target gender is COED
if($target_gender != COED) {
// If a check for rooms of the opposite gender returns true, then return false
if($this->checkForOtherRoomGenders($target_gender)) {
return false;
}
}
}
return true;
}
public function check_for_rooms_of_gender($gender_type)
{
$db = PdoFactory::getPdoInstance();
$sql = "SELECT hms_room.id
FROM hms_room
LEFT JOIN hms_floor
ON floor_id = hms_floor.id
WHERE hms_floor.id = :id AND hms_room.gender_type = :gender";
$sth = $db->prepare($sql);
$sth->execute(array('id' => $this->id, 'gender' => $gender_type));
$result = $sth->rowCount();
if($result == 0) {
return false;
} else {
return true;
}
}
/**
* Returns true if there are any rooms on this floor set to a gender
* *other than* the specificed gender.
*
* @param Integer $gender
* @return boolean
* @throws DatabaseException
*/
public function checkForOtherRoomGenders($gender)
{
$db = PdoFactory::getPdoInstance();
$sql = "SELECT hms_room.id
FROM hms_room
LEFT JOIN hms_floor
ON floor_id = hms_floor.id
WHERE hms_floor.id = :id AND hms_room.gender_type != :gender";
$sth = $db->prepare($sql);
$sth->execute(array('id' => $this->id, 'gender' => $gender));
$result = $sth->rowCount();
if($result > 0) {
return true;
} else {
return false;
}
}
public function getUsernames()
{
$db = PdoFactory::getPdoInstance();
$sql = "SELECT hms_assignment.asu_username
FROM hms_assignment
LEFT JOIN hms_bed
ON bed_id = hms_bed.id
LEFT JOIN hms_room
ON room_id = hms_room.id
LEFT JOIN hms_floor
ON floor_id = hms_floor.id
WHERE hms_floor.id = :id";
$sth = $db->prepare($sql);
$sth->execute(array('id' => $this->id));
$result = $sth->fetchAll(\PDO::FETCH_COLUMN);
return $result;
}
public function getFloorNumber()
{
return $this->floor_number;
}
/*
* Returns the number of rooms on the current floor
*/
public function get_number_of_rooms()
{
$db = PdoFactory::getPdoInstance();
$sql = "SELECT hms_room.id
FROM hms_room
LEFT JOIN hms_floor
ON floor_id = hms_floor.id
WHERE hms_floor.id = :id";
$sth = $db->prepare($sql);
$sth->execute(array('id' => $this->id));
$result = $sth->rowCount();
return $result;
}
/*
* Returns the number of beds on the current floor
*/
public function get_number_of_beds()
{
$db = PdoFactory::getPdoInstance();
$sql = "SELECT hms_bed.id
FROM hms_bed
LEFT JOIN hms_room
ON room_id = hms_room.id
LEFT JOIN hms_floor
ON floor_id = hms_floor.id
WHERE hms_floor.id = :id";
$sth = $db->prepare($sql);
$sth->execute(array('id' => $this->id));
$result = $sth->rowCount();
return $result;
}
public function countNominalBeds()
{
$db = PdoFactory::getPdoInstance();
$sql = "SELECT hms_bed.id
FROM hms_bed
LEFT JOIN hms_room
ON room_id = hms_room.id
LEFT JOIN hms_floor
ON floor_id = hms_floor.id
WHERE hms_floor.id = :id AND hms_room.offline = 0 AND hms_room.overflow = 0 AND hms_room.parlor = 0";
$sth = $db->prepare($sql);
$sth->execute(array('id' => $this->id));
$result = $sth->rowCount();
return $result;
}
/*
* Returns the number of assignees on the current floor
*/
public function get_number_of_assignees()
{
$db = PdoFactory::getPdoInstance();
$sql = "SELECT hms_assignment.id
FROM hms_assignment
LEFT JOIN hms_bed
ON bed_id = hms_bed.id
LEFT JOIN hms_room
ON room_id = hms_room.id
LEFT JOIN hms_floor
ON floor_id = hms_floor.id
WHERE hms_floor.id = :id";
$sth = $db->prepare($sql);
$sth->execute(array('id' => $this->id));
$result = $sth->rowCount();
return $result;
}
/*
* Returns the parent hall object of this floor
*/
public function get_parent()
{
$this->loadHall();
return $this->_hall;
}
/*
* Returns an array of the rooms on the current floor
*/
public function get_rooms()
{
if(!$this->loadRooms()) {
return false;
}
return $this->_rooms;
}
/**
* Returns an associative array where the keys are room ID's
* and the values are the room numbers.
*/
public function get_rooms_array()
{
if(!$this->loadRooms()) {
return false;
}
$rooms = array();
foreach($this->_rooms as $room) {
$rooms[$room->id] = $room->room_number;
}
return $rooms;
}
/**
* Returns an array of the bed on the current floor
*
* @return Array An array of Bed objects that exist on the current floor.
*/
public function get_beds()
{
$beds = array();
if(!$this->loadRooms()) {
return false;
}
foreach($this->_rooms as $room) {
$room_beds = $room->get_beds();
$beds = array_merge($beds, $room_beds);
}
return $beds;
}
/**
* Returns an array of student objects which are currently assigned to this floor
*/
public function get_assignees()
{
if(!$this->loadRooms()) {
return false;
}
$assignees = array();
if(!isset($this->_rooms))
{
return $assignees;
}
foreach($this->_rooms as $room) {
$room_assignees = $room->get_assignees();
$assignees = array_merge($assignees, $room_assignees);
}
return $assignees;
}
/**
* Returns true if this floor has vancancies, false otherwise
*
* @return bool True if the floor has vacancies, false otherwise.
*/
public function has_vacancy()
{
if($this->get_number_of_assignees() < $this->get_number_of_beds()) {
return true;
}
return false;
}
/**
* Returns an array of room objects on this floor that have vacancies
*
* @return Array<Room> An array of Room objects which are vacant on this floor.
*/
public function getRoomsWithVacancies()
{
if(!$this->loadRooms()) {
return false;
}
$vacant_rooms = array();
foreach($this->_rooms as $room) {
if($room->has_vacancy()) {
$vacant_rooms[] = $room;
}
}
return $vacant_rooms;
}
public function where_am_i($link = false)
{
$building = $this->get_parent();
$text = $building->hall_name . ', Floor ' . $this->floor_number;
if($link) {
$editFloorCmd = CommandFactory::getCommand('EditFloorView');
$editFloorCmd->setFloorId($this->id);
return $editFloorCmd->getLink($text);
}else{
return $text;
}
}
public function count_avail_lottery_rooms($gender, $rlcId = null)
{
$now = time();
$db = PdoFactory::getPdoInstance();
// Calculate the number of non-full male/female rooms in this hall
$query = "SELECT DISTINCT COUNT(hms_room.id) FROM hms_room
JOIN hms_bed ON hms_bed.room_id = hms_room.id
JOIN hms_floor ON hms_room.floor_id = hms_floor.id
WHERE (hms_bed.id NOT IN (SELECT bed_id FROM hms_lottery_reservation WHERE term = :term AND expires_on > :now)
AND hms_bed.id NOT IN (SELECT bed_id FROM hms_assignment WHERE term = :term))
AND hms_floor.id = :id
AND hms_floor.rlc_id IS null
AND hms_floor.is_online = 1
AND hms_room.gender_type IN (:gender, 3)
AND hms_room.reserved = 0
AND hms_room.offline = 0
AND hms_room.private = 0
AND hms_room.overflow = 0
AND hms_room.parlor = 0 ";
$params = array('id' => $this->id, 'term' => $this->term, 'now' => $now, 'gender' => $gender);
if($rlcId != null) {
$query .= "AND hms_room.reserved_rlc_id = $rlcId ";
}else {
$query .= "AND hms_room.reserved_rlc_id IS NULL ";
}
$query .= "AND hms_bed.international_reserved = 0
AND hms_bed.ra = 0
AND hms_bed.ra_roommate = 0";
$sth = $db->prepare($query);
$sth->execute($params);
$avail_rooms = $sth->fetch(\PDO::FETCH_COLUMN);
return $avail_rooms;
}
public function get_pager_by_hall_tags()
{
$tpl = array();
$tpl['FLOOR_NUMBER'] = $this->getLink();
$tpl['GENDER_TYPE'] = HMS_Util::formatGender($this->gender_type);
$tpl['IS_ONLINE'] = $this->is_online ? 'Yes' : 'No';
return $tpl;
}
/******************************
* Accessor / Mutator Methods *
*/
public function getId()
{
return $this->id;
}
public function getTerm()
{
return $this->term;
}
public function isOnline()
{
if($this->is_online == 1){
return true;
}
return false;
}
//TODO lots more here
/******************
* Static Methods *
*****************/
public static function get_pager_by_hall($hall_id)
{
$pager = new \DBPager('hms_floor', '\Homestead\Floor');
$pager->addWhere('hms_floor.residence_hall_id', $hall_id);
$pager->db->addOrder('hms_floor.floor_number');
$pager->setModule('hms');
$pager->setTemplate('admin/floor_pager_by_hall.tpl');
$pager->setLink('index.php?module=hms');
$pager->setEmptyMessage("No floors found.");
$pager->addRowTags('get_pager_by_hall_tags');
return $pager->get();
}
}