cache = new CacheManager('dashboard'); $this->cache->invalidateGroup('dashboard'); 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_include', [$this, 'dashboardTemplates']); add_action('admin_init', [$this, 'redirectFromAdmin']); add_action('wp_enqueue_scripts', [$this, 'dashboardScripts'], 50); } /** * 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 wp_redirect(home_url('dash')); exit; } /** * Ensures the necessary pages ar created * @return void */ public function buildDashboard():void { $manageableContent = jvbGetAllDashboardPages(); foreach ($manageableContent as $slug) { $title = $this->getTitle($slug); $slug = sanitize_title($title); $ID = wp_insert_post(array( 'post_title' => $title, 'post_name' => $slug, 'post_type' => BASE.'dash', 'post_status' => 'publish', )); if ($title === 'Integrations') { $integrations = ['BlueSky', 'Cloudflare', 'Facebook', 'Google Maps', 'Google My Business', 'Helcim', 'Instagram', 'Square', 'Umami']; foreach ($integrations as $integration) { $slug = sanitize_title($integration); wp_insert_post([ 'post_title' => $integration, 'post_name' => $slug, 'post_type' => BASE.'dash', 'post_status' => 'publish', 'post_parent' => $ID ]); } } } update_option(BASE.'dashboard_registered', true); remove_action('init', [$this, 'buildDashboard']); } protected function getAllDashboardPages():array { $manageableContent = get_option(BASE.'all_dashboard_pages'); if (JVB_TESTING) { $manageableContent = false; } if ($manageableContent === false) { $manageableContent = []; $bios = []; foreach (JVB_USER as $role => $config) { $manageableContent = array_merge($manageableContent, jvbRolePages($role)); } if (Features::forSite()->has('referrals')) { $manageableContent[] = 'referrals'; } foreach (JVB_TAXONOMY as $tax => $config) { if (Features::forTaxonomy($tax)->has('is_content')) { $manageableContent[] = strtolower($config['plural']); } } if (Features::forMembership()->has('can_invite')) { $manageableContent[] = 'invites'; } if (Features::forMembership()->has('term_approval')) { $manageableContent[] = 'approvals'; } if (Features::forMembership()->has('forum')) { $manageableContent[] = 'news'; } if (Features::forMembership()->has('member_content')) { $manageableContent[] = 'metrics'; } if (!empty($bios)) { $manageableContent[] = 'bio'; } if (Features::forSite()->has('favourites')) { $manageableContent[] = 'favourites'; } if (Features::anyContentHas('karma') || Features::anyTaxonomyHas('karma') || Features::anyUserHas('karma')){ $manageableContent[] = 'karmic-score'; } if (Features::forSite()->has('notifications')) { $manageableContent[] = 'notifications'; } if (Features::forSite()->has('support')){ $manageableContent[] = 'support'; } if (Features::hasAnyIntegration()) { $manageableContent[] = 'integrations'; } $manageableContent[] = 'admin'; $manageableContent = apply_filters('jvbDashboardPages', $manageableContent); $manageableContent = array_unique($manageableContent); sort($manageableContent); $manageableContent = array_map(function ($content) { return str_replace('_', '-', $content); }, $manageableContent); update_option(BASE.'all_dashboard_pages', $manageableContent); } return $manageableContent; } protected function getRolePages(string $role):array { if (!array_key_exists(jvbNoBase($role), JVB_USER)) { return []; } $manageableContent = get_option(BASE.$role.'_pages'); if (JVB_TESTING) { $manageableContent = false; } if ($manageableContent === false) { $manageableContent = []; $config = JVB_USER[$role]; $content = $config['can_create']; $settings = $bio = false; if (array_key_exists('profile', $config)) { $manageableContent[] = $config['profile']; } foreach ($content as $c) { if (is_array($c)) { foreach ($c as $type => $contents) { $manageableContent = array_merge($manageableContent, $contents); } } else { $manageableContent = array_merge($manageableContent, [$c]); } } if (array_key_exists('has_dashboard', $config)) { $manageableContent[] = 'settings'; } update_option(BASE.$role.'_pages', $manageableContent); } return $manageableContent; } protected function getTitle(string $page):string { $content = JVB_CONTENT; $contentTax = array_filter(JVB_TAXONOMY, function ($tax) { return jvbCheck('is_content', $tax); }); $content = array_merge($content, $contentTax); $title = ''; if (array_key_exists($page, $content)) { $config = $content[$page]; $title = (array_key_exists('dash_title', $config)) ? $config['dash_title'] : $config['plural']; } else { switch ($page) { case 'admin': $title = 'Admin'; break; default: $title = ucwords(str_replace('_', ' ', str_replace('-', ' ', $page))); } } return $title; } protected function getDescription(string $page):string { $content = JVB_CONTENT; $contentTax = array_filter(JVB_TAXONOMY, function ($tax) { return jvbCheck('is_content', $tax); }); $content = array_merge($content, $contentTax); if (array_key_exists($page, $content)) { $config = $content[$page]; $description = (array_key_exists('dash_description', $config)) ? $config['dash_description'] : ''; } else { 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; } if (!isOurPeople() && !current_user_can('manage_options')) { error_log('Redirecting because:'); if (!isOurPeople()) { error_log('Not our people'); } if (!current_user_can('manage_options')) { error_log('Cannot manage options'); } wp_redirect(wp_login_url(get_home_url(null, '/dash'))); exit; } // Get current page/section $page = $this->getCurrentPage(); switch ($page) { case 'integrations': if (!Features::hasAnyIntegration('user', $this->role)) { wp_redirect(get_home_url(null, '/dash')); exit; } break; case 'bluesky': case 'cloudflare': case 'facebook': case 'google-maps': case 'google-my-business': case 'helcim': case 'instagram': case 'square': case 'umami': if (!Features::hasIntegration($page,'user', $this->role)) { wp_redirect(get_home_url(null, '/dash')); exit; } break; case 'bio': $permission = JVB_USER[$this->role]['profile']??false; if (!$permission || (!current_user_can('manage_'.$permission) && !current_user_can('manage_options'))) { wp_redirect(get_home_url(null, '/dash')); exit; } break; case 'settings': if (!current_user_can('manage_settings') && !current_user_can('manage_options')) { wp_redirect(get_home_url(null, '/dash')); exit; } break; case 'approval': if (!current_user_can('skip_moderation')) { wp_redirect(get_home_url(null, '/dash')); exit; } break; case 'dash': break; default: $type = match($page) { 'menu-item' => 'menu_item', 'events' => 'event', default => $page }; $permission = strtolower(str_replace(' ', '_',JVB_CONTENT[$type]['plural']??$type.'s')); if (!current_user_can('edit_'.$permission)) { error_log('User cannot edit: '.$permission); wp_redirect(get_home_url(null, '/dash')); exit; } break; } // Enqueue needed styles/scripts jvbInlineStyles('nav'); jvbInlineStyles('dash'); jvbInlineStyles('forms'); $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 ''; } /** * Enqueues necessary scripts * @return void */ public function dashboardScripts():void { if (is_post_type_archive(BASE.'dash') || is_singular(BASE.'dash')) { // wp_enqueue_style('quill-css', 'https://cdn.quilljs.com/1.3.6/quill.snow.css'); 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'); // wp_enqueue_script('jvb-dashboard-navigator'); $page = $this->getCurrentPage(); switch ($page) { case 'notifications': if (jvbSiteHasNotifications()) { 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 (jvbSiteHasFavourites()) { 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 (jvbSiteHasForum()) { wp_enqueue_script('jvb-news'); } do_action('jvbDashScripts', $page); } } protected function getCurrentPage():string { global $wp; $dash = str_replace('dash/', '', $wp->request); if (str_starts_with($dash, 'integrations/')) { $dash = str_replace('integrations/', '', $dash); } return ($dash === '') ? 'dash' : $dash; } protected function renderHeader():void { ?> > <?= (array_key_exists('dashboard_title', JVB_SITE)) ? JVB_SITE['dashboard_title'] : 'Dashboard | '.get_bloginfo('name') ?>
'. jvbIcon('light'). jvbIcon('dark').''; ?>

getCurrentPage()); ?> userLink, BASE.'firstname', true); $name = ($name === '') ? $this->user->display_name : $name; echo '

Hey '.$name.'

'; echo '

Welcome back!

'; $pages = jvbGetUserDashboardPages(); echo '

What would you like to do today?

'; global $jvb_everything; echo ''; echo '

Everything saves auto-magically, so rest easy.

'; } /** * 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(); } ?>
Name Requester Actions
Name Requester Actions
'menu_item', 'events' => 'event', default => $type }; $crud = new CRUD($type); $crud->render(); } protected function renderAdmin():void { ?>

ArtistsManage artists here

$settings) { $meta = new MetaManager(null, 'form'); $fields = jvbGetFields($type); ?> renderForm('admin', [], $fields) ); } } }