From 23d9465c282bd4cf58e456a84fff0a168bbd8427 Mon Sep 17 00:00:00 2001 From: coderkun Date: Wed, 23 Apr 2014 15:08:53 +0200 Subject: [PATCH] improve Questtype ?submit? and store additional data for Character answers --- app/QuesttypeController.inc | 12 +++ configs/AppConfig.inc | 4 +- controllers/QuestsController.inc | 5 +- models/QuestsModel.inc | 27 +++++++ .../BossfightQuesttypeController.inc | 14 ++++ .../ChoiceinputQuesttypeController.inc | 14 ++++ .../CrosswordQuesttypeController.inc | 14 ++++ .../DragndropQuesttypeController.inc | 14 ++++ .../MultiplechoiceQuesttypeController.inc | 14 ++++ .../submit/SubmitQuesttypeController.inc | 79 ++++++++++++++++--- questtypes/submit/SubmitQuesttypeModel.inc | 62 ++++++++++++--- questtypes/submit/html/quest.tpl | 33 +++++++- questtypes/submit/html/submission.tpl | 34 ++++++-- .../TextinputQuesttypeController.inc | 14 ++++ 14 files changed, 302 insertions(+), 38 deletions(-) diff --git a/app/QuesttypeController.inc b/app/QuesttypeController.inc index 25544ab2..9b13512e 100644 --- a/app/QuesttypeController.inc +++ b/app/QuesttypeController.inc @@ -41,6 +41,18 @@ public abstract function saveAnswersOfCharacter($seminary, $questgroup, $quest, $character, $answers); + /** + * Save additional data for the answers of a Character for a Quest. + * + * @param array $seminary Current Seminary data + * @param array $questgroup Current Questgroup data + * @param array $quest Current Quest data + * @param array $character Current Character data + * @param array $data Additional (POST-) data + */ + public abstract function saveDataForCharacterAnswers($seminary, $questgroup, $quest, $character, $data); + + /** * Check if answers of a Character for a Quest match the correct ones. * diff --git a/configs/AppConfig.inc b/configs/AppConfig.inc index 38fef10e..28f4c00f 100644 --- a/configs/AppConfig.inc +++ b/configs/AppConfig.inc @@ -117,12 +117,12 @@ ), 'prename' => array( 'minlength' => 2, - 'maxlength' => 128, + 'maxlength' => 32, 'regex' => '/^\S*$/' ), 'surname' => array( 'minlength' => 2, - 'maxlength' => 128, + 'maxlength' => 32, 'regex' => '/^\S*$/' ), 'password' => array( diff --git a/controllers/QuestsController.inc b/controllers/QuestsController.inc index 6da2906d..04fd1d31 100644 --- a/controllers/QuestsController.inc +++ b/controllers/QuestsController.inc @@ -625,7 +625,7 @@ $this->Quests->setQuestSubmitted($quest['id'], $character['id']); // Redirect - $this->redirect($this->linker->link('Prolog', 5, true)); + //$this->redirect($this->linker->link('Prolog', 5, true)); } } catch(\hhu\z\exceptions\SubmissionNotValidException $e) { @@ -703,6 +703,9 @@ $this->Quests->setQuestUnsolved($quest['id'], $character['id']); } + // Save additional data for Character answers + $questtypeAgent->controller->saveDataForCharacterAnswers($seminary, $questgroup, $quest, $character, $this->request->getPostParam('characterdata')); + // Redirect $this->redirect($this->linker->link(array('submissions', $seminary['url'], $questgroup['url'], $quest['url']), 1)); } diff --git a/models/QuestsModel.inc b/models/QuestsModel.inc index ffffb536..d4175545 100644 --- a/models/QuestsModel.inc +++ b/models/QuestsModel.inc @@ -406,6 +406,33 @@ } + /** + * Get the last status of a Quest for a Character. + * + * @param int $questId ID of Quest + * @param int $characterId ID of Character to get status for + * @return int Last status + */ + public function getLastQuestStatus($questId, $characterId) + { + $data = $this->db->query( + 'SELECT id, created, status '. + 'FROM quests_characters '. + 'WHERE quest_id = ? AND character_id = ? '. + 'ORDER BY created DESC '. + 'LIMIT 1', + 'ii', + $questId, $characterId + ); + if(!empty($data)) { + return $data[0]; + } + + + return null; + } + + /** * Create a new Quest. * diff --git a/questtypes/bossfight/BossfightQuesttypeController.inc b/questtypes/bossfight/BossfightQuesttypeController.inc index 366aabc8..4f8001e7 100644 --- a/questtypes/bossfight/BossfightQuesttypeController.inc +++ b/questtypes/bossfight/BossfightQuesttypeController.inc @@ -53,6 +53,20 @@ } + /** + * Save additional data for the answers of a Character for a Quest. + * + * @param array $seminary Current Seminary data + * @param array $questgroup Current Questgroup data + * @param array $quest Current Quest data + * @param array $character Current Character data + * @param array $data Additional (POST-) data + */ + public function saveDataForCharacterAnswers($seminary, $questgroup, $quest, $character, $data) + { + } + + /** * Check if answers of a Character for a Quest match the correct ones. * diff --git a/questtypes/choiceinput/ChoiceinputQuesttypeController.inc b/questtypes/choiceinput/ChoiceinputQuesttypeController.inc index 1b7eff27..be75b852 100644 --- a/questtypes/choiceinput/ChoiceinputQuesttypeController.inc +++ b/questtypes/choiceinput/ChoiceinputQuesttypeController.inc @@ -48,6 +48,20 @@ } + /** + * Save additional data for the answers of a Character for a Quest. + * + * @param array $seminary Current Seminary data + * @param array $questgroup Current Questgroup data + * @param array $quest Current Quest data + * @param array $character Current Character data + * @param array $data Additional (POST-) data + */ + public function saveDataForCharacterAnswers($seminary, $questgroup, $quest, $character, $data) + { + } + + /** * Check if answers of a Character for a Quest match the correct ones. * diff --git a/questtypes/crossword/CrosswordQuesttypeController.inc b/questtypes/crossword/CrosswordQuesttypeController.inc index ba3e5a0c..318271f9 100644 --- a/questtypes/crossword/CrosswordQuesttypeController.inc +++ b/questtypes/crossword/CrosswordQuesttypeController.inc @@ -81,6 +81,20 @@ } + /** + * Save additional data for the answers of a Character for a Quest. + * + * @param array $seminary Current Seminary data + * @param array $questgroup Current Questgroup data + * @param array $quest Current Quest data + * @param array $character Current Character data + * @param array $data Additional (POST-) data + */ + public function saveDataForCharacterAnswers($seminary, $questgroup, $quest, $character, $data) + { + } + + /** * Check if answers of a Character for a Quest match the correct ones. * diff --git a/questtypes/dragndrop/DragndropQuesttypeController.inc b/questtypes/dragndrop/DragndropQuesttypeController.inc index 5fbf6328..9797f8fd 100644 --- a/questtypes/dragndrop/DragndropQuesttypeController.inc +++ b/questtypes/dragndrop/DragndropQuesttypeController.inc @@ -65,6 +65,20 @@ } + /** + * Save additional data for the answers of a Character for a Quest. + * + * @param array $seminary Current Seminary data + * @param array $questgroup Current Questgroup data + * @param array $quest Current Quest data + * @param array $character Current Character data + * @param array $data Additional (POST-) data + */ + public function saveDataForCharacterAnswers($seminary, $questgroup, $quest, $character, $data) + { + } + + /** * Check if answers of a Character for a Quest match the correct ones. * diff --git a/questtypes/multiplechoice/MultiplechoiceQuesttypeController.inc b/questtypes/multiplechoice/MultiplechoiceQuesttypeController.inc index bca8c33a..b025f758 100644 --- a/questtypes/multiplechoice/MultiplechoiceQuesttypeController.inc +++ b/questtypes/multiplechoice/MultiplechoiceQuesttypeController.inc @@ -55,6 +55,20 @@ } + /** + * Save additional data for the answers of a Character for a Quest. + * + * @param array $seminary Current Seminary data + * @param array $questgroup Current Questgroup data + * @param array $quest Current Quest data + * @param array $character Current Character data + * @param array $data Additional (POST-) data + */ + public function saveDataForCharacterAnswers($seminary, $questgroup, $quest, $character, $data) + { + } + + /** * Check if answers of a Character for a Quest match the correct ones. * diff --git a/questtypes/submit/SubmitQuesttypeController.inc b/questtypes/submit/SubmitQuesttypeController.inc index 18e55d1b..e064c542 100644 --- a/questtypes/submit/SubmitQuesttypeController.inc +++ b/questtypes/submit/SubmitQuesttypeController.inc @@ -24,7 +24,7 @@ * * @var array */ - public $models = array('quests'); + public $models = array('quests', 'uploads', 'users'); @@ -41,11 +41,8 @@ */ public function saveAnswersOfCharacter($seminary, $questgroup, $quest, $character, $answers) { - // Get already submitted answer - $characterSubmission = $this->Submit->getCharacterSubmission($quest['id'], $character['id']); - // Save answer - if(is_null($characterSubmission) && array_key_exists('answers', $_FILES)) + if(array_key_exists('answers', $_FILES)) { $answer = $_FILES['answers']; @@ -78,8 +75,17 @@ ); } + // Create filename + $filename = sprintf( + '%s,%s,%s.%s', + $character['url'], + mb_substr($quest['url'], 0, 32), + date('Ymd-His'), + mb_substr(mb_substr($answer['name'], strrpos($answer['name'], '.')+1), 0, 4) + ); + // Save file - if(!$this->Submit->setCharacterSubmission($seminary['id'], $quest['id'], $this->Auth->getUserId(), $character['id'], $answer)) { + if(!$this->Submit->setCharacterSubmission($seminary['id'], $quest['id'], $this->Auth->getUserId(), $character['id'], $answer, $filename)) { throw new \hhu\z\exceptions\SubmissionNotValidException( new \hhu\z\exceptions\FileUploadException(error_get_last()['message']) ); @@ -88,6 +94,21 @@ } + /** + * Save additional data for the answers of a Character for a Quest. + * + * @param array $seminary Current Seminary data + * @param array $questgroup Current Questgroup data + * @param array $quest Current Quest data + * @param array $character Current Character data + * @param array $data Additional (POST-) data + */ + public function saveDataForCharacterAnswers($seminary, $questgroup, $quest, $character, $data) + { + $this->Submit->addCommentForCharacterAnswer($this->Auth->getUserId(), $data['submission_id'], $data['comment']); + } + + /** * Check if answers of a Character for a Quest match the correct ones. * @@ -119,19 +140,38 @@ */ public function quest($seminary, $questgroup, $quest, $character, $exception) { - // Answer (Submission) - $characterSubmission = $this->Submit->getCharacterSubmission($quest['id'], $character['id']); + // Answers (Submissions) + $characterSubmissions = $this->Submit->getCharacterSubmissions($quest['id'], $character['id']); + foreach($characterSubmissions as &$submission) + { + $submission['upload'] = $this->Uploads->getSeminaryuploadById($submission['upload_id']); + $submission['comments'] = $this->Submit->getCharacterSubmissionComments($submission['id']); + foreach($submission['comments'] as &$comment) + { + try { + $comment['user'] = $this->Users->getUserById($comment['created_user_id']); + $comment['user']['character'] = $this->Characters->getCharacterForUserAndSeminary($comment['user']['id'], $seminary['id']); + } + catch(\nre\exceptions\IdNotFoundException $e) { + } + } + } // Has Character already solved Quest? $solved = $this->Quests->hasCharacterSolvedQuest($quest['id'], $character['id']); + // Last Quest status for Character + $lastStatus = $this->Quests->getLastQuestStatus($quest['id'], $character['id']); + // Get allowed mimetypes $mimetypes = $this->Submit->getAllowedMimetypes($seminary['id']); // Pass data to view - $this->set('submission', $characterSubmission); + $this->set('seminary', $seminary); + $this->set('submissions', $characterSubmissions); $this->set('solved', $solved); + $this->set('lastStatus', $lastStatus); $this->set('mimetypes', $mimetypes); $this->set('exception', $exception); } @@ -149,15 +189,30 @@ */ public function submission($seminary, $questgroup, $quest, $character) { - // Get Character submission - $submission = $this->Submit->getCharacterSubmission($quest['id'], $character['id']); + // Get Character submissions + $submissions = $this->Submit->getCharacterSubmissions($quest['id'], $character['id']); + foreach($submissions as &$submission) + { + $submission['upload'] = $this->Uploads->getSeminaryuploadById($submission['upload_id']); + $submission['comments'] = $this->Submit->getCharacterSubmissionComments($submission['id']); + foreach($submission['comments'] as &$comment) + { + try { + $comment['user'] = $this->Users->getUserById($comment['created_user_id']); + $comment['user']['character'] = $this->Characters->getCharacterForUserAndSeminary($comment['user']['id'], $seminary['id']); + } + catch(\nre\exceptions\IdNotFoundException $e) { + } + } + } // Status $solved = $this->Quests->hasCharacterSolvedQuest($quest['id'], $character['id']); // Pass data to view - $this->set('submission', $submission); + $this->set('seminary', $seminary); + $this->set('submissions', $submissions); $this->set('solved', $solved); } diff --git a/questtypes/submit/SubmitQuesttypeModel.inc b/questtypes/submit/SubmitQuesttypeModel.inc index 2d0a17e3..5d821655 100644 --- a/questtypes/submit/SubmitQuesttypeModel.inc +++ b/questtypes/submit/SubmitQuesttypeModel.inc @@ -32,14 +32,15 @@ /** * Save Character’s submitted upload. * + * @param int $seminaryId ID of Seminary * @param int $questId ID of Quest * @param int $characterId ID of Character * @param array $file Submitted upload */ - public function setCharacterSubmission($seminaryId, $questId, $userId, $characterId, $file) + public function setCharacterSubmission($seminaryId, $questId, $userId, $characterId, $file, $filename) { // Save file on harddrive - $uploadId = $this->Uploads->uploadFile($userId, $file['name'], $file['tmp_name'], $file['type'], $seminaryId); + $uploadId = $this->Uploads->uploadSeminaryFile($userId, $seminaryId, $file['name'], $filename, $file['tmp_name'], $file['type']); if($uploadId === false) { return false; } @@ -60,27 +61,44 @@ /** - * Get upload submitted by Character. + * Add a comment for the answer of a Character. + * + * @param int $userId ID of user that comments + * @param int $submissionId ID of Character answer to comment + * @param string $comment Comment text + */ + public function addCommentForCharacterAnswer($userId, $submissionId, $comment) + { + $this->db->query( + 'INSERT INTO questtypes_submit_characters_comments '. + '(created_user_id, questtypes_submit_character_id, comment) '. + 'VALUES '. + '(?, ?, ?)', + 'iis', + $userId, + $submissionId, + $comment + ); + } + + + /** + * Get all uploads submitted by Character. * * @param int $questId ID of Quest * @param int $characterId ID of Character * @return array Text submitted by Character or NULL */ - public function getCharacterSubmission($questId, $characterId) + public function getCharacterSubmissions($questId, $characterId) { - $data = $this->db->query( - 'SELECT upload_id '. + return $this->db->query( + 'SELECT id, created, upload_id '. 'FROM questtypes_submit_characters '. - 'WHERE quest_id = ? AND character_id = ?', + 'WHERE quest_id = ? AND character_id = ? '. + 'ORDER BY created ASC', 'ii', $questId, $characterId ); - if(!empty($data)) { - return $this->Uploads->getUploadById($data[0]['upload_id']); - } - - - return null; } @@ -101,6 +119,24 @@ ); } + + /** + * Get all comments for a Character submission. + * + * @param int $characterSubmissionId ID of Character submission + * @return array Comments for this submission + */ + public function getCharacterSubmissionComments($characterSubmissionId) + { + return $this->db->query( + 'SELECT id, created, created_user_id, comment '. + 'FROM questtypes_submit_characters_comments '. + 'WHERE questtypes_submit_character_id = ?', + 'i', + $characterSubmissionId + ); + } + } ?> diff --git a/questtypes/submit/html/quest.tpl b/questtypes/submit/html/quest.tpl index 7132de5e..4581c40d 100644 --- a/questtypes/submit/html/quest.tpl +++ b/questtypes/submit/html/quest.tpl @@ -11,17 +11,42 @@

- + $submissions[count($submissions)-1]['created'])) : ?>

:

- - (format(new \DateTime($submission['created'])), $timeFormatter->format(new \DateTime($submission['created'])))?>) + + + 0) : ?> +

+
    + +
  1. +
    + format(new \DateTime($submission['created'])), $timeFormatter->format(new \DateTime($submission['created'])))?>
    + + + + 0) : ?> +
      + +
    1. + + format(new \DateTime($comment['created'])), $timeFormatter->format(new \DateTime($comment['created'])))?>:
      + + +
    2. + +
    + +
  2. + +
diff --git a/questtypes/submit/html/submission.tpl b/questtypes/submit/html/submission.tpl index b3d89275..f3c748ef 100644 --- a/questtypes/submit/html/submission.tpl +++ b/questtypes/submit/html/submission.tpl @@ -1,10 +1,32 @@ + 0) : ?> +
    + +
  1. +
    + format(new \DateTime($submission['created'])), $timeFormatter->format(new \DateTime($submission['created'])))?>
    + 0) : ?> +
      + +
    1. + + format(new \DateTime($comment['created'])), $timeFormatter->format(new \DateTime($comment['created'])))?>:
      + + +
    2. + +
    + +
  2. + +
+ +
- (format(new \DateTime($submission['created'])), $timeFormatter->format(new \DateTime($submission['created'])))?>) -

- - - - + + +
+
+ diff --git a/questtypes/textinput/TextinputQuesttypeController.inc b/questtypes/textinput/TextinputQuesttypeController.inc index 5be23690..02db2d8b 100644 --- a/questtypes/textinput/TextinputQuesttypeController.inc +++ b/questtypes/textinput/TextinputQuesttypeController.inc @@ -47,6 +47,20 @@ } + /** + * Save additional data for the answers of a Character for a Quest. + * + * @param array $seminary Current Seminary data + * @param array $questgroup Current Questgroup data + * @param array $quest Current Quest data + * @param array $character Current Character data + * @param array $data Additional (POST-) data + */ + public function saveDataForCharacterAnswers($seminary, $questgroup, $quest, $character, $data) + { + } + + /** * Check if answers of a Character for a Quest match the correct ones. *