Files
cwsvJudo/homepage/participo/lib/participoLib/user.php
marko f28fa7b51b WIP: bring participo back - consistent use of bootstrap - formatting -
phpstan level 0 error free - fixes for kyu subpage - move mams into
participo framework - remove legacy `lib/db.php` usage - add attributer
admin function - add newsposter - fixing apiKey creation
2025-11-19 12:24:38 +01:00

539 lines
16 KiB
PHP

<?php
require_once "participoLib/participo.php";
require_once "participoLib/dbConnector.php";
/** Frame for a User if the Participo system
*/
class User
{
/** Constructor
* @todo Document parameter
* @todo Input sanitation
*/
public function __construct(
$id,
$loginName,
$name,
$firstName,
$dateOfBirth = null,
$eMail = null,
$config = null,
$pwHash = null,
) {
$this->id = filterId($id);
$this->loginName = $loginName;
$this->name = $name;
$this->firstName = $firstName;
$this->dateOfBirth =
$dateOfBirth != null
? DateTime::createFromFormat("Y-m-d", $dateOfBirth)
: null;
$this->eMail =
$eMail != null
? filter_var($eMail, FILTER_VALIDATE_EMAIL, [
"options" => ["default" => null],
])
: null;
$this->config = $config;
$this->pwHash = $pwHash;
}
/** return users year of birth as int
*
* @retval int>=0 on success,
* @retval null failure
*/
public function yearOfBirth()
{
if (isset($this->dateOfBirth)) {
return filterPosInt($this->dateOfBirth->format("Y"));
}
return null;
}
////
// dbInterface
////
public function addToDb()
{
// if the user has an Id set it has to come from the Db. Hence don't add an User that is already added.
if (isset($this->id) || !participo::isUserAdmin()) {
return;
}
$this->id = self::dbInsert(
$this->loginName,
$this->name,
$this->firstName,
isset($this->dateOfBirth)
? $this->dateOfBirth->format("Y-m-d")
: null,
$this->eMail,
$this->config,
$this->pwHash,
);
return $this->id;
}
private static function dbInsert(
$loginName,
$name,
$firstName,
$dateOfBirth = null,
$eMail = null,
$config = null,
$pwHash = null,
) {
$query =
"INSERT INTO `" .
self::$tableName .
"` " .
"(loginName, name, vorname, gebDatum, eMail, config, pwHash) " .
" VALUES (:loginName, :name, :vorname, :gebDatum, :eMail, :config, :pwHash);";
$params = [
":loginName" => [
"value" => $loginName,
"data_type" => self::$dbColumns["loginName"],
],
":name" => [
"value" => $name,
"data_type" => self::$dbColumns["name"],
],
":vorname" => [
"value" => $firstName,
"data_type" => self::$dbColumns["vorname"],
],
":gebDatum" => [
"value" => $dateOfBirth,
"data_type" => self::$dbColumns["gebDatum"],
],
":eMail" => [
"value" => $eMail,
"data_type" => self::$dbColumns["eMail"],
],
":config" => [
"value" => $config,
"data_type" => self::$dbColumns["config"],
],
":pwHash" => [
"value" => $pwHash,
"data_type" => self::$dbColumns["pwHash"],
],
];
$response = dbConnector::query($query, $params);
return dbConnector::getLastInsertId();
}
public static function dbSelectWithAttribute(int $attributeId)
{
$query =
"SELECT DISTINCT" .
" `wkParticipo_Users`.* " .
" FROM `wkParticipo_Users`" .
" JOIN `wkParticipo_user<=>userAttributes`" .
" ON `wkParticipo_user<=>userAttributes`.`userId` = `wkParticipo_Users`.`id`" .
" WHERE `wkParticipo_user<=>userAttributes`.`attributeId` = :attributeId" .
" ORDER BY `wkParticipo_Users`.`id` ASC;";
$params = [
":attributeId" => [
"value" => $attributeId,
"data_type" => PDO::PARAM_INT,
],
];
$response = dbConnector::query($query, $params);
return $response;
}
/** Name of the table with all the Users
*
* @var string
*/
private static $tableName = "wkParticipo_Users";
/** columns in the User table (in the database) with their type
*
* @var array
*/
private static $dbColumns = [
"id" => PDO::PARAM_INT,
"loginName" => PDO::PARAM_STR,
"name" => PDO::PARAM_STR,
"vorname" => PDO::PARAM_STR,
"gebDatum" => PDO::PARAM_STR,
"eMail" => PDO::PARAM_STR,
"config" => PDO::PARAM_STR,
"pwHash" => PDO::PARAM_STR,
];
////
// html interface
////
public static function getHtmlFormAddUser($options = [])
{
$returnToUrl = $options["returnToUrl"] ?? urlencode(getCurPagesUrl());
$formClass = isset($options["formClass"])
? 'class="' . $options["formClass"] . '"'
: "";
$form =
"<form " .
$formClass .
' action="api.user.add.php" method="post">' .
'<input type="hidden" name="returnToUrl" id="returnToUrl" value="' .
$returnToUrl .
'" >' .
'<div><label for="loginName">Benutzername</label> <input type="text" name="loginName" id="loginName"></div>' .
'<div><label for="name">Nachname</label> <input type="text" name="name" id="name"></div>' .
'<div><label for="firstName">Vorname</label> <input type="text" name="firstName" id="firstName"></div>' .
'<div><label for="dateOfBirth">Geb.Datum</label> <input type="text" name="dateOfBirth" id="dateOfBirth"></div>' .
'<div><label for="eMail">eMail</label> <input type="text" name="eMail" id="eMail"></div>' .
'<button class="btn" type="submit" name="submit">erstellen</button>' .
"</form>";
return $form;
}
public static function htmlFormAddUser($options = [])
{
echo self::getHtmlFormAddUser($options);
}
// member variables
private $id;
private $loginName;
private $name;
private $firstName;
private $dateOfBirth;
private $eMail;
private $config;
private $pwHash;
// database member data
/** List of ids of the users kids */
private $kidIds = null;
/** List of users kids */
private $kids = null;
// public function kidIds(bool $forceLoading = false)
// {
// if (is_null($this->kidIds) || $forceLoading) {
// $this->kidIds = self::getKidIds($id);
// }
// return self::$kidIds;
// }
public function kids(bool $forceLoading = false)
{
if (is_null($this->kids) || $forceLoading) {
$this->kids = participo::getKids($this->id);
}
return $this->kids;
}
// private static function getKidIds(int $id)
// {
// $response = dbConnector::query(
// 'SELECT * FROM `wkParticipo_Users` WHERE `' . $name . '` = :' . $name,
// [$name => ['value' => $value, 'data_type' => self::$dbColumns[$name]]]
// );
// $query = <<<SQL
// SELECT *
// FROM `wkParticipo_Users`
// JOIN `vormundschaft`
// ON `wkParticipo_Users`.`id` = `vormundschaft`.`kidId`
// WHERE `vormundschaft`.`userId` = :userId;
// SQL;
// $params = [
// ':userId' => ['value' => $userId, 'data_type' => PDO::PARAM_INT]
// ];
// $response = dbConnector::query($query, $params);
// return $response;
// }
/** 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;
}
public function getDateOfBirth()
{
return $this->dateOfBirth;
}
public function getStrBirthday()
{
return $this->dateOfBirth->format("Y-m-d");
}
// 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 but under 'userID', 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) &&
$member["config"]
? 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 ?User loaded user or null (if sth. wrong)
*/
public static function loadFromDb(int $userId)
{
return self::loadFromDbBy("id", $userId);
}
/** Load an User from the db via the loginName
*
* @param int $login
* @return ?User 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
*
* @todo There is exactly the same function in the `Starter` class. It seems this could be a general dbInterface function.
*
* @param string $name name of the column in which to search the value for
* @param mixed $value value to look for
* @return ?User loaded user or null (if sth. wrong)
*/
public static function loadFromDbBy(string $name, mixed $value): ?User
{
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],
],
],
someOptions: ["dbCharset" => "UTF-8"],
);
if (count($response) != 1) {
return null;
}
return User::fromDbArray($response[0]);
}
public static function loadFromDbByAttribute(int $attributeId)
{
$query =
"SELECT DISTINCT" .
" `wkParticipo_Users`.* " .
" FROM `wkParticipo_Users`" .
" JOIN `wkParticipo_user<=>userAttributes`" .
" ON `wkParticipo_user<=>userAttributes`.`userId` = `wkParticipo_Users`.`id`" .
" WHERE `wkParticipo_user<=>userAttributes`.`attributeId` = :attributeId" .
" ORDER BY `wkParticipo_Users`.`id` ASC;";
$response = dbConnector::query($query, [
"attributeId" => [
"value" => filterId($attributeId),
"data_type" => PDO::PARAM_INT,
],
]);
// Postprocessing
// - convert the comma separated list into an array
foreach ($response as &$user) {
$user["eMail"] = explode(",", $user["eMail"]);
foreach ($user["eMail"] as &$email) {
$email = trim($email);
}
}
return $response;
}
}
/// @todo Legacy function! Replace with one within the User-Framework!
function getUsersWithAttribute($dbConnection, $attributeName)
{
$query = <<<SQL
SELECT userId, name, vorname
FROM `wkParticipo_Users`
JOIN `wkParticipo_user<=>userAttributes`
ON `wkParticipo_Users`.`id` = `wkParticipo_user<=>userAttributes`.`userId`
WHERE `wkParticipo_user<=>userAttributes`.`attributeId` IN (
SELECT `id` FROM `wkParticipo_userAttributes` WHERE `name` = :attributeName
);
SQL;
$params = [
":attributeName" => [
"value" => $attributeName,
"data_type" => PDO::PARAM_STR,
],
];
return dbConnector::query($query, $params);
}
/// @todo Legacy function! Replace with one within the User-Framework!
function getLastAttendances($db, $minDate = null)
{
if ($minDate == null) {
$minDate = new DateTime();
$minDate->sub(new DateInterval("P1M")); // from the current date subtract a *P*eriod of *1* *M*onth
}
$query = <<<SQL
SELECT userId, date, vorname, name, corona_PLZ, corona_telephon, corona_eMail
FROM `anwesenheit`
JOIN `wkParticipo_Users`
ON `anwesenheit`.`userId` = `wkParticipo_Users`.`id`
WHERE :minDate <= date
ORDER BY `date` DESC, `name`;
SQL;
$params = [
"minDate" => [
"value" => $minDate->format("Y-m-d"),
"data_type" => PDO::PARAM_STR,
],
];
$options = [];
$ret = dbConnector::query($query, $params, $options);
return $ret;
}
/// @todo Legacy function! Replace with one within the User-Framework!
function giveUserAnUserAttribute($userId, $attributeName)
{
$query = <<<SQL
INSERT INTO `wkParticipo_user<=>userAttributes` (`userId`, `attributeId`)
SELECT :userId, `id`
FROM `wkParticipo_userAttributes`
WHERE `name` = :attributeName;
SQL;
$params = [
":userId" => ["value" => $userId, "data_type" => PDO::PARAM_INT],
":attributeName" => [
"value" => $attributeName,
"data_type" => PDO::PARAM_STR,
],
];
return dbConnector::query($query, $params);
}
/// @todo Legacy function! Replace with one within the User-Framework!
function getUserData($userId)
{
$query = <<<SQL
SELECT *
FROM `cwsvjudo_main`.`wkParticipo_Users`
WHERE `id` = :userId;
SQL;
$params = [
":userId" => ["value" => $userId, "data_type" => PDO::PARAM_INT],
];
$userData = \dbConnector::query($query, $params);
return $userData[0];
}
// @todo: Achtung, als id ist die id der Vormundschaft gespeichert. Unter kidId die des Kindes.
/// @todo Legacy function! Replace with one within the User-Framework!
function getUsersKids($userId, $options = [])
{
$options["attribute"] ??
($query = <<<SQL
SELECT *
FROM `wkParticipo_Users`
JOIN `vormundschaft`
ON `wkParticipo_Users`.`id` = `vormundschaft`.`kidId`
WHERE `vormundschaft`.`userId` = :userId;
SQL);
$params = [
":userId" => ["value" => $userId, "data_type" => PDO::PARAM_INT],
];
$result = dbConnector::query($query, $params);
return $result;
}