From: Roland Häder <roland@mxchange.org>
Date: Tue, 4 Jun 2013 12:45:38 +0000 (+0000)
Subject: Project continued:
X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=b045ba361328cce0482ad1e5a73c3f7549ae1f40;p=mailer.git

Project continued:
- Added more functions for ext-grade
- Fixesd XML template for ext-grade
- Added missing language element
- Swapped out 'setup' phase for ext-grade
- Added more asserts
- Various other fixes
---

diff --git a/.gitattributes b/.gitattributes
index fb60ceb11c..bff1090714 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -258,6 +258,8 @@ inc/extensions/ext-yacy.php svneol=native#text/plain
 inc/extensions/ext-yoomedia.php svneol=native#text/plain
 inc/extensions/forced/.htaccess svneol=native#text/plain
 inc/extensions/forced/mode-setup.php svneol=native#text/plain
+inc/extensions/grade/.htaccess svneol=native#text/plain
+inc/extensions/grade/mode-setup.php svneol=native#text/plain
 inc/extensions/holiday/.htaccess svneol=native#text/plain
 inc/extensions/holiday/mode-update.php svneol=native#text/plain
 inc/extensions/html_mail/.htaccess svneol=native#text/plain
@@ -2142,6 +2144,8 @@ templates/de/html/select/select_forced_costs_id_box.tpl svneol=native#text/plain
 templates/de/html/select/select_forced_costs_id_option.tpl svneol=native#text/plain
 templates/de/html/select/select_forced_costs_visibility_box.tpl svneol=native#text/plain
 templates/de/html/select/select_forced_costs_visibility_option.tpl svneol=native#text/plain
+templates/de/html/select/select_grade_parent_id_box.tpl svneol=native#text/plain
+templates/de/html/select/select_grade_parent_id_option.tpl svneol=native#text/plain
 templates/de/html/select/select_network_box.tpl svneol=native#text/plain
 templates/de/html/select/select_network_configured_box.tpl svneol=native#text/plain
 templates/de/html/select/select_network_configured_option.tpl svneol=native#text/plain
diff --git a/inc/callback-functions.php b/inc/callback-functions.php
index ee0a38754b..0f800a2fd3 100644
--- a/inc/callback-functions.php
+++ b/inc/callback-functions.php
@@ -1290,7 +1290,7 @@ function doXmlCallbackExtraParameterListEntry ($resource, $attributes) {
 	// There are three attributes, by default
 	if (count($attributes) != 3) {
 		// Not the right count
-		reportBug(__FUNCTION__, __LINE__, 'Expected 5 attributes, got ' . count($attributes));
+		reportBug(__FUNCTION__, __LINE__, 'Expected 3 attributes, got ' . count($attributes));
 	} elseif (!isset($attributes['COLUMN'])) {
 		// 'COLUMN' not found
 		reportBug(__FUNCTION__, __LINE__, 'Required attribute COLUMN not found.');
@@ -1300,15 +1300,18 @@ function doXmlCallbackExtraParameterListEntry ($resource, $attributes) {
 	} elseif (!isInvalidXmlType($attributes['TYPE'])) {
 		// No valid type
 		reportBug(__FUNCTION__, __LINE__, 'TYPE is not valid, got: ' . $attributes['TYPE']);
-	} elseif (!isset($attributes['VALUE'])) {
+	} elseif ((!isset($attributes['VALUE'])) && (!isset($attributes['DATA']))) {
 		// 'VALUE' not found
-		reportBug(__FUNCTION__, __LINE__, 'Required attribute VALUE not found.');
-	} elseif (!isXmlValueValid($attributes['TYPE'], $attributes['VALUE'])) {
+		reportBug(__FUNCTION__, __LINE__, 'Required attribute VALUE/DATA not found.');
+	} elseif ((isset($attributes['VALUE'])) && (!isXmlValueValid($attributes['TYPE'], $attributes['VALUE']))) {
 		// 'VALUE' not valid/verifyable
 		reportBug(__FUNCTION__, __LINE__, 'Attribute VALUE does not validate. VALUE=' . $attributes['VALUE']);
 	} elseif (!isset($GLOBALS['__XML_ARGUMENTS']['doXmlCallbackFunction']['__EXTRA_PARAMETER'])) {
-		// doXmlCallbackFunction is missing
+		// doXmlCallbackFunction/__EXTRA_PARAMETER is missing
 		reportBug(__FUNCTION__, __LINE__, 'Required XML node callback-function/__EXTRA_PARAMETER not included around this node. Please fix your XML.');
+	} elseif (!isset($GLOBALS['__XML_ARGUMENTS']['doXmlCallbackFunction']['data_column_list'])) {
+		// doXmlCallbackFunction/data_column_list is missing
+		reportBug(__FUNCTION__, __LINE__, 'Required XML node callback-function/data_column_list not included around this node.');
 	}
 
 	// Add the entry to the array
@@ -1320,7 +1323,7 @@ function doXmlNoEntryFoundMessage ($resource, $attributes) {
 	// There are two attributes, by default
 	if (count($attributes) != 2) {
 		// Not the right count
-		reportBug(__FUNCTION__, __LINE__, 'Expected 3 attributes, got ' . count($attributes));
+		reportBug(__FUNCTION__, __LINE__, 'Expected 2 attributes, got ' . count($attributes));
 	} elseif (!isset($attributes['VALUE'])) {
 		// 'VALUE' not found
 		reportBug(__FUNCTION__, __LINE__, 'Required attribute VALUE not found.');
@@ -1509,9 +1512,16 @@ function addXmlValueToCallbackAttributes ($element, $attributes, $extraKey = '',
 		);
 		//* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'element=' . $element . ',extraKey=' . $extraKey . ',TYPE=' . $attributes['TYPE'] . ',NAME[' . gettype($attributes['NAME']) . ']=' . $attributes['NAME'] . ' - TYPE-COLUMN! (COLUMN=' . $attributes['COLUMN'] . ')');
 		$GLOBALS['__XML_ARGUMENTS']['doXmlCallbackFunction'][$element][count($GLOBALS['__XML_ARGUMENTS']['doXmlCallbackFunction'][$element])] = $array;
-	} elseif (isset($attributes['COLUMN'])) {
+	} elseif ((isset($attributes['COLUMN'])) && (isset($attributes['VALUE']))) {
 		// COLUMN/VALUE detected
-		//* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'element=' . $element . ',VALUE[' . gettype($attributes['VALUE']) . ']=' . $attributes['VALUE'] . ',COLUMN[' . gettype($attributes['COLUMN']) . ']=' . $attributes['COLUMN'] . ' - COLUMN!');
+		//* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'element=' . $element . ',VALUE[' . gettype($attributes['VALUE']) . ']=' . $attributes['VALUE'] . ',COLUMN[' . gettype($attributes['COLUMN']) . ']=' . $attributes['COLUMN'] . ' - COLUMN/VALUE!');
+		if (!isset($GLOBALS['__XML_ARGUMENTS']['doXmlCallbackFunction'][$element][$attributes['COLUMN']])) {
+			$GLOBALS['__XML_ARGUMENTS']['doXmlCallbackFunction'][$element][$attributes['COLUMN']] = array();
+		} // END - if
+		$GLOBALS['__XML_ARGUMENTS']['doXmlCallbackFunction'][$element][$attributes['COLUMN']][count($GLOBALS['__XML_ARGUMENTS']['doXmlCallbackFunction'][$element][$attributes['COLUMN']])] = $attributes['VALUE'];
+	} elseif ((isset($attributes['COLUMN'])) && (isset($attributes['DATA']))) {
+		// COLUMN/DATA detected
+		//* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'element=' . $element . ',DATA[' . gettype($attributes['DATA']) . ']=' . $attributes['DATA'] . ',COLUMN[' . gettype($attributes['COLUMN']) . ']=' . $attributes['COLUMN'] . ' - COLUMN/DATA!');
 		if (!isset($GLOBALS['__XML_ARGUMENTS']['doXmlCallbackFunction'][$element][$attributes['COLUMN']])) {
 			$GLOBALS['__XML_ARGUMENTS']['doXmlCallbackFunction'][$element][$attributes['COLUMN']] = array();
 		} // END - if
@@ -1530,10 +1540,13 @@ function addXmlValueToCallbackAttributes ($element, $attributes, $extraKey = '',
 	} elseif (isset($GLOBALS['__XML_ARGUMENTS']['doXmlCallbackFunction'][$element][$attributes['NAME']])) {
 		// Already created
 		reportBug(__FUNCTION__, __LINE__, 'NAME=' . $attributes['NAME'] . ' already addded to ' . $element . ' attributes=<pre>' . print_r($attributes, TRUE) . '</pre>');
-	} else {
-		// Use from NAME
+	} elseif ((isset($attributes['NAME'])) && (isset($attributes['VALUE']))) {
+		// Use from NAME/VALUE
 		//* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'element=' . $element . ',NAME=' . $attributes['NAME'] . ',VALUE[' . gettype($attributes['VALUE']) . ']=' . $attributes['VALUE'] . ' - NAME!');
 		$GLOBALS['__XML_ARGUMENTS']['doXmlCallbackFunction'][$element][$attributes['NAME']] = $attributes['VALUE'];
+	} else {
+		// Unknown stage
+		reportBug(__FUNCTION__, __LINE__, 'Unexpected stage detected. element=' . $element . ',attributes()=' . count($attributes));
 	}
 	//* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'element=' . $element . ',extraKey=' . $extraKey . ',key=' . $key . ' - EXIT!');
 }
diff --git a/inc/extensions/ext-grade.php b/inc/extensions/ext-grade.php
index 3eca648b6c..addae42a9c 100644
--- a/inc/extensions/ext-grade.php
+++ b/inc/extensions/ext-grade.php
@@ -51,66 +51,6 @@ enableExtensionProductive(FALSE);
 
 switch (getExtensionMode()) {
 	case 'setup': // Do stuff when installation is running
-		// General and grade level data
-		addDropTableSql('grade_data');
-		addCreateTableSql('grade_data', "
-`grade_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
-`grade_name` VARCHAR(255) NOT NULL DEFAULT '',
-`grade_description` TINYTEXT NOT NULL,
-`grade_parent_id` BIGINT(20) UNSIGNED NULL DEFAULT NULL,
-UNIQUE INDEX (`grade_name`),
-INDEX (`grade_parent_id`),
-PRIMARY KEY (`grade_id`)",
-			'Grade data');
-
-		// Data for if a grade level has been reached
-		addDropTableSql('grade_cash_data');
-		addCreateTableSql('grade_cash_data', "
-`cash_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
-`grade_cash_name` VARCHAR(255) NOT NULL DEFAULT '',
-`grade_cash_type` ENUM('DISCOUNT','BONUS') NOT NULL DEFAULT 'DISCOUNT',
-`reached_points` FLOAT(20,5) UNSIGNED NULL DEFAULT NULL,
-`reached_mails` BIGINT(20) UNSIGNED NULL DEFAULT NULL,
-`time_valid` BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
-UNIQUE INDEX (`grade_cash_name`),
-PRIMARY KEY (`cash_id`)",
-			'Data for "cashed" grades');
-
-		// Connection grade<->cash data
-		addDropTableSql('grade_cash_connect');
-		addCreateTableSql('grade_cash_connect', "
-`connect_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
-`grade_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
-`grade_cash_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
-UNIQUE INDEX `grade_cash` (`grade_id`, `grade_cash_id`),
-INDEX (`grade_cash_id`),
-PRIMARY KEY (`connect_id`)",
-			'Grade<->cash data connection');
-
-		// Connection grade<->user data
-		addDropTableSql('grade_user_connect');
-		addCreateTableSql('grade_user_connect', "
-`connect_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
-`userid` BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
-`grade_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
-`grade_expired` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
-UNIQUE INDEX (`userid`, `grade_id`),
-INDEX (`grade_id`),
-PRIMARY KEY (`connect_id`)",
-			'Grade<->user connection');
-
-		// Admin menu entries
-		addAdminMenuSql('grade', NULL, 'Accountstufen', 'Stufen Sie Ihre Mitglieder ein, die sie ab einer einstellbaren Anzahl an {OPEN_CONFIG}POINTS{CLOSE_CONFIG} oder best&auml;tigten Mails usw. erhalten und durch die Accountstufe Erm&auml;&szlig;igungen oder Sonderboni erhalten k&ouml;nnen.', 6);
-		addAdminMenuSql('grade', 'list_grade_data', 'Auflisten...', 'Listet alle Accountstufen auf, auch sind diese hier editierbar, neue hinzuf&uuml;gbar und l&ouml;schbar.', 1);
-		addAdminMenuSql('grade', 'list_cash_grade', 'Erm&auml;&szlig;igungen/Sonderboni', 'Listet alle Erm&auml;&szlig;igungen/Sonderboni auf, auch sind diese hier editierbar, neue hinzuf&uuml;gbar und l&ouml;schbar.', 2);
-		addAdminMenuSql('grade', 'list_current_grades', 'Mitgliedaccountsstufen', 'Liste alle durch die Mitglieder aktuell erreichten Einstungen auf. Diese sind nicht editierbar (wir wollen ja nicht schummeln und bestimmten Mitgliedern bessere Accountstufen geben, oder? ;-) ).', 3);
-		addAdminMenuSql('grade', 'config_grade', 'Einstellungen ...', 'Diverse Einstellungen zu den Accountstufen.', 4);
-
-		// Member menu
-		addMemberMenuSql('account', 'grade', 'Erreichte Stufe', 2);
-
-		// Guest menu
-		addGuestMenuSql('members', 'grade', 'Accountstufen', 4);
 		break;
 
 	case 'remove': // Do stuff when removing extension
diff --git a/inc/extensions/grade/.htaccess b/inc/extensions/grade/.htaccess
new file mode 100644
index 0000000000..3a42882788
--- /dev/null
+++ b/inc/extensions/grade/.htaccess
@@ -0,0 +1 @@
+Deny from all
diff --git a/inc/extensions/grade/mode-setup.php b/inc/extensions/grade/mode-setup.php
new file mode 100644
index 0000000000..4bf66510cb
--- /dev/null
+++ b/inc/extensions/grade/mode-setup.php
@@ -0,0 +1,111 @@
+<?php
+/************************************************************************
+ * Mailer v0.2.1-FINAL                                Start: 11/24/2009 *
+ * ===================                          Last change: 11/24/2009 *
+ *                                                                      *
+ * -------------------------------------------------------------------- *
+ * File              : ext-grade.php                                    *
+ * -------------------------------------------------------------------- *
+ * Short description : Grades for your members                          *
+ * -------------------------------------------------------------------- *
+ * Kurzbeschreibung  : Accountstufen Ihrer Mitglieder                   *
+ * -------------------------------------------------------------------- *
+ * $Revision::                                                        $ *
+ * $Date::                                                            $ *
+ * $Tag:: 0.2.1-FINAL                                                 $ *
+ * $Author::                                                          $ *
+ * -------------------------------------------------------------------- *
+ * Copyright (c) 2003 - 2009 by Roland Haeder                           *
+ * Copyright (c) 2009 - 2013 by Mailer Developer Team                   *
+ * For more information visit: http://mxchange.org                      *
+ *                                                                      *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or    *
+ * (at your option) any later version.                                  *
+ *                                                                      *
+ * This program is distributed in the hope that it will be useful,      *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
+ * GNU General Public License for more details.                         *
+ *                                                                      *
+ * You should have received a copy of the GNU General Public License    *
+ * along with this program; if not, write to the Free Software          *
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,               *
+ * MA  02110-1301  USA                                                  *
+ ************************************************************************/
+
+// Some security stuff...
+if (!defined('__SECURITY')) {
+	die();
+} // END - if
+
+// @TODO Remove double tabs from all lines
+		// General and grade level data
+		addDropTableSql('grade_data');
+		addCreateTableSql('grade_data', "
+`grade_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+`grade_name` VARCHAR(255) NOT NULL DEFAULT '',
+`grade_description` TINYTEXT NOT NULL,
+`grade_parent_id` BIGINT(20) UNSIGNED NULL DEFAULT NULL,
+UNIQUE INDEX (`grade_name`),
+INDEX (`grade_parent_id`),
+PRIMARY KEY (`grade_id`)",
+			'Grade data');
+
+		// Data for if a grade level has been reached
+		addDropTableSql('grade_cash_data');
+		addCreateTableSql('grade_cash_data', "
+`cash_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+`grade_cash_name` VARCHAR(255) NOT NULL DEFAULT '',
+`grade_cash_type` ENUM('DISCOUNT','BONUS') NOT NULL DEFAULT 'DISCOUNT',
+`reached_points` FLOAT(20,5) UNSIGNED NULL DEFAULT NULL,
+`reached_mails` BIGINT(20) UNSIGNED NULL DEFAULT NULL,
+`time_valid` BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
+UNIQUE INDEX (`grade_cash_name`),
+PRIMARY KEY (`cash_id`)",
+			'Data for "cashed" grades');
+
+		// Connection grade<->cash data
+		addDropTableSql('grade_cash_connect');
+		addCreateTableSql('grade_cash_connect', "
+`connect_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+`grade_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
+`grade_cash_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
+UNIQUE INDEX `grade_cash` (`grade_id`, `grade_cash_id`),
+INDEX (`grade_cash_id`),
+PRIMARY KEY (`connect_id`)",
+			'Grade<->cash data connection');
+
+		// Connection grade<->user data
+		addDropTableSql('grade_user_connect');
+		addCreateTableSql('grade_user_connect', "
+`connect_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
+`userid` BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
+`grade_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
+`grade_expired` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
+UNIQUE INDEX (`userid`, `grade_id`),
+INDEX (`grade_id`),
+PRIMARY KEY (`connect_id`)",
+			'Grade<->user connection');
+
+		// Add example grade
+		addExtensionSql("INSERT INTO `{?_MYSQL_PREFIX?}_grade_data` (`grade_name`,`grade_description`) VALUES ('Metall','Einfache Metallstufe.')");
+		addExtensionSql("INSERT INTO `{?_MYSQL_PREFIX?}_grade_cash_data` (`grade_cash_name`,`grade_cash_type`,`reached_points`) VALUES('Metallbonus','BONUS',1000)");
+		addExtensionSql("INSERT INTO `{?_MYSQL_PREFIX?}_grade_cash_connect` (`grade_id`,`grade_cash_id`) VALUES (1,1)");
+
+		// Admin menu entries
+		addAdminMenuSql('grade', NULL, 'Accountstufen', 'Stufen Sie Ihre Mitglieder ein, die sie ab einer einstellbaren Anzahl an {OPEN_CONFIG}POINTS{CLOSE_CONFIG} oder best&auml;tigten Mails usw. erhalten und durch die Accountstufe Erm&auml;&szlig;igungen oder Sonderboni erhalten k&ouml;nnen.', 6);
+		addAdminMenuSql('grade', 'list_grade_data', 'Auflisten...', 'Listet alle Accountstufen auf, auch sind diese hier editierbar, neue hinzuf&uuml;gbar und l&ouml;schbar.', 1);
+		addAdminMenuSql('grade', 'list_cash_grade', 'Erm&auml;&szlig;igungen/Sonderboni', 'Listet alle Erm&auml;&szlig;igungen/Sonderboni auf, auch sind diese hier editierbar, neue hinzuf&uuml;gbar und l&ouml;schbar.', 2);
+		addAdminMenuSql('grade', 'list_current_grades', 'Mitgliedaccountsstufen', 'Liste alle durch die Mitglieder aktuell erreichten Einstungen auf. Diese sind nicht editierbar (wir wollen ja nicht schummeln und bestimmten Mitgliedern bessere Accountstufen geben, oder? ;-) ).', 3);
+		addAdminMenuSql('grade', 'config_grade', 'Einstellungen ...', 'Diverse Einstellungen zu den Accountstufen.', 4);
+
+		// Member menu
+		addMemberMenuSql('account', 'grade', 'Erreichte Stufe', 2);
+
+		// Guest menu
+		addGuestMenuSql('members', 'grade', 'Accountstufen', 4);
+
+// [EOF]
+?>
diff --git a/inc/functions.php b/inc/functions.php
index bc7aa6bad7..c2c7101ca9 100644
--- a/inc/functions.php
+++ b/inc/functions.php
@@ -766,7 +766,13 @@ function generateHash ($plainText, $salt = '', $hash = TRUE) {
 		$server = $_SERVER['PHP_SELF'] . getEncryptSeparator() . detectUserAgent() . getEncryptSeparator() . getenv('SERVER_SOFTWARE') . getEncryptSeparator() . detectRealIpAddress() . getEncryptSeparator() . detectRemoteAddr();
 
 		// Build key string
-		$keys   = getSiteKey() . getEncryptSeparator() . getDateKey() . getEncryptSeparator() . getSecretKey() . getEncryptSeparator() . getFileHash() . getEncryptSeparator() . getDateFromRepository() . getEncryptSeparator() . getMasterSalt();
+		$keys = getSiteKey() . getEncryptSeparator() . getDateKey() . getEncryptSeparator() . getFileHash() . getEncryptSeparator() . getDateFromRepository() . getEncryptSeparator() . getMasterSalt();
+
+		// Is the secret_key config entry set?
+		if (isConfigEntrySet('secret_key')) {
+			// Add it
+			$keys .= getEncryptSeparator() . getSecretKey();
+		} // END - if
 
 		// Additional data
 		$data = $plainText . getEncryptSeparator() . uniqid(mt_rand(), TRUE) . getEncryptSeparator() . time();
diff --git a/inc/language/de.php b/inc/language/de.php
index 54415a2f6d..ac71b66d48 100644
--- a/inc/language/de.php
+++ b/inc/language/de.php
@@ -583,7 +583,6 @@ addMessages(array(
 	'ADMIN_NO_ADMIN_ASSIGNED' => "Kein Admin-Login zugewiesen.",
 	'ADMIN_UNKNOWN_TASK_TYPE' => "Unbekannter Aufgabentyp <span class=\"data\">%s</span> f&uuml;r Aufgabe <span class=\"data\">%s</span> erkannt.",
 	'ADMIN_TASK_SYSTEM_WELCOME' => "Task-Management Ihres {?mt_word2?}",
-	'ADMIN_UNSELECT_ALL' => "Alles abw&auml;hlen",
 	'ADMIN_ASSIGN_TASKS' => "Zuweisen/Bearbeiten",
 	'ADMIN_UNASSIGN_TASKS' => "Zuweisung aufheben",
 	'ADMIN_REDIRECT_TASKS' => "Weiterleiten",
@@ -1012,6 +1011,7 @@ addMessages(array(
 	'ADMIN_BOOKING_PACKAGE_ID' => "Buchungspaket",
 	'ADMIN_BOOKING_PACKAGE_LINK' => "Zum Paket ...",
 	'APPLICATION_DIED_TITLE' => "Bug im Script erkannt.",
+	'ADMIN_UNSELECT_ALL' => "Alles abw&auml;hlen",
 
 	// Admin config - security-related settings
 	'ADMIN_CONFIG_SECURE_TITLE' => "Sicherheitseinstellungen:",
diff --git a/inc/libs/grade_functions.php b/inc/libs/grade_functions.php
index 42c781db2a..65ce5c6ed2 100644
--- a/inc/libs/grade_functions.php
+++ b/inc/libs/grade_functions.php
@@ -40,6 +40,43 @@ if (!defined('__SECURITY')) {
 	die();
 } // END - if
 
+// Generates a option "list" for all created grade ids
+function generateGradeDataIdOptions ($defaultId = NULL) {
+	// Do we have cache?
+	if (!isset($GLOBALS[__FUNCTION__][$defaultId])) {
+		// Look for all
+		$grades = getArrayFromTable('grade_data', array('grade_id', 'grade_name'), 'grade_id');
+
+		// Init entries arrays
+		$gradeKeys = array();
+		$gradeValues = array();
+
+		// Load all entries
+		foreach ($grades as $grade) {
+			// Add it to arrays
+			array_push($gradeKeys  , $grade['grade_id']);
+			array_push($gradeValues, $grade['grade_name']);
+		} // END - foreach
+
+		// Generate option "list"
+		$GLOBALS[__FUNCTION__][$defaultId] = generateOptions(
+			'/ARRAY/',
+			$gradeKeys,
+			$gradeValues,
+			$defaultId,
+			'',
+			'',
+			array(),
+			'',
+			TRUE,
+			FALSE
+		);
+	} // END - if
+
+	// Return cache
+	return $GLOBALS[__FUNCTION__][$defaultId];
+}
+
 // Generates a option "list" for all created "parent" grade ids
 function generateGradeDataParentIdOptions ($defaultId = NULL) {
 	// Do we have cache?
@@ -50,32 +87,22 @@ function generateGradeDataParentIdOptions ($defaultId = NULL) {
 		// Is default set?
 		if (!is_null($defaultId)) {
 			// Then exlude it
-			$whereStatement = sprintf('WHERE `grade_id`=%s', bigintval($defaultId));
+			$whereStatement = sprintf('WHERE `grade_id` != %s', bigintval($defaultId));
 		} // END - if
 
 		// Look for all
-		$result = sqlQuery('SELECT
-	`grade_id`,
-	`grade_name`
-FROM
-	`{?_MYSQL_PREFIX?}_grade_data`
-' . $whereStatement . '
-ORDER BY
-	`grade_id` ASC', __FUNCTION__, __LINE__);
+		$grades = getArrayFromTable('grade_data', array('grade_id', 'grade_name'), 'grade_id', 'ASC', $whereStatement);
 
 		// Init entries arrays
 		$gradeKeys = array();
 		$gradeValues = array();
 
 		// Are there entries?
-		if (!ifSqlHasZeroNums($result)) {
-			// Load all entries
-			while ($grade = sqlFetchArray($result)) {
-				// Add it to arrays
-				array_push($gradeKeys  , $grade['grade_id']);
-				array_push($gradeValues, $grade['grade_name']);
-			} // END - while
-		} // END - if
+		foreach ($grades as $grade) {
+			// Add it to arrays
+			array_push($gradeKeys  , $grade['grade_id']);
+			array_push($gradeValues, $grade['grade_name']);
+		} // END - foreach
 
 		// Generate option "list"
 		$GLOBALS[__FUNCTION__][$defaultId] = generateOptions(
@@ -84,15 +111,22 @@ ORDER BY
 			$gradeValues,
 			$defaultId
 		);
-
-		// Free result
-		sqlFreeResult($result);
 	} // END - if
 
 	// Return cache
 	return $GLOBALS[__FUNCTION__][$defaultId];
 }
 
+// Generates a selection box for grades
+function generateAdminGradeDataSelectionBox ($gradeId, $defaultId = NULL) {
+	// May only be called as admin
+	assert(isAdmin());
+	assert(isValidId($gradeId));
+
+	// Load template
+	return generateSelectionBoxFromArray(getArrayFromTable('grade_data', array('grade_id', 'grade_name'), 'grade_id'), 'grade_parent_id', $defaultId, '', '', '', $defaultId, '', TRUE, TRUE);
+}
+
 // ----------------------------------------------------------------------------
 //                             XML call-back functions
 // ----------------------------------------------------------------------------
diff --git a/inc/modules/member/what-transaction_fees.php b/inc/modules/member/what-transaction_fees.php
index aa410fcdc6..4df0054b81 100644
--- a/inc/modules/member/what-transaction_fees.php
+++ b/inc/modules/member/what-transaction_fees.php
@@ -154,21 +154,8 @@ $data = array_merge($data, sqlFetchArray($result));
 // Free result
 sqlFreeResult($result);
 
-// Get total collected fees
-$result = sqlQuery("SELECT
-	SUM(`transaction_fee_receiver` + `transaction_fee_sender`) AS `total_fee`
-FROM
-	`" . $GLOBALS['db_table']['translog'] . "`
-WHERE
-	`transaction_confirmed`='N' AND
-	`transaction_captcha_failed`='N'
-LIMIT 1", __FILE__, __LINE__);
-
-// Load total sum
-list($data['total_fee']) = sqlFetchRow($result);
-
-// Free result
-sqlFreeResult($result);
+// Total fees from config as it contains all transaction fees
+$data['total_fee'] = getConfig('transaction_pot');
 
 // Get total confirmed
 $result = sqlQuery("SELECT
diff --git a/inc/mysql-manager.php b/inc/mysql-manager.php
index da948fbee8..0583c16dfa 100644
--- a/inc/mysql-manager.php
+++ b/inc/mysql-manager.php
@@ -1387,8 +1387,15 @@ function getAdminMenuMode ($adminId) {
 }
 
 // Generates an option list from various parameters
-function generateOptions ($table, $key, $value, $default = '', $extra = '', $whereStatement = '', $disabled = array(), $callback = '') {
+function generateOptions ($table, $key, $value, $default = '', $extra = '', $whereStatement = '', $disabled = array(), $callback = '', $allowNone = FALSE) {
 	$ret = '';
+
+	// Allow none?
+	if ($allowNone === TRUE) {
+		// Add option for none
+		$ret .= '<option value="0">{--SELECT_NONE--}</option>';
+	} // END - if
+
 	if ($table == '/ARRAY/') {
 		// Selection from array
 		if ((is_array($key)) && (is_array($value)) && ((count($key)) == (count($value)) || (!empty($callback)))) {
@@ -2016,7 +2023,7 @@ function doListEntries ($sql, $tableTemplate, $noEntryMessageId, $rowTemplate, $
 
 				// Call the callback-function
 				//* NOISY-DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'callbackFunction=' . $callbackName . ',args=<pre>'.print_r($args, TRUE).'</pre>');
-				// @TODO If we can rewrite the EL sub-system to support more than one parameter, this call_user_func_array() can be avoided
+				// @TODO If the EL sub-system can support more than one parameter, this call_user_func_array() can be avoided
 				$row[$columnName] = call_user_func_array($callbackName, $args);
 			} // END - foreach
 
@@ -2505,5 +2512,43 @@ function addKeyValueSql ($key, $value) {
 	return $sql;
 }
 
+// "Getter" for an array from given table and columns
+function getArrayFromTable ($tableName, $columns, $orderBy, $ordered = 'ASC', $whereSql = '') {
+	// The table must exist
+	assert(ifSqlTableExists($tableName));
+
+	// Search for it
+	$result = sqlQueryEscaped('SELECT
+	`' . implode('`, `', $columns) . '`
+FROM
+	`{?_MYSQL_PREFIX?}_%s`
+' . $whereSql . '
+ORDER BY
+	`%s` %S',
+		array(
+			$tableName,
+			$orderBy,
+			$ordered
+		), __FUNCTION__, __LINE__
+	);
+
+	// Init array
+	$rows = array();
+
+	// Are there entries?
+	if (!ifSqlHasZeroNums($result)) {
+		// Load all entries
+		while ($row = sqlFetchArray($result)) {
+			array_push($rows, $row);
+		} // END - while
+	} // END - if
+
+	// Free result
+	sqlFreeResult($result);
+
+	// Return all found rows
+	return $rows;
+}
+
 // [EOF]
 ?>
diff --git a/inc/template-functions.php b/inc/template-functions.php
index 4805bb0e99..139759e5b0 100644
--- a/inc/template-functions.php
+++ b/inc/template-functions.php
@@ -1800,6 +1800,9 @@ function sendModeMails ($mod, $modes) {
 
 // Generates a 'selection box' from given array
 function generateSelectionBoxFromArray ($options, $name, $optionKey, $optionContent = '', $extraName = '', $templateName = '', $default = NULL, $nameElement = '', $allowNone = FALSE, $useDefaultAsArray = FALSE) {
+	// options must be an array
+	assert(is_array($options));
+
 	// Default is empty
 	$addKey = '';
 
diff --git a/templates/de/html/select/select_grade_parent_id_box.tpl b/templates/de/html/select/select_grade_parent_id_box.tpl
new file mode 100644
index 0000000000..1abcfa7a14
--- /dev/null
+++ b/templates/de/html/select/select_grade_parent_id_box.tpl
@@ -0,0 +1,3 @@
+<div>
+	$content[selection_box]
+</div>
diff --git a/templates/de/html/select/select_grade_parent_id_option.tpl b/templates/de/html/select/select_grade_parent_id_option.tpl
new file mode 100644
index 0000000000..6ad70c694e
--- /dev/null
+++ b/templates/de/html/select/select_grade_parent_id_option.tpl
@@ -0,0 +1,3 @@
+<option value="$content[grade_id]"$content[default]>
+	$content[grade_name]
+</option>
diff --git a/templates/xml/admin/admin_list_grade_data.xml b/templates/xml/admin/admin_list_grade_data.xml
index f14221eee3..2628bf7138 100644
--- a/templates/xml/admin/admin_list_grade_data.xml
+++ b/templates/xml/admin/admin_list_grade_data.xml
@@ -109,7 +109,8 @@ MA  02110-1301  USA
 				A single parameter, 'type' can be one of 'float', 'int',
 				'bool', 'string'. 'array' is not yet supported.
 				//-->
-				<callback-extra-parameter-list-entry type="int" column="grade_parent_id" value="2" />
+				<callback-extra-parameter-list-entry type="int" column="grade_parent_id" data="grade_id" />
+				<callback-extra-parameter-list-entry type="int" column="grade_parent_id" data="grade_parent_id" />
 			</callback-extra-parameter-list>
 		</column-callback-list-entry>
 	</column-callback-list>