File: //wordpress/plugins/wp-cloud-client/beta/src/Access/LoginPageGuard.php
<?php
declare(strict_types=1);
namespace VPlugins\WPCloudClient\Access;
use VPlugins\WPCloudClient\Settings\SettingsRepository;
class LoginPageGuard {
/**
* Login-page actions that must always reach native handling, even when the
* login page is hidden (logout, lost-password and reset-password flows).
*
* @var string[]
*/
private const ALLOWED_ACTIONS = [ 'logout', 'lostpassword', 'rp', 'resetpass' ];
/**
* Construct the login page guard.
*
* @param SettingsRepository $settings Settings repository.
*/
public function __construct(
private readonly SettingsRepository $settings,
) {}
/**
* Hooked to `init` and `login_init`. Redirects unauthenticated visitors
* away from wp-login.php when the login page is hidden.
*
* The redirect is governed by the manager's expose_login flag (set via
* set_login_visibility) and only ever applies to production sites.
* Staging sites always use WordPress's native login page — expose_login
* has no bearing on staging, since set_login_visibility is never called
* during staging site creation. One-click login, logout and
* password-reset flows are always allowed through.
*
* @return void
*/
public function handle(): void {
$pagenow = $GLOBALS['pagenow'] ?? basename( $_SERVER['PHP_SELF'] ?? '' );
if ( 'wp-login.php' !== $pagenow ) {
return;
}
// Authenticated users keep full access to the login page.
if ( is_user_logged_in() ) {
return;
}
// Staging sites always use the native WordPress login page —
// Advanced Login (expose_login) only applies to production sites.
if ( $this->settings->isStaging() ) {
return;
}
// Respect the manager's expose_login flag.
if ( $this->settings->isLoginExposed() ) {
return;
}
// One-click login (handled by LoginInterceptor on the same hook).
if ( isset( $_GET['wpcc_login_token'] ) ) {
return;
}
// A just-logged-out request (WordPress lands on wp-login.php?loggedout=true)
// must never be bounced into the sign-in SSO entry — that silently
// re-authenticates the user from a still-live upstream session. Send
// them to the logout destination instead (LogoutRedirect normally
// handles this via the logout_redirect filter; this is the safety net
// for direct landings and un-provisioned sites).
if ( isset( $_GET['loggedout'] ) ) {
$logout_url = $this->settings->getLogoutRedirectUrl();
wp_redirect( esc_url_raw( '' !== $logout_url ? $logout_url : home_url() ) );
exit;
}
// Logout and password-reset flows must continue to work.
$action = isset( $_REQUEST['action'] )
? sanitize_key( wp_unslash( $_REQUEST['action'] ) )
: '';
if ( in_array( $action, self::ALLOWED_ACTIONS, true ) ) {
return;
}
$target = $this->settings->getLoginRedirectUrl();
if ( '' === $target ) {
return;
}
// External host, so wp_redirect (not wp_safe_redirect), matching the
// bootstrapper's redirect to the Portal. esc_url_raw() guards against a
// malformed or javascript:-scheme URL supplied by the manager.
wp_redirect( esc_url_raw( $target ) );
exit;
}
}