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 @@
+=$file?>
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