implement copying a complete Seminary (implements issue #7)

This commit is contained in:
coderkun 2015-03-21 15:15:49 +01:00
commit b2d00bc624
31 changed files with 2151 additions and 157 deletions

View file

@ -0,0 +1,79 @@
<?php
/**
* The Legend of Z
*
* @author Oliver Hanraths <oliver.hanraths@uni-duesseldorf.de>
* @copyright 2014 Heinrich-Heine-Universität Düsseldorf
* @license http://www.gnu.org/licenses/gpl.html
* @link https://bitbucket.org/coderkun/the-legend-of-z
*/
namespace hhu\z\exceptions;
/**
* Exception: File copy went wrong
*
* @author Oliver Hanraths <oliver.hanraths@uni-duesseldorf.de>
*/
class FileCopyException extends \nre\core\Exception
{
/**
* Error code
*
* @var int
*/
const CODE = 204;
/**
* Error message
*
* @var string
*/
const MESSAGE = 'File copy went wrong';
/**
* Nested error
*
* @var array
*/
private $nestedError;
/**
* Construct a new exception.
*
* @param array $nestedError Nested error
* @param string $message Error message
* @param int $code Error code
*/
function __construct($nestedError, $message=self::MESSAGE, $code=self::CODE)
{
parent::__construct(
$message,
$code,
$nestedError['message']
);
// Store values
$this->nestedError = $nestedError;
}
/**
* Get nested error.
*
* @return Nested error
*/
public function getNestedError()
{
return $this->nestedError;
}
}
?>

View file

@ -22,7 +22,18 @@
/**
* Copy a Quest.
*
* @param int $userId ID of creating user
* @param int $sourceQuestId ID of Quest to copy from
* @param int $targetQuestId ID of Quest to copy to
* @param int $seminaryMediaIds Mapping of SeminaryMedia-IDs from source Seminary to targetSeminary
*/
public abstract function copyQuest($userId, $sourceQuestId, $targetQuestId, $seminaryMediaIds);
/** /**
* Load a Model. * Load a Model.
* *

View file

@ -244,8 +244,8 @@
array('^users/all/?$', 'users/index/all', true), array('^users/all/?$', 'users/index/all', true),
array('^users/([^/]+)/(edit|delete)/?$', 'users/$2/$1', true), array('^users/([^/]+)/(edit|delete)/?$', 'users/$2/$1', true),
array('^users/(?!(index|login|register|logout|manage|create|edit|delete))/?', 'users/user/$1', true), array('^users/(?!(index|login|register|logout|manage|create|edit|delete))/?', 'users/user/$1', true),
array('^seminaries/([^/]+)/(edit|delete)/?$', 'seminaries/$2/$1', true), array('^seminaries/([^/]+)/(edit|copy|delete)/?$', 'seminaries/$2/$1', true),
array('^seminaries/(?!(index|create|edit|delete|calculatexps))/?', 'seminaries/seminary/$1', true), array('^seminaries/(?!(index|create|edit|copy|delete|calculatexps))/?', 'seminaries/seminary/$1', true),
array('^xplevels/([^/]+)/(manage)/?$', 'xplevels/$2/$1', true), array('^xplevels/([^/]+)/(manage)/?$', 'xplevels/$2/$1', true),
array('^questgroupshierarchy/([^/]+)/create/?$', 'questgroupshierarchy/create/$1', true), array('^questgroupshierarchy/([^/]+)/create/?$', 'questgroupshierarchy/create/$1', true),
array('^questgroupshierarchy/([^/]+)/([^/]+)/(edit|delete|moveup|movedown)/?$', 'questgroupshierarchy/$3/$1/$2', true), array('^questgroupshierarchy/([^/]+)/([^/]+)/(edit|delete|moveup|movedown)/?$', 'questgroupshierarchy/$3/$1/$2', true),

View file

@ -24,7 +24,7 @@
* *
* @var array * @var array
*/ */
public $models = array('seminaries', 'users', 'characterroles', 'charactertypes', 'xplevels', 'questgroupshierarchy', 'questgroups', 'questgrouptexts', 'media'); public $models = array('users', 'seminaries', 'characterroles', 'charactertypes', 'xplevels', 'questgroupshierarchy', 'questgroups', 'questgrouptexts', 'quests', 'questtexts', 'media');
/** /**
* Required components * Required components
* *
@ -41,6 +41,7 @@
'seminary' => array('admin', 'moderator', 'user'), 'seminary' => array('admin', 'moderator', 'user'),
'create' => array('admin', 'moderator'), 'create' => array('admin', 'moderator'),
'edit' => array('admin', 'moderator', 'user'), 'edit' => array('admin', 'moderator', 'user'),
'copy' => array('admin', 'moderator', 'user'),
'delete' => array('admin', 'moderator', 'user'), 'delete' => array('admin', 'moderator', 'user'),
'calculatexps' => array('admin', 'moderator', 'user') 'calculatexps' => array('admin', 'moderator', 'user')
); );
@ -52,6 +53,7 @@
public $seminaryPermissions = array( public $seminaryPermissions = array(
'seminary' => array('admin', 'moderator', 'user', 'guest'), 'seminary' => array('admin', 'moderator', 'user', 'guest'),
'edit' => array('admin'), 'edit' => array('admin'),
'copy' => array('admin'),
'delete' => array('admin'), 'delete' => array('admin'),
'calculatexps' => array('admin', 'moderator') 'calculatexps' => array('admin', 'moderator')
); );
@ -138,7 +140,7 @@
} }
// Get first Questgroup text // Get first Questgroup text
$text = $this->Questgrouptexts->getFirstQuestgroupText($questgroup['id']); $text = $this->getFirstQuestgroupText($questgroup['id']);
if(!is_null($text)) if(!is_null($text))
{ {
$questgroup['text'] = \hhu\z\Utils::shortenString($text, 100, 120).' …'; $questgroup['text'] = \hhu\z\Utils::shortenString($text, 100, 120).' …';
@ -390,6 +392,101 @@
$this->set('validation', $validation); $this->set('validation', $validation);
$this->set('validationSettings', $validationSettings); $this->set('validationSettings', $validationSettings);
} }
/**
* Copy a Seminary and selected content.
*
* @throws \nre\exceptions\IdNotFoundException
* @param string $seminaryUrl URL-Title of a seminary
*/
public function copy($seminaryUrl)
{
// Get seminary
$seminary = $this->Seminaries->getSeminaryByUrl($seminaryUrl);
// Values
$title = sprintf('%s (%s)', $seminary['title'], _('Copy'));
$course = $seminary['course'];
$description = $seminary['description'];
$elements = array();
$fields = array('title', 'course');
$validation = array();
$exception = null;
// 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->Seminaries->seminaryTitleExists($title)) {
$validation = $this->Validation->addValidationResult($validation, 'title', 'exist', true);
}
$course = $this->request->getPostParam('course');
$description = $this->request->getPostParam('description');
$elements = $this->request->getPostParam('elements');
if(!is_array($elements)) {
$elements = array();
}
// Copy Seminary
if($validation === true)
{
try {
$seminaryId = $this->Seminaries->copySeminary(
$this->Auth->getUserId(),
$seminary['id'],
$title,
$course,
$description,
array_key_exists('seminaryfields', $elements),
array_key_exists('media', $elements),
array_key_exists('questgroupshierarchy', $elements),
array_key_exists('questgroups', $elements),
array_key_exists('quests', $elements),
array_key_exists('questtopics', $elements),
array_key_exists('charactertypes', $elements),
array_key_exists('xplevels', $elements),
array_key_exists('avatars', $elements),
array_key_exists('achievements', $elements),
array_key_exists('charactergroupsgroups', $elements),
array_key_exists('charactergroupsquests', $elements)
);
$seminary = $this->Seminaries->getSeminaryById($seminaryId);
// Redirect to overview
$this->redirect($this->linker->link('index', 1));
}
catch(\hhu\z\exceptions\QuesttypeModelNotValidException $e) {
$exception = $e;
}
catch(\hhu\z\exceptions\QuesttypeModelNotFoundException $e) {
$exception = $e;
}
catch(\hhu\z\exceptions\FileCopyException $e) {
$exception = $e;
}
}
}
// Get validation settings
$validationSettings = array();
foreach($fields as &$field) {
$validationSettings[$field] = \nre\configs\AppConfig::$validation[$field];
}
// Pass data to view
$this->set('seminary', $seminary);
$this->set('title', $title);
$this->set('course', $course);
$this->set('description', $description);
$this->set('elements', $elements);
$this->set('validation', $validation);
$this->set('validationSettings', $validationSettings);
$this->set('exception', $exception);
}
/** /**
@ -444,22 +541,59 @@
// Get Seminary // Get Seminary
$seminary = $this->Seminaries->getSeminaryByUrl($seminaryUrl); $seminary = $this->Seminaries->getSeminaryByUrl($seminaryUrl);
// Questgrouphierarchy and Questgroups // (Re-) Calculate XPs
$questgroupshierarchy = $this->Questgroupshierarchy->getHierarchyOfSeminary($seminary['id']); $this->Seminaries->calculateXPsForSeminary($seminary['id']);
foreach($questgroupshierarchy as &$hierarchy)
// Redirect to Questgroup
$this->redirect($this->linker->link(array('seminary', $seminary['url']), 1));
}
/**
* Get the first text of a Questgroup.
*
* @param int $questgroupId ID of a Questgroup
* @return string First text of this Questgroup or NULL
*/
private function getFirstQuestgroupText($questgroupId)
{
// Text of Questgroup itself
$questgroupTexts = $this->Questgrouptexts->getQuestgroupTexts($questgroupId);
if(!empty($questgroupTexts)) {
return $questgroupTexts[0]['text'];
}
// Text of first Quest
$quest = $this->Quests->getFirstQuestOfQuestgroup($questgroupId);
if(!is_null($quest))
{
$questText = $this->Questtexts->getFirstQuestText($quest['id']);
if(!is_null($questText)) {
return $questText;
}
}
// Text of ChildQuestgroups
$questgroupHierarchy = $this->Questgroupshierarchy->getHierarchyForQuestgroup($questgroupId);
$childQuestgroupshierarchy = $this->Questgroupshierarchy->getChildQuestgroupshierarchy($questgroupHierarchy['id']);
foreach($childQuestgroupshierarchy as &$hierarchy)
{ {
// Get Questgroups // Get Questgroups
$hierarchy['questgroups'] = $this->Questgroups->getQuestgroupsForHierarchy($hierarchy['id']); $questgroups = $this->Questgroups->getQuestgroupsForHierarchy($hierarchy['id'], $questgroupId);
foreach($hierarchy['questgroups'] as &$questgroup) foreach($questgroups as &$group)
{ {
// Calculate achievable XPs $childQuestgroupText = $this->getFirstQuestgroupText($group['id']);
$this->Questgroups->calculateXPsForQuestgroup($questgroup['id']); if(!is_null($childQuestgroupText)) {
return $childQuestgroupText;
}
} }
} }
// Redirect to Questgroup // No text found
$this->redirect($this->linker->link(array('seminary', $seminary['url']), 1)); return null;
} }
} }

View file

@ -1,15 +1,15 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: The Legend of Z\n" "Project-Id-Version: The Legend of Z\n"
"POT-Creation-Date: 2014-08-29 15:17+0100\n" "POT-Creation-Date: 2015-03-21 14:54+0100\n"
"PO-Revision-Date: 2014-08-29 15:17+0100\n" "PO-Revision-Date: 2015-03-21 14:55+0100\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: \n" "Language-Team: \n"
"Language: de_DE\n" "Language: de_DE\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.6.7\n" "X-Generator: Poedit 1.7.4\n"
"X-Poedit-Basepath: ../../../\n" "X-Poedit-Basepath: ../../../\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-SourceCharset: UTF-8\n" "X-Poedit-SourceCharset: UTF-8\n"
@ -17,8 +17,8 @@ msgstr ""
"X-Poedit-SearchPath-1: questtypes\n" "X-Poedit-SearchPath-1: questtypes\n"
"X-Poedit-SearchPath-2: controllers\n" "X-Poedit-SearchPath-2: controllers\n"
#: controllers/CharactersController.inc:401 #: controllers/CharactersController.inc:402
#: controllers/UsersController.inc:320 views/ajax/characters/index.tpl:10 #: controllers/UsersController.inc:322 views/ajax/characters/index.tpl:10
#: views/ajax/users/index.tpl:10 views/html/characters/index.tpl:48 #: views/ajax/users/index.tpl:10 views/html/characters/index.tpl:48
#: views/html/characters/manage.tpl:35 views/html/characters/manage.tpl:50 #: views/html/characters/manage.tpl:35 views/html/characters/manage.tpl:50
#: views/html/characters/manage.tpl:58 views/html/userroles/user.tpl:5 #: views/html/characters/manage.tpl:58 views/html/userroles/user.tpl:5
@ -27,8 +27,8 @@ msgstr ""
msgid "Admin" msgid "Admin"
msgstr "Administrator" msgstr "Administrator"
#: controllers/CharactersController.inc:407 #: controllers/CharactersController.inc:408
#: controllers/UsersController.inc:326 views/ajax/characters/index.tpl:12 #: controllers/UsersController.inc:328 views/ajax/characters/index.tpl:12
#: views/ajax/users/index.tpl:12 views/html/characters/index.tpl:49 #: views/ajax/users/index.tpl:12 views/html/characters/index.tpl:49
#: views/html/characters/manage.tpl:36 views/html/characters/manage.tpl:51 #: views/html/characters/manage.tpl:36 views/html/characters/manage.tpl:51
#: views/html/characters/manage.tpl:59 views/html/userroles/user.tpl:7 #: views/html/characters/manage.tpl:59 views/html/userroles/user.tpl:7
@ -37,8 +37,8 @@ msgstr "Administrator"
msgid "Moderator" msgid "Moderator"
msgstr "Moderator" msgstr "Moderator"
#: controllers/CharactersController.inc:413 #: controllers/CharactersController.inc:414
#: controllers/UsersController.inc:332 views/ajax/characters/index.tpl:14 #: controllers/UsersController.inc:334 views/ajax/characters/index.tpl:14
#: views/ajax/users/index.tpl:14 views/html/characters/index.tpl:50 #: views/ajax/users/index.tpl:14 views/html/characters/index.tpl:50
#: views/html/characters/manage.tpl:37 views/html/characters/manage.tpl:53 #: views/html/characters/manage.tpl:37 views/html/characters/manage.tpl:53
#: views/html/characters/manage.tpl:61 views/html/userroles/user.tpl:9 #: views/html/characters/manage.tpl:61 views/html/userroles/user.tpl:9
@ -51,19 +51,19 @@ msgstr "Benutzer"
msgid "New user registration" msgid "New user registration"
msgstr "Neue Benutzerregistrierung" msgstr "Neue Benutzerregistrierung"
#: controllers/MailController.inc:74 #: controllers/MailController.inc:75
msgid "New Character registration" msgid "New Character registration"
msgstr "Neue Charakterregistrierung" msgstr "Neue Charakterregistrierung"
#: controllers/MailController.inc:99 #: controllers/MailController.inc:100
msgid "New Character submission" msgid "New Character submission"
msgstr "Neuer Lösungsvorschlag" msgstr "Neuer Lösungsvorschlag"
#: controllers/MailController.inc:124 #: controllers/MailController.inc:125
msgid "Character submission approved" msgid "Character submission approved"
msgstr "Lösungsvorschlag bewertet" msgstr "Lösungsvorschlag bewertet"
#: controllers/QuestsController.inc:1287 #: controllers/QuestsController.inc:1249
#: questtypes/submit/html/submission.tpl:30 #: questtypes/submit/html/submission.tpl:30
#: views/html/achievements/conditions.tpl:54 #: views/html/achievements/conditions.tpl:54
#: views/html/achievements/conditions.tpl:121 views/html/quests/quest.tpl:54 #: views/html/achievements/conditions.tpl:121 views/html/quests/quest.tpl:54
@ -71,6 +71,55 @@ msgstr "Lösungsvorschlag bewertet"
msgid "solved" msgid "solved"
msgstr "Richtig!" msgstr "Richtig!"
#: controllers/SeminariesController.inc:409
msgid "Copy"
msgstr "Kopie"
#: questtypes/bossfight/html/edittask.tpl:3
msgid "Boss-Fight"
msgstr ""
#: questtypes/bossfight/html/edittask.tpl:4
msgid "Boss name"
msgstr ""
#: questtypes/bossfight/html/edittask.tpl:6
msgid "Boss image"
msgstr ""
#: questtypes/bossfight/html/edittask.tpl:8
msgid "Boss lives"
msgstr ""
#: questtypes/bossfight/html/edittask.tpl:10
msgid "Character lives"
msgstr ""
#: questtypes/bossfight/html/edittask.tpl:14
msgid "Stages"
msgstr ""
#: questtypes/bossfight/html/edittask.tpl:17
#: questtypes/choiceinput/html/edittask.tpl:83
#: questtypes/multiplechoice/html/edittask.tpl:79
#: questtypes/textinput/html/edittask.tpl:44
#: views/html/achievements/conditions.tpl:151
#: views/html/achievements/create.tpl:109 views/html/achievements/edit.tpl:112
#: views/html/charactergroupsquests/manage.tpl:66
#: views/html/charactertypes/edit.tpl:124 views/html/library/edit.tpl:46
#: views/html/library/edit.tpl:86 views/html/quests/edit.tpl:114
#: views/html/users/edit.tpl:105 views/html/xplevels/manage.tpl:49
msgid "save"
msgstr "speichern"
#: questtypes/bossfight/html/edittask.tpl:26
msgid "Character"
msgstr "Charakter"
#: questtypes/bossfight/html/edittask.tpl:26
msgid "Boss"
msgstr ""
#: questtypes/bossfight/html/quest.tpl:11 #: questtypes/bossfight/html/quest.tpl:11
#: questtypes/bossfight/html/quest.tpl:24 #: questtypes/bossfight/html/quest.tpl:24
#: questtypes/bossfight/html/submission.tpl:21 #: questtypes/bossfight/html/submission.tpl:21
@ -78,7 +127,7 @@ msgstr "Richtig!"
msgid "lost" msgid "lost"
msgstr "verloren" msgstr "verloren"
#: questtypes/bossfight/html/quest.tpl:41 views/html/quests/quest.tpl:129 #: questtypes/bossfight/html/quest.tpl:41 views/html/quests/quest.tpl:133
msgid "Choose" msgid "Choose"
msgstr "Wählen" msgstr "Wählen"
@ -132,18 +181,6 @@ msgstr "Auswahleingaben"
msgid "Preview" msgid "Preview"
msgstr "Vorschau" msgstr "Vorschau"
#: questtypes/choiceinput/html/edittask.tpl:83
#: questtypes/multiplechoice/html/edittask.tpl:79
#: questtypes/textinput/html/edittask.tpl:44
#: views/html/achievements/conditions.tpl:151
#: views/html/achievements/create.tpl:109 views/html/achievements/edit.tpl:112
#: views/html/charactergroupsquests/manage.tpl:66
#: views/html/charactertypes/edit.tpl:124 views/html/library/edit.tpl:46
#: views/html/library/edit.tpl:86 views/html/quests/edit.tpl:114
#: views/html/users/edit.tpl:105 views/html/xplevels/manage.tpl:49
msgid "save"
msgstr "speichern"
#: questtypes/crossword/html/quest.tpl:22 #: questtypes/crossword/html/quest.tpl:22
#: questtypes/crossword/html/submission.tpl:22 #: questtypes/crossword/html/submission.tpl:22
msgid "vertical" msgid "vertical"
@ -383,7 +420,8 @@ msgstr "Fehler"
#: views/html/achievements/conditions.tpl:8 #: views/html/achievements/conditions.tpl:8
#: views/html/achievements/create.tpl:8 views/html/achievements/delete.tpl:8 #: views/html/achievements/create.tpl:8 views/html/achievements/delete.tpl:8
#: views/html/achievements/edit.tpl:8 views/html/achievements/index.tpl:16 #: views/html/achievements/edit.tpl:8 views/html/achievements/index.tpl:16
#: views/html/achievements/manage.tpl:8 views/html/seminarymenu/index.tpl:6 #: views/html/achievements/manage.tpl:8 views/html/seminaries/copy.tpl:107
#: views/html/seminarymenu/index.tpl:6
msgid "Achievements" msgid "Achievements"
msgstr "Achievements" msgstr "Achievements"
@ -432,8 +470,8 @@ msgid "Count"
msgstr "Zählen" msgstr "Zählen"
#: views/html/achievements/conditions.tpl:41 #: views/html/achievements/conditions.tpl:41
#: views/html/achievements/conditions.tpl:108 views/html/quests/quest.tpl:116 #: views/html/achievements/conditions.tpl:108 views/html/quests/quest.tpl:120
#: views/html/quests/quest.tpl:132 #: views/html/quests/quest.tpl:136
msgid "Quest" msgid "Quest"
msgstr "Quest" msgstr "Quest"
@ -479,7 +517,7 @@ msgid "Achievement"
msgstr "Achievement" msgstr "Achievement"
#: views/html/achievements/conditions.tpl:81 #: views/html/achievements/conditions.tpl:81
#: views/html/achievements/delete.tpl:14 views/html/achievements/manage.tpl:24 #: views/html/achievements/delete.tpl:14 views/html/achievements/manage.tpl:22
#: views/html/charactergroups/deletegroup.tpl:15 #: views/html/charactergroups/deletegroup.tpl:15
#: views/html/charactergroups/deletegroupsgroup.tpl:14 #: views/html/charactergroups/deletegroupsgroup.tpl:14
#: views/html/charactergroupsquests/delete.tpl:15 #: views/html/charactergroupsquests/delete.tpl:15
@ -536,7 +574,8 @@ msgstr "Das Bild ist ungültig"
#: views/html/library/edit.tpl:62 views/html/library/edit.tpl:100 #: views/html/library/edit.tpl:62 views/html/library/edit.tpl:100
#: views/html/questgroups/create.tpl:33 views/html/questgroups/edit.tpl:30 #: views/html/questgroups/create.tpl:33 views/html/questgroups/edit.tpl:30
#: views/html/quests/create.tpl:30 views/html/quests/edit.tpl:30 #: views/html/quests/create.tpl:30 views/html/quests/edit.tpl:30
#: views/html/seminaries/create.tpl:30 views/html/seminaries/edit.tpl:32 #: views/html/seminaries/copy.tpl:41 views/html/seminaries/create.tpl:30
#: views/html/seminaries/edit.tpl:32
#, php-format #, php-format
msgid "Title is too short (min. %d chars)" msgid "Title is too short (min. %d chars)"
msgstr "Der Titel ist zu kurz (min. %d Zeichen)" msgstr "Der Titel ist zu kurz (min. %d Zeichen)"
@ -548,7 +587,8 @@ msgstr "Der Titel ist zu kurz (min. %d Zeichen)"
#: views/html/library/edit.tpl:64 views/html/library/edit.tpl:102 #: views/html/library/edit.tpl:64 views/html/library/edit.tpl:102
#: views/html/questgroups/create.tpl:35 views/html/questgroups/edit.tpl:32 #: views/html/questgroups/create.tpl:35 views/html/questgroups/edit.tpl:32
#: views/html/quests/create.tpl:32 views/html/quests/edit.tpl:32 #: views/html/quests/create.tpl:32 views/html/quests/edit.tpl:32
#: views/html/seminaries/create.tpl:32 views/html/seminaries/edit.tpl:34 #: views/html/seminaries/copy.tpl:43 views/html/seminaries/create.tpl:32
#: views/html/seminaries/edit.tpl:34
#, php-format #, php-format
msgid "Title is too long (max. %d chars)" msgid "Title is too long (max. %d chars)"
msgstr "Der Titel ist zu lang (max. %d Zeichen)" msgstr "Der Titel ist zu lang (max. %d Zeichen)"
@ -560,7 +600,8 @@ msgstr "Der Titel ist zu lang (max. %d Zeichen)"
#: views/html/library/edit.tpl:66 views/html/library/edit.tpl:104 #: views/html/library/edit.tpl:66 views/html/library/edit.tpl:104
#: views/html/questgroups/create.tpl:37 views/html/questgroups/edit.tpl:34 #: views/html/questgroups/create.tpl:37 views/html/questgroups/edit.tpl:34
#: views/html/quests/create.tpl:34 views/html/quests/edit.tpl:34 #: views/html/quests/create.tpl:34 views/html/quests/edit.tpl:34
#: views/html/seminaries/create.tpl:34 views/html/seminaries/edit.tpl:36 #: views/html/seminaries/copy.tpl:45 views/html/seminaries/create.tpl:34
#: views/html/seminaries/edit.tpl:36
msgid "Title contains illegal characters" msgid "Title contains illegal characters"
msgstr "Der Titel enthält ungültige Zeichen" msgstr "Der Titel enthält ungültige Zeichen"
@ -571,7 +612,8 @@ msgstr "Der Titel enthält ungültige Zeichen"
#: views/html/library/edit.tpl:68 views/html/library/edit.tpl:106 #: views/html/library/edit.tpl:68 views/html/library/edit.tpl:106
#: views/html/questgroups/create.tpl:39 views/html/questgroups/edit.tpl:36 #: views/html/questgroups/create.tpl:39 views/html/questgroups/edit.tpl:36
#: views/html/quests/create.tpl:36 views/html/quests/edit.tpl:36 #: views/html/quests/create.tpl:36 views/html/quests/edit.tpl:36
#: views/html/seminaries/create.tpl:36 views/html/seminaries/edit.tpl:38 #: views/html/seminaries/copy.tpl:47 views/html/seminaries/create.tpl:36
#: views/html/seminaries/edit.tpl:38
msgid "Title already exists" msgid "Title already exists"
msgstr "Der Titel existiert bereits" msgstr "Der Titel existiert bereits"
@ -582,7 +624,8 @@ msgstr "Der Titel existiert bereits"
#: views/html/library/edit.tpl:70 views/html/library/edit.tpl:108 #: views/html/library/edit.tpl:70 views/html/library/edit.tpl:108
#: views/html/questgroups/create.tpl:41 views/html/questgroups/edit.tpl:38 #: views/html/questgroups/create.tpl:41 views/html/questgroups/edit.tpl:38
#: views/html/quests/create.tpl:38 views/html/quests/edit.tpl:38 #: views/html/quests/create.tpl:38 views/html/quests/edit.tpl:38
#: views/html/seminaries/create.tpl:38 views/html/seminaries/edit.tpl:40 #: views/html/seminaries/copy.tpl:49 views/html/seminaries/create.tpl:38
#: views/html/seminaries/edit.tpl:40
msgid "Title invalid" msgid "Title invalid"
msgstr "Der Titel ist ungültig" msgstr "Der Titel ist ungültig"
@ -620,9 +663,10 @@ msgstr "Erhalten"
#: views/html/questgroups/questgroup.tpl:88 views/html/quests/create.tpl:70 #: views/html/questgroups/questgroup.tpl:88 views/html/quests/create.tpl:70
#: views/html/quests/create.tpl:71 views/html/quests/edit.tpl:73 #: views/html/quests/create.tpl:71 views/html/quests/edit.tpl:73
#: views/html/quests/edit.tpl:74 views/html/quests/index.tpl:47 #: views/html/quests/edit.tpl:74 views/html/quests/index.tpl:47
#: views/html/quests/index.tpl:48 views/html/seminaries/create.tpl:68 #: views/html/quests/index.tpl:48 views/html/seminaries/copy.tpl:69
#: views/html/seminaries/copy.tpl:70 views/html/seminaries/create.tpl:68
#: views/html/seminaries/create.tpl:69 views/html/seminaries/edit.tpl:70 #: views/html/seminaries/create.tpl:69 views/html/seminaries/edit.tpl:70
#: views/html/seminaries/edit.tpl:71 views/html/seminaries/seminary.tpl:65 #: views/html/seminaries/edit.tpl:71 views/html/seminaries/seminary.tpl:68
msgid "Title" msgid "Title"
msgstr "Titel" msgstr "Titel"
@ -632,6 +676,7 @@ msgstr "Titel"
#: views/html/charactergroupsquests/edit.tpl:85 #: views/html/charactergroupsquests/edit.tpl:85
#: views/html/charactergroupsquests/edit.tpl:86 #: views/html/charactergroupsquests/edit.tpl:86
#: views/html/charactergroupsquests/quest.tpl:45 #: views/html/charactergroupsquests/quest.tpl:45
#: views/html/seminaries/copy.tpl:73 views/html/seminaries/copy.tpl:74
#: views/html/seminaries/create.tpl:72 views/html/seminaries/create.tpl:73 #: views/html/seminaries/create.tpl:72 views/html/seminaries/create.tpl:73
#: views/html/seminaries/edit.tpl:74 views/html/seminaries/edit.tpl:75 #: views/html/seminaries/edit.tpl:74 views/html/seminaries/edit.tpl:75
msgid "Description" msgid "Description"
@ -779,7 +824,7 @@ msgstr "erhalten am: %s"
msgid "Continue playing to unlock this secret Achievement" msgid "Continue playing to unlock this secret Achievement"
msgstr "Spiele weiter, um diesen geheimen Erfolg freizuschalten" msgstr "Spiele weiter, um diesen geheimen Erfolg freizuschalten"
#: views/html/achievements/manage.tpl:23 #: views/html/achievements/manage.tpl:21
#: views/html/charactergroups/editgroup.tpl:83 #: views/html/charactergroups/editgroup.tpl:83
#: views/html/charactergroups/editgroupsgroup.tpl:50 #: views/html/charactergroups/editgroupsgroup.tpl:50
#: views/html/charactergroupsquests/edit.tpl:94 #: views/html/charactergroupsquests/edit.tpl:94
@ -805,7 +850,8 @@ msgstr "bearbeiten"
#: views/html/charactergroupsquests/edit.tpl:8 #: views/html/charactergroupsquests/edit.tpl:8
#: views/html/charactergroupsquests/manage.tpl:8 #: views/html/charactergroupsquests/manage.tpl:8
#: views/html/charactergroupsquests/quest.tpl:8 #: views/html/charactergroupsquests/quest.tpl:8
#: views/html/characters/character.tpl:119 views/html/seminarymenu/index.tpl:5 #: views/html/characters/character.tpl:119 views/html/seminaries/copy.tpl:109
#: views/html/seminarymenu/index.tpl:5
msgid "Character Groups" msgid "Character Groups"
msgstr "Gruppen" msgstr "Gruppen"
@ -1021,7 +1067,7 @@ msgstr "%squests"
#: views/html/charactergroupsquests/edit.tpl:78 #: views/html/charactergroupsquests/edit.tpl:78
#: views/html/characters/index.tpl:27 views/html/characters/index.tpl:90 #: views/html/characters/index.tpl:27 views/html/characters/index.tpl:90
#: views/html/characters/manage.tpl:17 #: views/html/characters/manage.tpl:17
#: views/html/questgroups/questgroup.tpl:62 views/html/quests/create.tpl:72 #: views/html/questgroups/questgroup.tpl:66 views/html/quests/create.tpl:72
#: views/html/quests/create.tpl:73 views/html/quests/edit.tpl:75 #: views/html/quests/create.tpl:73 views/html/quests/edit.tpl:75
#: views/html/quests/edit.tpl:76 views/html/xplevels/manage.tpl:43 #: views/html/quests/edit.tpl:76 views/html/xplevels/manage.tpl:43
#: views/html/xplevels/manage.tpl:81 #: views/html/xplevels/manage.tpl:81
@ -1056,6 +1102,7 @@ msgstr "Füge Charaktere hinzu"
#: views/html/charactergroups/managegroup.tpl:59 #: views/html/charactergroups/managegroup.tpl:59
#: views/html/questgroups/questgroup.tpl:108 views/html/quests/index.tpl:9 #: views/html/questgroups/questgroup.tpl:108 views/html/quests/index.tpl:9
#: views/html/seminaries/copy.tpl:89
msgid "Quests" msgid "Quests"
msgstr "Quests" msgstr "Quests"
@ -1133,6 +1180,7 @@ msgstr "%s-Quest bearbeiten"
#: views/html/charactergroupsquests/manage.tpl:26 #: views/html/charactergroupsquests/manage.tpl:26
#: views/html/charactergroupsquests/quest.tpl:31 #: views/html/charactergroupsquests/quest.tpl:31
#: views/html/seminaries/copy.tpl:81
msgid "Media" msgid "Media"
msgstr "Medien" msgstr "Medien"
@ -1243,6 +1291,7 @@ msgid "The Seminary field “%s” is invalid"
msgstr "Das Kursfeld „%s“ ist ungültig" msgstr "Das Kursfeld „%s“ ist ungültig"
#: views/html/characters/edit.tpl:86 views/html/characters/register.tpl:74 #: views/html/characters/edit.tpl:86 views/html/characters/register.tpl:74
#: views/html/seminaries/copy.tpl:79
msgid "Seminary fields" msgid "Seminary fields"
msgstr "Kursfelder" msgstr "Kursfelder"
@ -1315,7 +1364,7 @@ msgstr "Bitte wähle einen Avatar aus"
#: views/html/charactertypes/create.tpl:8 #: views/html/charactertypes/create.tpl:8
#: views/html/charactertypes/delete.tpl:8 views/html/charactertypes/edit.tpl:8 #: views/html/charactertypes/delete.tpl:8 views/html/charactertypes/edit.tpl:8
#: views/html/charactertypes/index.tpl:10 #: views/html/charactertypes/index.tpl:10 views/html/seminaries/copy.tpl:97
msgid "Charactertypes" msgid "Charactertypes"
msgstr "Charakterrassen" msgstr "Charakterrassen"
@ -1336,7 +1385,7 @@ msgstr "Soll die Charakterrasse „%s“ wirklich gelöscht werden?"
msgid "Edit Charactertype" msgid "Edit Charactertype"
msgstr "Characterrasse bearbeiten" msgstr "Characterrasse bearbeiten"
#: views/html/charactertypes/edit.tpl:45 #: views/html/charactertypes/edit.tpl:45 views/html/seminaries/copy.tpl:103
msgid "Avatars" msgid "Avatars"
msgstr "Avatare" msgstr "Avatare"
@ -1438,7 +1487,7 @@ msgstr "Einführung"
#: views/html/library/create.tpl:8 views/html/library/delete.tpl:8 #: views/html/library/create.tpl:8 views/html/library/delete.tpl:8
#: views/html/library/edit.tpl:8 views/html/library/index.tpl:9 #: views/html/library/edit.tpl:8 views/html/library/index.tpl:9
#: views/html/library/manage.tpl:8 views/html/library/topic.tpl:8 #: views/html/library/manage.tpl:8 views/html/library/topic.tpl:8
#: views/html/seminarymenu/index.tpl:7 #: views/html/seminaries/copy.tpl:92 views/html/seminarymenu/index.tpl:7
msgid "Library" msgid "Library"
msgstr "Bibliothek" msgstr "Bibliothek"
@ -1506,9 +1555,9 @@ msgstr "Thema verwalten"
msgid "Users" msgid "Users"
msgstr "Benutzer" msgstr "Benutzer"
#: views/html/menu/index.tpl:3 views/html/seminaries/create.tpl:5 #: views/html/menu/index.tpl:3 views/html/seminaries/copy.tpl:7
#: views/html/seminaries/delete.tpl:7 views/html/seminaries/edit.tpl:7 #: views/html/seminaries/create.tpl:5 views/html/seminaries/delete.tpl:7
#: views/html/seminaries/index.tpl:4 #: views/html/seminaries/edit.tpl:7 views/html/seminaries/index.tpl:4
msgid "Seminaries" msgid "Seminaries"
msgstr "Kurse" msgstr "Kurse"
@ -1516,7 +1565,7 @@ msgstr "Kurse"
msgid "Logout" msgid "Logout"
msgstr "Logout" msgstr "Logout"
#: views/html/questgroups/create.tpl:8 #: views/html/questgroups/create.tpl:8 views/html/seminaries/copy.tpl:86
msgid "Questgroups" msgid "Questgroups"
msgstr "Questgruppen" msgstr "Questgruppen"
@ -1525,24 +1574,28 @@ msgid "Create Questgroup"
msgstr "Questgruppe erstellen" msgstr "Questgruppe erstellen"
#: views/html/questgroups/create.tpl:22 views/html/questgroups/edit.tpl:19 #: views/html/questgroups/create.tpl:22 views/html/questgroups/edit.tpl:19
#: views/html/seminaries/create.tpl:19 views/html/seminaries/edit.tpl:21 #: views/html/seminaries/copy.tpl:30 views/html/seminaries/create.tpl:19
#: views/html/seminaries/edit.tpl:21
#, php-format #, php-format
msgid "Error during moodpic upload: %s" msgid "Error during moodpic upload: %s"
msgstr "Fehler beim Upload des Stimmungsbildes: %s" msgstr "Fehler beim Upload des Stimmungsbildes: %s"
#: views/html/questgroups/create.tpl:24 views/html/questgroups/edit.tpl:21 #: views/html/questgroups/create.tpl:24 views/html/questgroups/edit.tpl:21
#: views/html/seminaries/create.tpl:21 views/html/seminaries/edit.tpl:23 #: views/html/seminaries/copy.tpl:32 views/html/seminaries/create.tpl:21
#: views/html/seminaries/edit.tpl:23
#, php-format #, php-format
msgid "Moodpic has wrong type “%s”" msgid "Moodpic has wrong type “%s”"
msgstr "Der Dateityp „%s“ ist für Stimmungsbilder nicht erlaubt" msgstr "Der Dateityp „%s“ ist für Stimmungsbilder nicht erlaubt"
#: views/html/questgroups/create.tpl:26 views/html/questgroups/edit.tpl:23 #: views/html/questgroups/create.tpl:26 views/html/questgroups/edit.tpl:23
#: views/html/seminaries/create.tpl:23 views/html/seminaries/edit.tpl:25 #: views/html/seminaries/copy.tpl:34 views/html/seminaries/create.tpl:23
#: views/html/seminaries/edit.tpl:25
msgid "Moodpic exceeds size maximum" msgid "Moodpic exceeds size maximum"
msgstr "Das Stimmungsbild ist zu groß" msgstr "Das Stimmungsbild ist zu groß"
#: views/html/questgroups/create.tpl:28 views/html/questgroups/edit.tpl:25 #: views/html/questgroups/create.tpl:28 views/html/questgroups/edit.tpl:25
#: views/html/seminaries/create.tpl:25 views/html/seminaries/edit.tpl:27 #: views/html/seminaries/copy.tpl:36 views/html/seminaries/create.tpl:25
#: views/html/seminaries/edit.tpl:27
msgid "Moodpic invalid" msgid "Moodpic invalid"
msgstr "Das Stimmungsbild ist ungültig" msgstr "Das Stimmungsbild ist ungültig"
@ -1554,6 +1607,7 @@ msgstr "Einordnung"
#: views/html/questgroupshierarchy/create.tpl:8 #: views/html/questgroupshierarchy/create.tpl:8
#: views/html/questgroupshierarchy/delete.tpl:8 #: views/html/questgroupshierarchy/delete.tpl:8
#: views/html/questgroupshierarchy/edit.tpl:8 #: views/html/questgroupshierarchy/edit.tpl:8
#: views/html/seminaries/copy.tpl:83
msgid "Questgroupshierarchy" msgid "Questgroupshierarchy"
msgstr "Hierarchie" msgstr "Hierarchie"
@ -1591,27 +1645,27 @@ msgstr "Neue Quest erstellen"
#: views/html/questgroups/questgroup.tpl:40 #: views/html/questgroups/questgroup.tpl:40
#: views/html/questgroupshierarchy/edit.tpl:11 #: views/html/questgroupshierarchy/edit.tpl:11
#: views/html/seminaries/seminary.tpl:24 #: views/html/seminaries/seminary.tpl:25
msgid "Edit Questgroupshierarchy" msgid "Edit Questgroupshierarchy"
msgstr "Hierarchie bearbeiten" msgstr "Hierarchie bearbeiten"
#: views/html/questgroups/questgroup.tpl:41 #: views/html/questgroups/questgroup.tpl:41
#: views/html/questgroupshierarchy/delete.tpl:11 #: views/html/questgroupshierarchy/delete.tpl:11
#: views/html/seminaries/seminary.tpl:25 #: views/html/seminaries/seminary.tpl:26
msgid "Delete Questgroupshierarchy" msgid "Delete Questgroupshierarchy"
msgstr "Hierarchie löschen" msgstr "Hierarchie löschen"
#: views/html/questgroups/questgroup.tpl:66 #: views/html/questgroups/questgroup.tpl:70
msgid "Found optional Questline" msgid "Found optional Questline"
msgstr "Optionale Questline gefunden" msgstr "Optionale Questline gefunden"
#: views/html/questgroups/questgroup.tpl:89 #: views/html/questgroups/questgroup.tpl:89
#: views/html/seminaries/seminary.tpl:66 #: views/html/seminaries/seminary.tpl:69
msgid "Add new Questgroup" msgid "Add new Questgroup"
msgstr "Neue Questgruppe hinzufügen" msgstr "Neue Questgruppe hinzufügen"
#: views/html/questgroups/questgroup.tpl:98 #: views/html/questgroups/questgroup.tpl:98
#: views/html/seminaries/seminary.tpl:76 #: views/html/seminaries/seminary.tpl:79
msgid "New Questgroupshierarchy" msgid "New Questgroupshierarchy"
msgstr "Neue Hierarchie" msgstr "Neue Hierarchie"
@ -1620,7 +1674,7 @@ msgstr "Neue Hierarchie"
#: views/html/questgroupshierarchy/create.tpl:53 #: views/html/questgroupshierarchy/create.tpl:53
#: views/html/questgroupshierarchy/edit.tpl:52 #: views/html/questgroupshierarchy/edit.tpl:52
#: views/html/questgroupshierarchy/edit.tpl:53 #: views/html/questgroupshierarchy/edit.tpl:53
#: views/html/seminaries/seminary.tpl:77 #: views/html/seminaries/seminary.tpl:80
msgid "Title (singular)" msgid "Title (singular)"
msgstr "Titel (singular)" msgstr "Titel (singular)"
@ -1629,12 +1683,12 @@ msgstr "Titel (singular)"
#: views/html/questgroupshierarchy/create.tpl:55 #: views/html/questgroupshierarchy/create.tpl:55
#: views/html/questgroupshierarchy/edit.tpl:54 #: views/html/questgroupshierarchy/edit.tpl:54
#: views/html/questgroupshierarchy/edit.tpl:55 #: views/html/questgroupshierarchy/edit.tpl:55
#: views/html/seminaries/seminary.tpl:78 #: views/html/seminaries/seminary.tpl:81
msgid "Title (plural)" msgid "Title (plural)"
msgstr "Titel (plural)" msgstr "Titel (plural)"
#: views/html/questgroups/questgroup.tpl:102 #: views/html/questgroups/questgroup.tpl:102
#: views/html/seminaries/seminary.tpl:79 #: views/html/seminaries/seminary.tpl:82
msgid "Add new Questgroupshierarchy" msgid "Add new Questgroupshierarchy"
msgstr "Neue Hierarchy hinzufügen" msgstr "Neue Hierarchy hinzufügen"
@ -1770,26 +1824,26 @@ msgstr "Du hast die Aufgabe bereits erfolgreich gelöst"
msgid "Show answer" msgid "Show answer"
msgstr "Lösung anzeigen" msgstr "Lösung anzeigen"
#: views/html/quests/quest.tpl:83 #: views/html/quests/quest.tpl:84
msgid "Game over"
msgstr "Spielende"
#: views/html/quests/quest.tpl:86
msgid "Epilog" msgid "Epilog"
msgstr "Epilog" msgstr "Epilog"
#: views/html/quests/quest.tpl:109 #: views/html/quests/quest.tpl:113
msgid "Continuation" msgid "Continuation"
msgstr "Setze deine Reise fort" msgstr "Setze deine Reise fort"
#: views/html/quests/quest.tpl:134 #: views/html/quests/quest.tpl:138
msgid "Go on" msgid "Go on"
msgstr "Fortfahren" msgstr "Fortfahren"
#: views/html/quests/quest.tpl:143 views/html/seminaries/seminary.tpl:48 #: views/html/quests/quest.tpl:147 views/html/seminaries/seminary.tpl:55
msgid "Lets go" msgid "Lets go"
msgstr "Auf ins Abenteuer!" msgstr "Auf ins Abenteuer!"
#: views/html/quests/quest.tpl:146
msgid "Game over"
msgstr "Spielende"
#: views/html/quests/submission.tpl:9 #: views/html/quests/submission.tpl:9
#, php-format #, php-format
msgid "Submission of %s" msgid "Submission of %s"
@ -1799,25 +1853,58 @@ msgstr "Lösung von %s"
msgid "Submissions" msgid "Submissions"
msgstr "Lösungen" msgstr "Lösungen"
#: views/html/seminaries/create.tpl:8 #: views/html/seminaries/copy.tpl:10 views/html/seminaries/seminary.tpl:11
msgid "New seminary" msgid "Copy seminary"
msgstr "Neuer Kurs" msgstr "Kurs kopieren"
#: views/html/seminaries/create.tpl:43 views/html/seminaries/edit.tpl:45 #: views/html/seminaries/copy.tpl:14
#, php-format
msgid "Copying of files failed: “%s”"
msgstr "Kopieren von Dateien fehlgeschlagen: „%s“"
#: views/html/seminaries/copy.tpl:16
#, php-format
msgid "Copying of Seminary failed: “%s”"
msgstr "Kopieren des Kurses fehlgeschlagen: „%s“"
#: views/html/seminaries/copy.tpl:54 views/html/seminaries/create.tpl:43
#: views/html/seminaries/edit.tpl:45
#, php-format #, php-format
msgid "Course is too long (max. %d chars)" msgid "Course is too long (max. %d chars)"
msgstr "Der Kurs ist zu lang (max. %d Zeichen)" msgstr "Der Kurs ist zu lang (max. %d Zeichen)"
#: views/html/seminaries/create.tpl:45 views/html/seminaries/edit.tpl:47 #: views/html/seminaries/copy.tpl:56 views/html/seminaries/create.tpl:45
#: views/html/seminaries/edit.tpl:47
msgid "Course invalid" msgid "Course invalid"
msgstr "Das Kurs ist ungültig" msgstr "Das Kurs ist ungültig"
#: views/html/seminaries/copy.tpl:71 views/html/seminaries/copy.tpl:72
#: views/html/seminaries/create.tpl:70 views/html/seminaries/create.tpl:71 #: views/html/seminaries/create.tpl:70 views/html/seminaries/create.tpl:71
#: views/html/seminaries/edit.tpl:72 views/html/seminaries/edit.tpl:73 #: views/html/seminaries/edit.tpl:72 views/html/seminaries/edit.tpl:73
msgid "Course" msgid "Course"
msgstr "Kurs" msgstr "Kurs"
#: views/html/seminaries/delete.tpl:10 views/html/seminaries/seminary.tpl:11 #: views/html/seminaries/copy.tpl:77
msgid "Elements"
msgstr "Elemente"
#: views/html/seminaries/copy.tpl:100
msgid "XP-Levels"
msgstr "XP-Levels"
#: views/html/seminaries/copy.tpl:112
msgid "Character Groups Quests"
msgstr "Gruppenquests"
#: views/html/seminaries/copy.tpl:115
msgid "copy"
msgstr "kopieren"
#: views/html/seminaries/create.tpl:8
msgid "New seminary"
msgstr "Neuer Kurs"
#: views/html/seminaries/delete.tpl:10 views/html/seminaries/seminary.tpl:12
msgid "Delete seminary" msgid "Delete seminary"
msgstr "Kurs löschen" msgstr "Kurs löschen"
@ -1848,11 +1935,11 @@ msgstr "Erstelle einen Charakter"
msgid "Your Character “%s” has not been activated yet" msgid "Your Character “%s” has not been activated yet"
msgstr "Dein Charakter „%s“ wurde noch nicht aktiviert" msgstr "Dein Charakter „%s“ wurde noch nicht aktiviert"
#: views/html/seminaries/seminary.tpl:15 #: views/html/seminaries/seminary.tpl:16
msgid "Show Quests" msgid "Show Quests"
msgstr "Quests anzeigen" msgstr "Quests anzeigen"
#: views/html/seminaries/seminary.tpl:16 #: views/html/seminaries/seminary.tpl:17
msgid "Recalculate XPs" msgid "Recalculate XPs"
msgstr "XP neuberechnen" msgstr "XP neuberechnen"
@ -2124,9 +2211,6 @@ msgstr "Hallo %s"
#~ msgid "%stQuests" #~ msgid "%stQuests"
#~ msgstr "Quests" #~ msgstr "Quests"
#~ msgid "Character Groups Quests"
#~ msgstr "Gruppenquests"
#~ msgid "continue" #~ msgid "continue"
#~ msgstr "fortfahren" #~ msgstr "fortfahren"

View file

@ -19,6 +19,12 @@
*/ */
class AchievementsModel extends \hhu\z\Model class AchievementsModel extends \hhu\z\Model
{ {
/**
* Required models
*
* @var array
*/
public $models = array('media');
@ -249,8 +255,9 @@
public function getAchievementsForSeminary($seminaryId) public function getAchievementsForSeminary($seminaryId)
{ {
return $this->db->query( 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 '. '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 '. 'FROM achievements '.
'LEFT JOIN achievementconditions ON achievementconditions.id = achievements.achievementcondition_id '.
'WHERE seminary_id = ? '. 'WHERE seminary_id = ? '.
'ORDER BY pos ASC', 'ORDER BY pos ASC',
'i', 'i',
@ -371,6 +378,28 @@
} }
/**
* Copy all date 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 copyAchievementConditionsDate($userId, $sourceAchievementId, $targetAchievementId)
{
$this->db->query(
'INSERT INTO achievementconditions_date '.
'(created_user_id, achievement_id, `select`) '.
'SELECT ?, ?, `select` '.
'FROM achievementconditions_date '.
'WHERE achievement_id = ?',
'iii',
$userId, $targetAchievementId,
$sourceAchievementId
);
}
/** /**
* Delete a date condition. * Delete a date condition.
* *
@ -519,6 +548,28 @@
} }
/**
* Copy all Character 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 copyAchievementConditionsCharacter($userId, $sourceAchievementId, $targetAchievementId)
{
$this->db->query(
'INSERT INTO achievementconditions_character '.
'(created_user_id, achievement_id, field, value) '.
'SELECT ?, ?, field, value '.
'FROM achievementconditions_character '.
'WHERE achievement_id = ?',
'iii',
$userId, $targetAchievementId,
$sourceAchievementId
);
}
/** /**
* Delete a Character condition. * Delete a Character condition.
* *
@ -696,6 +747,52 @@
} }
/**
* Copy all Quest 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
* @param array $questIds Mapping of Quest-IDs from source Seminary to target Seminary
*/
public function copyAchievementConditionsQuest($userId, $sourceAchievementId, $targetAchievementId, $questIds)
{
// Get conditions
$conditions = $this->getAchievementConditionsQuest($sourceAchievementId);
// Copy each condition
foreach($conditions as &$condition)
{
if(is_null($condition['quest_id']))
{
$this->db->query(
'INSERT INTO achievementconditions_quest '.
'(created_user_id, achievement_id, field, count, value, status, groupby) '.
'SELECT ?, ?, field, count, value, status, groupby '.
'FROM achievementconditions_quest '.
'WHERE id = ?',
'iii',
$userId, $targetAchievementId,
$condition['id']
);
}
else
{
$this->db->query(
'INSERT INTO achievementconditions_quest '.
'(created_user_id, achievement_id, field, count, value, quest_id, status, groupby) '.
'SELECT ?, ?, field, count, value, ?, status, groupby '.
'FROM achievementconditions_quest '.
'WHERE id = ?',
'iiii',
$userId, $targetAchievementId, $questIds[$condition['quest_id']],
$condition['id']
);
}
}
}
/** /**
* Delete a Quest condition. * Delete a Quest condition.
* *
@ -865,6 +962,52 @@
} }
/**
* Copy all Achievement 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
* @param array $achievementIds Mapping of Achievement-IDs from source Seminary to target Seminary
*/
public function copyAchievementConditionsAchievement($userId, $sourceAchievementId, $targetAchievementId, $achievementIds)
{
// Get conditions
$conditions = $this->getAchievementConditionsAchievement($sourceAchievementId);
// Copy each condition
foreach($conditions as &$condition)
{
if(is_null($condition['meta_achievement_id']) || !array_key_exists($condition['meta_achievement_id'], $achievementIds))
{
$this->db->query(
'INSERT INTO achievementconditions_achievement '.
'(created_user_id, achievement_id, field, count, value, groupby) '.
'SELECT ?, ?, field, count, value, groupby '.
'FROM achievementconditions_achievement '.
'WHERE id = ?',
'iii',
$userId, $targetAchievementId,
$condition['id']
);
}
else
{
$this->db->query(
'INSERT INTO achievementconditions_achievement '.
'(created_user_id, achievement_id, field, count, value, meta_achievement_id, groupby) '.
'SELECT ?, ?, field, count, value, ?, groupby '.
'FROM achievementconditions_achievement '.
'WHERE id = ?',
'iiii',
$userId, $targetAchievementId, $achievementIds[$condition['meta_achievement_id']],
$condition['id']
);
}
}
}
/** /**
* Delete a Achievement condition. * Delete a Achievement condition.
* *
@ -1134,6 +1277,97 @@
); );
} }
/**
* Copy all Achievements of a Seminary.
*
* @param int $userId ID of creating user
* @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
* @param array $questIds Mapping of Quest-IDs from source Seminary to target Seminary (optional)
*/
public function copyAchievementsOfSeminary($userId, $sourceSeminaryId, $targetSeminaryId, $seminaryMediaIds, $questIds=null)
{
$achievementIds = array();
// Get Achievements
$achievements = $this->getAchievementsForSeminary($sourceSeminaryId);
// Copy each Achievements
foreach($achievements as &$achievement)
{
// Check Quest-IDs
if($achievement['condition'] == 'quest' && is_null($questIds)) {
continue;
}
// Copy 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) '.
'SELECT ?, ?, achievementcondition_id, pos, title, url, description, progress, hidden, only_once, all_conditions, deadline '.
'FROM achievements '.
'WHERE id = ?',
'iii',
$userId, $targetSeminaryId,
$achievement['id']
);
$achievementIds[$achievement['id']] = $this->db->getInsertId();
// Copy media
if(!is_null($achievement['unachieved_achievementsmedia_id']))
{
$this->Media->copyAchievementMedia($userId, $seminaryMediaIds[$achievement['unachieved_achievementsmedia_id']]);
$this->db->query(
'UPDATE achievements '.
'SET unachieved_achievementsmedia_id = ? '.
'WHERE id = ?',
'ii',
$seminaryMediaIds[$achievement['unachieved_achievementsmedia_id']],
$achievementIds[$achievement['id']]
);
}
if(!is_null($achievement['achieved_achievementsmedia_id']))
{
$this->Media->copyAchievementMedia($userId, $seminaryMediaIds[$achievement['achieved_achievementsmedia_id']]);
$this->db->query(
'UPDATE achievements '.
'SET achieved_achievementsmedia_id = ? '.
'WHERE id = ?',
'ii',
$seminaryMediaIds[$achievement['achieved_achievementsmedia_id']],
$achievementIds[$achievement['id']]
);
}
}
// Copy Achievement conditions
// Do this after copying the Achievements itself to ensure Meta-
// Achievements work correctly
foreach($achievements as &$achievement)
{
// Copy conditions
switch($achievement['condition'])
{
case 'date':
$this->copyAchievementConditionsDate($userId, $achievement['id'], $achievementIds[$achievement['id']]);
break;
case 'quest':
if(!is_null($questIds)) {
$this->copyAchievementConditionsQuest($userId, $achievement['id'], $achievementIds[$achievement['id']], $questIds);
}
break;
case 'character':
$this->copyAchievementConditionsCharacter($userId, $achievement['id'], $achievementIds[$achievement['id']]);
break;
case 'achievement':
$this->copyAchievementConditionsAchievement($userId, $achievement['id'], $achievementIds[$achievement['id']], $achievementIds);
break;
}
}
}
/** /**
* Delete an Achievement. * Delete an Achievement.

View file

@ -19,6 +19,12 @@
*/ */
class AvatarsModel extends \hhu\z\Model class AvatarsModel extends \hhu\z\Model
{ {
/**
* Required models
*
* @var array
*/
public $models = array('media');
@ -88,6 +94,32 @@
} }
/**
* Get an Avatar by its Character type and XP-level.
*
* @param int $charactertypeId ID of Character type
* @param int $xplevelId ID of XP-level
* @return array Avatar data
*/
public function getAvatarByTypeAndLevelId($charactertypeId, $xplevelId)
{
$data = $this->db->query(
'SELECT id, charactertype_id, xplevel_id, avatarpicture_id, small_avatarpicture_id '.
'FROM avatars '.
'WHERE charactertype_id = ? AND xplevel_id = ?',
'ii',
$charactertypeId,
$xplevelId
);
if(empty($data)) {
throw new \nre\exceptions\IdNotFoundException($charactertypeId.'-'.$xplevelId);
}
return $data[0];
}
/** /**
* Set the picture for an Avatar. * Set the picture for an Avatar.
* *
@ -140,6 +172,51 @@
$avatarpictureId $avatarpictureId
); );
} }
/**
* Copy all Avatars from a Seminary.
*
* @param int $userId ID of copying user
* @param array $charactertypeIds Mapping of Charactertype-IDs from source Seminary to target Seminary
* @param array $xplevelIds Mapping of XP-level-IDs from source Seminary to targetSeminary
* @param array $seminaryMediaIds Mapping of Seminarymedia-IDs from source Seminary to target Seminary
*/
public function copyAvatars($userId, $charactertypeIds, $xplevelIds, $seminaryMediaIds)
{
// Copy Avatars
foreach($charactertypeIds as $sourceCharactertypeId => $targetCharactertypeId)
{
foreach($xplevelIds as $sourceXplevelId => $targetXplevelId)
{
try {
// Get Avatar
$avatar = $this->getAvatarByTypeAndLevelId($sourceCharactertypeId, $sourceXplevelId);
// Copy media
$this->Media->copyAvatarpicture($userId, $seminaryMediaIds[$avatar['avatarpicture_id']]);
$this->Media->copyAvatarpicture($userId, $seminaryMediaIds[$avatar['small_avatarpicture_id']]);
// Copy Avatar
$this->db->query(
'INSERT INTO avatars '.
'(created_user_id, charactertype_id, xplevel_id, avatarpicture_id, small_avatarpicture_id) '.
'VALUES '.
'(?, ?, ?, ?, ?)',
'iiiii',
$userId,
$targetCharactertypeId,
$targetXplevelId,
$seminaryMediaIds[$avatar['avatarpicture_id']],
$seminaryMediaIds[$avatar['small_avatarpicture_id']]
);
}
catch(\nre\exceptions\IdNotFoundException $e) {
// Not all combinations of charactertypes and XP-levels exist
}
}
}
}
} }

View file

@ -176,6 +176,42 @@
$groupsgroupId $groupsgroupId
); );
} }
/**
* Copy all Character groups-groups of a Seminary.
*
* @param int $userId ID of creating user
* @param int $sourceSeminaryId ID of Seminary to copy from
* @param int $targetSeminaryId ID of Seminary to copy to
* @param array Mapping of Character groups-groups-IDs from source Seminary to target Seminary
*/
public function copyGroupsgroupsOfSeminary($userId, $sourceSeminaryId, $targetSeminaryId)
{
$groupsgroupIds = array();
// Get Character groups
$groupsgroups = $this->getGroupsroupsForSeminary($sourceSeminaryId);
// Copy each Groups-group
foreach($groupsgroups as &$group)
{
$this->db->query(
'INSERT INTO charactergroupsgroups '.
'(created_user_id, seminary_id, name, url, preferred) '.
'SELECT ?, ?, name, url, preferred '.
'FROM charactergroupsgroups '.
'WHERE id = ?',
'iii',
$userId, $targetSeminaryId,
$group['id']
);
$groupsgroupIds[$group['id']] = $this->db->getInsertId();
}
return $groupsgroupIds;
}
/** /**

View file

@ -25,7 +25,7 @@
* *
* @var array * @var array
*/ */
public $models = array('uploads'); public $models = array('uploads', 'media');
@ -50,7 +50,7 @@
public function getQuestsForCharactergroupsgroup($groupsgroupId) public function getQuestsForCharactergroupsgroup($groupsgroupId)
{ {
return $this->db->query( return $this->db->query(
'SELECT id, questgroups_id, title, url, xps '. 'SELECT id, questgroups_id, title, url, xps, questsmedia_id '.
'FROM charactergroupsquests '. 'FROM charactergroupsquests '.
'WHERE charactergroupsgroup_id = ? '. 'WHERE charactergroupsgroup_id = ? '.
'ORDER BY created ASC', 'ORDER BY created ASC',
@ -375,6 +375,55 @@
} }
/**
* Copy all Character groups Quests from a Seminary.
*
* @param int $userId ID of copying user
* @param array $groupsgroupIds Mapping of Character groups-group-IDs from source Seminary to target Seminary
* @param array $questgroupIds Mapping of Questgroup-IDs from source Seminary to target Seminary
* @param array $seminaryMediaIds Mapping of Seminarymedia-IDs from source Seminary to target Seminary (optional)
*/
public function copyQuestsOfSeminary($userId, $groupsgroupIds, $questgroupIds, $seminaryMediaIds=null)
{
foreach($groupsgroupIds as $sourceGroupsgroupId => $targetGroupsgroupId)
{
// Get Quests
$quests = $this->getQuestsForCharactergroupsgroup($sourceGroupsgroupId);
// Copy each Quest
foreach($quests as &$quest)
{
// Copy Quest
$this->db->query(
'INSERT INTO charactergroupsquests '.
'(created_user_id, charactergroupsgroup_id, questgroups_id, title, url, description, xps, rules, won_text, lost_text) '.
'SELECT ?, ?, ?, title, url, description, xps, rules, won_text, lost_text '.
'FROM charactergroupsquests '.
'WHERE id = ?',
'iiii',
$userId, $targetGroupsgroupId, $questgroupIds[$quest['questgroups_id']],
$quest['id']
);
$targetQuestId = $this->db->getInsertId();
// Copy media
if(!is_null($seminaryMediaIds) && !is_null($quest['questsmedia_id']))
{
$this->Media->copyQuestsmedia($userId, $seminaryMediaIds[$quest['questsmedia_id']]);
$this->db->query(
'UPDATE charactergroupsquests '.
'SET questsmedia_id = ? '.
'WHERE id = ?',
'ii',
$seminaryMediaIds[$quest['questsmedia_id']],
$targetQuestId
);
}
}
}
}
/** /**
* Delete a Character groups Quest. * Delete a Character groups Quest.
* *

View file

@ -201,6 +201,42 @@
} }
/**
* Copy all Charactertypes of a Seminary.
*
* @param int $userId ID of copying user
* @param int $sourceSeminaryId ID of Seminary to copy from
* @param int $targetSeminaryId ID of Seminary to copy to
* @param array Mapping of Charactertype-IDs from source Seminary to targetSeminary
*/
public function copyCharactertypesOfSeminary($userId, $sourceSeminaryId, $targetSeminaryId)
{
$charactertypeIds = array();
// Get Charactertypes
$charactertypes = $this->getCharacterTypesForSeminary($sourceSeminaryId);
// Copy each Charactertype
foreach($charactertypes as &$type)
{
$this->db->query(
'INSERT INTO charactertypes '.
'(created_user_id, seminary_id, name, url) '.
'SELECT ?, ?, name, url '.
'FROM charactertypes '.
'WHERE id = ?',
'iii',
$userId, $targetSeminaryId,
$type['id']
);
$charactertypeIds[$type['id']] = $this->db->getInsertId();
}
return $charactertypeIds;
}
/** /**
* Delete a Charactertype. * Delete a Charactertype.
* *

View file

@ -133,6 +133,68 @@
return $data[0]; return $data[0];
} }
/**
* Copy all media from a Seminary.
*
* @param int $userId ID of creating user
* @param int $sourceSeminaryId ID of Seminary to copy from
* @param int $targetSeminaryId ID of Seminary to copy to
* @return array Mapping of Media-IDs from source Seminary to target Seminary
*/
public function copySeminaryMedia($userId, $sourceSeminaryId, $targetSeminaryId)
{
$seminaryMediaIds = array();
$copiedFiles = array();
// Get all media from a Seminary
$seminaryMedia = $this->db->query(
'SELECT id '.
'FROM seminarymedia '.
'WHERE seminary_id = ?',
'i',
$sourceSeminaryId
);
// Copy each medium
try {
foreach($seminaryMedia as &$medium)
{
// Copy database record
$this->db->query(
'INSERT INTO seminarymedia '.
'(created_user_id, seminary_id, name, url, description, mimetype) '.
'SELECT ?, ?, name, url, description, mimetype '.
'FROM seminarymedia '.
'WHERE id = ?',
'iii',
$userId, $targetSeminaryId,
$medium['id']
);
$seminaryMediaIds[$medium['id']] = $this->db->getInsertId();
// Copy file
$sourceFilename = ROOT.DS.\nre\configs\AppConfig::$dirs['seminarymedia'].DS.$medium['id'];
$targetFilename = ROOT.DS.\nre\configs\AppConfig::$dirs['seminarymedia'].DS.$seminaryMediaIds[$medium['id']];
if(!copy($sourceFilename, $targetFilename)) {
throw new \hhu\z\exceptions\FileCopyException(error_get_last());
}
$copiedFiles[] = $targetFilename;
}
}
catch(\hhu\z\exceptions\FileCopyException $e) {
// Cleanup
foreach($copiedFiles as $filename) {
unlink($filename);
}
throw $e;
}
// Return new media IDs
return $seminaryMediaIds;
}
/** /**
@ -227,6 +289,29 @@
return $mediaId; return $mediaId;
} }
/**
* Copy an Avatar picture.
*
* @param int $userId ID of creating user
* @param int $seminaryMediaId ID of Seminary media to copy
*/
public function copyAvatarpicture($userId, $avatarpictureId)
{
$this->db->query(
'INSERT INTO avatarpictures '.
'(seminarymedia_id, created_user_id) '.
'VALUES '.
'(?, ?) '.
'ON DUPLICATE KEY UPDATE '.
'created_user_id = ?',
'iii',
$avatarpictureId,
$userId,
$userId
);
}
/** /**
* Create a new Questgroup picture (Moodpic). * Create a new Questgroup picture (Moodpic).
@ -280,6 +365,29 @@
$this->db->setAutocommit(true); $this->db->setAutocommit(true);
return $mediaId; return $mediaId;
} }
/**
* Copy a Questgroup picture.
*
* @param int $userId ID of creating user
* @param int $seminaryMediaId ID of Seminary media to copy
*/
public function copyQuestgroupspicture($userId, $questgroupspictureId)
{
$this->db->query(
'INSERT INTO questgroupspictures '.
'(media_id, created_user_id) '.
'VALUES '.
'(?, ?) '.
'ON DUPLICATE KEY UPDATE '.
'created_user_id = ?',
'iii',
$questgroupspictureId,
$userId,
$userId
);
}
/** /**
@ -337,6 +445,30 @@
$this->db->setAutocommit(true); $this->db->setAutocommit(true);
return $mediaId; return $mediaId;
} }
/**
* Copy media of a Quest.
*
* @param int $userId ID of creating user
* @param int $seminaryMediaId ID of Quest media to copy
*/
public function copyQuestsmedia($userId, $seminaryMediaId)
{
$this->db->query(
'INSERT INTO questsmedia '.
'(media_id, created_user_id) '.
'VALUES '.
'(?, ?) '.
'ON DUPLICATE KEY UPDATE '.
'created_user_id = ?',
'iii',
$seminaryMediaId,
$userId,
$userId
);
}
/** /**
@ -445,6 +577,30 @@
$this->db->setAutocommit(true); $this->db->setAutocommit(true);
return $mediaId; return $mediaId;
} }
/**
* Copy Achievement media.
*
* @param int $userId ID of creating user
* @param int $seminaryMediaId ID of Seminary media to copy
*/
public function copyAchievementMedia($userId, $seminaryMediaId)
{
$this->db->query(
'INSERT INTO achievementsmedia '.
'(seminarymedia_id, created_user_id) '.
'VALUES '.
'(?, ?) '.
'ON DUPLICATE KEY UPDATE '.
'created_user_id = ?',
'iii',
$seminaryMediaId,
$userId,
$userId
);
}
@ -465,8 +621,9 @@
$data = $this->db->query( $data = $this->db->query(
'SELECT id '. 'SELECT id '.
'FROM seminarymedia '. 'FROM seminarymedia '.
'WHERE url = ?', 'WHERE seminary_id = ? AND url = ?',
's', 'is',
$seminaryId,
\nre\core\Linker::createLinkParam($filename) \nre\core\Linker::createLinkParam($filename)
); );
if(!empty($data)) { if(!empty($data)) {

View file

@ -31,7 +31,7 @@
* *
* @var array * @var array
*/ */
public $models = array('questgroupshierarchy', 'quests'); public $models = array('questgroupshierarchy', 'questgrouptexts', 'quests', 'questtexts', 'media');
@ -98,7 +98,7 @@
public function getQuestgroupsForSeminary($seminaryId) public function getQuestgroupsForSeminary($seminaryId)
{ {
return $this->db->query( return $this->db->query(
'SELECT id, title, url, achievable_xps '. 'SELECT id, title, url, questgroupspicture_id, achievable_xps '.
'FROM questgroups '. 'FROM questgroups '.
'WHERE seminary_id = ? '. 'WHERE seminary_id = ? '.
'ORDER BY title ASC', 'ORDER BY title ASC',
@ -396,6 +396,7 @@
} }
// XPs of child Questgroups // XPs of child Questgroups
//var_dump($this->Questgroupshierarchy);
$questgroupHierarchy = $this->Questgroupshierarchy->getHierarchyForQuestgroup($questgroupId); $questgroupHierarchy = $this->Questgroupshierarchy->getHierarchyForQuestgroup($questgroupId);
if(!empty($questgroupHierarchy)) if(!empty($questgroupHierarchy))
{ {
@ -519,6 +520,79 @@
} }
/**
* Copy Questgroupshierarchy of Questgroups from a Seminary.
*
* @param array $questgroupshierarchyIds Mapping of hierarchy-IDs from source Seminary to target Seminary
* @param array $questgroupIds Mapping of Questgroup-IDs from source Seminary to target Seminary
*/
public function copyQuestgroupsHierarchy($questgroupshierarchyIds, $questgroupIds)
{
foreach($questgroupIds as $sourceQuestgroupId => $targetQuestgroupId)
{
$hierarchy = $this->Questgroupshierarchy->getHierarchyForQuestgroup($sourceQuestgroupId);
if(!is_null($hierarchy))
{
if(is_null($hierarchy['parent_questgroup_id']))
{
$this->db->query(
'INSERT INTO questgroups_questgroupshierarchy '.
'(questgroup_id, questgroupshierarchy_id, parent_questgroup_id, pos) '.
'VALUES '.
'(?, ?, null, ?)',
'iii',
$targetQuestgroupId,
$questgroupshierarchyIds[$hierarchy['id']],
$hierarchy['questgroup_pos']
);
}
else
{
$this->db->query(
'INSERT INTO questgroups_questgroupshierarchy '.
'(questgroup_id, questgroupshierarchy_id, parent_questgroup_id, pos) '.
'VALUES '.
'(?, ?, ?, ?)',
'iiii',
$targetQuestgroupId,
$questgroupshierarchyIds[$hierarchy['id']],
$questgroupIds[$hierarchy['parent_questgroup_id']],
$hierarchy['questgroup_pos']
);
}
}
}
}
/**
* Copy all related Questgroups of Questtexts of a Seminary.
*
* @param array $questgroupIds Mapping of Questgroup-IDs from source Seminary to target Seminary
* @param array $questtextIds Mapping of Questtext-IDs from source Seminary to target Seminary
*/
public function copyRelatedQuestgroups($questgroupIds, $questtextIds)
{
foreach($questgroupIds as $sourceQuestgroupId => $targetQuestgroupId)
{
$questtexts = $this->Questtexts->getRelatedQuesttextsForQuestgroup($sourceQuestgroupId);
foreach($questtexts as &$questtext)
{
$this->db->query(
'INSERT INTO questgroups_questtexts '.
'(questgroup_id, questtext_id, entry_text) '.
'SELECT ?, ?, entry_text '.
'FROM questgroups_questtexts '.
'WHERE questgroup_id = ? AND questtext_id = ?',
'iiii',
$targetQuestgroupId, $questtextIds[$questtext['id']],
$sourceQuestgroupId, $questtext['id']
);
}
}
}
/** /**
* Move a Questgroup up (decrement position) or down (increment * Move a Questgroup up (decrement position) or down (increment
* position). * position).
@ -604,6 +678,61 @@
} }
/**
* Copy Questgroups of Seminary.
*
* @throws \nre\exceptions\DatamodelException
* @param int $userId ID of creating user
* @param int $sourceSeminaryId ID of Seminary to copy Questgroups from
* @param int $targetSeminaryId ID of Seminary to copy Questgroups to
* @param array $questgroupshierarchyIds Mapping of hierarchy-IDs from source Seminary to target Seminary
* @param array $seminaryMediaIds Mapping of Seminary-media-IDs from source Seminary to target Seminary (optional)
* @return array Mapping of Questgroup-IDs from source Seminary to target Seminary
*/
public function copyQuestgroupsOfSeminary($userId, $sourceSeminaryId, $targetSeminaryId, $questgroupshierarchyIds, $seminaryMediaIds=null)
{
// Get Questgroups of source Seminary
$questgroupIds = array();
$questgroups = $this->getQuestgroupsForSeminary($sourceSeminaryId);
foreach($questgroups as &$questgroup)
{
// Insert into target Seminary
$this->db->query(
'INSERT INTO questgroups '.
'(created_user_id, seminary_id, title, url) '.
'VALUES '.
'(?, ?, ?, ?)',
'iiss',
$userId,
$targetSeminaryId,
$questgroup['title'],
$questgroup['url']
);
$questgroupIds[$questgroup['id']] = $this->db->getInsertId();
// Copy media
if(!is_null($seminaryMediaIds) && !is_null($questgroup['questgroupspicture_id']))
{
$this->Media->copyQuestgroupspicture($userId, $seminaryMediaIds[$questgroup['questgroupspicture_id']]);
$this->db->query(
'UPDATE questgroups '.
'SET questgroupspicture_id = ? '.
'WHERE id = ?',
'ii',
$seminaryMediaIds[$questgroup['questgroupspicture_id']],
$questgroupIds[$questgroup['id']]
);
}
// Copy Questgroup texts
$this->Questgrouptexts->copyQuestgrouptexts($userId, $questgroup['id'], $questgroupIds[$questgroup['id']]);
}
return $questgroupIds;
}
/** /**
* Delete a Questgroup. * Delete a Questgroup.
* *

View file

@ -302,7 +302,31 @@
} }
$this->db->setAutocommit(true); $this->db->setAutocommit(true);
} }
/**
* Copy complete Questgroupshierarchy of a Seminary.
*
* @param int $userId ID of creating user
* @param int $sourceSeminaryId ID of Seminary to copy hierarchy from
* @param int $targetSeminaryId ID of Seminary to copy hierarchy to
* @return array Mapping of hierarchy-IDs from source Seminary to target Seminary
*/
public function copyQuestgroupshierarchy($userId, $sourceSeminaryId, $targetSeminaryId)
{
// Get Hierarchy of Seminary
$questgroupshierarchy = $this->getHierarchyOfSeminary($sourceSeminaryId);
// Copy hierarchy
$hierarchyIds = array();
foreach($questgroupshierarchy as $hierarchy) {
$this->copyHierarchy($userId, $sourceSeminaryId, $targetSeminaryId, $hierarchy, $hierarchyIds);
}
return $hierarchyIds;
}
/** /**
* Delete a Questgroupshierarchy. * Delete a Questgroupshierarchy.
@ -313,6 +337,56 @@
{ {
$this->db->query('DELETE FROM questgroupshierarchy WHERE id = ?', 'i', $questgroupshierarchyId); $this->db->query('DELETE FROM questgroupshierarchy WHERE id = ?', 'i', $questgroupshierarchyId);
} }
/**
* Copy a Questgroupshierarchy and its child hierarchy.
*
* @param int $userId ID of creating user
* @param int $sourceSeminaryId ID of Seminary to copy hierarchy from
* @param int $targetSeminaryId ID of Seminary to copy hierarchy to
* @param array $hierarchy Hierarchy to copy
* @return array $hierarchyIds Mapping of hierarchy IDs from source Seminary to target Seminary
*/
private function copyHierarchy($userId, $sourceSeminaryId, $targetSeminaryId, $hierarchy, &$hierarchyIds)
{
// insert for new seminary
if(is_null($hierarchy['parent_questgroupshierarchy_id']))
{
$this->db->query(
'INSERT INTO questgroupshierarchy '.
'(created_user_id, seminary_id, parent_questgroupshierarchy_id, pos, title_singular, title_plural, url) '.
'SELECT ?, ?, null, pos, title_singular, title_plural, url '.
'FROM questgroupshierarchy '.
'WHERE id = ?',
'iii',
$userId, $targetSeminaryId,
$hierarchy['id']
);
}
else
{
$this->db->query(
'INSERT INTO questgroupshierarchy '.
'(created_user_id, seminary_id, parent_questgroupshierarchy_id, pos, title_singular, title_plural, url) '.
'SELECT ?, ?, ?, pos, title_singular, title_plural, url '.
'FROM questgroupshierarchy '.
'WHERE id = ?',
'iiii',
$userId, $targetSeminaryId, $hierarchyIds[$hierarchy['parent_questgroupshierarchy_id']],
$hierarchy['id']
);
}
$hierarchyIds[$hierarchy['id']] = $this->db->getInsertId();
// insert sub hierarchy
$childHierarchy = $this->getChildQuestgroupshierarchy($hierarchy['id']);
foreach($childHierarchy as $hierarchy) {
$this->copyHierarchy($userId, $sourceSeminaryId, $targetSeminaryId, $hierarchy, $hierarchyIds);
}
}
} }

View file

@ -19,12 +19,6 @@
*/ */
class QuestgrouptextsModel extends \hhu\z\Model class QuestgrouptextsModel extends \hhu\z\Model
{ {
/**
* Required models
*
* @var array
*/
public $models = array('questgroupshierarchy', 'questgroups', 'quests', 'questtexts');
@ -59,52 +53,6 @@
} }
/**
* Get the first text of a Questgroup.
*
* @param int $questgroupId ID of a Questgroup
* @return string First text of this Questgroup or NULL
*/
public function getFirstQuestgroupText($questgroupId)
{
// Text of Questgroup itself
$questgroupTexts = $this->getQuestgroupTexts($questgroupId);
if(!empty($questgroupTexts)) {
return $questgroupTexts[0]['text'];
}
// Text of first Quest
$quest = $this->Quests->getFirstQuestOfQuestgroup($questgroupId);
if(!is_null($quest))
{
$questText = $this->Questtexts->getFirstQuestText($quest['id']);
if(!is_null($questText)) {
return $questText;
}
}
// Text of ChildQuestgroups
$questgroupHierarchy = $this->Questgroupshierarchy->getHierarchyForQuestgroup($questgroupId);
$childQuestgroupshierarchy = $this->Questgroupshierarchy->getChildQuestgroupshierarchy($questgroupHierarchy['id']);
foreach($childQuestgroupshierarchy as &$hierarchy)
{
// Get Questgroups
$questgroups = $this->Questgroups->getQuestgroupsForHierarchy($hierarchy['id'], $questgroupId);
foreach($questgroups as &$group)
{
$childQuestgroupText = $this->getFirstQuestgroupText($group['id']);
if(!is_null($childQuestgroupText)) {
return $childQuestgroupText;
}
}
}
// No text found
return null;
}
/** /**
* Add a Questgroup text to a Questgroup. * Add a Questgroup text to a Questgroup.
* *
@ -155,6 +103,28 @@
} }
/**
* Copy Questgroup texts from one Questgroup to another.
*
* @param $userId ID of copying user
* @param $sourceQuestgroupId ID of source Questgroup
* @param $targetQuestgroupId ID of target Questgroup
*/
public function copyQuestgrouptexts($userId, $sourceQuestgroupId, $targetQuestgroupId)
{
$this->db->query(
'INSERT INTO questgrouptexts '.
'(created_user_id, questgroup_id, pos, text) '.
'SELECT ?, ?, pos, text '.
'FROM questgrouptexts '.
'WHERE questgroup_id = ?',
'iii',
$userId, $targetQuestgroupId,
$sourceQuestgroupId
);
}
/** /**
* Delete a Questgroup text. * Delete a Questgroup text.
* *

View file

@ -43,6 +43,13 @@
* @var int; * @var int;
*/ */
const QUEST_STATUS_SOLVED = 3; const QUEST_STATUS_SOLVED = 3;
/**
* Required models
*
* @var array
*/
public $models = array('questtypes', 'questtexts', 'media');
@ -481,7 +488,6 @@
/** /**
* Mark a Quest for a Character. * Mark a Quest for a Character.
* *
@ -676,6 +682,83 @@
} }
/**
* Copy all Quests from a Seminary.
*
* @param int $userId ID of creating user
* @param int $seminaryId ID of Seminary to copy from
* @param array $questgroupIds Mapping of Questgroup-IDs from source Seminary to target Seminary
* @param array $seminaryMediaIds Mapping of Seminary-media-IDs from source Seminary to target Seminary (optional)
* @return array Mapping of Quest-IDs from source Seminary to target Seminary
*/
public function copyQuests($userId, $sourceSeminaryId, $questgroupIds, $seminaryMediaIds=null)
{
$questIds = array();
$questtextIds = array();
// Get Quests
$quests = $this->getQuestsForSeminary($sourceSeminaryId);
// Copy each Quest
foreach($quests as &$quest)
{
// Copy Quest
$this->db->query(
'INSERT INTO quests '.
'(created_user_id, questgroup_id, questtype_id, title, url, xps, entry_text, wrong_text, task) '.
'SELECT ?, ?, questtype_id, title, url, xps, entry_text, wrong_text, task '.
'FROM quests '.
'WHERE id = ?',
'iii',
$userId,
$questgroupIds[$quest['questgroup_id']],
$quest['id']
);
$questIds[$quest['id']] = $this->db->getInsertId();
// Copy media
if(!is_null($seminaryMediaIds) && !is_null($quest['questsmedia_id']))
{
$this->Media->copyQuestsmedia($userId, $seminaryMediaIds[$quest['questsmedia_id']]);
$this->db->query(
'UPDATE quests '.
'SET questsmedia_id = ? '.
'WHERE id = ?',
'ii',
$seminaryMediaIds[$quest['questsmedia_id']],
$questIds[$quest['id']]
);
}
// Copy texts
$questtextIds = array_merge(
$questtextIds,
$this->Questtexts->copyQuesttexts($userId, $quest['id'], $questIds[$quest['id']], $seminaryMediaIds)
);
// Copy content
$questtype = $this->Questtypes->getQuesttypeById($quest['questtype_id']);
if(!is_null($questtype['classname']))
{
// Load Questtype Model
\hhu\z\models\QuesttypeModel::load($questtype['classname']);
// Construct Questtype Model
$questtypeModel = \hhu\z\models\QuesttypeModel::factory($questtype['classname']);
// Copy content
$questtypeModel->copyQuest($userId, $quest['id'], $questIds[$quest['id']], $seminaryMediaIds);
}
}
return array(
'quests' => $questIds,
'questtexts' => $questtextIds
);
}
/** /**
* Delete a Quest of a Seminary. * Delete a Quest of a Seminary.
* *

View file

@ -19,6 +19,12 @@
*/ */
class QuesttextsModel extends \hhu\z\Model class QuesttextsModel extends \hhu\z\Model
{ {
/**
* Required models
*
* @var array
*/
public $models = array('media');
@ -304,6 +310,57 @@
$questtextId $questtextId
); );
} }
/**
* Copy Quest texts from one Quest to another.
*
* @param int $userId ID of copying user
* @param int $sourceQuestId ID of source Quest
* @param int $targetQuestId ID of target Quest
* @param array $seminaryMediaIds Mapping of Seminary-media-IDs from source Seminary to target Seminary (optional)
*/
public function copyQuesttexts($userId, $sourceQuestId, $targetQuestId, $seminaryMediaIds=null)
{
$questtextIds = array();
// Get Questtexts
$questtexts = $this->getQuesttextsOfQuest($sourceQuestId);
// Copy each text
foreach($questtexts as &$text)
{
// Copy text
$this->db->query(
'INSERT INTO questtexts '.
'(created_user_id, quest_id, questtexttype_id, pos, text, out_text, abort_text) '.
'SELECT ?, ?, questtexttype_id, pos, text, out_text, abort_text '.
'FROM questtexts '.
'WHERE id = ?',
'iii',
$userId, $targetQuestId,
$text['id']
);
$questtextIds[$text['id']] = $this->db->getInsertId();
// Copy media
if(!is_null($seminaryMediaIds) && !is_null($text['questsmedia_id']))
{
$this->Media->copyQuestsmedia($userId, $seminaryMediaIds[$text['questsmedia_id']]);
$this->db->query(
'UPDATE questtexts '.
'SET questsmedia_id = ? '.
'WHERE id = ?',
'ii',
$seminaryMediaIds[$text['questsmedia_id']],
$questtextIds[$text['id']]
);
}
}
return $questtextIds;
}
/** /**

View file

@ -100,6 +100,81 @@
$seminaryId $seminaryId
); );
} }
/**
* Copy all Questtopics and their subtopics of a Seminary.
*
* @param int $userId ID of creating user
* @param int $sourceSeminaryId ID of Seminary to copy from
* @param int $targetSeminaryId ID of Seminary to copy to
* @param array $questIds Mapping of Quest-IDs from source Seminary to target Seminary
* @return array Mapping of Questsubtopic-IDs from source Seminary to targetSeminary
*/
public function copyQuesttopicsOfSeminary($userId, $sourceSeminaryId, $targetSeminaryId, $questIds)
{
$questsubtopicIds = array();
// Get Questtopics
$questtopics = $this->getQuesttopicsForSeminary($sourceSeminaryId);
foreach($questtopics as &$questtopic)
{
// Copy Questtopic
$this->db->query(
'INSERT INTO questtopics '.
'(created_user_id, seminary_id, title, url) '.
'SELECT ?, ?, title, url '.
'FROM questtopics '.
'WHERE id = ?',
'iii',
$userId, $targetSeminaryId,
$questtopic['id']
);
$targetQuesttopicId = $this->db->getInsertId();
// Get Questsubtopics
$questsubtopics = $this->getSubtopicsForQuesttopic($questtopic['id']);
foreach($questsubtopics as &$questsubtopic)
{
// Copy Questsubtopic
$this->db->query(
'INSERT INTO questsubtopics '.
'(created_user_id, questtopic_id, title, url) '.
'SELECT ?, ?, title, url '.
'FROM questsubtopics '.
'WHERE id = ?',
'iii',
$userId, $targetQuesttopicId,
$questsubtopic['id']
);
$questsubtopicIds[$questsubtopic['id']] = $this->db->getInsertId();
// Get Quest links
$quests = $this->db->query(
'SELECT quest_id '.
'FROM quests_questsubtopics '.
'WHERE questsubtopic_id = ?',
'i',
$questsubtopic['id']
);
foreach($quests as &$quest)
{
$this->db->query(
'INSERT INTO quests_questsubtopics '.
'(quest_id, questsubtopic_id) '.
'VALUES '.
'(?, ?)',
'ii',
$questIds[$quest['quest_id']],
$questsubtopicIds[$questsubtopic['id']]
);
}
}
}
return $questsubtopicIds;
}
/** /**

View file

@ -24,7 +24,7 @@
* *
* @var array * @var array
*/ */
public $models = array('questgroupshierarchy', 'questgroups'); public $models = array('questgroupshierarchy', 'questgroups', 'quests', 'questtopics', 'media', 'charactertypes', 'xplevels', 'avatars', 'achievements', 'charactergroups', 'charactergroupsquests', 'seminarycharacterfields');
@ -200,6 +200,28 @@
$seminaryId $seminaryId
); );
} }
/**
* (Re-) Calculate the amount of achievable XPs for a Seminary.
*
* @param int $seminaryId ID of Seminary to calculate XPs for
*/
public function calculateXPsForSeminary($seminaryId)
{
// Questgrouphierarchy and Questgroups
$questgroupshierarchy = $this->Questgroupshierarchy->getHierarchyOfSeminary($seminaryId);
foreach($questgroupshierarchy as &$hierarchy)
{
// Get Questgroups
$hierarchy['questgroups'] = $this->Questgroups->getQuestgroupsForHierarchy($hierarchy['id']);
foreach($hierarchy['questgroups'] as &$questgroup)
{
// Calculate achievable XPs
$this->Questgroups->calculateXPsForQuestgroup($questgroup['id']);
}
}
}
/** /**
@ -225,6 +247,122 @@
$seminaryId $seminaryId
); );
} }
/**
* Copy a Seminary and its content.
*
* @param int $userId ID of copying user
* @param int $sourceSeminaryId ID of Seminary to copy
* @param string $title Title of new Seminary
* @param string $course Course of now Seminary
* @param string $description Description of new Seminary
* @param boolean $copySeminaryfields Whether to copy Seminary Character fields of not
* @param boolean $copyMedia Whether to copy media or not
* @param boolean $copyQuestgroupshierarchy Whether to copy Questgroupshierarchy or not
* @param boolean $copyQuestgroups Whether to copy Questgroups or not
* @param boolean $copyQuests Whether to copy Quests or not
* @param boolean $copyQuesttopics Whether to copy Quest topics or not
* @param boolean $copyCharactertypes Whether to copy Charactertypes or not
* @param boolean $copyXPlevels Whether to copy XP-levels or not
* @param boolean $copyAvatars Whether to copy Avatars or not
* @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
* @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)
{
$this->db->setAutocommit(false);
try {
// Create new Seminary
$targetSeminaryId = $this->createSeminary($userId, $title, $course, $description);
// Copy Seminary fields
if($copySeminaryfields) {
$this->Seminarycharacterfields->copyFieldsOfSeminary($userId, $sourceSeminaryId, $targetSeminaryId);
}
// Copy media
$seminaryMediaIds = null;
if($copyMedia) {
$seminaryMediaIds = $this->Media->copySeminaryMedia($userId, $sourceSeminaryId, $targetSeminaryId);
}
// Copy Quest content
$questIds = null;
$questgroupIds = null;
// Questgroupshierarchy
if($copyQuestgroupshierarchy)
{
$questgroupshierarchyIds = $this->Questgroupshierarchy->copyQuestgroupshierarchy($userId, $sourceSeminaryId, $targetSeminaryId);
// Questgroups
if($copyQuestgroups)
{
$questgroupIds = $this->Questgroups->copyQuestgroupsOfSeminary($userId, $sourceSeminaryId, $targetSeminaryId, $questgroupshierarchyIds, $seminaryMediaIds);
$this->Questgroups->copyQuestgroupsHierarchy($questgroupshierarchyIds, $questgroupIds);
// Quests
if($copyQuests)
{
$questAndTextIds = $this->Quests->copyQuests($userId, $sourceSeminaryId, $questgroupIds, $seminaryMediaIds);
$questIds = $questAndTextIds['quests'];
$questtextIds = $questAndTextIds['questtexts'];
$this->Questgroups->copyRelatedQuestgroups($questgroupIds, $questtextIds);
// Questtopics
if($copyQuesttopics) {
$questsubtopicIds = $this->Questtopics->copyQuesttopicsOfSeminary($userId, $sourceSeminaryId, $targetSeminaryId, $questIds);
}
}
}
}
// Copy Character content
// Charactertypes
if($copyCharactertypes)
{
$charactertypeIds = $this->Charactertypes->copyCharactertypesOfSeminary($userId, $sourceSeminaryId, $targetSeminaryId);
// XP-levels
if($copyXPlevels)
{
$xplevelIds = $this->Xplevels->copyXPLevelsOfSeminary($userId, $sourceSeminaryId, $targetSeminaryId);
// Avatars
if($copyAvatars && !is_null($seminaryMediaIds)) {
$this->Avatars->copyAvatars($userId, $charactertypeIds, $xplevelIds, $seminaryMediaIds);
}
}
}
// Copy Achievements
if($copyAchievements && !is_null($seminaryMediaIds)) {
$this->Achievements->copyAchievementsOfSeminary($userId, $sourceSeminaryId, $targetSeminaryId, $seminaryMediaIds, $questIds);
}
// Copy Charactergroups content
// Charactergroupsgroups
if($copyCharactergroupsgroups)
{
$characterGroupsgroupIds = $this->Charactergroups->copyGroupsgroupsOfSeminary($userId, $sourceSeminaryId, $targetSeminaryId);
// Copy Charactergroupsquests
if($copyCharactergroupsquests &!is_null($questgroupIds)) {
$this->Charactergroupsquests->copyQuestsOfSeminary($userId, $characterGroupsgroupIds, $questgroupIds, $seminaryMediaIds);
}
}
// Recalculate XPs
$this->calculateXPsForSeminary($targetSeminaryId);
$this->db->commit();
}
catch(\Exception $e) {
$this->db->rollback();
$this->db->setAutocommit(true);
throw $e;
}
$this->db->setAutocommit(true);
return $targetSeminaryId;
}
/** /**
@ -236,7 +374,7 @@
{ {
$this->db->query('DELETE FROM seminaries WHERE id = ?', 'i', $seminaryId); $this->db->query('DELETE FROM seminaries WHERE id = ?', 'i', $seminaryId);
} }
} }
?> ?>

View file

@ -123,6 +123,28 @@
$characterId $characterId
); );
} }
/**
* Copy all Character fields of a Seminary.
*
* @param int $userId ID of copying user
* @param int $sourceSeminaryId ID of Seminary to copy from
* @param int $targetSeminaryId ID of Seminary to copy to
*/
public function copyFieldsOfSeminary($userId, $sourceSeminaryId, $targetSeminaryId)
{
$this->db->query(
'INSERT INTO seminarycharacterfields '.
'(created_user_id, seminary_id, pos, title, url, seminarycharacterfieldtype_id, regex, required) '.
'SELECT ?, ?, pos, title, url, seminarycharacterfieldtype_id, regex, required '.
'FROM seminarycharacterfields '.
'WHERE seminary_id = ?',
'iii',
$userId, $targetSeminaryId,
$sourceSeminaryId
);
}
} }

View file

@ -161,6 +161,42 @@
); );
} }
/**
* Copy all XP-levels of a Seminary.
*
* @param int $userId ID of copying user
* @param int $sourceSeminaryId ID of Seminary to copy from
* @param int $targetSeminaryId ID of Seminary to copy to
* @param array Mapping of XP-level-IDs from source Seminary to targetSeminary
*/
public function copyXPLevelsOfSeminary($userId, $sourceSeminaryId, $targetSeminaryId)
{
$xplevelIds = array();
// Get XP-levels
$xplevels = $this->getXPLevelsForSeminary($sourceSeminaryId);
// Copy each XP-level
foreach($xplevels as &$level)
{
$this->db->query(
'INSERT INTO xplevels '.
'(created_user_id, seminary_id, xps, level, name) '.
'SELECT ?, ?, xps, level, name '.
'FROM xplevels '.
'WHERE id = ?',
'iii',
$userId, $targetSeminaryId,
$level['id']
);
$xplevelIds[$level['id']] = $this->db->getInsertId();
}
return $xplevelIds;
}
/** /**
* Delete a XP-level. * Delete a XP-level.

View file

@ -19,10 +19,55 @@
*/ */
class BossfightQuesttypeModel extends \hhu\z\models\QuesttypeModel class BossfightQuesttypeModel extends \hhu\z\models\QuesttypeModel
{ {
/**
* Required models
*
* @var array
*/
public $models = array('media');
/**
* Copy a Quest
*
* @param int $userId ID of creating user
* @param int $sourceQuestId ID of Quest to copy from
* @param int $targetQuestId ID of Quest to copy to
* @param int $seminaryMediaIds Mapping of SeminaryMedia-IDs from source Seminary to targetSeminary
*/
public function copyQuest($userId, $sourceQuestId, $targetQuestId, $seminaryMediaIds)
{
// Check Seminary media
if(is_null($seminaryMediaIds)) {
return;
}
// Get boss fight
$bossfight = $this->getBossFight($sourceQuestId);
// Copy media
$this->Media->copyQuestsmedia($userId, $seminaryMediaIds[$bossfight['boss_seminarymedia_id']]);
// Copy boss fight
$this->db->query(
'INSERT INTO questtypes_bossfight '.
'(quest_id, created_user_id, bossname, boss_seminarymedia_id, lives_character, lives_boss) '.
'SELECT ?, ?, bossname, ?, lives_character, lives_boss '.
'FROM questtypes_bossfight '.
'WHERE quest_id = ?',
'iiii',
$targetQuestId, $userId, $seminaryMediaIds[$bossfight['boss_seminarymedia_id']],
$sourceQuestId
);
// Copy stages
$stage = $this->getFirstStage($sourceQuestId);
$this->copyStage($userId, $targetQuestId, $stage);
}
/** /**
* Get a Boss-Fight. * Get a Boss-Fight.
* *
@ -57,7 +102,7 @@
public function getFirstStage($questId) public function getFirstStage($questId)
{ {
$data = $this->db->query( $data = $this->db->query(
'SELECT id, text, question, livedrain_character, livedrain_boss '. 'SELECT id, parent_stage_id, text, question, livedrain_character, livedrain_boss '.
'FROM questtypes_bossfight_stages '. 'FROM questtypes_bossfight_stages '.
'WHERE questtypes_bossfight_quest_id = ? AND parent_stage_id IS NULL', 'WHERE questtypes_bossfight_quest_id = ? AND parent_stage_id IS NULL',
'i', 'i',
@ -105,7 +150,7 @@
public function getChildStages($parentStageId) public function getChildStages($parentStageId)
{ {
return $this->db->query( return $this->db->query(
'SELECT id, text, question, livedrain_character, livedrain_boss '. 'SELECT id, parent_stage_id, text, question, livedrain_character, livedrain_boss '.
'FROM questtypes_bossfight_stages '. 'FROM questtypes_bossfight_stages '.
'WHERE parent_stage_id = ?', 'WHERE parent_stage_id = ?',
'i', 'i',
@ -177,6 +222,55 @@
return (!empty($data)); return (!empty($data));
} }
/**
* Copy a Bossfight stage and its child-stages.
*
* @param int $userId ID of copying user
* @param int $targetQuestId ID of Quest to copy to
* @param array $stage Data of stage to copy
* @param array $stageIds Mapping of Stage-IDs from source Seminary to target Seminary
*/
private function copyStage($userId, $targetQuestId, $stage, $stageIds=array())
{
// Copy stage
if(is_null($stage['parent_stage_id']))
{
$this->db->query(
'INSERT INTO questtypes_bossfight_stages '.
'(questtypes_bossfight_quest_id, text, question, livedrain_character, livedrain_boss) '.
'SELECT ?, text, question, livedrain_character, livedrain_boss '.
'FROM questtypes_bossfight_stages '.
'WHERE id = ?',
'ii',
$targetQuestId,
$stage['id']
);
}
else
{
$this->db->query(
'INSERT INTO questtypes_bossfight_stages '.
'(questtypes_bossfight_quest_id, parent_stage_id, text, question, livedrain_character, livedrain_boss) '.
'SELECT ?, ?, text, question, livedrain_character, livedrain_boss '.
'FROM questtypes_bossfight_stages '.
'WHERE id = ?',
'iii',
$targetQuestId, $stageIds[$stage['parent_stage_id']],
$stage['id']
);
}
$stageIds[$stage['id']] = $this->db->getInsertId();
// Copy child stages
$childStages = $this->getChildStages($stage['id']);
foreach($childStages as $childStage) {
$this->copyStage($userId, $targetQuestId, $childStage, $stageIds);
}
}
} }

View file

@ -24,6 +24,79 @@
/**
* Copy a Quest
*
* @param int $userId ID of creating user
* @param int $sourceQuestId ID of Quest to copy from
* @param int $targetQuestId ID of Quest to copy to
* @param int $seminaryMediaIds Mapping of SeminaryMedia-IDs from source Seminary to targetSeminary
*/
public function copyQuest($userId, $sourceQuestId, $targetQuestId, $seminaryMediaIds)
{
// Copy choiceinput
$this->db->query(
'INSERT INTO questtypes_choiceinput '.
'(quest_id, created_user_id, text) '.
'SELECT ?, ?, text '.
'FROM questtypes_choiceinput '.
'WHERE quest_id = ?',
'iii',
$targetQuestId, $userId,
$sourceQuestId
);
// Copy lists
$lists = $this->getChoiceinputLists($sourceQuestId);
foreach($lists as &$list)
{
// Copy list
$this->db->query(
'INSERT INTO questtypes_choiceinput_lists '.
'(questtypes_choiceinput_quest_id, number) '.
'SELECT ?, number '.
'FROM questtypes_choiceinput_lists '.
'WHERE id = ?',
'ii',
$targetQuestId,
$list['id']
);
$targetListId = $this->db->getInsertId();
// Copy choices
$choiceIds = array();
$choices = $this->getChoiceinputChoices($list['id']);
foreach($choices as $choice)
{
$this->db->query(
'INSERT INTO questtypes_choiceinput_choices '.
'(questtypes_choiceinput_list_id, pos, text) '.
'SELECT ?, pos, text '.
'FROM questtypes_choiceinput_choices '.
'WHERE id = ?',
'ii',
$targetListId,
$choice['id']
);
$choiceIds[$choice['id']] = $this->db->getInsertId();
}
// Set correct choice
if(!is_null($list['questtypes_choiceinput_choice_id']))
{
$this->db->query(
'UPDATE questtypes_choiceinput_lists '.
'SET questtypes_choiceinput_choice_id = ? '.
'WHERE id = ?',
'ii',
$choiceIds[$list['questtypes_choiceinput_choice_id']],
$targetListId
);
}
}
}
/** /**
* Get choiceinput-text for a Quest. * Get choiceinput-text for a Quest.
* *

View file

@ -23,6 +23,30 @@
/**
* Copy a Quest
*
* @param int $userId ID of creating user
* @param int $sourceQuestId ID of Quest to copy from
* @param int $targetQuestId ID of Quest to copy to
* @param int $seminaryMediaIds Mapping of SeminaryMedia-IDs from source Seminary to targetSeminary
*/
public function copyQuest($userId, $sourceQuestId, $targetQuestId, $seminaryMediaIds)
{
// Copy words
$this->db->query(
'INSERT INTO questtypes_crossword_words '.
'(quest_id, question, word, vertical, pos_x, pos_y) '.
'SELECT ?, question, word, vertical, pos_x, pos_y '.
'FROM questtypes_crossword_words '.
'WHERE quest_id = ?',
'ii',
$targetQuestId,
$sourceQuestId
);
}
/** /**
* Get all words for a crossword-Quest. * Get all words for a crossword-Quest.
* *

View file

@ -19,10 +19,115 @@
*/ */
class DragndropQuesttypeModel extends \hhu\z\models\QuesttypeModel class DragndropQuesttypeModel extends \hhu\z\models\QuesttypeModel
{ {
/**
* Required models
*
* @var array
*/
public $models = array('media');
/**
* Copy a Quest
*
* @param int $userId ID of creating user
* @param int $sourceQuestId ID of Quest to copy from
* @param int $targetQuestId ID of Quest to copy to
* @param int $seminaryMediaIds Mapping of SeminaryMedia-IDs from source Seminary to targetSeminary
*/
public function copyQuest($userId, $sourceQuestId, $targetQuestId, $seminaryMediaIds)
{
// Check Seminary media
if(is_null($seminaryMediaIds)) {
return;
}
// Get Dragndrop
$dragndrop = $this->getDragndrop($sourceQuestId);
// Copy media
$this->Media->copyQuestsmedia($userId, $seminaryMediaIds[$dragndrop['questmedia_id']]);
// Copy dran&drop
$this->db->query(
'INSERT INTO questtypes_dragndrop '.
'(quest_id, created_user_id, questmedia_id, width, height) '.
'SELECT ?, ?, ?, width, height '.
'FROM questtypes_dragndrop '.
'WHERE quest_id = ?',
'iiii',
$targetQuestId, $userId, $seminaryMediaIds[$dragndrop['questmedia_id']],
$sourceQuestId
);
// Copy drags
$dragIds = array();
$drags = $this->getDrags($sourceQuestId);
foreach($drags as &$drag)
{
// Copy media
$this->Media->copyQuestsmedia($userId, $seminaryMediaIds[$drag['questmedia_id']]);
// Copy drag
$this->db->query(
'INSERT INTO questtypes_dragndrop_drags '.
'(questtypes_dragndrop_id, questmedia_id) '.
'SELECT ?, ? '.
'FROM questtypes_dragndrop_drags '.
'WHERE id = ?',
'iii',
$targetQuestId, $seminaryMediaIds[$drag['questmedia_id']],
$drag['id']
);
$dragIds[$drag['id']] = $this->db->getInsertId();
}
// Copy drops
$dropIds = array();
$drops = $this->getDrops($sourceQuestId);
foreach($drops as &$drop)
{
// Copy drop
$this->db->query(
'INSERT INTO questtypes_dragndrop_drops '.
'(questtypes_dragndrop_id, top, `left`, width, height) '.
'SELECT ?, top, `left`, width, height '.
'FROM questtypes_dragndrop_drops '.
'WHERE id = ?',
'ii',
$targetQuestId,
$drop['id']
);
$dropIds[$drop['id']] = $this->db->getInsertId();
// Link drags and drops
$links = $this->db->query(
'SELECT questtypes_dragndrop_drag_id '.
'FROM questtypes_dragndrop_drops_drags '.
'WHERE questtypes_dragndrop_drop_id = ?',
'i',
$drop['id']
);
foreach($links as $link)
{
$this->db->query(
'INSERT INTO questtypes_dragndrop_drops_drags '.
'(questtypes_dragndrop_drop_id, questtypes_dragndrop_drag_id, created_user_id) '.
'VALUES '.
'(?, ?, ?)',
'iii',
$dropIds[$drop['id']],
$dragIds[$link['questtypes_dragndrop_drag_id']],
$userId
);
}
}
}
/** /**
* Get Drag&Drop-field. * Get Drag&Drop-field.
* *

View file

@ -23,6 +23,50 @@
/**
* Copy a Quest
*
* @param int $userId ID of creating user
* @param int $sourceQuestId ID of Quest to copy from
* @param int $targetQuestId ID of Quest to copy to
* @param int $seminaryMediaIds Mapping of SeminaryMedia-IDs from source Seminary to targetSeminary
*/
public function copyQuest($userId, $sourceQuestId, $targetQuestId, $seminaryMediaIds)
{
// Get questions
$questions = $this->getQuestionsOfQuest($sourceQuestId);
// Copy each question
foreach($questions as &$question)
{
// Copy question
$this->db->query(
'INSERT INTO questtypes_multiplechoice '.
'(created_user_id, quest_id, pos, question) '.
'SELECT ?, ?, pos, question '.
'FROM questtypes_multiplechoice '.
'WHERE id = ?',
'iii',
$userId, $targetQuestId,
$question['id']
);
$targetQuestionId = $this->db->getInsertId();
// Copy answers
$this->db->query(
'INSERT INTO questtypes_multiplechoice_answers '.
'(created_user_id, questtypes_multiplechoice_id, pos, answer, tick) '.
'SELECT ?, ?, pos, answer, tick '.
'FROM questtypes_multiplechoice_answers '.
'WHERE questtypes_multiplechoice_id = ?',
'iii',
$userId, $targetQuestionId,
$question['id']
);
}
}
/** /**
* Get the count of multiple choice questions for a Quest. * Get the count of multiple choice questions for a Quest.
* *

View file

@ -29,6 +29,19 @@
/**
* Copy a Quest
*
* @param int $userId ID of creating user
* @param int $sourceQuestId ID of Quest to copy from
* @param int $targetQuestId ID of Quest to copy to
* @param int $seminaryMediaIds Mapping of SeminaryMedia-IDs from source Seminary to targetSeminary
*/
public function copyQuest($userId, $sourceQuestId, $targetQuestId, $seminaryMediaIds)
{
}
/** /**
* Save Characters submitted upload. * Save Characters submitted upload.
* *

View file

@ -23,6 +23,42 @@
/**
* Copy a Quest
*
* @param int $userId ID of creating user
* @param int $sourceQuestId ID of Quest to copy from
* @param int $targetQuestId ID of Quest to copy to
* @param int $seminaryMediaIds Mapping of SeminaryMedia-IDs from source Seminary to targetSeminary
*/
public function copyQuest($userId, $sourceQuestId, $targetQuestId, $seminaryMediaIds)
{
// Copy textinput
$this->db->query(
'INSERT INTO questtypes_textinput '.
'(quest_id, created_user_id, text) '.
'SELECT ?, ?, text '.
'FROM questtypes_textinput '.
'WHERE quest_id = ?',
'iii',
$targetQuestId, $userId,
$sourceQuestId
);
// Copy fields
$this->db->query(
'INSERT INTO questtypes_textinput_fields '.
'(questtypes_textinput_quest_id, number, questtypes_textinput_fieldsize_id, regex) '.
'SELECT ?, number, questtypes_textinput_fieldsize_id, regex '.
'FROM questtypes_textinput_fields '.
'WHERE questtypes_textinput_quest_id = ?',
'ii',
$targetQuestId,
$sourceQuestId
);
}
/** /**
* Get textinput-text for a Quest. * Get textinput-text for a Quest.
* *

View file

@ -0,0 +1,116 @@
<?php if(!is_null($seminary['seminarymedia_id'])) : ?>
<div class="moodpic">
<img src="<?=$linker->link(array('media','seminarymoodpic',$seminary['url']))?>">
</div>
<?php endif ?>
<ul class="breadcrumbs">
<li><a href="<?=$linker->link('index',1)?>"><?=_('Seminaries')?></a></li>
</ul>
<h1><?=_('Copy seminary')?></h1>
<?php if(!is_null($exception)) : ?>
<p class="error">
<?php if($exception instanceof \hhu\z\exceptions\FileCopyException) : ?>
<?=sprintf(_('Copying of files failed: “%s”'), $exception->getNestedError()['message'])?>
<?php elseif($exception instanceof \Exception) : ?>
<?=sprintf(_('Copying of Seminary failed: “%s”'), $exception->getMessage())?>
<?php endif ?>
</p>
<?php endif ?>
<?php if($validation !== true) : ?>
<ul>
<?php foreach($validation as $field => &$settings) : ?>
<li>
<ul>
<?php foreach($settings as $setting => $value) : ?>
<li>
<?php switch($field) {
case 'moodpic':
switch($setting) {
case 'error': printf(_('Error during moodpic upload: %s'), $value);
break;
case 'mimetype': printf(_('Moodpic has wrong type “%s”'), $value);
break;
case 'size': echo _('Moodpic exceeds size maximum');
break;
default: echo _('Moodpic invalid');
}
break;
case 'title':
switch($setting) {
case 'minlength': printf(_('Title is too short (min. %d chars)'), $value);
break;
case 'maxlength': printf(_('Title is too long (max. %d chars)'), $value);
break;
case 'regex': echo _('Title contains illegal characters');
break;
case 'exist': echo _('Title already exists');
break;
default: echo _('Title invalid');
}
break;
case 'course':
switch($setting) {
case 'maxlength': printf(_('Course is too long (max. %d chars)'), $value);
break;
default: echo _('Course invalid');
}
break;
} ?>
</li>
<?php endforeach ?>
</ul>
</li>
<?php endforeach ?>
</ul>
<?php endif ?>
<form method="post" class="logreg" enctype="multipart/form-data">
<fieldset>
<label for="title"><?=_('Title')?>:</label>
<input type="text" id="title" name="title" placeholder="<?=_('Title')?>" maxlength="<?=$validationSettings['title']['maxlength']?>" value="<?=$title?>" <?=($validation !== true && array_key_exists('title', $validation)) ? 'class="invalid"' : null?> /><br />
<label for="course"><?=_('Course')?>:</label>
<input type="text" id="course" name="course" placeholder="<?=_('Course')?>" maxlength="<?=$validationSettings['course']['maxlength']?>" value="<?=$course?>" <?=($validation !== true && array_key_exists('course', $validation)) ? 'class="invalid"' : null?> /><br />
<label for="description"><?=_('Description')?>:<br />
<textarea id="description" name="description" placeholder="<?=_('Description')?>"><?=$description?></textarea><br />
</fieldset>
<fieldset>
<legend><?=_('Elements')?></legend>
<input type="checkbox" id="elements_seminaryfields" name="elements[seminaryfields]" <?php if(array_key_exists('seminaryfields', $elements)) : ?>checked="checked"<?php endif ?> />
<label for="elements_seminaryfields"><?=_('Seminary fields')?></label>
<input type="checkbox" id="elements_media" name="elements[media]" <?php if(array_key_exists('media', $elements)) : ?>checked="checked"<?php endif ?> />
<label for="elements_media"><?=_('Media')?></label>
<input type="checkbox" id="elements_questgroupshierarchy" name="elements[questgroupshierarchy]" <?php if(array_key_exists('questgroupshierarchy', $elements)) : ?>checked="checked"<?php endif ?> />
<label for="elements_questgroupshierarchy"><?=_('Questgroupshierarchy')?></label>
<div class="cond">
<input type="checkbox" id="elements_questgroups" name="elements[questgroups]" <?php if(array_key_exists('questgroups', $elements)) : ?>checked="checked"<?php endif ?> />
<label for="elements_questgroups"><?=_('Questgroups')?></label>
<div class="cond">
<input type="checkbox" id="elements_quests" name="elements[quests]" <?php if(array_key_exists('quests', $elements)) : ?>checked="checked"<?php endif ?> />
<label for="elements_quests"><?=_('Quests')?></label>
<div class="cond">
<input type="checkbox" id="elements_questtopics" name="elements[questtopics]" <?php if(array_key_exists('questtopics', $elements)) : ?>checked="checked"<?php endif ?> />
<label for="elements_questtopics"><?=_('Library')?></label>
</div>
</div>
</div>
<input type="checkbox" id="elements_charactertypes" name="elements[charactertypes]" <?php if(array_key_exists('charactertypes', $elements)) : ?>checked="checked"<?php endif ?> />
<label for="elements_charactertypes"><?=_('Charactertypes')?></label>
<div class="cond">
<input type="checkbox" id="elements_xplevels" name="elements[xplevels]" <?php if(array_key_exists('xplevels', $elements)) : ?>checked="checked"<?php endif ?> />
<label for="elements_xplevels"><?=_('XP-Levels')?></label>
<div class="cond">
<input type="checkbox" id="elements_avatars" name="elements[avatars]" <?php if(array_key_exists('avatars', $elements)) : ?>checked="checked"<?php endif ?> />
<label for="elements_avatars"><?=_('Avatars')?></label>
</div>
</div>
<input type="checkbox" id="elements_achievements" name="elements[achievements]" <?php if(array_key_exists('achievements', $elements)) : ?>checked="checked"<?php endif ?> />
<label for="elements_achievements"><?=_('Achievements')?></label>
<input type="checkbox" id="elements_charactergroupsgroups" name="elements[charactergroupsgroups]" <?php if(array_key_exists('charactergroupsgroups', $elements)) : ?>checked="checked"<?php endif ?> />
<label for="elements_charactergroupsgroups"><?=_('Character Groups')?></label>
<div class="cond">
<input type="checkbox" id="elements_charactergroupsquests" name="elements[charactergroupsquests]" <?php if(array_key_exists('charactergroupsquests', $elements)) : ?>checked="checked"<?php endif ?> />
<label for="elements_charactergroupsquests"><?=_('Character Groups Quests')?></label>
</div>
</fieldset>
<input type="submit" name="edit" value="<?=_('copy')?>" />
</form>

View file

@ -8,6 +8,7 @@
<?php if(in_array('admin', \hhu\z\controllers\SeminaryController::$character['characterroles'])) : ?> <?php if(in_array('admin', \hhu\z\controllers\SeminaryController::$character['characterroles'])) : ?>
<nav class="admin"> <nav class="admin">
<li><a href="<?=$linker->link('edit', 3)?>"><?=_('Edit seminary')?></a></li> <li><a href="<?=$linker->link('edit', 3)?>"><?=_('Edit seminary')?></a></li>
<li><a href="<?=$linker->link('copy', 3)?>"><?=_('Copy seminary')?></a></li>
<li><a href="<?=$linker->link('delete', 3)?>"><?=_('Delete seminary')?></a></li> <li><a href="<?=$linker->link('delete', 3)?>"><?=_('Delete seminary')?></a></li>
</nav> </nav>
<?php endif ?> <?php endif ?>

View file

@ -181,6 +181,9 @@ input[type="submit"][disabled]{text-shadow:1px 2px #d48c4e;background:#f9ac69;bo
.logreg textarea,.logreg select{width:100%;margin:5px 0 15px;-webkit-box-sizing: border-box;-moz-box-sizing:border-box;box-sizing:border-box} .logreg textarea,.logreg select{width:100%;margin:5px 0 15px;-webkit-box-sizing: border-box;-moz-box-sizing:border-box;box-sizing:border-box}
.logreg textarea{height:150px} .logreg textarea{height:150px}
.logreg .cta{display:block} .logreg .cta{display:block}
.logreg input[type="checkbox"]{margin:0}
.logreg input[type="checkbox"] + label{display:inline;}
.logreg input[type="checkbox"] + label:after{content:"\A";white-space:pre}
.inlbl input{display:inline;margin:0 10px 0 0} .inlbl input{display:inline;margin:0 10px 0 0}
.inlbl label{display:inline} .inlbl label{display:inline}
@ -453,3 +456,7 @@ aside .charstats{background:#f7f5f2;border-radius:3px;padding:10px 0;margin-top:
aside .charstats li{font-size:.875em;padding:2px 0} aside .charstats li{font-size:.875em;padding:2px 0}
aside .cranks li:nth-child(odd){background:#f7f5f2} aside .cranks li:nth-child(odd){background:#f7f5f2}
} }
div.cond{display:none;margin-left:15px}
input[type="checkbox"]:checked + label + div.cond{display:block}