/models/election.php
PHP | 422 lines | 310 code | 52 blank | 60 comment | 102 complexity | 8c6b27bd1f5eccf0b5af7cb24fc66a7e MD5 | raw file
- <?php
- /**
- * Model for election database table.
- *
- * Copyright (c) 2013 Janne Seppänen, Antti Ranta, Matias Ylipelto
- * This program is made available under the terms of the MIT License.
- */
- class Election_Model extends Model
- {
- protected $idColumn = 'electionId';
- protected $tableName = 'election';
-
- //States
- const STATE_CLOSED = 0;
- const STATE_ACTIVE = 1;
- const STATE_ENDED = 2;
- const STATE_HISTORY = 3;
-
- //Result calculation options
- const CALCULATE_COALITIONS = 1;
- const NO_COALITIONS = 0;
-
- const ONLY_ONE_OPEN_ELECTION_ALLOWED = -2;
- const TOTAL_SEATS = 74; //37*2
-
- /**
- * Fetches the current ongoing election
- *
- * Return type can be chosen:
- * 'array' = returns all the database information about the election as an associative array
- * 'id' = returns the election id field value
- *
- * @param string $returnType
- * @return array|int|boolean
- */
- public function fetchCurrentElection($returnType = 'array')
- {
- $sql = "SELECT electionId, name, status, startDate, endDate, calcMethod\n".
- "FROM {$this->tableName}\n".
- "WHERE status='".self::STATE_ACTIVE."' AND startDate < NOW() AND endDate > NOW()\n".
- "LIMIT 1";
-
- if(!in_array($returnType, array('id', 'array')))
- die("Return type '{$returnType}' was not valid.");
-
- switch ($returnType) {
- case 'array':
- $electionArr = $this->fetchQueryResults($sql, array('singleRow' => true));
- if(!$electionArr)
- return false;
- return $electionArr;
- break;
- case 'id':
- $electionId = $this->fetchQueryResults($sql, array('fetchColumn' => 0));
- if(!$electionId)
- return false;
- return $electionId;
- break;
- }
-
- }
-
-
- /**
- * Fetches the current closed, open and ended elections
- *
- * @return array|int|boolean
- */
- public function fetchActiveElections()
- {
- $sql = "SELECT electionId, name, status, startDate, endDate, calcMethod\n".
- "FROM {$this->tableName}\n".
- "WHERE (status=? OR status=? OR status=?)";
-
- $paramArr = array(Election_Model::STATE_ACTIVE, Election_Model::STATE_CLOSED, Election_Model::STATE_ENDED);
- $result = $this->fetchQueryResults($sql,null,$paramArr);
- if(!$result)
- return false;
- return $result;
- }
-
- public function fetchPastElections()
- {
- $sql = "SELECT electionId, name, status, startDate, endDate,\n".
- "calcMethod, totalWwwVotes, totalPaperVotes, \n".
- "(SELECT SUM(votes + paperVotes) FROM candidate WHERE candidateNum=? AND candidate.election=election.electionId) ".
- "AS emptyVotes\n". //,
- //"IF((totalWwwVotes + totalPaperVotes) > 0, (totalWwwVotes + totalPaperVotes) / ".
- //"(SELECT COUNT(*) FROM voter WHERE canVote=? AND hasVoted > 0 AND election=electionId), 0) ".
- //"AS voterTurnout \n".
- "FROM {$this->tableName} WHERE status=?";
-
- $paramArr = array(Candidate_Model::EMPTY_VOTE,/* Voter_Model::HAS_VOTING_RIGHT,*/ Election_Model::STATE_HISTORY);
- $result = $this->fetchQueryResults($sql,null,$paramArr);
- if(!$result)
- return false;
- return $result;
- }
-
- /**
- * This method handles updating and inserting election data.
- *
- * This method cannot be used to modify these fields: name, status, startDate, startTime, endDate, endTime
- *
- * @param array $electionArr
- * @param int $electionId
- * @return int
- */
- public function updateElection($electionArr, $electionId = 0)
- {
- $electionId = (int)$electionId;
- $startDate = date('Y-m-d', strtotime($electionArr['startDate'])).' ';
- $startDate .= date('H:i:s', strtotime($electionArr['startTime']));
- $endDate = date('Y-m-d', strtotime($electionArr['endDate'])).' ';
- $endDate .= date('H:i:s', strtotime($electionArr['endTime']));
- $name = htmlspecialchars($electionArr['name'], ENT_QUOTES, "UTF-8");
-
- $paramArr = array('name'=>$name, 'startDate'=>$startDate,'endDate'=>$endDate, 'status'=>(int)$electionArr['status'], 'calcMethod'=>(int)$electionArr['calcMethod']);
- $sql = "name, startDate, endDate, status, calcMethod";
-
- $this->beginTransaction();
-
- //check that there are no other open elections than this
- if($electionArr['status'] == self::STATE_ACTIVE){
- $activeElections = $this->fetchByField('status', Election_Model::STATE_ACTIVE);
-
- if($activeElections != false && count($activeElections) > 0){
- $found = false;
- foreach($activeElections as $activeElection){
- if($activeElection['electionId'] == $electionId){
- $found = true;
- break;
- }
- }
- if(!$found){
- $this->rollBack();
- return self::ONLY_ONE_OPEN_ELECTION_ALLOWED;
- }
- }//if2
- }
-
- if($electionId == 0) { //Insert a new record
- if($this->insertInto($sql, $paramArr) == false) {
- $this->rollBack();
- return parent::FAILURE;
- }
- $id = $this->lastInsertId();
-
- //insert empty vote
- $candidateModel = new Candidate_Model;
- if($candidateModel->fetchByCompositeId(Candidate_Model::EMPTY_VOTE, $id) == false){
-
- $params = array('candidateNum'=>Candidate_Model::EMPTY_VOTE, 'firstName'=>EMPTY_VOTE_TEXT, 'election'=>$id);
- $query = "candidateNum, firstName, election";
-
- if($candidateModel->insertInto($query, $params) == false){
- $this->rollBack();
- return parent::FAILURE;
- }
- }
- }else { //Update existing record
- $paramArr[':electionId'] = $electionId;
- $sql .= "\nWHERE electionId = :electionId";
- if($this->updateSet($sql, $paramArr) == false){
- $this->rollBack();
- return parent::FAILURE;
- }
- }
- $this->commit();
- return parent::SUCCESS;
- }
-
- public function removeElection($electionId)
- {
- $this->beginTransaction();
- if(!is_null($electionId) && $electionId != 0) {
-
- $candidateModel = new Candidate_Model;
- if($candidateModel->countByFieldValues(array('election'=>$electionId)) > 0){
- if($candidateModel->removeByField("election", $electionId) == false) {
- $candidateModel->rollBack();
- return false;
- }
- }
- $voterModel = new Voter_Model;
- if($voterModel->countByFieldValues(array('election'=>$electionId)) > 0){
- if($voterModel->removeByField("election", $electionId) == false) {
- $voterModel->rollBack();
- return false;
- }
- }
- $allianceModel = new Alliance_Model;
- if($allianceModel->countByFieldValues(array('election'=>$electionId)) > 0){
- if($allianceModel->removeByField("election", $electionId) == false) {
- $allianceModel->rollBack();
- return false;
- }
- }
- $coalitionModel = new Coalition_Model;
- if($coalitionModel->countByFieldValues(array('election'=>$electionId)) > 0){
- if($coalitionModel->removeByField("election", $electionId) == false) {
- $coalitionModel->rollBack();
- return false;
- }
- }
- if($this->removeByField("electionId", $electionId) == false) {
- $this->rollBack();
- return false;
- }
- }
- $this->commit();
- return true;
-
- }
-
- public function endElection($electionId)
- {
- if(is_null($electionId) || $electionId==0)
- return false;
-
- $paramArr = array('status' => self::STATE_ENDED);
- $sql = "status";
- $paramArr[':electionId'] = $electionId;
-
- $sql .= "\nWHERE electionId = :electionId";
- if($this->updateSet($sql, $paramArr) == false) {
- $this->rollBack();
- return false;
- }
- return true;
- }
-
- public function startOrStopElectionElection($electionId, $curStatus)
- {
- if(is_null($electionId) || $electionId==0)
- return false;
-
- if($curStatus == self::STATE_ACTIVE){
- $paramArr = array('status' => self::STATE_CLOSED);
- }else if($curStatus == self::STATE_CLOSED){
- $paramArr = array('status' => self::STATE_ACTIVE);
- }
- $sql = "status";
- $paramArr[':electionId'] = $electionId;
-
- $sql .= "\nWHERE electionId = :electionId";
- if($this->updateSet($sql, $paramArr) == false) {
- $this->rollBack();
- return false;
- }
- return true;
- }
-
- public function putElectionToHistory($electionId)
- {
- if(is_null($electionId) || $electionId==0)
- return false;
-
- //calculate total papervotes and wwwvoter
- $voterModel = new Voter_Model;
- $wwwVotes = $voterModel->countVotes($electionId, Voter_Model::VOTE_METHOD_WWW);
- $paperVotes = $voterModel->countVotes($electionId, Voter_Model::VOTE_METHOD_PAPER);
-
- //update election status and votes
- $paramArr = array('status'=>self::STATE_HISTORY,'totalWwwVotes'=>$wwwVotes,
- 'totalPaperVotes'=>$paperVotes);
- $sql = "status,totalWwwVotes,totalPaperVotes";
- $paramArr[':electionId'] = $electionId;
-
- $sql .= "\nWHERE electionId = :electionId";
- if($this->updateSet($sql, $paramArr) == false) {
- $this->rollBack();
- return false;
- }
-
- //remove election voters
- if($voterModel->removeByField('election', $electionId) == false){
- $voterModel->rollBack();
- return false;
- }
- return true;
- }
-
- public function setResultsCalculated($electionId, $value)
- {
- if(is_null($electionId) || $electionId==0)
- return false;
-
- $paramArr = array('resultsCalculated'=>$value);
- $sql = "resultsCalculated";
- $paramArr[':electionId'] = $electionId;
-
- $sql .= "\nWHERE electionId = :electionId";
- if($this->updateSet($sql, $paramArr) == false) {
- $this->rollBack();
- return false;
- }
- return true;
- }
-
- /**
- * This function tells whether or not information regarding particular election can be deleted.
- *
- * Returns true if election with given id is in closed status.
- * Second parameter tells wether or not the time frame consisting of the
- * starting and ending dates should be checked.
- *
- * @param int $electionId
- * @param bool $compareDates
- * @return boolean
- */
- public function canBeDeleted($electionId, $compareDates = false)
- {
- $election = $this->fetchById((int) $electionId);
- if(empty($election))
- return false;
-
- //Status has to be closed
- if($election['status'] != self::STATE_CLOSED)
- return false;
-
- if ($compareDates) {
- //Current time cannot match the time frame of the election
- $now = date("Y-m-d H:i:s");
- if($election['startDate'] < $now && $election['endDate'] > $now)
- return false;
- }
-
- return true;
- }
-
- /**
- * This method validates the edit form's $_POST parameters and returns the valid input fields and error messages in an array.
- *
- * @param array $postArr
- * @return array
- */
- public function validateEditForm($postArr)
- {
- $electionArr = array();
- $errors = array();
- $formFields = array('name', 'startDate', 'startTime', 'endDate', 'endTime', 'calcMethod', 'status');
- $mandatory = array('name', 'startDate', 'startTime', 'endDate', 'endTime');
- $numeric = array('status', 'calcMethod');
- $datevalues = array('startDate', 'endDate');
- $timevalues = array('startTime', 'endTime');
- $invalidEndDate = false;
-
- $selectedStatus = $postArr['status'];
- if ($selectedStatus == 'stateOpen') {
- $postArr['status'] = self::STATE_ACTIVE;
- }else if ($selectedStatus == 'stateClosed') {
- $postArr['status'] = self::STATE_CLOSED;
- }else{
- $postArr['status'] = self::STATE_CLOSED;
- }
-
- $selectedCalcMethod = $postArr['calcMethod'];
- if ($selectedCalcMethod == 'countCoalitions') {
- $postArr['calcMethod'] = self::CALCULATE_COALITIONS;
- }else if ($selectedCalcMethod == 'noCoalitions') {
- $postArr['calcMethod'] = self::NO_COALITIONS;
- }else{
- $postArr['calcMethod'] = self::CALCULATE_COALITIONS;
- }
-
- $endDate = date('Y-m-d', strtotime($postArr['endDate'])).' '.date('H:i:s', strtotime($postArr['endTime']));
- $startDate = date('Y-m-d', strtotime($postArr['startDate'])).' '.date('H:i:s', strtotime($postArr['startTime']));
-
- if (strtotime($endDate) <= strtotime($startDate))
- $invalidEndDate = true;
-
- include_once SERVER_ROOT . '/lib/utils/data_validator.php';
-
- //Loop through form input and check that every mandatory field was filled
- foreach ($formFields as $field) {
- if(in_array($field, $mandatory) && empty($postArr[$field])) {
- $errors[$field] = MANDATORY_TEXT;
- }
- else if(in_array($field, $numeric) && !is_numeric($postArr[$field])) {
- $errors[$field] = HAS_TO_BE_A_NUMBER_TEXT;
- }
- else if(in_array($field, $datevalues) && !DataValidator::isValidDate($postArr[$field]) && !empty($postArr[$field])) {
- $errors[$field] = INVALID_DATEVALUE_TEXT;
- }
- else if(in_array($field, $timevalues) && !DataValidator::isValidTime($postArr[$field]) && !empty($postArr[$field])) {
- $errors[$field] = INVALID_TIMEVALUE_TEXT;
- }
- else if((in_array($field, $datevalues) || in_array($field, $timevalues)) && $invalidEndDate == true) {
- $errors[$field] = END_DATE_INVALID;
- }
-
- if(!isset($errors[$field]))
- $electionArr[$field] = $postArr[$field];
- }
- return array($electionArr, $errors);
- }
-
- public static function getElectionStateString($state)
- {
- switch ($state) {
- case self::STATE_CLOSED:
- return ELECTION_STATUS_CLOSED_TEXT;
- case self::STATE_ACTIVE:
- return ELECTION_STATUS_ACTIVE_TEXT;
- case self::STATE_ENDED:
- return ELECTION_STATUS_ENDED_TEXT;
- }
- }
-
- public static function checkActiveElectionDates($startDate = null, $endDate = null)
- {
- $returnVal = "";
- if(isset($startDate) && strtotime($startDate) > strtotime(date('d.m.Y H:i:s'))){
- $returnVal = ' (' . mb_strtolower(ELECTION_HAS_NOT_STARTED_YET_TEXT,'UTF-8') . ')';
- }
- if(isset($endDate) && strtotime($endDate) < strtotime(date('d.m.Y H:i:s'))){
- $returnVal = ' (' . mb_strtolower(ELECTION_STATUS_ENDED_TEXT,'UTF-8') . ')';
- }
- return $returnVal;
- }
- }