leilukin-tumbleblog/includes/model/Group.php

380 lines
12 KiB
PHP
Raw Normal View History

2024-06-20 14:10:42 +00:00
<?php
/**
* Class: Group
* The Group model.
*
* See Also:
* <Model>
*/
class Group extends Model {
public $has_many = "users";
# Integer: $size
# The number of users in the group.
private $size;
/**
* Function: __construct
*
* See Also:
* <Model::grab>
*/
public function __construct($group_id = null, $options = array()) {
$options["left_join"][] = array(
"table" => "permissions",
"where" => "group_id = groups.id"
);
$options["select"][] = "groups.*";
$options["select"][] = "permissions.id AS permissions";
parent::grab($this, $group_id, $options);
$this->permissions = (array) oneof($this->permissions, array());
if ($this->no_results)
return;
Trigger::current()->filter($this, "group");
}
/**
* Function: find
*
* See Also:
* <Model::search>
*/
public static function find(
$options = array(),
$options_for_object = array()
): array {
$options["left_join"][] = array(
"table" => "permissions",
"where" => "group_id = groups.id"
);
$options["select"][] = "groups.*";
$options["select"][] = "permissions.id AS permissions";
return parent::search(
self::class,
$options,
$options_for_object
);
}
/**
* Function: can
* Checks if the group can perform the specified actions.
*
* Parameters:
* $permissions - Permissions to check, as separate args.
*
* Returns:
* @true@ or @false@
*
* Notes:
* If the last arg is <true>, logic is "and", otherwise "or".
*/
public function can(): bool {
if ($this->no_results)
return false;
$actions = func_get_args();
if (end($actions) !== true) {
# OR comparison
foreach ($actions as $action) {
if (in_array($action, $this->permissions))
return true;
}
return false;
} else {
# AND comparison
array_pop($actions);
foreach ($actions as $action) {
if (!in_array($action, $this->permissions))
return false;
}
return true;
}
}
/**
* Function: add
* Adds a group to the database.
*
* Parameters:
* $name - The group's name
* $permissions - An array of the permissions (IDs).
*
* Returns:
* The newly created <Group>.
*
* See Also:
* <update>
*/
public static function add($name, $permissions): self {
$sql = SQL::current();
$trigger = Trigger::current();
$name = strip_tags($name);
$trigger->filter($name, "before_group_add_name");
$trigger->filter($permissions, "before_group_add_permissions");
$sql->insert("groups", array("name" => $name));
$group_id = $sql->latest("groups");
# Grab valid permissions.
$results = $sql->select(
tables:"permissions",
fields:array("id", "name"),
conds:array("group_id" => 0)
)->fetchAll();
$valid_permissions = array();
foreach ($results as $permission)
$valid_permissions[$permission["id"]] = $permission["name"];
$permissions = array_intersect(
array_keys($valid_permissions),
$permissions
);
# Insert the permissions for the new group.
foreach ($permissions as $id)
$sql->insert(
table:"permissions",
data:array(
"id" => $id,
"name" => $valid_permissions[$id],
"group_id" => $group_id
)
);
$group = new self($group_id);
$trigger->call("add_group", $group);
return $group;
}
/**
* Function: update
* Updates a group with the given name and permissions.
*
* Parameters:
* $name - The new Name to set.
* $permissions - An array of the new permissions to set (IDs).
*
* Returns:
* The updated <Group>.
*/
public function update($name, $permissions): self|false {
if ($this->no_results)
return false;
$sql = SQL::current();
$trigger = Trigger::current();
$name = strip_tags($name);
$trigger->filter($name, "before_group_update_name");
$trigger->filter($permissions, "before_group_update_permissions");
# Grab valid permissions.
$results = $sql->select(
tables:"permissions",
fields:array("id", "name"),
conds:array("group_id" => 0)
)->fetchAll();
$valid_permissions = array();
foreach ($results as $permission)
$valid_permissions[$permission["id"]] = $permission["name"];
$permissions = array_intersect(
array_keys($valid_permissions),
$permissions
);
$sql->update(
table:"groups",
conds:array("id" => $this->id),
data:array("name" => $name)
);
# Delete the old permissions for this group.
$sql->delete(
table:"permissions",
conds:array("group_id" => $this->id)
);
# Insert the new permissions for this group.
foreach ($permissions as $id)
$sql->insert(
table:"permissions",
data:array(
"id" => $id,
"name" => $valid_permissions[$id],
"group_id" => $this->id
)
);
$group = new self(
null,
array(
"read_from" => array(
"id" => $this->id,
"name" => $name,
"permissions" => $permissions
)
)
);
$trigger->call("update_group", $group, $this);
return $group;
}
/**
* Function: delete
* Deletes a given group and its permissions.
*
* See Also:
* <Model::destroy>
*/
public static function delete($group_id): void {
if (!empty($group_id))
SQL::current()->delete(
table:"permissions",
conds:array("group_id" => $group_id)
);
parent::destroy(self::class, $group_id);
}
/**
* Function: add_permission
* Adds a permission to the Groups table.
*
* Parameters:
* $id - The ID for the permission, e.g "can_do_something".
* $name - The name for the permission, e.g. "Can Do Something".
*/
public static function add_permission($id, $name = null): void {
$sql = SQL::current();
if (
$sql->count(
tables:"permissions",
conds:array(
"id" => $id,
"group_id" => 0
)
)
)
return; # Permission already exists.
fallback($name, camelize($id, true));
$sql->insert(
table:"permissions",
data:array(
"id" => $id,
"name" => $name,
"group_id" => 0
)
);
}
/**
* Function: remove_permission
* Removes a permission from the Groups table.
*
* Parameters:
* $id - The ID of the permission to remove.
*/
public static function remove_permission($id): void {
SQL::current()->delete(
table:"permissions",
conds:array("id" => $id)
);
}
/**
* Function: list_permissions
* Returns an array of all permissions in the Groups table.
*
* Parameters:
* $group_id - List enabled permissions for this group ID.
*/
public static function list_permissions($group_id = 0): array {
$permissions = SQL::current()->select(
tables:"permissions",
conds:array("group_id" => $group_id)
)->fetchAll();
$names = array(
"change_settings" => __("Change Settings"),
"toggle_extensions" => __("Toggle Extensions"),
"view_site" => __("View Site"),
"view_private" => __("View Private Posts"),
"view_scheduled" => __("View Scheduled Posts"),
"view_draft" => __("View Drafts"),
"view_own_draft" => __("View Own Drafts"),
"add_post" => __("Add Posts"),
"add_draft" => __("Add Drafts"),
"edit_post" => __("Edit Posts"),
"edit_draft" => __("Edit Drafts"),
"edit_own_post" => __("Edit Own Posts"),
"edit_own_draft" => __("Edit Own Drafts"),
"delete_post" => __("Delete Posts"),
"delete_draft" => __("Delete Drafts"),
"delete_own_post" => __("Delete Own Posts"),
"delete_own_draft" => __("Delete Own Drafts"),
"view_page" => __("View Pages"),
"add_page" => __("Add Pages"),
"edit_page" => __("Edit Pages"),
"delete_page" => __("Delete Pages"),
"add_user" => __("Add Users"),
"edit_user" => __("Edit Users"),
"delete_user" => __("Delete Users"),
"add_group" => __("Add Groups"),
"edit_group" => __("Edit Groups"),
"delete_group" => __("Delete Groups"),
"import_content" => __("Import Content"),
"export_content" => __("Export Content")
);
Trigger::current()->filter($names, "list_permissions");
foreach ($permissions as &$permission) {
if (array_key_exists($permission["id"], $names))
$permission["name"] = $names[$permission["id"]];
}
usort($permissions, function ($a, $b) {
return substr_compare($a["id"], $b["id"], 0);
});
return $permissions;
}
/**
* Function: size
* Returns the number of users in the group.
*/
public function size(): int|false {
if ($this->no_results)
return false;
if (!isset($this->size))
$this->size = SQL::current()->count(
tables:"users",
conds:array("group_id" => $this->id)
);
return (int) $this->size;
}
}