cache = CacheManager::for('dashboard', WEEK_IN_SECONDS);
$this->cache->invalidate();
add_action('init', [$this, 'registerDashboard']);
if (!$this->isRegistered()) {
add_action('init', [$this, 'buildDashboard']);
}
$this->user = wp_get_current_user();
$this->role = jvbUserRole();
$this->userLink = (int)get_user_meta($this->user->ID, BASE.'link', true);
add_action('template_redirect', [$this, 'handleRedirects']);
add_action('template_include', [$this, 'dashboardTemplates']);
add_action('admin_init', [$this, 'redirectFromAdmin']);
add_action('wp_enqueue_scripts', [$this, 'dashboardScripts'], 50);
add_filter('jvbDashboardPage', [$this, 'renderIndex'], 10, 2);
}
/**
* Registers the custom post type that handles the dashboard
* @return void
*/
public function registerDashboard():void
{
$plural = 'Dashboards';
$singular = 'Dashboard';
register_post_type(BASE.'dash', array(
'labels' => [
'name' => $plural,
'singular_name' => $singular,
'menu_name' => $plural,
'add_new' => "Add New {$singular}",
'add_new_item' => "Add New {$singular}",
'edit_item' => "Edit {$singular}",
'new_item' => "New {$singular}",
'view_item' => "View {$singular}",
'search_items' => "Search {$plural}",
'not_found' => "No {$plural} found",
'not_found_in_trash' => "No {$plural} found in Trash"
],
'menu_icon' => jvbCSSIcon('gauge'),
'public' => true,
'publicly_queryable' => true,
'show_in_menu' => true,
'show_in_admin_bar' => false,
'has_archive' => true,
'hierarchical' => true,
'rewrite' => array(
'slug' => 'dash',
'with_front' => false
),
'capability_type' => 'post',
'supports' => array('title', 'editor', 'custom-fields')
));
}
/**
* Redirect all non-admin users from wp-admin to custom dashboard
*/
public function redirectFromAdmin()
{
// Allow admins to access wp-admin if needed
if (current_user_can('manage_options')) {
return;
}
// Redirect to custom dashboard
$this->redirectToDashboard();
}
protected function redirectToLogin():void
{
wp_redirect(wp_login_url(get_home_url(null, '/dash')));
exit;
}
protected function redirectToDashboard():void
{
wp_redirect(get_home_url(null, '/dash'));
exit;
}
protected function getConfig(string $page):array
{
$pages = $this->getAllDashboardPages();
$key = array_search($page, $pages);
if ($key === false || is_numeric($key)) {
return [];
}
return Features::getConfig($key);
}
/**
* Check if user can access page and redirect if not
* @param string $page
* @param int|null $userID
* @return void
*/
protected function requirePageAccess(string $page, ?int $userID = null):void
{
$allowedPages = $this->getUserAllowedPages($userID);
if (!in_array($page, $allowedPages)) {
$this->redirectToDashboard();
}
}
protected function getTitle(string $slug):string
{
$config = $this->getConfig($slug);
if (!empty($config)) {
return $config['dash_title']??$config['plural'];
}
return ucwords(str_replace('-', ' ', str_replace('_', ' ', $slug)));
}
public function handleRedirects():void
{
// Only process dashboard-related pages and 404s
if (!is_singular(BASE.'dash') && !is_post_type_archive(BASE.'dash') && !is_404()) {
return;
}
// Check if user is logged in first
if (!is_404() && !is_user_logged_in()) {
error_log('Redirecting to login - user not logged in');
$this->redirectToLogin();
return;
}
// If logged in but doesn't have dashboard access, redirect to home
if (!is_404() && !isOurPeople() && !current_user_can('manage_options')) {
error_log('Redirecting to home - user lacks dashboard access');
wp_redirect(home_url());
exit;
}
// Handle 404s that are trying to access dashboard URLs
global $wp;
if (is_404() && (str_starts_with($wp->request, 'dash/') || $wp->request === 'dash')) {
error_log('404 on dashboard URL, redirecting to dashboard home');
$this->redirectToDashboard();
return;
}
// For valid dashboard pages, check access permissions
if (!is_404()) {
$page = $this->getCurrentPage();
// Dashboard home is always accessible (if authenticated)
if ($page === '' || $page === 'dash') {
return;
}
// Check if page exists in allowed pages
$allowedPages = $this->getUserAllowedPages();
if (!in_array($page, $allowedPages)) {
error_log("User not allowed to access page: {$page}");
$this->redirectToDashboard();
return;
}
}
}
/**
* Ensures the necessary pages are created
* @return void
*/
public function buildDashboard():void
{
$manageableContent = $this->getAllDashboardPages();
foreach ($manageableContent as $key => $slug) {
if ($slug === 'dash') {
continue;
}
$existing = get_page_by_path($slug, OBJECT, BASE.'dash');
if ($existing) {
continue;
}
$title = $this->getTitle($slug);
$ID = wp_insert_post(array(
'post_title' => $title,
'post_name' => $slug,
'post_type' => BASE.'dash',
'post_status' => 'publish',
));
if ($title === 'Integrations') {
$this->buildIntegrationPages($ID);
}
}
update_option(BASE.'dashboard_registered', true);
remove_action('init', [$this, 'buildDashboard']);
}
/**
* Build integration sub-pages
* @param int $parentID
* @return void
*/
protected function buildIntegrationPages(int $parentID):void
{
$integrations = JVB()->getAvailableServices(false);
foreach ($integrations as $name => $integration) {
$title = $integration->getTitle();
$slug = sanitize_title($title);
// Check if integration page already exists
$existing = get_posts([
'post_type' => BASE.'dash',
'name' => $slug,
'post_parent' => $parentID,
'posts_per_page' => 1,
]);
if (!empty($existing)) {
continue; // Skip if exists
}
wp_insert_post([
'post_title' => $title,
'post_name' => $slug,
'post_type' => BASE.'dash',
'post_status' => 'publish',
'post_parent' => $parentID
]);
}
}
protected function getDescription(string $page):string
{
$config = $this->getConfig($page);
if (!empty($config)) {
$description = (array_key_exists('dash_description', $config)) ? $config['dash_description'] : '';
} else {
$description = apply_filters('jvbDashboardDescription', $page);
switch ($page) {
case 'approval':
$description = 'See your approval requests for term creation, joining shops, or joining edmonton.ink. You can also help shape the community by approving other\'s requests!';
break;
case 'metrics':
$description = 'See what kind of traffic you\'re getting. (coming soon)';
break;
case 'favourites':
$description = 'See what you favourited, and create, manage, and share lists.';
break;
case 'support':
$description = 'Sometimes we all need a hand. This is your direct access to the site admin - or text Jake at 825-823-9916';
break;
case 'settings':
$description = 'Control your privacy and email frequency.';
break;
}
}
return $description;
}
/**
* Checks if we've already created the need pages
* @return bool
*/
protected function isRegistered():bool
{
return get_option(BASE.'dashboard_registered', false);
}
/**
* Hacking into the template_include to set our custom templates and protections
* @param string $template
*
* @return string
*/
public function dashboardTemplates(string $template):string
{
if (!is_singular(BASE.'dash') && !is_post_type_archive(BASE.'dash')) {
return $template;
}
// Get current page/section
$page = $this->getCurrentPage();
$integrationSlugs = array_map(function($name) {
return sanitize_title(str_replace('_', '-', $name));
}, array_keys(JVB()->getAvailableServices(false)));
// Check if this is an integration subpage
if (in_array($page, $integrationSlugs)) {
// Pass along to the Integrations template handler which knows to check for subpages
$page = 'integrations';
}
echo $this->cache->remember(
$page,
function() use ($page) {
return $this->renderDashboard($page);
}
);
return '';
}
protected function getConstantSlug(string $page):string
{
$slug = array_search($page, $this->getAllDashboardPages());
return (is_numeric($slug)) ? '' : $slug;
}
protected function renderDashboard(string $page):string
{
ob_start();
jvbInlineStyles('nav');
jvbInlineStyles('dash');
jvbInlineStyles('forms');
$this->renderHeader();
// Pass to page handler
$constantSlug = $this->getConstantSlug($page);
echo apply_filters(
'jvbDashboardPage',
$this->renderPage($page),
$page,
$constantSlug
);
$this->renderFooter();
return ob_get_clean();
// $integrationSlugs = array_map(function($name) {
// return sanitize_title(str_replace('_', '-', $name));
// }, array_keys(JVB()->getAvailableServices(false)));
//
// if ($page === 'integrations' || in_array($page, $integrationSlugs)) {
// // Check integration access
// if ($page === 'integrations') {
// if (!Features::hasAnyIntegration('user', $this->role)) {
// $this->redirectToDashboard();
// }
// } else {
// if (!Features::hasIntegration($page, 'user', $this->role)) {
// $this->redirectToDashboard();
// }
// }
// } elseif ($page === 'bio') {
// // Bio page logic
// $permission = JVB_USER[$this->role]['profile'] ?? false;
// if (!$permission || (!current_user_can('manage_'.$permission) && !current_user_can('manage_options'))) {
// $this->redirectToDashboard();
// }
// } elseif ($page === 'settings') {
// // Settings page logic
// if (!current_user_can('manage_settings') && !current_user_can('manage_options')) {
// $this->redirectToDashboard();
// }
// } elseif ($page === 'approval') {
// // Approval page logic
// if (!current_user_can('skip_moderation')) {
// $this->redirectToDashboard();
// }
// } elseif ($page !== 'dash') {
// // Regular content type - check permission
// $type = match($page) {
// 'menu-item' => 'menu_item',
// 'events' => 'event',
// default => $page
// };
//
// $permission = $this->getPermissionForType($type);
// if (!current_user_can($permission)) {
// $this->redirectToDashboard();
// }
// }
// // Enqueue needed styles/scripts
//
// $this->cache->delete($page);
// echo $this->cache->remember(
// $page,
// function() use ($page) {
// ob_start();
// $this->renderHeader();
//
// switch ($page) {
// case 'dash':
// if (current_user_can('manage_options')) {
// $content = apply_filters('jvbAdminDashboard', '');
//
// if ($content !== '') {
// echo $content;
// }else {
// $this->renderAdmin();
// }
// } else {
// $this->renderIndex();
// }
//
// break;
// case 'admin':
// $this->renderAdmin();
// break;
// case 'bio':
// $this->renderForm(JVB_USER[$this->role]['profile']);
// break;
// case 'settings':
// $this->renderSettings();
// break;
// case 'integrations':
// case 'bluesky':
// case 'cloudflare':
// case 'facebook':
// case 'google-maps':
// case 'google-my-business':
// case 'helcim':
// case 'instagram':
// case 'square':
// case 'umami':
// $this->renderIntegrations($page);
// break;
// case 'approval':
// $this->renderApprovals();
// break;
// default:
// $this->renderCRUD($page);
// break;
// }
//
// echo jvbLoadingScreen();
// $this->renderFooter();
//
// // Get buffer contents and clean buffer
// return ob_get_clean();
// }
// );
//
// // Return empty string to prevent default template
// return '';
}
protected function renderPage(string $page):string
{
return '
Whoops
It seems this page isn\'t configured yet.
If this keeps happening, maybe contact the admin.
';
}
/**
* Enqueues necessary scripts
* @return void
*/
public function dashboardScripts():void
{
if (!is_singular(BASE.'dash') && !is_post_type_archive(BASE.'dash')) {
return;
}
wp_enqueue_script('jvb-loading');
wp_enqueue_script('jvb-form');
// Consolidate all dashboard settings
wp_localize_script('jvb-loading', 'dashboardSettings', array(
'loadingMessages' => array(
'default' => 'Loading...',
'error' => 'Failed to load page'
),
'strings' => array(
'deleteConfirm' => 'Are you sure you want to delete this item?',
'bulkDeleteConfirm' => 'Are you sure you want to delete these items?',
'deleteSuccess' => 'Item(s) deleted successfully',
'deleteError' => 'Error deleting item(s)',
'saveSuccess' => 'Changes saved successfully',
'saveError' => 'Error saving changes',
'loadError' => 'Error loading content'
),
'currentUser' => array(
'id' => $this->user->ID,
'name' => $this->user->display_name,
'role' => array_values($this->user->roles)[0] ?? '',
'type' => str_replace(BASE, '', array_values($this->user->roles)[0]),
'city' => '', // Add if needed,
'artistID' => $this->userLink,
)
));
wp_enqueue_script('jvb-selector');
wp_enqueue_script('jvb-uploader');
wp_enqueue_script('jvb-content');
wp_enqueue_script('jvb-crud');
$page = $this->getCurrentPage();
switch ($page) {
case 'notifications':
if (Features::forSite()->has('notifications')) {
wp_enqueue_script('jvb-notification-manager');
}
break;
case 'integrations':
wp_enqueue_script('jvb-integrations');
break;
case 'admin':
case 'dash':
if (current_user_can('manage_options') && apply_filters('jvbAdminDashboard', '') === '') {
wp_enqueue_script(
'jvb-admin',
JVB_URL . 'assets/js/min/admin.min.js',
[
'jvb-queue',
'jvb-loading'
],
[
'strategy' => 'defer',
'in_footer' => true
]
);
wp_localize_script(
'jvb-admin',
'jvbAdmin',
[
'nonce' => wp_create_nonce('itsme')
]
);
}
break;
}
if (Features::forSite()->has('favourites')) {
wp_enqueue_script('jvb-favourites');
wp_localize_script('jvb-favourites-manager', 'favouritesSettings', [
'strings' => [
'loadError' => 'Error loading favourites',
'saveError' => 'Error updating favourite',
'removeSuccess' => 'Removed from favourites',
'addSuccess' => 'Added to favourites'
]
]);
}
wp_enqueue_script('jvb-creator');
if (Features::forSite()->has('forum')) {
wp_enqueue_script('jvb-news');
}
do_action('jvbDashScripts', $page);
}
protected function getCurrentPage():string
{
if (is_post_type_archive(BASE.'dash')) {
return 'dash';
}
global $post;
if (!$post) {
return '';
}
return $post->post_name;
}
protected function renderHeader():void
{
?>
>
= (array_key_exists('dashboard_title', JVB_SITE)) ? JVB_SITE['dashboard_title'] : 'Dashboard | '.get_bloginfo('name') ?>
getUserAllowedPages();
foreach($pages as $page) {
$page = str_replace('_', '-', $page);
$link = ($page === 'dash') ? '/'.$page : "/dash/$page";
?>
getCurrentPage());
?>
user->first_name !== '') ? $this->user->first_name : $this->user->display_name;
echo 'Hey '.$name.'
';
echo 'Welcome back!
';
$pages = $this->getUserAllowedPages();
echo 'What would you like to do today?
';
echo '';
echo 'Everything saves auto-magically, so rest easy.
';
return ob_get_clean();
}
/**
* Similar to CRUD, except it only manages a single item, such as a user's profile or a shop
* @param string $type
*
* @return void
*/
protected function renderForm(string $type):void
{
wp_enqueue_script(
'jvb-bio-manager',
JVB_URL.'assets/js/min/bioManager.min.js',
array('jvb-queue', 'sortablejs', 'quill-js', 'jvb-selector'),
'1.0.0',
true
);
wp_localize_script('jvb-bio-manager', 'bioSettings', [
'type' => 'bio_update',
]);
jvbRenderSections($this->userLink, 'post', $type);
}
protected function renderSettings():void
{
wp_enqueue_script('jvb-form');
wp_enqueue_script(
'jvb-bio-manager',
JVB_URL.'assets/js/min/bioManager.min.js',
array('jvb-client-queue', 'sortablejs', 'quill-js', 'jvb-taxonomy-selector'),
'1.0.0',
true
);
wp_localize_script('jvb-bio-manager', 'bioSettings', [
'type' => 'user_settings',
]);
$content = apply_filters('jvbDashboardSettings', '');
if ($content !== '') {
echo $content;
} else {
jvbRenderSections($this->user->ID, 'user', jvbUserRole());
}
}
protected function getIntegrationsMenu():string
{
$integrations = JVB()->getAvailableServices(false);
$out = '';
if (!empty($integrations)) {
$out = '';
}
return $out;
}
protected function renderIntegrations(string $page):void
{
echo $this->getIntegrationsMenu();
$map = [
'google-my-business' => 'gmb',
'google-maps' => 'maps'
];
$connection = (array_key_exists($page, $map)) ? $map[$page] : $page;
if ($connection !== 'integrations') {
$userID = (jvbSiteHasMembership()) ? $this->user->ID : null;
$integration = JVB()->connect($connection, $userID);
echo 'Managing '.$integration->title.'
';
$integration->renderDefaults();
} else {
?>
getAvailableServices();
foreach ($all as $name) {
if (current_user_can('manage_options')) {
$userID = null;
} else {
$userID = $this->user->ID;
}
JVB()->connect($name, $userID)->renderConnection();
}
?>
ArtistsManage artists here
= jvbRenderToggleTextField(
'vertical',
'TAB NAV:',
'',
jvbIcon('down'),
jvbIcon('right'))?>
$settings) {
$meta = new MetaManager(null, 'form');
$fields = jvbGetFields($type);
?>
|
Actions |
$config) {
if (array_key_exists('quickEdit', $config)) {
$extra = '';
switch ($config['type']) {
case 'set':
case 'radio':
$extra = '( '.implode(', ', $config['options']).' )';
break;
case 'repeater':
$temp = [];
foreach ($config['fields'] as $f => $c) {
$temp[] = $c['label'];
}
$extra = '[ '.implode(', ', $temp).' ]';
break;
}
$extra = ($extra === '') ? '' : ''.$extra.'
';
if (!array_key_exists('label', $config)) {
error_log('No label set for: '.print_r($n, true));
}
?>
= $config['label'].$extra ?>
|
|
= jvbIcon('grab') ?>
|
= jvbRenderToggleTextField(
'public',
'',
'',
jvbIcon('show'),
jvbIcon('hide'))
?>
|
$config) {
if (array_key_exists('quickEdit', $config)) {
?>
render('form', $n, $config);
?>
|
renderForm('admin', [], $fields)
);
}
return ob_get_clean();
}
/**
* Get all possible dashboard pages regardless of user
* Used during dashboard build process
* @return array
*/
protected function getAllDashboardPages():array
{
$cacheKey = 'all_pages';
$pages = $this->cache->get($cacheKey);
if ($pages === false || JVB_TESTING) {
$pages = [];
// Add feature-dependent pages (non-config)
if (Features::forSite()->has('referrals')) {
$pages[] = 'referrals';
}
if (Features::forMembership()->has('can_invite')) {
$pages[] = 'invites';
}
if (Features::forMembership()->has('term_approval')) {
$pages[] = 'approvals';
}
if (Features::forMembership()->has('forum')) {
$pages[] = 'news';
}
if (Features::forMembership()->has('member_content')) {
$pages[] = 'metrics';
}
if (Features::forSite()->has('favourites')) {
$pages[] = 'favourites';
}
if (Features::anyContentHas('karma') || Features::anyTaxonomyHas('karma') || Features::anyUserHas('karma')) {
$pages[] = 'karmic-score';
}
if (Features::forSite()->has('notifications')) {
$pages[] = 'notifications';
}
if (Features::forSite()->has('support')) {
$pages[] = 'support';
}
if (Features::hasAnyIntegration()) {
$pages[] = 'integrations';
}
// Add all content types (with config keys)
foreach (JVB_CONTENT as $slug => $config) {
$pages[$slug] = sanitize_title($config['plural']);
}
foreach (JVB_TAXONOMY as $slug=>$config) {
$pages[$slug] = sanitize_title($config['plural']);
}
// Allow filtering
$pages = apply_filters('jvbAllDashboardPages', $pages);
// Remove duplicates while preserving keys
$pages = array_unique($pages);
// Dash home always first
array_unshift($pages, 'dash');
$this->cache->set($cacheKey, $pages, WEEK_IN_SECONDS);
}
return $pages;
}
/**
* Get pages available to a specific role
* @param string $role The role slug (with or without BASE prefix)
* @return array
*/
protected function getRolePages(string $role):array
{
$role = jvbNoBase($role);
if (!array_key_exists($role, JVB_USER)) {
return [];
}
return Features::forUser($role)->getDashboardPages();
}
/**
* Get pages that a specific user is allowed to access
* Filters based on capabilities and features
* @param int|null $userID Optional user ID (defaults to current user)
* @return array
*/
public function getUserAllowedPages(?int $userID = null):array
{
if ($userID === null) {
$user = $this->user;
$userID = $user->ID;
} else {
$user = get_userdata($userID);
}
if (!$user || !$this->userHasDashboardAccess($user)) {
return [];
}
$cacheKey = "user_pages_{$userID}";
$pages = $this->cache->get($cacheKey);
if ($pages === false || JVB_TESTING) {
if (user_can($userID, 'manage_options')) {
// Admin gets all pages as flat array
$pages = $this->getAllDashboardPages();
// Extract just the values (slugs)
$this->cache->set($cacheKey, $pages, WEEK_IN_SECONDS);
return $pages;
}
$roles = array_map('jvbNoBase', $user->roles);
$pages = $this->getAllDashboardPages();
$canSkip = user_can($userID, 'skip_moderation');
foreach($pages as $key => $slug) {
//Default to Remove pages
$remove = true;
if (!is_numeric($key)) {
$type = Features::getType($key);
if ($type) {
$permission = RoleManager::getPlural($key);
}
switch ($type) {
case 'content':
if (!user_can($userID, "edit_{$permission}")) {
$remove = false;
}
break;
case 'taxonomy':
$config = Features::getConfig($key, 'taxonomy');
if (array_key_exists('is_content', $config) && $config['is_content'] && (user_can($userID, "own_{$key}") || user_can($userID, "manage_{$key}"))) {
$remove = false;
}
break;
}
} else {
switch ($slug) {
case 'integrations':
foreach($roles as $role) {
if (Features::hasAnyIntegration('user', $role)) {
$remove = false;
}
}
break;
case 'invites':
$canInvite = JVB_MEMBERSHIP['can_invite']??[];
foreach ($roles as $role) {
if (array_key_exists($role, $canInvite)) {
$remove = false;
}
}
if ($remove) {
if ($canSkip || array_key_exists('invitable', $config)) {
$remove = false;
}
}
break;
case 'approvals':
$canApprove = false;
if (Features::forMembership()->has('term_approval')) {
if (array_key_exists('can_approve', JVB_MEMBERSHIP)) {
foreach ($roles as $role) {
if (in_array($role, JVB_MEMBERSHIP['can_approve'])) {
$canApprove = true;
}
}
} else {
//Anyone can approve
$canApprove = true;
}
}
if ($canSkip && $canApprove) {
$remove = false;
}
break;
case 'news':
$canAccess = false;
if (array_key_exists('member_only', JVB_MEMBERSHIP)){
foreach ($roles as $role) {
if (in_array($role, JVB_MEMBERSHIP['member_only'])) {
$canAccess = true;
}
}
}
if ($canAccess && $canSkip) {
$remove = false;
}
break;
case 'metrics':
foreach ($roles as $role) {
if (!empty(Features::forUser($role)->getCreatableContent())) {
$remove = false;
}
}
break;
case 'karmic-score':
foreach ($roles as $role) {
$contents = Features::forUser($role)->getCreatableContent();
if (!empty($contents)) {
foreach($contents as $content) {
if (Features::forContent($content)->has('karma')) {
$remove = false;
}
}
}
}
break;
case 'favourites':
case 'notifications':
case 'support':
$remove = false;
break;
default:
break;
}
if ($remove) {
unset($pages[$key]);
}
}
}
//Allow Filtering
$pages = apply_filters('jvbUserDashboardPages', $pages, $user->roles, $userID);
$pages = array_unique($pages);
$this->cache->set($cacheKey, $pages, WEEK_IN_SECONDS);
}
return $pages;
}
/**
* Check if user can create content
* Replaces jvbUserCanCreate()
* @param int $userID
* @return bool
*/
protected function userCanCreate(int $userID = 0):bool
{
$user = ($userID === 0) ? wp_get_current_user() : get_userdata($userID);
$roles = array_intersect(
$this->getRolesWithDashboard(),
array_map('jvbNoBase', $user->roles)
);
$creatable = [];
foreach ($roles as $role) {
$roleCreatable = Features::forUser($role)->getCreatableContent();
$creatable = array_merge($creatable, $roleCreatable);
}
return !empty($creatable);
}
/**
* Get user roles that have dashboard access
* Replaces jvbRolesWithDashboard()
* @return array
*/
protected function getRolesWithDashboard():array
{
return array_keys(array_filter(JVB_USER, function ($role) {
return Features::forUser(array_search($role, JVB_USER))->has('has_dashboard');
}));
}
/**
* Check if user has dashboard access
* @param WP_User $user
* @return bool
*/
protected function userHasDashboardAccess(WP_User $user):bool
{
if (user_can($user, 'manage_options')) {
return true;
}
$userRoles = array_map('jvbNoBase', $user->roles);
$dashboardRoles = $this->getRolesWithDashboard();
return count(array_intersect($dashboardRoles, $userRoles)) > 0;
}
/**
* Get the capability needed to access a content type
* @param string $type
* @return string
*/
protected function getPermissionForType(string $type):string
{
// Check if it's a registered content type
if (array_key_exists($type, JVB_CONTENT)) {
$plural = JVB_CONTENT[$type]['plural'];
return 'edit_'.$plural;
}
// Default to edit_{type}s
return 'edit_'.$type.'s';
}
/**
* Invalidate dashboard page cache for a user or all users
* Call this when user roles or permissions change
* @param int|null $userID Specific user to invalidate, null for all
* @return void
*/
public function invalidatePagesCache(?int $userID = null):void
{
if ($userID !== null) {
$this->cache->delete("user_pages_{$userID}");
} else {
// Invalidate all user caches by invalidating the group
$this->cache->invalidate();
}
}
}