diff --git a/configs/AppConfig.inc b/configs/AppConfig.inc index c7ba2a0e..29872845 100644 --- a/configs/AppConfig.inc +++ b/configs/AppConfig.inc @@ -145,6 +145,16 @@ 'mimetype' => 'image/png', 'size' => 1048576 ) + ), + 'map' => array( + array( + 'mimetype' => 'image/jpeg', + 'size' => 5242880 + ), + array( + 'mimetype' => 'image/png', + 'size' => 10485760 + ) ) ); @@ -296,6 +306,8 @@ array('^library/([^/]+)/create/?$', 'library/create/$1', true), array('^library/([^/]+)/([^/]+)/?$', 'library/topic/$1/$2', true), array('^library/([^/]+)/([^/]+)/(edit|delete|manage)/?$', 'library/$3/$1/$2', true), + array('^map/([^/]+)/?$', 'map/index/$1', true), + array('^map/([^/]+)/(edit)/?$', 'map/$2/$1', true), array('^media/(.*)$', 'media/$1?layout=binary', false), array('^uploads/(.*)$', 'uploads/$1?layout=binary', false) ); @@ -345,7 +357,9 @@ array('^library/index/([^/]+)/?$', 'library/$1', true), array('^library/create/([^/]+)/?$', 'library/$1/create', true), array('^library/topic/([^/]+)/([^/]+)/?$', 'library/$1/$2', true), - array('^library/(edit|delete|manage)/([^/]+)/([^/]+)/?$', 'library/$2/$3/$1', true) + array('^library/(edit|delete|manage)/([^/]+)/([^/]+)/?$', 'library/$2/$3/$1', true), + array('^map/index/(.*)$', 'map/$1', true), + array('^map/(edit)/(.*)$', 'map/$2/$1', true) ); diff --git a/controllers/MapController.inc b/controllers/MapController.inc index d489fc57..b88b45a1 100644 --- a/controllers/MapController.inc +++ b/controllers/MapController.inc @@ -24,14 +24,21 @@ * * @var array */ - public $models = array('seminaries', 'map'); + public $models = array('seminaries', 'map', 'media'); + /** + * 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'), + 'edit' => array('admin', 'moderator', 'user') ); /** * User seminary permissions @@ -39,7 +46,8 @@ * @var array */ public $seminaryPermissions = array( - 'index' => array('admin', 'moderator', 'user') + 'index' => array('admin', 'moderator', 'user'), + 'edit' => array('admin', 'moderator') ); @@ -51,7 +59,7 @@ * Draw the map. * * @throws \nre\exceptions\IdNotFoundException - * @param string $seminaryUrl URL-Title of Seminary + * @param string $seminaryUrl URL-Title of Seminary */ public function index($seminaryUrl) { @@ -61,12 +69,106 @@ // Get map $map = $this->Map->getMapOfSeminary($seminary['id']); + // Check permissions + if(is_null($map) && count(array_intersect(array('admin','moderator'), \hhu\z\controllers\IntermediateController::$user['roles'])) == 0) { + throw new \nre\exceptions\IdNotFoundException($seminaryUrl); + } + // Pass data to view $this->set('seminary', $seminary); $this->set('map', $map); } + + /** + * Action: edit. + * + * Edit the map of a Seminary. + * + * @param string $seminaryUrl URL-Title of Seminary + */ + public function edit($seminaryUrl) + { + // Get Seminary + $seminary = $this->Seminaries->getSeminaryByUrl($seminaryUrl); + + // Get map + $map = $this->Map->getMapOfSeminary($seminary['id']); + + // Get allowed mimetypes + $mimetypes = \nre\configs\AppConfig::$mimetypes['map']; + + // Values + $validation = true; + + // Check request method + if($this->request->getRequestMethod() == 'POST') + { + // Validate media (map file) + $media = null; + if(!empty($_FILES) && array_key_exists('media', $_FILES) && $_FILES['media']['error'] != UPLOAD_ERR_NO_FILE) + { + $media = $_FILES['media']; + + // Check error + if($media['error'] !== UPLOAD_ERR_OK) { + $validation = $this->Validation->addValidationResult($validation, 'media', 'error', $media['error']); + } + + // Check mimetype + $mediaMimetype = null; + $media['mimetype'] = \hhu\z\Utils::getMimetype($media['tmp_name'], $media['type']); + foreach($mimetypes as &$mimetype) { + if($mimetype['mimetype'] == $media['mimetype']) { + $mediaMimetype = $mimetype; + break; + } + } + if(is_null($mediaMimetype)) { + $validation = $this->Validation->addValidationResult($validation, 'media', 'mimetype', $media['mimetype']); + } + elseif($media['size'] > $mediaMimetype['size']) { + $validation = $this->Validation->addValidationResult($validation, 'media', 'size', $mediaMimetype['size']); + } + } + + // Edit map + if($validation === true) + { + // Update media + if(!is_null($media)) + { + $seminarymediaId = $this->Media->createMapMedia( + $this->Auth->getUserId(), + $seminary['id'], + $media['name'], + sprintf('map of %s', $seminary['title']), + $media['type'], + $media['tmp_name'] + ); + if($seminarymediaId > 0) { + $this->Map->setMapOfSeminary($seminary['id'], $seminarymediaId); + } + } + + // Redirect + $this->redirect($this->linker->link(array('index', $seminary['url']), 1)); + } + } + + // Set titile + //$this->addTitleLocalized('Delete Quest'); + //$this->addTitle($seminary['title']); + + + // Pass data to view + $this->set('seminary', $seminary); + $this->set('map', $map); + $this->set('mimetypes', $mimetypes); + $this->set('validation', $validation); + } + } ?> diff --git a/controllers/MediaController.inc b/controllers/MediaController.inc index 0336d6fb..3261028e 100644 --- a/controllers/MediaController.inc +++ b/controllers/MediaController.inc @@ -128,6 +128,9 @@ case 'library': $index = 'library_seminarymedia_id'; break; + case 'map': + $index = 'map_seminarymedia_id'; + break; } // Get media diff --git a/controllers/SeminariesController.inc b/controllers/SeminariesController.inc index 19e6bea8..95c41cab 100644 --- a/controllers/SeminariesController.inc +++ b/controllers/SeminariesController.inc @@ -451,7 +451,8 @@ array_key_exists('avatars', $elements), array_key_exists('achievements', $elements), array_key_exists('charactergroupsgroups', $elements), - array_key_exists('charactergroupsquests', $elements) + array_key_exists('charactergroupsquests', $elements), + array_key_exists('map', $elements) ); $seminary = $this->Seminaries->getSeminaryById($seminaryId); diff --git a/models/MapModel.inc b/models/MapModel.inc index 02ea0842..ff7393b5 100644 --- a/models/MapModel.inc +++ b/models/MapModel.inc @@ -19,6 +19,12 @@ */ class MapModel extends \hhu\z\Model { + /** + * Required models + * + * @var array + */ + public $models = array('media'); @@ -57,6 +63,85 @@ return null; } + + /** + * Set map of a Seminary. + * + * @param int $seminaryId ID of Seminary to set map of + * @param int $seminarymediaId ID of Seminary media of map to set + */ + public function setMapOfSeminary($seminaryId, $seminarymediaId) + { + // Get image measurements + $infos = $this->Media->getSeminarymediaInfos($seminarymediaId); + + // Insert record + $this->db->query( + 'INSERT INTO maps '. + '(seminary_id, seminarymedia_id, width, height) '. + 'VALUES '. + '(?, ?, ?, ?) '. + 'ON DUPLICATE KEY UPDATE '. + 'seminarymedia_id = ?, width = ?, height = ?', + 'iiiiiii', + $seminaryId, $seminarymediaId, $infos['width'], $infos['height'], + $seminarymediaId, $infos['width'], $infos['height'] + ); + } + + + /** + * Copy the map of a Seminary. + * + * @param int $sourceSeminaryId Seminary to copy from + * @param int $targetSeminaryId Seminary to copy to + * @param array $seminaryMediaIds Mapping of Seminarymedia-IDs from source Seminary to target Seminary + */ + public function copyMapOfSeminary($sourceSeminaryId, $targetSeminaryId, $seminaryMediaIds) + { + // Get map of source Seminary + $map = $this->getMapOfSeminary($sourceSeminaryId); + + // Set map of targetSeminary + $this->setMapOfSeminary($targetSeminaryId, $seminaryMediaIds[$map['seminarymedia_id']]); + } + + + /** + * Delete the map of a Seminary. + * + * @param int $seminaryId ID of Seminary to delete map of + */ + public function deleteMapOfSeminary($seminaryId) + { + // Get map + $map = $this->getMap($seminaryId); + if(is_null($map)) { + return; + } + + // Delete map + $this->db->setAutocommit(false); + try { + // Delete map record + $this->db->query( + 'DELETE FROM maps '. + 'WHERE seminary_id = ?', + 'i', + $seminaryId + ); + + // Delete Seminary media + $this->Media->deleteSeminaryMedia($map['seminarymedia_id']); + + $this->db->commit(); + } + catch(\nre\exceptions\DatamodelException $e) { + $this->db->rollback(); + } + $this->db->setAutocommit(true); + } + } ?> diff --git a/models/MediaModel.inc b/models/MediaModel.inc index a1cfc775..7f2e0d49 100644 --- a/models/MediaModel.inc +++ b/models/MediaModel.inc @@ -603,6 +603,45 @@ } + /** + * Create a new map medium. + * + * @param int $userId ID of user that does the upload + * @param int $seminaryId ID of Seminary + * @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 createMapMedia($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); + + // 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; + } + + /** * Gather some information about a Seminary medium. * diff --git a/models/SeminariesModel.inc b/models/SeminariesModel.inc index ff53815c..53462668 100644 --- a/models/SeminariesModel.inc +++ b/models/SeminariesModel.inc @@ -24,7 +24,7 @@ * * @var array */ - public $models = array('questgroupshierarchy', 'questgroups', 'quests', 'questtopics', 'media', 'charactertypes', 'xplevels', 'avatars', 'achievements', 'charactergroups', 'charactergroupsquests', 'seminarycharacterfields'); + public $models = array('questgroupshierarchy', 'questgroups', 'quests', 'questtopics', 'media', 'charactertypes', 'xplevels', 'avatars', 'achievements', 'charactergroups', 'charactergroupsquests', 'seminarycharacterfields', 'map'); @@ -259,6 +259,25 @@ } + /** + * Set the moodpic for the map of a Seminary. + * + * @param int $seminaryId ID of Seminary to set moodpic for Map for + * @param int $seminaryMediaId ID of Seminarymedia to set as moodpic + */ + public function setMoodpicForMap($seminaryId, $seminaryMediaId) + { + $this->db->query( + 'UPDATE seminaries '. + 'SET map_seminarymedia_id = ? '. + 'WHERE id = ?', + 'ii', + $seminaryMediaId, + $seminaryId + ); + } + + /** * (Re-) Calculate the amount of achievable XPs for a Seminary. * @@ -326,9 +345,10 @@ * @param boolean $copyAchievements Whether to copy Achievements or not * @param boolean $copyCharactergroupsgroups Whether to copy Character groups-groups or not * @param boolean $copyCharactergroupsquests Whether to copy Character groups Quests or not + * @param boolean $copyMap Whether to copy Map or not * @return ID of newly created Seminary */ - public function copySeminary($userId, $sourceSeminaryId, $title, $course, $description, $copySeminaryfields, $copyMedia, $copyQuestgroupshierarchy, $copyQuestgroups, $copyQuests, $copyQuesttopics, $copyCharactertypes, $copyXPlevels, $copyAvatars, $copyAchievements, $copyCharactergroupsgroups, $copyCharactergroupsquests) + public function copySeminary($userId, $sourceSeminaryId, $title, $course, $description, $copySeminaryfields, $copyMedia, $copyQuestgroupshierarchy, $copyQuestgroups, $copyQuests, $copyQuesttopics, $copyCharactertypes, $copyXPlevels, $copyAvatars, $copyAchievements, $copyCharactergroupsgroups, $copyCharactergroupsquests, $copyMap) { // Get Seminary $seminary = $this->getSeminaryById($sourceSeminaryId); @@ -362,6 +382,9 @@ if(!is_null($seminary['library_seminarymedia_id'])) { $this->setMoodpicForLibrary($targetSeminaryId, $seminaryMediaIds[$seminary['library_seminarymedia_id']]); } + if(!is_null($seminary['map_seminarymedia_id'])) { + $this->setMoodpicForMap($targetSeminaryId, $seminaryMediaIds[$seminary['map_seminarymedia_id']]); + } } // Copy Quest content @@ -423,6 +446,11 @@ } } + // Copy Map + if($copyMap && !is_null($seminaryMediaIds)) { + $this->Map->copyMapOfSeminary($sourceSeminaryId, $targetSeminaryId, $seminaryMediaIds); + } + // Recalculate XPs $this->calculateXPsForSeminary($targetSeminaryId); diff --git a/views/html/map/edit.tpl b/views/html/map/edit.tpl new file mode 100644 index 00000000..1bfe2a86 --- /dev/null +++ b/views/html/map/edit.tpl @@ -0,0 +1,51 @@ + +