diff --git a/homepage/participo/api.starter.add.php b/homepage/participo/api.starter.add.php
new file mode 100644
index 0000000..5af7aef
--- /dev/null
+++ b/homepage/participo/api.starter.add.php
@@ -0,0 +1,30 @@
+addToDb();
+
+header('Location: ' . urldecode($returnToUrl), true, 301);
+exit(-1); // shouldn't matter
diff --git a/homepage/participo/api.starter.remove.php b/homepage/participo/api.starter.remove.php
new file mode 100644
index 0000000..bc6130a
--- /dev/null
+++ b/homepage/participo/api.starter.remove.php
@@ -0,0 +1,28 @@
+removeFromDb();
+
+header('Location: ' . urldecode($returnToUrl), true, 301);
+exit(-1); // shouldn't matter
diff --git a/homepage/participo/apiKeyTest.php b/homepage/participo/apiKeyTest.php
new file mode 100644
index 0000000..fd6ba82
--- /dev/null
+++ b/homepage/participo/apiKeyTest.php
@@ -0,0 +1,35 @@
+format('Y-m-d'));
+$newKey->addToDb();
+$loadedKey = ApiKey::loadFromDb($apiKey);
+
+?>
+
+
+
+
+ - rightsRoundabout: isValidFor($rightArray) ? 'TRUE' : 'FALSE' );?>
+
+
+
\ No newline at end of file
diff --git a/homepage/participo/events.js b/homepage/participo/events.js
new file mode 100644
index 0000000..1e4e0b1
--- /dev/null
+++ b/homepage/participo/events.js
@@ -0,0 +1,44 @@
+function initSelects() {
+ var selectElements = document.querySelectorAll('select');
+ var selectInstances = M.FormSelect.init(selectElements, {});
+
+}
+
+function initSidenav() {
+ var sidenavElements = document.querySelectorAll('.sidenav');
+ var sidenavInstances = M.Sidenav.init(sidenavElements, {});
+};
+
+function initModals() {
+ var modalElements = document.querySelectorAll('.modal');
+ var modalInstances = M.Modal.init(modalElements, {
+ 'onOpenEnd': initSelects
+ });
+};
+
+function openEventModal(eventId) {
+ openModal(`#event-modal-${eventId}`);
+}
+
+function openModal(modalId) {
+ var modalElement = document.querySelector(modalId);
+ if (modalElement === null) {
+ return;
+ }
+ var modalInstance = M.Modal.getInstance(modalElement);
+ modalInstance.open();
+}
+
+// What to do when the document is loaded.
+document.addEventListener('DOMContentLoaded', function () {
+ // init materialize elements
+ initModals();
+ initSidenav();
+ initSelects();
+
+ // opening event modal if given
+ var eventId = parseInt(window.location.hash.substring(1));
+ if (!isNaN(eventId)) {
+ openEventModal(eventId);
+ }
+});
diff --git a/homepage/participo/lib/participoLib/dbConnector.php b/homepage/participo/lib/participoLib/dbConnector.php
index a9ba3c9..1c3bb2e 100644
--- a/homepage/participo/lib/participoLib/dbConnector.php
+++ b/homepage/participo/lib/participoLib/dbConnector.php
@@ -45,6 +45,7 @@ class dbConnector
/// als UTF8 in latin1(?) gespeichert.
/// @toDo: Die Standardwerte sollten vielleicht aus einer config
/// kommen, nicht hardcoded
+
try {
$pdoStatement = self::$db->prepare($aQueryString);
foreach ($aBindArray as $bindName => $bind) {
@@ -92,6 +93,12 @@ class dbConnector
return $ret;
}
+ // @todo docu
+ public static function getLastInsertId()
+ {
+ return self::$db->lastInsertId();
+ }
+
// get a Connection to the database
private static function connectToPdo($hostname, $dbName, $user, $password)
{
@@ -120,4 +127,19 @@ class dbConnector
self::$db = null;
}
}
+
+ public static function debugEchoQuery($query, $params)
+ {
+ foreach ($params as $key => $value) {
+ switch($value['data_type']) {
+ case PDO::PARAM_STR:{
+ $query = str_replace($key, '\'' . $value['value'] . '\'', $query);
+ }
+ default:{
+ $query = str_replace($key, $value['value'], $query);
+ }
+ }
+ };
+ echo('query: ' . $query . PHP_EOL);
+ }
}
diff --git a/homepage/participo/lib/participoLib/event.php b/homepage/participo/lib/participoLib/event.php
new file mode 100644
index 0000000..1c43e2b
--- /dev/null
+++ b/homepage/participo/lib/participoLib/event.php
@@ -0,0 +1,209 @@
+id = (int) $id;
+ $this->date = DateTime::createFromFormat('Y-m-d', $date);
+ $this->shiaiId = (($shiaiId != null) ? ((int)$shiaiId) : (null));
+ $this->deadline = DateTime::createFromFormat('Y-m-d', $deadline);
+ $this->remarks = $remarks;
+
+ $this->shiai = $shiai;
+ }
+
+ public static function loadFromDb(int $id)
+ {
+ $query = 'SELECT * FROM `cwsvjudo`.`wkParticipo_Events` WHERE `id` = :id;';
+ $params = [':id' => ['value' => $id, 'data_type' => PDO::PARAM_INT]];
+ $response = dbConnector::query($query, $params);
+
+ // ids are considered unique. so every other count then 1 is treated as error to prevent unprivileged access
+ if (count($response) != 1) {
+ return null;
+ }
+ return Event::fromDbArray($response[0]);
+ }
+
+ /** Representation of an event as (materializeCss) card
+ *
+ * @return string string with the html code of the event
+ */
+ public function asHtmlCard()
+ {
+ return
+ '' .
+ '
' .
+ '
' . $this->shiai->getHtmlName() . '' .
+ '
' .
+ '- Datum
' .
+ '- ' . $this->date->format('Y-m-d') . '
' .
+ '- Meldefrist
' .
+ '- ' . $this->deadline->format('Y-m-d') . '
' .
+ '- Altersklassen
' .
+ '- ' . $this->shiai->getAgeClasses() . '
' .
+ '
' .
+ '
';
+ }
+
+ public function htmlTableRow()
+ {
+ return
+ '' .
+ '| ' . $this->date->format('Y-m-d') . ' | ' .
+ '' . $this->shiai->getHtmlName() . ' | ' .
+ '' . $this->shiai->getAgeClasses() . ' | ' .
+ 'zoom_in | ' .
+ '
';
+ }
+
+ public function htmlModal()
+ {
+ $modal =
+ ''
+ . '
'
+ . $this->shiai->getHtml()
+ . $this->getHtmlStarterList();
+ $kids = participo::getKids();
+ $modal .= '
';
+ foreach ($kids as $k) {
+ $modal .= $this->getHtmlAddStarterForm($k);
+ }
+ $modal .= '
';
+ $modal .=
+ '
' . // end modal-content
+ '' . // end modal-footer
+ '
';
+ echo($modal);
+ }
+
+ public function getHtmlStarterList()
+ {
+ $listOfStarter = $this->getStarter();
+
+ if (!isset($listOfStarter) || count($listOfStarter) == 0) {
+ return '';
+ }
+ $starterList .= 'Bereits eingetragen: ';
+ foreach ($listOfStarter as $s) {
+ $u = $s->getUser();
+ $starterList .= '
' . $u->getName() . ', ' . $u->getFirstname() . $this->getHtmlRemoveStarterForm($s->getEventId(), $s->getUserId()) . '
';
+ }
+ $starterList .= '
';
+ return $starterList;
+ }
+
+ /** Returns the currents users starter to this event
+ *
+ * @todo docu
+ */
+ private function getStarter()
+ {
+ $userId = $_SESSION['user']['userId'] ?? null;
+
+ $query = 'SELECT `wkParticipo_Starter`.`id` as `starterId` FROM `wkParticipo_Starter` '
+ . 'LEFT JOIN `vormundschaft` ON `vormundschaft`.`kidId` = `wkParticipo_Starter`.`userId` '
+ . ' WHERE `wkParticipo_Starter`.`eventId` = :eventId AND `vormundschaft`.`userId` = :userId;';
+ $params = [
+ ':eventId' => ['value' => $this->id, 'data_type' => PDO::PARAM_INT],
+ ':userId' => ['value' => $userId, 'data_type' => PDO::PARAM_INT]
+ ];
+ $response = dbConnector::query($query, $params);
+
+ $starter = [];
+ foreach ($response as $r) {
+ $starter[] = Starter::loadFromDb($r['starterId']);
+ }
+ return $starter;
+ }
+
+ public static function fromArray($member)
+ {
+ $shiai = json_decode($member['bemerkungen'], true);
+
+ return new event(
+ $member['id'] ?? null,
+ $member['date'] ?? null,
+ $member['wkId'] ?? null,
+ $member['meldefrist'] ?? null,
+ $member['bemerkungen'] ?? null,
+ shiai::fromArray(($shiai != null) ? $shiai : $member)
+ );
+ }
+
+ /// Einen Starter per userId mit typeId zu einem Event per eventId hinzufügen
+ /// Es erfolgt keine Überprüfung der Meldeberechtigung!
+ public static function addStarter($dbConnection, $starter)
+ {
+ $retMessage = [];
+
+ $query = 'INSERT INTO `wkParticipo_Starter` (eventId, userId, type) values (:eventId, :userId, :typeId);';
+ $params = [
+ ':eventId' => ['value' => $starter->getEventId(), 'data_type' => PDO::PARAM_INT],
+ ':userId' => ['value' => $starter->getUserId(), 'data_type' => PDO::PARAM_INT],
+ ':typeId' => ['value' => $starter->getTypeId(), 'data_type' => PDO::PARAM_INT]
+ ];
+
+ return dbConnector::query($query, $params);
+ }
+
+ // @todo docu
+ public static function getHtmlRemoveStarterForm($eventId, $userId, $class = null)
+ {
+ $form =
+ '';
+
+ return $form;
+ }
+
+ public function getHtmlAddStarterForm($user)
+ {
+ $key = isset($_SESSION['apiKey']) ? $_SESSION['apiKey'] : null;
+ $form =
+ '';
+
+ return $form;
+ }
+} // end class event
diff --git a/homepage/participo/lib/participoLib/participo.php b/homepage/participo/lib/participoLib/participo.php
index b617318..9175a4c 100644
--- a/homepage/participo/lib/participoLib/participo.php
+++ b/homepage/participo/lib/participoLib/participo.php
@@ -1,28 +1,40 @@
null, 'success' => null, 'notice' => null];
private static $userId = null;
- /**
- * Returns the current login status
+ /** Returns the current login status
*
* The login status is stored in the session cookie. If it is not even set it means the login is invalid.
*
- * @return The login status or false if none is set so far
+ * @return bool true if the login status is true, false otherwise
*/
public static function isLoginValid()
{
- return ($_SESSION['login'] ?? false);
+ return (isset($_SESSION) && array_key_exists('login', $_SESSION) && $_SESSION['login'] == true);
}
- /**
- * A little Box with the login status as html entity
+ /** Remove all login data from the session data
+ *
+ * @return void
+ */
+ public static function logout()
+ {
+ foreach (['login', 'user'] as $key) {
+ unset($_SESSION[$key]);
+ }
+ }
+
+ /** A little Box with the login status as html entity
*
* @return string htmlEntity showing the login status
*/
@@ -36,48 +48,54 @@ class participo
'';
}
- /**
- * Checks, if there already is a valid login, if not redirect to the login form
- * @todo rename to authenticate
+ /** Checking if an action is allowed. A present apiKey overrides (and deletes) a present login.
+ *
+ * 1. If apiKey is present:
+ * - chancel current login
+ * - If apiKey is valid for requested action:
+ * - set some session data
+ * - return
+ * 2. If there is a valid Login session:
+ * - return
+ * 3. redirect to Login Page
+ *
+ * @todo rename to authenticate (authorize?)
+ *
+ * @param $action the action we want to get authorized for (default=['login'])
*
* @retval void
*/
- public static function authentificate()
+ public static function authentificate($action = ['login'])
{
+ // Ensure a session is started
session_start();
- // check if an api key was received
+ // check if an apiKey was received
if (array_key_exists('apiKey', $_GET)) {
+ self::logout();
$key = ApiKey::loadFromDb($_GET['apiKey']);
- if ($key) {
- if ($key->isValidFor('login')) {
- // query *all* users with the entered name
- // @todo check for e.g., len(user)=1
- // @todo getUser?
- $user = dbConnector::query(
- 'SELECT `id`, `loginName`, `config` FROM `wkParticipo_Users` WHERE `id` = :id',
- ['id' => ['value' => $key->getUserId(), 'data_type' => PDO::PARAM_INT]]
- );
- $user = $user[0];
-
- // case valid login: Set the session data
- $_SESSION = [
- 'login' => true,
- 'user' => [
- 'username' => $user['loginName'],
- 'userId' => $user['id'],
- 'userConfig' => json_decode($user['config'], true)
- ]
- ];
- };
- }
+ if (isset($key) && $key->isValidFor($action)) {
+ $user = User::loadFromDb($key->getUserId());
+ // case valid login: Set the session data
+ $_SESSION = [
+ 'login' => true, //false,
+ 'apiKey' => $key->getKey(),
+ 'user' => [
+ 'username' => $user->getLoginName(),
+ 'userId' => $user->getId(),
+ 'userConfig' => $user->getConfig(),
+ ]
+ ];
+ // we're not logged in, but authorized for the stuff we want to do. So don't redirect
+ return;
+ };
}
+ // if not returned yet: no login, no valid apiKey -> redirect to login page
if (!self::isLoginValid()) {
header('Location: login?returnToUrl=' . urlencode($_SERVER['REQUEST_URI'] . ($_POST['fragment'] ?? '')), true, 301);
- exit(); // should'nt matter
+ exit(); // shouldn't matter
}
- participo::$userId = $_SESSION['user']['userId'];
}
public static function getMessages()
@@ -90,8 +108,7 @@ class participo
self::$message[$type] = (self::$message[$type] ?? '') . $message;
}
- /**
- * check password for user
+ /** check password for user
*
* @param string $loginName user who wants to get in
* @param string $password password for the user
@@ -102,23 +119,17 @@ class participo
public static function checkCredentials($loginName, $password)
{
sleep(1); // just to discourage brute force attacks
+
// Check for dbConnection
if (!dbConnector::getDbConnection()) {
self::addMessage('error', 'No DbConnection available
');
return false;
}
- // query *all* users with the entered name
- // @todo check for e.g., len(user)=1
- // @todo getUser?
- $user = dbConnector::query(
- 'SELECT `id`, `loginName`, `pwHash`, `config` FROM `wkParticipo_Users` WHERE `loginName` = :loginName',
- ['loginName' => ['value' => $loginName, 'data_type' => PDO::PARAM_STR]]
- );
- $user = $user[0];
+ $user = User::loadFromDbByLoginName($loginName);
// If there is no such user OR the password isn't valid the login fails
- if (empty($user) || !password_verify($password, $user['pwHash'])) {
+ if ($user == null || !$user->verifyPassword($password)) {
sleep(5); // discourage brute force attacks
self::addMessage('error', 'Falsches Passwort oder LoginName
');
return false;
@@ -129,9 +140,9 @@ class participo
$_SESSION = [
'login' => true,
'user' => [
- 'username' => $user['loginName'],
- 'userId' => $user['id'],
- 'userConfig' => json_decode($user['config'], true)
+ 'username' => $user->getLoginName(),
+ 'userId' => $user->getId(),
+ 'userConfig' => json_decode($user->getConfig(), true)
]
];
@@ -142,8 +153,7 @@ class participo
return true;
}
- /**
- * Checks, if a user is an admin
+ /** Checks, if a user is an admin
*
* @param [type] $userId id of the user to check
* @retval true user with id $userId has attribute "isAdmin"
@@ -154,8 +164,48 @@ class participo
return self::hasUserAttribute($userId, 'isAdmin');
}
- /**
- * Checks, if a user as a certain attribute
+ public static function getKids($userId = null)
+ {
+ $userId = $userId ?? $_SESSION['user']['userId'] ?? null;
+
+ $query =
+ 'SELECT * FROM `wkParticipo_Users` '
+ . 'INNER JOIN `vormundschaft` ON `wkParticipo_Users`.`id` = `vormundschaft`.`kidId` '
+ . 'WHERE `vormundschaft`.`userId` = :userId;';
+ $params = [':userId' => ['value' => $userId, 'data_type' => PDO::PARAM_INT]];
+
+ $response = dbConnector::query($query, $params);
+
+ $kids = [];
+ foreach ($response as $r) {
+ $kids[] = User::fromDbArray($r, ['id' => 'kidId']);
+ }
+ return $kids;
+ }
+
+ /** Check if one user is ward of another
+ *
+ * @param integer $kidId ID of the ward
+ * @param integer|null $userId ID of the guardian, if null it is tried to read it from the session data
+ * @return boolean true if kid is ward of user, false otherwise
+ */
+ public static function isWardOf(int $kidId, int $userId = null)
+ {
+ // Try to get the Guard from the session data.
+ $userId = $userId ?? $_SESSION['user']['userId'] ?? null;
+
+ $query = 'SELECT `kidId` FROM `vormundschaft` WHERE `userId` = :userId AND `kidId` = :kidId;';
+ $params = [
+ ':userId' => ['value' => $userId, 'data_type' => PDO::PARAM_INT],
+ ':kidId' => ['value' => $kidId, 'data_type' => PDO::PARAM_INT]
+ ];
+
+ $response = dbConnector::query($query, $params);
+
+ return (count($response) >= 1);
+ }
+
+ /** Checks, if a user as a certain attribute
*
* @param [type] $userId id of the user to check
* @param [type] $attributeName string name of the attribute to check
@@ -207,22 +257,20 @@ FROM `wkParticipo_Starter`
WHERE `wkParticipo_Events`.`date` >= $sinceDate AND `vormundschaft`.`userId` = $userId
ORDER BY `wkParticipo_Events`.`date` DESC;
SQL;
- $commingStarts = dbConnector::query($query);
+ $comingStarts = dbConnector::query($query);
- return $commingStarts;
+ return $comingStarts;
}
}
-/**
- * Action element of an MaterializeCss (App-)card
+/** Action element of an MaterializeCss (App-)card
*/
class AppCardAction
{
private $caption = null; //< Caption for the action
private $link = '.'; //< link for the action
- /**
- * Constructor for the AppAction
+ /** Constructor for the AppAction
*
* @param string $caption caption for the action
* @param string $link link to the action
@@ -234,8 +282,7 @@ class AppCardAction
$this->caption = $caption;
}
- /**
- * Create htmlCode for the action
+ /** Create htmlCode for the action
*
* @return string with htmlCode of the action
*/
@@ -244,8 +291,7 @@ class AppCardAction
return '' . $this->caption . '';
}
- /**
- * Create AppCardAction from assoziative array
+ /** Create AppCardAction from assoziative array
*
* @param array $member array with the member values
* @return AppCardAction
@@ -258,8 +304,7 @@ class AppCardAction
}
}
-/**
- * MaterializeCss card for an App
+/** MaterializeCss card for an App
*/
class AppCard
{
@@ -331,8 +376,7 @@ class AppCard
}
}
-/**
- * Generate a html table of the last logins of the users
+/** Generate a html table of the last logins of the users
*
* @param string $jsonFileName path to the json file with the logged logins
* @return string Html table of users last logins
@@ -387,11 +431,10 @@ function htmlRetMessage($anRetMessage)
return $retHtmlString;
}
-/**
- * load a MarkdownFile with yaml header
+/** load a MarkdownFile with yaml header
*
* @param string $fileName filename of the markdown file
- * @return array assocative array('yaml'=>array(..), 'mdText'=>string) containing the yamlHeader as associative array and the markdown text as string
+ * @return array associative array('yaml'=>array(..), 'mdText'=>string) containing the yamlHeader as associative array and the markdown text as string
*/
function loadMarkdownFile($fileName)
{
@@ -399,7 +442,7 @@ function loadMarkdownFile($fileName)
$fileText = file_get_contents($fileName);
// split at '---' to get ((),yamls,array)
$fileParts = preg_split('/[\n]*[-]{3}[\n]/', $fileText, 3);
- // not all mdfiles have a yamlHeader, so the mdText can be at different indices
+ // not all mdFiles have a yamlHeader, so the mdText can be at different indices
$yaml = [];
$mdText = '';
switch(count($fileParts)) {
@@ -433,8 +476,7 @@ function loadMarkdownFile($fileName)
];
}
-/**
- * Log the Login of an user into a logFile
+/** Log the Login of an user into a logFile
*
* @param string $userName name of the user
* @param string $fileName filename to log to
@@ -460,64 +502,18 @@ function logLoginsToJsonFile($userName, $fileName = 'lastLogins.json')
}
}
-/**
- * User for the Participo system
- */
-class User
+/// @brief Gibt die URL der gerade aufgerufenen Seite zurück
+function getCurPagesUrl()
{
- private $id;
- private $loginName;
- private $name;
- private $firstName;
- private $dateOfBirth;
- private $eMail;
-
- public function __construct($id, $loginName, $name, $firstName, $dateOfBirth, $eMail)
- {
- $this->id = (int) id;
- $this->loginName = $loginName;
- $this->name = $name;
- $this->firstName = $firstName;
- $this->dateOfBirth = $dateOfBirth != null ? DateTime::createFromFormat('Y-m-d', $dateOfBirth) : null;
- $this->eMail = $eMail;
+ $pageURL = 'http';
+ if ($_SERVER['HTTPS'] == 'on') {
+ $pageURL .= 's';
}
-
- /**
- * Create a User from an assoziative array like it is returned from db requests
- *
- * @param array $member associative array with the UserData from the dbRequest
- * @return User initialized user
- */
- public static function fromDbArray($member)
- {
- return new User(
- $member['id'] ?? null,
- $member['loginName'] ?? null,
- $member['name'] ?? null,
- $member['vorname'] ?? null,
- $member['gebDatum'] ?? null,
- array_key_exist('eMail', $member) ? explode(',', $member['eMail']) : null
- );
- }
-
- /**
- * Export the User data into an associative array
- */
- public function toAssoc()
- {
- return [
- 'id' => $this->id,
- 'loginName' => $this->loginName,
- 'name' => $this->name,
- 'vorname' => $this->firstName,
- 'gebDatum' => $this->dateOfBirth,
- 'eMail' => $this->eMail];
- }
-
- public function loadFromDb($dbConn, $id)
- {
- $this->set(
- loadUserDataFromDb($dbConn, $id)
- );
+ $pageURL .= '://';
+ if ($_SERVER['SERVER_PORT'] != '80') {
+ $pageURL .= $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT'] . $_SERVER['REQUEST_URI'];
+ } else {
+ $pageURL .= $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
}
+ return $pageURL;
}
diff --git a/homepage/participo/lib/participoLib/planer.php b/homepage/participo/lib/participoLib/planer.php
index e3eaad8..4bb8cda 100644
--- a/homepage/participo/lib/participoLib/planer.php
+++ b/homepage/participo/lib/participoLib/planer.php
@@ -1,341 +1,63 @@
id = (int) $id;
- $this->date = DateTime::createFromFormat('Y-m-d', $date);
- $this->name = $name;
- $this->ageclasses = $ageclasses;
- $this->place = $place;
- $this->announcementUrl = $announcementUrl;
- $this->routeUrl = $routeUrl;
- $this->galleryUrl = $galleryUrl;
- $this->promoImgUrl = $promoImgUrl;
- }
-
- public function getId()
- {
- return $this->id;
- }
-
- public function getName()
- {
- return ($this->name != null ? $this->name : 'Wettkampf ohne Namen');
- }
-
- public function getHtmlDate()
- {
- return ($this->date != null ? $this->date->format('Y-m-d') : 'fehlendes Datum');
- }
-
- public function getAgeClasses()
- {
- return ($this->ageclasses != null ? $this->ageclasses : '-');
- }
-
- public function getPlace()
- {
- return ($this->place != null ? $this->place : '-');
- }
-
- public static function fromArray($member)
- {
- return new shiai(
- $member['lfdeNr'] ?? null,
- $member['Datum'] ?? null,
- $member['Veranstaltung'] ?? '',
- $member['Altersklassen'] ?? null,
- $member['Ort'] ?? '',
- $member['Ausschreibung'] ?? null,
- $member['Routenplaner'] ?? null,
- $member['galleryLink'] ?? null,
- $member['promoPic'] ?? null
- );
- }
-
- /**
- * shiai event as html code for displaying
- *
- * @return html formated string
- */
- public function getHtml()
- {
- $retHtml = '';
- $retHtml =
- '' .
- '
' . $this->getName() . '
' .
- '
' .
- '- Datum:
- ' . $this->getHtmlDate() . '
' .
- '- Altersklassen
- ' . $this->getAgeClasses() . '
' .
- '- Ort
- ' . $this->getPlace() . '
' .
- '
' .
- '
';
- return $retHtml;
- }
-} // end class shiai
-
-/**
- * Framework for a event
- */
-class Event
-{
- private $id = null; //< unique id of the event in the db
- private $date = null; //< date for the event (@todo ranges?)
- private $shiaiId = null; //< unique id of the shiai in the db (if appropriate)
- private $deadline = null; //< until when one can register for the event
- private $remarks = null; //< remarks to the event (special rules) or a json object for missing data (e.g. non-shiai events)
-
- private $shiai = null; //< a place to load the linked shiai to (if loaded)
-
- /**
- * constructor
- *
- * @param int $id id in the database
- * @param string $date date of the event as string in the format "YYYY-MM-DD"
- * @param int $shiaiId id of the linked shiai or null if not appropriate
- * @param string $deadline deadline for sign ins in the format "YYYY-MM-DD"
- * @param string $remarks (json formatted) string with meta information
- * @param Shiai $shiai if the shiai is loaded anyway it can be placed here.
- */
- public function __construct($id, $date, $shiaiId, $deadline, $remarks, $shiai)
- {
- //! @todo InputValidation
- $this->id = (int) $id;
- $this->date = DateTime::createFromFormat('Y-m-d', $date);
- $this->shiaiId = (($shiaiId != null) ? ((int)$shiaiId) : (null));
- $this->deadline = DateTime::createFromFormat('Y-m-d', $deadline);
- $this->remarks = $remarks;
-
- $this->shiai = $shiai;
- }
-
- /**
- * Representation of an event as (materializeCss) card
- *
- * @return string string with the html code of the event
- */
- public function asHtmlCard()
- {
- return
- '' .
- '
' .
- '
' . $this->shiai->getName() . '' .
- '
' .
- '- Datum
' .
- '- ' . $this->date->format('Y-m-d') . '
' .
- '- Meldefrist
' .
- '- ' . $this->deadline->format('Y-m-d') . '
' .
- '- Altersklassen
' .
- '- ' . $this->shiai->getAgeClasses() . '
' .
- '
' .
- '
';
- }
-
- public function htmlTableRow()
- {
- return
- '' .
- '| ' . $this->date->format('Y-m-d') . ' | ' .
- '' . $this->shiai->getName() . ' | ' .
- 'zoom_in
- | ' .
- '
';
- }
-
- public function htmlModal()
- {
- return
- '' .
- '
' .
- $this->shiai->getHtml() .
- '
' . // end modal content
- '' .
- '
';
- }
-
- public static function fromArray($member)
- {
- $shiai = json_decode($member['bemerkungen'], true);
-
- return new event(
- $member['id'] ?? null,
- $member['date'] ?? null,
- $member['wkId'] ?? null,
- $member['meldefrist'] ?? null,
- $member['bemerkungen'] ?? null,
- shiai::fromArray(($shiai != null) ? $shiai : $member)
- );
- }
-
- /// Einen Starter per userId mit typeId zu einem Event per eventId hinzufügen
- /// Es erfolgt keine Überprüfung der Meldeberechtigung!
- public static function addStarter($dbConnection, $starter)
- {
- $retMessage = [];
-
- $query = 'INSERT INTO `wkParticipo_Starter` (eventId, userId, type) values (:eventId, :userId, :typeId);';
- $params = [
- ':eventId' => ['value' => $starter->getEventId(), 'data_type' => PDO::PARAM_INT],
- ':userId' => ['value' => $starter->getUserId(), 'data_type' => PDO::PARAM_INT],
- ':typeId' => ['value' => $starter->getTypeId(), 'data_type' => PDO::PARAM_INT]
- ];
-
- return dbConnector::query($query, $params);
- }
-} // end class event
-
-abstract class StartingType
-{
- const __default = null;
-
- const Fighter = 1;
- const Audience = 2;
- const NoParticipation = 3;
-
- /**
- * convert a variable into a StartingType
- *
- * @param [int] $type starting type candidate
- * @return int representation of the StartingType if successful converted, otherwise null
- */
- public static function toStartingType($type)
- {
- return filter_var($type, FILTER_VALIDATE_INT, ['options' => ['default' => null, 'min_range' => 1, 'max_range' => 3]]);
- }
-
- /**
- * string representations of the starting type
- *
- * @var array array of StartingType=> its string representation
- */
- public static $AsString = [1 => 'Kämpfer', 2 => 'Zuschauer', 3 => 'keine Teilnahme'];
-}
-
-class Starter
-{
- private $id = null; //< id of the event in the database
- private $eventId = null; //< dbId of the event one is starting
- private $typeId = null; //< type(id) of the starter
- private $userId = null; //< id of the starting user
- private $rideId = null; //< id of the ride where the starter can car pool
- private $mass = null; //< mass in kg on the scale
- private $result = null; //< result of the start (array of places if multi start)
-
- // Getter for the member
- public function getId()
- {
- return $this->id;
- }
-
- public function getEventId()
- {
- return $this->eventId;
- }
-
- public function getTypeId()
- {
- return $this->typeId;
- }
-
- public function getUserId()
- {
- return $this->userId;
- }
-
- public function getRideId()
- {
- return $this->rideId;
- }
-
- public function getMass()
- {
- return $this->mass;
- }
-
- public function getResult()
- {
- return $this->result;
- }
-
- /**
- * Construtor
- *
- * @todo Document
- * @todo Rethink validation: filter_var is supposed to return the converted value in case of success. But the reference didn't say anything about not success...
- */
- public function __construct($id, $eventId, $typeId, $userId, $rideId, $mass, $result)
- {
- $this->id = filter_var($id, FILTER_VALIDATE_INT, ['options' => ['default' => null, 'min_range' => 1]]);
- $this->eventId = filter_var($id, FILTER_VALIDATE_INT, ['options' => ['default' => null, 'min_range' => 1]]);
- $this->typeId = StartingType::toStartingType($type);
- $this->userId = filter_var($id, FILTER_VALIDATE_INT, ['options' => ['default' => null, 'min_range' => 1]]);
- $this->rideId = filter_var($id, FILTER_VALIDATE_INT, ['options' => ['default' => null, 'min_range' => 1]]);
- $this->mass = filter_var($mass, FILTER_VALIDATE_FLOAT, ['options' => ['default' => null, 'min_range' => 0.0]]);
-
- if (is_iterable($result)) {
- $this->result = [];
- foreach ($result as $r) {
- $r = filter_var($r, FILTER_VAR_INT, ['options' => ['default' => null, 'min_range' => 0]]);
- if ($r) {
- array_push($this->result, $r);
- }
- }
- } else {
- $this->$result = filter_var($r, FILTER_VAR_INT, ['options' => ['default' => null, 'min_range' => 0]]);
- }
- }
-
- // create starter from assoc array
- public static function create($parameter)
- {
- $id = $parameter['id'] ?? null; //< id of the event in the database
- $eventId = $parameter['eventId'] ?? null; //< dbId of the event one is starting
- $typeId = $parameter['typeId'] ?? null; //< type(id) of the starter
- $userId = $parameter['userId'] ?? null; //< id of the starting user
- $rideId = $parameter['rideId'] ?? null; //< id of the ride where the starter can car pool
- $mass = $parameter['mass'] ?? null; //< mass in kg on the scale
- $result = $parameter['result'] ?? null; //< result of the start (array of places if multi start)
-
- return new Starter($id, $eventId, $typeId, $userId, $rideId, $mass, $result);
- }
-}
+require_once 'participoLib/shiai.php';
+require_once 'participoLib/event.php';
+require_once 'participoLib/starter.php';
class eventPlaner
{
- private static $db = null;
+ // db table column names
+ private static $dbTable = [
+ 'events' => 'wkParticipo_Events',
+ 'starts' => 'wkParticipo_Starter',
+ 'user' => 'wkParticipo_Users',
+ 'shiaiCal' => 'wettkampfkalender',
+ 'wardship' => 'vormundschaft'
+ ];
- // set the dbConnection (just setting, no establishing)
- public static function setDbConnection($dbConnection)
+ private static function getComingStarts($sinceDate = null, $userId = null)
{
- if ($dbConnection instanceof PDO) {
- self::$db = $dbConnection;
- } else {
- self::$db = null;
- }
- return;
+ $userId = $userId ?? $_SESSION['user']['userId'];
+ $sinceDate = $sinceDate ?? new DateTime();
+
+ $params = [
+ ':userId' => ['value' => $userId, 'data_type' => PDO::PARAM_INT],
+ ':sinceDate' => ['value' => $sinceDate->format('Y-m-d'), 'data_type' => PDO::PARAM_STR]
+ ];
+
+ // shorter variable names for better readability
+ $starts = self::$dbTable['starts'];
+ $user = self::$dbTable['user'];
+ $events = self::$dbTable['events'];
+ $shiaiCal = self::$dbTable['shiaiCal'];
+ $wardship = self::$dbTable['wardship'];
+
+ $query =
+ 'SELECT '
+ . '`' . $events . '`.`id` as eventId, '
+ . '`' . $events . '`.`date` as eventDate, '
+ . '`' . $events . '`.`meldefrist` as deadline, '
+ . '`' . $starts . '`.`id` as starterId, '
+ . '`' . $user . '`.`id` as userId, '
+ . '`' . $user . '`.`name` as userName, '
+ . '`' . $user . '`.`vorname` as userFirstname, '
+ . '`' . $shiaiCal . '`.`veranstaltung` as eventName '
+ . 'FROM `' . $starts . '` '
+ . 'LEFT JOIN `' . $user . '` ON `' . $starts . '`.`userId` = `' . $user . '`.`id` '
+ . 'LEFT JOIN `' . $events . '` ON `' . $starts . '`.`eventId` = `' . $events . '`.`id` '
+ . 'LEFT JOIN `' . $shiaiCal . '` ON `' . $events . '`.`wkId` = `' . $shiaiCal . '`.`lfdeNr` '
+ . 'LEFT JOIN `' . $wardship . '` ON `' . $user . '`.`id` = `' . $wardship . '`.`kidId` '
+ . 'WHERE `' . $events . '`.`date` >= :sinceDate AND ( `' . $wardship . '`.`userId` = :userId OR `' . $starts . '`.`userId` = :userId ) '
+ . 'ORDER BY `' . $events . '`.`date` DESC;';
+
+ $comingStarts = dbConnector::query($query, $params);
+
+ return $comingStarts;
}
- public static function getCommingWkEvents($someOptions = [])
+ public static function getComingWkEvents($someOptions = [])
{
// wir befinden uns in der Übergangsphase:
// - als Standard wird das derzeitige Verhalten definiert (ISO-8859-1
@@ -365,7 +87,7 @@ class eventPlaner
'ON wettkampfkalender.lfdeNr = wkParticipo_Events.wkId ' .
'WHERE wkParticipo_Events.date >= CURDATE() ' .
'ORDER BY wkParticipo_Events.date;';
- $ret = dbQuery(self::$db, $query);
+ $ret = dbConnector::query($query);
$events = [];
foreach ($ret as $event) {
array_push($events, event::fromArray($event));
@@ -385,4 +107,37 @@ class eventPlaner
}
return $ret;
}
+
+ // inserting html code
+
+ /** Generate the htmlCode for the list of upcoming starts of
+ *
+ * @return void
+ */
+ public static function htmlComingStarts()
+ {
+ $comingStarts = self::getComingStarts();
+ $htmlTable = null;
+ if ($comingStarts) {
+ $htmlTable = ''
+ . '| Datum | Veranstaltung | Starter | |
'
+ . '';
+ foreach ($comingStarts as $s) {
+ $eventDeadline = DateTime::createFromFormat('Y-m-d', $s['deadline']);
+ $today = new DateTime();
+ $htmlTable .= ''
+ . '| ' . $s['eventDate'] . ' | '
+ . '' . $s['eventName'] . ' | '
+ . '' . $s['userName'] . ', ' . $s['userFirstname'] . ' | '
+ . '' . ($eventDeadline <= $today ? Event::getHtmlRemoveStarterForm($s['eventId'], $s['userId']) : '') . ' | '
+ . '
';
+ }
+ $htmlTable .= '
';
+ echo('Aktuelle Einschreibungen
');
+ echo($htmlTable);
+ } else {
+ echo('Keine Meldungen zu bevorstehenden Events
');
+ }
+ return;
+ }
}
diff --git a/homepage/participo/lib/participoLib/shiai.php b/homepage/participo/lib/participoLib/shiai.php
new file mode 100644
index 0000000..bd3bd8d
--- /dev/null
+++ b/homepage/participo/lib/participoLib/shiai.php
@@ -0,0 +1,94 @@
+id = (int) $id;
+ $this->date = DateTime::createFromFormat('Y-m-d', $date);
+ $this->name = $name;
+ $this->ageclasses = $ageclasses;
+ $this->place = $place;
+ $this->announcementUrl = $announcementUrl;
+ $this->routeUrl = $routeUrl;
+ $this->galleryUrl = $galleryUrl;
+ $this->promoImgUrl = $promoImgUrl;
+ }
+
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ public function getHtmlName()
+ {
+ $name = ($this->name != null ? $this->name : 'Wettkampf ohne Namen');
+ foreach (['meisterschaft', 'turnier', 'randori'] as $fragment) {
+ str_replace($fragment, '', $name);
+ }
+ return $name;
+ }
+
+ public function getHtmlDate()
+ {
+ return ($this->date != null ? $this->date->format('Y-m-d') : 'fehlendes Datum');
+ }
+
+ public function getAgeClasses()
+ {
+ return ($this->ageclasses != null ? $this->ageclasses : '-');
+ }
+
+ public function getPlace()
+ {
+ return ($this->place != null ? $this->place : '-');
+ }
+
+ public static function fromArray($member)
+ {
+ return new shiai(
+ $member['lfdeNr'] ?? null,
+ $member['Datum'] ?? null,
+ $member['Veranstaltung'] ?? '
',
+ $member['Altersklassen'] ?? null,
+ $member['Ort'] ?? '',
+ $member['Ausschreibung'] ?? null,
+ $member['Routenplaner'] ?? null,
+ $member['galleryLink'] ?? null,
+ $member['promoPic'] ?? null
+ );
+ }
+
+ /**
+ * shiai event as html code for displaying
+ *
+ * @return html formated string
+ */
+ public function getHtml()
+ {
+ $retHtml = '';
+ $retHtml =
+ '' .
+ '
' . $this->getHtmlName() . '
' .
+ '
' .
+ '- Datum:
- ' . $this->getHtmlDate() . '
' .
+ '- Altersklassen
- ' . $this->getAgeClasses() . '
' .
+ '- Ort
- ' . $this->getPlace() . '
' .
+ '
' .
+ '
';
+ return $retHtml;
+ }
+} // end class shiai
diff --git a/homepage/participo/lib/participoLib/starter.php b/homepage/participo/lib/participoLib/starter.php
new file mode 100644
index 0000000..4c7155d
--- /dev/null
+++ b/homepage/participo/lib/participoLib/starter.php
@@ -0,0 +1,256 @@
+ ['default' => null, 'min_range' => 1, 'max_range' => 3]]);
+ }
+
+ /** string representations of the starting type
+ *
+ * @var array array of StartingType => its string representation
+ */
+ public static $AsString = [1 => 'Kämpfer', 2 => 'Zuschauer', 3 => 'keine Teilnahme'];
+}
+
+/** Frame for a start to a shiai */
+class Starter
+{
+ private $id = null; //< id of the event in the database
+ private $eventId = null; //< dbId of the event one is starting
+ private $typeId = null; //< type(id) of the starter
+ private $userId = null; //< id of the starting user
+ private $rideId = null; //< id of the ride where the starter can car pool
+ private $mass = null; //< mass in kg on the scale
+ private $result = null; //< result of the start (array of places if multi start)
+
+ private $shiai = null; //< to store the shiai if needed
+ private $user = null;
+
+ /** columns in the table (in the database) with their type
+ *
+ * @var array
+ */
+ private static $dbColumns = [
+ 'id' => PDO::PARAM_INT,
+ 'eventId' => PDO::PARAM_INT,
+ 'type' => PDO::PARAM_INT,
+ 'userId' => PDO::PARAM_INT,
+ 'fahrtId' => PDO::PARAM_INT,
+ 'masse' => PDO::PARAM_STR,
+ 'platz' => PDO::PARAM_STR,
+ ];
+
+ /** Constructor
+ *
+ * @todo Document
+ */
+ public function __construct($id, $eventId, $typeId, $userId, $rideId = null, $mass = null, $result = null)
+ {
+ $this->id = filter_var($id, FILTER_VALIDATE_INT, ['options' => ['default' => null, 'min_range' => 1]]);
+ $this->eventId = filter_var($eventId, FILTER_VALIDATE_INT, ['options' => ['default' => null, 'min_range' => 1]]);
+ $this->typeId = StartingType::toStartingType($typeId);
+ $this->userId = filter_var($userId, FILTER_VALIDATE_INT, ['options' => ['default' => null, 'min_range' => 1]]);
+ $this->rideId = filter_var($rideId, FILTER_VALIDATE_INT, ['options' => ['default' => null, 'min_range' => 1]]);
+ $this->mass = filter_var($mass, FILTER_VALIDATE_FLOAT, ['options' => ['default' => null, 'min_range' => 0.0]]);
+
+ if (is_iterable($result)) {
+ $this->result = [];
+ foreach ($result as $r) {
+ $r = filter_var($r, FILTER_VAR_INT, ['options' => ['default' => null, 'min_range' => 0]]);
+ if ($r) {
+ array_push($this->result, $r);
+ }
+ }
+ } else {
+ $this->$result = filter_var($r, FILTER_VALIDATE_INT, ['options' => ['default' => null, 'min_range' => 0]]);
+ }
+ }
+
+ /** Create a Starter from an assoziative array like it is returned from db requests
+ *
+ * @param array $member associative array with the UserData from the dbRequest
+ * @param $columnMappings renaming of columnNames, e.g., if the id isn't under id in the array, add 'id'=>'starterId' to the mappings
+ * @return User initialized user
+ */
+ public static function fromDbArray($member, $columnMappings = [])
+ {
+ // if it isn't remapped, take default column name
+ foreach (self::$dbColumns as $columnName => $columnDataType) {
+ if (!array_key_exists($columnName, $columnMappings)) {
+ $columnMappings[$columnName] = $columnName;
+ }
+ }
+
+ return new Starter(
+ $member[$columnMappings['id']] ?? null,
+ $member[$columnMappings['eventId']] ?? null,
+ $member[$columnMappings['type']] ?? null,
+ $member[$columnMappings['userId']] ?? null,
+ $member[$columnMappings['fahrtId']] ?? null,
+ $member[$columnMappings['masse']] ?? null,
+ $member[$columnMappings['platz']] ?? null
+ );
+ }
+
+ /** Load a starter from the db by a column
+ *
+ * @param [string] $name name of the column
+ * @param [mixed] $value value to look for
+ * @param [bool] $unique if the value is unique (true->return single value) or not (false->return array)
+ * @return loaded user or null (if sth. wrong)
+ */
+ public static function loadFromDbBy($name, $value)
+ {
+ if (!array_key_exists($name, self::$dbColumns)) {
+ return null;
+ }
+
+ $response = dbConnector::query(
+ 'SELECT * FROM `wkParticipo_Starter` WHERE `' . $name . '` = :' . $name,
+ [$name => ['value' => $value, 'data_type' => self::$dbColumns[$name]]]
+ );
+
+ if (count($response) != 1) {
+ return null;
+ }
+
+ return self::fromDbArray($response[0]);
+ }
+
+ /** Load a Starter from the db via an id
+ *
+ * @param int $starterId
+ * @return loaded starter or null (if sth. wrong)
+ */
+ public static function loadFromDb($starterId)
+ {
+ return self::loadFromDbBy('id', $starterId);
+ }
+
+ /** Add a Start to the db
+ *
+ * - backend function no input validation/sanitation is done
+ *
+ * @param [int] $eventId eventId for the start
+ * @param [int] $typeId type(Id) for the start
+ * @param [int] $userId id of the starting user
+ * @return [int] lastInserted id of the Start
+ */
+ private static function dbInsert($eventId, $typeId, $userId)
+ {
+ $query = 'INSERT INTO `cwsvjudo`.`wkParticipo_Starter` (eventId, type, userId) values (:eventId, :typeId, :userId);';
+ $params = [
+ ':eventId' => ['value' => $eventId, 'data_type' => PDO::PARAM_INT],
+ ':typeId' => ['value' => $typeId, 'data_type' => PDO::PARAM_INT],
+ ':userId' => ['value' => $userId, 'data_type' => PDO::PARAM_INT]
+ ];
+
+ $response = dbConnector::query($query, $params);
+ return dbConnector::getLastInsertId();
+ }
+
+ private static function dbDelete($eventId, $userId)
+ {
+ $query = 'DELETE FROM `cwsvjudo`.`wkParticipo_Starter` WHERE eventId = :eventId AND userId = :userId;';
+ $params = [
+ ':eventId' => ['value' => $eventId, 'data_type' => PDO::PARAM_INT],
+ ':userId' => ['value' => $userId, 'data_type' => PDO::PARAM_INT]
+ ];
+
+ $response = dbConnector::query($query, $params);
+ return;
+ }
+
+ public function addToDb()
+ {
+ // - if the id is already set it *has* to be already in the DB hence we don't add it
+ // - the logged in user must have wardship over the starter
+ if (isset($this->id) && !participo::isWardOf($this->userId)) {
+ return null;
+ }
+ // You can only start once to an event so delete *all* other starts of this user to this event
+ self::dbDelete($this->eventId, $this->userId);
+ $this->id = self::dbInsert($this->eventId, $this->typeId, $this->userId);
+ return $this->id;
+ }
+
+ public function removeFromDb()
+ {
+ // - the logged in user must have wardship over the starter
+ if (!participo::isWardOf($this->userId)) {
+ return null;
+ }
+
+ self::dbDelete($this->eventId, $this->userId);
+ return;
+ }
+
+ // create starter from assoc array
+ public static function create($parameter)
+ {
+ $id = $parameter['id'] ?? null; //< id of the event in the database
+ $eventId = $parameter['eventId'] ?? null; //< dbId of the event one is starting
+ $typeId = $parameter['typeId'] ?? null; //< type(id) of the starter
+ $userId = $parameter['userId'] ?? null; //< id of the starting user
+ $rideId = $parameter['rideId'] ?? null; //< id of the ride where the starter can car pool
+ $mass = $parameter['mass'] ?? null; //< mass in kg on the scale
+ $result = $parameter['result'] ?? null; //< result of the start (array of places if multi start)
+
+ return new Starter($id, $eventId, $typeId, $userId, $rideId, $mass, $result);
+ }
+
+ // Getter for the member
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ public function getEventId()
+ {
+ return $this->eventId;
+ }
+
+ public function getTypeId()
+ {
+ return $this->typeId;
+ }
+
+ public function getUserId()
+ {
+ return $this->userId;
+ }
+
+ public function getRideId()
+ {
+ return $this->rideId;
+ }
+
+ public function getMass()
+ {
+ return $this->mass;
+ }
+
+ public function getResult()
+ {
+ return $this->result;
+ }
+
+ public function getUser()
+ {
+ return User::loadFromDb($this->userId);
+ }
+}
diff --git a/homepage/participo/lib/participoLib/user.php b/homepage/participo/lib/participoLib/user.php
new file mode 100644
index 0000000..6eab3ca
--- /dev/null
+++ b/homepage/participo/lib/participoLib/user.php
@@ -0,0 +1,176 @@
+ PDO::PARAM_INT,
+ 'loginName' => PDO::PARAM_STR,
+ 'name' => PDO::PARAM_STR,
+ 'vorname' => PDO::PARAM_STR,
+ 'gebDatum' => PDO::PARAM_STR,
+ 'eMail' => PDO::PARAM_STR,
+ 'pwHash' => PDO::PARAM_STR,
+ 'config' => PDO::PARAM_STR
+ ];
+
+ /** Constructor
+ * @todo Document parameter
+ * @todo Input sanitation
+ */
+ public function __construct($id, $loginName, $name, $firstName, $dateOfBirth, $eMail, $config, $pwHash)
+ {
+ $this->id = (int) $id;
+ $this->loginName = $loginName;
+ $this->name = $name;
+ $this->firstName = $firstName;
+ $this->dateOfBirth = $dateOfBirth != null ? DateTime::createFromFormat('Y-m-d', $dateOfBirth) : null;
+ $this->eMail = $eMail;
+ $this->config = $config;
+ $this->pwHash = $pwHash;
+ }
+
+ /** Export the User data into an associative array
+ *
+ * @return array associative array representing the user
+ */
+ public function toAssoc()
+ {
+ return [
+ 'id' => $this->id,
+ 'loginName' => $this->loginName,
+ 'name' => $this->name,
+ 'vorname' => $this->firstName,
+ 'gebDatum' => $this->dateOfBirth,
+ 'eMail' => $this->eMail,
+ 'config' => $this->config,
+ 'pwHash' => $this->pwHash
+ ];
+ }
+
+ /** verify the users password
+ *
+ * @param [string] $password the password to verify
+ * @return true if password is verified, false otherwise
+ */
+ public function verifyPassword($password)
+ {
+ return password_verify($password, $this->pwHash);
+ }
+
+ // getter functions
+
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ public function getLoginName()
+ {
+ return $this->loginName;
+ }
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function getFirstname()
+ {
+ return $this->firstName;
+ }
+
+ public function getConfig()
+ {
+ return $this->$config;
+ }
+
+ // static functions
+
+ /** Create a User from an assoziative array like it is returned from db requests
+ *
+ * @param array $member associative array with the UserData from the dbRequest
+ * @param $columnMappings renaming of columnNames, e.g., if the id isn't under id in the array, add 'id'=>'userId' to the mappings
+ * @return User initialized user
+ */
+ public static function fromDbArray($member, $columnMappings = [])
+ {
+ // if it isn't remapped, take default column name
+ foreach (self::$dbColumns as $columnName => $columnDataType) {
+ if (!array_key_exists($columnName, $columnMappings)) {
+ $columnMappings[$columnName] = $columnName;
+ }
+ }
+
+ return new User(
+ $member[$columnMappings['id']] ?? null,
+ $member[$columnMappings['loginName']] ?? null,
+ $member[$columnMappings['name']] ?? null,
+ $member[$columnMappings['vorname']] ?? null,
+ $member[$columnMappings['gebDatum']] ?? null,
+ array_key_exists($columnMappings['eMail'], $member) ? explode(',', $member['eMail']) : null,
+ array_key_exists($columnMappings['config'], $member) ? json_decode($member['config']) : null,
+ array_key_exists($columnMappings['pwHash'], $member) ? $member['pwHash'] : null
+ );
+ }
+
+ /** Load an User from the db via an id
+ *
+ * @param int $userId
+ * @return loaded user or null (if sth. wrong)
+ */
+ public static function loadFromDb($userId)
+ {
+ return self::loadFromDbBy('id', $userId);
+ }
+
+ /** Load an User from the db via the loginName
+ *
+ * @param int $login
+ * @return loaded user or null (if sth. wrong)
+ */
+ public static function loadFromDbByLoginName($login)
+ {
+ return self::loadFromDbBy('loginName', $login);
+ }
+
+ /** Load a user from the db by a column
+ *
+ * @param [string] $name name of the column
+ * @param [mixed] $value value to look for
+ * @param [bool] $unique if the value is unique (true->return single value) or not (false->return array)
+ * @return loaded user or null (if sth. wrong)
+ */
+ public static function loadFromDbBy($name, $value)
+ {
+ if (!array_key_exists($name, self::$dbColumns)) {
+ return null;
+ }
+
+ $response = dbConnector::query(
+ 'SELECT * FROM `wkParticipo_Users` WHERE `' . $name . '` = :' . $name,
+ [$name => ['value' => $value, 'data_type' => self::$dbColumns[$name]]]
+ );
+
+ if (count($response) != 1) {
+ return null;
+ }
+
+ return User::fromDbArray($response[0]);
+ }
+}
diff --git a/homepage/participo/test.py b/homepage/participo/test.py
new file mode 100644
index 0000000..9ab8329
--- /dev/null
+++ b/homepage/participo/test.py
@@ -0,0 +1,71 @@
+#! /usr/bin/env python
+
+import sys
+
+import html5lib
+
+from selenium import webdriver
+from selenium.webdriver.support.ui import WebDriverWait
+from selenium.webdriver.chrome.options import Options
+from selenium.webdriver.common.by import By
+
+# credentials
+username = "marko"
+password = "kodokan"
+
+# initialize the Chrome driver
+chromeOptions = Options()
+chromeOptions.headless = True
+driver = webdriver.Chrome(options=chromeOptions)
+
+html5Parser = html5lib.HTMLParser(strict=True)
+
+# head to login page
+driver.get("http://cwsvjudo.bplaced.net/participo/")
+# find username/email field and send the username itself to the input field
+driver.find_element("id", "username").send_keys(username)
+# find password input field and insert password as well
+driver.find_element("id", "password").send_keys(password)
+# click login button
+driver.find_element("name", "submit").click()
+
+
+# wait the ready state to be complete
+WebDriverWait(driver=driver, timeout=10).until(
+ lambda x: x.execute_script("return document.readyState === 'complete'")
+)
+
+# Open the sidemenu if necessary
+for m in driver.find_elements(By.CLASS_NAME, "material-icons"):
+ if m.text == "menu":
+ m.click()
+
+try:
+ html5Parser.parse(" "+driver.page_source)
+ print("mainpage ok")
+except Exception as e:
+ print(repr(e), file=sys.stderr)
+ print(driver.page_source)
+
+loginText = "Angemeldet als " + username
+divList = driver.find_elements(By.TAG_NAME, 'li')
+
+if not any(loginText in d.text for d in divList):
+ print("login failed", file=sys.stderr)
+ driver.close()
+ driver.quit()
+ exit(-1)
+
+for pageName in ["events", "attendance", "kyu", "user"]: # missing: "infoZettel"
+ driver.get("http://cwsvjudo.bplaced.net/participo/"+pageName)
+
+ try:
+ html5Parser.parse(""+driver.page_source)
+ print(f"{pageName} ok")
+ except Exception as e:
+ print(repr(e), file=sys.stderr)
+ print(driver.page_source)
+
+
+driver.close()
+driver.quit()
diff --git a/homepage/participo/wk.api.php b/homepage/participo/wk.api.php
new file mode 100644
index 0000000..a512f4e
--- /dev/null
+++ b/homepage/participo/wk.api.php
@@ -0,0 +1,24 @@
+= CURDATE();';
+$wkSqlResponse = dbConnector::query($wkSqlQuery);
+
+header('Access-Control-Allow-Headers: *');
+header('Access-Control-Allow-Origin: *');
+
+echo(json_encode($wkSqlResponse));