diff --git a/controllers/AchievementsController.inc b/controllers/AchievementsController.inc index 9e9f2a5c..66e005d2 100644 --- a/controllers/AchievementsController.inc +++ b/controllers/AchievementsController.inc @@ -693,6 +693,10 @@ case 'achievement': $conditions = $this->Achievements->getAchievementConditionsAchievement($achievement['id']); break; + // QR-Code conditions + case 'qrcode': + $conditions = $this->Achievements->getAchievementConditionsQrcode($achievement['id']); + break; } // Values @@ -809,6 +813,12 @@ ); } break; + // QR-Code conditions + case 'qrcode': + if(array_key_exists($condition['id'], $deletes)) { + $this->Achievements->deleteAchievementConditionQrcode($condition['id']); + } + break; } } @@ -892,6 +902,16 @@ ); } break; + // QR-code conditions + case 'qrcode': + if(array_key_exists('qrcode', $condition)) + { + $this->Achievements->addAchievementConditionQrcode( + $this->Auth->getUserId(), + $achievement['id'] + ); + } + break; } } diff --git a/controllers/QrController.inc b/controllers/QrController.inc index 15c340d1..b335aad1 100644 --- a/controllers/QrController.inc +++ b/controllers/QrController.inc @@ -25,11 +25,84 @@ * * @var array */ - public $models = array('seminaries', 'charactergroups', 'charactergroupsquests', 'charactergroupsqueststations', 'charactergroupsachievements'); + public $models = array('seminaries', 'achievements', 'charactergroups', 'charactergroupsquests', 'charactergroupsqueststations', 'charactergroupsachievements'); + /** + * Action: a. + * + * Trigger an Achievement by a hash typically provided via a QR-code. + * + * @param $achievementConditionHash Hash value of QR-code condition of an Achievement + */ + public function a($achievementConditionHash) + { + // Check Achievement condition + $condition = $this->Achievements->getAchievementConditionQrcode( + $achievementConditionHash + ); + if(empty($condition)) { + throw new \nre\exceptions\IdNotFoundException($achievementConditionHash); + } + + // Get Achievement + $achievement = $this->Achievements->getAchievementById($condition['achievement_id']); + + // Get Seminary + $seminary = $this->Seminaries->getSeminaryById($achievement['seminary_id']); + + // Get Character + $character = $this->Characters->getCharacterForUserAndSeminary( + self::$user['id'], + $seminary['id'] + ); + + // Set Achievement achieved + $this->Achievements->setAchievementAchieved( + $achievement['id'], + $character['id'] + ); + + // Add notifications + $this->Notification->addNotification( + \hhu\z\controllers\components\NotificationComponent::TYPE_ACHIEVEMENT, + $achievement['title'], + $this->linker->link( + array( + 'achievements', + 'index', + $seminary['url'] + ), 0, true, null, true, $achievement['url'] + ), + ( + !is_null($achievement['achieved_achievementsmedia_id']) + ? $this->linker->link( + array( + 'media', + 'achievement', + $seminary['url'], + $achievement['url'] + ) + ) + : null + ) + ); + + // Redirect to Character profile + $this->redirect( + $this->linker->link( + array( + 'achievements', + 'index', + $seminary['url'] + ) + ) + ); + } + + /** * Action: cgqs. * diff --git a/controllers/QrcodesController.inc b/controllers/QrcodesController.inc index 256d1650..3598a223 100644 --- a/controllers/QrcodesController.inc +++ b/controllers/QrcodesController.inc @@ -24,7 +24,7 @@ * * @var array */ - public $models = array('seminaries', 'charactergroups', 'charactergroupsquests', 'charactergroupsqueststations', 'charactergroupsachievements'); + public $models = array('seminaries', 'achievements', 'charactergroups', 'charactergroupsquests', 'charactergroupsqueststations', 'charactergroupsachievements'); @@ -46,6 +46,48 @@ } + /** + * Action: achievement + * + * Display a QR-code for an Achievement. + * + * @throws \nre\exceptions\IdNotFoundException + * @param string $seminaryUrl URL-Title of a Seminary + * @param string $groupsgroupUrl URL-Title of a Character groups-group + * @param string $achievementUrl URL of Achievement + */ + public function achievement($seminaryUrl, $achievementUrl, $size=1) + { + // Get seminary + $seminary = $this->Seminaries->getSeminaryByUrl($seminaryUrl); + + // Get Achievement + $achievement = $this->Achievements->getAchievementByUrl( + $seminary['id'], + $achievementUrl + ); + + // Get condition + $conditions = $this->Achievements->getAchievementConditionsQrcode( + $achievement['id'] + ); + if(empty($conditions)) { + throw new IdNotFoundException($achievementUrl); + } + + // Generate QR-code + $url = $this->linker->link(array('qr', 'a', $conditions[0]['hash']), 0, true, null, true, null, true); + $file = $this->generateQRcode($url, $size); + if(is_null($file)) { + return; + } + + + // Pass data to view + $this->set('file', $file); + } + + /** * Action: charactergroupsqueststation * diff --git a/db/create.sql b/db/create.sql index 2fc813f8..2ceed202 100644 --- a/db/create.sql +++ b/db/create.sql @@ -100,6 +100,27 @@ CREATE TABLE `achievementconditions_date` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `achievementconditions_qrcode` +-- + +DROP TABLE IF EXISTS `achievementconditions_qrcode`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `achievementconditions_qrcode` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `created_user_id` int(11) NOT NULL, + `achievement_id` int(11) NOT NULL, + `hash` varchar(40) COLLATE utf8mb4_unicode_ci NOT NULL, + PRIMARY KEY (`id`), + KEY `created_user_id` (`created_user_id`), + KEY `achievement_id` (`achievement_id`), + CONSTRAINT `achievementconditions_qrcode_ibfk_1` FOREIGN KEY (`created_user_id`) REFERENCES `users` (`id`), + CONSTRAINT `achievementconditions_qrcode_ibfk_2` FOREIGN KEY (`achievement_id`) REFERENCES `achievements` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `achievementconditions_quest` -- diff --git a/locale/de_DE/LC_MESSAGES/The Legend of Z.mo b/locale/de_DE/LC_MESSAGES/The Legend of Z.mo index 0cf53c8d..edb15af3 100644 Binary files a/locale/de_DE/LC_MESSAGES/The Legend of Z.mo and b/locale/de_DE/LC_MESSAGES/The Legend of Z.mo differ diff --git a/locale/de_DE/LC_MESSAGES/The Legend of Z.po b/locale/de_DE/LC_MESSAGES/The Legend of Z.po index 7d7f8a39..f671e6f6 100644 --- a/locale/de_DE/LC_MESSAGES/The Legend of Z.po +++ b/locale/de_DE/LC_MESSAGES/The Legend of Z.po @@ -1,8 +1,8 @@ msgid "" msgstr "" "Project-Id-Version: The Legend of Z\n" -"POT-Creation-Date: 2016-03-12 17:24+0100\n" -"PO-Revision-Date: 2016-03-12 17:25+0100\n" +"POT-Creation-Date: 2016-03-12 19:17+0100\n" +"PO-Revision-Date: 2016-03-12 19:18+0100\n" "Last-Translator: \n" "Language-Team: \n" "Language: de_DE\n" @@ -72,7 +72,7 @@ msgstr "Lösungsvorschlag bewertet" #: controllers/QuestsController.inc:1247 #: questtypes/submit/html/submission.tpl:30 #: views/html/achievements/conditions.tpl:50 -#: views/html/achievements/conditions.tpl:117 +#: views/html/achievements/conditions.tpl:121 #: views/html/charactergroupsqueststations/station.tpl:180 #: views/html/quests/quest.tpl:68 views/html/quests/submissions.tpl:26 msgid "solved" @@ -111,7 +111,7 @@ msgstr "" #: questtypes/dragndrop/html/edittask.tpl:144 #: questtypes/multiplechoice/html/edittask.tpl:84 #: questtypes/textinput/html/edittask.tpl:44 -#: views/html/achievements/conditions.tpl:147 +#: views/html/achievements/conditions.tpl:152 #: views/html/achievements/edit.tpl:114 #: views/html/charactergroupsachievements/edit.tpl:69 #: views/html/charactergroupsqueststations/edit.tpl:177 @@ -254,9 +254,9 @@ msgstr "Schritt %d" #: views/html/achievements/conditions.tpl:18 #: views/html/achievements/conditions.tpl:27 #: views/html/achievements/conditions.tpl:55 -#: views/html/achievements/conditions.tpl:85 -#: views/html/achievements/conditions.tpl:94 -#: views/html/achievements/conditions.tpl:122 +#: views/html/achievements/conditions.tpl:89 +#: views/html/achievements/conditions.tpl:98 +#: views/html/achievements/conditions.tpl:126 msgid "Field" msgstr "Feld" @@ -444,7 +444,7 @@ msgstr "Kommentar" #: questtypes/submit/html/submission.tpl:31 #: views/html/achievements/conditions.tpl:49 -#: views/html/achievements/conditions.tpl:116 +#: views/html/achievements/conditions.tpl:120 #: views/html/charactergroupsqueststations/station.tpl:197 #: views/html/quests/quest.tpl:73 views/html/quests/submissions.tpl:16 msgid "unsolved" @@ -559,7 +559,7 @@ msgid "Conditions" msgstr "Bedingungen" #: views/html/achievements/conditions.tpl:15 -#: views/html/achievements/conditions.tpl:82 +#: views/html/achievements/conditions.tpl:86 msgid "Date" msgstr "Datum" @@ -569,23 +569,23 @@ msgstr "Datum" #: views/html/achievements/conditions.tpl:36 #: views/html/achievements/conditions.tpl:63 #: views/html/achievements/conditions.tpl:64 -#: views/html/achievements/conditions.tpl:91 -#: views/html/achievements/conditions.tpl:102 -#: views/html/achievements/conditions.tpl:103 -#: views/html/achievements/conditions.tpl:130 -#: views/html/achievements/conditions.tpl:131 +#: views/html/achievements/conditions.tpl:95 +#: views/html/achievements/conditions.tpl:106 +#: views/html/achievements/conditions.tpl:107 +#: views/html/achievements/conditions.tpl:134 +#: views/html/achievements/conditions.tpl:135 msgid "Value" msgstr "Wert" #: views/html/achievements/conditions.tpl:34 #: views/html/achievements/conditions.tpl:62 -#: views/html/achievements/conditions.tpl:101 -#: views/html/achievements/conditions.tpl:129 +#: views/html/achievements/conditions.tpl:105 +#: views/html/achievements/conditions.tpl:133 msgid "Count" msgstr "Zählen" #: views/html/achievements/conditions.tpl:37 -#: views/html/achievements/conditions.tpl:104 views/html/quests/quest.tpl:145 +#: views/html/achievements/conditions.tpl:108 views/html/quests/quest.tpl:145 #: views/html/quests/quest.tpl:161 msgid "Quest" msgstr "Quest" @@ -593,24 +593,24 @@ msgstr "Quest" #: views/html/achievements/conditions.tpl:39 #: views/html/achievements/conditions.tpl:46 #: views/html/achievements/conditions.tpl:67 -#: views/html/achievements/conditions.tpl:106 -#: views/html/achievements/conditions.tpl:113 -#: views/html/achievements/conditions.tpl:134 +#: views/html/achievements/conditions.tpl:110 +#: views/html/achievements/conditions.tpl:117 +#: views/html/achievements/conditions.tpl:138 msgid "unset" msgstr "nicht gesetzt" #: views/html/achievements/conditions.tpl:44 -#: views/html/achievements/conditions.tpl:111 +#: views/html/achievements/conditions.tpl:115 msgid "Status" msgstr "Status" #: views/html/achievements/conditions.tpl:47 -#: views/html/achievements/conditions.tpl:114 +#: views/html/achievements/conditions.tpl:118 msgid "entered" msgstr "betreten" #: views/html/achievements/conditions.tpl:48 -#: views/html/achievements/conditions.tpl:115 +#: views/html/achievements/conditions.tpl:119 #: views/html/quests/submissions.tpl:6 msgid "submitted" msgstr "eingereicht" @@ -619,20 +619,20 @@ msgstr "eingereicht" #: views/html/achievements/conditions.tpl:53 #: views/html/achievements/conditions.tpl:72 #: views/html/achievements/conditions.tpl:73 -#: views/html/achievements/conditions.tpl:119 -#: views/html/achievements/conditions.tpl:120 -#: views/html/achievements/conditions.tpl:139 -#: views/html/achievements/conditions.tpl:140 +#: views/html/achievements/conditions.tpl:123 +#: views/html/achievements/conditions.tpl:124 +#: views/html/achievements/conditions.tpl:143 +#: views/html/achievements/conditions.tpl:144 msgid "Group by" msgstr "Gruppiert über" #: views/html/achievements/conditions.tpl:65 -#: views/html/achievements/conditions.tpl:132 views/html/html.tpl:82 +#: views/html/achievements/conditions.tpl:136 views/html/html.tpl:82 #: views/html/html.tpl:94 msgid "Achievement" msgstr "Achievement" -#: views/html/achievements/conditions.tpl:77 +#: views/html/achievements/conditions.tpl:81 #: views/html/achievements/delete.tpl:10 views/html/achievements/manage.tpl:21 #: views/html/charactergroups/deletegroup.tpl:11 #: views/html/charactergroups/deletegroupsgroup.tpl:10 @@ -651,11 +651,15 @@ msgstr "Achievement" msgid "delete" msgstr "löschen" -#: views/html/achievements/conditions.tpl:83 -#: views/html/achievements/conditions.tpl:92 +#: views/html/achievements/conditions.tpl:87 +#: views/html/achievements/conditions.tpl:96 msgid "New condition" msgstr "Neue Bedingung" +#: views/html/achievements/conditions.tpl:147 +msgid "create new QR-Code" +msgstr "einen neuen QR-Code erstellen" + #: views/html/achievements/create.tpl:7 msgid "Create Achievement" msgstr "Achievement erstellen" @@ -2627,6 +2631,9 @@ msgstr "Ein neuer Benutzer wurde registriert" msgid "Hello %s" msgstr "Hallo %s" +#~ msgid "Create new QR-Code" +#~ msgstr "Einen neuen QR-Code erstellen" + #~ msgid "Introduction" #~ msgstr "Einführung" diff --git a/models/AchievementsModel.inc b/models/AchievementsModel.inc index 22bc78b7..265eaee3 100644 --- a/models/AchievementsModel.inc +++ b/models/AchievementsModel.inc @@ -1019,6 +1019,110 @@ } + /** + * Get all QR-code conditions for an Achievement. + * + * @param int $achievementId ID of Achievement + * @return array List of QR-code conditions + */ + public function getAchievementConditionsQrcode($achievementId) + { + return $this->db->query( + 'SELECT id, hash '. + 'FROM achievementconditions_qrcode '. + 'WHERE achievement_id = ?', + 'i', + $achievementId + ); + } + + + /** + * Get QR-code condition for a hash value. + * + * @param string $hash Hash value to get condition for + * @return array QR-code condition or null + */ + public function getAchievementConditionQrcode($hash) + { + $data = $this->db->query( + 'SELECT id, achievement_id, hash '. + 'FROM achievementconditions_qrcode '. + 'WHERE hash = ?', + 's', + $hash + ); + if(!empty($data)) { + return $data[0]; + } + + + return null; + } + + + /** + * Add a new QR-code condition. + * + * @param int $userId ID of creating user + * @param int $achievementId ID of Achievement to add condition to + */ + public function addAchievementConditionQrcode($userId, $achievementId) + { + // Delete all existing QR-codes, we allow only one per Achievement + $this->db->query( + 'DELETE FROM achievementconditions_qrcode WHERE achievement_id = ?', + 'i', + $achievementId + ); + + // Create new QR-code condition + $this->db->query( + 'INSERT INTO achievementconditions_qrcode '. + '(created_user_id, achievement_id, hash) '. + 'VALUES '. + '(?, ?, ?)', + 'iis', + $userId, $achievementId, + \hhu\z\Utils::createRandomHash() + ); + } + + + /** + * Copy all QR-code conditions of an Achievement. + * + * @param int $userId ID of creating user + * @param int $sourceAchievementId ID of Achievement to copy conditions from + * @param int $targetAchievementId ID of Achievement to copy conditions to + */ + public function copyAchievementConditionsQrcode($userId, $sourceAchievementId, $targetAchievementId) + { + $this->db->query( + 'INSERT INTO achievementconditions_qrcode '. + '(created_user_id, achievement_id, hash) '. + 'SELECT ?, ?, ? '. + 'FROM achievementconditions_qrcode '. + 'WHERE achievement_id = ?', + 'iisi', + $userId, $targetAchievementId, + \hhu\z\Utils::createRandomHash(), + $sourceAchievementId + ); + } + + + /** + * Delete a QR-code condition. + * + * @param int $conditionId ID of condition to delete + */ + public function deleteAchievementConditionQrcode($conditionId) + { + $this->db->query('DELETE FROM achievementconditions_qrcode WHERE id = ?', 'i', $conditionId); + } + + /** * Set an Achievement as achieved for a Character. * @@ -1364,6 +1468,13 @@ case 'achievement': $this->copyAchievementConditionsAchievement($userId, $achievement['id'], $achievementIds[$achievement['id']], $achievementIds); break; + case 'qrcode': + $this->copyAchievementConditionsQrcode( + $userId, + $achievement['id'], + $achievementIds[$achievement['id']] + ); + break; } } } diff --git a/views/binary/qrcodes/achievement.tpl b/views/binary/qrcodes/achievement.tpl new file mode 100644 index 00000000..0d6fb0df --- /dev/null +++ b/views/binary/qrcodes/achievement.tpl @@ -0,0 +1 @@ + diff --git a/views/html/achievements/conditions.tpl b/views/html/achievements/conditions.tpl index 8091fe7d..d123cc80 100644 --- a/views/html/achievements/conditions.tpl +++ b/views/html/achievements/conditions.tpl @@ -71,6 +71,10 @@
+ + + +
checked="checked" /> @@ -138,8 +142,9 @@
- - hallo + + +
diff --git a/views/html/achievements/create.tpl b/views/html/achievements/create.tpl index 0dbc3593..3b0f6843 100644 --- a/views/html/achievements/create.tpl +++ b/views/html/achievements/create.tpl @@ -96,6 +96,8 @@ break; case 'achievement': echo _('Achievement conditions Achievement'); break; + case 'qrcode': echo _('QR-Code'); + break; } ?> diff --git a/views/html/achievements/edit.tpl b/views/html/achievements/edit.tpl index bc67eb85..0b719a74 100644 --- a/views/html/achievements/edit.tpl +++ b/views/html/achievements/edit.tpl @@ -102,6 +102,8 @@ break; case 'achievement': echo _('Achievement conditions Achievement'); break; + case 'qrcode': echo _('QR-Code'); + break; } ?> diff --git a/views/html/qr/a.tpl b/views/html/qr/a.tpl new file mode 100644 index 00000000..e69de29b