From ca458bb8ae09d6f9c44b78e6ad619152475a391c Mon Sep 17 00:00:00 2001 From: James Griffin Date: Mon, 8 Jun 2026 11:06:47 -0300 Subject: [PATCH] Group the studio admin menu into three sections with separators MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add sidebar separators (wp-menu-separator) that set the studio menus apart from the core WordPress items and split them into three sections: [sep] Studio Settings · Policies · Invites · Offerings [sep] Students · Group Classes · Payments [sep] Scheduler (then the instructor menus: My Availability, My Lessons) Separators live at positions 29 / 34 / 38; each is only added when the user can see a menu in the following section, to avoid orphaned dividers. Co-Authored-By: Claude Opus 4.8 --- src/AdminMenu.php | 75 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 67 insertions(+), 8 deletions(-) diff --git a/src/AdminMenu.php b/src/AdminMenu.php index ac757b3..0b894c1 100644 --- a/src/AdminMenu.php +++ b/src/AdminMenu.php @@ -58,6 +58,8 @@ class AdminMenu { } public function addPages(): void { + $this->addStudioSeparators(); + // Studio-wide dashboard: all upcoming lessons across instructors. add_menu_page( __( 'Scheduler', 'unsupervised-schedular' ), @@ -66,7 +68,7 @@ class AdminMenu { 'us-scheduler', [ $this->lessonController, 'renderAdminDashboard' ], 'dashicons-calendar-alt', - 30 + 39 ); // Instructor: manage their own availability. @@ -77,7 +79,7 @@ class AdminMenu { 'us-availability', [ $this->availabilityController, 'renderPage' ], 'dashicons-clock', - 31 + 40 ); // Studio admin / instructor: manage offerings. @@ -109,7 +111,7 @@ class AdminMenu { 'us-policies', [ $this->policyController, 'renderPage' ], 'dashicons-text-page', - 34 + 31 ); // Studio admin: invite students to register. @@ -120,7 +122,7 @@ class AdminMenu { 'us-invites', [ $this->registrationController, 'renderPage' ], 'dashicons-email', - 35 + 32 ); // Studio admin: all group-class enrolments. @@ -142,7 +144,7 @@ class AdminMenu { 'us-students', [ $this->studentController, 'renderPage' ], 'dashicons-id', - 37 + 35 ); // Studio admin: confirm pending (e-transfer) payments. @@ -153,7 +155,7 @@ class AdminMenu { 'us-payments', [ $this->paymentController, 'renderPage' ], 'dashicons-money-alt', - 38 + 37 ); // Studio admin: Stripe credentials and billing settings. @@ -164,7 +166,7 @@ class AdminMenu { 'us-settings', [ $this->settings, 'renderPage' ], 'dashicons-admin-settings', - 39 + 30 ); // Instructor: view their upcoming lessons. @@ -175,7 +177,64 @@ class AdminMenu { 'us-my-lessons', [ $this->lessonController, 'renderInstructorLessons' ], 'dashicons-welcome-learn-more', - 32 + 41 ); } + + /** + * Insert sidebar separators around the studio menus so they sit visually + * apart from the core WordPress items and split into three sections — + * mirroring the dividers core uses. Each separator is only added when the user + * can see a menu in the following section, to avoid orphaned dividers. + * + * Layout: [29] · setup (Settings/Policies/Invites/Offerings) · [34] · + * people & money (Students/Group Classes/Payments) · [38] · operations + * (Scheduler) and instructor menus. + */ + private function addStudioSeparators(): void { + $this->addSeparatorAt( 29, $this->userSeesStudioMenu() ); + $this->addSeparatorAt( 34, $this->userSeesPeopleSection() ); + $this->addSeparatorAt( 38, current_user_can( RoleManager::CAP_VIEW_ALL_LESSONS ) ); + } + + private function addSeparatorAt( int $position, bool $visible ): void { + if ( ! $visible ) { + return; + } + + global $menu; + if ( ! is_array( $menu ) || isset( $menu[ $position ] ) ) { + return; + } + + // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- writing to $menu is the supported way to add an admin sidebar separator. + $menu[ $position ] = [ '', 'read', 'us-studio-separator-' . $position, '', 'wp-menu-separator' ]; + } + + private function userSeesPeopleSection(): bool { + return current_user_can( RoleManager::CAP_MANAGE_STUDENTS ) + || current_user_can( RoleManager::CAP_VIEW_ALL_LESSONS ) + || current_user_can( RoleManager::CAP_MANAGE_BILLING ); + } + + private function userSeesStudioMenu(): bool { + $caps = [ + RoleManager::CAP_VIEW_ALL_LESSONS, + RoleManager::CAP_VIEW_LESSONS, + RoleManager::CAP_MANAGE_AVAILABILITY, + RoleManager::CAP_MANAGE_OFFERINGS, + RoleManager::CAP_MANAGE_QUESTIONS, + RoleManager::CAP_MANAGE_POLICIES, + RoleManager::CAP_MANAGE_STUDENTS, + RoleManager::CAP_MANAGE_BILLING, + ]; + + foreach ( $caps as $cap ) { + if ( current_user_can( $cap ) ) { + return true; + } + } + + return false; + } }