PageRenderTime 26ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/woocommerce-payments/vendor/woocommerce/subscriptions-core/includes/class-wcs-query.php

https://gitlab.com/remyvianne/krowkaramel
PHP | 389 lines | 204 code | 58 blank | 127 comment | 43 complexity | bfb3e1c27cc8cf2d548a00a304166374 MD5 | raw file
  1. <?php
  2. /**
  3. * WooCommerce Subscriptions Query Handler
  4. *
  5. * @version 2.0
  6. * @author Prospress
  7. */
  8. class WCS_Query extends WC_Query {
  9. public function __construct() {
  10. add_action( 'init', array( $this, 'add_endpoints' ) );
  11. add_filter( 'the_title', array( $this, 'change_endpoint_title' ), 11, 1 );
  12. if ( ! is_admin() ) {
  13. add_filter( 'query_vars', array( $this, 'add_query_vars' ), 0 );
  14. add_action( 'parse_request', array( $this, 'parse_request' ), 0 );
  15. add_action( 'pre_get_posts', array( $this, 'maybe_redirect_payment_methods' ) );
  16. add_action( 'pre_get_posts', array( $this, 'pre_get_posts' ), 11 );
  17. add_filter( 'woocommerce_get_query_vars', array( $this, 'add_wcs_query_vars' ) );
  18. // Inserting your new tab/page into the My Account page.
  19. add_filter( 'woocommerce_account_menu_items', array( $this, 'add_menu_items' ) );
  20. // Since WC 3.3.0, add_wcs_query_vars() is enough for custom endpoints to work.
  21. if ( wcs_is_woocommerce_pre( '3.3.0' ) ) {
  22. add_filter( 'woocommerce_get_endpoint_url', array( $this, 'get_endpoint_url' ), 10, 4 );
  23. }
  24. add_filter( 'woocommerce_get_endpoint_url', array( $this, 'maybe_redirect_to_only_subscription' ), 10, 2 );
  25. add_action( 'woocommerce_account_subscriptions_endpoint', array( $this, 'endpoint_content' ) );
  26. add_filter( 'woocommerce_account_menu_item_classes', array( $this, 'maybe_add_active_class' ), 10, 2 );
  27. add_filter( 'woocommerce_endpoint_subscriptions_title', array( $this, 'change_my_account_endpoint_title' ), 10, 2 );
  28. add_filter( 'woocommerce_endpoint_view-subscription_title', array( $this, 'change_my_account_endpoint_title' ), 10, 2 );
  29. }
  30. $this->init_query_vars();
  31. if ( wcs_is_woocommerce_pre( '3.4' ) ) {
  32. add_filter( 'woocommerce_account_settings', array( $this, 'add_endpoint_account_settings' ) );
  33. } else {
  34. add_filter( 'woocommerce_get_settings_advanced', array( $this, 'add_endpoint_account_settings' ) );
  35. }
  36. }
  37. /**
  38. * Init query vars by loading options.
  39. *
  40. * @since 2.0
  41. */
  42. public function init_query_vars() {
  43. $this->query_vars = array(
  44. 'view-subscription' => $this->get_view_subscription_endpoint(),
  45. );
  46. if ( ! wcs_is_woocommerce_pre( '2.6' ) ) {
  47. $this->query_vars['subscriptions'] = get_option( 'woocommerce_myaccount_subscriptions_endpoint', 'subscriptions' );
  48. $this->query_vars['subscription-payment-method'] = get_option( 'woocommerce_myaccount_subscription_payment_method_endpoint', 'subscription-payment-method' );
  49. }
  50. }
  51. /**
  52. * Changes page title on view subscription page
  53. *
  54. * @param string $title original title
  55. * @return string changed title
  56. */
  57. public function change_endpoint_title( $title ) {
  58. if ( in_the_loop() && is_account_page() ) {
  59. foreach ( $this->query_vars as $key => $query_var ) {
  60. if ( $this->is_query( $query_var ) ) {
  61. $title = $this->get_endpoint_title( $key );
  62. // unhook after we've returned our title to prevent it from overriding others
  63. remove_filter( 'the_title', array( $this, __FUNCTION__ ), 11 );
  64. }
  65. }
  66. }
  67. return $title;
  68. }
  69. /**
  70. * Hooks onto `woocommerce_endpoint_{$endpoint}_title` to return the correct page title for subscription endpoints
  71. * in My Account.
  72. *
  73. * @param string $title
  74. * @param string $endpoint
  75. * @return string
  76. *
  77. * @since 3.0.10
  78. */
  79. public function change_my_account_endpoint_title( $title, $endpoint ) {
  80. global $wp;
  81. switch ( $endpoint ) {
  82. case 'view-subscription':
  83. $subscription = wcs_get_subscription( $wp->query_vars['view-subscription'] );
  84. // translators: placeholder is a subscription ID.
  85. $title = ( $subscription ) ? sprintf( _x( 'Subscription #%s', 'hash before order number', 'woocommerce-subscriptions' ), $subscription->get_order_number() ) : '';
  86. break;
  87. case 'subscriptions':
  88. if ( ! empty( $wp->query_vars['subscriptions'] ) ) {
  89. // translators: placeholder is a page number.
  90. $title = sprintf( __( 'Subscriptions (page %d)', 'woocommerce-subscriptions' ), intval( $wp->query_vars['subscriptions'] ) );
  91. } else {
  92. $title = __( 'Subscriptions', 'woocommerce-subscriptions' );
  93. }
  94. break;
  95. }
  96. return $title;
  97. }
  98. /**
  99. * Insert the new endpoint into the My Account menu.
  100. *
  101. * @param array $items
  102. * @return array
  103. */
  104. public function add_menu_items( $menu_items ) {
  105. // If the Subscriptions endpoint setting is empty, don't display it in line with core WC behaviour.
  106. if ( empty( $this->query_vars['subscriptions'] ) ) {
  107. return $menu_items;
  108. }
  109. if ( 1 === count( wcs_get_users_subscriptions() ) && apply_filters( 'wcs_my_account_redirect_to_single_subscription', true ) ) {
  110. $label = __( 'My Subscription', 'woocommerce-subscriptions' );
  111. } else {
  112. $label = __( 'Subscriptions', 'woocommerce-subscriptions' );
  113. }
  114. // Add our menu item after the Orders tab if it exists, otherwise just add it to the end
  115. if ( array_key_exists( 'orders', $menu_items ) ) {
  116. $menu_items = wcs_array_insert_after( 'orders', $menu_items, 'subscriptions', $label );
  117. } else {
  118. $menu_items['subscriptions'] = $label;
  119. }
  120. return $menu_items;
  121. }
  122. /**
  123. * Changes the URL for the subscriptions endpoint when there's only one user subscription.
  124. *
  125. * @since 2.2.17
  126. * @param string $url
  127. * @param string $endpoint
  128. * @return string
  129. */
  130. public function maybe_redirect_to_only_subscription( $url, $endpoint ) {
  131. if ( $this->query_vars['subscriptions'] === $endpoint && is_account_page() ) {
  132. $subscriptions = wcs_get_users_subscriptions();
  133. if ( is_array( $subscriptions ) && 1 === count( $subscriptions ) && apply_filters( 'wcs_my_account_redirect_to_single_subscription', true ) ) {
  134. $subscription = reset( $subscriptions );
  135. $url = $subscription->get_view_order_url();
  136. }
  137. }
  138. return $url;
  139. }
  140. /**
  141. * Endpoint HTML content.
  142. *
  143. * @param int $current_page
  144. */
  145. public function endpoint_content( $current_page = 1 ) {
  146. $current_page = empty( $current_page ) ? 1 : absint( $current_page );
  147. wc_get_template( 'myaccount/subscriptions.php', array( 'current_page' => $current_page ), '', WC_Subscriptions_Core_Plugin::instance()->get_subscriptions_core_directory( 'templates/' ) );
  148. }
  149. /**
  150. * Check if the current query is for a type we want to override.
  151. *
  152. * @param string $query_var the string for a query to check for
  153. * @return bool
  154. */
  155. protected function is_query( $query_var ) {
  156. global $wp;
  157. if ( is_main_query() && is_page() && isset( $wp->query_vars[ $query_var ] ) ) {
  158. $is_view_subscription_query = true;
  159. } else {
  160. $is_view_subscription_query = false;
  161. }
  162. return apply_filters( 'wcs_query_is_query', $is_view_subscription_query, $query_var );
  163. }
  164. /**
  165. * Fix for endpoints on the homepage
  166. *
  167. * Based on WC_Query->pre_get_posts(), but only applies the fix for endpoints on the homepage from it
  168. * instead of duplicating all the code to handle the main product query.
  169. *
  170. * @param mixed $q query object
  171. */
  172. public function pre_get_posts( $q ) {
  173. // We only want to affect the main query
  174. if ( ! $q->is_main_query() ) {
  175. return;
  176. }
  177. if ( $q->is_home() && 'page' === get_option( 'show_on_front' ) && absint( get_option( 'page_on_front' ) ) !== absint( $q->get( 'page_id' ) ) ) {
  178. $_query = wp_parse_args( $q->query );
  179. if ( ! empty( $_query ) && array_intersect( array_keys( $_query ), array_keys( $this->query_vars ) ) ) {
  180. $q->is_page = true;
  181. $q->is_home = false;
  182. $q->is_singular = true;
  183. $q->set( 'page_id', (int) get_option( 'page_on_front' ) );
  184. add_filter( 'redirect_canonical', '__return_false' );
  185. }
  186. }
  187. }
  188. /**
  189. * Redirect to order-pay flow for Subscription Payment Method endpoint.
  190. *
  191. * @param WP_Query $query WordPress query object
  192. * @since 2.5.0
  193. */
  194. public function maybe_redirect_payment_methods( $query ) {
  195. if ( ! $query->is_main_query() || ! absint( $query->get( 'subscription-payment-method' ) ) ) {
  196. return;
  197. }
  198. $subscription = wcs_get_subscription( absint( $query->get( 'subscription-payment-method' ) ) );
  199. if ( ! $subscription ) {
  200. return;
  201. }
  202. if ( ! $subscription->can_be_updated_to( 'new-payment-method' ) ) {
  203. $url = $subscription->get_view_order_url();
  204. wc_add_notice( __( 'The payment method can not be changed for that subscription.', 'woocommerce-subscriptions' ), 'error' );
  205. } else {
  206. $args = array(
  207. 'change_payment_method' => $subscription->get_id(),
  208. '_wpnonce' => wp_create_nonce(),
  209. );
  210. $url = add_query_arg( $args, $subscription->get_checkout_payment_url() );
  211. }
  212. wp_redirect( $url ); // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect
  213. exit();
  214. }
  215. /**
  216. * Reset the woocommerce_myaccount_view_subscriptions_endpoint option name to woocommerce_myaccount_view_subscription_endpoint
  217. *
  218. * @return mixed Value set for the option
  219. * @since 2.2.18
  220. */
  221. private function get_view_subscription_endpoint() {
  222. $value = get_option( 'woocommerce_myaccount_view_subscriptions_endpoint', null );
  223. if ( isset( $value ) ) {
  224. 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' );
  225. // Update the current option name with the value that was set in the deprecated option name
  226. update_option( 'woocommerce_myaccount_view_subscription_endpoint', $value );
  227. // Now that things are upto date, do away with the deprecated option name
  228. delete_option( 'woocommerce_myaccount_view_subscriptions_endpoint' );
  229. }
  230. return get_option( 'woocommerce_myaccount_view_subscription_endpoint', 'view-subscription' );
  231. }
  232. /**
  233. * Add UI option for changing Subscription endpoints in WC settings
  234. *
  235. * @param mixed $account_settings
  236. * @return mixed $account_settings
  237. */
  238. public function add_endpoint_account_settings( $settings ) {
  239. $subscriptions_endpoint_setting = array(
  240. 'title' => __( 'Subscriptions', 'woocommerce-subscriptions' ),
  241. 'desc' => __( 'Endpoint for the My Account &rarr; Subscriptions page', 'woocommerce-subscriptions' ),
  242. 'id' => 'woocommerce_myaccount_subscriptions_endpoint',
  243. 'type' => 'text',
  244. 'default' => 'subscriptions',
  245. 'desc_tip' => true,
  246. );
  247. $view_subscription_endpoint_setting = array(
  248. 'title' => __( 'View subscription', 'woocommerce-subscriptions' ),
  249. 'desc' => __( 'Endpoint for the My Account &rarr; View Subscription page', 'woocommerce-subscriptions' ),
  250. 'id' => 'woocommerce_myaccount_view_subscription_endpoint',
  251. 'type' => 'text',
  252. 'default' => 'view-subscription',
  253. 'desc_tip' => true,
  254. );
  255. $subscription_payment_method_endpoint_setting = array(
  256. 'title' => __( 'Subscription payment method', 'woocommerce-subscriptions' ),
  257. 'desc' => __( 'Endpoint for the My Account &rarr; Change Subscription Payment Method page', 'woocommerce-subscriptions' ),
  258. 'id' => 'woocommerce_myaccount_subscription_payment_method_endpoint',
  259. 'type' => 'text',
  260. 'default' => 'subscription-payment-method',
  261. 'desc_tip' => true,
  262. );
  263. 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' );
  264. return $settings;
  265. }
  266. /**
  267. * Get endpoint URL.
  268. *
  269. * Gets the URL for an endpoint, which varies depending on permalink settings.
  270. *
  271. * @param string $endpoint
  272. * @param string $value
  273. * @param string $permalink
  274. *
  275. * @return string $url
  276. */
  277. public function get_endpoint_url( $url, $endpoint, $value = '', $permalink = '' ) {
  278. if ( ! empty( $this->query_vars[ $endpoint ] ) ) {
  279. remove_filter( 'woocommerce_get_endpoint_url', array( $this, 'get_endpoint_url' ) );
  280. $url = wc_get_endpoint_url( $this->query_vars[ $endpoint ], $value, $permalink );
  281. add_filter( 'woocommerce_get_endpoint_url', array( $this, 'get_endpoint_url' ), 10, 4 );
  282. }
  283. return $url;
  284. }
  285. /**
  286. * Hooks into `woocommerce_get_query_vars` to make sure query vars defined in
  287. * this class are also considered `WC_Query` query vars.
  288. *
  289. * @param array $query_vars
  290. * @return array
  291. * @since 2.3.0
  292. */
  293. public function add_wcs_query_vars( $query_vars ) {
  294. return array_merge( $query_vars, $this->query_vars );
  295. }
  296. /**
  297. * Adds `is-active` class to Subscriptions label when we're viewing a single Subscription.
  298. *
  299. * @param array $classes The classes present in the current endpoint.
  300. * @param string $endpoint The endpoint/label we're filtering.
  301. *
  302. * @return array
  303. * @since 2.5.6
  304. */
  305. public function maybe_add_active_class( $classes, $endpoint ) {
  306. if ( ! isset( $classes['is-active'] ) && 'subscriptions' === $endpoint && wcs_is_view_subscription_page() ) {
  307. $classes[] = 'is-active';
  308. }
  309. return $classes;
  310. }
  311. /**
  312. * Adds endpoint breadcrumb when viewing subscription.
  313. *
  314. * Deprecated as we now use the `woocommerce_endpoint_{$endpoint}_title` hook which automatically integrates with
  315. * breadcrumb generation.
  316. *
  317. * @param array $crumbs already assembled breadcrumb data
  318. * @return array $crumbs if we're on a view-subscription page, then augmented breadcrumb data
  319. *
  320. * @deprecated 3.0.10
  321. */
  322. public function add_breadcrumb( $crumbs ) {
  323. _deprecated_function( __METHOD__, '3.0.10' );
  324. foreach ( $this->query_vars as $key => $query_var ) {
  325. if ( $this->is_query( $query_var ) ) {
  326. $crumbs[] = array( $this->get_endpoint_title( $key ) );
  327. }
  328. }
  329. return $crumbs;
  330. }
  331. }