Submit
Path:
~
/
home
/
getwphos
/
www
/
BenjaminMarc2023
/
wp-content
/
plugins
/
woocommerce
/
src
/
Admin
/
Features
/
Navigation
/
File Content:
Menu.php
<?php /** * WooCommerce Navigation Menu * * @package Woocommerce Navigation */ namespace Automattic\WooCommerce\Admin\Features\Navigation; use Automattic\WooCommerce\Admin\Features\Navigation\Favorites; use Automattic\WooCommerce\Admin\Features\Navigation\Screen; use Automattic\WooCommerce\Admin\Features\Navigation\CoreMenu; /** * Contains logic for the WooCommerce Navigation menu. */ class Menu { /** * Class instance. * * @var Menu instance */ protected static $instance = null; /** * Array index of menu capability. * * @var int */ const CAPABILITY = 1; /** * Array index of menu callback. * * @var int */ const CALLBACK = 2; /** * Array index of menu callback. * * @var int */ const SLUG = 3; /** * Array index of menu CSS class string. * * @var int */ const CSS_CLASSES = 4; /** * Array of usable menu IDs. */ const MENU_IDS = array( 'primary', 'favorites', 'plugins', 'secondary', ); /** * Store menu items. * * @var array */ protected static $menu_items = array(); /** * Store categories with menu item IDs. * * @var array */ protected static $categories = array( 'woocommerce' => array(), ); /** * Registered callbacks or URLs with migration boolean as key value pairs. * * @var array */ protected static $callbacks = array(); /** * Get class instance. */ final public static function instance() { if ( ! static::$instance ) { static::$instance = new static(); } return static::$instance; } /** * Init. */ public function init() { add_action( 'admin_menu', array( $this, 'add_core_items' ), 100 ); add_filter( 'admin_enqueue_scripts', array( $this, 'enqueue_data' ), 20 ); add_filter( 'admin_menu', array( $this, 'migrate_core_child_items' ), PHP_INT_MAX - 1 ); add_filter( 'admin_menu', array( $this, 'migrate_menu_items' ), PHP_INT_MAX - 2 ); } /** * Convert a WordPress menu callback to a URL. * * @param string $callback Menu callback. * @return string */ public static function get_callback_url( $callback ) { // Return the full URL. if ( strpos( $callback, 'http' ) === 0 ) { return $callback; } $pos = strpos( $callback, '?' ); $file = $pos > 0 ? substr( $callback, 0, $pos ) : $callback; if ( file_exists( ABSPATH . "/wp-admin/$file" ) ) { return $callback; } return 'admin.php?page=' . $callback; } /** * Get the parent key if one exists. * * @param string $callback Callback or URL. * @return string|null */ public static function get_parent_key( $callback ) { global $submenu; if ( ! $submenu ) { return null; } // This is already a parent item. if ( isset( $submenu[ $callback ] ) ) { return null; } foreach ( $submenu as $key => $menu ) { foreach ( $menu as $item ) { if ( $item[ self::CALLBACK ] === $callback ) { return $key; } } } return null; } /** * Adds a top level menu item to the navigation. * * @param array $args Array containing the necessary arguments. * $args = array( * 'id' => (string) The unique ID of the menu item. Required. * 'title' => (string) Title of the menu item. Required. * 'url' => (string) URL or callback to be used. Required. * 'order' => (int) Menu item order. * 'migrate' => (bool) Whether or not to hide the item in the wp admin menu. * 'menuId' => (string) The ID of the menu to add the category to. * ). */ private static function add_category( $args ) { if ( ! isset( $args['id'] ) || isset( self::$menu_items[ $args['id'] ] ) ) { return; } $defaults = array( 'id' => '', 'title' => '', 'order' => 100, 'migrate' => true, 'menuId' => 'primary', 'isCategory' => true, ); $menu_item = wp_parse_args( $args, $defaults ); $menu_item['title'] = wp_strip_all_tags( wp_specialchars_decode( $menu_item['title'] ) ); unset( $menu_item['url'] ); unset( $menu_item['capability'] ); if ( ! isset( $menu_item['parent'] ) ) { $menu_item['parent'] = 'woocommerce'; $menu_item['backButtonLabel'] = __( 'WooCommerce Home', 'woocommerce' ); } 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']; } } /** * Adds a child menu item to the navigation. * * @param array $args Array containing the necessary arguments. * $args = array( * 'id' => (string) The unique ID of the menu item. Required. * 'title' => (string) Title of the menu item. Required. * 'parent' => (string) Parent menu item ID. * 'capability' => (string) Capability to view this menu item. * 'url' => (string) URL or callback to be used. Required. * 'order' => (int) Menu item order. * 'migrate' => (bool) Whether or not to hide the item in the wp admin menu. * 'menuId' => (string) The ID of the menu to add the item to. * 'matchExpression' => (string) A regular expression used to identify if the menu item is active. * ). */ private static function add_item( $args ) { if ( ! isset( $args['id'] ) ) { return; } if ( isset( self::$menu_items[ $args['id'] ] ) ) { error_log( // phpcs:ignore sprintf( /* translators: 1: Duplicate menu item path. */ esc_html__( 'You have attempted to register a duplicate item with WooCommerce Navigation: %1$s', 'woocommerce' ), '`' . $args['id'] . '`' ) ); return; } $defaults = array( 'id' => '', 'title' => '', 'capability' => 'manage_woocommerce', 'url' => '', 'order' => 100, 'migrate' => true, 'menuId' => 'primary', ); $menu_item = wp_parse_args( $args, $defaults ); $menu_item['title'] = wp_strip_all_tags( wp_specialchars_decode( $menu_item['title'] ) ); $menu_item['url'] = self::get_callback_url( $menu_item['url'] ); if ( ! isset( $menu_item['parent'] ) ) { $menu_item['parent'] = 'woocommerce'; } $menu_item['menuId'] = self::get_item_menu_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']; } } /** * Get an item's menu ID from its parent. * * @param array $item Item args. * @return string */ public static function get_item_menu_id( $item ) { $favorites = Favorites::get_all( get_current_user_id() ); if ( is_array( $favorites ) && ! empty( $favorites ) && in_array( $item['id'], $favorites, true ) ) { return 'favorites'; } if ( isset( $item['parent'] ) && isset( self::$menu_items[ $item['parent'] ] ) ) { $menu_id = self::$menu_items[ $item['parent'] ]['menuId']; return 'favorites' === $menu_id ? 'plugins' : $menu_id; } return $item['menuId']; } /** * Adds a plugin category. * * @param array $args Array containing the necessary arguments. * $args = array( * 'id' => (string) The unique ID of the menu item. Required. * 'title' => (string) Title of the menu item. Required. * 'url' => (string) URL or callback to be used. Required. * 'migrate' => (bool) Whether or not to hide the item in the wp admin menu. * 'order' => (int) Menu item order. * ). */ public static function add_plugin_category( $args ) { $category_args = array_merge( $args, array( 'menuId' => 'plugins', ) ); if ( ! isset( $category_args['parent'] ) ) { unset( $category_args['order'] ); } $menu_id = self::get_item_menu_id( $category_args ); if ( ! in_array( $menu_id, array( 'plugins', 'favorites' ), true ) ) { return; } $category_args['menuId'] = $menu_id; self::add_category( $category_args ); } /** * Adds a plugin item. * * @param array $args Array containing the necessary arguments. * $args = array( * 'id' => (string) The unique ID of the menu item. Required. * 'title' => (string) Title of the menu item. Required. * 'parent' => (string) Parent menu item ID. * 'capability' => (string) Capability to view this menu item. * 'url' => (string) URL or callback to be used. Required. * 'migrate' => (bool) Whether or not to hide the item in the wp admin menu. * 'order' => (int) Menu item order. * 'matchExpression' => (string) A regular expression used to identify if the menu item is active. * ). */ public static function add_plugin_item( $args ) { if ( ! isset( $args['parent'] ) ) { unset( $args['order'] ); } $item_args = array_merge( $args, array( 'menuId' => 'plugins', ) ); $menu_id = self::get_item_menu_id( $item_args ); if ( 'plugins' !== $menu_id ) { return; } self::add_item( $item_args ); } /** * Adds a plugin setting item. * * @param array $args Array containing the necessary arguments. * $args = array( * 'id' => (string) The unique ID of the menu item. Required. * 'title' => (string) Title of the menu item. Required. * 'capability' => (string) Capability to view this menu item. * 'url' => (string) URL or callback to be used. Required. * 'migrate' => (bool) Whether or not to hide the item in the wp admin menu. * ). */ public static function add_setting_item( $args ) { unset( $args['order'] ); if ( isset( $args['parent'] ) || isset( $args['menuId'] ) ) { error_log( // phpcs:ignore sprintf( /* translators: 1: Duplicate menu item path. */ esc_html__( 'The item ID %1$s attempted to register using an invalid option. The arguments `menuId` and `parent` are not allowed for add_setting_item()', 'woocommerce' ), '`' . $args['id'] . '`' ) ); } $item_args = array_merge( $args, array( 'menuId' => 'secondary', 'parent' => 'woocommerce-settings', ) ); self::add_item( $item_args ); } /** * Get menu item templates for a given post type. * * @param string $post_type Post type to add. * @param array $menu_args Arguments merged with the returned menu items. * @return array */ public static function get_post_type_items( $post_type, $menu_args = array() ) { $post_type_object = get_post_type_object( $post_type ); if ( ! $post_type_object || ! $post_type_object->show_in_menu ) { return; } $parent = isset( $menu_args['parent'] ) ? $menu_args['parent'] . '-' : ''; $match_expression = isset( $_GET['post'] ) && get_post_type( intval( $_GET['post'] ) ) === $post_type // phpcs:ignore WordPress.Security.NonceVerification ? '(edit.php|post.php)' : null; return array( 'default' => array_merge( array( 'title' => esc_attr( $post_type_object->labels->menu_name ), 'capability' => $post_type_object->cap->edit_posts, 'id' => $parent . $post_type, 'url' => "edit.php?post_type={$post_type}", 'matchExpression' => $match_expression, ), $menu_args ), 'all' => array_merge( array( 'title' => esc_attr( $post_type_object->labels->all_items ), 'capability' => $post_type_object->cap->edit_posts, 'id' => "{$parent}{$post_type}-all-items", 'url' => "edit.php?post_type={$post_type}", 'order' => 10, 'matchExpression' => $match_expression, ), $menu_args ), 'new' => array_merge( array( 'title' => esc_attr( $post_type_object->labels->add_new ), 'capability' => $post_type_object->cap->create_posts, 'id' => "{$parent}{$post_type}-add-new", 'url' => "post-new.php?post_type={$post_type}", 'order' => 20, ), $menu_args ), ); } /** * Get menu item templates for a given taxonomy. * * @param string $taxonomy Taxonomy to add. * @param array $menu_args Arguments merged with the returned menu items. * @return array */ public static function get_taxonomy_items( $taxonomy, $menu_args = array() ) { $taxonomy_object = get_taxonomy( $taxonomy ); if ( ! $taxonomy_object || ! $taxonomy_object->show_in_menu ) { return; } $parent = isset( $menu_args['parent'] ) ? $menu_args['parent'] . '-' : ''; $product_type_query = ! empty( $taxonomy_object->object_type ) ? "&post_type={$taxonomy_object->object_type[0]}" : ''; $match_expression = 'term.php'; // Match term.php pages. $match_expression .= "(?=.*[?|&]taxonomy={$taxonomy}(&|$|#))"; // Lookahead to match a taxonomy URL param. $match_expression .= '|'; // Or. $match_expression .= 'edit-tags.php'; // Match edit-tags.php pages. $match_expression .= "(?=.*[?|&]taxonomy={$taxonomy}(&|$|#))"; // Lookahead to match a taxonomy URL param. return array( 'default' => array_merge( array( 'title' => esc_attr( $taxonomy_object->labels->menu_name ), 'capability' => $taxonomy_object->cap->edit_terms, 'id' => $parent . $taxonomy, 'url' => "edit-tags.php?taxonomy={$taxonomy}{$product_type_query}", 'matchExpression' => $match_expression, ), $menu_args ), 'all' => array_merge( array( 'title' => esc_attr( $taxonomy_object->labels->all_items ), 'capability' => $taxonomy_object->cap->edit_terms, 'id' => "{$parent}{$taxonomy}-all-items", 'url' => "edit-tags.php?taxonomy={$taxonomy}{$product_type_query}", 'matchExpression' => $match_expression, 'order' => 10, ), $menu_args ), ); } /** * Add core menu items. */ public function add_core_items() { $categories = CoreMenu::get_categories(); foreach ( $categories as $category ) { self::add_category( $category ); } $items = CoreMenu::get_items(); foreach ( $items as $item ) { if ( isset( $item['is_category'] ) && $item['is_category'] ) { self::add_category( $item ); } else { self::add_item( $item ); } } } /** * Add an item or taxonomy. * * @param array $menu_item Menu item. */ public function add_item_and_taxonomy( $menu_item ) { if ( in_array( $menu_item[2], CoreMenu::get_excluded_items(), true ) ) { return; } $menu_item[2] = htmlspecialchars_decode( $menu_item[2] ); // Don't add already added items. $callbacks = self::get_callbacks(); if ( array_key_exists( $menu_item[2], $callbacks ) ) { return; } // Don't add these Product submenus because they are added elsewhere. if ( in_array( $menu_item[2], array( 'product_importer', 'product_exporter', 'product_attributes' ), true ) ) { return; } self::add_plugin_item( array( 'title' => $menu_item[0], 'capability' => $menu_item[1], 'id' => sanitize_title( $menu_item[0] ), 'url' => $menu_item[2], ) ); // Determine if migrated items are a taxonomy or post_type. If they are, register them. $parsed_url = wp_parse_url( $menu_item[2] ); $query_string = isset( $parsed_url['query'] ) ? $parsed_url['query'] : false; if ( $query_string ) { $query = array(); parse_str( $query_string, $query ); if ( isset( $query['taxonomy'] ) ) { Screen::register_taxonomy( $query['taxonomy'] ); } elseif ( isset( $query['post_type'] ) ) { Screen::register_post_type( $query['post_type'] ); } } } /** * Migrate any remaining WooCommerce child items. * * @param array $menu Menu items. * @return array */ public function migrate_core_child_items( $menu ) { global $submenu; if ( ! isset( $submenu['woocommerce'] ) && ! isset( $submenu['edit.php?post_type=product'] ) ) { return $menu; } $main_items = isset( $submenu['woocommerce'] ) ? $submenu['woocommerce'] : array(); $product_items = isset( $submenu['edit.php?post_type=product'] ) ? $submenu['edit.php?post_type=product'] : array(); foreach ( $main_items as $key => $menu_item ) { self::add_item_and_taxonomy( $menu_item ); // phpcs:disable if ( ! isset( $menu_item[ self::CSS_CLASSES ] ) ) { $submenu['woocommerce'][ $key ][] .= ' hide-if-js'; } else if ( strpos( $submenu['woocommerce'][ $key ][ self::CSS_CLASSES ], 'hide-if-js' ) !== false ) { continue; } else { $submenu['woocommerce'][ $key ][ self::CSS_CLASSES ] .= ' hide-if-js'; } // phpcs:enable } foreach ( $product_items as $key => $menu_item ) { self::add_item_and_taxonomy( $menu_item ); } return $menu; } /** * Check if a menu item's callback is registered in the menu. * * @param array $menu_item Menu item args. * @return bool */ public static function has_callback( $menu_item ) { if ( ! $menu_item || ! isset( $menu_item[ self::CALLBACK ] ) ) { return false; } $callback = $menu_item[ self::CALLBACK ]; if ( isset( self::$callbacks[ $callback ] ) && self::$callbacks[ $callback ] ) { return true; } if ( isset( self::$callbacks[ self::get_callback_url( $callback ) ] ) && self::$callbacks[ self::get_callback_url( $callback ) ] ) { return true; } return false; } /** * Hides all WP admin menus items and adds screen IDs to check for new items. */ public static function migrate_menu_items() { global $menu, $submenu; foreach ( $menu as $key => $menu_item ) { if ( self::has_callback( $menu_item ) ) { // Disable phpcs since we need to override submenu classes. // Note that `phpcs:ignore WordPress.Variables.GlobalVariables.OverrideProhibited` does not work to disable this check. // phpcs:disable $menu[ $key ][ self::CSS_CLASSES ] .= ' hide-if-js'; // phps:enable continue; } // WordPress core menus make the parent item the same URL as the first child. $has_children = isset( $submenu[ $menu_item[ self::CALLBACK ] ] ) && isset( $submenu[ $menu_item[ self::CALLBACK ] ][0] ); $first_child = $has_children ? $submenu[ $menu_item[ self::CALLBACK ] ][0] : null; if ( 'woocommerce' !== $menu_item[2] && self::has_callback( $first_child ) ) { // Disable phpcs since we need to override submenu classes. // Note that `phpcs:ignore WordPress.Variables.GlobalVariables.OverrideProhibited` does not work to disable this check. // phpcs:disable $menu[ $key ][ self::CSS_CLASSES ] .= ' hide-if-js'; // phps:enable } } // Remove excluded submenu items if ( isset( $submenu['woocommerce'] ) ) { foreach ( $submenu['woocommerce'] as $key => $submenu_item ) { if ( in_array( $submenu_item[ self::CALLBACK ], CoreMenu::get_excluded_items(), true ) ) { if ( isset( $submenu['woocommerce'][ $key ][ self::CSS_CLASSES ] ) ) { $submenu['woocommerce'][ $key ][ self::CSS_CLASSES ] .= ' hide-if-js'; } else { $submenu['woocommerce'][ $key ][] = 'hide-if-js'; } } } } foreach ( $submenu as $parent_key => $parent ) { foreach ( $parent as $key => $menu_item ) { if ( self::has_callback( $menu_item ) ) { // Disable phpcs since we need to override submenu classes. // Note that `phpcs:ignore WordPress.Variables.GlobalVariables.OverrideProhibited` does not work to disable this check. // phpcs:disable if ( ! isset( $menu_item[ self::SLUG ] ) ) { $submenu[ $parent_key ][ $key ][] = ''; } if ( ! isset( $menu_item[ self::CSS_CLASSES ] ) ) { $submenu[ $parent_key ][ $key ][] .= ' hide-if-js'; } else { $submenu[ $parent_key ][ $key ][ self::CSS_CLASSES ] .= ' hide-if-js'; } // phps:enable } } } foreach ( array_keys( self::$callbacks ) as $callback ) { Screen::add_screen( $callback ); } } /** * Add a callback to identify and hide pages in the WP menu. */ public static function hide_wp_menu_item( $callback ) { self::$callbacks[ $callback ] = true; } /** * Get registered menu items. * * @return array */ public static function get_items() { return apply_filters( 'woocommerce_navigation_menu_items', self::$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 ]; } } return apply_filters( 'woocommerce_navigation_menu_category_items', $category_menu_items ); } /** * Get registered callbacks. * * @return array */ public static function get_callbacks() { return apply_filters( 'woocommerce_navigation_callbacks', self::$callbacks ); } /** * Gets the menu item data mapped by category and menu ID. * * @return array */ public static function get_mapped_menu_items() { $menu_items = self::get_items(); $mapped_items = array(); // Sort the items by order and title. $order = array_column( $menu_items, 'order' ); $title = array_column( $menu_items, 'title' ); array_multisort( $order, SORT_ASC, $title, SORT_ASC, $menu_items ); foreach ( $menu_items as $id => $menu_item ) { $category_id = $menu_item[ 'parent' ]; $menu_id = $menu_item[ 'menuId' ]; if ( ! isset( $mapped_items[ $category_id ] ) ) { $mapped_items[ $category_id ] = array(); foreach ( self::MENU_IDS as $available_menu_id ) { $mapped_items[ $category_id ][ $available_menu_id ] = array(); } } // Incorrect menu ID. if ( ! isset( $mapped_items[ $category_id ][ $menu_id ] ) ) { continue; } // Remove the item if the user cannot access it. if ( isset( $menu_item[ 'capability' ] ) && ! current_user_can( $menu_item[ 'capability' ] ) ) { continue; } $mapped_items[ $category_id ][ $menu_id ][] = $menu_item; } return $mapped_items; } /** * Add the menu to the page output. * * @param array $menu Menu items. * @return array */ public function enqueue_data( $menu ) { $data = array( 'menuItems' => array_values( self::get_items() ), 'rootBackUrl' => get_dashboard_url(), ); wp_add_inline_script( WC_ADMIN_APP, 'window.wcNavigation = ' . wp_json_encode( $data ), 'before' ); } }
Edit
Rename
Chmod
Delete
FILE
FOLDER
Name
Size
Permission
Action
CoreMenu.php
12385 bytes
0644
Favorites.php
2681 bytes
0644
Init.php
4044 bytes
0644
Menu.php
22813 bytes
0644
Screen.php
5702 bytes
0644
N4ST4R_ID | Naxtarrr