diff --git a/gamemgr.php b/gamemgr.php index 5a41b9b..e33ef15 100644 --- a/gamemgr.php +++ b/gamemgr.php @@ -90,7 +90,7 @@ function get_all_games() function patch_up_game_data(array &$game_data) { - $game_version = $game_data["version"] ?: 0; + $game_version = $game_data["version"] ?? 0; if ($game_version < 2) { // update to game version 2 if (!key_exists("public_id", $game_data)) { $game_data["public"] = false; diff --git a/globals.php b/globals.php index 6981379..7ff05c3 100644 --- a/globals.php +++ b/globals.php @@ -15,6 +15,8 @@ const LOGIN_URL = "login.php"; const MAIN_URL = "main.php"; const SESSION_NAME = "spreadquiz_sid"; +const MISSING_IMAGE_PLACEHOLDER = "media/image-missing_120px.png"; + session_name(SESSION_NAME); // autoload session diff --git a/groupmgr.php b/groupmgr.php index bb467a6..b5ecee8 100644 --- a/groupmgr.php +++ b/groupmgr.php @@ -63,7 +63,7 @@ function change_group_user_assignments(string $groupid, $nickname_add, $nickname if (count($group_data) != 0) { // --------- UPDATE group assignments (DEV ONLY!)------ - $group_data["editors"] = $group_data["editors"] ?: []; + $group_data["editors"] = $group_data["editors"] ?? []; // --------- diff --git a/interface.php b/interface.php index a7b69b6..ff9435e 100644 --- a/interface.php +++ b/interface.php @@ -22,7 +22,6 @@ require_once "testmgr.php"; require_once "controller.php"; -const MISSING_IMAGE_PLACEHOLDER = "media/image-missing_120px.png"; function patch_through_image(string $gameid, string $img_url) { $game_dir = get_game_dir_by_gameid($gameid); @@ -105,14 +104,14 @@ switch ($action) { break; case "start_or_continue_test": { - $gameid = trim($_REQUEST["gameid"] ?: ""); + $gameid = trim($_REQUEST["gameid"] ?? ""); $testid = create_or_continue_test($gameid, $nickname); $result = $testid; } break; case "get_results_overview": { - $gameid = trim($_REQUEST["gameid"] ?: ""); + $gameid = trim($_REQUEST["gameid"] ?? ""); $concluded_tests = get_concluded_tests($gameid, $nickname); $overviews = []; foreach ($concluded_tests as $ct) { @@ -130,50 +129,56 @@ switch ($action) { } // test-related queries -$is_a_default_test_with_access = isset($_REQUEST["testid"]) && (($testid = trim($_REQUEST["testid"])) !== "") && - ((count($test_data = get_test($testid))) > 0) && (($test_data["nickname"] === $nickname)); +const TEST_RELATED_ACTIONS = ["get_test", "save_answer", "submit_test"]; +if (in_array($action, TEST_RELATED_ACTIONS)) { -$user_is_contributor_or_quizmaster = $is_quizmaster || is_user_contributor_to_game($test_data["gameid"], $nickname); + $testid = trim($_REQUEST["testid"] ?? ""); + $test_data = ($testid !== "") ? get_test($testid) : []; + $is_a_default_test_with_access = ($testid !== "") && ((count($test_data)) > 0) && (($test_data["nickname"] === $nickname)); -if ($is_a_default_test_with_access || $user_is_contributor_or_quizmaster) { + $user_is_contributor_or_quizmaster = $is_quizmaster || is_user_contributor_to_game($test_data["gameid"], $nickname); - // update the test if timed - update_timed_tests([$test_data]); + if ($is_a_default_test_with_access || $user_is_contributor_or_quizmaster) { - switch ($action) { - case "get_test": - { - $test_data_with_current_time = $test_data; - $test_data_with_current_time["current_time"] = time(); - $result = json_encode($test_data_with_current_time); - } - break; - case "save_answer": - { - $chidx = $_REQUEST["challenge_index"]; - $answeridx = $_REQUEST["answer_index"]; - save_answer($testid, $chidx, $answeridx); - } - break; - case "submit_test": - { - conclude_test($testid); - } - break; - } -} + // update the test if timed + update_timed_tests([$test_data]); -// $user_has_access_to_game = does_user_access_game($nickname, $gameid); - -// get_image needs special treatment -if ($action === "get_image") { - if ($is_a_default_test_with_access || $user_is_contributor_or_quizmaster) { // default case - $img_url = trim($_REQUEST["img_url"] ?: ""); - if ($img_url !== "") { - $gameid = $test_data["gameid"]; - patch_through_image($gameid, $img_url); + switch ($action) { + case "get_test": + { + $test_data_with_current_time = $test_data; + $test_data_with_current_time["current_time"] = time(); + $result = json_encode($test_data_with_current_time); + } + break; + case "save_answer": + { + $chidx = $_REQUEST["challenge_index"]; + $answeridx = $_REQUEST["answer_index"]; + save_answer($testid, $chidx, $answeridx); + } + break; + case "submit_test": + { + conclude_test($testid); + } + break; } } + + // $user_has_access_to_game = does_user_access_game($nickname, $gameid); + + // get_image needs special treatment + if ($action === "get_image") { + if ($is_a_default_test_with_access || $user_is_contributor_or_quizmaster) { // default case + $img_url = trim($_REQUEST["img_url"] ?? ""); + if ($img_url !== "") { + $gameid = $_REQUEST["gameid"]; + patch_through_image($gameid, $img_url); + } + } + } + } // creator or quizmaster actions @@ -188,17 +193,17 @@ switch ($action) { case "update_game": { $update = $action === "update_game"; - $data = json_decode($_REQUEST["data"], true) ?: []; - if (($data === []) || (trim($data["name"] ?: "") === "")) { // no further processing + $data = json_decode($_REQUEST["data"], true) ?? []; + if (($data === []) || (trim($data["name"] ?? "") === "")) { // no further processing goto print_result; // ~exit... } $gameid = $data["_id"]; $name = $data["name"]; $description = $data["description"]; - $contributors = explode_list($data["contributors"] ?: ""); - $owner = $update ? trim($data["owner"] ?: $nickname) : $nickname; - $groups = explode_list($data["groups"] ?: ""); - $properties = $data["properties"] ?: []; + $contributors = explode_list($data["contributors"] ?? ""); + $owner = $update ? trim($data["owner"] ?? $nickname) : $nickname; + $groups = explode_list($data["groups"] ?? ""); + $properties = $data["properties"] ?? []; $groupids = get_groupids_by_compounds($groups); // convert group compounds to _ids @@ -277,7 +282,7 @@ switch ($action) { $zip->extractTo($game_dir . DIRECTORY_SEPARATOR); // 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)) { $challenge_import_status = import_challenges_from_csv($csv_files[0], $gameid); } @@ -302,7 +307,7 @@ switch ($action) { break; case "get_challenges": { - $gameid = ($_REQUEST["gameid"] ?: ""); + $gameid = ($_REQUEST["gameid"] ?? ""); $game_data = get_game($gameid); if ((count($game_data) > 0) && ($is_quizmaster || (is_user_contributor_to_game($gameid, $requester_nickname)))) { $result = file_get_contents(get_game_file_by_gameid($gameid)); @@ -311,7 +316,7 @@ switch ($action) { break; case "delete_games": { - $gameids = explode_list(trim($_REQUEST["ids"] ?: "")); + $gameids = explode_list(trim($_REQUEST["ids"] ?? "")); foreach ($gameids as $gameid) { if (($gameid !== "") && (is_user_owner_of_the_game($gameid, $nickname))) { // only the owner may delete a game delete_game($gameid); @@ -321,7 +326,7 @@ switch ($action) { break; case "export_game_file_csv": { - $gameid = trim($_REQUEST["gameid"] ?: ""); + $gameid = trim($_REQUEST["gameid"] ?? ""); if (($gameid !== "") && is_user_contributor_to_game($gameid, $nickname)) { $f = tmpfile(); header("Content-Type: text/csv"); @@ -334,9 +339,9 @@ switch ($action) { break; case "get_results_by_gameid": { - $gameid = trim($_REQUEST["gameid"] ?: ""); - $filter = trim($_REQUEST["filter"] ?: ""); - $ordering = trim($_REQUEST["orderby"] ?: ""); + $gameid = trim($_REQUEST["gameid"] ?? ""); + $filter = trim($_REQUEST["filter"] ?? ""); + $ordering = trim($_REQUEST["orderby"] ?? ""); if (($gameid !== "") && (is_user_contributor_to_game($gameid, $nickname) || $is_quizmaster)) { $game_results = get_results_by_gameid($gameid, $filter, $ordering, true); $result = json_encode($game_results); @@ -345,20 +350,20 @@ switch ($action) { break; case "generate_detailed_stats": { - $testids = json_decode(trim($_REQUEST["testids"] ?: "[]"), true); - $gameid = trim($_REQUEST["gameid"] ?: ""); + $testids = json_decode(trim($_REQUEST["testids"] ?? "[]"), true); + $gameid = trim($_REQUEST["gameid"] ?? ""); $stats = generate_detailed_stats($gameid, $testids); $result = json_encode($stats); } break; - case "get_image": - { - $gameid = trim($_REQUEST["gameid"] ?: ""); - $img_url = trim($_REQUEST["img_url"] ?: ""); - patch_through_image($gameid, $img_url); - } - break; +// case "get_image": +// { +// $gameid = trim($_REQUEST["gameid"] ?? ""); +// $img_url = trim($_REQUEST["img_url"] ?? ""); +// patch_through_image($gameid, $img_url); +// } +// break; } // quizmaster actions @@ -371,9 +376,9 @@ switch ($action) { case "update_group": { $update = $action === "update_group"; - $groupname = trim($_REQUEST["groupname"] ?: ""); - $description = trim($_REQUEST["description"] ?: ""); - $editors = explode_list(trim($_REQUEST["editors"] ?: "")); + $groupname = trim($_REQUEST["groupname"] ?? ""); + $description = trim($_REQUEST["description"] ?? ""); + $editors = explode_list(trim($_REQUEST["editors"] ?? "")); $owner = (!$update) ? $user_data["nickname"] : trim($_REQUEST["owner"]); if ($owner === "") { $owner = $user_data["nickname"]; @@ -404,7 +409,7 @@ switch ($action) { break; case "delete_groups": { - $groups = explode_list($_REQUEST["ids"] ?: ""); + $groups = explode_list($_REQUEST["ids"] ?? ""); foreach ($groups as $g) { delete_group($g); } @@ -415,7 +420,7 @@ switch ($action) { break; case "search_groups": { - $needle = $_REQUEST["needle"] ?: ""; + $needle = $_REQUEST["needle"] ?? ""; $result = json_encode(search_groups($needle)); } break; @@ -423,11 +428,11 @@ switch ($action) { case "update_user": { $update = $action === "update_user"; - $target_nickname = trim($_REQUEST["nickname"] ?: ""); - $password = trim($_REQUEST["password"] ?: ""); - $groups = explode_list($_REQUEST["groups"] ?: ""); - $realname = trim($_REQUEST["realname"] ?: ""); - $privilege = trim($_REQUEST["privilege"] ?: PRIVILEGE_PLAYER); + $target_nickname = trim($_REQUEST["nickname"] ?? ""); + $password = trim($_REQUEST["password"] ?? ""); + $groups = explode_list($_REQUEST["groups"] ?? ""); + $realname = trim($_REQUEST["realname"] ?? ""); + $privilege = trim($_REQUEST["privilege"] ?? PRIVILEGE_PLAYER); $groupids = get_groupids_by_compounds($groups); // convert group compounds to _ids @@ -469,7 +474,7 @@ switch ($action) { break; case "delete_users": { - $users = explode_list($_REQUEST["users"] ?: ""); + $users = explode_list($_REQUEST["users"] ?? ""); foreach ($users as $g) { delete_user($g); } diff --git a/js/common.js b/js/common.js index cf616b9..4b2e6a3 100644 --- a/js/common.js +++ b/js/common.js @@ -1,7 +1,11 @@ -function unix_time_to_human_readable(tunix, date_delim = ". ") { +function unix_time_to_human_readable(tunix) { const date = new Date(Number(tunix) * 1000); - return date.getFullYear() + date_delim + String(date.getMonth() + 1).padStart(2, "0") + date_delim + String(date.getDate()).padStart(2, "0") + ". " - + String(date.getHours()).padStart(2, "0") + ":" + String(date.getMinutes()).padStart(2, "0") + ":" + String(date.getSeconds()).padStart(2, "0"); + return date.getFullYear() + "-" + String(date.getMonth() + 1).padStart(2, "0") + "-" + String(date.getDate()).padStart(2, "0") + " " + + String(date.getHours()).padStart(2, "0") + ":" + String(date.getMinutes()).padStart(2, "0") + ":" + String(date.getSeconds()).padStart(2, "0"); +} + +function human_readable_to_unix_time(hrtime) { + return (new Date(hrtime)).getTime() / 1000; } function seconds_to_time(s) { diff --git a/js/result_analyzer.js b/js/result_analyzer.js index 5044709..6160123 100644 --- a/js/result_analyzer.js +++ b/js/result_analyzer.js @@ -4,15 +4,46 @@ function create_cell(content = "") { return cell; } +function autoconvert_datetime(str) { + // preprocess time fields in filter string + const dateTimeRE = /([0-9]{4}-[0-1][0-9]-[0-3][0-9] [0-2][0-9]:[0-5][0-9]:[0-5][0-9])/; + let filterParts = str.split(dateTimeRE); + + // First, process full datetime entries + // datetime values will be at the odd indices + for (let i = 1; i < filterParts.length; i += 2) { + filterParts[i] = human_readable_to_unix_time(filterParts[i]); + } + + // join the surrounding and converted parts + let filter = filterParts.join(""); + + // Now, process the only date parts + const dateRE = /([0-9]{4}-[0-1][0-9]-[0-3][0-9])/; + filterParts = filter.split(dateRE); + + for (let i = 1; i < filterParts.length; i += 2) { + filterParts[i] = human_readable_to_unix_time(filterParts[i] + " 00:00:00"); + } + + filter = filterParts.join(""); + + return filter; +} + function fetch_results() { let filterF = document.getElementById("filter"); let orderbyF = document.getElementById("orderby"); + let filter = autoconvert_datetime(filterF.value.trim()); + + // ---------- + let req = { action: "get_results_by_gameid", gameid: GAMEID, - filter: filterF.value.trim(), + filter: filter.trim(), orderby: orderbyF.value.trim() }; diff --git a/result_analyzer.php b/result_analyzer.php index bc7d779..44b62ae 100644 --- a/result_analyzer.php +++ b/result_analyzer.php @@ -36,6 +36,11 @@ if (!is_user_contributor_to_game($game_id, $user_data["nickname"]) && ($user_dat + diff --git a/testground.php b/testground.php index bc1f92e..ba052c3 100644 --- a/testground.php +++ b/testground.php @@ -8,9 +8,9 @@ if (!get_autologin_state() || !isset($_REQUEST["testid"])) { exit(); } -$testid = trim($_REQUEST["testid"] ?: ""); -$view_only = trim($_REQUEST["view_only"] ?: "false") === "true" ? true : false; -$gameid = trim($_REQUEST["gameid"] ?: ""); +$testid = trim($_REQUEST["testid"] ?? ""); +$view_only = trim($_REQUEST["view_only"] ?? "false") === "true"; +$gameid = trim($_REQUEST["gameid"] ?? ""); if ($testid === "") { exit(); diff --git a/testmgr.php b/testmgr.php index 02b8ab7..133214e 100644 --- a/testmgr.php +++ b/testmgr.php @@ -187,8 +187,6 @@ function automatic_typecast(string $rval) } else { // is it a float? return (double)$rval; } - } elseif (str_starts_with($rval, 'T')) { // is it a date/time value? - return strtotime(substr($rval, 1)); // convert to UNIX timestamp } else { // it's a string return substr($rval, 1, strlen($rval) - 2); // strip leading and trailing quotes }