Pre-merge state

This commit is contained in:
Wiesner András 2024-09-25 09:19:28 +02:00
parent 1504c483fc
commit 42190c6cba
14 changed files with 373 additions and 110 deletions

32
class/AutoStoring.php Normal file
View File

@ -0,0 +1,32 @@
<?php
class AutoStoring
{
protected bool $autoStoring;
function __construct() {
$this->autoStoring = true;
}
// Disable autostoring feature.
public function disableAutoStoring() : void
{
$this->autoStoring = false;
}
// Enable autostoring feature.
public function enableAutoStoring() : void {
$this->autoStoring = true;
}
// Store modifications.
public function storeMods() : void {
return;
}
public function commitMods() : void {
if ($this->autoStoring) {
$this->storeMods();
}
}
}

View File

@ -1,6 +1,8 @@
<?php <?php
class Game require_once "AutoStoring.php";
class Game extends AutoStoring
{ {
public const DEFAULT_GAME_PROPERTIES = [ public const DEFAULT_GAME_PROPERTIES = [
"forward_only" => false, // player may traverse back and forth between challenges "forward_only" => false, // player may traverse back and forth between challenges
@ -40,12 +42,18 @@ class Game
} }
// Store modifications. // Store modifications.
function storeMods(): void public function storeMods() : void
{ {
$this->patchUpGameDate();
$this->gameMgr->updateGame($this); $this->gameMgr->updateGame($this);
} }
// Commit modifications.
function commitMods(): void
{
//$this->patchUpGameDate();
parent::commitMods();
}
// Load game challenges. // Load game challenges.
public function loadChallenges(): void public function loadChallenges(): void
{ {
@ -66,6 +74,8 @@ class Game
array $contributors = [], bool $gameFileIsPresent = false, array $properties = [], array $contributors = [], bool $gameFileIsPresent = false, array $properties = [],
bool $public = false, string $publicId = "", int $version = 2) bool $public = false, string $publicId = "", int $version = 2)
{ {
parent::__construct();
$this->gameMgr = $gameMgr; $this->gameMgr = $gameMgr;
$this->id = $id; $this->id = $id;
$this->name = $name; $this->name = $name;
@ -83,17 +93,19 @@ class Game
// Create game from array representation. // Create game from array representation.
static function fromArray(GameMgr &$gameMgr, array $a): Game static function fromArray(GameMgr &$gameMgr, array $a): Game
{ {
$id = $a["id"] ?? -1; $id = $a["_id"] ?? -1;
self::patchUpGameDate($a); self::patchUpGameDate($a);
return new Game($gameMgr, $a["name"], $a["description"], $id, $a["owner"], $a["contributors"], return new Game($gameMgr, $a["name"], $a["description"], $id, $a["owner"], $a["contributors"],
$a["gameFileIsPresent"], $a["properties"], $a["public"], $a["publicId"], $a["version"]); $a["game_file_present"], $a["properties"], $a["public"], $a["public_id"], $a["version"]);
} }
const OMIT_ADVANCED_FIELDS = ["contributors", "game_file_is_present", "properties", "groups", "public", "public_id", "version"];
// Convert game to array representation. // Convert game to array representation.
function toArray(array $omit = []): array function toArray(array $omit = []): array
{ {
$a = [ $a = [
"_id" => $this->_id, "_id" => $this->id,
"name" => $this->name, "name" => $this->name,
"description" => $this->description, "description" => $this->description,
"owner" => $this->owner, "owner" => $this->owner,
@ -230,7 +242,7 @@ class Game
$this->gameFileIsPresent = true; $this->gameFileIsPresent = true;
// store modifications // store modifications
$this->storeMods(); $this->commitMods();
return ["n" => count($this->challenges), "encoding" => $encoding]; return ["n" => count($this->challenges), "encoding" => $encoding];
} }
@ -287,6 +299,11 @@ class Game
return $this->gameFileIsPresent; return $this->gameFileIsPresent;
} }
function setProperties(array $properties): void {
$this->properties = $properties;
$this->commitMods();
}
public function& getProperties(): array public function& getProperties(): array
{ {
return $this->properties; return $this->properties;
@ -302,6 +319,11 @@ class Game
return $this->publicId; return $this->publicId;
} }
public function setPublic(bool $public) : void {
$this->public = $public;
$this->commitMods();
}
public function getChallenges(): array public function getChallenges(): array
{ {
return $this->challenges; return $this->challenges;
@ -330,7 +352,7 @@ class GameMgr
function getGame(string $gameid): Game|null function getGame(string $gameid): Game|null
{ {
$game_data_array = $this->db->findById($gameid); $game_data_array = $this->db->findById($gameid);
return count($game_data_array) != 0 ? Game::fromArray($this, $game_data_array[0]) : null; return count($game_data_array) != 0 ? Game::fromArray($this, $game_data_array) : null;
} }
// Get public game. FIXME!!! // Get public game. FIXME!!!

View File

@ -1,6 +1,8 @@
<?php <?php
class Group require_once "AutoStoring.php";
class Group extends AutoStoring
{ {
private int $_id; // Group's ID (assigned by SleekDB) private int $_id; // Group's ID (assigned by SleekDB)
private string $name; // Group's name private string $name; // Group's name
@ -15,7 +17,7 @@ class Group
// -------------- // --------------
// store modifications to the database // store modifications to the database
private function storeMods() public function storeMods() : void
{ {
$this->groupMgr->updateGroup($this); $this->groupMgr->updateGroup($this);
} }
@ -24,6 +26,8 @@ class Group
function __construct(GroupMgr &$groupMgr, string $name, string $description, string $owner, int $id = -1, bool $unique = true, array $editors = [], array $members = [], array $games = []) function __construct(GroupMgr &$groupMgr, string $name, string $description, string $owner, int $id = -1, bool $unique = true, array $editors = [], array $members = [], array $games = [])
{ {
parent::__construct();
$this->_id = $id; $this->_id = $id;
$this->name = $name; $this->name = $name;
$this->unique = $unique; $this->unique = $unique;
@ -38,7 +42,7 @@ class Group
// Create Group from array // Create Group from array
static function fromArray(GroupMgr &$groupMgr, array $a): Group static function fromArray(GroupMgr &$groupMgr, array $a): Group
{ {
return new Group($groupMgr, $a["name"], $a["description"], $a["owner"], $a["_id"], $a["unique"], $a["editors"], $a["members"], $a["games"]); return new Group($groupMgr, $a["groupname"], $a["description"], $a["owner"], $a["_id"], $a["unique"], $a["editors"], $a["users"], $a["games"]);
} }
// Convert Group to array // Convert Group to array
@ -51,7 +55,7 @@ class Group
"description" => $this->description, "description" => $this->description,
"owner" => $this->owner, "owner" => $this->owner,
"editors" => $this->editors, "editors" => $this->editors,
"members" => $this->members, "users" => $this->members,
"games" => $this->games "games" => $this->games
]; ];
@ -216,7 +220,7 @@ class GroupMgr
// ------------------------- // -------------------------
private function manageTwins(int $current_group_id, string $groupname): bool public function manageTwins(int $current_group_id, string $groupname): bool
{ {
// make test on name uniqueness // make test on name uniqueness
$twins = $this->db->findBy([["groupname", "=", "$groupname"], "AND", ["_id", "!=", $current_group_id]]); $twins = $this->db->findBy([["groupname", "=", "$groupname"], "AND", ["_id", "!=", $current_group_id]]);
@ -239,7 +243,7 @@ class GroupMgr
function getGroup(string $groupid): Group|null function getGroup(string $groupid): Group|null
{ {
$group_data_array = $this->db->findById($groupid); $group_data_array = $this->db->findById($groupid);
return count($group_data_array) != 0 ? Group::fromArray($this, $group_data_array[0]) : null; return count($group_data_array) != 0 ? Group::fromArray($this, $group_data_array) : null;
} }
// Update group. // Update group.

View File

@ -2,7 +2,9 @@
require_once "common_func.php"; require_once "common_func.php";
class User require_once "AutoStoring.php";
class User extends AutoStoring
{ {
private int $id; // User's ID private int $id; // User's ID
private string $nickname; // User's nickname private string $nickname; // User's nickname
@ -15,7 +17,7 @@ class User
// ------------------------------------------- // -------------------------------------------
// Store modifications to the database. // Store modifications to the database.
private function storeMods(): void public function storeMods(): void
{ {
$this->userMgr->updateUser($this); $this->userMgr->updateUser($this);
} }
@ -24,6 +26,8 @@ class User
function __construct(UserMgr &$usrmgr, int $id, string $nickname = null, string $password = null, string $realname = null, array $groups = null, string $privilege = null) function __construct(UserMgr &$usrmgr, int $id, string $nickname = null, string $password = null, string $realname = null, array $groups = null, string $privilege = null)
{ {
parent::__construct();
$this->id = $id; $this->id = $id;
$this->nickname = $nickname; $this->nickname = $nickname;
$this->password = $password; $this->password = $password;
@ -38,7 +42,7 @@ class User
// Create user from an array // Create user from an array
static function fromArray(UserMgr &$usrmgr, array $a): User static function fromArray(UserMgr &$usrmgr, array $a): User
{ {
$id = $a["id"] ?? -1; $id = $a["_id"] ?? -1;
return new User($usrmgr, $id, $a["nickname"], $a["password"], $a["realname"], $a["groups"], $a["privilege"]); return new User($usrmgr, $id, $a["nickname"], $a["password"], $a["realname"], $a["groups"], $a["privilege"]);
} }

View File

@ -1,5 +1,8 @@
{ {
"require": { "require": {
"rakibtg/sleekdb": "2.15" "rakibtg/sleekdb": "2.15",
"ext-http": "*",
"ext-mbstring" : "*",
"ext-zip": "*"
} }
} }

View File

@ -14,6 +14,7 @@ const QUIZMASTER_NICKNAME = "quizmaster";
const LOGIN_URL = "login.php"; const LOGIN_URL = "login.php";
const MAIN_URL = "main.php"; const MAIN_URL = "main.php";
const SESSION_NAME = "spreadquiz_sid"; const SESSION_NAME = "spreadquiz_sid";
const MAINTENANCE_FLAG_FILE = "MAINTENANCE";
const MISSING_IMAGE_PLACEHOLDER = "media/image-missing_120px.png"; const MISSING_IMAGE_PLACEHOLDER = "media/image-missing_120px.png";
@ -34,3 +35,9 @@ function init_datadir() {
} }
} }
// check MAINTENANCE file
if (file_exists(MAINTENANCE_FLAG_FILE)) {
header("Location: maintenance.html");
exit(0);
}

View File

@ -10,6 +10,21 @@ function create_group(string $groupname, string $owner, string $description = ""
{ {
global $groupdb; global $groupdb;
// test name uniqueness
$unique = manage_unique_in_siblings(0, $groupname);
// initialize group data
$group_data = [
"groupname" => $groupname,
"unique" => $unique,
"owner" => $owner,
"description" => $description,
"editors" => [],
"users" => [],
"games" => []
];
$groupdb->insert($group_data); // insert group
return true;
} }

View File

@ -26,6 +26,10 @@ require_once "class/ReqHandler.php";
require_once "class/UserMgr.php"; require_once "class/UserMgr.php";
require_once "class/GroupMgr.php";
require_once "class/GameMgr.php";
// ------------------------ // ------------------------
$userMgr = new UserMgr(); $userMgr = new UserMgr();
@ -46,7 +50,8 @@ $is_quizmaster = false;
$rh = new ReqHandler(); $rh = new ReqHandler();
// action dump callback // action dump callback
function dump_actions(ReqHandler &$rh, array $params): string { function dump_actions(ReqHandler &$rh, array $params): string
{
return $rh->dump_actions(); return $rh->dump_actions();
} }
@ -86,6 +91,8 @@ $user = $userMgr->getUser($_SESSION["nickname"]);
$nickname = $user->getNickname(); $nickname = $user->getNickname();
$privilege = $user->getPrivilege(); $privilege = $user->getPrivilege();
$is_quizmaster = $privilege === PRIVILEGE_QUIZMASTER; $is_quizmaster = $privilege === PRIVILEGE_QUIZMASTER;
$groupMgr = new GroupMgr();
$gameMgr = new GameMgr();
/* ---------- ACTIONS REQUIRING BEING LOGGED IN ------------ */ /* ---------- ACTIONS REQUIRING BEING LOGGED IN ------------ */
@ -107,19 +114,25 @@ function get_user_info(ReqHandler &$rh, array $params): array
function get_available_games(ReqHandler &$rh, array $params): array function get_available_games(ReqHandler &$rh, array $params): array
{ {
global $user; global $user;
global $groupMgr;
global $gameMgr;
$games_by_groups = []; $games_by_groups = [];
$groupids = $user->getGroups(); $groupids = $user->getGroups();
foreach ($groupids as $groupid) { foreach ($groupids as $groupid) {
$group_data = get_group($groupid); $group = $groupMgr->getGroup($groupid);
$game_collection = [ $game_collection = [
"groupname" => $group_data["groupname"], "groupname" => $group->getName(),
"description" => $group_data["description"], "description" => $group->getDescription(),
"games" => [] "games" => []
]; ];
$gameids = $group_data["games"]; $gameids = $group->getGames();
foreach ($gameids as $gameid) { foreach ($gameids as $gameid) {
$game = get_game($gameid); $game = $gameMgr->getGame($gameid);
$game_collection["games"][] = $game; if ($game->isGameFileIsPresent()) {
$a = $game->toArray(Game::OMIT_ADVANCED_FIELDS);
$game_collection["games"][] = $a;
}
} }
$games_by_groups[] = $game_collection; $games_by_groups[] = $game_collection;
} }
@ -151,7 +164,19 @@ function get_results_overview(ReqHandler &$rh, array $params): array
return $overviews; return $overviews;
} }
function change_password(ReqHandler &$rh, array $params): string
{
$oldpass = $params["oldpass"];
$newpass = $params["newpass"];
global $user;
$success = $user->changePassword($newpass, $oldpass);
return $success ? "OK" : "FAIL";
}
$rh->add("logout", [], PRIVILEGE_PLAYER, "logout", RESP_PLAIN, "Log out the user."); $rh->add("logout", [], PRIVILEGE_PLAYER, "logout", RESP_PLAIN, "Log out the user.");
$rh->add("change_password", ["oldpass", "newpass"], PRIVILEGE_PLAYER, "change_password", RESP_PLAIN, "Change users password.");
$rh->add("get_user_info", [], PRIVILEGE_PLAYER, "get_user_info", RESP_JSON, "Get user information."); $rh->add("get_user_info", [], PRIVILEGE_PLAYER, "get_user_info", RESP_JSON, "Get user information.");
$rh->add("get_available_games", [], PRIVILEGE_PLAYER, "get_available_games", RESP_JSON, "Get available games to the player."); $rh->add("get_available_games", [], PRIVILEGE_PLAYER, "get_available_games", RESP_JSON, "Get available games to the player.");
$rh->add("start_or_continue_test", ["gameid"], PRIVILEGE_PLAYER, "start_or_continue_test", RESP_PLAIN, "Start new or continue an ongoing test."); $rh->add("start_or_continue_test", ["gameid"], PRIVILEGE_PLAYER, "start_or_continue_test", RESP_PLAIN, "Start new or continue an ongoing test.");
@ -270,8 +295,10 @@ $requester_nickname = $is_quizmaster ? "*" : $nickname; // "*" means every game
function create_update_game(ReqHandler &$rh, array $params): array function create_update_game(ReqHandler &$rh, array $params): array
{ {
global $userMgr; global $userMgr;
global $user;
global $nickname; global $nickname;
global $is_quizmaster; global $is_quizmaster;
global $gameMgr;
$update = $params[ReqHandler::ACTION_KEY] === "update_game"; $update = $params[ReqHandler::ACTION_KEY] === "update_game";
$data = json_decode($params["data"], true) ?? []; $data = json_decode($params["data"], true) ?? [];
@ -303,43 +330,49 @@ function create_update_game(ReqHandler &$rh, array $params): array
$result = []; $result = [];
// create or update // create or update
if (!$update) { if (!$update) { // CREATE
create_game($name, $owner, $description); $gameMgr->addGame($name, $owner, $description);
} else if (is_user_contributor_to_game($gameid, $nickname) || $is_quizmaster) { } else { // UPDATE
$game_data = get_game($gameid); $game = $gameMgr->getGame($gameid); // fetch game
if (count($game_data) !== 0) {
// group management if (($game !== null) && $game->isUserContributorOrOwner($nickname) || $user->hasQuizmasterPrivilege()) {
$old_groupids = $game_data["groups"]; // retain old groupids // group management TODO: átkerül a csoportkezelőbe
$new_groupids = $groupids; // get new groupids // $old_groupids = $game_data["groups"]; // retain old groupids
$groupids_add = array_diff($new_groupids, $old_groupids); // groups this user needs to be added to // $new_groupids = $groupids; // get new groupids
$groupids_remove = array_diff($old_groupids, $new_groupids); // groups this user need to be removed from // $groupids_add = array_diff($new_groupids, $old_groupids); // groups this user needs to be added to
foreach ($groupids_add as $groupid) { // execute insertion and removal // $groupids_remove = array_diff($old_groupids, $new_groupids); // groups this user need to be removed from
change_group_game_assignments($groupid, $gameid, null); // foreach ($groupids_add as $groupid) { // execute insertion and removal
} // change_group_game_assignments($groupid, $gameid, null);
foreach ($groupids_remove as $groupid) { // }
change_group_game_assignments($groupid, null, $gameid); // foreach ($groupids_remove as $groupid) {
} // change_group_game_assignments($groupid, null, $gameid);
// }
// re-fetch game data // re-fetch game data
$game_data = get_game($gameid); // $game_data = get_game($gameid);
// disable autostoring
$game->disableAutoStoring();
// update game header data // update game header data
$game_data["name"] = $name; $game->setName($name);
$game_data["description"] = $description; $game->setDescription($description);
if (($game_data["owner"] === $nickname) || $is_quizmaster) {
$game_data["owner"] = $owner;
}
$game_data["contributors"] = array_intersect($contributors, $userMgr->getAllNicknames()); if ($game->isUserOwner($nickname) || $user->hasQuizmasterPrivilege()) {
$game_data["properties"]["time_limit"] = $properties["time_limit"]; $game->setOwner($owner);
$game_data["properties"]["repeatable"] = $properties["repeatable"]; }
$game->setContributors($contributors);
$game->setProperties($properties);
// process game public flag: a game might be only public if not being time-constrained and is allowed to be taken multiple times // process game public flag: a game might be only public if not being time-constrained and is allowed to be taken multiple times
$game_data["public"] = ($properties["time_limit"] !== 0) || (!$properties["repeatable"]) ? false : $data["public"]; $public = ($properties["time_limit"] !== 0) || (!$properties["repeatable"]) ? false : $data["public"];
$game->setPublic($public);
// update game data // store modifications
update_game($game_data); $game->storeMods();
// re-enable auto-storing
$game->enableAutoStoring();
// update game file if supplied // update game file if supplied
if (isset($_FILES["game_file"])) { if (isset($_FILES["game_file"])) {
@ -354,7 +387,7 @@ function create_update_game(ReqHandler &$rh, array $params): array
$zip = new ZipArchive; $zip = new ZipArchive;
if ($zip->open($file["tmp_name"])) { if ($zip->open($file["tmp_name"])) {
$game_dir = get_game_dir_by_gameid($gameid); // get game directory $game_dir = $game->getGameDir(); // get game directory
//$game_files = glob($game_dir); // get list of existing game files //$game_files = glob($game_dir); // get list of existing game files
// remove former files recursively // remove former files recursively
$dir_iter = new RecursiveDirectoryIterator($game_dir, FilesystemIterator::SKIP_DOTS); $dir_iter = new RecursiveDirectoryIterator($game_dir, FilesystemIterator::SKIP_DOTS);
@ -368,12 +401,12 @@ function create_update_game(ReqHandler &$rh, array $params): array
// search for the CSV table file // search for the CSV table file
$csv_files = glob($game_dir . DIRECTORY_SEPARATOR . "*.csv") ?? []; $csv_files = glob($game_dir . DIRECTORY_SEPARATOR . "*.csv") ?? [];
if (count($csv_files)) { if (count($csv_files) > 0) {
$challenge_import_status = import_challenges_from_csv($csv_files[0], $gameid); $challenge_import_status = $game->importChallengesFromCSV($csv_files[0]);
} }
} }
} else if ($file_type === "csv") { // a plain table was uploaded } else if ($file_type === "csv") { // a plain table was uploaded
$challenge_import_status = import_challenges_from_csv($file["tmp_name"], $gameid); $challenge_import_status = $game->importChallengesFromCSV($file["tmp_name"]);
} }
$result = $challenge_import_status; $result = $challenge_import_status;
} }
@ -386,22 +419,25 @@ function create_update_game(ReqHandler &$rh, array $params): array
function get_all_game_headers(ReqHandler &$rh, array $params): array function get_all_game_headers(ReqHandler &$rh, array $params): array
{ {
global $requester_nickname; global $requester_nickname;
$game_headers = get_all_game_data_by_contributor_nickname($requester_nickname); global $gameMgr;
foreach ($game_headers as &$game_header) { $games = $gameMgr->getAllGameDataByContributor($requester_nickname);
resolve_groupids($game_header["groups"]); $a = [];
foreach ($games as &$game) {
$a[] = $game->toArray();
} }
return $game_headers; return $a;
} }
function get_challenges(ReqHandler &$rh, array $params): string function get_challenges(ReqHandler &$rh, array $params): string
{ {
global $is_quizmaster; global $user;
global $requester_nickname; global $gameMgr;
$gameid = $params["gameid"]; $gameid = $params["gameid"];
$game_data = get_game($gameid); $game = $gameMgr->getGame($gameid);
$result = ""; $result = "";
if ((count($game_data) > 0) && ($is_quizmaster || (is_user_contributor_to_game($gameid, $requester_nickname)))) { if (($game !== null) && ($user->hasQuizmasterPrivilege() || ($game->isUserContributorOrOwner($user->getNickname())))) {
$result = file_get_contents(get_game_file_by_gameid($gameid)); $result = file_get_contents($game->getGameFile());
} }
return $result; return $result;
@ -409,12 +445,14 @@ function get_challenges(ReqHandler &$rh, array $params): string
function delete_games(ReqHandler &$rh, array $params): string function delete_games(ReqHandler &$rh, array $params): string
{ {
global $nickname; global $user;
global $gameMgr;
$gameids = explode_list(trim($params["ids"])); $gameids = explode_list(trim($params["ids"]));
foreach ($gameids as $gameid) { foreach ($gameids as $gameid) {
if (($gameid !== "") && (is_user_owner_of_the_game($gameid, $nickname))) { // only the owner may delete a game $game = $gameMgr->getGame($gameid);
delete_game($gameid); if (($game !== null) && ($game->isUserOwner($user->getNickname()))) { // only the owner may delete a game
$gameMgr->deleteGame($gameid);
} }
} }
@ -423,9 +461,13 @@ function delete_games(ReqHandler &$rh, array $params): string
function export_game_file_csv(ReqHandler &$rh, array $params): string function export_game_file_csv(ReqHandler &$rh, array $params): string
{ {
global $nickname; global $user;
global $gameMgr;
$gameid = trim($params["gameid"]); $gameid = trim($params["gameid"]);
if (($gameid !== "") && is_user_contributor_to_game($gameid, $nickname)) { $game = $gameMgr->getGame($gameid);
if (($game !== null) && ($game->isUserContributorOrOwner($user->getNickname()) || $user->hasQuizmasterPrivilege())) {
$f = tmpfile(); $f = tmpfile();
header("Content-Type: text/csv"); header("Content-Type: text/csv");
header("Content-Disposition: attachment; filename=\"challenges_$gameid.csv\"\r\n"); header("Content-Disposition: attachment; filename=\"challenges_$gameid.csv\"\r\n");
@ -438,16 +480,18 @@ function export_game_file_csv(ReqHandler &$rh, array $params): string
function get_player_results_by_gameid(ReqHandler &$rh, array $params): array function get_player_results_by_gameid(ReqHandler &$rh, array $params): array
{ {
global $nickname; global $gameMgr;
global $is_quizmaster; global $user;
$gameid = trim($params["gameid"]); $gameid = trim($params["gameid"]);
$filter = trim($params["filter"] ?? ""); $filter = trim($params["filter"] ?? "");
$ordering = trim($params["orderby"] ?? ""); $ordering = trim($params["orderby"] ?? "");
$game = $gameMgr->getGame($gameid);
$result = []; $result = [];
if (($gameid !== "") && (is_user_contributor_to_game($gameid, $nickname) || $is_quizmaster)) { if (($game !== null) && ($game->isUserContributorOrOwner($user->getNickname()) || $user->hasQuizmasterPrivilege())) {
$game_results = get_results_by_gameid($gameid, $filter, $ordering, true); $game_results = get_results_by_gameid($gameid, $filter, $ordering, true); // FIXME!!
$result = $game_results; $result = $game_results;
} }
@ -458,7 +502,7 @@ function generate_detailed_game_stats(ReqHandler &$rh, array $params): array
{ {
$testids = json_decode(trim($params["testids"]), true); $testids = json_decode(trim($params["testids"]), true);
$gameid = trim($params["gameid"]); $gameid = trim($params["gameid"]);
$stats = generate_detailed_stats($gameid, $testids); $stats = generate_detailed_stats($gameid, $testids); // FIXME!!!
return $stats; return $stats;
} }
@ -481,6 +525,7 @@ if ($privilege === PRIVILEGE_CREATOR) {
function create_update_group(ReqHandler &$rh, array $params): string function create_update_group(ReqHandler &$rh, array $params): string
{ {
global $user; global $user;
global $groupMgr;
$update = $params[ReqHandler::ACTION_KEY] === "update_group"; $update = $params[ReqHandler::ACTION_KEY] === "update_group";
$groupname = trim($params["groupname"]); $groupname = trim($params["groupname"]);
@ -491,18 +536,23 @@ function create_update_group(ReqHandler &$rh, array $params): string
$result = "FAIL"; $result = "FAIL";
if ($groupname != "") { if ($groupname != "") {
if (!$update) { if (!$update) {
create_group($groupname, $owner, $description); $groupMgr->addGroup($groupname, $owner, $description);
$result = "OK"; $result = "OK";
} else { } else {
$gid = $params["id"]; $gid = $params["id"];
$group = get_group($gid); $group = $groupMgr->getGroup($gid);
if (count($group) !== 0) { if ($group !== null) {
$group["unique"] = manage_unique_in_siblings($gid, $groupname); // manage unique flag in case of renaming $group->disableAutoStoring();
$group["groupname"] = $groupname; $group->setName($groupname);
$group["description"] = $description; $group->setDescription($description);
$group["editors"] = array_intersect($editors, $group["users"]); // a user cannot be an editor if not part of the group $group->setOwner($owner);
$group["owner"] = $owner;
update_group($group); $editors = array_intersect($editors, $group->getMembers()); // a user cannot be an editor if not participant of the group
$group->setEditors($editors);
$group->storeMods();
$group->enableAutoStoring();
$result = "OK"; $result = "OK";
} }
} }
@ -512,21 +562,35 @@ function create_update_group(ReqHandler &$rh, array $params): string
function delete_groups(ReqHandler &$rh, array $params): string function delete_groups(ReqHandler &$rh, array $params): string
{ {
global $groupMgr;
$groups = explode_list($params["ids"] ?? ""); $groups = explode_list($params["ids"] ?? "");
foreach ($groups as $g) { foreach ($groups as $g) {
delete_group($g); $groupMgr->deleteGroup($g);
} }
return "OK"; return "OK";
} }
function get_all_player_groups(ReqHandler &$rh, array $params): array function get_all_player_groups(ReqHandler &$rh, array $params): array
{ {
return get_all_groups(); global $groupMgr;
$groups = $groupMgr->getAllGroups();
$a = [];
foreach ($groups as $g) {
$a[] = $g->toArray();
}
return $a;
} }
function search_player_groups(ReqHandler &$rh, array $params): array function search_player_groups(ReqHandler &$rh, array $params): array
{ {
return search_groups($params["needle"]); global $groupMgr;
$groups = $groupMgr->searchGroups($params["needle"]);
$a = [];
foreach ($groups as $g) {
$a[] = $g->toArray();
}
return $a;
} }
function create_update_user(ReqHandler &$rh, array $params): string function create_update_user(ReqHandler &$rh, array $params): string
@ -540,32 +604,33 @@ function create_update_user(ReqHandler &$rh, array $params): string
$realname = trim($params["realname"]); $realname = trim($params["realname"]);
$privilege = trim($params["privilege"]); $privilege = trim($params["privilege"]);
$groupids = get_groupids_by_compounds($groups); // convert group compounds to _ids // $groupids = get_groupids_by_compounds($groups); // convert group compounds to _ids FIXME!!!
$success = false; $success = false;
if (($target_nickname !== "")) { if (($target_nickname !== "")) {
if ((!$update) && ($password !== "")) { // CREATE if ((!$update) && ($password !== "")) { // CREATE
$success = $userMgr->addUser($target_nickname, $password, $realname, $groupids, $privilege); $success = $userMgr->addUser($target_nickname, $password, $realname, [], $privilege); // FIXME!!!
} else if ($update) { // UPDATE } else if ($update) { // UPDATE
$tuser = $userMgr->getUser($target_nickname); // load user data $tuser = $userMgr->getUser($target_nickname); // load user data
if ($tuser !== null) { if ($tuser !== null) {
// group management // group management FIXME!!!
$old_groupids = $tuser->getGroups(); // retain old groupids // $old_groupids = $tuser->getGroups(); // retain old groupids
$new_groupids = $groupids; // get new groupids // $new_groupids = $groupids; // get new groupids
$groupids_add = array_diff($new_groupids, $old_groupids); // groups this user needs to be added to // $groupids_add = array_diff($new_groupids, $old_groupids); // groups this user needs to be added to
$groupids_remove = array_diff($old_groupids, $new_groupids); // groups this user need to be removed from // $groupids_remove = array_diff($old_groupids, $new_groupids); // groups this user need to be removed from
foreach ($groupids_add as $groupid) { // execute insertion and removal // foreach ($groupids_add as $groupid) { // execute insertion and removal
change_group_user_assignments($groupid, $target_nickname, null); // change_group_user_assignments($groupid, $target_nickname, null);
} // }
foreach ($groupids_remove as $groupid) { // foreach ($groupids_remove as $groupid) {
change_group_user_assignments($groupid, null, $target_nickname); // change_group_user_assignments($groupid, null, $target_nickname);
} // }
// re-fetch user // re-fetch user
//$tuser = get_user($target_nickname); // load user data //$tuser = get_user($target_nickname); // load user data
// further field update // further field update
$tuser->disableAutoStoring();
$tuser->setRealname($realname); $tuser->setRealname($realname);
$tuser->setPrivilege($privilege); $tuser->setPrivilege($privilege);
@ -574,6 +639,9 @@ function create_update_user(ReqHandler &$rh, array $params): string
$tuser->changePassword(password_hash($password, PASSWORD_DEFAULT), "", false); $tuser->changePassword(password_hash($password, PASSWORD_DEFAULT), "", false);
} }
$tuser->storeMods();
$tuser->enableAutoStoring();
$success = true; $success = true;
} }
} }
@ -582,7 +650,8 @@ function create_update_user(ReqHandler &$rh, array $params): string
return $success ? "OK" : "FAIL"; return $success ? "OK" : "FAIL";
} }
function delete_users(ReqHandler &$rh, array $params): string { function delete_users(ReqHandler &$rh, array $params): string
{
global $userMgr; global $userMgr;
$nicknames = explode_list($params["users"]); $nicknames = explode_list($params["users"]);
foreach ($nicknames as $nick) { foreach ($nicknames as $nick) {
@ -591,20 +660,22 @@ function delete_users(ReqHandler &$rh, array $params): string {
return "OK"; return "OK";
} }
function get_all_game_users(ReqHandler &$rh, array $params): array { function get_all_game_users(ReqHandler &$rh, array $params): array
{
global $userMgr; global $userMgr;
$user_data_filtered = []; $user_data_filtered = [];
$all_users = $userMgr->getAllUsers(); $all_users = $userMgr->getAllUsers();
for ($i = 0; $i < count($all_users); $i++) { for ($i = 0; $i < count($all_users); $i++) {
$a = $all_users[$i]->toArray(); // convert user to array $a = $all_users[$i]->toArray(); // convert user to array
unset($a["password"]); // remove password from records unset($a["password"]); // remove password from records
resolve_groupids($a["groups"]); // resolve group IDs resolve_groupids($a["groups"]); // resolve group IDs FIXME!!!!
$user_data_filtered[] = $a; $user_data_filtered[] = $a;
} }
return $user_data_filtered; return $user_data_filtered;
} }
function import_users_from_csv(ReqHandler &$rh, array $params): string { function import_users_from_csv(ReqHandler &$rh, array $params): string
{
if (!isset($_FILES["users_table"])) { if (!isset($_FILES["users_table"])) {
} }
@ -622,7 +693,8 @@ $rh->add("delete_users", ["users"], PRIVILEGE_QUIZMASTER, "delete_users", RESP_P
$rh->add("get_all_users", [], PRIVILEGE_QUIZMASTER, "get_all_game_users", RESP_JSON, "Get all users."); $rh->add("get_all_users", [], PRIVILEGE_QUIZMASTER, "get_all_game_users", RESP_JSON, "Get all users.");
$rh->add("import_users_from_csv", [], PRIVILEGE_QUIZMASTER, "import_users_from_csv", RESP_JSON, "Get all users."); $rh->add("import_users_from_csv", [], PRIVILEGE_QUIZMASTER, "import_users_from_csv", RESP_JSON, "Get all users.");
function test(ReqHandler &$rh, array $params): string { function test(ReqHandler &$rh, array $params): string
{
$usrmgr = new UserMgr(); $usrmgr = new UserMgr();
$nicknames = $usrmgr->getAllNicknames(); $nicknames = $usrmgr->getAllNicknames();
return join(", ", $nicknames); return join(", ", $nicknames);

View File

@ -94,7 +94,7 @@ function create_edit_game(game = null) {
ownerF.value = game["owner"]; ownerF.value = game["owner"];
ownerF.readOnly = false; ownerF.readOnly = false;
contributorsF.value = game["contributors"].join(", "); contributorsF.value = game["contributors"].join(", ");
groupF.value = game["groups"].join(", "); // groupF.value = game["groups"].join(", "); FIXME
publicChk.addEventListener("change", hide_public_url_field); publicChk.addEventListener("change", hide_public_url_field);
publicChk.checked = game["public"]; publicChk.checked = game["public"];

View File

@ -5,4 +5,66 @@ function logout() {
request(req).then(resp => { request(req).then(resp => {
location.href = "login.php"; location.href = "login.php";
}); });
}
function change_password() {
let oldpassF = document.getElementById("old_password");
let newpass1F = document.getElementById("new_password_1");
let newpass2F = document.getElementById("new_password_2");
let oldpass = oldpassF.value;
let newpass1 = newpass1F.value;
let newpass2 = newpass2F.value;
if (newpass1 !== newpass2) {
alert("Az új jelszavak nem egyeznek!");
} else {
let req = {
action: "change_password",
oldpass: oldpass,
newpass: newpass1
}
request(req).then(resp => {
if (resp === "OK") {
alert("Sikeres jelszóváltoztatás!");
hide("change_password_window");
oldpassF.value = "";
newpass1F.value = "";
newpass2F.value = "";
} else {
alert("Sikertelen jelszóváltoztatás!");
}
});
}
}
function change_password() {
let oldpassF = document.getElementById("old_password");
let newpass1F = document.getElementById("new_password_1");
let newpass2F = document.getElementById("new_password_2");
let oldpass = oldpassF.value;
let newpass1 = newpass1F.value;
let newpass2 = newpass2F.value;
if (newpass1 !== newpass2) {
alert("Az új jelszavak nem egyeznek!");
} else {
let req = {
action: "change_password",
oldpass: oldpass,
newpass: newpass1
}
request(req).then(resp => {
if (resp === "OK") {
alert("Sikeres jelszóváltoztatás!");
hide("change_password_window");
oldpassF.value = "";
newpass1F.value = "";
newpass2F.value = "";
} else {
alert("Sikertelen jelszóváltoztatás!");
}
});
}
} }

View File

@ -77,7 +77,9 @@ function assemble_answer_radio_id(challenge_N, answer_N) {
function mark_answers(challenges, view_only = false) { function mark_answers(challenges, view_only = false) {
for (let i = 0; i < challenges.length; i++) { for (let i = 0; i < challenges.length; i++) {
let marked_answerR = document.getElementById(assemble_answer_radio_id(i, challenges[i]["player_answer"])); let marked_answerR = document.getElementById(assemble_answer_radio_id(i, challenges[i]["player_answer"]));
marked_answerR.checked = true; if (marked_answerR !== null) {
marked_answerR.checked = true;
}
} }
} }
@ -146,6 +148,8 @@ function populate_challenges(challenges, concluded, view_only = false, gameid) {
test_display.appendChild(challenge_box); test_display.appendChild(challenge_box);
}); });
mark_answers(challenges, view_only);
MathJax.typeset(); MathJax.typeset();
} }

View File

@ -22,6 +22,7 @@ $privilege = $user_data["privilege"];
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0'> <meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0'>
<title>SpreadQuiz</title> <title>SpreadQuiz</title>
<script src="js/o.js"></script>
<script src="js/req.js"></script> <script src="js/req.js"></script>
<script src="js/main.js"></script> <script src="js/main.js"></script>
<script src="js/spreadquiz.js"></script> <script src="js/spreadquiz.js"></script>
@ -40,7 +41,7 @@ $privilege = $user_data["privilege"];
<php? if ($privilege === PRIVILEGE_QUIZMASTER) { ?> <php? if ($privilege === PRIVILEGE_QUIZMASTER) { ?>
<span style="font-size: 10pt;"><?= $_COOKIE[SESSION_NAME] ?></span><br> <span style="font-size: 10pt;"><?= $_COOKIE[SESSION_NAME] ?></span><br>
<php? } ?> <php? } ?>
<input type="button" value="Beállítások"><br> <input type="button" value="Jelszóváltoztatás" onclick="show('change_password_window')"><br>
<input type="button" value="Kijelentkezés" onclick="logout()"> <input type="button" value="Kijelentkezés" onclick="logout()">
</section> </section>
</section> </section>
@ -57,6 +58,28 @@ $privilege = $user_data["privilege"];
<?php } ?> <?php } ?>
</section> </section>
</section> </section>
<section class="window" shown="false" id="change_password_window">
<section class="window-inner">
<section>
<table>
<tr>
<td><label for="old_password">Aktuális jelszó:</label></td>
<td><input type="password" id="old_password"></td>
</tr>
<tr>
<td><label for="new_password_1">Új jelszó:</label></td>
<td><input type="password" id="new_password_1"></td>
</tr>
<tr>
<td><label for="new_password_2">...mégegyszer:</label></td>
<td><input type="password" id="new_password_2"></td>
</tr>
</table>
</section>
<input type="button" value="Mentés" onclick="change_password()">
<input type="button" value="Mégse" onclick="hide('change_password_window')">
</section>
</section>
</body> </body>
</html> </html>
<?php } ?> <?php } ?>

11
maintenance.html Normal file
View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>SpreadQuiz :: Karbantartás</title>
</head>
<body>
<img src="media/maintenance.png" width="180">
<h3> Az oldal karbantartás alatt áll!</h3>
</body>
</html>

View File

@ -72,4 +72,8 @@
padding: 1em; padding: 1em;
max-height: calc(100vh - 2em); max-height: calc(100vh - 2em);
} }
td {
display: block;
}
} }