From 816b68eb837b4f9694d58fca6fc18027c966e97b Mon Sep 17 00:00:00 2001 From: Joshua T Flowers Date: Thu, 4 Feb 2021 11:20:35 -0500 Subject: [PATCH] Add WooCommerce flyout menu (https://github.com/woocommerce/woocommerce-admin/pull/6165) * Unhide the submenu * Add method to get items by category * Add flyout menu items * Sort items by menu ID * Allow marketplace in flyout menu * Remove unused styles on non-wc pages --- .../packages/navigation/src/style.scss | 17 ----- .../src/Features/Navigation/CoreMenu.php | 60 ++++++++++++++++++ .../src/Features/Navigation/Init.php | 19 ------ .../src/Features/Navigation/Menu.php | 63 ++++++++++++++++--- 4 files changed, 113 insertions(+), 46 deletions(-) delete mode 100644 plugins/woocommerce-admin/packages/navigation/src/style.scss diff --git a/plugins/woocommerce-admin/packages/navigation/src/style.scss b/plugins/woocommerce-admin/packages/navigation/src/style.scss deleted file mode 100644 index 055fcc0cb16..00000000000 --- a/plugins/woocommerce-admin/packages/navigation/src/style.scss +++ /dev/null @@ -1,17 +0,0 @@ -// Hide elements on non-WooCommerce pages. -body.js:not(.has-woocommerce-navigation) { - #adminmenu - li.toplevel_page_woocommerce.wp-has-submenu.wp-not-current-submenu.opensub:hover::after { - display: none; - } - - .toplevel_page_woocommerce ul.wp-submenu { - display: none; - - @include breakpoint( '<782px' ) { - .wp-first-item.hide-if-js { - display: list-item; - } - } - } -} diff --git a/plugins/woocommerce-admin/src/Features/Navigation/CoreMenu.php b/plugins/woocommerce-admin/src/Features/Navigation/CoreMenu.php index b9fa548e35f..7e8700d1aca 100644 --- a/plugins/woocommerce-admin/src/Features/Navigation/CoreMenu.php +++ b/plugins/woocommerce-admin/src/Features/Navigation/CoreMenu.php @@ -36,6 +36,8 @@ class CoreMenu { */ public function init() { add_action( 'admin_menu', array( $this, 'register_post_types' ) ); + // Add this after we've finished migrating menu items to avoid hiding these items. + add_action( 'add_menu_classes', array( $this, 'add_dashboard_menu_items' ), PHP_INT_MAX ); } /** @@ -275,6 +277,64 @@ class CoreMenu { Screen::register_post_type( 'shop_coupon' ); } + /** + * Add the dashboard items to the WP menu to create a quick-access flyout menu. + * + * @param array $menu Menu. + * @returna array + */ + public function add_dashboard_menu_items( $menu ) { + $top_level_items = Menu::get_category_items( 'woocommerce' ); + + // phpcs:disable + global $submenu; + + if ( ! isset( $submenu['woocommerce'] ) ) { + return $menu; + } + + foreach( $top_level_items as $item ) { + // Skip specific categories. + if ( + in_array( + $item['id'], + array( + 'woocommerce-tools', + ), + true + ) + ) { + continue; + } + + // Use the link from the first item if it's a category. + if ( ! isset( $item['url'] ) ) { + $category_items = Menu::get_category_items( $item['id'] ); + $first_item = $category_items[0]; + + $submenu['woocommerce'][] = array( + $item['title'], + $first_item['capability'], + isset( $first_item['url'] ) ? $first_item['url'] : null, + $item['title'], + ); + + continue; + } + + // Show top-level items. + $submenu['woocommerce'][] = array( + $item['title'], + $item['capability'], + isset( $item['url'] ) ? $item['url'] : null, + $item['title'], + ); + } + // phpcs:enable + + return $menu; + } + /** * Get items excluded from WooCommerce menu migration. * diff --git a/plugins/woocommerce-admin/src/Features/Navigation/Init.php b/plugins/woocommerce-admin/src/Features/Navigation/Init.php index 743f8276618..f198eff407f 100644 --- a/plugins/woocommerce-admin/src/Features/Navigation/Init.php +++ b/plugins/woocommerce-admin/src/Features/Navigation/Init.php @@ -34,7 +34,6 @@ class Init { if ( Loader::is_feature_enabled( 'navigation' ) ) { add_action( 'in_admin_header', array( __CLASS__, 'embed_navigation' ) ); - add_action( 'admin_enqueue_scripts', array( $this, 'maybe_enqueue_scripts' ) ); Menu::instance()->init(); CoreMenu::instance()->init(); @@ -146,24 +145,6 @@ class Init { array(), + ); + /** * Registered callbacks or URLs with migration boolean as key value pairs. * @@ -172,7 +181,9 @@ class Menu { ); } - self::$menu_items[ $menu_item['id'] ] = $menu_item; + self::$menu_items[ $menu_item['id'] ] = $menu_item; + self::$categories[ $menu_item['id'] ] = array(); + self::$categories[ $menu_item['parent'] ][] = $menu_item['id']; if ( isset( $args['url'] ) ) { self::$callbacks[ $args['url'] ] = $menu_item['migrate']; @@ -230,7 +241,8 @@ class Menu { $menu_item['menuId'] = self::get_item_menu_id( $menu_item ); - self::$menu_items[ $menu_item['id'] ] = $menu_item; + self::$menu_items[ $menu_item['id'] ] = $menu_item; + self::$categories[ $menu_item['parent'] ][] = $menu_item['id']; if ( isset( $args['url'] ) ) { self::$callbacks[ $args['url'] ] = $menu_item['migrate']; @@ -644,7 +656,32 @@ class Menu { * @return array */ public static function get_items() { - return apply_filters( 'woocommerce_navigation_menu_items', self::$menu_items ); + $menu_items = self::get_prepared_menu_item_data( self::$menu_items ); + return apply_filters( 'woocommerce_navigation_menu_items', $menu_items ); + } + + /** + * Get registered menu items. + * + * @return array + */ + public static function get_category_items( $category ) { + if ( ! isset( self::$categories[ $category ] ) ) { + return array(); + } + + $menu_item_ids = self::$categories[ $category ]; + + + $category_menu_items = array(); + foreach ( $menu_item_ids as $id ) { + if ( isset( self::$menu_items[ $id ] ) ) { + $category_menu_items[] = self::$menu_items[ $id ]; + } + } + + $category_menu_items = self::get_prepared_menu_item_data( $category_menu_items ); + return apply_filters( 'woocommerce_navigation_menu_category_items', $category_menu_items ); } /** @@ -659,10 +696,10 @@ class Menu { /** * Gets the menu item data for use in the client. * + * @param array $menu_items Menu items to prepare. * @return array */ - public static function get_prepared_menu_item_data() { - $menu_items = self::get_items(); + public static function get_prepared_menu_item_data( $menu_items ) { foreach ( $menu_items as $index => $menu_item ) { if ( $menu_item[ 'capability' ] && ! current_user_can( $menu_item[ 'capability' ] ) ) { unset( $menu_items[ $index ] ); @@ -670,11 +707,17 @@ class Menu { } // Sort the menu items. - $order = array_column( $menu_items, 'order' ); - $title = array_column( $menu_items, 'title' ); - array_multisort( $order, SORT_ASC, $title, SORT_ASC, $menu_items ); + $menuOrder = array( + 'primary' => 0, + 'secondary' => 1, + 'plugins' => 2, + ); + $menu = array_map( function( $item ) use( $menuOrder ) { return $menuOrder[ $item['menuId'] ]; }, $menu_items ); + $order = array_column( $menu_items, 'order' ); + $title = array_column( $menu_items, 'title' ); + array_multisort( $menu, SORT_ASC, $order, SORT_ASC, $title, SORT_ASC, $menu_items ); - return array_values( $menu_items ); + return $menu_items; } /** @@ -685,7 +728,7 @@ class Menu { */ public function enqueue_data( $menu ) { $data = array( - 'menuItems' => self::get_prepared_menu_item_data(), + 'menuItems' => array_values( self::get_items() ), 'rootBackUrl' => apply_filters( 'woocommerce_navigation_root_back_url', get_dashboard_url() ), 'rootBackLabel' => apply_filters( 'woocommerce_navigation_root_back_label', __( 'WordPress Dashboard', 'woocommerce-admin' ) ), );