From 406bc54174789f7f83cddc1cefede77b4caee5dd Mon Sep 17 00:00:00 2001 From: Miguel Peixe Date: Fri, 25 Oct 2024 13:49:45 -0300 Subject: [PATCH] refactor: wizards menu order handling --- includes/class-newspack.php | 6 +- includes/class-wizards.php | 46 +++++++++++++-- .../class-advertising-display-ads.php | 17 +++++- .../class-advertising-sponsors.php | 27 ++++----- includes/wizards/class-components-demo.php | 7 --- includes/wizards/class-network-wizard.php | 44 +++++++------- includes/wizards/class-newsletters-wizard.php | 57 ++++--------------- includes/wizards/class-wizard.php | 31 ++++++---- .../newspack/class-newspack-dashboard.php | 7 --- .../newspack/class-newspack-settings.php | 11 +--- 10 files changed, 122 insertions(+), 131 deletions(-) diff --git a/includes/class-newspack.php b/includes/class-newspack.php index 138f73b1c7..8b11bb60da 100644 --- a/includes/class-newspack.php +++ b/includes/class-newspack.php @@ -127,7 +127,7 @@ private function includes() { include_once NEWSPACK_ABSPATH . 'includes/wizards/class-setup-wizard.php'; include_once NEWSPACK_ABSPATH . 'includes/wizards/class-components-demo.php'; - + include_once NEWSPACK_ABSPATH . 'includes/wizards/traits/trait-wizards-admin-header.php'; // Newspack Wizards and Sections. @@ -140,8 +140,8 @@ private function includes() { include_once NEWSPACK_ABSPATH . 'includes/wizards/class-setup-wizard.php'; include_once NEWSPACK_ABSPATH . 'includes/wizards/class-components-demo.php'; - - // Advertising Wizard. + + // Advertising Wizard. include_once NEWSPACK_ABSPATH . 'includes/wizards/advertising/class-advertising-display-ads.php'; include_once NEWSPACK_ABSPATH . 'includes/wizards/advertising/class-advertising-sponsors.php'; diff --git a/includes/class-wizards.php b/includes/class-wizards.php index 76984a7c8b..766c5cb410 100644 --- a/includes/class-wizards.php +++ b/includes/class-wizards.php @@ -44,22 +44,25 @@ public static function init() { 'settings' => new Settings(), // v2 Information Architecture. 'newspack-dashboard' => new Newspack_Dashboard(), - 'newspack-settings' => new Newspack_Settings( + 'newspack-settings' => new Newspack_Settings( [ 'sections' => [ 'custom-events' => 'Newspack\Wizards\Newspack\Custom_Events_Section', 'social-pixels' => 'Newspack\Wizards\Newspack\Pixels_Section', 'recirculation' => 'Newspack\Wizards\Newspack\Recirculation_Section', ], - ] + ] ), 'advertising-display-ads' => new Advertising_Display_Ads(), 'advertising-sponsors' => new Advertising_Sponsors(), + 'network' => new Network_Wizard(), + 'newsletters' => new Newsletters_Wizard(), ]; - // Not needed in $wizards[] since it's just for Admin Headers, not full react pages. - new Network_Wizard(); - new Newsletters_Wizard(); + // Allow custom menu order. + add_filter( 'custom_menu_order', '__return_true' ); + // Fix menu order for wizards with parent menu items. + add_filter( 'menu_order', [ __CLASS__, 'menu_order' ], 11 ); } /** @@ -134,5 +137,38 @@ public static function is_completed( $wizard_slug ) { return false; } + + /** + * Update menu order for wizards with parent menu items. + * + * @param array $menu_order The current menu order. + * + * @return array The updated menu order. + */ + public static function menu_order( $menu_order ) { + $index = array_search( 'newspack-dashboard', $menu_order, true ); + if ( false === $index ) { + return $menu_order; + } + $ordered_wizards = []; + foreach ( self::$wizards as $slug => $wizard ) { + if ( ! empty( $wizard->parent_menu ) && ! empty( $wizard->menu_order ) ) { + $ordered_wizards[ $wizard->menu_order ] = $wizard->parent_menu; + } + } + if ( empty( $ordered_wizards ) ) { + return $menu_order; + } + ksort( $ordered_wizards ); + foreach ( array_reverse( $ordered_wizards ) as $menu_item ) { + $key = array_search( $menu_item, $menu_order, true ); + if ( false === $key ) { + continue; + } + array_splice( $menu_order, $key, 1 ); + array_splice( $menu_order, $index + 1, 0, $menu_item ); + } + return $menu_order; + } } Wizards::init(); diff --git a/includes/wizards/advertising/class-advertising-display-ads.php b/includes/wizards/advertising/class-advertising-display-ads.php index 77e9279cc1..1470083e22 100644 --- a/includes/wizards/advertising/class-advertising-display-ads.php +++ b/includes/wizards/advertising/class-advertising-display-ads.php @@ -55,6 +55,20 @@ class Advertising_Display_Ads extends Wizard { ), ); + /** + * The parent menu item name. + * + * @var string + */ + public $parent_menu = 'advertising-display-ads'; + + /** + * Order relative to the Newspack Dashboard menu item. + * + * @var int + */ + public $menu_order = 4; + /** * Constructor. */ @@ -546,8 +560,7 @@ public function add_page() { $this->capability, $this->slug, array( $this, 'render_wizard' ), - $icon, - 3.5 + $icon ); add_submenu_page( $this->slug, diff --git a/includes/wizards/advertising/class-advertising-sponsors.php b/includes/wizards/advertising/class-advertising-sponsors.php index 5677b958bc..f7b0f2529d 100644 --- a/includes/wizards/advertising/class-advertising-sponsors.php +++ b/includes/wizards/advertising/class-advertising-sponsors.php @@ -21,21 +21,21 @@ class Advertising_Sponsors extends Wizard { /** * Newspack Sponsors CPT name. - * + * * @var string */ const CPT_NAME = 'newspack_spnsrs_cpt'; /** * Sponsors CPT list path. - * + * * @var string */ const URL = 'edit.php?post_type=newspack_spnsrs_cpt'; - /** + /** * Advertising Page path. - * + * * @var string */ const PARENT_URL = 'admin.php?page=advertising-display-ads'; @@ -47,13 +47,6 @@ class Advertising_Sponsors extends Wizard { */ protected $capability = 'manage_options'; - /** - * High menu priority since we need core registrations to exist before we can modify them. - * - * @var int - */ - protected $menu_priority = 99; - /** * Advertising_Sponsors Constructor. */ @@ -83,8 +76,8 @@ public function __construct() { 'textContent' => esc_html__( 'Settings', 'newspack-plugin' ), 'href' => admin_url( static::URL . '&page=newspack-sponsors-settings-admin' ), ], - ], - 'title' => $this->get_name(), + ], + 'title' => $this->get_name(), ] ); } @@ -174,7 +167,7 @@ public function update_sponsors_cpt_args( $args, $post_type ) { * Parent file filter. Used to determine active menu items. * * @param string $parent_file Parent file to be overridden. - * @return string + * @return string */ public function parent_file( $parent_file ) { global $pagenow, $typenow; @@ -182,11 +175,11 @@ public function parent_file( $parent_file ) { if ( in_array( $pagenow, [ 'post.php', 'post-new.php' ] ) && $typenow === static::CPT_NAME ) { return 'advertising-display-ads'; } - + if ( isset( $_GET['page'] ) && $_GET['page'] === 'newspack-sponsors-settings-admin' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended return static::PARENT_URL; } - + return $parent_file; } @@ -200,7 +193,7 @@ public function submenu_file( $submenu_file ) { if ( isset( $_GET['page'] ) && $_GET['page'] === 'newspack-sponsors-settings-admin' ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended return static::URL; } - + return $submenu_file; } } diff --git a/includes/wizards/class-components-demo.php b/includes/wizards/class-components-demo.php index cfe3138782..4f0fd7a20c 100644 --- a/includes/wizards/class-components-demo.php +++ b/includes/wizards/class-components-demo.php @@ -30,13 +30,6 @@ class Components_Demo extends Wizard { */ protected $capability = 'manage_options'; - /** - * Priority setting for ordering admin submenu items. - * - * @var int. - */ - protected $menu_priority = 100; - /** * Whether the wizard should be displayed in the Newspack submenu. * diff --git a/includes/wizards/class-network-wizard.php b/includes/wizards/class-network-wizard.php index ba3a2a5fbd..1cd66d798d 100644 --- a/includes/wizards/class-network-wizard.php +++ b/includes/wizards/class-network-wizard.php @@ -30,6 +30,20 @@ class Network_Wizard extends Wizard { */ private $screen_type = ''; + /** + * The parent menu item name. + * + * @var string + */ + public $parent_menu = 'newspack-network'; + + /** + * Order relative to the Newspack Dashboard menu item. + * + * @var int + */ + public $menu_order = 5; + /** * Constructor. */ @@ -38,7 +52,7 @@ public function __construct() { if ( ! is_plugin_active( 'newspack-network/newspack-network.php' ) ) { return; } - + // Admin screens based on Newspack Network plugin's admin pages and post types. $this->admin_screens = [ 'page' => [ @@ -55,8 +69,8 @@ public function __construct() { ], ]; - // Move entire Network Menu. Use a high priority to load after Network Plugin itself loads. - add_action( 'admin_menu', [ $this, 'move_menu' ], 99 ); + // Update menu information. + add_action( 'admin_menu', [ $this, 'modify_menu' ], 11 ); // Use current_screen for better detection of which admin screen we might be on. add_action( 'current_screen', [ $this, 'current_screen' ] ); @@ -77,7 +91,7 @@ public function current_screen() { } // Check for admin post type screen: Listings page and classic editor (add new + edit), but not block editor. - if ( ! empty( $current_screen->post_type ) + if ( ! empty( $current_screen->post_type ) && ! empty( $this->admin_screens['post_type'][ $current_screen->post_type ] ) && false === $current_screen->is_block_editor ) { $this->slug = $current_screen->post_type; @@ -120,10 +134,9 @@ public function is_wizard_page() { * * @return void */ - public function move_menu() { - + public function modify_menu() { global $menu; - + // Find the Newspack Network menu item in the admin menu. $network_key = null; foreach ( $menu as $k => $v ) { @@ -133,29 +146,16 @@ public function move_menu() { break; } } - + // Verify a key was found. if ( empty( $network_key ) ) { return; } - + // Adjust the network menu attributes. // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited $menu[ $network_key ][0] = __( 'Network', 'newspack-plugin' ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited $menu[ $network_key ][6] = 'data:image/svg+xml;base64,' . base64_encode( '' ); - - // Try to move the network item to a higher position near "Newspack". - $new_position = '3.9'; - - // if position/key collision, keep increasing increment. - while ( array_key_exists( $new_position, $menu ) ) { - $new_position .= '9'; - } - - // Move network menu in the array. - // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited - $menu[ $new_position ] = $menu[ $network_key ]; - unset( $menu[ $network_key ] ); } } diff --git a/includes/wizards/class-newsletters-wizard.php b/includes/wizards/class-newsletters-wizard.php index 3e0fb380ac..12e50f6bfb 100644 --- a/includes/wizards/class-newsletters-wizard.php +++ b/includes/wizards/class-newsletters-wizard.php @@ -30,11 +30,18 @@ class Newsletters_Wizard extends Wizard { private $admin_screens = []; /** - * Must be run after Newsletters Plugin. + * The parent menu item name. * - * @var int. + * @var string */ - protected $menu_priority = 11; + public $parent_menu = 'edit.php?post_type=newspack_nl_cpt'; + + /** + * Order relative to the Newspack Dashboard menu item. + * + * @var int + */ + public $menu_order = 2; /** * Constructor. @@ -94,10 +101,6 @@ public function __construct() { * Adjusts the Newsletters menu. Called from parent constructor 'admin_menu'. */ public function add_page() { - - // Move the entire Newsletters CPT menu. - $this->move_cpt_menu(); - // Remove "Add New" menu item. remove_submenu_page( 'edit.php?post_type=' . Newspack_Newsletters::NEWSPACK_NEWSLETTERS_CPT, 'post-new.php?post_type=' . Newspack_Newsletters::NEWSPACK_NEWSLETTERS_CPT ); @@ -270,46 +273,6 @@ public function is_wizard_page() { return isset( $this->admin_screens[ $this->get_screen_slug() ] ); } - /** - * Move CPT Menu using a decimal value. (CPT objects only allow integer positions). - * - * @return void - */ - private function move_cpt_menu() { - - // @todo: Is there a better way to set a CPT Menu position to a decimal value???? - - global $menu; - - // Look for the Newsletters parent menu in the admin menu. - $current_position = null; - foreach ( $menu as $position => $item ) { - // Test each item until found. - if ( $item[2] === 'edit.php?post_type=' . Newspack_Newsletters::NEWSPACK_NEWSLETTERS_CPT ) { - $current_position = $position; - break; - } - } - - // Verify a key was found. - if ( empty( $current_position ) ) { - return; - } - - // Move the item to a higher position near "Newspack". - $new_position = '3.3'; - - // if position/key collision, keep increasing increment... 3.3 => 3.33 => 3.333 ... - while ( array_key_exists( $new_position, $menu ) ) { - $new_position .= '3'; - } - - // Move menu in the array. - // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited - $menu[ $new_position ] = $menu[ $current_position ]; - unset( $menu[ $current_position ] ); - } - /** * Callback when Newsletters CPT is registered. * diff --git a/includes/wizards/class-wizard.php b/includes/wizards/class-wizard.php index b9ce4073c9..976c81cada 100644 --- a/includes/wizards/class-wizard.php +++ b/includes/wizards/class-wizard.php @@ -40,30 +40,37 @@ abstract class Wizard { protected $hidden = false; /** - * Priority setting for ordering admin submenu items. + * Array to store instances of section objects. * - * @var int. + * @var Wizards\Section[] */ - protected $menu_priority = 2; + protected $sections = []; /** - * Array to store instances of section objects. + * The parent menu item name. * - * @var Wizards\Section[] + * @var string */ - protected $sections = []; + public $parent_menu = ''; + + /** + * Order relative to the Newspack Dashboard menu item. + * + * @var int + */ + public $menu_order = 0; /** * Initialize. * * @param array $args Array of optional arguments. i.e. `sections`. - * @return void - * + * @return void + * * @example * $my_wizard = new My_Wizard( [ 'sections' => [ 'my-wizard-section' => 'Newspack\Wizards\My_Wizard\My_Wizard_Section' ] ] ); */ public function __construct( $args = [] ) { - add_action( 'admin_menu', [ $this, 'add_page' ], $this->menu_priority ); + add_action( 'admin_menu', [ $this, 'add_page' ], 2 ); add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_scripts_and_styles' ] ); if ( isset( $args['sections'] ) ) { $this->load_wizard_sections( $args['sections'] ); @@ -98,7 +105,7 @@ public function render_wizard() { /** * Is Wizard admin page being viewed. * - * @return bool + * @return bool */ public function is_wizard_page() { return filter_input( INPUT_GET, 'page', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) === $this->slug; @@ -277,7 +284,7 @@ abstract public function get_name(); /** * Load wizard sections. - * + * * @param string[] $sections Array of Section class names. */ public function load_wizard_sections( $sections ) { @@ -291,7 +298,7 @@ public function load_wizard_sections( $sections ) { /** * Add body class for wizard pages. - * + * * @param string $classes The current body classes. */ public function add_body_class( $classes ) { diff --git a/includes/wizards/newspack/class-newspack-dashboard.php b/includes/wizards/newspack/class-newspack-dashboard.php index 3753763022..1e10c74dd8 100644 --- a/includes/wizards/newspack/class-newspack-dashboard.php +++ b/includes/wizards/newspack/class-newspack-dashboard.php @@ -28,13 +28,6 @@ class Newspack_Dashboard extends Wizard { */ protected $capability = 'manage_options'; - /** - * Priority setting for ordering admin submenu items. Dashboard must come first. - * - * @var int. - */ - protected $menu_priority = 1; - /** * Initialize. */ diff --git a/includes/wizards/newspack/class-newspack-settings.php b/includes/wizards/newspack/class-newspack-settings.php index 7df16a7aa1..9251940da7 100644 --- a/includes/wizards/newspack/class-newspack-settings.php +++ b/includes/wizards/newspack/class-newspack-settings.php @@ -35,17 +35,10 @@ class Newspack_Settings extends Wizard { */ protected $capability = 'manage_options'; - /** - * Priority setting for ordering admin submenu items. Settings must come second. - * - * @var int. - */ - protected $menu_priority = 2; - /** * Get Settings local data * - * @return [] + * @return [] */ public function get_local_data() { $google_site_kit_url = google_site_kit_available() ? admin_url( 'admin.php?page=googlesitekit-settings#/connected-services/analytics-4' ) : admin_url( 'admin.php?page=googlesitekit-splash' ); @@ -148,7 +141,7 @@ public function enqueue_scripts_and_styles() { * JavaScript */ wp_localize_script( - 'newspack-wizards', + 'newspack-wizards', 'newspackSettings', $this->get_local_data() );