From ab0734519594848d79f7dc6d4d0bbd552b0974f1 Mon Sep 17 00:00:00 2001 From: Epagris Date: Tue, 17 Sep 2024 14:49:59 +0200 Subject: [PATCH] - GroupMgr OO implementation --- class/GameMgr.php | 13 ++ class/GroupMgr.php | 350 +++++++++++++++++++++++++++++++++++++++++++++ class/UserMgr.php | 47 +++--- groupmgr.php | 14 -- interface.php | 2 +- 5 files changed, 387 insertions(+), 39 deletions(-) create mode 100644 class/GameMgr.php create mode 100644 class/GroupMgr.php diff --git a/class/GameMgr.php b/class/GameMgr.php new file mode 100644 index 0000000..10030c1 --- /dev/null +++ b/class/GameMgr.php @@ -0,0 +1,13 @@ +groupMgr->updateGroup($this); + } + + // -------------- + + function __construct(GroupMgr &$groupMgr, string $name, string $description, string $owner, int $id = -1, bool $unique = true, array $editors = [], array $members = [], array $games = []) + { + $this->_id = $id; + $this->name = $name; + $this->unique = $unique; + $this->description = $description; + $this->owner = $owner; + $this->editors = $editors; + $this->members = $members; + $this->games = $games; + $this->groupMgr = &$groupMgr; + } + + // Create Group from array + 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"]); + } + + // Convert Group to array + function toArray(array $omit = []): array + { + $a = [ + "_id" => $this->_id, + "groupname" => $this->name, + "unique" => $this->unique, + "description" => $this->description, + "owner" => $this->owner, + "editors" => $this->editors, + "members" => $this->members, + "games" => $this->games + ]; + + foreach ($omit as $field) { + unset($a[$field]); + } + + return $a; + } + + // Get group's ID. + function getID() : int + { + return $this->_id; + } + + // Get group's name. + function getName() : string + { + return $this->name; + } + + // Set group's name. + function setName(string $name) : void { + $this->name = $name; + $this->storeMods(); + } + + // Tell if group is unique + function isUnique() : bool { + return $this->unique; + } + + // Get group's description. + function getDescription() : string { + return $this->description; + } + + // Set group's description. + function setDescription(string $description) : void { + $this->description = $description; + $this->storeMods(); + } + + // Get group's owner. + function getOwner() : string { + return $this->owner; + } + + // Set group's owner. + function setOwner(string $owner) : void { + $this->owner = $owner; + $this->storeMods(); + } + + // Get list of editors. + function getEditors() : array { + return $this->editors; + } + + // Set editors. + function setEditors(array $editors) : void { + $this->editors = $editors; + $this->storeMods(); + } + + // Get group members. + function getMembers() : array { + return $this->members; + } + + // Set group members. + function setMembers(array $members) : void { + $this->members = $members; + $this->storeMods(); + } + + // Get games. + function getGames() : array { + return $this->games; + } + + // Set games. + function setGames(array $games) : void { + $this->games = $games; + $this->storeMods(); + } + + // Include/exclude members. + function changeMembers(array $nicknames_add, array $nicknames_remove): void + { + foreach ($nicknames_add as $nickname) { // add members + alter_array_contents($this->members, $nickname, null); + } + foreach ($nicknames_remove as $nickname) { // remove members + alter_array_contents($this->members, null, $nickname); // delete from members + alter_array_contents($this->editors, null, $nickname); // delete from editors + } + + $this->storeMods(); // store changes + } + + // Include/exclude games. + function changeGames(array $gameids_add, array $gameids_remove): void + { + foreach ($gameids_add as $gameid) { // add games + alter_array_contents($this->games, $gameid, null); + } + foreach ($gameids_remove as $gameid) { // remove games + alter_array_contents($this->members, null, $gameid); + } + + $this->storeMods(); // store changes + } + + // Returns whether the user is an editor of this group. + function isUserEditor(string $nickname): bool { + return in_array($nickname, $this->editors); + } + + // Returns whether the user is an editor or the owner of the group. + function isUserContributor(string $nickname): bool { + return $this->isUserEditor($nickname) || ($this->owner === $nickname); + } + + // Returns if user is member of the group. + function isMember(string $nickname): bool + { + return in_array($nickname, $this->members); + } + + // Return if game is assigned to this group. + function isGameAssigned(string $gameid): bool + { + return in_array($gameid, $this->games); + } + + // Get groups unique name. + function getUniqueName() : string + { + return $this->name . ($this->unique ? "" : ("#" . $this->_id)); + } +} + +class GroupMgr +{ + private \SleekDB\Store $db; // database + + // ------------------------- + + private function manageTwins(int $current_group_id, string $groupname): bool { + // make test on name uniqueness + $twins = $this->db->findBy([["groupname", "=", "$groupname"], "AND", ["_id", "!=", $current_group_id]]); + $unique = count($twins) == 0; + if (count($twins) === 1) { // if fails, then also indicate in the original group that its name is no longer unique + $twins[0]["unique"] = false; + $this->db->update($twins[0]); // UPDATE WITHOUT CONVERTING TO GROUP OBJECT!! BE CAREFUL! + } + return $unique; + } + + // ------------------------- + + function __construct() + { + $this->db = new \SleekDB\Store(GROUPDB, DATADIR, ["timeout" => false]); + } + + // Get group by ID. + function getGroup(string $groupid): Group|null + { + $group_data_array = $this->db->findById($groupid); + return count($group_data_array) != 0 ? Group::fromArray($this, $group_data_array[0]) : null; + } + + // Update group. + function updateGroup(Group $group): void + { + $a = $group->toArray(); + $this->db->update($a); + } + + // Add a new group. + function addGroup(string $groupname, string $owner, string $description = ""): bool { + // test name uniqueness + $unique = $this->manageTwins(0, $groupname); + + // initialize group data + $group_data = [ + "groupname" => $groupname, + "unique" => $unique, + "owner" => $owner, + "description" => $description, + "editors" => [], + "members" => [], + "games" => [] + ]; + + $group = Group::fromArray($this, $group_data); // create group + + $this->db->insert($group->toArray(["_id"])); // insert group + return true; + } + + // Delete group. + function deleteGroup(string $groupid): void + { + $group = $this->getGroup($groupid); + if ($group != null) { + $this->db->deleteById($groupid); + } + } + + // Get all groups. + function getAllGroups(): array + { + return array_map(fn($a): Group => Group::fromArray($this, $a), $this->db->findAll()); + } + + // Search groups. + function searchGroups(string $needle, bool $infoOnly = true): array + { + if (strlen($needle) < 3) { + return []; + } + $parts = explode("#", $needle, 2); + $groupname = $parts[0]; + $group_data_array = []; + if (count($parts) === 1) { + $group_data_array = $this->db->findBy(["groupname", "LIKE", "%$groupname%"]); + } else if (count($parts) > 1) { + $groupid = $parts[1]; + $group_data_array = $this->db->findBy([["groupname", "LIKE", "%$groupname%"], "AND", ["_id", "LIKE", "%$groupid%"]]); + } + + $results = []; + foreach ($group_data_array as $group_data) { + if ($infoOnly) { + $results[] = [ + "groupname" => $group_data["groupname"], + "_id" => $group_data["_id"], + "unique" => $group_data["unique"] + ]; + } else { + $results[] = Group::fromArray($this, $group_data); + } + } + return $results; + } + + // Get group IDs by the group compounds (name#ID). + function getGroupIdsByCompounds(array $compounds): array + { + $groupids = []; + foreach ($compounds as $compound) { + if (trim($compound) === "") { // skip empty entries + continue; + } + + // fetch the group + $parts = explode("#", $compound); + $group_data = []; + if (count($parts) === 1) { + $fetch_cmd = ["groupname", "=", $parts[0]]; + $group_data = $this->db->findBy($fetch_cmd); + if (count($group_data) == 1) { // too many hits + $group_data = $group_data[0]; + } else { + $group_data = []; + } + } else { + $group_data = $this->db->findById($parts[1]); + } + if ($group_data !== []) { + $groupids[] = $group_data["_id"]; + } + } + return $groupids; + } + + // cache for converting group ID's to unique group names + private array $groupid_cache = []; + + // Convert group IDs into unique group names IN PLACE! + function resolveGroupIds(array &$groupids): void { + foreach ($groupids as &$groupid) { + if (array_key_exists($groupid, $this->groupid_cache)) { + $group = $this->getGroup($groupid); // fetch group + $unique_name = $group->getUniqueName(); // get group's unique name + $this->groupid_cache[$groupid] = $unique_name; // store into the cache so that subsequent queries will be somewhat faster + } + + $groupid = $this->groupid_cache[$groupid]; // replace with the unique name + } + } +} \ No newline at end of file diff --git a/class/UserMgr.php b/class/UserMgr.php index e286b6d..46a640f 100644 --- a/class/UserMgr.php +++ b/class/UserMgr.php @@ -22,24 +22,14 @@ class User // ------------------------------------------- - function __construct(UserMgr &$usrmgr, int|array $id_serialized, 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) { - if (is_array($id_serialized)) { - $init = $id_serialized; - $this->id = $id_serialized["_id"] ?? "-1"; - $this->nickname = $init["nickname"]; - $this->password = $init["password"]; - $this->realname = $init["realname"]; - $this->groups = $init["groups"]; - $this->privilege = $init["privilege"]; - } else { - $this->id = $id_serialized; - $this->nickname = $nickname; - $this->password = $password; - $this->realname = $realname; - $this->groups = $groups; - $this->privilege = $privilege; - } + $this->id = $id; + $this->nickname = $nickname; + $this->password = $password; + $this->realname = $realname; + $this->groups = $groups; + $this->privilege = $privilege; // save reference to user manager $this->userMgr = &$usrmgr; @@ -48,7 +38,8 @@ class User // Create user from an array static function fromArray(UserMgr &$usrmgr, array $a): User { - return new User($usrmgr, $a); + $id = $a["id"] ?? -1; + return new User($usrmgr, $id, $a["nickname"], $a["password"], $a["realname"], $a["groups"], $a["privilege"]); } // Convert user to array @@ -116,12 +107,14 @@ class User } // Set user's real name. - function setRealname(string $realname): void { + function setRealname(string $realname): void + { $this->realname = $realname; } // Get user's real name. - function getRealname(): string { + function getRealname(): string + { return $this->realname; } @@ -130,6 +123,11 @@ class User { return password_verify($password, $this->password); } + + // Has the user quizmaster privileges? + function hasQuizmasterPrivilege(): bool { + return $this->privilege == PRIVILEGE_QUIZMASTER; + } } class UserMgr @@ -146,7 +144,7 @@ class UserMgr function getUser(string $nickname): User|null { $user_data_array = $this->db->findBy(["nickname", "=", $nickname]); - return count($user_data_array) != 0 ? new User($this, $user_data_array[0]) : null; + return count($user_data_array) != 0 ? User::fromArray($this, $user_data_array[0]) : null; } // Update user. @@ -157,7 +155,8 @@ class UserMgr } // checks if a nickname is taken - function isNicknameTaken(string $nickname): bool { + function isNicknameTaken(string $nickname): bool + { return !($this->db->findOneBy(["nickname", "=", $nickname]) == null); } @@ -177,7 +176,7 @@ class UserMgr ]; // create user object - $user = new User($this, $a); + $user = User::fromArray($this, $a); // add user to specific groups FIXME!!!! foreach ($groupids as $groupid) { @@ -209,7 +208,7 @@ class UserMgr // Dump all users. Users come wrapped in User objects. function getAllUsers(): array { - return array_map(fn($a): User => new User($this, $a), $this->db->findAll()); + return array_map(fn($a): User => User::fromArray($this, $a), $this->db->findAll()); } // Get all nicknames. diff --git a/groupmgr.php b/groupmgr.php index b5ecee8..0edbc0c 100644 --- a/groupmgr.php +++ b/groupmgr.php @@ -10,21 +10,7 @@ function create_group(string $groupname, string $owner, string $description = "" { 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; } function get_group(string $groupid): array diff --git a/interface.php b/interface.php index 9341189..c14fa62 100644 --- a/interface.php +++ b/interface.php @@ -331,7 +331,7 @@ function create_update_game(ReqHandler &$rh, array $params): array $game_data["owner"] = $owner; } - $game_data["contributors"] = array_intersect($contributors, $usrMgr->getAllNicknames()); + $game_data["contributors"] = array_intersect($contributors, $userMgr->getAllNicknames()); $game_data["properties"]["time_limit"] = $properties["time_limit"]; $game_data["properties"]["repeatable"] = $properties["repeatable"];