init_query_vars(); if ( wcs_is_woocommerce_pre( '3.4' ) ) { add_filter( 'woocommerce_account_settings', array( $this, 'add_endpoint_account_settings' ) ); } else { add_filter( 'woocommerce_get_settings_advanced', array( $this, 'add_endpoint_account_settings' ) ); } } /** * Init query vars by loading options. * * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0 */ public function init_query_vars() { $this->query_vars = array( 'view-subscription' => $this->get_view_subscription_endpoint(), ); if ( ! wcs_is_woocommerce_pre( '2.6' ) ) { $this->query_vars['subscriptions'] = get_option( 'woocommerce_myaccount_subscriptions_endpoint', 'subscriptions' ); $this->query_vars['subscription-payment-method'] = get_option( 'woocommerce_myaccount_subscription_payment_method_endpoint', 'subscription-payment-method' ); } } /** * Changes page title on view subscription page * * @param string $title original title * @return string changed title */ public function change_endpoint_title( $title ) { if ( in_the_loop() && is_account_page() ) { foreach ( $this->query_vars as $key => $query_var ) { if ( $this->is_query( $query_var ) ) { $title = $this->get_endpoint_title( $key ); // unhook after we've returned our title to prevent it from overriding others remove_filter( 'the_title', array( $this, __FUNCTION__ ), 11 ); } } } return $title; } /** * Hooks onto `woocommerce_endpoint_{$endpoint}_title` to return the correct page title for subscription endpoints * in My Account. * * @param string $title * @param string $endpoint * @return string * * @since 1.0.0 - Migrated from WooCommerce Subscriptions v3.0.10 */ public function change_my_account_endpoint_title( $title, $endpoint ) { global $wp; switch ( $endpoint ) { case 'view-subscription': $subscription = wcs_get_subscription( $wp->query_vars['view-subscription'] ); // translators: placeholder is a subscription ID. $title = ( $subscription ) ? sprintf( _x( 'Subscription #%s', 'hash before order number', 'woocommerce-subscriptions' ), $subscription->get_order_number() ) : ''; break; case 'subscriptions': if ( ! empty( $wp->query_vars['subscriptions'] ) ) { // translators: placeholder is a page number. $title = sprintf( __( 'Subscriptions (page %d)', 'woocommerce-subscriptions' ), intval( $wp->query_vars['subscriptions'] ) ); } else { $title = __( 'Subscriptions', 'woocommerce-subscriptions' ); } break; } return $title; } /** * Insert the new endpoint into the My Account menu. * * @param array $menu_items * @return array */ public function add_menu_items( $menu_items ) { // If the Subscriptions endpoint setting is empty, don't display it in line with core WC behaviour. if ( empty( $this->query_vars['subscriptions'] ) ) { return $menu_items; } if ( 1 === count( wcs_get_users_subscriptions() ) && apply_filters( 'wcs_my_account_redirect_to_single_subscription', true ) ) { $label = __( 'My Subscription', 'woocommerce-subscriptions' ); } else { $label = __( 'Subscriptions', 'woocommerce-subscriptions' ); } // Add our menu item after the Orders tab if it exists, otherwise just add it to the end if ( array_key_exists( 'orders', $menu_items ) ) { $menu_items = wcs_array_insert_after( 'orders', $menu_items, 'subscriptions', $label ); } else { $menu_items['subscriptions'] = $label; } return $menu_items; } /** * Changes the URL for the subscriptions endpoint when there's only one user subscription. * * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.2.17 * @param string $url * @param string $endpoint * @return string */ public function maybe_redirect_to_only_subscription( $url, $endpoint ) { if ( $this->query_vars['subscriptions'] === $endpoint && ( is_account_page() || is_order_received_page() ) ) { $subscriptions = wcs_get_users_subscriptions(); if ( is_array( $subscriptions ) && 1 === count( $subscriptions ) && apply_filters( 'wcs_my_account_redirect_to_single_subscription', true ) ) { $subscription = reset( $subscriptions ); $url = $subscription->get_view_order_url(); } } return $url; } /** * Endpoint HTML content. * * @param int $current_page */ public function endpoint_content( $current_page = 1 ) { $current_page = empty( $current_page ) ? 1 : absint( $current_page ); wc_get_template( 'myaccount/subscriptions.php', array( 'current_page' => $current_page ), '', WC_Subscriptions_Plugin::instance()->get_plugin_directory( 'templates/' ) ); } /** * Check if the current query is for a type we want to override. * * @param string $query_var the string for a query to check for * @return bool */ protected function is_query( $query_var ) { global $wp; if ( is_main_query() && is_page() && isset( $wp->query_vars[ $query_var ] ) ) { $is_view_subscription_query = true; } else { $is_view_subscription_query = false; } return apply_filters( 'wcs_query_is_query', $is_view_subscription_query, $query_var ); } /** * Fix for endpoints on the homepage * * Based on WC_Query->pre_get_posts(), but only applies the fix for endpoints on the homepage from it * instead of duplicating all the code to handle the main product query. * * @param mixed $q query object */ public function pre_get_posts( $q ) { // We only want to affect the main query if ( ! $q->is_main_query() ) { return; } if ( $q->is_home() && 'page' === get_option( 'show_on_front' ) && absint( get_option( 'page_on_front' ) ) !== absint( $q->get( 'page_id' ) ) ) { $_query = wp_parse_args( $q->query ); if ( ! empty( $_query ) && array_intersect( array_keys( $_query ), array_keys( $this->query_vars ) ) ) { $q->is_page = true; $q->is_home = false; $q->is_singular = true; $q->set( 'page_id', (int) get_option( 'page_on_front' ) ); add_filter( 'redirect_canonical', '__return_false' ); } } } /** * Redirect to order-pay flow for Subscription Payment Method endpoint. * * @param WP_Query $query WordPress query object * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.5.0 */ public function maybe_redirect_payment_methods( $query ) { if ( ! $query->is_main_query() || ! absint( $query->get( 'subscription-payment-method' ) ) ) { return; } $subscription_id = absint( $query->get( 'subscription-payment-method' ) ); $subscription = wcs_get_subscription( $subscription_id ); if ( ! $subscription || ! current_user_can( 'edit_shop_subscription_payment_method', $subscription_id ) ) { return; } if ( ! $subscription->can_be_updated_to( 'new-payment-method' ) ) { $url = $subscription->get_view_order_url(); wc_add_notice( __( 'The payment method can not be changed for that subscription.', 'woocommerce-subscriptions' ), 'error' ); } else { $args = array( 'change_payment_method' => $subscription->get_id(), '_wpnonce' => wp_create_nonce(), ); $url = add_query_arg( $args, $subscription->get_checkout_payment_url() ); } wp_redirect( $url ); // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect exit(); } /** * Reset the woocommerce_myaccount_view_subscriptions_endpoint option name to woocommerce_myaccount_view_subscription_endpoint * * @return mixed Value set for the option * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.2.18 */ private function get_view_subscription_endpoint() { $value = get_option( 'woocommerce_myaccount_view_subscriptions_endpoint', null ); if ( isset( $value ) ) { wcs_doing_it_wrong( 'woocommerce_myaccount_view_subscriptions_endpoint', sprintf( '%1$s option is deprecated. Use %2$s option instead.', 'woocommerce_myaccount_view_subscriptions_endpoint', 'woocommerce_myaccount_view_subscription_endpoint' ), '2.2.17' ); // Update the current option name with the value that was set in the deprecated option name update_option( 'woocommerce_myaccount_view_subscription_endpoint', $value ); // Now that things are upto date, do away with the deprecated option name delete_option( 'woocommerce_myaccount_view_subscriptions_endpoint' ); } return get_option( 'woocommerce_myaccount_view_subscription_endpoint', 'view-subscription' ); } /** * Add UI option for changing Subscription endpoints in WC settings * * @param mixed $settings * @return mixed $settings */ public function add_endpoint_account_settings( $settings ) { $subscriptions_endpoint_setting = array( 'title' => __( 'Subscriptions', 'woocommerce-subscriptions' ), 'desc' => __( 'Endpoint for the My Account → Subscriptions page', 'woocommerce-subscriptions' ), 'id' => 'woocommerce_myaccount_subscriptions_endpoint', 'type' => 'text', 'default' => 'subscriptions', 'desc_tip' => true, ); $view_subscription_endpoint_setting = array( 'title' => __( 'View subscription', 'woocommerce-subscriptions' ), 'desc' => __( 'Endpoint for the My Account → View Subscription page', 'woocommerce-subscriptions' ), 'id' => 'woocommerce_myaccount_view_subscription_endpoint', 'type' => 'text', 'default' => 'view-subscription', 'desc_tip' => true, ); $subscription_payment_method_endpoint_setting = array( 'title' => __( 'Subscription payment method', 'woocommerce-subscriptions' ), 'desc' => __( 'Endpoint for the My Account → Change Subscription Payment Method page', 'woocommerce-subscriptions' ), 'id' => 'woocommerce_myaccount_subscription_payment_method_endpoint', 'type' => 'text', 'default' => 'subscription-payment-method', 'desc_tip' => true, ); WC_Subscriptions_Admin::insert_setting_after( $settings, 'woocommerce_myaccount_view_order_endpoint', array( $subscriptions_endpoint_setting, $view_subscription_endpoint_setting, $subscription_payment_method_endpoint_setting ), 'multiple_settings' ); return $settings; } /** * Get endpoint URL. * * Gets the URL for an endpoint, which varies depending on permalink settings. * * @param string $endpoint * @param string $value * @param string $permalink * * @return string $url */ public function get_endpoint_url( $url, $endpoint, $value = '', $permalink = '' ) { if ( ! empty( $this->query_vars[ $endpoint ] ) ) { remove_filter( 'woocommerce_get_endpoint_url', array( $this, 'get_endpoint_url' ) ); $url = wc_get_endpoint_url( $this->query_vars[ $endpoint ], $value, $permalink ); add_filter( 'woocommerce_get_endpoint_url', array( $this, 'get_endpoint_url' ), 10, 4 ); } return $url; } /** * Hooks into `woocommerce_get_query_vars` to make sure query vars defined in * this class are also considered `WC_Query` query vars. * * @param array $query_vars * @return array * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.3.0 */ public function add_wcs_query_vars( $query_vars ) { return array_merge( $query_vars, $this->query_vars ); } /** * Adds `is-active` class to Subscriptions label when we're viewing a single Subscription. * * @param array $classes The classes present in the current endpoint. * @param string $endpoint The endpoint/label we're filtering. * * @return array * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.5.6 */ public function maybe_add_active_class( $classes, $endpoint ) { if ( ! isset( $classes['is-active'] ) && 'subscriptions' === $endpoint && wcs_is_view_subscription_page() ) { $classes[] = 'is-active'; } return $classes; } /** * Adds endpoint breadcrumb when viewing subscription. * * Deprecated as we now use the `woocommerce_endpoint_{$endpoint}_title` hook which automatically integrates with * breadcrumb generation. * * @param array $crumbs already assembled breadcrumb data * @return array $crumbs if we're on a view-subscription page, then augmented breadcrumb data * * @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v3.0.10 */ public function add_breadcrumb( $crumbs ) { _deprecated_function( __METHOD__, '3.0.10' ); foreach ( $this->query_vars as $key => $query_var ) { if ( $this->is_query( $query_var ) ) { $crumbs[] = array( $this->get_endpoint_title( $key ) ); } } return $crumbs; } }