Source of file GameSignupPage.php
Size: 16,147 Bytes - Last Modified: 2022-02-21T10:00:34+00:00
/var/www/docs.ssmods.com/process/src/code/pagetypes/GameSignupPage.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635 | <?php /* * This page allows users to register game choices, writing to the PlayerGame dataobject */ class GameSignupPage extends Page { private static $icon = "gamesevent/images/gamesignup.png"; private static $hide_preview_panel = true; private static $db = array( 'OpenGameReg'=>'Boolean', 'GameLiveContent'=>'HTMLText' ); private static $many_many = array( 'OpenGameRegForGroups'=>'Group' ); public function getCMSFields() { $fields = parent::getCMSFields(); $fields->insertAfter($gameFormContent = new HTMLEditorField('GameLiveContent', 'Game selection form detail'),'Content'); $gameFormContent->setRows(20); $regOpen = new SwitchField('OpenGameReg', 'Open game selection (to all)'); $fields->insertBefore($regOpen, 'Content'); $groupsMap = array(); foreach(Group::get() as $group) { // Listboxfield values are escaped, use ASCII char instead of » $groupsMap[$group->ID] = $group->getBreadcrumbs(' > '); } asort($groupsMap); $fields->insertBefore( ListboxField::create('OpenGameRegForGroups', "Open game selection for group (limited)") ->setMultiple(true) ->setSource($groupsMap) ->setAttribute( 'data-placeholder', _t('Member.ADDGROUP', 'Add group', 'Placeholder text for a dropdown') ),'Content' ); return $fields; } /* * @return Registration */ public function getCurrentRegistration(){ $member = Member::currentUser(); $currentID = $this->getCurrentEvent()->ID; if(!$currentID || !$member){ return false; } $reg = Registration::get()->filter(array( 'MemberID' => $member->ID, 'ParentID' => $this->getCurrentEvent()->ID, )); if(!$reg){ return false; } return $reg->First(); } /* * @return Event */ public function getCurrentEvent() { return SiteConfig::current_site_config()->CurrentEvent(); } /* * @return String */ public function MenuTitle(){ if($this->getCurrentRegistration() && $this->getCurrentRegistration()->PlayerGames()->Count() > 0){ return "Your Games"; } return $this->MenuTitle; } } class GameSignupPage_Controller extends Page_Controller { private static $allowed_actions = array ( 'Form' => true, 'yourgames' => true, 'addplayergames' => true, 'gamesessionasjson' => true ); /* * Check if there are any groups added to OpenGameRegForGroups * return true if the current member is in one of these groups * * If game reg is open, return true * @return Boolean */ public function userGameRegOpen() { if($this->OpenGameReg){ return true; } if($this->OpenGameRegForGroups()) { foreach ($this->OpenGameRegForGroups() as $group){ if (Member::currentUser()->inGroup($group->ID)){ return true; } } } return false; } /** * @return Form */ public function Form() { // Attempt to retrieve a current registration for the logged in member $reg = $this->getCurrentRegistration(); $register = RegistrationPage::get()->First(); // If the user has no registration, redirect them to the registration page if(!$reg) { if($register) { $this->redirect($register->AbsoluteLink()); return; } else { $this->redirect($this->baseURL); return; } } if(!$this->userGameRegOpen()) { return false; } // If the user has already added games, redirect them to after submission // @todo: allow users to edit submitted game choices if option enabled, and within 10 minutes if($reg->PlayerGames()->Count() > 0) { $this->redirect($this->Link('yourgames')); } $fields = $this->GameSignupFields($reg); $form = Form::create( $this, 'Form', $fields, FieldList::create( FormAction::create('addplayergames', 'Submit') ) ); $form->enableSpamProtection(); $form->addExtraClass('preference-select'); return $form; } /* * Used for autocomplete type functionality when adding genres */ public function renderGamesList($games){ return $this->customise(array('Games'=>$games))->renderWith('GamesList'); } /* * Fields for game signup * Note: this is strongly tied to the hydra sites need for sortable games lists. * The frontend uses jquery sortable to allow users to order games by preference order */ public function GameSignupFields($reg){ $fields = new FieldList(); $currentID = $this->getCurrentEvent()->ID; $event = Event::get()->byID($currentID); $prefNum = $event->PreferencesPerSession; $reg = $this->getCurrentRegistration(); $fields->push(HiddenField::create('RegistrationID', 'Reg', $reg->ID)); if (!$this->DisableFavourite()) { $fields->push($fav = HiddenField::create('FavouriteID', 'Favourite')); $fav->addExtraClass('favourite-id'); } $fields->push(LiteralField::create('no-js','<p class="js-hide">This page works better with javascript. If you can\'t use javascript, rank the items below in your order of preference. 1 for your first choice, 2 for your second. Note, only the top ' . $prefNum . ' will be recorded</p>')); for ($session = 1; $session <= $event->NumberOfSessions; $session++){ $evenOdd = $session % 2 == 0 ? 'even': 'odd'; $fieldset = '<fieldset id="round'.$session.'" class="preference-group preference-'.$prefNum.' data-preference-select="preference-select-group">'; $fields->push(LiteralField::create('Heading_'.$session, '<h5>Round '.$session.' preferences</h5>'. $fieldset)); $games = Game::get()->filter(array( 'Session' => $session, 'ParentID' =>$currentID, 'Status' => true ))->sort('RAND()'); $i = 1; foreach ($games as $game){ $gameOptions = NumericField::create("GameID_".$game->ID, ''); $gameOptions->setValue($i) ->setRightTitle($game->Title) ->setAttribute('type','number') ->setAttribute('data-id',$game->ID) ->addExtraClass('small-input js-hide-input'); $fields->push($gameOptions); $i++; } if($this->EnableLuckyDip()) { // Add not playing option $gameOptions = NumericField::create("LuckyDip_".$session, ''); $gameOptions->setValue($i) ->setRightTitle("Lucky dip") ->setAttribute('type','number') ->addExtraClass('small-input js-hide-input isfinal'); $fields->push($gameOptions); $i++; } // Add not playing option $gameOptions = NumericField::create("NotPlaying_".$session, ''); $gameOptions->setValue($i) ->setRightTitle("No game (or Facilitating)") ->setAttribute('type','number') ->addExtraClass('small-input js-hide-input not-playing isfinal'); $fields->push($gameOptions); $fields->push(LiteralField::create('fieldset', '</fieldset>')); } $allgames = Game::get()->filter(array( 'ParentID' => $currentID, 'Status' => true )); $allgamesMap = $allgames->map("ID", "Title")->toArray(); asort($allgamesMap); // tag input field $fields->push($tagfield = new Listboxfield( 'HasPlayed', 'I have already played these games' )); $tagfield->setMultiple(true) ->setSource($allgamesMap) ->setAttribute( 'data-placeholder', 'Select games' ); $tagfield->addExtraClass('js-select2 ptl'); return $fields; } /* * Generate a json object of games for a session. * URL format: $this->Link/gamesessionasjson/$i * @return Json | Games per session */ public function gamesessionasjson($request){ $session = $request->param('ID') ? $request->param('ID') : 1; $games = Game::get()->filter(array('Session' => $session, 'Status' => true))->map('ID', 'Title')->toArray(); return Convert::array2json($games); } /** * Handles adding new games */ public function addplayergames($data, Form $form) { if($reg = $this->addPlayerGame($data, $form)) { $this->handleAppEmails($reg); $this->redirect($this->Link('yourgames')); return; } else { return $this->redirectBack(); } } /** * Send an email with two csv attachments: * * the HasPlayed Game list for this registration * * the Player game selections for this player * * @param Registration | $reg */ public function handleAppEmails($reg) { $siteConfig = SiteConfig::current_site_config(); $address = $reg->Parent()->AppEmail; $currentID = $reg->Parent()->ID; if(!$address) { return; } $hasPlayedData = $this->getHasPlayed($reg); $hasPlayedFile = $this->handleFile($hasPlayedData, "playedgames.csv", $reg); $playerGames = PlayerGame::get()->filter( 'ParentID', $reg->ID ); $formatter = new CsvDataFormatter(); $playerGameData = $formatter->convertDataObjectSet($playerGames); $playerGamesFile = $this->handleFile($playerGameData, "gameselections.csv", $reg); $email = Email::create(); $email->attachFile($playerGamesFile); $email->attachFile($hasPlayedFile); $email->setTo($address); $email->setFrom('it@nzlarps.org'); $email->setSubject("Chimera games for " . $reg->getMemberName()); $email->setBody('Game details are attached'); $email->send(); } /** * Compile custom hasplayed records as a csv formatted string * * @param Registration | $reg * @return String */ public function getHasPlayed($reg) { $hasPlayed = $reg->HasPlayed(); $result = '"RegID", "MemberEmail", "GameID", "GameTitle"'; $id = $reg->ID; $email = $reg->getMemberEmail(); foreach($hasPlayed as $game) { $gID = $game->ID; $title = $game->Title; $result .= PHP_EOL .'"'. $id . '","' . $email . '","' . $gID . '","'. $title .'"'; } return $result; } /** * Generate the export and return the filepath if successful * * @param Data | $fileData csv formatted string * @param String | $filename * @param Registraton | $reg user registration * @return filepath */ public function handleFile($fileData, $fileName, $reg) { $ID = $reg->ID; $email = $reg->Email; $folder = "/tmp/$ID-$email/"; $filepath = $folder . $fileName; try { if(!file_exists($folder)) { if (!mkdir($folder, 0700)){ die('Failed to create export folder'); } } $file = fopen($filepath, "w"); fwrite($file, $fileData); fclose($file); return $filepath; } catch(Exception $e) { return false; } } public function handleExistingGames($reg) { // @todo - handle a proper 'change game' case if($reg->PlayerGames()->Count() > 0) { foreach($reg->PlayerGames() as $playerGame) { $reg->PlayerGames()->removeByID($playerGame->ID); $playerGame->delete(); } } } /** * Attempts to save a game * * @return Game|null */ protected function addPlayerGame($data,$form) { $event = $this->getCurrentEvent(); $currentID = $event->ID; $regID = $data['RegistrationID']; $reg = Registration::get()->byID($regID); if (!$reg) { return false; } $this->handleExistingGames($reg); $favouriteID = false; if (!$this->DisableFavourite()) { $favouriteID = $data["FavouriteID"]; } for ($session = 1; $session <= $event->NumberOfSessions; $session++) { $notPlay = (int)$data["NotPlaying_".$session]; $luckyDip = false; if($this->EnableLuckyDip()) { $luckyDip = (int)$data["LuckyDip_".$session]; //gets position/value of luckydip entry } $prefNum = $event->PreferencesPerSession; $games = Game::get()->filter(array( 'Session' => $session, 'ParentID' => $currentID, 'Status' => 1 )); // Alter prefnumber so it stops when it encounters "Not Playing" if($notPlay != 0 && $notPlay < $prefNum) { $prefNum = $notPlay; } // if first choice is to not play, don't create any games this session if($notPlay === 1) { continue; } if($luckyDip) { $this->writeLuckyDip($luckyDip, $prefNum, $regID, $session, $form); // Alter prefnumber so it stops when it encounters our lucky dip if($luckyDip < $prefNum) { $prefNum = $luckyDip; } } $this->writeSessionChoices($games, $data, $prefNum, $regID, $session, $favouriteID, $form); } $this->writeHasPlayed($reg, $form); return $reg; } /** * Write HasPlayed data for this registration * * @param Registration | $reg - the id of the registration this choice belongs to * @param Form | $form */ public function writeHasPlayed($reg, $form) { $form->saveInto($reg); try { $reg->write(); } catch(ValidationException $e) { $form->sessionMessage($e->getResult()->message(), 'bad'); } } /** * Write all games for this session that are less than our current number of preferences to write * * @param DataList | $games - A list of Games for this session * @param Array | $data - submitted form data * @param Int | $prefNum - the number of preferences allowed * @param Int | $regID - the id of the registration this choice belongs to * @param Int | $session - the session number of the lucky dip option * @param Int | $favouriteID * @param Form | $form */ public function writeSessionChoices($games, $data, $prefNum, $regID, $session, $favouriteID, $form) { foreach ($games as $game) { $gamePref = (int)$data["GameID_".$game->ID]; //get value of field, this should be our preference number // only store games with a preference higher than our threshold if ($gamePref > $prefNum || !isset($gamePref)) { continue; } $playerGame = PlayerGame::create(); $form->saveInto($playerGame); $playerGame->GameID = $game->ID; $playerGame->ParentID = $regID; $playerGame->Preference = $gamePref; $playerGame->Session = $session; if($favouriteID == $game->ID) { $playerGame->Favourite = true; } try { $playerGame->write(); } catch(ValidationException $e) { $form->sessionMessage($e->getResult()->message(), 'bad'); } } } /** * A Lucky dip is a player game where the game itself hasn't been chosen. * The player would like a game, but is happy to have an organiser vhoose for them. * This means we need to write a player game that has a registration, but no game assigned * * @param Int | $luckyDipPref - the value of the lucky dip option (choice number), * @param Int | $prefNum - the number of preferences allowed * @param Int | $regID - the id of the registration this choice belongs to * @param Int | $session - the session number of the lucky dip option * @param Form | $form */ public function writeLuckyDip($luckyDipPref, $prefNum, $regID, $session, $form) { // only store luckydip with a preference higher than our threshold if ($luckyDipPref > $prefNum) { return; } $playerGame = PlayerGame::create(); $form->saveInto($playerGame); $playerGame->ParentID = $regID; $playerGame->Preference = $luckyDipPref; $playerGame->Session = $session; try { $playerGame->write(); } catch(ValidationException $e) { $form->sessionMessage($e->getResult()->message(), 'bad'); } } /** * Returns data for the your games view (after game selection) * * @return array */ public function yourgames() { $reg = $this->getCurrentRegistration(); if(!$reg || !$reg->PlayerGames()->Count() > 0) { $this->redirect($this->Link()); return; } return array ( 'Title' => "Your Games", 'Content' => "Your game choices are listed below. If any of this is incorrect, or if you wish to change your game choices, please contact us.", 'Form' => false, 'SubmittedGames' => true ); } /* * @return GroupedList */ public function getGroupedPlayerGames() { $reg = $this->getCurrentRegistration(); if(!$reg){ return false; } $playergames = $reg->PlayerGames(); $games = new ArrayList(); foreach($playergames as $playergame) { $data = array( "GameTitle" => $playergame->getTitle(), "Preference" => $playergame->Preference, "Favourite" => $playergame->Favourite, "Status" => $playergame->Status, "Session" => $playergame->GameSession() ); if ($this->DisableFavourite()) { unset($data['Favourite']); } $games->push(new ArrayData($data)); } $result = $games->sort(array('Session' => 'ASC', 'Preference' => 'ASC')); return GroupedList::create($result); } public function DisableFavourite() { return $this->getCurrentEvent()->DisableFavourite; } public function EnableLuckyDip() { return $this->getCurrentEvent()->EnableLuckyDip; } } |