API / Minn\Login / LoginController

LoginController final readonly class

Minn\Login\LoginController · public/minn/src/Minn/Login/LoginController.php · 501 lines

Signing in. The page people see is /minn-admin/login: the form, the lost-password and reset flows, and logout all live there and link there. /wp-login.php stays as the address tooling knows (one-time login links, uptime probes, scripted sign-ins) and answers in place with the same shapes; a bare GET of it sends a browser to the clean page. Sessions and cookies validate on the engine AND on WordPress either way.

Used by 1

Constants and properties

privateDAY = 86400
constPATH = '/minn-admin/login'
privateSEGMENTS = array ( 'lost-password' => 'lostpassword', 'reset' => 'rp', 'logout' => 'logout', 'register' => 'register', 'confirm-email' => 'confirm_admin_email', )

Clean path segment => the action wp-login.php spells with ?action=.

privatereadonly Minn\Content\Site $site

Promoted from the constructor.

privatereadonly Minn\Front\Permalinks $permalinks

Promoted from the constructor.

privatereadonly Minn\Auth\Authenticator $authenticator

Promoted from the constructor.

privatereadonly Minn\Auth\SignIn $signIn

Promoted from the constructor.

privatereadonly Minn\Content\Users $users

Promoted from the constructor.

privatereadonly Minn\Auth\PasswordReset $reset

Promoted from the constructor.

Public

new__construct(Minn\Content\Site $site, Minn\Front\Permalinks $permalinks, Minn\Auth\Authenticator $authenticator, Minn\Auth\SignIn $signIn, Minn\Content\Users $users, Minn\Auth\PasswordReset $reset)#
methodform(Minn\Http\Request $request): Minn\Http\ResponseGET /minn-admin/loginGET /minn-admin/login/{segment:lost-password|reset|logout|register|confirm-email}GET /wp-login.php (public)#

The sign-in, lost-password, reset, and logout pages.

methodsignIn(Minn\Http\Request $request): Minn\Http\ResponsePOST /minn-admin/loginPOST /minn-admin/login/{segment:lost-password|reset|logout|confirm-email}POST /wp-login.php (public)#

Handles the posted form for each of those pages.

Internals 22

Private and protected methods: how the class does its work. Not a contract; they change whenever the code is tidied.

privatelandingFor(Minn\Http\Request $request, Minn\Content\UserRecord|WP_Error|null $user): string#

Where a sign-in from this page lands, through login_redirect: the address asked for, or the admin, with who the sign-in found.

privateasked(Minn\Http\Request $request): array#

The address a sign-in from this page asks for, and where it lands without one (the admin). @return array{0: string, 1: string}

@return array{0: string, 1: string}
privatecheckEmail(Minn\Http\Request $request): Minn\Login\LoginNotices#

The check-your-email page's word, as the reference's: the confirmation link is on its way, or the registration is done.

privatesignInNotices(Minn\Http\Request $request, Minn\Login\LoginNotices $notices): Minn\Login\LoginNotices#

A sign-in page's notices after wp_login_errors, handed where a sign-in would land (the admin, unless the page names a landing).

privatelostPassword(Minn\Http\Request $request): ?Minn\Http\Response#

POST lostpassword mints a key and mails the link; POST resetpass saves the new password. Null for other actions.

privateretrieve(Minn\Http\Request $request, string $login, string $siteName): Minn\Http\Response#

A reset asked for with plugins loaded, as the reference asks for it (retrieve_password, its hooks and mail): the page again with the refusal in its words, or on to "check your email". An unknown account still counts against the address's attempts.

privateopenResetLink(Minn\Http\Request $request): Minn\Http\Response#

The link from the email: the key moves into a cookie scoped to wp-login.php and the browser lands on the form without the key in its address bar, as on the reference.

privateresetSession(Minn\Http\Request $request): array#

The user and key from the reset cookie, when the key is still good. @return array{0: ?array, 1: string}

@return array{0: ?array, 1: string}
privatesavePassword(Minn\Http\Request $request): Minn\Http\Response#
privateregister(Minn\Http\Request $request, string $siteName): Minn\Http\Response#

Registration, when the site allows it (else off to the sign-in page saying so): the form (its landing as registration_redirect says), or a POST through register_new_user, landing where the form said (else on the sign-in page, to check the email), or back on the form with every refusal in its words.

privatevalidateReset(Minn\Content\UserRecord $user, string $mismatch): Minn\Login\LoginNotices#

A new password judged as the reference judges it: the mismatch, then whatever validate_password_reset adds.

privateparts(string $action, string $title, string $siteName, ?Minn\Content\UserRecord $user = NULL, ?Minn\Login\LoginNotices $notices = NULL): array#

What plugins put on one of the sign-in pages (LoginHooks::page()), for a page titled $title, with its notices printed; without plugins, the notices alone. @return array<string, string>

@return array<string, string>
privatetokenLogin(Minn\Http\Request $request): Minn\Http\Response#

The one-time login link `wp user login` prints (the captaincore helper's contract): the token in user meta must match, be under fifteen minutes old, and is spent on use. Any failure reads the same so ids cannot be probed.

privateadminEmail(Minn\Http\Request $request, string $siteName): Minn\Http\Response#

The administration email check (action confirm_admin_email): the screen, or on to where the sign-in was going once the address is confirmed or the reminder put off; someone who may not answer it is sent to sign in.

privatesafeRedirect(string $target): string#

Only this site's own URLs are sign-in destinations: a path, or an absolute URL on the home host. Anything else lands in the admin.

privatelogout(Minn\Http\Request $request): Minn\Http\Response#

Logging out ends the server-side session as well as the cookies, and needs the session's own nonce so a stray link cannot do it; without the nonce the reader is asked first.

privateaction(Minn\Http\Request $request): string#

The action asked for: a clean path segment (/minn-admin/login/reset) or wp-login.php's ?action=. The reset flow's two halves share the "reset" segment; a POST there saves the password.

privateactionUrl(Minn\Http\Request $request, string $action, string $query = ''): string#

An action's address on the page this request came in on: a path under the clean page, a query on wp-login.php.

privatesiteName(): string#

The site's name, as the sign-in pages head themselves ("Site" when it has none).

privatebase(Minn\Http\Request $request): string#

The sign-in page this request arrived at: the clean page, or wp-login.php for the tooling that still names it.

privatetooManyAttempts(Minn\Http\Request $request, int $wait): Minn\Http\Response#

A guessed-at address waits out the window; the page says so and the status lets tooling see it.

privaterender(Minn\Http\Request $request, Minn\Login\LoginNotices $notices, string $redirect): string#

The sign-in page, its notices through wp_login_errors first.