HEX
Server: LiteSpeed
System: Linux eko108.isimtescil.net 4.18.0-477.21.1.lve.1.el8.x86_64 #1 SMP Tue Sep 5 23:08:35 UTC 2023 x86_64
User: uyarreklamcomtr (11202)
PHP: 7.4.33
Disabled: opcache_get_status
Upload Files
File: /var/www/vhosts/uyarreklam.com.tr/httpdocs/Navigation.tar
CoreMenu.php000064400000030141151546772540007011 0ustar00<?php
/**
 * WooCommerce Navigation Core Menu
 *
 * @package Woocommerce Admin
 */

namespace Automattic\WooCommerce\Admin\Features\Navigation;

use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\Navigation\Menu;
use Automattic\WooCommerce\Admin\Features\Navigation\Screen;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists;
use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController;

/**
 * CoreMenu class. Handles registering Core menu items.
 */
class CoreMenu {
	/**
	 * Class instance.
	 *
	 * @var Menu instance
	 */
	protected static $instance = null;

	/**
	 * 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, 'register_post_types' ) );
		// Add this after we've finished migrating menu items to avoid hiding these items.
		add_action( 'admin_menu', array( $this, 'add_dashboard_menu_items' ), PHP_INT_MAX );
	}

	/**
	 * Add registered admin settings as menu items.
	 */
	public static function get_setting_items() {
		// Let the Settings feature add pages to the navigation if enabled.
		if ( Features::is_enabled( 'settings' ) ) {
			return array();
		}

		// Calling this method adds pages to the below tabs filter on non-settings pages.
		\WC_Admin_Settings::get_settings_pages();
		$tabs = apply_filters( 'woocommerce_settings_tabs_array', array() );

		$menu_items = array();
		$order      = 0;
		foreach ( $tabs as $key => $setting ) {
			$order       += 10;
			$menu_items[] = (
			array(
				'parent'     => 'woocommerce-settings',
				'title'      => $setting,
				'capability' => 'manage_woocommerce',
				'id'         => 'settings-' . $key,
				'url'        => 'admin.php?page=wc-settings&tab=' . $key,
				'order'      => $order,
			)
			);
		}

		return $menu_items;
	}

	/**
	 * Get unfulfilled order count
	 *
	 * @return array
	 */
	public static function get_shop_order_count() {
		$status_counts = array_map( 'wc_orders_count', array( 'processing', 'on-hold' ) );
		return array_sum( $status_counts );
	}

	/**
	 * Get all menu categories.
	 *
	 * @return array
	 */
	public static function get_categories() {
		$analytics_enabled = Features::is_enabled( 'analytics' );
		return array(
			array(
				'title' => __( 'Orders', 'woocommerce' ),
				'id'    => 'woocommerce-orders',
				'badge' => self::get_shop_order_count(),
				'order' => 10,
			),
			array(
				'title' => __( 'Products', 'woocommerce' ),
				'id'    => 'woocommerce-products',
				'order' => 20,
			),
			$analytics_enabled ?
				array(
					'title' => __( 'Analytics', 'woocommerce' ),
					'id'    => 'woocommerce-analytics',
					'order' => 30,
				) : null,
			$analytics_enabled ?
				array(
					'title'  => __( 'Reports', 'woocommerce' ),
					'id'     => 'woocommerce-reports',
					'parent' => 'woocommerce-analytics',
					'order'  => 200,
				) : null,
			array(
				'title' => __( 'Marketing', 'woocommerce' ),
				'id'    => 'woocommerce-marketing',
				'order' => 40,
			),
			array(
				'title'  => __( 'Settings', 'woocommerce' ),
				'id'     => 'woocommerce-settings',
				'menuId' => 'secondary',
				'order'  => 20,
				'url'    => 'admin.php?page=wc-settings',
			),
			array(
				'title'  => __( 'Tools', 'woocommerce' ),
				'id'     => 'woocommerce-tools',
				'menuId' => 'secondary',
				'order'  => 30,
			),
		);
	}

	/**
	 * Get all menu items.
	 *
	 * @return array
	 */
	public static function get_items() {
		$order_items       = self::get_order_menu_items();
		$product_items     = Menu::get_post_type_items( 'product', array( 'parent' => 'woocommerce-products' ) );
		$product_tag_items = Menu::get_taxonomy_items(
			'product_tag',
			array(
				'parent' => 'woocommerce-products',
				'order'  => 30,
			)
		);
		$product_cat_items = Menu::get_taxonomy_items(
			'product_cat',
			array(
				'parent' => 'woocommerce-products',
				'order'  => 20,
			)
		);

		$coupon_items  = Menu::get_post_type_items( 'shop_coupon', array( 'parent' => 'woocommerce-marketing' ) );
		$setting_items = self::get_setting_items();
		$wca_items     = array();
		$wca_pages     = \Automattic\WooCommerce\Admin\PageController::get_instance()->get_pages();

		foreach ( $wca_pages as $page ) {
			if ( ! isset( $page['nav_args'] ) ) {
				continue;
			}

			$path = isset( $page['path'] ) ? $page['path'] : null;
			$item = array_merge(
				array(
					'id'         => $page['id'],
					'url'        => $path,
					'title'      => $page['title'][0],
					'capability' => isset( $page['capability'] ) ? $page['capability'] : 'manage_woocommerce',
				),
				$page['nav_args']
			);

			// Don't allow top-level items to be added to the primary menu.
			if ( ! isset( $item['parent'] ) || 'woocommerce' === $item['parent'] ) {
				$item['menuId'] = 'plugins';
			}

			$wca_items[] = $item;
		}

		$home_item = array();
		$setup_tasks_remaining = TaskLists::setup_tasks_remaining();
		if ( defined( '\Automattic\WooCommerce\Internal\Admin\Homescreen::MENU_SLUG' ) ) {
			$home_item = array(
				'id'              => 'woocommerce-home',
				'title'           => __( 'Home', 'woocommerce' ),
				'url'             => \Automattic\WooCommerce\Internal\Admin\Homescreen::MENU_SLUG,
				'order'           => 0,
				'matchExpression' => 'page=wc-admin((?!path=).)*$',
				'badge'           => $setup_tasks_remaining ? $setup_tasks_remaining : null,
			);
		}

		$customers_item = array();
		if ( Features::is_enabled( 'analytics' ) ) {
			$customers_item = array(
				'id'    => 'woocommerce-analytics-customers',
				'title' => __( 'Customers', 'woocommerce' ),
				'url'   => 'wc-admin&path=/customers',
				'order' => 50,
			);
		}

		$add_product_mvp = array();
		if ( Features::is_enabled( 'new-product-management-experience' ) ) {
			$add_product_mvp = array(
				'id'     => 'woocommerce-add-product-mbp',
				'title'  => __( 'Add New (MVP)', 'woocommerce' ),
				'url'    => 'admin.php?page=wc-admin&path=/add-product',
				'parent' => 'woocommerce-products',
				'order'  => 50,
			);
		}

		return array_merge(
			array(
				$home_item,
				$customers_item,
				$order_items['all'],
				$order_items['new'],
				$product_items['all'],
				$product_cat_items['default'],
				$product_tag_items['default'],
				array(
					'id'              => 'woocommerce-product-attributes',
					'title'           => __( 'Attributes', 'woocommerce' ),
					'url'             => 'edit.php?post_type=product&page=product_attributes',
					'capability'      => 'manage_product_terms',
					'order'           => 40,
					'parent'          => 'woocommerce-products',
					'matchExpression' => 'edit.php(?=.*[?|&]page=product_attributes(&|$|#))|edit-tags.php(?=.*[?|&]taxonomy=pa_)(?=.*[?|&]post_type=product(&|$|#))',
				),
				array_merge( $product_items['new'], array( 'order' => 50 ) ),
				$coupon_items['default'],
				// Marketplace category.
				array(
					'title'      => __( 'Marketplace', 'woocommerce' ),
					'capability' => 'manage_woocommerce',
					'id'         => 'woocommerce-marketplace',
					'url'        => 'wc-addons',
					'menuId'     => 'secondary',
					'order'      => 10,
				),
				$add_product_mvp,
			),
			// Tools category.
			self::get_tool_items(),
			// WooCommerce Admin items.
			$wca_items,
			// Settings category.
			$setting_items,
			// Legacy report items.
			self::get_legacy_report_items()
		);
	}

	/**
	 * Supplies menu items for orders.
	 *
	 * This varies depending on whether we are actively using traditional post type-based orders or the new custom
	 * table-based orders.
	 *
	 * @return ?array
	 */
	private static function get_order_menu_items(): ?array {
		if ( ! wc_get_container()->get( CustomOrdersTableController::class )->custom_orders_table_usage_is_enabled() ) {
			return Menu::get_post_type_items( 'shop_order', array( 'parent' => 'woocommerce-orders' ) );
		}

		$main_orders_menu = array(
			'title'      => __( 'Orders', 'woocommerce' ),
			'capability' => 'edit_others_shop_orders',
			'id'         => 'woocommerce-orders-default',
			'url'        => 'admin.php?page=wc-orders',
			'parent'     => 'woocommerce-orders',
		);

		$all_orders_entry          = $main_orders_menu;
		$all_orders_entry['id']    = 'woocommerce-orders-all-items';
		$all_orders_entry['order'] = 10;

		$new_orders_entry          = $main_orders_menu;
		$new_orders_entry['title'] = __( 'Add order', 'woocommerce' );
		$new_orders_entry['id']    = 'woocommerce-orders-add-item';
		$new_orders_entry['url']   = 'admin.php?page=TBD';
		$new_orders_entry['order'] = 20;

		return array(
			'default' => $main_orders_menu,
			'all'     => $all_orders_entry,
			'new'     => $new_orders_entry,
		);
	}

	/**
	 * Get items for tools category.
	 *
	 * @return array
	 */
	public static function get_tool_items() {
		$tabs = array(
			'status' => __( 'System status', 'woocommerce' ),
			'tools'  => __( 'Utilities', 'woocommerce' ),
			'logs'   => __( 'Logs', 'woocommerce' ),
		);
		$tabs = apply_filters( 'woocommerce_admin_status_tabs', $tabs );

		$order = 1;
		$items = array(
			array(
				'parent'     => 'woocommerce-tools',
				'title'      => __( 'Import / Export', 'woocommerce' ),
				'capability' => 'import',
				'id'         => 'tools-import-export',
				'url'        => 'import.php',
				'migrate'    => false,
				'order'      => 0,
			),
		);

		foreach ( $tabs as $key => $tab ) {
			$items[] = array(
				'parent'     => 'woocommerce-tools',
				'title'      => $tab,
				'capability' => 'manage_woocommerce',
				'id'         => 'tools-' . $key,
				'url'        => 'wc-status&tab=' . $key,
				'order'      => $order,
			);
			$order++;
		}

		return $items;
	}

	/**
	 * Get legacy report items.
	 *
	 * @return array
	 */
	public static function get_legacy_report_items() {
		$reports    = \WC_Admin_Reports::get_reports();
		$menu_items = array();

		$order = 0;
		foreach ( $reports as $key => $report ) {
			$menu_items[] = array(
				'parent'     => 'woocommerce-reports',
				'title'      => $report['title'],
				'capability' => 'view_woocommerce_reports',
				'id'         => $key,
				'url'        => 'wc-reports&tab=' . $key,
				'order'      => $order,
			);
			$order++;
		}

		return $menu_items;
	}

	/**
	 * Register all core post types.
	 */
	public function register_post_types() {
		Screen::register_post_type( 'shop_order' );
		Screen::register_post_type( 'product' );
		Screen::register_post_type( 'shop_coupon' );
	}

	/**
	 * Add the dashboard items to the WP menu to create a quick-access flyout menu.
	 */
	public function add_dashboard_menu_items() {
		global $submenu, $menu;
		$mapped_items = Menu::get_mapped_menu_items();
		$top_level    = $mapped_items['woocommerce'];

		// phpcs:disable
		if ( ! isset( $submenu['woocommerce'] ) || empty( $top_level ) ) {
			return;
		}

		$menuIds = array(
			'primary',
			'secondary',
			'favorites',
		);

		foreach ( $menuIds as $menuId ) {
			foreach( $top_level[ $menuId ] 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'] ) ) {
					$categoryMenuId = $menuId === 'favorites' ? 'plugins' : $menuId;
					$category_items = $mapped_items[ $item['id'] ][ $categoryMenuId ];

					if ( ! empty( $category_items ) ) {
						$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
	}

	/**
	 * Get items excluded from WooCommerce menu migration.
	 *
	 * @return array
	 */
	public static function get_excluded_items() {
		$excluded_items = array(
			'woocommerce',
			'wc-reports',
			'wc-settings',
			'wc-status',
		);

		return apply_filters( 'woocommerce_navigation_core_excluded_items', $excluded_items );
	}
}
Favorites.php000064400000005171151546772540007243 0ustar00<?php
/**
 * WooCommerce Navigation Favorite
 *
 * @package Woocommerce Navigation
 */

namespace Automattic\WooCommerce\Admin\Features\Navigation;

use Automattic\WooCommerce\Internal\Admin\WCAdminUser;

/**
 * Contains logic for the WooCommerce Navigation menu.
 */
class Favorites {

	/**
	 * Array index of menu capability.
	 *
	 * @var int
	 */
	const META_NAME = 'navigation_favorites';

	/**
	 * Favorites instance.
	 *
	 * @var Favorites|null
	 */
	protected static $instance = null;

	/**
	 * Get class instance.
	 */
	final public static function instance() {
		if ( ! static::$instance ) {
			static::$instance = new static();
		}
		return static::$instance;
	}

	/**
	 * Set given favorites string to the user meta data.
	 *
	 * @param string|number $user_id User id.
	 * @param array         $favorites Array of favorite values to set.
	 */
	private static function set_meta_value( $user_id, $favorites ) {
		WCAdminUser::update_user_data_field( $user_id, self::META_NAME, wp_json_encode( (array) $favorites ) );
	}

	/**
	 * Add item to favorites
	 *
	 * @param string        $item_id Identifier of item to add.
	 * @param string|number $user_id Identifier of user to add to.
	 * @return WP_Error|Boolean   Throws exception if item already exists.
	 */
	public static function add_item( $item_id, $user_id ) {

		$all_favorites = self::get_all( $user_id );

		if ( in_array( $item_id, $all_favorites, true ) ) {
			return new \WP_Error(
				'woocommerce_favorites_already_exists',
				__( 'Favorite already exists', 'woocommerce' )
			);
		}

		$all_favorites[] = $item_id;

		self::set_meta_value( $user_id, $all_favorites );

		return true;
	}

	/**
	 * Remove item from favorites
	 *
	 * @param string        $item_id Identifier of item to remove.
	 * @param string|number $user_id Identifier of user to remove from.
	 * @return \WP_Error|Boolean   Throws exception if item does not exist.
	 */
	public static function remove_item( $item_id, $user_id ) {
		$all_favorites = self::get_all( $user_id );

		if ( ! in_array( $item_id, $all_favorites, true ) ) {
			return new \WP_Error(
				'woocommerce_favorites_does_not_exist',
				__( 'Favorite item not found', 'woocommerce' )
			);
		}

		$remaining = array_values( array_diff( $all_favorites, [ $item_id ] ) );

		self::set_meta_value( $user_id, $remaining );

		return true;
	}

	/**
	 * Get all registered favorites.
	 *
	 * @param string|number $user_id Identifier of user to query.
	 * @return WP_Error|Array
	 */
	public static function get_all( $user_id ) {
		$response = WCAdminUser::get_user_data_field( $user_id, self::META_NAME );

		return $response ? json_decode( $response, true ) : array();
	}

}
Init.php000064400000007714151546772540006211 0ustar00<?php
/**
 * Navigation Experience
 *
 * @package Woocommerce Admin
 */

namespace Automattic\WooCommerce\Admin\Features\Navigation;

use Automattic\WooCommerce\Internal\Admin\Survey;
use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\Navigation\Screen;
use Automattic\WooCommerce\Admin\Features\Navigation\Menu;
use Automattic\WooCommerce\Admin\Features\Navigation\CoreMenu;
use Automattic\WooCommerce\Internal\Admin\WCAdminAssets;

/**
 * Contains logic for the Navigation
 */
class Init {
	/**
	 * Option name used to toggle this feature.
	 */
	const TOGGLE_OPTION_NAME = 'woocommerce_navigation_enabled';

	/**
	 * Determines if the feature has been toggled on or off.
	 *
	 * @var boolean
	 */
	protected static $is_updated = false;

	/**
	 * Hook into WooCommerce.
	 */
	public function __construct() {
		add_action( 'update_option_' . self::TOGGLE_OPTION_NAME, array( $this, 'reload_page_on_toggle' ), 10, 2 );
		add_action( 'woocommerce_settings_saved', array( $this, 'maybe_reload_page' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'maybe_enqueue_opt_out_scripts' ) );

		if ( Features::is_enabled( 'navigation' ) ) {
			Menu::instance()->init();
			CoreMenu::instance()->init();
			Screen::instance()->init();
		}
	}

	/**
	 * Add the feature toggle to the features settings.
	 *
	 * @deprecated 7.0 The WooCommerce Admin features are now handled by the WooCommerce features engine (see the FeaturesController class).
	 *
	 * @param array $features Feature sections.
	 * @return array
	 */
	public static function add_feature_toggle( $features ) {
		return $features;
	}

	/**
	 * Determine if sufficient versions are present to support Navigation feature
	 */
	public function is_nav_compatible() {
		include_once ABSPATH . 'wp-admin/includes/plugin.php';

		$gutenberg_minimum_version = '9.0.0'; // https://github.com/WordPress/gutenberg/releases/tag/v9.0.0.
		$wp_minimum_version        = '5.6';
		$has_gutenberg             = is_plugin_active( 'gutenberg/gutenberg.php' );
		$gutenberg_version         = $has_gutenberg ? get_plugin_data( WP_PLUGIN_DIR . '/gutenberg/gutenberg.php' )['Version'] : false;

		if ( $gutenberg_version && version_compare( $gutenberg_version, $gutenberg_minimum_version, '>=' ) ) {
			return true;
		}

		// Get unmodified $wp_version.
		include ABSPATH . WPINC . '/version.php';

		// Strip '-src' from the version string. Messes up version_compare().
		$wp_version = str_replace( '-src', '', $wp_version );

		if ( version_compare( $wp_version, $wp_minimum_version, '>=' ) ) {
			return true;
		}

		return false;
	}

	/**
	 * Reloads the page when the option is toggled to make sure all nav features are loaded.
	 *
	 * @param string $old_value Old value.
	 * @param string $value     New value.
	 */
	public static function reload_page_on_toggle( $old_value, $value ) {
		if ( $old_value === $value ) {
			return;
		}

		if ( 'yes' !== $value ) {
			update_option( 'woocommerce_navigation_show_opt_out', 'yes' );
		}

		self::$is_updated = true;
	}

	/**
	 * Reload the page if the setting has been updated.
	 */
	public static function maybe_reload_page() {
		if ( ! isset( $_SERVER['REQUEST_URI'] ) || ! self::$is_updated ) {
			return;
		}

		wp_safe_redirect( wp_unslash( $_SERVER['REQUEST_URI'] ) );
		exit();
	}

	/**
	 * Enqueue the opt out scripts.
	 */
	public function maybe_enqueue_opt_out_scripts() {
		if ( get_option( 'woocommerce_navigation_show_opt_out', 'no' ) !== 'yes' ) {
			return;
		}

		$rtl = is_rtl() ? '.rtl' : '';
		wp_enqueue_style(
			'wc-admin-navigation-opt-out',
			WCAdminAssets::get_url( "navigation-opt-out/style{$rtl}", 'css' ),
			array( 'wp-components' ),
			WCAdminAssets::get_file_version( 'css' )
		);

		WCAdminAssets::register_script( 'wp-admin-scripts', 'navigation-opt-out', true );
		wp_localize_script(
			'wc-admin-navigation-opt-out',
			'surveyData',
			array(
				'url' => Survey::get_url( '/new-navigation-opt-out' ),
			)
		);
		delete_option( 'woocommerce_navigation_show_opt_out' );
	}
}
Menu.php000064400000054435151546772540006214 0ustar00<?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' );
	}
}
Screen.php000064400000013106151546772540006515 0ustar00<?php
/**
 * WooCommerce Navigation Screen
 *
 * @package Woocommerce Navigation
 */

namespace Automattic\WooCommerce\Admin\Features\Navigation;

use Automattic\WooCommerce\Admin\Features\Navigation\Menu;

/**
 * Contains logic for the WooCommerce Navigation menu.
 */
class Screen {
	/**
	 * Class instance.
	 *
	 * @var Screen instance
	 */
	protected static $instance = null;

	/**
	 * Screen IDs of registered pages.
	 *
	 * @var array
	 */
	protected static $screen_ids = array();

	/**
	 * Registered post types.
	 *
	 * @var array
	 */
	protected static $post_types = array();

	/**
	 * Registered taxonomies.
	 *
	 * @var array
	 */
	protected static $taxonomies = array();

	/**
	 * Get class instance.
	 */
	final public static function instance() {
		if ( ! static::$instance ) {
			static::$instance = new static();
		}
		return static::$instance;
	}

	/**
	 * Init.
	 */
	public function init() {
		add_filter( 'admin_body_class', array( $this, 'add_body_class' ) );
	}

	/**
	 * Returns an array of filtered screen ids.
	 */
	public static function get_screen_ids() {
		return apply_filters( 'woocommerce_navigation_screen_ids', self::$screen_ids );
	}

	/**
	 * Returns an array of registered post types.
	 */
	public static function get_post_types() {
		return apply_filters( 'woocommerce_navigation_post_types', self::$post_types );
	}

	/**
	 * Returns an array of registered post types.
	 */
	public static function get_taxonomies() {
		return apply_filters( 'woocommerce_navigation_taxonomies', self::$taxonomies );
	}

	/**
	 * Check if we're on a WooCommerce page
	 *
	 * @return bool
	 */
	public static function is_woocommerce_page() {
		global $pagenow;

		// Get taxonomy if on a taxonomy screen.
		$taxonomy = '';
		if ( in_array( $pagenow, array( 'edit-tags.php', 'term.php' ), true ) ) {
			if ( isset( $_GET['taxonomy'] ) ) { // phpcs:ignore CSRF ok.
				$taxonomy = sanitize_text_field( wp_unslash( $_GET['taxonomy'] ) ); // phpcs:ignore CSRF ok.
			}
		}
		$taxonomies = self::get_taxonomies();

		// Get post type if on a post screen.
		$post_type = '';
		if ( in_array( $pagenow, array( 'edit.php', 'post.php', 'post-new.php' ), true ) ) {
			if ( isset( $_GET['post'] ) ) { // phpcs:ignore CSRF ok.
				$post_type = get_post_type( (int) $_GET['post'] ); // phpcs:ignore CSRF ok.
			} elseif ( isset( $_GET['post_type'] ) ) { // phpcs:ignore CSRF ok.
				$post_type = sanitize_text_field( wp_unslash( $_GET['post_type'] ) ); // phpcs:ignore CSRF ok.
			}
		}
		$post_types = self::get_post_types();

		// Get current screen ID.
		$current_screen    = get_current_screen();
		$screen_ids        = self::get_screen_ids();
		$current_screen_id = $current_screen ? $current_screen->id : null;

		if (
			in_array( $post_type, $post_types, true ) ||
			in_array( $taxonomy, $taxonomies, true ) ||
			self::is_woocommerce_core_taxonomy( $taxonomy ) ||
			in_array( $current_screen_id, $screen_ids, true )
		) {
			return true;
		}

		return false;
	}

	/**
	 * Check if a given taxonomy is a WooCommerce core related taxonomy.
	 *
	 * @param string $taxonomy Taxonomy.
	 * @return bool
	 */
	public static function is_woocommerce_core_taxonomy( $taxonomy ) {
		if ( in_array( $taxonomy, array( 'product_cat', 'product_tag' ), true ) ) {
			return true;
		}

		if ( 'pa_' === substr( $taxonomy, 0, 3 ) ) {
			return true;
		}

		return false;
	}

	/**
	 * Add navigation classes to body.
	 *
	 * @param string $classes Classes.
	 * @return string
	 */
	public function add_body_class( $classes ) {
		if ( self::is_woocommerce_page() ) {
			$classes .= ' has-woocommerce-navigation';

			/**
			 * Adds the ability to skip disabling of the WP toolbar.
			 *
			 * @param boolean $bool WP Toolbar disabled.
			 */
			if ( apply_filters( 'woocommerce_navigation_wp_toolbar_disabled', true ) ) {
				$classes .= ' is-wp-toolbar-disabled';
			}
		}

		return $classes;
	}

	/**
	 * Adds a screen ID to the list of screens that use the navigtion.
	 * Finds the parent if none is given to grab the correct screen ID.
	 *
	 * @param string      $callback Callback or URL for page.
	 * @param string|null $parent   Parent screen ID.
	 */
	public static function add_screen( $callback, $parent = null ) {
		global $submenu;

		$plugin_page = self::get_plugin_page( $callback );

		if ( ! $parent ) {
			$parent = Menu::get_parent_key( $callback );
		}

		$screen_id = get_plugin_page_hookname( $plugin_page, $parent );

		// This screen has already been added.
		if ( in_array( $screen_id, self::$screen_ids, true ) ) {
			return;
		}

		self::$screen_ids[] = $screen_id;
	}

	/**
	 * Get the plugin page slug.
	 *
	 * @param string $callback Callback.
	 * @return string
	 */
	public static function get_plugin_page( $callback ) {
		$url   = Menu::get_callback_url( $callback );
		$parts = wp_parse_url( $url );

		if ( ! isset( $parts['query'] ) ) {
			return $callback;
		}

		parse_str( $parts['query'], $query );

		if ( ! isset( $query['page'] ) ) {
			return $callback;
		}

		$plugin_page = wp_unslash( $query['page'] );
		$plugin_page = plugin_basename( $plugin_page );
		return $plugin_page;
	}

	/**
	 * Register post type for use in WooCommerce Navigation screens.
	 *
	 * @param string $post_type Post type to add.
	 */
	public static function register_post_type( $post_type ) {
		if ( ! in_array( $post_type, self::$post_types, true ) ) {
			self::$post_types[] = $post_type;
		}
	}

	/**
	 * Register taxonomy for use in WooCommerce Navigation screens.
	 *
	 * @param string $taxonomy Taxonomy to add.
	 */
	public static function register_taxonomy( $taxonomy ) {
		if ( ! in_array( $taxonomy, self::$taxonomies, true ) ) {
			self::$taxonomies[] = $taxonomy;
		}
	}
}