Link('results') . "', { minChars: 3, selectFirst: true, autoFill: true, }); $('#SearchForm_MemberSearchForm_mq').focus(); }); "); // If we're in HTTPS mode, reset to HTTP for this page if (isset($_SERVER['HTTPS'])) { $destURL = str_replace('https:', 'http:', Director::absoluteURL($_SERVER['REQUEST_URI'])); // check to make sure we're not already there to prevent redirect loop if ($destURL != Director::absoluteURL($_SERVER['REQUEST_URI'])) { $this->redirect($destURL); } } } static $allowed_actions = array( 'confirmNomination', 'CurrentElection', 'saveNomination', 'profile', 'results', 'MemberSearchForm', 'candidateStats', 'CandidateApplication', 'idList' => 'ADMIN', 'assignGroup' => 'ADMIN', 'ListExport', 'CSVExport' => 'ADMIN' ); function MemberList() { if (isset($_GET['letter'])) { $requestedLetter = Convert::raw2xml($_GET['letter']); if ($requestedLetter == 'intl') { $likeString = "NOT Surname REGEXP '[A-Za-z0-9]'"; } elseif (ctype_alpha($requestedLetter)) { $likeString = "Surname LIKE '" . substr($requestedLetter, 0, 1) . "%'"; } else { $likeString = "Surname LIKE 'a%'"; } } else { $likeString = "Surname LIKE 'a%'"; } $list = Member::get() ->where("Group_Members.GroupID = 5 AND " . $likeString) ->leftJoin('Group_Members', 'Member.ID = Group_Members.MemberID') ->sort('Surname'); return GroupedList::create($list); } // Return the currently running election // This simple function primarily exists to be used in the template function CurrentElection() { // Load the election system $Elections = ElectionSystem::get()->first(); if ($Elections && $Elections->CurrentElectionID != 0) return $Elections->CurrentElection(); } function alreadyNominated($candidateID, $CurrentElection) { $memberID = Member::currentUserID(); $NominationsForThisCandidate = $CurrentElection->CandidateNominations("`MemberID` = " . $memberID . " AND `CandidateID` = " . $candidateID); if ($NominationsForThisCandidate->Count() >= 1) { return TRUE; } } function findMember($CandidateID) { $Candidate = Member::get()->byID($CandidateID); // Check to make sure they are in the foundation membership group If ($Candidate && $Candidate->inGroup(5, TRUE)) return $Candidate; } function confirmNomination() { $results = array(); $results["Success"] = FALSE; // Grab candidate ID from the URL $CandidateID = $this->request->param("ID"); // Check to see if the candidate ID is numeric and if the person is logged in if ($this->validateNomation($CandidateID) == 'VALID') { $Nominee = Member::get()->filter(array('ID' => $CandidateID)); $results["Success"] = TRUE; $results["Candidate"] = $Nominee; $results["NominateLink"] = $this->Link() . "saveNomination/" . $CandidateID; $results["BackLink"] = $this->Link() . "profile/" . $CandidateID; } elseif ($this->validateNomation($CandidateID) == 'ALREADY NOMINATED') { $Nominee = Member::get()->filter(array('ID' => $CandidateID)); $CurrentElection = $this->CurrentElection(); $results["Election"] = $CurrentElection; $results["Success"] = FALSE; $results["NominatedByMe"] = TRUE; $results["Candidate"] = $Nominee; $results["BackLink"] = $this->Link() . "profile/" . $CandidateID; } elseif ($this->validateNomation($CandidateID) == 'LIMIT EXCEEDED') { $Nominee = Member::get()->filter(array('ID' => $CandidateID)); $results["Success"] = FALSE; $results["LimitExceeded"] = TRUE; $results["Candidate"] = $Nominee; $results["BackLink"] = $this->Link() . "profile/" . $CandidateID; } else { $results["Success"] = FALSE; $results["BackLink"] = $this->Link() . "profile/" . $CandidateID; } return $results; } // Checks whether a nomination is valid: // Requires there to be a current election, the member to be logged in, and the ID of a member that hasn't been nominated yet. function validateNomation($CandidateID) { $CurrentElection = $this->CurrentElection(); // Look for nominations for this candidate $CandidateNominations = CandidateNomination::get()->where("CandidateID = " . $CandidateID . " AND ElectionID = " . $CurrentElection->ID); $NumberOfNominations = 0; if ($CandidateNominations) $NumberOfNominations = $CandidateNominations->Count(); // 1. Check to see if there's a current, active election if (!$CurrentElection || !$CurrentElection->NominationsAreOpen()) { return 'NO ACTIVE NOMINATIONS'; } // 2. Check to see if a member is logged in if (!Member::currentUserID()) { return 'NOT LOGGED IN'; } // 3. Check to make sure there's a valid Candidate ID if (!is_numeric($CandidateID) || !$this->findMember($CandidateID)) { return 'INVALID CANDIDATE'; } // 4. Check to see if the member has already nominated this person if ($this->alreadyNominated($CandidateID, $CurrentElection)) { return 'ALREADY NOMINATED'; } // 5. Check to see if this person already has 10 nominations if ($NumberOfNominations >= 10) { return 'LIMIT EXCEEDED'; } // 6. Make sure that the person nominating is a foundation member $CurrentMember = Member::currentUser(); If (!$CurrentMember->inGroup(5, TRUE)) { return 'INVALID VOTER'; } // If all of the above tests pass, this is a valid nomination return 'VALID'; } function saveNomination() { $CandidateID = $this->request->param("OtherID"); $NominationStatus = $this->validateNomation($CandidateID); // Check to see if this is a valid nomination if ($NominationStatus == 'VALID') { // Grab the currently logged in member $currentMember = Member::currentUser(); $CurrentElection = $this->CurrentElection(); // Record the nomination $CandidateNomination = new CandidateNomination(); $CandidateNomination->MemberID = Member::currentUserID(); $CandidateNomination->CandidateID = $CandidateID; $CandidateNomination->ElectionID = $CurrentElection->ID; $CandidateNomination->write(); // Create a candidate record for the nominations page if one does not exist $Candidate = Candidate::get()->filter(array('MemberID'=>$CandidateID,'ElectionID'=>$CurrentElection->ID))->first(); if (!$Candidate) { // Create a new candidate entry $Candidate = new Candidate(); $Candidate->MemberID = $CandidateID; $Candidate->ElectionID = $CurrentElection->ID; $Candidate->write(); } // Log this new candidate $logLine = $currentMember->FirstName . " " . $currentMember->Surname . " nominated " . $Candidate->Member()->FirstName . " " . $Candidate->Member()->Surname . " (ID " . $Candidate->Member()->ID . ") on " . $CandidateNomination->Created . " \n"; $file = fopen(ASSETS_PATH . '/candidate-nomination-log.txt', 'a'); fwrite($file, $logLine); fclose($file); // Email the member // In dev and testing, send the nomination emails to the person who did the nomination $To = $currentMember->Email; // In live mode, send the email to the candidate if (Director::isLive()) $To = $Candidate->Member()->Email; $Subject = "You have been nominated in the " . $CurrentElection->Title; $email = EmailFactory::getInstance()->buildEmail(CANDIDATE_NOMINATION_FROM_EMAIL, $To, $Subject); $email->setTemplate('NominationEmail'); // Gather Data to send to template $data["Candidate"] = $Candidate; $data["Election"] = $CurrentElection; $email->populateTemplate($data); $email->send(); $this->setMessage('Success', "You've just nominated " . $Candidate->Member()->FirstName . ' for the OpenStack Board.'); $this->redirect('/community/members/candidateStats/' . $Candidate->Member()->ID); } elseif ($NominationStatus = 'ALREADY NOMINATED') { $this->setMessage('Error', "Oops, you have already nominated this person."); $this->redirect($this->Link()); } elseif ($NominationStatus = 'INVALID CANDIDATE') { $this->setMessage('Error', "Oops, no candidate was selected."); $this->redirect($this->Link()); } else { $this->setMessage('Error', "There was an error logging your nomination."); $this->redirect($this->Link()); } } //Show the profile of the member using the MemberListPage_profile.ss template function profile() { // Grab member ID from the URL $MemberID = Convert::raw2sql($this->request->param("ID")); // Check to see if the ID is numeric if (is_numeric($MemberID)) { // Check to make sure there's a member with the current id if ($Profile = $this->findMember($MemberID)) { $CurrentElection = $this->CurrentElection(); if ($CurrentElection) { $Candidate = Candidate::get()->filter(array('MemberID'=>$MemberID,'ElectionID'=>$CurrentElection->ID))->first(); $data["Candidate"] = $Candidate; $data["CurrentElection"] = $CurrentElection; } $data["Profile"] = $Profile; // A member is looking at own profile if (Member::currentUserID() == $MemberID) $data["OwnProfile"] = TRUE; //return our $Data to use on the page return $this->Customise($data); } } return $this->httpError(404, 'Sorry that member could not be found'); } function candidateStats() { // Grab candidate ID from the URL $CandidateID = $this->request->param("OtherID"); // Check to see if the candidate is valid if (is_numeric($CandidateID) && $this->findMember($CandidateID)) { $CurrentElection = $this->CurrentElection(); $Candidate = $CurrentElection->Candidates("MemberID = " . $CandidateID); $results["Success"] = TRUE; $results["Candidate"] = $Candidate; return $results; } else { //Member not found return $this->httpError(404, 'Sorry that candidate could not be found'); } } public function MemberSearchForm() { $fields = new FieldList( new TextField('mq', 'Search Member name', $this->getSearchQuery()) ); $form = new SearchForm($this, 'MemberSearchForm', $fields); $form->setFormAction($this->Link('results')); return $form; } public function results() { if ($query = $this->getSearchQuery()) { // Search for only foundation members (Group 5) against the query. $filter = "(MATCH (FirstName, Surname) AGAINST ('{$query}') OR FirstName LIKE '%{$query}%' OR Surname LIKE '%{$query}%') AND Group_Members.GroupID=5"; $Results = Member::get() ->where($filter) ->leftJoin("Group_Members", "Member.ID = Group_Members.MemberID"); // No Member was found if (!isset($Results)) { $this->setMessage("Error", "No member by that name could be found."); $this->redirectBack(); return; } // For AutoComplete if (Director::is_ajax()) { $Members = $Results->map('ID', 'Name'); $Suggestions = ''; foreach ($Members as $Member) { $Suggestions = $Suggestions . $Member . '|' . '1' . "\n"; } return $Suggestions; } // For Results Template else { $filter = "(CONCAT(FirstName, ' ', Surname) LIKE '%$query%') AND Group_Members.GroupID=5"; $OneMember = Member::get() ->where($filter) ->leftJoin("Group_Members", "Member.ID = Group_Members.MemberID"); // see if one member exactly matches the search term if ($OneMember) { $Results = $OneMember; } // If there is only one person with this name, go straight to the resulting profile page if ($OneMember && $OneMember->Count() == 1) { $this->redirect($this->Link() . 'profile/' . $OneMember->First()->ID); } $Output = new ArrayData(array( 'Title' => 'Results', 'Results' => $Results )); return $this->customise($Output); } } $this->redirect($this->Link()); } function getSearchQuery() { if ($this->request){ $query = $this->request->getVar("mq"); if(!empty($query)) return Convert::raw2sql($query); return false; } } private function GetMembersInDateRange($StartTime = NULL, $EndTime = NULL) { $DateRange = ""; if ($StartTime && $EndTime) { $DateRange = " AND (LastEdited BETWEEN '" . $StartTime . "' AND '" . $EndTime . "')"; } elseif ($EndTime) { $DateRange = " AND (LastEdited <= '" . $EndTime . "')"; } elseif ($StartTime) { $DateRange = " AND (LastEdited >= '" . $StartTime . "')"; } else { $DateRange = ""; } // Pull Members using a custom db query. This returns a MySQLQuery object $MemberList = DB::query(" SELECT Member.ID, `FirstName`, `Surname`, `IRCHandle`, `TwitterName`, `Email`, `SecondEmail`, `ThirdEmail` FROM `Member` LEFT JOIN `Group_Members` ON `Member`.`ID` = `Group_Members`.`MemberID` WHERE `Group_Members`.`GroupID`= 5" . $DateRange ); return $MemberList; } function ListExport() { if (isset($_GET['token']) && $_GET['token'] == "fcv4x7Nl8v") { // Check URL parameters for start and end times $Start = isset($_GET['start']) ? $_GET['start'] : NULL; $End = isset($_GET['end']) ? $_GET['end'] : NULL; $StartTime = $Start ? date("Y-m-d H:i:s", strtotime($Start)) : NULL; $EndTime = $End ? date("Y-m-d H:i:s", strtotime($End)) : NULL; $MemberList = $this->GetMembersInDateRange($StartTime, $EndTime); $results = array(); // Transform the MySQLQuery object created above into an ArrayData object if ($MemberList) { foreach ($MemberList as $Member) { $dbMember = Member::get()->byID($Member['ID']); if (!is_null($dbMember)) { $AffiliationList = $dbMember->OrderedAffiliations(); // If there are Affiliation updates, push a new copy of the member to the results array filled in with the org and date from the update if ($AffiliationList && $AffiliationList->Count() > 0) { foreach ($AffiliationList as $a) { $currentMemberOrg = $a->Organization(); $Member['OrgAffiliations'] = $currentMemberOrg->Name; if ($a->Current) $Member['untilDate'] = NULL; else $Member['untilDate'] = $a->EndDate; // Push the member to the results array_push($results, $Member); } } else { //no affiliations $Member['OrgAffiliations'] = NULL; $Member['untilDate'] = NULL; array_push($results, $Member); } } } } // Finally, convert the array from the ArrayData object to JSON $json = Convert::Array2JSON($results); return $json; } } function FullMemberList(){ return Member::get()->leftJoin('Group_Members','`Member`.`ID` = `Group_Members`.`MemberID` AND Group_Members.GroupID=5'); } }