AppStateESS/homestead

View on GitHub
class/LotteryApplication.php

Summary

Maintainability
D
2 days
Test Coverage
<?php

namespace Homestead;

use \Homestead\Exception\DatabaseException;
use \PHPWS_Error;
use \PHPWS_DB;

/**
 * Lottery Application - Model to represent a lottery re-application
 * for continuing students.
 *
 * @author Jeremy Booker <jbooker at tux dot appstate dot edu>
 * @package hms
*/
class LotteryApplication extends HousingApplication {

    public $magic_winner        = 0;
    public $invited_on          = NULL;

    // Date the student opted-into the waiting list
    public $waiting_list_date;

    // This variable is set to the name of the special interest group
    // *IF AND ONLY IF* and student is approved for that group
    public $special_interest    = NULL;

    // These are preferences input by the student on the application form.
    // They don't necessarily mean a student has been approved by a group.
    public $sorority_pref;
    //public $tf_pref;
    public $wg_pref;
    public $honors_pref;
    public $rlc_interest;

    public $early_release;

    // Static variable for waiting list position calculation
    private static $waitingList;

    /**
     * Constructor
     * @param number $id
     * @param string $term
     * @param string $banner_id
     * @param string $username
     * @param string $gender
     * @param string $student_type
     * @param string $application_term
     * @param string $cell_phone
     * @param string $meal_plan
     * @param string $international
     * @param string $specialInterest
     * @param number $magicWinner
     * @param string $sororityPref
     * @param string $wgPref
     * @param string $honorsPref
     * @param string $rlcInterest
     * @param string $earlyRelease
     */
    public function __construct($id = 0, $term = NULL, $banner_id = NULL, $username = NULL, $gender = NULL, $student_type = NULL, $application_term = NULL, $cell_phone = NULL, $meal_plan = NULL, $international = NULL, $specialInterest = NULL, $magicWinner = 0, $sororityPref = NULL, $wgPref = NULL, $honorsPref = NULL, $rlcInterest = NULL, $earlyRelease = NULL)
    {
        /**
         * If the id is non-zero, then we need to load the other member variables
         * of this object from the database
         */
        if($id != 0){
            $this->id = (int)$id;
            $this->load();
            return;
        }

        $this->application_type = 'lottery';

        parent::__construct($term, $banner_id, $username, $gender, $student_type, $application_term, $cell_phone, $meal_plan, $international);

        $this->special_interest = $specialInterest;
        $this->magic_winner = $magicWinner;

        $this->sorority_pref  = $sororityPref;
        //$this->tf_pref        = $tfPref;
        $this->wg_pref        = $wgPref;
        $this->honors_pref    = $honorsPref;
        $this->rlc_interest   = $rlcInterest;

        $this->early_release = $earlyRelease;
    }

    /**
     * Loads the LotteryApplication object with the corresponding id. Requires that $this->id be non-zero.
     */
    protected function load()
    {
        if($this->id == 0){
            return;
        }

        # Load the core application data using the parent class
        if(!parent::load()){
            return false;
        }

        # Load the application-specific data
        $db = new PHPWS_DB('hms_lottery_application');

        if(PHPWS_Error::logIfError($db->loadObject($this))){
            $this->id = 0;
            throw new DatabaseException($result->toString());
        }

        return true;
    }

    /**
     * Saves this object
     */
    public function save()
    {
        $is_new = $this->getId() == 0 ? true : false;

        # Save the core application data using the parent class
        if(!parent::save()){
            return false;
        }

        # Save the application-specific data
        $db = new PHPWS_DB('hms_lottery_application');

        /* If this is a new object, call saveObject with the third parameter as 'false' so
         * the database class will insert the object with the ID set by the parent::save() call.
        * Otherwise, call save object as normal so that the database class will detect the ID and
        * update the object.
        */
        if($is_new){
            $result = $db->saveObject($this, false, false);
        }else{
            $result = $db->saveObject($this);
        }

        if(PHPWS_Error::logIfError($result)){
            throw new DatabaseException($result->toString());
        }

        return true;
    }

    /**
     * (non-PHPdoc)
     * @see HousingApplication::delete()
     */
    public function delete()
    {
        $db = new PHPWS_DB('hms_lottery_application');
        $db->addWhere('id', $this->id);
        $result = $db->delete();
        if(!$result || PHPWS_Error::logIfError($result)){
            return $result;
        }

        if(!parent::delete()){
            return false;
        }

        return TRUE;
    }

    /**
     * Returns true is this LotteryApplication has received an invite
     * and that invite hasn't expired.
     *
     * @return boolean
     */
    public function isWinner()
    {
        $ttl = INVITE_TTL_HRS * 3600;

        if(!is_null($this->invited_on) && ($this->invited_on + $ttl) > time()){
            return true;
        }else{
            return false;
        }
    }

    /**
     * @return integer position of this LotteryApplication in the on-campus waiting list.
     */
    public function getWaitListPosition()
    {
        if(!isset(self::$waitingList)){
            self::$waitingList = self::getRemainingWaitListApplications($term = $this->getTerm());
        }

        $position = array_search($this->getUsername(), self::$waitingList);

        if($position === FALSE){
            return 'unknown';
        }

        // Fix the off-by-one indexing
        return $position + 1;
    }

    /**
     * Row tags for waiting list pager.
     *
     * @return Array Array of row tags for this LotteryApplication.
     */
    public function getRowTags(){
        $student = StudentFactory::getStudentByUsername($this->username, $this->term);

        $template = array();

        $template['ASU_USERNAME']        = $student->getProfileLink();

        $form = new \PHPWS_Form('clear_disabilities');
        $form->addHidden('da_clear', $this->asu_username);
        $form->addHidden('type',     'lottery');
        $form->addHidden('op',       'view_lottery_needs');
        $form->addSubmit('clear',    'Clear Disabilities');

        $tpl = $form->getTemplate();
        $template = array_merge($template, $tpl);

        return $template;
    }

    /**
     * Returns an array of row tags for the speical interest group DBPager
     * @return multitype:string NULL
     */
    public function specialInterestTags()
    {
        $this->load($this->id);
        $student = StudentFactory::getStudentByUsername($this->username, $this->term);

        $tags = array();

        $tags['NAME']       = $student->getProfileLink();
        $tags['USER']       = $this->username;
        $tags['BANNER_ID']  = $student->getBannerId();

        if(is_null($this->special_interest)){
            // Student HAS NOT been accepted to group, show accept link.
            $acceptCmd = CommandFactory::getCommand('AcceptSpecialInterest');
            $acceptCmd->setId($this->id);
            $acceptCmd->setGroup($_REQUEST['group']); // TODO: find a better way of doing this
            $tags['ACTION']     = $acceptCmd->getLink('Accept');
        }else{
            // Student HAS been accepted, show remove link.
            $removeCmd = CommandFactory::getCommand('RemoveSpecialInterest');
            $removeCmd->setId($this->id);
            $removeCmd->setGroup($_REQUEST['group']); // TODO: find a better way of doing this
            $tags['ACTION'] = $removeCmd->getLink('Remove');
            $tags['ROW_CLASS'] = 'accepted';
        }

        return $tags;
    }

    /**
     * Row fields for CSV export of special interest group DBPager.
     * @return unknown
     */
    public function specialInterestCsvRow()
    {
        $student = StudentFactory::getStudentByUsername($this->username, $this->term);
        $tags = array();

        $tags['NAME']       = $student->getFullName();
        $tags['USER']       = $this->username;
        $tags['BANNER_ID']  = $student->getBannerId();

        return $tags;
    }

    /**
     * Returns row tags for waiting list pager
     * @return Array <number, string>
     */
    public function waitingListTags()
    {
        $student = StudentFactory::getStudentByUsername($this->username, $this->term);

        $tags = array();

        $tags['POSITION']   = $this->getWaitListPosition();
        $tags['NAME']       = $student->getProfileLink();
        $tags['USER']       = $this->username;
        $tags['BANNER_ID']  = $student->getBannerId();
        $tags['CLASS']      = $student->getPrintableClass();

        if(isset($this->cell_phone) && !is_null($this->cell_phone) && $this->cell_phone != ''){
            $tags['PHONE']      = '('.substr($this->cell_phone, 0, 3).')';
            $tags['PHONE']      .= substr($this->cell_phone, 3, 3);
            $tags['PHONE']      .= '-'.substr($this->cell_phone, 6, 4);
        }

        $tags['GENDER']     = $student->getPrintableGender();
        $tags['APP_DATE'] = date("n/j/Y h:ia", $this->getWaitingListDate());

        $assign_link = \PHPWS_Text::secureLink('[Assign]','hms', array('module'=>'hms', 'action'=>'ShowAssignStudent', 'username'=>$this->username));
        $remove_link = \PHPWS_Text::secureLink('[Remove]','hms', array('module'=>'hms', 'action'=>'WaitingListRemove', 'username'=>$this->username));
        $tags['ACTION']     = "$assign_link $remove_link";

        return $tags;
    }

    /**
     * Returns array tags for waiting list DBPager csv export.
     * @return Array
     */
    public function waitingListCsvTags()
    {
        $student = StudentFactory::getStudentByUsername($this->username, $this->term);

        $tags = array();

        $tags['NAME']       = $student->getFulLName();
        $tags['USER']       = $this->username;
        $tags['BANNER_ID']  = $student->getBannerId();
        $tags['CLASS']      = $student->getPrintableClass();
        $tags['GENDER']     = $student->getPrintableGender();
        $tags['APPLICATION_TERM'] = $student->getApplicationTerm();
        $tags['APPLICATION_DATE'] = date("n/j/Y h:ia", $this->getCreatedOn());
        $tags['WAITINGLIST_DATE'] = date("n/j/Y h:ia", $this->getWaitingListDate());

        if(isset($this->cell_phone) && !is_null($this->cell_phone) && $this->cell_phone != ''){
            $tags['PHONE']      = '('.substr($this->cell_phone, 0, 3).')';
            $tags['PHONE']      .= substr($this->cell_phone, 3, 3);
            $tags['PHONE']      .= '-'.substr($this->cell_phone, 6, 4);
        }

        return $tags;
    }

    /*****
     * Getters and setters.
     */
    public function getSororityPref(){
        return $this->sorority_pref;
    }

    public function getTeachingFellowsPref(){
        return $this->tf_pref;
    }

    public function getWataugaGlobalPref(){
        return $this->wg_pref;
    }

    public function getHonorsPref(){
        return $this->honors_pref;
    }

    public function setSororityPref($pref){
        $this->sorority_pref = $pref;
    }
    public function setTeachingFellowsPref($pref){
        $this->tf_pref = $pref;
    }

    public function setWataugaGlobalPref($pref){
        $this->wg_pref = $pref;
    }

    public function setHonorsPref($pref){
        $this->honors_pref = $pref;
    }

    /**
     * @return integer Unixtimestamp that the student opted into the waiting list
     */
    public function getWaitingListDate()
    {
        return $this->waiting_list_date;
    }

    /**
     * Sets the date (unix timestamp) that the student opted into the waiting list
     *
     * @param integer $timestamp
     */
    public function setWaitingListDate($timestamp)
    {
        $this->waiting_list_date = $timestamp;
    }




    /******************
     * Static Methods *
     */

    /**
     * Special Interest Group DBPager for lottery
     *
     * @param unknown $group
     * @param unknown $term
     * @throws \InvalidArgumentException
     */
    public static function specialInterestPager($group, $term)
    {
        $pager = new \DBPager('hms_new_application', '\Homestead\LotteryApplication');
        $pager->setModule('hms');
        $pager->addRowTags('specialInterestTags');

        $pager->db->addJoin('left outer', 'hms_new_application', 'hms_lottery_application', 'id', 'id');
        // Gotta add column from hms_lottery_application so you can order by special_interest.
        $pager->db->addColumn('hms_lottery_application.*');
        $pager->addWhere('hms_new_application.term', $term);

        // If student is in special interest group already then only show them in the list when their group
        // is selected in the drop down. Or show them everywhere is they're not in a group.
        $pager->addWhere('hms_lottery_application.special_interest', $group, '=', 'OR', 'in_group');
        $pager->addWhere('hms_lottery_application.special_interest', 'NULL', '=', 'OR', 'in_group');

        if($group == 'honors'){
            $pager->addWhere('hms_lottery_application.honors_pref', 1);
        }else if($group == 'watauga_global'){
            $pager->addWhere('hms_lottery_application.wg_pref', 1);
        }else if($group == 'teaching'){
            $pager->addWhere('hms_lottery_application.tf_pref', 1);
        }else if(substr($group, 0, 8) == 'sorority'){ // starts with 'sorority'
            $pager->addWhere('hms_lottery_application.sorority_pref', $group);
        }else{
            // bad group
            throw new \InvalidArgumentException('Invalid special interest group specified.');
        }

        $pager->setOrder('hms_lottery_application.special_interest', 'desc');
        $pager->setTemplate('admin/special_interest_pager.tpl');
        $pager->setEmptyMessage('No students found.');
        $pager->setReportRow('specialInterestCsvRow');

        return $pager->get();
    }

    /**
     * Waiting List pager for On-campus Waiting List
     * @return string HTML for pager
     */
    public static function waitingListPager()
    {
        $term = \PHPWS_Settings::get('hms', 'lottery_term');

        $pager = new \DBPager('hms_new_application', '\Homestead\LotteryApplication');
        $pager->db->addColumn('hms_new_application.*');
        $pager->db->addColumn('hms_lottery_application.*');
        $pager->db->addJoin('LEFT', 'hms_new_application', 'hms_lottery_application', 'id', 'id');
        $pager->db->addJoin('LEFT OUTER', 'hms_new_application', 'hms_assignment', 'username', 'asu_username AND hms_new_application.term = hms_assignment.term');
        $pager->db->addWhere('hms_assignment.asu_username', 'NULL');
        $pager->db->addWhere('hms_new_application.term', $term);
        $pager->db->addWhere('hms_new_application.cancelled', 0);
        $pager->db->addWhere('hms_lottery_application.special_interest', 'NULL');
        $pager->db->addWhere('hms_lottery_application.waiting_list_date', 'NULL', '!=');

        // Order by class, then by application ID in order to keep a fixed order
        // This accounts for the 'you are x of y students' message on the student's menu
        $pager->db->addOrder(array('application_term DESC', 'hms_new_application.id ASC'));

        $pager->setModule('hms');
        $pager->setTemplate('admin/lottery_wait_list_pager.tpl');
        $pager->setEmptyMessage('No students found.');
        $pager->addPageTags(array('TITLE'=>'Re-application Waiting List - ' . Term::toString($term)));
        $pager->addRowTags('waitingListTags');
        $pager->setReportRow('waitingListCsvTags');
        $pager->setSearch('hms_new_application.username', 'hms_new_application.banner_id');

        return $pager->get();
    }

    /**
     * Returns a list of usernames which are currently on the waiting list
     * (has a valid housing application, not assigned)
     *
     * @param unknown $term
     * @throws DatabaseException
     * @return unknown
     */
    public static function getRemainingWaitListApplications($term)
    {
        // Get the list of user names still on the waiting list, sorted by ID (first come, first served)
        $sql = "SELECT username FROM hms_new_application JOIN hms_lottery_application ON hms_new_application.id = hms_lottery_application.id
                    LEFT OUTER JOIN (SELECT asu_username FROM hms_assignment WHERE hms_assignment.term=$term) as foo ON hms_new_application.username = foo.asu_username
                    WHERE foo.asu_username IS NULL
                    AND hms_new_application.term = $term
                    AND special_interest IS NULL
                    AND waiting_list_date IS NOT NULL
                    ORDER BY application_term DESC, hms_new_application.id ASC";

        $applications = PHPWS_DB::getCol($sql);

        if(PHPWS_Error::logIfError($applications)){
            throw new DatabaseException($applications->toString());
        }

        return $applications;
    }
}