diff --git a/configs/AppConfig.inc b/configs/AppConfig.inc index 056860be..a5eecdba 100644 --- a/configs/AppConfig.inc +++ b/configs/AppConfig.inc @@ -219,6 +219,9 @@ 'questgroupshierarchytitle' => array( 'minlength' => 1, 'maxlength' => 64 + ), + 'deadline' => array( + 'regex' => '/^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})?$/' ) ); @@ -261,7 +264,9 @@ array('^charactergroupsquests/([^/]+)/([^/]+)/create/?$', 'charactergroupsquests/create/$1/$2', true), array('^charactergroupsquests/([^/]+)/([^/]+)/([^/]+)/?$', 'charactergroupsquests/quest/$1/$2/$3', true), array('^charactergroupsquests/([^/]+)/([^/]+)/([^/]+)/(edit|delete|manage)/?$', 'charactergroupsquests/$4/$1/$2/$3', true), - array('^achievements/([^/]+)/?$', 'achievements/index/$1', true), + array('^achievements/([^/]+)/(create|manage)/?$', 'achievements/$2/$1', true), + array('^achievements/([^/]+)/([^/]+)/(edit|conditions|moveup|movedown|delete)/?$', 'achievements/$3/$1/$2', true), + array('^achievements/([^/]+)/?$', 'achievements/index/$1', true), array('^library/([^/]+)/?$', 'library/index/$1', true), array('^library/([^/]+)/create/?$', 'library/create/$1', true), array('^library/([^/]+)/([^/]+)/?$', 'library/topic/$1/$2', true), @@ -305,7 +310,9 @@ array('^charactergroupsquests/create/([^/]+)/([^/]+)/?$', 'charactergroupsquests/$1/$2/create', true), array('^charactergroupsquests/quest/(.*)$', 'charactergroupsquests/$1', true), array('^charactergroupsquests/(edit|delete|manage)/([^/]+)/([^/]+)/([^/]+)$', 'charactergroupsquests/$2/$3/$4/$1', true), - array('^achievements/index/(.*)$', 'achievements/$1', true), + array('^achievements/index/(.*)$', 'achievements/$1', true), + array('^achievements/(create|manage)/(.*)$', 'achievements/$2/$1', true), + array('^achievements/(edit|conditions|moveup|movedown|delete)/(.*)$', 'achievements/$2/$1', true), array('^library/index/([^/]+)/?$', 'library/$1', true), array('^library/create/([^/]+)/?$', 'library/$1/create', true), array('^library/topic/([^/]+)/([^/]+)/?$', 'library/$1/$2', true), diff --git a/controllers/AchievementsController.inc b/controllers/AchievementsController.inc index 560de16b..964878c9 100644 --- a/controllers/AchievementsController.inc +++ b/controllers/AchievementsController.inc @@ -24,14 +24,25 @@ * * @var array */ - public $models = array('achievements', 'seminaries', 'media', 'characters'); + public $models = array('achievements', 'seminaries', 'media', 'characters', 'quests'); + /** + * Required components + * + * @var array + */ + public $components = array('validation'); /** * User permissions * * @var array */ public $permissions = array( - 'index' => array('admin', 'moderator', 'user') + 'index' => array('admin', 'moderator', 'user'), + 'create' => array('admin', 'moderator', 'user'), + 'moveup' => array('admin', 'moderator', 'user'), + 'movedown' => array('admin', 'moderator', 'user'), + 'edit' => array('admin', 'moderator', 'user'), + 'delete' => array('admin', 'moderator', 'user') ); /** * User seminary permissions @@ -39,7 +50,12 @@ * @var array */ public $seminaryPermissions = array( - 'index' => array('admin', 'moderator', 'user') + 'index' => array('admin', 'moderator', 'user'), + 'create' => array('admin'), + 'moveup' => array('admin', 'moderator'), + 'movedown' => array('admin', 'moderator'), + 'edit' => array('admin', 'moderator'), + 'delete' => array('admin') ); @@ -183,7 +199,760 @@ $this->set('achievedAchievements', $achievedAchievements); $this->set('unachievedAchievements', $unachievedAchievements); } + + + /** + * Action: manage. + * + * Manage Achievements of a Seminary. + * + * @throws IdNotFoundException + * @param string $seminaryUrl URL-Title of Seminary + */ + public function manage($seminaryUrl) + { + // Get Seminary + $seminary = $this->Seminaries->getSeminaryByUrl($seminaryUrl); + + // Get Achievements + $achievements = $this->Achievements->getAchievementsForSeminary($seminary['id']); + + + // Set title + $this->addTitleLocalized('Manage Achievements'); + $this->addTitle($seminary['title']); + + // Pass data to view + $this->set('seminary', $seminary); + $this->set('achievements', $achievements); + } + + + /** + * Action: create. + * + * Create a new Achievement. + * + * @throws IdNotFoundException + * @param string $seminaryUrl URL-title of Seminary + */ + public function create($seminaryUrl) + { + // Get seminary + $seminary = $this->Seminaries->getSeminaryByUrl($seminaryUrl); + + // Get Achievements conditions + $conditions = $this->Achievements->getAchievementsConditions(); + + // Get allowed mimetypes + $mimetypes = \nre\configs\AppConfig::$mimetypes['moodpics']; + + // Values + $title = ''; + $description = ''; + $progress = 0; + $hidden = 0; + $onlyOnce = 0; + $allConditions = 1; + $deadline = ''; + $condition = $conditions[0]['condition']; + $fields = array('title', 'deadline'); + $validation = array(); + + // Create Achievement + 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->Achievements->achievementTitleExists($seminary['id'], $title)) { + $validation = $this->Validation->addValidationResult($validation, 'title', 'exist', true); + } + $description = $this->request->getPostParam('description'); + $progress = !is_null($this->request->getPostParam('progress')); + $hidden = !is_null($this->request->getPostParam('hidden')); + $onlyOnce = !is_null($this->request->getPostParam('only_once')); + $allConditions = !is_null($this->request->getPostParam('all_conditions')); + $deadline = $this->request->getPostParam('deadline'); + $condition = $this->request->getPostParam('condition'); + + // Validate condition + $conditionIndex = null; + foreach($conditions as $index => &$c) { + if($condition == $c['condition']) { + $conditionIndex = $index; + } + } + if(is_null($conditionIndex)) { + throw new \nre\exceptions\ParamsNotValidException($condition); + } + + // Validate images + $images = array( + 'unachieved_image' => null, + 'achieved_image' => null + ); + foreach($images as $key => $image) + { + if(!empty($_FILES) && array_key_exists($key, $_FILES) && $_FILES[$key]['error'] != UPLOAD_ERR_NO_FILE) + { + $images[$key] = $_FILES[$key]; + + // Check error + if($images[$key]['error'] !== UPLOAD_ERR_OK) { + $validation = $this->Validation->addValidationResult($validation, 'image', 'error', $image[$key]['error']); + } + + // Check mimetype + $mediaMimetype = null; + $images[$key]['mimetype'] = \hhu\z\Utils::getMimetype($images[$key]['tmp_name'], $images[$key]['type']); + foreach($mimetypes as &$mimetype) { + if($mimetype['mimetype'] == $images[$key]['mimetype']) { + $mediaMimetype = $mimetype; + break; + } + } + if(is_null($mediaMimetype)) { + $validation = $this->Validation->addValidationResult($validation, 'image', 'mimetype', $images[$key]['mimetype']); + } + elseif($images[$key]['size'] > $mediaMimetype['size']) { + $validation = $this->Validation->addValidationResult($validation, 'image', 'size', $mediaMimetype['size']); + } + } + } + + // Create Achievement + if($validation === true) + { + $achievementId = $this->Achievements->createAchievement( + $this->Auth->getUserId(), + $seminary['id'], + $conditions[$conditionIndex]['id'], + $title, + $description, + $progress, + $hidden, + $onlyOnce, + $allConditions, + (!empty($deadline)) ? $deadline : NULL + ); + $achievement = $this->Achievements->getAchievementById($achievementId); + + // Upload images + foreach($images as $key => &$image) + { + if(!is_null($image)) + { + $image['media_id'] = $this->Media->createAchievementMedia( + $this->Auth->getUserId(), + $seminary['id'], + sprintf('achievement-%d', $achievement['id']).(substr($key, 0, 2) == 'un' ? '-locked' : NULL), + '', + $image['mimetype'], + $image['tmp_name'] + ); + } + } + if(!is_null($images['unachieved_image']) && $images['unachieved_image']['media_id'] !== false) { + $this->Achievements->setUnachievedMediaForAchievement($achievement['id'], $images['unachieved_image']['media_id']); + } + if(!is_null($images['achieved_image']) && $images['achieved_image']['media_id'] !== false) { + $this->Achievements->setAchievedMediaForAchievement($achievement['id'], $images['achieved_image']['media_id']); + } + + // Redirect to condition editing + //$this->redirect($this->linker->link(array('conditions', $seminary['url'], $achievement['url']), 1)); + } + } + + // Get validation settings + $validationSettings = array(); + foreach($fields as &$field) { + $validationSettings[$field] = \nre\configs\AppConfig::$validation[$field]; + } + + + // Set title + $this->addTitleLocalized('Create Achievement'); + $this->addTitle($seminary['title']); + + // Pass data to view + $this->set('seminary', $seminary); + $this->set('title', $title); + $this->set('description', $description); + $this->set('progress', $progress); + $this->set('hidden', $hidden); + $this->set('onlyOnce', $onlyOnce); + $this->set('allConditions', $allConditions); + $this->set('deadline', $deadline); + $this->set('condition', $condition); + $this->set('conditions', $conditions); + $this->set('mimetypes', $mimetypes); + $this->set('validation', $validation); + $this->set('validationSettings', $validationSettings); + } + + /** + * Action: moveup. + * + * Move an Achievement up (decrement position). + * + * @throws IdNotFoundException + * @param string $seminaryUrl URL-title of Seminary + * @param string $achievementUrl URL-title of Achievement + */ + public function moveup($seminaryUrl, $achievementUrl) + { + // Get seminary + $seminary = $this->Seminaries->getSeminaryByUrl($seminaryUrl); + + // Get Achievement + $achievement = $this->Achievements->getAchievementByUrl($seminary['id'], $achievementUrl); + + // Set position + $this->Achievements->moveAchievement($achievement, true); + + + // Redirect + $this->redirect($this->linker->link(array('manage', $seminary['url']), 1, true, null, false, $achievement['url'])); + } + + + /** + * Action: movedown. + * + * Move an Achievement down (increment position). + * + * @throws IdNotFoundException + * @param string $seminaryUrl URL-title of Seminary + * @param string $achievementUrl URL-title of Achievement + */ + public function movedown($seminaryUrl, $achievementUrl) + { + // Get seminary + $seminary = $this->Seminaries->getSeminaryByUrl($seminaryUrl); + + // Get Achievement + $achievement = $this->Achievements->getAchievementByUrl($seminary['id'], $achievementUrl); + + // Set position + $this->Achievements->moveAchievement($achievement, false); + + + // Redirect + $this->redirect($this->linker->link(array('manage', $seminary['url']), 1, true, null, false, $achievement['url'])); + } + + + /** + * Action: edit. + * + * Edit an Achievement. + * + * @throws IdNotFoundException + * @param string $seminaryUrl URL-title of Seminary + * @param string $achievementUrl URL-title of Achievement to edit + */ + public function edit($seminaryUrl, $achievementUrl) + { + // Get seminary + $seminary = $this->Seminaries->getSeminaryByUrl($seminaryUrl); + + // Get Achievement + $achievement = $this->Achievements->getAchievementByUrl($seminary['id'], $achievementUrl); + + // Get Achievements conditions + $conditions = $this->Achievements->getAchievementsConditions(); + + // Get allowed mimetypes + $mimetypes = \nre\configs\AppConfig::$mimetypes['moodpics']; + + // Values + $title = $achievement['title']; + $description = $achievement['description']; + $progress = $achievement['progress']; + $hidden = $achievement['hidden']; + $onlyOnce = $achievement['only_once']; + $allConditions = $achievement['all_conditions']; + $deadline = $achievement['deadline']; + $condition = $achievement['condition']; + $fields = array('title', 'deadline'); + $validation = array(); + + // Edit Achievement + if($this->request->getRequestMethod() == 'POST' && (!is_null($this->request->getPostParam('edit')) || !is_null($this->request->getPostParam('edit-conditions')))) + { + // Get params and validate them + $validation = $this->Validation->validateParams($this->request->getPostParams(), $fields); + $title = $this->request->getPostParam('title'); + if($this->Achievements->achievementTitleExists($seminary['id'], $title, $achievement['id'])) { + $validation = $this->Validation->addValidationResult($validation, 'title', 'exist', true); + } + $description = $this->request->getPostParam('description'); + $progress = !is_null($this->request->getPostParam('progress')); + $hidden = !is_null($this->request->getPostParam('hidden')); + $onlyOnce = !is_null($this->request->getPostParam('only_once')); + $allConditions = !is_null($this->request->getPostParam('all_conditions')); + $deadline = $this->request->getPostParam('deadline'); + $condition = $this->request->getPostParam('condition'); + + // Validate condition + $conditionIndex = null; + foreach($conditions as $index => &$c) { + if($condition == $c['condition']) { + $conditionIndex = $index; + } + } + if(is_null($conditionIndex)) { + throw new \nre\exceptions\ParamsNotValidException($condition); + } + + // Validate images + $images = array( + 'unachieved_image' => null, + 'achieved_image' => null + ); + foreach($images as $key => $image) + { + if(!empty($_FILES) && array_key_exists($key, $_FILES) && $_FILES[$key]['error'] != UPLOAD_ERR_NO_FILE) + { + $images[$key] = $_FILES[$key]; + + // Check error + if($images[$key]['error'] !== UPLOAD_ERR_OK) { + $validation = $this->Validation->addValidationResult($validation, 'image', 'error', $image[$key]['error']); + } + + // Check mimetype + $mediaMimetype = null; + $images[$key]['mimetype'] = \hhu\z\Utils::getMimetype($images[$key]['tmp_name'], $images[$key]['type']); + foreach($mimetypes as &$mimetype) { + if($mimetype['mimetype'] == $images[$key]['mimetype']) { + $mediaMimetype = $mimetype; + break; + } + } + if(is_null($mediaMimetype)) { + $validation = $this->Validation->addValidationResult($validation, 'image', 'mimetype', $images[$key]['mimetype']); + } + elseif($images[$key]['size'] > $mediaMimetype['size']) { + $validation = $this->Validation->addValidationResult($validation, 'image', 'size', $mediaMimetype['size']); + } + } + } + + // Edit Achievement + if($validation === true) + { + $this->Achievements->editAchievement( + $achievement['id'], + $conditions[$conditionIndex]['id'], + $title, + $description, + $progress, + $hidden, + $onlyOnce, + $allConditions, + (!empty($deadline)) ? $deadline : NULL + ); + + // Remove old conditions + if($conditions[$conditionIndex]['condition'] != $achievement['condition']) + { + var_dump("remove"); + switch($achievement['condition']) + { + // Date conditions + case 'date': + foreach($this->Achievements->getAchievementConditionsDate($achievement['id']) as $c) { + $this->Achievements->deleteAchievementConditionDate($c['id']); + } + break; + // Character conditions + case 'character': + foreach($this->Achievements->getAchievementConditionsCharacter($achievement['id']) as $c) { + $this->Achievements->deleteAchievementConditionCharacter($c['id']); + } + break; + // Quest conditions + case 'quest': + foreach($this->Achievements->getAchievementConditionsQuest($achievement['id']) as $c) { + $this->Achievements->deleteAchievementConditionQuest($c['id']); + } + break; + // Achievement conditions + case 'achievement': + foreach($this->Achievements->getAchievementConditionsAchievement($achievement['id']) as $c) { + $this->Achievements->deleteAchievementConditionAchievement($c['id']); + } + break; + } + } + + // Upload images + foreach($images as $key => &$image) + { + if(!is_null($image)) + { + $image['media_id'] = $this->Media->createAchievementMedia( + $this->Auth->getUserId(), + $seminary['id'], + sprintf('achievement-%d', $achievement['id']).(substr($key, 0, 2) == 'un' ? '-locked' : NULL), + '', + $image['mimetype'], + $image['tmp_name'] + ); + } + } + if(!is_null($images['unachieved_image']) && $images['unachieved_image']['media_id'] !== false) { + $this->Achievements->setUnachievedMediaForAchievement($achievement['id'], $images['unachieved_image']['media_id']); + } + if(!is_null($images['achieved_image']) && $images['achieved_image']['media_id'] !== false) { + $this->Achievements->setAchievedMediaForAchievement($achievement['id'], $images['achieved_image']['media_id']); + } + + // Redirect + if(!is_null($this->request->getPostParam('edit-conditions'))) { + // To condition editing + $this->redirect($this->linker->link(array('conditions', $seminary['url'], $achievement['url']), 1)); + } + else { + // To overview + $this->redirect($this->linker->link(array('manage', $seminary['url']), 1, true, null, false, $achievement['url'])); + } + } + } + + // Get validation settings + $validationSettings = array(); + foreach($fields as &$field) { + $validationSettings[$field] = \nre\configs\AppConfig::$validation[$field]; + } + + + // Set title + $this->addTitleLocalized('Edit Achievement'); + $this->addTitle($seminary['title']); + + // Pass data to view + $this->set('seminary', $seminary); + $this->set('achievement', $achievement); + $this->set('title', $title); + $this->set('description', $description); + $this->set('progress', $progress); + $this->set('hidden', $hidden); + $this->set('onlyOnce', $onlyOnce); + $this->set('allConditions', $allConditions); + $this->set('deadline', $deadline); + $this->set('condition', $condition); + $this->set('conditions', $conditions); + $this->set('mimetypes', $mimetypes); + $this->set('validation', $validation); + $this->set('validationSettings', $validationSettings); + } + + + /** + * Action: conditions. + * + * Edit conditions of an Achievement. + * + * @throws IdNotFoundException + * @param string $seminaryUrl URL-title of Seminary + * @param string $achievementUrl URL-title of Achievement to edit + */ + public function conditions($seminaryUrl, $achievementUrl) + { + // Get seminary + $seminary = $this->Seminaries->getSeminaryByUrl($seminaryUrl); + + // Get Achievement + $achievement = $this->Achievements->getAchievementByUrl($seminary['id'], $achievementUrl); + + // Get conditions + $conditions = array(); + switch($achievement['condition']) + { + // Date conditions + case 'date': + $conditions = $this->Achievements->getAchievementConditionsDate($achievement['id']); + break; + // Character conditions + case 'character': + $conditions = $this->Achievements->getAchievementConditionsCharacter($achievement['id']); + break; + // Quest conditions + case 'quest': + $conditions = $this->Achievements->getAchievementConditionsQuest($achievement['id']); + break; + // Achievement conditions + case 'achievement': + $conditions = $this->Achievements->getAchievementConditionsAchievement($achievement['id']); + break; + } + + // Values + $characterFields = array( + 'id', 'created', 'user_id', 'name', 'url', 'xps', 'quest_xps', 'avatar_id', + 'charactertype_id', 'charactertype_name', 'charactertype_url', + 'xplevel_id', 'xplevel' + ); + $questFields = array( + 'id', 'quest_id', 'character_id', 'created', 'status' + ); + $achievementFields = array( + 'achievement_id', 'character_id', 'created' + ); + $quests = $this->Quests->getQuestsForSeminary($seminary['id']); + $achievements = $this->Achievements->getAchievementsForSeminary($seminary['id']); + $deletes = array(); + + // Save conditions + if($this->request->getRequestMethod() == 'POST' && !is_null($this->request->getPostParam('edit'))) + { + // Get entered conditions + $selectedConditions = $this->request->getPostParam('conditions'); + $deletes = $this->request->getPostParam('deletes'); + if(!is_array($deletes)) { + $deletes = array(); + } + + // Edit or delete conditions + foreach($conditions as &$condition) + { + $selectedCondition = $selectedConditions[$condition['id']]; + switch($achievement['condition']) + { + // Date conditions + case 'date': + if(array_key_exists($condition['id'], $deletes)) { + $this->Achievements->deleteAchievementConditionDate($condition['id']); + } + else { + $this->Achievements->editAchievementConditionDate( + $condition['id'], + $selectedCondition['select'] + ); + } + break; + // Character conditions + case 'character': + if(array_key_exists($condition['id'], $deletes)) { + $this->Achievements->deleteAchievementConditionCharacter($condition['id']); + } + else { + $this->Achievements->editAchievementConditionCharacter( + $condition['id'], + $selectedCondition['field'], + $selectedCondition['value'] + ); + } + break; + // Quest conditions + case 'quest': + if(array_key_exists($condition['id'], $deletes)) { + $this->Achievements->deleteAchievementConditionQuest($condition['id']); + } + else + { + // Get selected Quest + $questIndex = null; + if(!empty($selectedCondition['quest'])) { + foreach($quests as $index => &$quest) { + if($quest['url'] == $selectedCondition['quest']) { + $questIndex = $index; + } + } + } + + // Edit condition + $this->Achievements->editAchievementConditionQuest( + $condition['id'], + $selectedCondition['field'], + array_key_exists('count', $selectedCondition), + $selectedCondition['value'], + (!is_null($questIndex)) ? $quests[$questIndex]['id'] : null, + ($selectedCondition['status'] != '') ? $selectedCondition['status'] : null, + (!empty($selectedCondition['groupby'])) ? $selectedCondition['groupby'] : null + ); + } + break; + // Achievement conditions + case 'achievement': + if(array_key_exists($condition['id'], $deletes)) { + $this->Achievements->deleteAchievementConditionAchievement($condition['id']); + } + else + { + // Get selected Achievement + $achievmentIndex = null; + if(!empty($selectedCondition['achievement'])) { + foreach($achievements as $index => &$a) { + if($a['url'] == $selectedCondition['achievement']) { + $achievementIndex = $index; + } + } + } + + // Edit condition + $this->Achievements->editAchievementConditionAchievement( + $condition['id'], + $selectedCondition['field'], + array_key_exists('count', $selectedCondition), + $selectedCondition['value'], + (!is_null($achievementIndex)) ? $achievements[$achievementIndex]['id'] : null, + (!empty($selectedCondition['groupby'])) ? $selectedCondition['groupby'] : null + ); + } + break; + } + } + + // Add new condition + if(array_key_exists('new', $selectedConditions)) + { + $condition = $selectedConditions['new']; + switch($achievement['condition']) + { + // Date conditions + case 'date': + if(!empty($condition['select'])) { + $this->Achievements->addAchievementConditionDate( + $this->Auth->getUserId(), + $achievement['id'], + $condition['select'] + ); + } + break; + // Character conditions + case 'character': + if(!empty($condition['value'])) { + $this->Achievements->addAchievementConditionCharacter( + $this->Auth->getUserId(), + $achievement['id'], + $condition['field'], + $condition['value'] + ); + } + break; + // Quest conditions + case 'quest': + if(!empty($condition['value'])) + { + // Get selected Quest + $questIndex = null; + if(!empty($condition['quest'])) { + foreach($quests as $index => &$quest) { + if($quest['url'] == $condition['quest']) { + $questIndex = $index; + } + } + } + + // Edit condition + $this->Achievements->addAchievementConditionQuest( + $this->Auth->getUserId(), + $achievement['id'], + $condition['field'], + array_key_exists('count', $condition), + $condition['value'], + (!is_null($questIndex)) ? $quests[$questIndex]['id'] : null, + ($condition['status'] != '') ? $condition['status'] : null, + (!empty($condition['groupby'])) ? $condition['groupby'] : null + ); + } + break; + // Achievement conditions + case 'achievement': + if(!empty($condition['value'])) + { + // Get selected Achievement + $achievmentIndex = null; + if(!empty($selectedCondition['achievement'])) { + foreach($achievements as $index => &$a) { + if($a['url'] == $selectedCondition['achievement']) { + $achievementIndex = $index; + } + } + } + + // Edit condition + $this->Achievements->addAchievementConditionAchievement( + $this->Auth->getUserId(), + $achievement['id'], + $condition['field'], + array_key_exists('count', $condition), + $condition['value'], + (!is_null($achievementIndex)) ? $achievements[$achievementIndex]['id'] : null, + (!empty($condition['groupby'])) ? $condition['groupby'] : null + ); + } + break; + } + } + + // Redirect to overview + $this->redirect($this->linker->link(array('manage', $seminary['url']), 1, true, null, false, $achievement['url'])); + } + + + // Set title + $this->addTitleLocalized('Edit Achievement conditions'); + $this->addTitle($seminary['title']); + + // Pass data to view + $this->set('seminary', $seminary); + $this->set('achievement', $achievement); + $this->set('conditions', $conditions); + $this->set('characterFields', $characterFields); + $this->set('questFields', $questFields); + $this->set('quests', $quests); + $this->set('achievementFields', $achievementFields); + $this->set('achievements', $achievements); + $this->set('deletes', $deletes); + } + + + /** + * Action: delete. + * + * Delete an Achievement. + * + * @throws IdNotFoundException + * @param string $seminaryUrl URL-title of Seminary + * @param string $achievementUrl URL-title of Achievement + */ + public function delete($seminaryUrl, $achievementUrl) + { + // Get seminary + $seminary = $this->Seminaries->getSeminaryByUrl($seminaryUrl); + + // Get Achievement + $achievement = $this->Achievements->getAchievementByUrl($seminary['id'], $achievementUrl); + + // Check request method + if($this->request->getRequestMethod() == 'POST') + { + // Check confirmation + if(!is_null($this->request->getPostParam('delete'))) + { + // Delete seminary + $this->Achievements->deleteAchievement($achievement['id']); + } + + // Redirect to entry + $this->redirect($this->linker->link(array('manage', $seminary['url']), 1)); + } + + + // Set titile + $this->addTitleLocalized('Delete seminary'); + + // Show confirmation + $this->set('seminary', $seminary); + $this->set('achievement', $achievement); + } } ?> diff --git a/models/AchievementsModel.inc b/models/AchievementsModel.inc index 99097a33..9b0b7d97 100644 --- a/models/AchievementsModel.inc +++ b/models/AchievementsModel.inc @@ -44,7 +44,7 @@ public function getAchievementByUrl($seminaryId, $achievementUrl) { $data = $this->db->query( - 'SELECT achievements.id, achievementconditions.condition, title, url, description, progress, unachieved_achievementsmedia_id, achieved_achievementsmedia_id '. + 'SELECT achievements.id, achievementconditions.condition, seminary_id, pos, title, url, description, progress, hidden, only_once, all_conditions, deadline, unachieved_achievementsmedia_id, achieved_achievementsmedia_id '. 'FROM achievements '. 'LEFT JOIN achievementconditions ON achievementconditions.id = achievements.achievementcondition_id '. 'WHERE seminary_id = ? AND url = ?', @@ -58,6 +58,31 @@ return $data[0]; } + + + /** + * Get an Achievement by its ID. + * + * @param int $achievementId ID of Achievement + * @return array Achievement data + */ + public function getAchievementById($achievementId) + { + $data = $this->db->query( + 'SELECT achievements.id, achievementconditions.condition, seminary_id, pos, title, url, description, progress, hidden, only_once, all_conditions, deadline, unachieved_achievementsmedia_id, achieved_achievementsmedia_id '. + 'FROM achievements '. + 'LEFT JOIN achievementconditions ON achievementconditions.id = achievements.achievementcondition_id '. + 'WHERE achievements.id = ?', + 'i', + $achievementId + ); + if(empty($data)) { + throw new \nre\exceptions\IdNotFoundException($achievementId); + } + + + return $data[0]; + } /** @@ -211,6 +236,25 @@ return 0; } + + + /** + * Get all Achievements for a Seminary. + * + * @param int $seminaryId ID of Seminary + * @return array List of Achievements + */ + public function getAchievementsForSeminary($seminaryId) + { + return $this->db->query( + 'SELECT id, created, created_user_id, achievementcondition_id, pos, title, url, description, progress, hidden, only_once, all_conditions, deadline, unachieved_achievementsmedia_id, achieved_achievementsmedia_id '. + 'FROM achievements '. + 'WHERE seminary_id = ? '. + 'ORDER BY pos ASC', + 'i', + $seminaryId + ); + } /** @@ -254,7 +298,7 @@ public function getAchievementConditionsDate($achievementId) { return $this->db->query( - 'SELECT `select` '. + 'SELECT id, `select` '. 'FROM achievementconditions_date '. 'WHERE achievement_id = ?', 'i', @@ -281,6 +325,59 @@ return false; } + + + /** + * Add a new date condition. + * + * @param int $userId ID of creating user + * @param int $achievementId ID of Achievement to add condition to + * @param string $select SELECT-string for condition + */ + public function addAchievementConditionDate($userId, $achievementId, $select) + { + $this->db->query( + 'INSERT INTO achievementconditions_date '. + '(created_user_id, achievement_id, `select`) '. + 'VALUES '. + '(?, ?, ?)', + 'iis', + $userId, + $achievementId, + $select + ); + + } + + + /** + * Edit a date condition. + * + * @param int $conditionId ID of condition to edit + * @param string $select New SELECT-string for condition + */ + public function editAchievementConditionDate($conditionId, $select) + { + $this->db->query( + 'UPDATE achievementconditions_date '. + 'SET `select` = ? '. + 'WHERE id = ?', + 'si', + $select, + $conditionId + ); + } + + + /** + * Delete a date condition. + * + * @param int $conditionId ID of condition to delete + */ + public function deleteAchievementConditionDate($conditionId) + { + $this->db->query('DELETE FROM achievementconditions_date WHERE id = ?', 'i', $conditionId); + } /** @@ -292,7 +389,7 @@ public function getAchievementConditionsCharacter($achievementId) { return $this->db->query( - 'SELECT field, value '. + 'SELECT id, field, value '. 'FROM achievementconditions_character '. 'WHERE achievement_id = ?', 'i', @@ -372,6 +469,63 @@ return 0; } + + + /** + * Add a new Character condition. + * + * @param int $userId ID of creating user + * @param int $achievementId ID of Achievement to add condition to + * @param string $field Field to match + * @param string $value Value to match + */ + public function addAchievementConditionCharacter($userId, $achievementId, $field, $value) + { + $this->db->query( + 'INSERT INTO achievementconditions_character '. + '(created_user_id, achievement_id, field, value) '. + 'VALUES '. + '(?, ?, ?, ?)', + 'iiss', + $userId, + $achievementId, + $field, + $value + ); + + } + + + /** + * Edit a Character condition. + * + * @param int $conditionId ID of condition to edit + * @param string $field Field to match + * @param string $value Value to match + */ + public function editAchievementConditionCharacter($conditionId, $field, $value) + { + $this->db->query( + 'UPDATE achievementconditions_character '. + 'SET field = ?, value = ? '. + 'WHERE id = ?', + 'ssi', + $field, + $value, + $conditionId + ); + } + + + /** + * Delete a Character condition. + * + * @param int $conditionId ID of condition to delete + */ + public function deleteAchievementConditionCharacter($conditionId) + { + $this->db->query('DELETE FROM achievementconditions_character WHERE id = ?', 'i', $conditionId); + } /** @@ -383,7 +537,7 @@ public function getAchievementConditionsQuest($achievementId) { return $this->db->query( - 'SELECT field, `count`, value, quest_id, status, groupby '. + 'SELECT id, field, `count`, value, quest_id, status, groupby '. 'FROM achievementconditions_quest '. 'WHERE achievement_id = ?', 'i', @@ -476,6 +630,79 @@ return 0; } + + + /** + * Add a new Quest condition. + * + * @param int $userId ID of creating user + * @param int $achievementId ID of Achievement to add condition to + * @param string $field Field to match + * @param boolean $count Count the value + * @param string $value Value to match + * @param int $questId ID of Quest (optional) + * @param int $status Quest status (optional) + * @param string $groupby Field to group by (optional) + */ + public function addAchievementConditionQuest($userId, $achievementId, $field, $count, $value, $questId=null, $status=null, $groupby=null) + { + $this->db->query( + 'INSERT INTO achievementconditions_quest '. + '(created_user_id, achievement_id, field, count, value, quest_id, status, groupby) '. + 'VALUES '. + '(?, ?, ?, ?, ?, ?, ?, ?)', + 'iisisiis', + $userId, + $achievementId, + $field, + $count, + $value, + $questId, + $status, + $groupby + ); + + } + + + /** + * Edit a Quest condition. + * + * @param int $conditionId ID of condition to edit + * @param string $field Field to match + * @param boolean $count Count the value + * @param string $value Value to match + * @param int $questId ID of Quest (optional) + * @param int $status Quest status (optional) + * @param string $groupby Field to group by (optional) + */ + public function editAchievementConditionQuest($conditionId, $field, $count, $value, $questId=null, $status=null, $groupby=null) + { + $this->db->query( + 'UPDATE achievementconditions_quest '. + 'SET field = ?, count = ?, value = ?, quest_id = ?, status = ?, groupby = ? '. + 'WHERE id = ?', + 'sisiisi', + $field, + $count, + $value, + $questId, + $status, + $groupby, + $conditionId + ); + } + + + /** + * Delete a Quest condition. + * + * @param int $conditionId ID of condition to delete + */ + public function deleteAchievementConditionQuest($conditionId) + { + $this->db->query('DELETE FROM achievementconditions_quest WHERE id = ?', 'i', $conditionId); + } /** @@ -487,7 +714,7 @@ public function getAchievementConditionsAchievement($achievementId) { return $this->db->query( - 'SELECT field, `count`, value, meta_achievement_id, groupby '. + 'SELECT id, field, `count`, value, meta_achievement_id, groupby '. 'FROM achievementconditions_achievement '. 'WHERE achievement_id = ?', 'i', @@ -576,6 +803,75 @@ return 0; } + + + /** + * Add a new Achievement condition. + * + * @param int $userId ID of creating user + * @param int $achievementId ID of Achievement to add condition to + * @param string $field Field to match + * @param boolean $count Count the value + * @param string $value Value to match + * @param int $metaAchievementId ID of Meta-Achievement (optional) + * @param string $groupby Field to group by (optional) + */ + public function addAchievementConditionAchievement($userId, $achievementId, $field, $count, $value, $metaAchievementId=null, $groupby=null) + { + $this->db->query( + 'INSERT INTO achievementconditions_achievement '. + '(created_user_id, achievement_id, field, count, value, meta_achievement_id, groupby) '. + 'VALUES '. + '(?, ?, ?, ?, ?, ?, ?)', + 'iisisis', + $userId, + $achievementId, + $field, + $count, + $value, + $metaAchievementId, + $groupby + ); + + } + + + /** + * Edit a Achievement condition. + * + * @param int $conditionId ID of condition to edit + * @param string $field Field to match + * @param boolean $count Count the value + * @param string $value Value to match + * @param int $metaAchievementId ID of Achievement (optional) + * @param string $groupby Field to group by (optional) + */ + public function editAchievementConditionAchievement($conditionId, $field, $count, $value, $metaAchievementId=null, $groupby=null) + { + $this->db->query( + 'UPDATE achievementconditions_achievement '. + 'SET field = ?, count = ?, value = ?, meta_achievement_id = ?, groupby = ? '. + 'WHERE id = ?', + 'sisisi', + $field, + $count, + $value, + $metaAchievementId, + $groupby, + $conditionId + ); + } + + + /** + * Delete a Achievement condition. + * + * @param int $conditionId ID of condition to delete + */ + public function deleteAchievementConditionAchievement($conditionId) + { + $this->db->query('DELETE FROM achievementconditions_achievement WHERE id = ?', 'i', $conditionId); + } /** @@ -620,6 +916,232 @@ return false; } + + + /** + * Get all existing Achievements conditions. + * + * @return array List of Achievements conditions + */ + public function getAchievementsConditions() + { + return $this->db->query( + 'SELECT id, created, `condition` '. + 'FROM achievementconditions' + ); + } + + + /** + * Check if an Achievement title already exists. + * + * @param int $seminaryId ID of Seminary + * @param string $title Achievement title to check + * @param int $characterId Do not check this ID (for editing) + * @return boolean Whether Achievement title exists or not + */ + public function achievementTitleExists($seminaryId, $title, $achievementId=null) + { + $data = $this->db->query( + 'SELECT id '. + 'FROM achievements '. + 'WHERE seminary_id = ? AND (title = ? OR url = ?)', + 'iss', + $seminaryId, + $title, + \nre\core\Linker::createLinkParam($title) + ); + + + return (!empty($data) && (is_null($achievementId) || $achievementId != $data[0]['id'])); + } + + + /** + * Create a new Achievement for a Seminary. + * + * @param int $userId ID of creating user + * @param int $seminaryId ID of Seminary + * @param int $conditionId ID of Achievement condition + * @param string $title Title of new Achievement + * @param string $description Description of new Achievement + * @param boolean $progress Show progress + * @param boolean $hidden Secret Achievement + * @param boolean $onlyOnce Only achieveable by one user + * @param boolean $allConditions Achievement must match all conditions + * @param string $deadline Deadline for Achievement + * @return int ID of newly created Achievement + */ + public function createAchievement($userId, $seminaryId, $conditionId, $title, $description, $progress, $hidden, $onlyOnce, $allConditions, $deadline) + { + // Get position + $pos = $this->db->query( + 'SELECT COALESCE(MAX(pos),0)+1 AS pos '. + 'FROM achievements '. + 'WHERE seminary_id = ?', + 'i', + $seminaryId + ); + $pos = $pos[0]['pos']; + + // Create Achievement + $this->db->query( + 'INSERT INTO achievements '. + '(created_user_id, seminary_id, achievementcondition_id, pos, title, url, description, progress, hidden, only_once, all_conditions, deadline) '. + 'VALUES '. + '(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', + 'iiiisssiiiis', + $userId, + $seminaryId, + $conditionId, + $pos, + $title, + \nre\core\Linker::createLinkParam($title), + $description, + $progress, + $hidden, + $onlyOnce, + $allConditions, + $deadline + ); + + + // Return ID + return $this->db->getInsertId(); + } + + + /** + * Move an Achievement up (decrement position) or down + * (increment position). + * + * @param array $achievement Achievement to move + * @param boolean $up True for moving up, false for down + */ + public function moveAchievement($achievement, $up) + { + $this->db->setAutocommit(false); + try { + // Set temporary position + $this->db->query( + 'UPDATE achievements '. + 'SET pos = 0 '. + 'WHERE id = ?', + 'i', + $achievement['id'] + ); + // Switch entry + $this->db->query( + 'UPDATE achievements '. + 'SET pos = ? '. + 'WHERE seminary_id = ? AND pos = ?', + 'iii', + $achievement['pos'], + $achievement['seminary_id'], + $achievement['pos'] + ($up ? -1 : 1) + ); + // Set new position + $this->db->query( + 'UPDATE achievements '. + 'SET pos = ? '. + 'WHERE id = ?', + 'ii', + $achievement['pos'] + ($up ? -1 : 1), + $achievement['id'] + ); + + $this->db->commit(); + } + catch(\nre\exceptions\DatamodelException $e) { + $this->db->rollback(); + $this->db->setAutocommit(true); + throw $e; + } + $this->db->setAutocommit(true); + } + + + /** + * Edit an Achievement of a Seminary. + * + * @param int $achievementId ID of Achievement to edit + * @param int $conditionId ID of Achievement condition + * @param string $title New title of Achievement + * @param string $description New description of Achievement + * @param boolean $progress Show progress + * @param boolean $hidden Secret Achievement + * @param boolean $onlyOnce Only achieveable by one user + * @param boolean $allConditions Achievement must match all conditions + * @param string $deadline Deadline for Achievement + */ + public function editAchievement($achievementId, $conditionId, $title, $description, $progress, $hidden, $onlyOnce, $allConditions, $deadline) + { + $this->db->query( + 'UPDATE achievements '. + 'SET achievementcondition_id = ?, title = ?, url = ?, description = ?, progress = ?, hidden = ?, only_once = ?, all_conditions = ?, deadline = ? '. + 'WHERE id = ?', + 'isssiiiisi', + $conditionId, + $title, + \nre\core\Linker::createLinkParam($title), + $description, + $progress, + $hidden, + $onlyOnce, + $allConditions, + $deadline, + $achievementId + ); + } + + + /** + * Set unachieved media for an Achievement. + * + * @param int $achievementId ID of Achievement to set media for + * @param int $achievementsmediaId ID of achievementsmedia to set + */ + public function setUnachievedMediaForAchievement($achievementId, $achievementsmediaId) + { + $this->db->query( + 'UPDATE achievements '. + 'SET unachieved_achievementsmedia_id = ? '. + 'WHERE id = ?', + 'ii', + $achievementsmediaId, + $achievementId + ); + } + + + /** + * Set achieved media for an Achievement. + * + * @param int $achievementId ID of Achievement to set media for + * @param int $achievementsmediaId ID of achievementsmedia to set + */ + public function setAchievedMediaForAchievement($achievementId, $achievementsmediaId) + { + $this->db->query( + 'UPDATE achievements '. + 'SET achieved_achievementsmedia_id = ? '. + 'WHERE id = ?', + 'ii', + $achievementsmediaId, + $achievementId + ); + } + + + /** + * Delete an Achievement. + * + * @param int $achievementId ID of Achievement to delete + */ + public function deleteAchievement($achievementId) + { + $this->db->query('DELETE FROM achievements WHERE id = ?', 'i', $achievementId); + } } diff --git a/models/MediaModel.inc b/models/MediaModel.inc index b02f51a1..1b678d49 100644 --- a/models/MediaModel.inc +++ b/models/MediaModel.inc @@ -337,6 +337,48 @@ $this->db->setAutocommit(true); return $mediaId; } + + + public function createAchievementMedia($userId, $seminaryId, $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 Achievements media + $this->db->query( + 'INSERT INTO achievementsmedia '. + '(seminarymedia_id, created_user_id) '. + 'VALUES '. + '(?, ?) '. + 'ON DUPLICATE KEY UPDATE '. + 'created_user_id = ?', + 'iii', + $mediaId, + $userId, + $userId + ); + + // Create filename + $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/views/html/achievements/conditions.tpl b/views/html/achievements/conditions.tpl new file mode 100644 index 00000000..12a28b65 --- /dev/null +++ b/views/html/achievements/conditions.tpl @@ -0,0 +1,152 @@ + +
=_('Achievement description')?>
=\hhu\z\Utils::t($achievement['description'])?>
+