From da6c132216cd605c7dcd19c55f279eeb817e21cf Mon Sep 17 00:00:00 2001
From: coderkun
Date: Thu, 19 Jun 2014 20:13:46 +0200
Subject: [PATCH] implement CRUD for Questgroups (issue #32)
---
agents/intermediate/QuestgroupsAgent.inc | 18 +
configs/AppConfig.inc | 8 +-
controllers/QuestgroupsController.inc | 399 ++++++++++++++++++++++-
models/MediaModel.inc | 54 +++
models/QuestgroupsModel.inc | 178 ++++++++++
views/html/questgroups/create.tpl | 67 +++-
views/html/questgroups/delete.tpl | 19 ++
views/html/questgroups/edit.tpl | 65 ++++
views/html/questgroups/movedown.tpl | 0
views/html/questgroups/moveup.tpl | 0
views/html/questgroups/questgroup.tpl | 44 ++-
views/html/seminaries/seminary.tpl | 28 +-
12 files changed, 852 insertions(+), 28 deletions(-)
create mode 100644 views/html/questgroups/delete.tpl
create mode 100644 views/html/questgroups/edit.tpl
create mode 100644 views/html/questgroups/movedown.tpl
create mode 100644 views/html/questgroups/moveup.tpl
diff --git a/agents/intermediate/QuestgroupsAgent.inc b/agents/intermediate/QuestgroupsAgent.inc
index 52ecd4e1..df9457ce 100644
--- a/agents/intermediate/QuestgroupsAgent.inc
+++ b/agents/intermediate/QuestgroupsAgent.inc
@@ -31,6 +31,24 @@
$this->addSubAgent('Questgroupshierarchypath', 'index', $request->getParam(3), $request->getParam(4));
}
+
+ /**
+ * Action: edit.
+ */
+ public function edit(\nre\core\Request $request, \nre\core\Response $response)
+ {
+ $this->addSubAgent('Questgroupshierarchypath', 'index', $request->getParam(3), $request->getParam(4));
+ }
+
+
+ /**
+ * Action: delete.
+ */
+ public function delete(\nre\core\Request $request, \nre\core\Response $response)
+ {
+ $this->addSubAgent('Questgroupshierarchypath', 'index', $request->getParam(3), $request->getParam(4));
+ }
+
}
?>
diff --git a/configs/AppConfig.inc b/configs/AppConfig.inc
index 5c68793f..e69f095b 100644
--- a/configs/AppConfig.inc
+++ b/configs/AppConfig.inc
@@ -237,7 +237,8 @@
array('^seminaries/(?!(index|create|edit|delete|calculatexps))/?', 'seminaries/seminary/$1', true),
array('^questgroupshierarchy/([^/]+)/create/?$', 'questgroupshierarchy/create/$1', true),
array('^questgroupshierarchy/([^/]+)/([^/]+)/(edit|delete|moveup|movedown)/?$', 'questgroupshierarchy/$3/$1/$2', true),
- array('^questgroups/([^/]+)/(create)/?$', 'questgroups/$2/$1', true),
+ array('^questgroups/([^/]+)/create/?$', 'questgroups/create/$1', true),
+ array('^questgroups/([^/]+)/([^/]+)/(edit|delete|moveup|movedown)/?$', 'questgroups/$3/$1/$2', true),
array('^questgroups/([^/]+)/([^/]+)/?$', 'questgroups/questgroup/$1/$2', true),
array('^quests/([^/]+)/?$', 'quests/index/$1', true),
array('^quests/([^/]+)/all/?$', 'quests/index/$1/all', true),
@@ -283,8 +284,9 @@
array('^seminaries/seminary/(.*)$', 'seminaries/$1', false),
array('^questgroupshierarchy/create/(.*)$', 'questgroupshierarchy/$1/create', true),
array('^questgroupshierarchy/([^/]+)/(.*)$', 'questgroupshierarchy/$2/$1', true),
- array('^questgroups/create/(.*)$', 'questgroups/$2/$1', true),
- array('^questgroups/questgroup/(.*)$', 'questgroups/$1', true),
+ array('^questgroups/create/(.*)$', 'questgroups/$1/create', true),
+ array('^questgroups/questgroup/(.*)$', 'questgroups/$1', true),
+ array('^questgroups/(edit|delete|moveup|movedown)/(.*)$', 'questgroups/$2/$1', true),
array('^quests/index/(.+)$', 'quests/$1', true),
array('^quests/quest/(.*)$', 'quests/$1', true),
array('^quests/(create|createmedia)/(.*)$', 'quests/$2/$1' , true),
diff --git a/controllers/QuestgroupsController.inc b/controllers/QuestgroupsController.inc
index 43402ce1..2dcd3d84 100644
--- a/controllers/QuestgroupsController.inc
+++ b/controllers/QuestgroupsController.inc
@@ -25,6 +25,12 @@
* @var array
*/
public $models = array('seminaries', 'questgroupshierarchy', 'questgroups', 'quests', 'questtexts', 'media');
+ /**
+ * Required components
+ *
+ * @var array
+ */
+ public $components = array('validation');
/**
* User permissions
*
@@ -32,7 +38,11 @@
*/
public $permissions = array(
'questgroup' => array('admin', 'moderator', 'user'),
- 'create' => array('admin', 'moderator', 'user')
+ 'create' => array('admin', 'moderator', 'user'),
+ 'edit' => array('admin', 'moderator', 'user'),
+ 'moveup' => array('admin', 'moderator', 'user'),
+ 'movedown' => array('admin', 'moderator', 'user'),
+ 'delete' => array('admin', 'moderator', 'user')
);
/**
* User seminary permissions
@@ -41,7 +51,11 @@
*/
public $seminaryPermissions = array(
'questgroup' => array('admin', 'moderator', 'user'),
- 'create' => array('admin', 'moderator')
+ 'create' => array('admin'),
+ 'edit' => array('admin'),
+ 'moveup' => array('admin'),
+ 'movedown' => array('admin'),
+ 'delete' => array('admin')
);
@@ -216,13 +230,72 @@
// Get seminary
$seminary = $this->Seminaries->getSeminaryByUrl($seminaryUrl);
- // Create Questgroup
- $validation = true;
+ // Get allowed mimetypes
+ $mimetypes = \nre\configs\AppConfig::$mimetypes['moodpics'];
+
+ // Values
+ $selectedQuestgroupshierarchy = null;
+ $selectedQuestgroup = null;
+ $title = '';
+ $fields = array('title');
+ $validation = array();
+
+ // Check request method
if($this->request->getRequestMethod() == 'POST' && !is_null($this->request->getPostParam('create')))
{
- // TODO Validation
+ // Get params and validate them
+ $validation = $this->Validation->validateParams($this->request->getPostParams(), $fields);
$title = $this->request->getPostParam('title');
+ if($this->Questgroups->questgroupTitleExists($seminary['id'], $title)) {
+ $validation = $this->Validation->addValidationResult($validation, 'title', 'exist', true);
+ }
+
+ // Validate Questgroupshierarchy
+ try {
+ $selectedQuestgroupshierarchy = $this->Questgroupshierarchy->getHierarchyByUrl($seminary['id'], $this->request->getPostParam('questgroupshierarchy'));
+ }
+ catch(\nre\exceptions\IdNotFoundException $e) {
+ throw new \nre\exceptions\ParamsNotValidException($this->request->getPostParam('questgroupshierarchy'));
+ }
+
+ // Validate Questgroup
+ if(!is_null($selectedQuestgroupshierarchy['parent_questgroupshierarchy_id'])) {
+ try {
+ $selectedQuestgroup = $this->Questgroups->getQuestgroupByUrl($seminary['id'], $this->request->getPostParam('questgroup'));
+ }
+ catch(\nre\exceptions\IdNotFoundException $e) {
+ throw new \nre\exceptions\ParamsNotValidException($this->request->getPostParam('questgroups'));
+ }
+ }
+
+ // Validate moodpic
+ $moodpic = null;
+ if(!empty($_FILES) && array_key_exists('moodpic', $_FILES) && $_FILES['moodpic']['error'] != UPLOAD_ERR_NO_FILE)
+ {
+ $moodpic = $_FILES['moodpic'];
+ // Check error
+ if($moodpic['error'] !== UPLOAD_ERR_OK) {
+ $validation = $this->Validation->addValidationResult($validation, 'moodpic', 'error', $moodpic['error']);
+ }
+
+ // Check mimetype
+ $mediaMimetype = null;
+ $moodpic['mimetype'] = \hhu\z\Utils::getMimetype($moodpic['tmp_name'], $moodpic['type']);
+ foreach($mimetypes as &$mimetype) {
+ if($mimetype['mimetype'] == $moodpic['mimetype']) {
+ $mediaMimetype = $mimetype;
+ break;
+ }
+ }
+ if(is_null($mediaMimetype)) {
+ $validation = $this->Validation->addValidationResult($validation, 'moodpic', 'mimetype', $moodpic['mimetype']);
+ }
+ elseif($moodpic['size'] > $mediaMimetype['size']) {
+ $validation = $this->Validation->addValidationResult($validation, 'moodpic', 'size', $mediaMimetype['size']);
+ }
+ }
+
// Create new Questgroup
if($validation === true)
{
@@ -231,19 +304,329 @@
$seminary['id'],
$title
);
+ $questgroup = $this->Questgroups->getQuestgroupById($questgroupId);
+
+ // Add to Hierarchy
+ $this->Questgroups->addQuestgroupToHierarchy(
+ $questgroupId,
+ $selectedQuestgroupshierarchy['id'],
+ (!is_null($selectedQuestgroup)) ? $selectedQuestgroup['id'] : null
+ );
- // Redirect
- $this->redirect($this->linker->link(array('seminaries', 'seminary', $seminary['url'])));
+ // Upload moodpic
+ var_dump($moodpic);
+ if(!is_null($moodpic))
+ {
+ $mediaId = $this->Media->createQuestgrouppicture(
+ $this->Auth->getUserId(),
+ $seminary['id'],
+ $questgroup['id'],
+ sprintf('questgroupmoodpic-%s', $questgroup['url']),
+ '',
+ $moodpic['mimetype'],
+ $moodpic['tmp_name']
+ );
+ if($mediaId !== false) {
+ $this->Questgroups->setMoodpicForQuestgroup($questgroup['id'], $mediaId);
+ }
+ }
+
+
+ // Redirect to new Questgroup
+ $this->redirect($this->linker->link(array('questgroup', $seminary['url'], $questgroup['url']), 1));
}
}
+
+ // Get validation settings
+ $validationSettings = array();
+ foreach($fields as &$field) {
+ $validationSettings[$field] = \nre\configs\AppConfig::$validation[$field];
+ }
-
+
// Set titile
$this->addTitleLocalized('Create Questgroup');
$this->addTitle($seminary['title']);
// Pass data to view
$this->set('seminary', $seminary);
+ $this->set('mimetypes', $mimetypes);
+ $this->set('questgroupshierarchy', $selectedQuestgroupshierarchy);
+ $this->set('questgroup', $selectedQuestgroup);
+ $this->set('title', $title);
+ $this->set('validation', $validation);
+ $this->set('validationSettings', $validationSettings);
+ }
+
+
+ /**
+ * Action: edit.
+ *
+ * Edit a Questgroup.
+ *
+ * @throws IdNotFoundException
+ * @param string $seminaryUrl URL-title of a Seminary
+ * @param string $questgroupUrl URL-title of Questgroup to edit
+ */
+ public function edit($seminaryUrl, $questgroupUrl)
+ {
+ // Get seminary
+ $seminary = $this->Seminaries->getSeminaryByUrl($seminaryUrl);
+
+ // Get Questgroup
+ $questgroup = $this->Questgroups->getQuestgroupByUrl($seminary['id'], $questgroupUrl);
+
+ // Get allowed mimetypes
+ $mimetypes = \nre\configs\AppConfig::$mimetypes['moodpics'];
+
+ // Values
+ $title = $questgroup['title'];
+ $fields = array('title');
+ $validation = array();
+
+ // Check request method
+ if($this->request->getRequestMethod() == 'POST' && !is_null($this->request->getPostParam('edit')))
+ {
+ // Get params and validate them
+ $validation = $this->Validation->validateParams($this->request->getPostParams(), $fields);
+ $title = $this->request->getPostParam('title');
+ if($this->Questgroups->questgroupTitleExists($seminary['id'], $title, $questgroup['id'])) {
+ $validation = $this->Validation->addValidationResult($validation, 'title', 'exist', true);
+ }
+
+ // Validate moodpic
+ $moodpic = null;
+ if(!empty($_FILES) && array_key_exists('moodpic', $_FILES) && $_FILES['moodpic']['error'] != UPLOAD_ERR_NO_FILE)
+ {
+ $moodpic = $_FILES['moodpic'];
+
+ // Check error
+ if($moodpic['error'] !== UPLOAD_ERR_OK) {
+ $validation = $this->Validation->addValidationResult($validation, 'moodpic', 'error', $moodpic['error']);
+ }
+
+ // Check mimetype
+ $mediaMimetype = null;
+ $moodpic['mimetype'] = \hhu\z\Utils::getMimetype($moodpic['tmp_name'], $moodpic['type']);
+ foreach($mimetypes as &$mimetype) {
+ if($mimetype['mimetype'] == $moodpic['mimetype']) {
+ $mediaMimetype = $mimetype;
+ break;
+ }
+ }
+ if(is_null($mediaMimetype)) {
+ $validation = $this->Validation->addValidationResult($validation, 'moodpic', 'mimetype', $moodpic['mimetype']);
+ }
+ elseif($moodpic['size'] > $mediaMimetype['size']) {
+ $validation = $this->Validation->addValidationResult($validation, 'moodpic', 'size', $mediaMimetype['size']);
+ }
+ }
+
+ // Edit Questgroup
+ if($validation === true)
+ {
+ $this->Questgroups->editQuestgroup(
+ $questgroup['id'],
+ $title
+ );
+ $questgroup = $this->Questgroups->getQuestgroupById($questgroup['id']);
+
+ // Upload moodpic
+ if(!is_null($moodpic))
+ {
+ $mediaId = $this->Media->createQuestgrouppicture(
+ $this->Auth->getUserId(),
+ $seminary['id'],
+ $questgroup['id'],
+ sprintf('questgroupmoodpic-%s', $questgroup['url']),
+ '',
+ $moodpic['mimetype'],
+ $moodpic['tmp_name']
+ );
+ if($mediaId !== false) {
+ $this->Questgroups->setMoodpicForQuestgroup($questgroup['id'], $mediaId);
+ }
+ }
+
+
+ // Redirect to new Questgroup
+ $this->redirect($this->linker->link(array('questgroup', $seminary['url'], $questgroup['url']), 1));
+ }
+ }
+
+ // Media
+ $picture = null;
+ if(!is_null($questgroup['questgroupspicture_id'])) {
+ $picture = $this->Media->getSeminaryMediaById($questgroup['questgroupspicture_id']);
+ }
+
+ // Get validation settings
+ $validationSettings = array();
+ foreach($fields as &$field) {
+ $validationSettings[$field] = \nre\configs\AppConfig::$validation[$field];
+ }
+
+
+ // Set titile
+ $this->addTitleLocalized('Edit Questgroup');
+ $this->addTitle($seminary['title']);
+
+ // Pass data to view
+ $this->set('seminary', $seminary);
+ $this->set('questgroup', $questgroup);
+ $this->set('picture', $picture);
+ $this->set('title', $title);
+ $this->set('mimetypes', $mimetypes);
+ $this->set('validation', $validation);
+ $this->set('validationSettings', $validationSettings);
+ }
+
+
+ /**
+ * Action: moveup.
+ *
+ * Move a Questgroup up (decrement position).
+ *
+ * @throws IdNotFoundException
+ * @param string $seminaryUrl URL-title of Seminary
+ * @param string $questgroupUrl URL-title of Questgroup
+ */
+ public function moveup($seminaryUrl, $questgroupUrl)
+ {
+ // Get Seminary
+ $seminary = $this->Seminaries->getSeminaryByUrl($seminaryUrl);
+
+ // Get Questgroup
+ $questgroup = $this->Questgroups->getQuestgroupByUrl($seminary['id'], $questgroupUrl);
+ $questgroup['hierarchy'] = $this->Questgroupshierarchy->getHierarchyForQuestgroup($questgroup['id']);
+
+ // Set position
+ $this->Questgroups->moveQuestgroup($questgroup, true);
+
+
+ // Redirect
+ $referer = $this->request->getGetParam('referer');
+ if(!is_null($referer))
+ {
+ try {
+ $questgroup = $this->Questgroups->getQuestgroupById($referer);
+ $this->redirect($this->linker->link(array('questgroups', 'questgroup', $seminary['url'], $questgroup['url'])));
+ }
+ catch(IdNotFoundException $e) {
+ }
+ }
+ $this->redirect($this->linker->link(array('seminaries', 'seminary', $seminary['url'])));
+ }
+
+
+ /**
+ * Action: movedown
+ *
+ * Move a Questgroup down (increment position).
+ *
+ * @throws IdNotFoundException
+ * @param string $seminaryUrl URL-title of Seminary
+ * @param string $questgroupUrl URL-title of Questgroup
+ */
+ public function movedown($seminaryUrl, $questgroupUrl)
+ {
+ // Get Seminary
+ $seminary = $this->Seminaries->getSeminaryByUrl($seminaryUrl);
+
+ // Get Questgroup
+ $questgroup = $this->Questgroups->getQuestgroupByUrl($seminary['id'], $questgroupUrl);
+ $questgroup['hierarchy'] = $this->Questgroupshierarchy->getHierarchyForQuestgroup($questgroup['id']);
+
+ // Set position
+ $this->Questgroups->moveQuestgroup($questgroup, false);
+
+
+ // Redirect
+ $referer = $this->request->getGetParam('referer');
+ if(!is_null($referer))
+ {
+ try {
+ $questgroup = $this->Questgroups->getQuestgroupById($referer);
+ $this->redirect($this->linker->link(array('questgroups', 'questgroup', $seminary['url'], $questgroup['url'])));
+ }
+ catch(IdNotFoundException $e) {
+ }
+ }
+ $this->redirect($this->linker->link(array('seminaries', 'seminary', $seminary['url'])));
+ }
+
+
+ /**
+ * Action: delete.
+ *
+ * Delete a Questgroup.
+ *
+ * @throws IdNotFoundException
+ * @param string $seminaryUrl URL-Title of a Seminary
+ * @param string $questgroupUrl URL-Title of a Questgroup
+ */
+ public function delete($seminaryUrl, $questgroupUrl)
+ {
+ // Get Seminary
+ $seminary = $this->Seminaries->getSeminaryByUrl($seminaryUrl);
+
+ // Get Questgroup
+ $questgroup = $this->Questgroups->getQuestgroupByUrl($seminary['id'], $questgroupUrl);
+
+ // Get Questgrouphierarchy
+ $questgroup['hierarchy'] = $this->Questgroupshierarchy->getHierarchyForQuestgroup($questgroup['id']);
+
+ // Check request method
+ if($this->request->getRequestMethod() == 'POST')
+ {
+ // Check confirmation
+ if(!is_null($this->request->getPostParam('delete')))
+ {
+ // Delete Questgroup
+ $this->Questgroups->deleteQuestgroup($questgroup['id']);
+
+ // Redirect
+ if(!is_null($questgroup['hierarchy']))
+ {
+ // Parent Questgroup
+ if(is_null($questgroup['hierarchy']['parent_questgroup_id'])) {
+ $this->redirect($this->linker->link(array('simenaries', 'seminary', $seminary['url'])));
+ }
+ else
+ {
+ $parentQuestgroup = $this->Questgroups->getQuestgroupById($questgroup['hierarchy']['parent_questgroup_id']);
+ $this->redirect($this->linker->link(array('questgroup', $seminary['url'], $parentQuestgroup['url']), 1));
+ }
+ }
+ else
+ {
+ // Related Questgroup
+ $questtexts = $this->Questtexts->getRelatedQuesttextsForQuestgroup($questgroup['id']);
+ $questtext = $this->Questtexts->pickQuesttextLastEnteredByCharacter(\hhu\z\controllers\SeminaryController::$character['id'], $questtexts);
+ $quest = $this->Quests->getQuestById($questtext['quest_id']);
+ $relatedQuestgroup = $this->Questgroups->getQuestgroupById($quest['questgroup_id']);
+ $this->redirect($this->linker->link(array('questgroup', $seminary['url'], $relatedQuestgroup['url']), 1));
+ }
+ }
+
+ // Redirect to entry
+ $this->redirect($this->linker->link(array('questgroup', $seminary['url'], $questgroup['url']), 1));
+ }
+
+ // Media
+ $picture = null;
+ if(!is_null($questgroup['questgroupspicture_id'])) {
+ $picture = $this->Media->getSeminaryMediaById($questgroup['questgroupspicture_id']);
+ }
+
+
+ // Set titile
+ $this->addTitleLocalized('Delete Questgroup');
+
+ // Show confirmation
+ $this->set('seminary', $seminary);
+ $this->set('questgroup', $questgroup);
+ $this->set('picture', $picture);
}
}
diff --git a/models/MediaModel.inc b/models/MediaModel.inc
index c1cdf6c7..ca709c19 100644
--- a/models/MediaModel.inc
+++ b/models/MediaModel.inc
@@ -172,6 +172,60 @@
$this->db->setAutocommit(true);
return $mediaId;
}
+
+
+ /**
+ * Create a new Questgroup picture (Moodpic).
+ *
+ * @param int $userId ID of user that does the upload
+ * @param int $seminaryId ID of Seminary
+ * @param int $questgroupId ID of Questgroup to create picture for
+ * @param string $filename Filename of uploading media
+ * @param string $description Description for media
+ * @param string $mimetype Mimetype of media
+ * @param string $tmpFilename Name of temporary uploaded file
+ * @return mixed ID of media record or false if upload failed
+ */
+ public function createQuestgrouppicture($userId, $seminaryId, $questgroupId, $filename, $description, $mimetype, $tmpFilename)
+ {
+ $mediaId = false;
+ $this->db->setAutocommit(false);
+
+ try {
+ // Create Seminary media record
+ $mediaId = $this->createSeminaryMedia($userId, $seminaryId, $filename, $description, $mimetype);
+
+ // Add media to Questgroups pictures
+ $this->db->query(
+ 'INSERT INTO questgroupspictures '.
+ '(media_id, created_user_id) '.
+ 'VALUES '.
+ '(?, ?) '.
+ 'ON DUPLICATE KEY UPDATE '.
+ 'created_user_id = ?',
+ 'iii',
+ $mediaId,
+ $userId,
+ $userId
+ );
+
+ // Upload file
+ $filename = ROOT.DS.\nre\configs\AppConfig::$dirs['seminarymedia'].DS.$mediaId;
+ if(!move_uploaded_file($tmpFilename, $filename))
+ {
+ $this->db->rollback();
+ $mediaId = false;
+ }
+ }
+ catch(\nre\exceptions\DatamodelException $e) {
+ $this->db->rollback();
+ $this->db->setAutocommit(true);
+ }
+
+
+ $this->db->setAutocommit(true);
+ return $mediaId;
+ }
/**
diff --git a/models/QuestgroupsModel.inc b/models/QuestgroupsModel.inc
index 36d741db..9525126e 100644
--- a/models/QuestgroupsModel.inc
+++ b/models/QuestgroupsModel.inc
@@ -479,6 +479,30 @@
}
+ /**
+ * Check if a Questgroups title already exists for a Seminary.
+ *
+ * @param int $seminaryId ID of Seminary
+ * @param string $title Questgroup title to check
+ * @param int $questgroupId Do not check this ID (for editing)
+ * @return boolean Whether Questgroup title exists or not
+ */
+ public function questgroupTitleExists($seminaryId, $title, $questgroupId=null)
+ {
+ $data = $this->db->query(
+ 'SELECT id '.
+ 'FROM questgroups '.
+ 'WHERE seminary_id = ? AND (title = ? OR url = ?)',
+ 'iss',
+ $seminaryId,
+ $title,
+ \nre\core\Linker::createLinkParam($title)
+ );
+
+ return (!empty($data) && (is_null($questgroupId) || $questgroupId != $data[0]['id']));
+ }
+
+
/**
* Create a new Questgroup.
*
@@ -504,6 +528,160 @@
return $this->db->getInsertId();
}
+
+
+ /**
+ * Set the moodpic for a Questgroup.
+ *
+ * @param int $questgroupId ID of Questgroup to set moodpic for
+ * @param int $mediaId ID of moodpic media
+ */
+ public function setMoodpicForQuestgroup($questgroupId, $mediaId)
+ {
+ $this->db->query(
+ 'UPDATE questgroups '.
+ 'SET questgroupspicture_id = ? '.
+ 'WHERE id = ?',
+ 'ii',
+ $mediaId,
+ $questgroupId
+ );
+ }
+
+
+ /**
+ * Add a Questgroup to a Questgroupshierarchy.
+ *
+ * @param int $questgroupId Id of Questgroup to add
+ * @param int $hierarchyId Id of Hierarchy to add Questgroup to
+ * @param int $parentQuestgroupId Id of parent Questgroup
+ */
+ public function addQuestgroupToHierarchy($questgroupId, $hierarchyId, $parentQuestgroupId)
+ {
+ // Get last position
+ $pos = $this->db->query(
+ 'SELECT COALESCE(MAX(pos),0) AS pos '.
+ 'FROM questgroups_questgroupshierarchy '.
+ 'WHERE questgroupshierarchy_id = ? AND '.
+ 'parent_questgroup_id '.(!is_null($parentQuestgroupId) ? sprintf('= %d', $parentQuestgroupId) : 'IS NULL'),
+ 'i',
+ $hierarchyId
+ );
+ $pos = intval($pos[0]['pos']);
+
+ // Add Questgroup to Hierarchy
+ $this->db->query(
+ 'INSERT INTO questgroups_questgroupshierarchy '.
+ '(questgroup_id, questgroupshierarchy_id, parent_questgroup_id, pos) '.
+ 'VALUES '.
+ '(?, ?, ?, ?)',
+ 'iiii',
+ $questgroupId,
+ $hierarchyId,
+ $parentQuestgroupId,
+ $pos + 1
+ );
+ }
+
+
+ /**
+ * Move a Questgroup up (decrement position) or down (increment
+ * position).
+ *
+ * @param array $questgroup Questgroup to move
+ * @param boolean $up True for moving up, false for down
+ */
+ public function moveQuestgroup($questgroup, $up)
+ {
+ $this->db->setAutocommit(false);
+ try {
+ // Set temporary position
+ $this->db->query(
+ 'UPDATE questgroups_questgroupshierarchy '.
+ 'SET pos = 0 '.
+ 'WHERE questgroup_id = ?',
+ 'i',
+ $questgroup['id']
+ );
+ // Switch entry
+ if(is_null($questgroup['hierarchy']['parent_questgroup_id'])) {
+ $this->db->query(
+ 'UPDATE questgroups_questgroupshierarchy '.
+ 'SET pos = ? '.
+ 'WHERE questgroupshierarchy_id = ? AND parent_questgroup_id IS NULL AND pos = ?',
+ 'iii',
+ $questgroup['hierarchy']['questgroup_pos'],
+ $questgroup['hierarchy']['id'],
+ $questgroup['hierarchy']['questgroup_pos'] + ($up ? -1 : 1)
+ );
+ }
+ else {
+ $this->db->query(
+ 'UPDATE questgroups_questgroupshierarchy '.
+ 'SET pos = ? '.
+ 'WHERE questgroupshierarchy_id = ? AND parent_questgroup_id = ? AND pos = ?',
+ 'iiii',
+ $questgroup['hierarchy']['questgroup_pos'],
+ $questgroup['hierarchy']['id'],
+ $questgroup['hierarchy']['parent_questgroup_id'],
+ $questgroup['hierarchy']['questgroup_pos'] + ($up ? -1 : 1)
+ );
+ }
+ // Set new position
+ $this->db->query(
+ 'UPDATE questgroups_questgroupshierarchy '.
+ 'SET pos = ? '.
+ 'WHERE questgroup_id = ?',
+ 'ii',
+ $questgroup['hierarchy']['questgroup_pos'] + ($up ? -1 : 1),
+ $questgroup['id']
+ );
+
+ $this->db->commit();
+ }
+ catch(\nre\exceptions\DatamodelException $e) {
+ $this->db->rollback();
+ $this->db->setAutocommit(true);
+ throw $e;
+ }
+ $this->db->setAutocommit(true);
+ }
+
+
+ /**
+ * Edit a Questgroup.
+ *
+ * @throws DatamodelException
+ * @param int $questgroupId ID of Questgroup to edit
+ * @param string $title New title of Questgroup
+ */
+ public function editQuestgroup($questgroupId, $title)
+ {
+ $this->db->query(
+ 'UPDATE questgroups '.
+ 'SET title = ?, url = ? '.
+ 'WHERE id = ?',
+ 'ssi',
+ $title,
+ \nre\core\Linker::createLinkParam($title),
+ $questgroupId
+ );
+ }
+
+
+ /**
+ * Delete a Questgroup.
+ *
+ * @param int $questgroupId ID of Questgroup to delete
+ */
+ public function deleteQuestgroup($questgroupId)
+ {
+ $this->db->query(
+ 'DELETE FROM questgroups WHERE id = ?',
+ 'i',
+ $questgroupId
+ );
+ }
diff --git a/views/html/questgroups/create.tpl b/views/html/questgroups/create.tpl
index 4041ba0f..ff24b874 100644
--- a/views/html/questgroups/create.tpl
+++ b/views/html/questgroups/create.tpl
@@ -1,18 +1,77 @@
-
)?>)
+
-=_('Create Questgroup')?>
-
diff --git a/views/html/questgroups/delete.tpl b/views/html/questgroups/delete.tpl
new file mode 100644
index 00000000..e005e785
--- /dev/null
+++ b/views/html/questgroups/delete.tpl
@@ -0,0 +1,19 @@
+
+
+
)?>)
+
+
+=$questgroupshierarchypath?>
+
+
+=$questgroup['hierarchy']['title_singular']?> =$questgroup['hierarchy']['questgroup_pos']?>: =$questgroup['title']?>
+
+=$questgroup['title']?>
+
+
+=_('Delete Questgroup')?>
+=sprintf(_('Should the Questgroup “%s” really be deleted?'), $questgroup['title'])?>
+
diff --git a/views/html/questgroups/edit.tpl b/views/html/questgroups/edit.tpl
new file mode 100644
index 00000000..ca844d36
--- /dev/null
+++ b/views/html/questgroups/edit.tpl
@@ -0,0 +1,65 @@
+
+
+
)?>)
+
+
+=$questgroupshierarchypath?>
+
+=_('Edit Questgroup')?>
+
+
+ &$settings) : ?>
+ -
+
+
+
+
+
+
diff --git a/views/html/questgroups/movedown.tpl b/views/html/questgroups/movedown.tpl
new file mode 100644
index 00000000..e69de29b
diff --git a/views/html/questgroups/moveup.tpl b/views/html/questgroups/moveup.tpl
new file mode 100644
index 00000000..e69de29b
diff --git a/views/html/questgroups/questgroup.tpl b/views/html/questgroups/questgroup.tpl
index 3d359611..7d5207bf 100644
--- a/views/html/questgroups/questgroup.tpl
+++ b/views/html/questgroups/questgroup.tpl
@@ -10,6 +10,13 @@
=$questgroup['title']?>
+ 0) : ?>
+
+
+
0): ?>
@@ -31,22 +38,22 @@
-
+ &$group) : ?>
-
-
-
-
-
-
+
+
+
+
+
Fortschritt:
-
+
-
=$group['character_xps']?> / =$group['achievable_xps']?> XP
+
=$group['character_xps']?> / =$group['achievable_xps']?> =_('XPs')?>
+
+
+
+
+ -
+
+
+
+
+
+
diff --git a/views/html/seminaries/seminary.tpl b/views/html/seminaries/seminary.tpl
index bc9ede9c..74354d17 100644
--- a/views/html/seminaries/seminary.tpl
+++ b/views/html/seminaries/seminary.tpl
@@ -28,11 +28,10 @@
=_('Delete Questgrouphierarchy')?>
0) : ?>
↑
↓
-
-
+
=$group['character_xps']?> / =$group['achievable_xps']?> XP
@@ -50,17 +49,36 @@
=$group['text']?>
=_('Let’s go')?>
+
+
+
+
+
+
+
+