SpreadQuiz/class/GroupMgr.php
2025-09-30 22:44:06 +02:00

210 lines
6.9 KiB
PHP

<?php
require_once "vendor/autoload.php";
require_once "AutoStoring.php";
require_once "privilege_levels.php";
require_once "Group.php";
class GroupMgr
{
private \SleekDB\Store $db; // database
// -------------------------
public 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) : 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" => [],
"users" => [],
"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
}
}
// Check if a user has access to a game, i.e. there's at least a single group that contains both the user and the game.
function doesUserAccessGame(string $gameid, string $nickname): bool {
$intersection = $this->db->findOneBy([["games", "CONTAINS", (int)$gameid], "AND", ["users", "CONTAINS", $nickname]]);
return $intersection !== null;
}
// Get user's groups IDs.
function getUserGroupIDs(string $nickname) : array {
$qb = $this->db->createQueryBuilder();
$a = $qb->where(["users", "CONTAINS", $nickname])->select(["_id"])->getQuery()->fetch();
return array_map(fn($r) => $r["_id"], $a);
}
// Get game's group IDs.
function getGameGroupIDs(string $gameid) : array {
$qb = $this->db->createQueryBuilder();
$a = $qb->where(["games", "CONTAINS", (int)$gameid])->select(["_id"])->getQuery()->fetch();
return array_map(fn($r) => $r["_id"], $a);
}
// Get group by group compound (name#id).
function getGroupByUniqueName(string $uniqueName): Group|null {
$a = $this->db->findOneBy([ function($g) use ($uniqueName) : bool {
$group = Group::fromArray($this, $g);
return $group->getUniqueName() === $uniqueName;
}]);
if ($a !== null) {
return Group::fromArray($this, $a);
} else {
return null;
}
}
// Get the union of all members in the groups specified
function getJoinedMembersByUniqueNames(array $uniqueNames) : array {
$nicknames = [];
foreach ($uniqueNames as $uniqueName) {
$group = $this->getGroupByUniqueName($uniqueName);
if ($group !== null) {
$nicknames = array_merge($nicknames, $group->getMembers());
}
}
return $nicknames;
}
}