From 2127b1bdd73ecd2423e443992da4b442f5a3c1a3 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Wed, 04 Feb 2026 21:19:25 +0000
Subject: [PATCH] =Major overhaul of MetaManager.php -> Meta.php and RestRouteManager.php -> Rest.php. Seems to work for JakeVan
---
inc/managers/RoleManager.php | 349 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 328 insertions(+), 21 deletions(-)
diff --git a/inc/managers/RoleManager.php b/inc/managers/RoleManager.php
index b575a04..d4a3988 100644
--- a/inc/managers/RoleManager.php
+++ b/inc/managers/RoleManager.php
@@ -17,10 +17,26 @@
{
$this->roles = array_keys(JVB_USER);
$this->content = array_map(function($content) {
- return strtolower($content['plural']);
+ return strtolower($content['plural']??$content['singular'].'s');
},JVB_CONTENT);
+ add_action('set_user_role', [$this, 'updateRoles'], 10, 3);
}
+ public function updateRoles(int $userID, string $role, array $oldRoles):void
+ {
+ if (doing_action('set_user_role') > 1) {
+ return;
+ }
+ $temp = jvbNoBase($role);
+ if (array_key_exists($temp, JVB_USER)) {
+ $user = get_userdata($userID);
+ if (!$user) {
+ return;
+ }
+ $this->reset($user);
+ $this->setUserAs($user, $temp);
+ }
+ }
/**
* @param WP_User $user
@@ -140,7 +156,6 @@
/**
* @param WP_User $user
* @param string $type
- * @param bool $add
*
* @return void
*/
@@ -356,22 +371,29 @@
}
}
+ /**
+ * @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_' . $plural,
- 'delete_' . $plural,
- 'read_' . $plural,
- 'edit_published_' . $plural,
- 'delete_published_' . $plural,
- 'edit_private_' . $plural,
- 'delete_private_' . $plural,
- 'publish_' . $plural,
+ "edit_{$content}",
+ "read_{$content}",
+ "delete_{$content}",
+ "edit_{$plural}",
+ "edit_others_{$plural}",
+ "publish_{$plural}",
+ "read_private_{$plural}",
+ "edit_{$plural}",
];
}
protected function getOthersCapabilities(string $content):array
@@ -382,23 +404,32 @@
}
$plural = $this->getContentPlural($content);
return [
- 'edit_others_' . $plural,
- 'delete_others_' . $plural,
- 'read_private_' . $plural,
- 'edit_private_' . $plural,
- 'delete_private_' . $plural,
+ "edit_others_{$plural}",
+ "delete_others_{$plural}",
+ "read_private_{$plural}",
+ "edit_private_{$plural}",
+ "delete_private_{$plural}",
];
}
- private function getContentPlural(string $content): string
+ public static function getPlural(string $content): string
+ {
+ $self = new self;
+ return $self->getContentPlural($content);
+ }
+ public function getContentPlural(string $content): string
{
$content = jvbNoBase($content);
-
- if (array_key_exists($content, JVB_CONTENT)) {
- return strtolower(JVB_CONTENT[$content]['plural'] ?? $content . 's');
+ $config = Features::getConfig($content);
+ $capsMap = $config['capability_type']??[];
+ if (empty($capsMap)){
+ $capsMap = [
+ $content,
+ str_replace('-', '_',sanitize_title(strtolower(JVB_CONTENT[$content]['plural']??JVB_TAXONOMY[$content]['plural'])))
+ ];
+ return $capsMap[1];
}
-
- return strtolower($content . 's');
+ return str_replace('-', '_', sanitize_title(strtolower($content . 's')));
}
public function activate(): void
@@ -407,4 +438,280 @@
$this->registerRole($slug, $config);
}
}
+
+ /******************************************************************
+ * 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);
+
+ // Verify this is an ownable content taxonomy
+ if (!Features::forTaxonomy($taxonomy)->has('is_content') ||
+ !Features::forTaxonomy($taxonomy)->has('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);
+
+ 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;
+ }
+
+ $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);
+
+ // Verify this is an ownable content taxonomy
+ if (!Features::forTaxonomy($taxonomy)->has('is_content') ||
+ !Features::forTaxonomy($taxonomy)->has('is_ownable')) {
+ return false;
+ }
+
+ $user = get_userdata($userID);
+ if (!$user) {
+ return false;
+ }
+
+ $user->add_cap(BASE . 'can_manage_' . $termID);
+
+ 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);
+
+ 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 = [];
+ foreach (JVB_TAXONOMY as $taxonomy => $config) {
+ if (Features::forTaxonomy($taxonomy)->has('is_content') &&
+ Features::forTaxonomy($taxonomy)->has('is_ownable')) {
+ $ownable[] = $taxonomy;
+ }
+ }
+ }
+
+ return $ownable;
+ }
+
+ /**
+ * Get all invitable taxonomies
+ *
+ * @return array Array of taxonomy slugs
+ */
+ public function getInvitableTaxonomies(): array
+ {
+ static $invitable = null;
+
+ if ($invitable === null) {
+ $invitable = [];
+ foreach (JVB_TAXONOMY as $taxonomy => $config) {
+ if (Features::forTaxonomy($taxonomy)->has('invitable')) {
+ $invitable[] = $taxonomy;
+ }
+ }
+ }
+
+ return $invitable;
+ }
}
--
Gitblit v1.10.0