431 lines
13 KiB
PHP
431 lines
13 KiB
PHP
<?php
|
|
|
|
require_once "vendor/autoload.php";
|
|
|
|
require_once "AutoStoring.php";
|
|
|
|
require_once "privilege_levels.php";
|
|
|
|
class Group extends AutoStoring
|
|
{
|
|
private int $_id; // Group's ID (assigned by SleekDB)
|
|
private string $name; // Group's name
|
|
private bool $unique; // Indicates if name is unique or not
|
|
private string $owner; // Group owner's nickname
|
|
private string $description; // Group description
|
|
private array $editors; // Nicknames of users able to manage the group
|
|
private array $members; // Nickname of group members
|
|
private array $games; // Game IDs assigned to this group
|
|
private GroupMgr $groupMgr; // Reference to GroupMgr object managing this group
|
|
|
|
// --------------
|
|
|
|
// store modifications to the database
|
|
public function storeMods() : void
|
|
{
|
|
$this->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 = [])
|
|
{
|
|
parent::__construct();
|
|
|
|
$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
|
|
{
|
|
$id = $a["_id"] ?? -1;
|
|
return new Group($groupMgr, $a["groupname"], $a["description"], $a["owner"], $id, $a["unique"], $a["editors"], $a["users"], $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,
|
|
"users" => $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
|
|
}
|
|
|
|
// Add members
|
|
function addMembers(array $nicknames) : void {
|
|
$this->changeMembers($nicknames, []);
|
|
}
|
|
|
|
// Remove members
|
|
function removeMembers(array $nicknames) : void {
|
|
$this->changeMembers([], $nicknames);
|
|
}
|
|
|
|
// 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
|
|
|
|
// -------------------------
|
|
|
|
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;
|
|
}
|
|
} |