380 lines
12 KiB
PHP
380 lines
12 KiB
PHP
|
<?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;
|
||
|
}
|
||
|
}
|