OwlCyberSecurity - MANAGER
Edit File: class-pinterest-for-woocommerce-admin.php
<?php /** * Handle Admin init. * * @package Pinterest/Admin * @version 1.0.0 */ use Automattic\WooCommerce\Admin\Features\Features; use Automattic\WooCommerce\Admin\Features\Navigation\Menu; use Automattic\WooCommerce\Admin\Features\Navigation\Screen; use Automattic\WooCommerce\Admin\Loader; use Automattic\WooCommerce\Admin\PageController; use Automattic\WooCommerce\Blocks\Package; use Automattic\WooCommerce\Blocks\Assets\AssetDataRegistry; use Automattic\WooCommerce\Pinterest\Compat; use Automattic\WooCommerce\Pinterest\Tracking; use Automattic\WooCommerce\Pinterest\PinterestSyncSettings; if ( ! defined( 'ABSPATH' ) ) { exit; } if ( ! class_exists( 'Pinterest_For_Woocommerce_Admin' ) ) : /** * Class handling the settings page and onboarding Wizard registration and rendering. */ class Pinterest_For_Woocommerce_Admin { /** * Initialize class */ public function __construct() { add_action( 'admin_enqueue_scripts', array( $this, 'load_admin_assets' ) ); add_action( 'admin_init', array( $this, 'maybe_redirect_to_middleware' ) ); add_filter( 'woocommerce_get_registered_extended_tasks', array( $this, 'register_task_list_item' ), 10, 1 ); add_filter( 'admin_footer', array( $this, 'load_settings' ) ); add_filter( 'woocommerce_marketing_menu_items', array( $this, 'add_menu_items' ) ); add_action( 'admin_menu', array( $this, 'fix_menu_paths' ) ); add_action( 'admin_menu', array( $this, 'register_wc_admin_pages' ) ); } /** * Handle registration of all needed pages, depending on setup_complete status, * and wether we have the new WC nav enabled or not. * * @return void */ public function register_wc_admin_pages() { $new_nav = $this->is_new_nav_enabled(); $setup_complete = Pinterest_For_Woocommerce()::is_setup_complete(); if ( $new_nav && $setup_complete ) { // If setup is complete, add the base menu item as a category, and the settings as the main item. // Connection & catalog are added later on, for both new and old nav. wc_admin_register_page( array( 'id' => 'pinterest-for-woocommerce-category', 'title' => esc_html__( 'Pinterest', 'pinterest-for-woocommerce' ), 'parent' => 'woocommerce', 'path' => '/pinterest/settings', 'nav_args' => array( 'title' => esc_html__( 'Pinterest', 'pinterest-for-woocommerce' ), 'is_category' => true, 'menuId' => 'plugins', 'is_top_level' => true, ), ) ); wc_admin_register_page( array( 'id' => 'pinterest-for-woocommerce-catalog', 'title' => esc_html__( 'Catalog', 'pinterest-for-woocommerce' ), 'parent' => 'pinterest-for-woocommerce-category', 'path' => '/pinterest/catalog', 'nav_args' => array( 'order' => 10, 'parent' => 'pinterest-for-woocommerce-category', ), ) ); } elseif ( $new_nav ) { // Setup not complete. Add the Landing page as the main menu item. wc_admin_register_page( array( 'id' => 'pinterest-for-woocommerce-landing-page', 'title' => esc_html__( 'Pinterest', 'pinterest-for-woocommerce' ), 'parent' => 'woocommerce', 'path' => '/pinterest/landing', 'nav_args' => array( 'title' => esc_html__( 'Pinterest', 'pinterest-for-woocommerce' ), 'menuId' => 'plugins', 'is_top_level' => true, ), ) ); // Allow rendering of the onboarding guide on a page refresh. wc_admin_register_page( array( 'id' => 'pinterest-for-woocommerce-setup-guide', 'title' => esc_html__( 'Setup Pinterest', 'pinterest-for-woocommerce' ), 'parent' => '', 'path' => '/pinterest/onboarding', ) ); } $menu_items_parent = $new_nav ? 'pinterest-for-woocommerce-category' : 'toplevel_page_woocommerce-marketing'; if ( $setup_complete ) { // The connection & settings pages are registered for both old & new nav, if setup is complete. wc_admin_register_page( array( 'id' => 'pinterest-for-woocommerce-connection', 'title' => esc_html__( 'Connection', 'pinterest-for-woocommerce' ), 'parent' => $menu_items_parent, 'path' => '/pinterest/connection', 'nav_args' => array( 'order' => 50, 'parent' => $menu_items_parent, ), ) ); wc_admin_register_page( array( 'id' => 'pinterest-for-woocommerce-settings', 'title' => esc_html__( 'Settings', 'pinterest-for-woocommerce' ), 'parent' => $menu_items_parent, 'path' => '/pinterest/settings', 'nav_args' => array( 'order' => 40, 'parent' => $menu_items_parent, ), ) ); } if ( ! $new_nav ) { // Allow rendering of the onboarding guide on a page refresh. wc_admin_register_page( array( 'id' => 'pinterest-for-woocommerce-setup-guide', 'title' => esc_html__( 'Setup Pinterest', 'pinterest-for-woocommerce' ), 'parent' => 'toplevel_page_woocommerce-marketing', 'path' => '/pinterest/onboarding', ) ); } if ( $setup_complete ) { // Allow rendering of the landing page on a page refresh for both old & new nav, when setup is complete. wc_admin_register_page( array( 'id' => 'pinterest-for-woocommerce-landing-page', 'title' => esc_html__( 'Landing page', 'pinterest-for-woocommerce' ), 'parent' => '', 'path' => '/pinterest/landing', ) ); } } /** * Fix sub-menu paths. wc_admin_register_page() gets it wrong. * * @return void */ public function fix_menu_paths() { global $submenu; if ( ! isset( $submenu['woocommerce-marketing'] ) || $this->is_new_nav_enabled() ) { return; } foreach ( $submenu['woocommerce-marketing'] as &$item ) { // The "slug" (aka the path) is the third item in the array. if ( 0 === strpos( $item[2], 'wc-admin' ) ) { $item[2] = 'admin.php?page=' . $item[2]; } } } /** * Add the base menu item using the woocommerce_marketing_menu_items filter, * Depending on status of setup_complete. * * @param array $items The array of items to be filtered. * * @return array */ public function add_menu_items( $items ) { if ( $this->is_new_nav_enabled() ) { return $items; } if ( Pinterest_For_Woocommerce()::is_setup_complete() ) { $items[] = array( 'id' => 'pinterest-for-woocommerce-catalog', 'title' => esc_html__( 'Pinterest', 'pinterest-for-woocommerce' ), 'path' => '/pinterest/catalog', 'capability' => 'manage_woocommerce', ); } else { $items[] = array( 'id' => 'pinterest-for-woocommerce-landing-page', 'title' => esc_html__( 'Pinterest', 'pinterest-for-woocommerce' ), 'path' => '/pinterest/landing', 'capability' => 'manage_woocommerce', ); } return $items; } /** * Checks if the new WC navigation is enabled. * * @return boolean */ public function is_new_nav_enabled() { return method_exists( Screen::class, 'register_post_type' ) && method_exists( Menu::class, 'add_plugin_item' ) && method_exists( Menu::class, 'add_plugin_category' ) && method_exists( Features::class, 'is_enabled' ) && Features::is_enabled( 'navigation' ); } /** * Compatibility layer for is_admin_page function. * Needed since WC 6.5. */ private function is_admin_page(): bool { if ( method_exists( PageController::class, 'is_admin_page' ) ) { return PageController::is_admin_page(); } else { return class_exists( Loader::class ) && Loader::is_admin_page(); } } /** * Load the scripts needed for the setup guide / settings page. */ public function load_setup_guide_scripts() { if ( ! $this->is_admin_page() ) { return; } $build_path = '/assets/build'; $handle = PINTEREST_FOR_WOOCOMMERCE_PREFIX . '-setup-guide'; $script_asset_path = Pinterest_For_Woocommerce()->plugin_path() . $build_path . '/setup-guide.asset.php'; $script_info = file_exists( $script_asset_path ) ? include $script_asset_path : array( 'dependencies' => array(), 'version' => PINTEREST_FOR_WOOCOMMERCE_VERSION, ); // This is a quick fix for a breaking change in WP 6.6. // We may not need this in the future when we update `@wordpress/*` packages to newer versions. $script_info['dependencies'][] = 'regenerator-runtime'; $script_info['dependencies'][] = 'wc-settings'; wp_register_script( $handle, Pinterest_For_Woocommerce()->plugin_url() . $build_path . '/setup-guide.js', $script_info['dependencies'], $script_info['version'], true ); wp_enqueue_script( $handle ); wp_register_style( $handle, Pinterest_For_Woocommerce()->plugin_url() . $build_path . '/style-setup-guide.css', array( 'wc-admin-app' ), PINTEREST_FOR_WOOCOMMERCE_VERSION ); wp_enqueue_style( $handle ); } /** * Enqueues admin related scripts & styles * * @return void */ public function load_admin_assets() { $assets_path_url = str_replace( array( 'http:', 'https:' ), '', Pinterest_For_Woocommerce()->plugin_url() ) . '/assets/'; $ext = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min'; wp_enqueue_script( 'pinterest-for-woocommerce-admin', $assets_path_url . 'js/admin/pinterest-for-woocommerce-admin' . $ext . '.js', array( 'jquery' ), PINTEREST_FOR_WOOCOMMERCE_VERSION, true ); $this->load_setup_guide_scripts(); } /** * Register the Task List item for WC-Admin. * * @param array $registered_tasks_list_items the list of tasks to be filtered. */ public function register_task_list_item( $registered_tasks_list_items ) { if ( ! $this->is_admin_page() || ! Compat::should_show_tasks() ) { return $registered_tasks_list_items; } $new_task_name = 'woocommerce_admin_add_task_pinterest_setup'; if ( ! in_array( $new_task_name, $registered_tasks_list_items, true ) ) { array_push( $registered_tasks_list_items, $new_task_name ); } return $registered_tasks_list_items; } /** * Load all plugin frontend data using the AssetDataRegistry class. * Hooked to admin_footer as AssetDataRegistry prints at wp_print_footer_scripts. * * @return void */ public function load_settings() { if ( ! $this->is_admin_page() || ! class_exists( AssetDataRegistry::class ) ) { return; } Package::container()->get( AssetDataRegistry::class )->add( 'pinterest_for_woocommerce', $this->get_component_settings() ); } /** * Initialize asset data and registering it with * the internal WC data registry. * * @return array */ private function get_component_settings() { $store_country = Pinterest_For_Woocommerce()::get_base_country(); return array( 'pluginVersion' => PINTEREST_FOR_WOOCOMMERCE_VERSION, 'pluginUrl' => Pinterest_For_Woocommerce()->plugin_url(), 'serviceLoginUrl' => $this->get_service_login_url(), 'createBusinessAccountUrl' => $this->get_create_business_account_url(), 'switchBusinessAccountUrl' => $this->get_switch_business_account_url(), 'billingSettingsUrl' => $this->get_advertiser_billing_settings_url(), 'homeUrlToVerify' => get_home_url(), 'storeCountry' => $store_country, 'isAdsSupportedCountry' => Pinterest_For_Woocommerce_Ads_Supported_Countries::is_ads_supported_country(), 'isConnected' => ! empty( Pinterest_For_Woocommerce()::is_connected() ), 'isBusinessConnected' => ! empty( Pinterest_For_Woocommerce()::is_business_connected() ), 'businessAccounts' => Pinterest_For_Woocommerce()::get_linked_businesses(), 'apiRoute' => PINTEREST_FOR_WOOCOMMERCE_API_NAMESPACE . '/v' . PINTEREST_FOR_WOOCOMMERCE_API_VERSION, 'optionsName' => PINTEREST_FOR_WOOCOMMERCE_OPTION_NAME, 'syncedSettings' => PinterestSyncSettings::get_synced_settings(), 'error' => isset( $_GET['error'] ) ? sanitize_text_field( wp_unslash( $_GET['error'] ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Recommended --- not needed 'pinterestLinks' => array( 'newAccount' => 'https://business.pinterest.com/', 'claimWebsite' => 'https://help.pinterest.com/en/business/article/claim-your-website', 'richPins' => 'https://help.pinterest.com/en/business/article/rich-pins', 'enhancedMatch' => 'https://help.pinterest.com/en/business/article/enhanced-match', 'createAdvertiser' => 'https://help.pinterest.com/en/business/article/create-an-advertiser-account', 'adGuidelines' => 'https://policy.pinterest.com/en/advertising-guidelines', 'adDataTerms' => 'https://policy.pinterest.com/en/ad-data-terms', 'merchantGuidelines' => 'https://policy.pinterest.com/en/merchant-guidelines', 'convertToBusinessAcct' => 'https://help.pinterest.com/en/business/article/get-a-business-account#section-15096', 'appealDeclinedMerchant' => 'https://www.pinterest.com/product-catalogs/data-source/?showModal=true', 'installTag' => 'https://help.pinterest.com/en/business/article/install-the-pinterest-tag', 'adsManager' => 'https://ads.pinterest.com/', 'preLaunchNotice' => 'https://help.pinterest.com/en-gb/business/article/get-a-business-profile/', 'adsAvailability' => 'https://help.pinterest.com/en/business/availability/ads-availability', 'automaticEnhancedMatch' => 'https://www.pinterest.com/_/_/help/business/article/automatic-enhanced-match', 'tagManager' => $this->get_tag_manager_link(), ), 'isSetupComplete' => Pinterest_For_Woocommerce()::is_setup_complete(), 'countryTos' => Pinterest_For_Woocommerce()::get_applicable_tos(), 'claimWebsiteErrorStatus' => array( 401 => 'token', 403 => 'connection', 406 => 'domain verification', 409 => 'meta-tag', ), 'conflictingTagsWarning' => Tracking\Tag::get_third_party_tags_warning_message(), ); } /** * Return the serviceLoginUrl * * @return string */ private function get_service_login_url() { return add_query_arg( array( 'page' => 'wc-admin', 'view' => 'wizard', PINTEREST_FOR_WOOCOMMERCE_PREFIX . '_go_to_service_login' => '1', PINTEREST_FOR_WOOCOMMERCE_PREFIX . '_nonce' => $this->get_middleware_url_nonce(), ), admin_url( 'admin.php' ) ); } /** * Return the createBusinessAccountUrl * * @return string */ private function get_create_business_account_url() { return add_query_arg( array( 'page' => 'wc-admin', 'view' => 'wizard', PINTEREST_FOR_WOOCOMMERCE_PREFIX . '_go_to_create_account' => '1', PINTEREST_FOR_WOOCOMMERCE_PREFIX . '_nonce' => $this->get_middleware_url_nonce(), ), admin_url( 'admin.php' ) ); } /** * Return the switchBusinessAccountUrl * * @return string */ private function get_switch_business_account_url() { return add_query_arg( array( 'page' => 'wc-admin', 'view' => 'wizard', PINTEREST_FOR_WOOCOMMERCE_PREFIX . '_go_to_switch_account' => '1', PINTEREST_FOR_WOOCOMMERCE_PREFIX . '_nonce' => $this->get_middleware_url_nonce(), ), admin_url( 'admin.php' ) ); } /** * Return the advertiser billing settings URL. * * @since 1.4.5 * @return string */ private function get_advertiser_billing_settings_url() { $advertiser_id = Pinterest_For_Woocommerce()->get_setting( 'tracking_advertiser' ); return "https://ads.pinterest.com/advertiser/{$advertiser_id}/billing"; } /** * Create & return a nonce for the service URL. * This nonce is runtime cached. * * @return string */ private function get_middleware_url_nonce() { static $nonce; return null === $nonce ? wp_create_nonce( 'go_to_middleware_url' ) : $nonce; } /** * Handles redirection to the Middleware App (Woo Connect Bridge). */ public function maybe_redirect_to_middleware() { if ( ! isset( $_GET[ PINTEREST_FOR_WOOCOMMERCE_PREFIX . '_go_to_service_login' ] ) && ! isset( $_GET[ PINTEREST_FOR_WOOCOMMERCE_PREFIX . '_go_to_create_account' ] ) && ! isset( $_GET[ PINTEREST_FOR_WOOCOMMERCE_PREFIX . '_go_to_switch_account' ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended --- not needed return; } if ( ! isset( $_GET[ PINTEREST_FOR_WOOCOMMERCE_PREFIX . '_nonce' ] ) || ! wp_verify_nonce( sanitize_key( $_GET[ PINTEREST_FOR_WOOCOMMERCE_PREFIX . '_nonce' ] ), 'go_to_middleware_url' ) || ! current_user_can( 'manage_woocommerce' ) ) { wp_die( esc_html__( "Cheatin' huh?", 'pinterest-for-woocommerce' ) ); } $context = 'login'; $args = array( 'view' => ! empty( $_REQUEST['view'] ) ? sanitize_key( $_REQUEST['view'] ) : null ); if ( isset( $_GET[ PINTEREST_FOR_WOOCOMMERCE_PREFIX . '_go_to_create_account' ] ) ) { $context = 'create_business'; } elseif ( isset( $_GET[ PINTEREST_FOR_WOOCOMMERCE_PREFIX . '_go_to_switch_account' ] ) && ! empty( $_GET['business_id'] ) ) { $context = 'switch_business'; $args['business_id'] = sanitize_key( $_GET['business_id'] ); } add_filter( 'allowed_redirect_hosts', array( $this, 'allow_service_login' ) ); wp_safe_redirect( Pinterest_For_Woocommerce()::get_middleware_url( $context, $args ) ); exit; } /** * Add the domain of API/Bridge service to the list of allowed redirect hosts. * * @param array $allowed_hosts the array of allowed hosts. * * @return array */ public function allow_service_login( $allowed_hosts ) { $service_domain = Pinterest_For_Woocommerce()::get_connection_proxy_url(); $allowed_hosts[] = wp_parse_url( $service_domain, PHP_URL_HOST ); return $allowed_hosts; } /** * Get tags manager link if there is a connected advertiser or the ads manager link if not. * * @since 1.2.18 * * @return string */ protected function get_tag_manager_link() { $tag_manager_link = 'https://ads.pinterest.com/advertiser/'; $advertiser_id = Pinterest_For_Woocommerce()->get_setting( 'tracking_advertiser' ); if ( ! $advertiser_id ) { return $tag_manager_link; } return "{$tag_manager_link}{$advertiser_id}/conversions/tag"; } } endif; return new Pinterest_For_Woocommerce_Admin();