<?php
|
namespace JVBase\managers;
|
|
use JVBase\registrar\Registrar;
|
use JVBase\base\Site;
|
use WP_User;
|
use WP_Role;
|
|
if (!defined('ABSPATH')) {
|
exit; // Exit if accessed directly
|
}
|
class RoleManager
|
{
|
private array $roles;
|
private array $content;
|
private array $subTypes = [];
|
|
public function __construct()
|
{
|
$this->roles = Registrar::getRegistered('user');
|
|
$this->content = array_map(function($content) {
|
$registrar = Registrar::getInstance($content);
|
return strtolower(str_replace(' ', '_', $registrar->getPlural()??$registrar->getSingular().'s'));
|
},array_merge(
|
Registrar::getRegistered('post'),
|
Registrar::getFeatured('is_content', 'term')
|
));
|
add_action('set_user_role', [$this, 'updateRoles'], 10, 3);
|
|
$this->checkRoleSubTypes();
|
}
|
|
public function checkRoleSubTypes():void
|
{
|
foreach ($this->roles as $role) {
|
$registrar = Registrar::getInstance($role);
|
if ($registrar->getUserSubtype()){
|
$this->subTypes[jvbCheckBase($registrar->getUserSubtype())] = $registrar->getCreatable();
|
}
|
}
|
if (!empty($this->subTypes)) {
|
add_action('set_object_terms', [$this, 'maybeSwitchPermissions'],10, 6);
|
}
|
}
|
|
public function updateRoles(int $userID, string $role, array $oldRoles):void
|
{
|
if (doing_action('set_user_role') > 1) {
|
return;
|
}
|
$temp = jvbNoBase($role);
|
$registrar = Registrar::getInstance($temp);
|
if ($registrar) {
|
$user = get_userdata($userID);
|
if (!$user) {
|
return;
|
}
|
$this->reset($user);
|
$this->setUserAs($user, $temp);
|
}
|
}
|
|
/**
|
* @param WP_User $user
|
*
|
* @return void
|
*/
|
public function reset(WP_User $user):void
|
{
|
foreach ($this->content as $content => $plural) {
|
$content = jvbCheckBase($content);
|
$this->grantContent($user, $content, false);
|
$this->grantOthersContent($user, $content, false);
|
}
|
}
|
|
private function isValidContentType(string $type): bool
|
{
|
$type = jvbNoBase($type);
|
|
$registrar = Registrar::getInstance($type);
|
if ($registrar && $registrar->getType() === 'post') {
|
return true;
|
}
|
|
if ($registrar && $registrar->getType() === 'term' && $registrar->hasFeature('is_content')) {
|
return true;
|
}
|
|
return false;
|
}
|
|
/**
|
* Ensures the role can manage the content before changing capabilities
|
* @param int|WP_User $user
|
* @param string $content
|
* @return bool
|
*/
|
public function checkRole(int|WP_User $user, string $content):bool
|
{
|
if(user_can($user, 'manage_options')) {
|
return true;
|
}
|
if (is_int($user)) {
|
$user = get_userdata($user);
|
}
|
|
$roles = array_keys($user->roles);
|
|
foreach ($roles as $role) {
|
$registrar = Registrar::getInstance($role);
|
if (!$registrar) {
|
return false;
|
}
|
foreach ($registrar->getCreatable() as $type) {
|
if (is_array($type) && in_array($content, $type)) {
|
return true;
|
} elseif ($content === $type) {
|
return true;
|
}
|
}
|
}
|
return false;
|
}
|
|
/**
|
* Grants content management capabilities to a user
|
* @param WP_User $user
|
* @param string $content
|
* @param bool $add
|
* @return void
|
*/
|
public function grantContent(WP_User $user, string $content, bool $add = true):void
|
{
|
if (!$this->isValidContentType($content) || !$this->checkRole($user, $content)) {
|
return;
|
}
|
|
$capabilities = $this->getCapabilities($content);
|
|
foreach ($capabilities as $cap) {
|
if ($add) {
|
$user->add_cap($cap);
|
} else {
|
$user->remove_cap($cap);
|
}
|
}
|
}
|
|
/**
|
* Grants management of other users' content to a user
|
* @param WP_User $user
|
* @param string $content
|
* @param bool $add
|
* @return void
|
*/
|
public function grantOthersContent(WP_USER $user, string $content, bool $add = true)
|
{
|
if (!$this->isValidContentType($content) || !$this->checkRole($user, $content)) {
|
return;
|
}
|
$capabilities = $this->getOthersCapabilities($content);
|
|
foreach ($capabilities as $cap) {
|
if ($add) {
|
$user->add_cap($cap);
|
} else {
|
$user->remove_cap($cap);
|
}
|
}
|
}
|
|
/**
|
* @param WP_User $user
|
* @param string $type
|
*
|
* @return void
|
*/
|
public function setUserAs(WP_User $user, string $type):void
|
{
|
$role = jvbNoBase(array_keys($user->roles)[0]);
|
$config = $this->getTypesConfig($role);
|
if (!$config || !array_key_exists($type, $config)) {
|
return;
|
}
|
foreach ($config as $role => $content) {
|
if ($type !== $role) {
|
foreach ($content as $c) {
|
$this->grantContent($user, $c, false);
|
}
|
} else {
|
foreach ($content as $c) {
|
$this->grantContent($user, $c);
|
}
|
}
|
}
|
}
|
|
protected function getTypesConfig(string $role):bool|array
|
{
|
$check = get_transient(BASE.'role_config_'.$role);
|
if ($check) {
|
return $check;
|
}
|
|
$registrar = Registrar::getInstance($role);
|
if (!$registrar) {
|
return false;
|
}
|
$out = [];
|
foreach ($registrar->getCreatable() as $types) {
|
if (is_array($types)) {
|
$out = array_merge($out, $types);
|
} else {
|
$out = [$types];
|
}
|
$out = array_unique($out);
|
}
|
set_transient(BASE.'role_config_'.$role, $out, MONTH_IN_SECONDS);
|
return $out;
|
}
|
|
/**
|
* @param WP_User $user
|
* @param string $type
|
*
|
* @return int|false
|
*/
|
public function addUserLink(WP_User $user, string $type)
|
{
|
if (!in_array($type, $this->roles)) {
|
return false;
|
}
|
$link = get_user_meta($user->ID, BASE.'profile_link', true);
|
if ($link === '') {
|
$type = BASE.$type;
|
$name = $user->display_name;
|
$status = ($user->has_cap('skip_moderation')) ? 'publish' : 'draft';
|
|
$link = wp_insert_post([
|
'post_type' => $type,
|
'post_status' => $status,
|
'post_title' => $name,
|
'post_author' => $user->ID,
|
]);
|
if ($link) {
|
update_user_meta($user->ID, BASE.'profile_link', $link);
|
update_post_meta($link, BASE.'profile_link', $user->ID);
|
}
|
}
|
return $link;
|
}
|
|
public function registerRole(string $slug): void
|
{
|
$role_name = BASE . $slug;
|
$display_name = $config['label'] ?? ucfirst($slug);
|
|
$registrar = Registrar::getInstance($slug);
|
if (!$registrar){
|
return;
|
}
|
// Build capabilities for this role
|
$capabilities = $this->buildRoleCapabilities($slug, $registrar);
|
|
// Remove role first to ensure clean slate
|
remove_role($role_name);
|
|
// Add the role with capabilities
|
add_role($role_name, $display_name, $capabilities);
|
|
// Add management capabilities to administrator
|
if ($registrar->hasFeature('has_dashboard') ?? false) {
|
$admin_role = get_role('administrator');
|
if ($admin_role) {
|
$admin_role->add_cap("manage_{$role_name}s");
|
$admin_role->add_cap("edit_{$role_name}_settings");
|
}
|
}
|
}
|
|
private function buildRoleCapabilities(string $slug, Registrar $registrar): array
|
{
|
//Everyone can see the things
|
$capabilities = [
|
'read' => true,
|
];
|
|
// Dashboard access
|
if ($registrar->hasFeature('has_dashboard') ?? false) {
|
$capabilities['access_dashboard'] = true;
|
}
|
|
if (Site::has('favourites') && $registrar->hasFeature('can_favourite') ?? true) {
|
$capabilities['can_favourite'] = true;
|
}
|
|
// Content creation capabilities
|
if (!empty($registrar->getCreatable())) {
|
$content = [];
|
foreach ($registrar->getCreatable() as $content_type) {
|
if (is_array($content_type)) {
|
$content = array_merge($content, $content_type);
|
}else {
|
$content[] = $content_type;
|
}
|
}
|
foreach ($content as $c) {
|
$this->addContentCapabilities($capabilities, $c, $registrar);
|
}
|
}
|
|
// Management capabilities
|
if (!empty($registrar->getManageOthers())) {
|
foreach ($registrar->getManageOthers() as $type) {
|
// Skip if content type doesn't exist
|
if (!$this->isValidContentType($type)) {
|
error_log("Warning: User role '{$slug}' references non-existent content type '{$type}'");
|
continue;
|
}
|
$addCaps = $this->getOthersCapabilities($type);
|
foreach ($addCaps as $cap) {
|
$capabilities[$cap] = true;
|
}
|
}
|
}
|
|
return apply_filters(BASE . 'role_capabilities', $capabilities, $slug);
|
}
|
|
/**
|
* Add content capabilities to capability array
|
*/
|
private function addContentCapabilities(array &$capabilities, $content_type, Registrar $registrar): void
|
{
|
if (!$this->isValidContentType($content_type)) {
|
error_log("Warning: Role references non-existent content type '{$content_type}'");
|
return;
|
}
|
$this->addSingleContentCapabilities($capabilities, $content_type, $registrar);
|
}
|
|
/**
|
* Add capabilities for a single content type
|
*/
|
private function addSingleContentCapabilities(array &$capabilities, string $type, Registrar $registrar): void
|
{
|
$caps = $this->getCapabilities($type);
|
foreach ($caps as $cap) {
|
$capabilities[$cap] = true;
|
}
|
|
if ($registrar->hasFeature('approve_new')) {
|
$plural = $this->getContentPlural($type);
|
// Publish capability depends on approval setting
|
$capabilities["publish_{$plural}"] = !($config['approve_new'] ?? false);
|
}
|
}
|
|
public function grantRoleCapabilities(string $role_name, string $content_slug, bool $grant = true): void
|
{
|
$role = get_role($role_name);
|
if (!$role) {
|
return;
|
}
|
|
$capabilities = $this->getCapabilities(jvbNoBase($content_slug));
|
foreach ($capabilities as $capability) {
|
if ($grant) {
|
$role->add_cap($capability);
|
} else {
|
$role->remove_cap($capability);
|
}
|
}
|
}
|
public function grantRoleOthersCapabilities(string $role_name, string $content_slug, bool $grant = true): void
|
{
|
$role = get_role($role_name);
|
if (!$role) {
|
return;
|
}
|
|
$capabilities = $this->getOthersCapabilities(jvbNoBase($content_slug));
|
foreach ($capabilities as $capability) {
|
if ($grant) {
|
$role->add_cap($capability);
|
} else {
|
$role->remove_cap($capability);
|
}
|
}
|
}
|
|
/**
|
* @param string $content
|
* @return array|string[]
|
* Note: must match what is created in PostTypeRegistrar.php::register
|
*/
|
protected function getCapabilities(string $content):array
|
{
|
$content = jvbNoBase($content);
|
if (!$this->isValidContentType($content)) {
|
return [];
|
}
|
|
$plural = $this->getContentPlural($content);
|
|
return [
|
"edit_{$content}",
|
"edit_published_{$content}",
|
"read_{$content}",
|
"delete_{$content}",
|
"delete_published_{$content}",
|
"edit_{$plural}",
|
"publish_{$plural}",
|
"read_private_{$plural}",
|
"edit_private_{$plural}",
|
"delete_private_{$plural}",
|
];
|
}
|
protected function getOthersCapabilities(string $content):array
|
{
|
$content = jvbNoBase($content);
|
if (!$this->isValidContentType($content)) {
|
return [];
|
}
|
$plural = $this->getContentPlural($content);
|
return [
|
"edit_others_{$plural}",
|
"delete_others_{$plural}",
|
];
|
}
|
|
public static function getPlural(string $content): string
|
{
|
$self = new self;
|
return $self->getContentPlural($content);
|
}
|
public function getContentPlural(string $content): string
|
{
|
$content = jvbNoBase($content);
|
$registrar = Registrar::getInstance($content);
|
if ($registrar && $registrar->getPlural()) {
|
return str_replace(' ', '_', $registrar->getPlural());
|
}
|
return str_replace(' ', '_', $content.'s');
|
}
|
|
public static function activate(): void
|
{
|
error_log('[RoleManager]::activate');
|
error_log('Registering roles...');
|
$instance = new self;
|
foreach (Registrar::getRegistered('user') as $role) {
|
$instance->registerRole($role);
|
}
|
error_log('Roles registered!');
|
error_log('Removing unneeded roles...');
|
remove_role('contributor');
|
remove_role('author');
|
remove_role('editor');
|
error_log('Roles removed!');
|
|
error_log('Adding Admin Capabilities');
|
$instance->addAdminCaps();
|
error_log('Ensuring Existing User\'s Roles...');
|
$instance->ensureRoleCaps();
|
error_log('Roles activated!');
|
}
|
protected function addAdminCaps():void
|
{
|
$users = get_users(['role' => 'administrator']);
|
foreach (array_merge(Registrar::getRegistered('post'), Registrar::getFeatured('is_content')) as $slug) {
|
$this->grantRoleCapabilities('administrator', $slug);
|
$this->grantRoleOthersCapabilities('administrator', $slug);
|
|
foreach ($users as $user) {
|
$this->grantContent($user, $slug);
|
$this->grantOthersContent($user, $slug);
|
}
|
}
|
}
|
protected function ensureRoleCaps():void
|
{
|
$roles = Registrar::getRegistered('user');
|
foreach ($roles as $role) {
|
$registrar = Registrar::getInstance($role);
|
$creatable = $registrar->getCreatable();
|
$manageable = $registrar->getManageOthers();
|
if (!empty($creatable) || !empty($manageable)) {
|
$users = get_users(['role' => jvbCheckBase($role)]);
|
foreach ($users as $user) {
|
foreach ($creatable as $slug) {
|
$this->grantContent($user, $slug);
|
}
|
foreach ($manageable as $slug) {
|
$this->grantOthersContent($user, $slug);
|
}
|
}
|
}
|
}
|
}
|
|
/******************************************************************
|
* OWNABLE and MANAGABLE terms (ie: tattoo shops)
|
******************************************************************/
|
/**
|
* Grant ownership of a content taxonomy term
|
* Owners have full control over the term and its members
|
*
|
* @param int $userID User ID
|
* @param int $termID Term ID
|
* @param string $taxonomy Taxonomy slug (without BASE)
|
* @return bool Success
|
*/
|
public function grantOwnership(int $userID, int $termID, string $taxonomy): bool
|
{
|
if (!get_userdata($userID) || !term_exists($termID)){
|
return false;
|
}
|
$taxonomy = jvbNoBase($taxonomy);
|
|
$registrar = Registrar::getInstance($taxonomy);
|
// Verify this is an ownable content taxonomy
|
if (!$registrar || !$registrar->hasFeature('is_content') ||
|
!$registrar->hasFeature('is_ownable')) {
|
return false;
|
}
|
|
$user = get_userdata($userID);
|
if (!$user) {
|
return false;
|
}
|
|
// Grant both ownership and management
|
$user->add_cap(BASE . 'can_own_' . $termID);
|
$user->add_cap(BASE . 'can_manage_' . $termID);
|
|
$owners = get_term_meta($termID, BASE.'owners', true);
|
if (empty($owners)) {
|
$owners = [];
|
}
|
$owners[] = $userID;
|
$owners = array_unique($owners);
|
update_term_meta($termID, BASE.'owners', $owners);
|
|
|
do_action(BASE . 'granted_ownership', $userID, $termID, $taxonomy);
|
|
return true;
|
}
|
|
/**
|
* Revoke ownership of a content taxonomy term
|
*
|
* @param int $userID User ID
|
* @param int $termID Term ID
|
* @param string $taxonomy Taxonomy slug (without BASE)
|
* @return bool Success
|
*/
|
public function revokeOwnership(int $userID, int $termID, string $taxonomy): bool
|
{
|
if (!get_userdata($userID) || !term_exists($termID)){
|
return false;
|
}
|
$taxonomy = jvbNoBase($taxonomy);
|
|
$user = get_userdata($userID);
|
if (!$user) {
|
return false;
|
}
|
|
$owners = get_term_meta($termID, BASE.'owners', true);
|
if (empty($owners)) {
|
$owners = [];
|
}
|
if (in_array($userID, $owners)) {
|
unset($owners[array_search($userID, $owners)]);
|
}
|
$owners = array_unique($owners);
|
update_term_meta($termID, BASE.'owners', $owners);
|
|
$user->remove_cap(BASE . 'can_own_' . $termID);
|
|
do_action(BASE . 'revoked_ownership', $userID, $termID, $taxonomy);
|
|
return true;
|
}
|
|
/**
|
* Grant management capabilities for a content taxonomy term
|
* Managers can approve members and edit content but don't own the term
|
*
|
* @param int $userID User ID
|
* @param int $termID Term ID
|
* @param string $taxonomy Taxonomy slug (without BASE)
|
* @return bool Success
|
*/
|
public function grantManagement(int $userID, int $termID, string $taxonomy): bool
|
{
|
if (!get_userdata($userID) || !term_exists($termID)){
|
return false;
|
}
|
$taxonomy = jvbNoBase($taxonomy);
|
|
$registrar = Registrar::getInstance($taxonomy);
|
// Verify this is an ownable content taxonomy
|
if (!$registrar || !$registrar->hasFeature('is_content') ||
|
!$registrar->hasFeature('is_ownable')) {
|
return false;
|
}
|
|
$user = get_userdata($userID);
|
if (!$user) {
|
return false;
|
}
|
|
$user->add_cap(BASE . 'can_manage_' . $termID);
|
|
$managers = get_term_meta($termID, BASE.'managers', true);
|
if (empty($managers)) {
|
$managers = [];
|
}
|
$managers[] = $userID;
|
$managers = array_unique($managers);
|
update_term_meta($termID, BASE.'managers', $managers);
|
|
do_action(BASE . 'granted_management', $userID, $termID, $taxonomy);
|
|
return true;
|
}
|
|
/**
|
* Revoke management capabilities for a content taxonomy term
|
*
|
* @param int $userID User ID
|
* @param int $termID Term ID
|
* @param string $taxonomy Taxonomy slug (without BASE)
|
* @return bool Success
|
*/
|
public function revokeManagement(int $userID, int $termID, string $taxonomy): bool
|
{
|
if (!get_userdata($userID) || !term_exists($termID)){
|
return false;
|
}
|
$taxonomy = jvbNoBase($taxonomy);
|
|
$user = get_userdata($userID);
|
if (!$user) {
|
return false;
|
}
|
|
$user->remove_cap(BASE . 'can_manage_' . $termID);
|
|
$managers = get_term_meta($termID, BASE.'managers', true);
|
if (empty($managers)) {
|
$managers = [];
|
}
|
if (in_array($userID, $managers)) {
|
unset($managers[array_search($userID, $managers)]);
|
}
|
$managers = array_unique($managers);
|
update_term_meta($termID, BASE.'managers', $managers);
|
|
do_action(BASE . 'revoked_management', $userID, $termID, $taxonomy);
|
|
return true;
|
}
|
|
/**
|
* Check if user owns a term
|
*
|
* @param int $userID User ID
|
* @param int $termID Term ID
|
* @return bool
|
*/
|
public function isOwner(int $userID, int $termID): bool
|
{
|
return user_can($userID, BASE . 'can_own_' . $termID);
|
}
|
|
/**
|
* Check if user can manage a term (owner or manager)
|
*
|
* @param int $userID User ID
|
* @param int $termID Term ID
|
* @return bool
|
*/
|
public function isManager(int $userID, int $termID): bool
|
{
|
return user_can($userID, BASE . 'can_manage_' . $termID) ||
|
user_can($userID, BASE . 'can_own_' . $termID);
|
}
|
|
/**
|
* Get all terms a user owns
|
*
|
* @param int $userID User ID
|
* @param string|null $taxonomy Optional: filter by taxonomy
|
* @return array Array of term IDs
|
*/
|
public function getOwnedTerms(int $userID, ?string $taxonomy = null): array
|
{
|
$user = get_userdata($userID);
|
if (!$user) {
|
return [];
|
}
|
|
$owned = [];
|
foreach ($user->allcaps as $cap => $value) {
|
if ($value && strpos($cap, BASE . 'can_own_') === 0) {
|
$termID = (int) str_replace(BASE . 'can_own_', '', $cap);
|
if ($termID) {
|
$owned[] = $termID;
|
}
|
}
|
}
|
|
// Filter by taxonomy if specified
|
if ($taxonomy && !empty($owned)) {
|
$taxonomy = jvbCheckBase($taxonomy);
|
$filtered = [];
|
foreach ($owned as $termID) {
|
$term = get_term($termID);
|
if ($term && !is_wp_error($term) && $term->taxonomy === $taxonomy) {
|
$filtered[] = $termID;
|
}
|
}
|
return $filtered;
|
}
|
|
return $owned;
|
}
|
|
/**
|
* Get all terms a user can manage (owns or manages)
|
*
|
* @param int $userID User ID
|
* @param string|null $taxonomy Optional: filter by taxonomy
|
* @return array Array of term IDs
|
*/
|
public function getManagedTerms(int $userID, ?string $taxonomy = null): array
|
{
|
$user = get_userdata($userID);
|
if (!$user) {
|
return [];
|
}
|
|
$managed = [];
|
foreach ($user->allcaps as $cap => $value) {
|
if ($value && (strpos($cap, BASE . 'can_manage_') === 0 ||
|
strpos($cap, BASE . 'can_own_') === 0)) {
|
$termID = (int) str_replace([BASE . 'can_manage_', BASE . 'can_own_'], '', $cap);
|
if ($termID && !in_array($termID, $managed)) {
|
$managed[] = $termID;
|
}
|
}
|
}
|
|
// Filter by taxonomy if specified
|
if ($taxonomy && !empty($managed)) {
|
$taxonomy = jvbCheckBase($taxonomy);
|
$filtered = [];
|
foreach ($managed as $termID) {
|
$term = get_term($termID);
|
if ($term && !is_wp_error($term) && $term->taxonomy === $taxonomy) {
|
$filtered[] = $termID;
|
}
|
}
|
return $filtered;
|
}
|
|
return $managed;
|
}
|
|
/**
|
* Get all ownable taxonomies
|
*
|
* @return array Array of taxonomy slugs
|
*/
|
public function getOwnableTaxonomies(): array
|
{
|
static $ownable = null;
|
|
if ($ownable === null) {
|
$ownable = array_map(function ($instance) {
|
return $instance->slug;
|
}, Registrar::getFeatured('is_ownable', 'term'));
|
}
|
|
return $ownable;
|
}
|
|
/**
|
* Get all invitable taxonomies
|
*
|
* @return array Array of taxonomy slugs
|
*/
|
public function getInvitableTaxonomies(): array
|
{
|
static $invitable = null;
|
|
if ($invitable === null) {
|
$invitable = array_map(function ($instance) {
|
return $instance->slug;
|
}, Registrar::getFeatured('invitable', 'term'));
|
}
|
|
return $invitable;
|
}
|
|
public function getPermission(string $action, string $content, ?int $ID = null):?string
|
{
|
$plural = $this->getContentPlural($content);
|
switch ($action) {
|
case 'edit':
|
if ($ID) {
|
return "edit_{$content}";
|
}
|
return "edit_{$plural}";
|
}
|
return null;
|
}
|
|
public function maybeSwitchPermissions(int $object_id, array $terms, array $tt_ids, string $taxonomy, bool $append, array $old_tt_ids):void
|
{
|
//This shouldn't happen, but whatever
|
if (empty($this->subTypes)) {
|
return;
|
}
|
|
if (!in_array($taxonomy, array_keys($this->subTypes))) {
|
return;
|
}
|
|
$new = array_diff($tt_ids, $old_tt_ids);
|
$old = array_diff($old_tt_ids, $tt_ids);
|
|
$userID = (int)get_post_meta($object_id, BASE.'profile_link',true);
|
if ($userID === 0) {
|
return;
|
}
|
$user = get_userdata($userID);
|
if (!$user) {
|
return;
|
}
|
|
//Revoke old first
|
if (!empty($old)) {
|
$old = array_filter(array_map(function ($id) use ($taxonomy) {
|
$termID = $this->getTermIDFromTTID($id);
|
return $this->getRootTermSlug($termID, $taxonomy);
|
}, $old));
|
foreach ($old as $slug) {
|
if (!array_key_exists($slug, $this->subTypes[$taxonomy])) {
|
error_log('[RoleManager]::maybeSwitchPermissions Could not find creatable types for role subtype '.$slug);
|
continue;
|
}
|
foreach ($this->subTypes[$taxonomy][$slug] ?? [] as $s) {
|
$this->grantContent($user, $s, false);
|
}
|
}
|
}
|
|
if (!empty($new)) {
|
$new = array_filter(array_map(function ($id) use ($taxonomy){
|
$termID = $this->getTermIDFromTTID($id);
|
return $this->getRootTermSlug($termID, $taxonomy);
|
}, $new));
|
foreach ($new as $slug) {
|
if (!array_key_exists($slug, $this->subTypes[$taxonomy])) {
|
error_log('[RoleManager]::maybeSwitchPermissions Could not find creatable types for role subtype '.$slug);
|
continue;
|
}
|
foreach ($this->subTypes[$taxonomy][$slug] ?? [] as $s) {
|
$this->grantContent($user, $s);
|
}
|
}
|
}
|
}
|
|
/**
|
* Helper function to get term_id from term_taxonomy_id
|
* @param int $tt_id
|
*
|
* @return int
|
*/
|
private function getTermIDFromTTID(int $tt_id):int
|
{
|
global $wpdb;
|
return $wpdb->get_var($wpdb->prepare(
|
"SELECT term_id FROM {$wpdb->term_taxonomy} WHERE term_taxonomy_id = %d",
|
$tt_id
|
));
|
}
|
|
private function getRootTermSlug(int $termID, string $taxonomy): string|false
|
{
|
$term = get_term($termID, $taxonomy);
|
if (!$term || is_wp_error($term)) {
|
return false;
|
}
|
while ($term->parent !== 0) {
|
$term = get_term($term->parent, $taxonomy);
|
if (!$term || is_wp_error($term)) {
|
return false;
|
}
|
}
|
return $term->slug;
|
}
|
}
|