| 1 |
<?php namespace TierPricingTable\Addons\NonLoggedInUsers\Visibility; |
| 2 |
|
| 3 |
use TierPricingTable\Addons\NonLoggedInUsers\Wholesale\Settings\Settings as WholesaleSettings; |
| 4 |
use WP_Error; |
| 5 |
|
| 6 |
/** |
| 7 |
* Closed store: visitors who are not logged in are sent to the login page. My Account (login, |
| 8 |
* registration, lost password), the wholesale registration page and the pages chosen in the settings |
| 9 |
* stay open; the Store API's product routes are closed to visitors too. |
| 10 |
*/ |
| 11 |
class ClosedStoreService { |
| 12 |
|
| 13 |
public function __construct() { |
| 14 |
add_action( 'template_redirect', array( $this, 'guard' ), 1 ); |
| 15 |
add_filter( 'rest_pre_dispatch', array( $this, 'guardStoreApi' ), 10, 3 ); |
| 16 |
add_filter( 'woocommerce_login_redirect', array( $this, 'redirectBack' ), 20 ); |
| 17 |
} |
| 18 |
|
| 19 |
public function guard() { |
| 20 |
if ( ! VisibilitySettings::isClosedStore() || is_user_logged_in() ) { |
| 21 |
return; |
| 22 |
} |
| 23 |
|
| 24 |
if ( is_admin() || wp_doing_ajax() || wp_doing_cron() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) || ( defined( 'WP_CLI' ) && WP_CLI ) ) { |
| 25 |
return; |
| 26 |
} |
| 27 |
|
| 28 |
// feeds and robots stay; a not-found page tells nothing and must not loop through the login page |
| 29 |
if ( is_feed() || is_robots() || is_trackback() || is_favicon() || is_404() ) { |
| 30 |
return; |
| 31 |
} |
| 32 |
|
| 33 |
if ( $this->isOpenPage() ) { |
| 34 |
return; |
| 35 |
} |
| 36 |
|
| 37 |
wp_safe_redirect( self::getLoginUrl( $this->currentUrl() ) ); |
| 38 |
exit; |
| 39 |
} |
| 40 |
|
| 41 |
protected function isOpenPage(): bool { |
| 42 |
$open = array_merge( array( (int) wc_get_page_id( 'myaccount' ), WholesaleSettings::getRegistrationPageId() ), VisibilitySettings::getOpenPageIds() ); |
| 43 |
$open = array_values( array_filter( array_map( 'intval', $open ), function ( $id ) { |
| 44 |
return $id > 0; |
| 45 |
} ) ); |
| 46 |
|
| 47 |
if ( $open && is_page( $open ) ) { |
| 48 |
return true; |
| 49 |
} |
| 50 |
|
| 51 |
// the WooCommerce login form on a page that is not the My Account page (a login shortcode, for example) |
| 52 |
if ( is_page() && has_shortcode( (string) get_post_field( 'post_content', get_queried_object_id() ), 'woocommerce_my_account' ) ) { |
| 53 |
return true; |
| 54 |
} |
| 55 |
|
| 56 |
return (bool) apply_filters( 'tiered_pricing_table/closed_store/is_open_page', false ); |
| 57 |
} |
| 58 |
|
| 59 |
/** |
| 60 |
* Visitors get no product data from the Store API while the store is closed. |
| 61 |
* |
| 62 |
* @param mixed $result |
| 63 |
* @param \WP_REST_Server $server |
| 64 |
* @param \WP_REST_Request $request |
| 65 |
*/ |
| 66 |
public function guardStoreApi( $result, $server, $request ) { |
| 67 |
if ( null !== $result || ! VisibilitySettings::isClosedStore() || is_user_logged_in() ) { |
| 68 |
return $result; |
| 69 |
} |
| 70 |
|
| 71 |
if ( preg_match( '#^/wc/store/v\d+/products#', (string) $request->get_route() ) ) { |
| 72 |
return new WP_Error( 'tpt_closed_store', __( 'Please log in to browse the store.', 'tier-pricing-table' ), array( 'status' => 401 ) ); |
| 73 |
} |
| 74 |
|
| 75 |
return $result; |
| 76 |
} |
| 77 |
|
| 78 |
/** |
| 79 |
* After the login the visitor lands where the closed store stopped them. |
| 80 |
*/ |
| 81 |
public function redirectBack( $redirect ) { |
| 82 |
$back = isset( $_REQUEST['redirect_to'] ) ? esc_url_raw( wp_unslash( $_REQUEST['redirect_to'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended |
| 83 |
|
| 84 |
return $back && wp_validate_redirect( $back, '' ) ? $back : $redirect; |
| 85 |
} |
| 86 |
|
| 87 |
/** |
| 88 |
* The login page (My Account, or wp-login.php without it) with the way back. |
| 89 |
*/ |
| 90 |
public static function getLoginUrl( string $redirectTo = '' ): string { |
| 91 |
$pageId = (int) wc_get_page_id( 'myaccount' ); |
| 92 |
|
| 93 |
if ( $pageId < 1 || 'publish' !== get_post_status( $pageId ) ) { |
| 94 |
return wp_login_url( $redirectTo ); |
| 95 |
} |
| 96 |
|
| 97 |
$url = get_permalink( $pageId ); |
| 98 |
|
| 99 |
return $redirectTo ? add_query_arg( 'redirect_to', rawurlencode( $redirectTo ), $url ) : $url; |
| 100 |
} |
| 101 |
|
| 102 |
protected function currentUrl(): string { |
| 103 |
$host = isset( $_SERVER['HTTP_HOST'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : (string) wp_parse_url( home_url(), PHP_URL_HOST ); |
| 104 |
$path = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '/'; |
| 105 |
|
| 106 |
return esc_url_raw( ( is_ssl() ? 'https://' : 'http://' ) . $host . $path ); |
| 107 |
} |
| 108 |
} |
| 109 |
|