5 Commits
Author SHA1 Message Date
thatguygriff 61b00c2ed3 Add the changelog entry for the continue link
CI / Tests (PHP 8.1) (pull_request) Successful in 50s
CI / Coding Standards (pull_request) Successful in 3m0s
CI / No Debug Code (pull_request) Successful in 2s
CI / Tests (PHP 8.2) (pull_request) Successful in 52s
CI / PHPStan (pull_request) Successful in 3m0s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m53s
CI / Build Plugin Zip (pull_request) Skipped
2026-07-28 23:07:11 -03:00
thatguygriff 7eb2afc6a3 Name the destination page in the continue link
"Continue to your account" says nothing about where the link goes. Use
the chosen page's own title instead — "Continue to Book a Lesson" — so
the visitor knows before clicking.

An untitled page keeps the generic wording rather than rendering
"Continue to ".
2026-07-28 23:06:54 -03:00
thatguygriff 8a985f04d6 Link a signed-in visitor to the configured continue page
The registration page's already-logged-in branch returned a bare
sentence with nowhere to go, leaving the visitor to find their own way
to their account. The invited-student branch a few lines above already
built exactly the link that was missing.

Extract that into continueLink() and use it for both logged-in
outcomes. There is deliberately still no wp_login_url() fallback:
sending someone already signed in to the login screen is the same dead
end with extra steps, so with no page configured there is no link.

Both messages now carry the us-register-form wrapper and enqueue the
plugin stylesheet, which the invite branch emitted markup for but never
loaded.

Closes #131
2026-07-28 23:06:54 -03:00
thatguygriff da985c7f71 Merge pull request 'Add the changelog entry missed by #135' (#136) from docs/changelog-upcoming-lessons-layout into main
CI / Tests (PHP 8.1) (push) Successful in 51s
CI / Tests (PHP 8.3) (push) Successful in 2m46s
CI / Tests (PHP 8.2) (push) Successful in 44s
CI / No Debug Code (push) Successful in 2s
CI / Coding Standards (push) Successful in 2m54s
CI / PHPStan (push) Successful in 2m46s
CI / Build Plugin Zip (push) Successful in 2m50s
Reviewed-on: #136
2026-07-29 02:04:51 +00:00
thatguygriff 7c91e1eef7 Add the changelog entry missed by #135
CI / Tests (PHP 8.1) (pull_request) Successful in 45s
CI / PHPStan (pull_request) Successful in 2m50s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m45s
CI / Build Plugin Zip (pull_request) Skipped
CI / Tests (PHP 8.2) (pull_request) Successful in 52s
CI / No Debug Code (pull_request) Successful in 2s
CI / Coding Standards (pull_request) Successful in 2m52s
The upcoming-lessons layout fix shipped without one.
2026-07-28 23:04:29 -03:00
4 changed files with 98 additions and 13 deletions
+4
View File
@@ -13,6 +13,10 @@ each change under the current top section as you work.
## [1.2.4]
### Fixed
- A student's **upcoming lessons no longer pile on top of each other**. On the booking page, the lesson name, its date and time, the status badge and the **Cancel** button could render over one another instead of sitting in a tidy row — worst with a long lesson-type name, and on narrow screens, where the row had no phone layout at all. The panel now keeps its shape whatever the theme around it does, long names wrap instead of shoving the Cancel button out of the row, and on a phone the lesson details stack above the buttons.
- The registration page **no longer dead-ends a visitor who is already signed in**. It used to greet them with "You already have an account and are logged in." and nothing else, leaving them to find their own way to the studio. They now get a link onward to the page chosen under the block's **After registration** panel, and the link names it — "Continue to Book a Lesson" rather than the vaguer wording an invited student used to see. With no page chosen, the message appears on its own as before, because sending someone who is already signed in to the sign-in screen helps nobody.
## [1.2.3]
### Changed
+1 -1
View File
@@ -132,7 +132,7 @@ recorded in `us_policy_acceptances` with `registration_type = account` and
The block's **After registration** panel picks the page a student continues to once
registration finishes, and whether they get there by hand or automatically.
- **Sign-in page** (`loginPageId` / `login_page_id`) — the target of the "Sign in to your account" link shown after email confirmation (`?us_confirmed=1|ready`, falling back to the WordPress login screen) and of the "Continue to your account" link an invited student sees on the spot (`?us_registered=invite`; no link at all with no page chosen, since an already-signed-in student has no use for the login screen).
- **Sign-in page** (`loginPageId` / `login_page_id`) — the target of the "Sign in to your account" link shown after email confirmation (`?us_confirmed=1|ready`, falling back to the WordPress login screen) and of the **"Continue to _<page title>_"** link every **logged-in** visitor gets (`RegistrationPage::continueLink()`): an invited student who just finished signing up (`?us_registered=invite`), and anyone who simply arrives at the registration page already signed in. The link names the chosen page (via `get_the_title()`) so the visitor knows where it goes; an untitled page falls back to "Continue to your account" rather than reading "Continue to ". Neither gets the WordPress-login-screen fallback — with no page chosen there is no link at all, since sending someone already signed in to the login screen is the same dead end with extra steps.
- **Redirect automatically** (`autoRedirect`, block only) — sends the student to that page instead of showing the link, via `BlockRegistrar::maybeAutoRedirect()` on `template_redirect`. It fires only on those two finished states (`RegistrationPage::isRegistrationComplete()`), so the "check your email" step, a validation error, and an `expired` confirmation link are always shown rather than redirected past. With no page chosen nothing happens — there is deliberately no login-screen fallback for the redirect. See `editor-blocks.md`.
## Token Redirect
+43 -12
View File
@@ -65,24 +65,21 @@ class RegistrationPage {
$registered = sanitize_key( Val::string( wp_unslash( $_GET['us_registered'] ?? '' ) ) );
if ( is_user_logged_in() ) {
if ( self::RESULT_INVITE === $registered ) {
// An invited student is done the moment they land here logged in,
// so this is where their "continue" link belongs. The sign-in-page
// fallback is deliberately not used: pointing someone who is
// already signed in at the login screen helps nobody.
$continue = $this->continueUrl( $this->successPageId( $atts ) );
$link = null === $continue
? ''
: '<p><a href="' . esc_url( $continue ) . '">'
. esc_html__( 'Continue to your account', 'unsupervised-schedular' )
. '</a></p>';
// Both logged-in outcomes are dead ends without somewhere to go next,
// so both offer the same "continue" link to the configured page.
wp_enqueue_style( 'us-scheduler' );
$link = $this->continueLink( $atts );
if ( self::RESULT_INVITE === $registered ) {
// An invited student is done the moment they land here logged in.
return '<div class="us-register-form"><p class="us-success">'
. esc_html__( 'Your account has been created and you are now logged in.', 'unsupervised-schedular' )
. '</p>' . $link . '</div>';
}
return '<p>' . esc_html__( 'You already have an account and are logged in.', 'unsupervised-schedular' ) . '</p>';
return '<div class="us-register-form"><p>'
. esc_html__( 'You already have an account and are logged in.', 'unsupervised-schedular' )
. '</p>' . $link . '</div>';
}
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- token identifies the invite; the form submit is nonce-checked in maybeHandleSubmit.
@@ -353,6 +350,40 @@ class RegistrationPage {
return $this->continueUrl( $loginPageId ) ?? wp_login_url();
}
/**
* The "continue" paragraph shown to a logged-in visitor, or an empty string
* when no destination page is configured. The link names the chosen page, so
* the visitor knows where it goes before clicking; an untitled page falls
* back to generic wording rather than reading "Continue to ".
*
* The sign-in-page fallback {@see loginUrl()} applies is deliberately not
* used here: pointing someone who is already signed in at the login screen is
* the same dead end with extra steps, so no link is better than that one.
*
* @param array<int|string, mixed> $atts
*/
private function continueLink( array $atts ): string {
$pageId = $this->successPageId( $atts );
$continue = $this->continueUrl( $pageId );
if ( null === $continue ) {
return '';
}
$title = trim( Val::string( get_the_title( $pageId ) ) );
$label = '' === $title
? esc_html__( 'Continue to your account', 'unsupervised-schedular' )
: esc_html(
sprintf(
/* translators: %s: title of the page the student continues to. */
__( 'Continue to %s', 'unsupervised-schedular' ),
$title
)
);
return '<p><a href="' . esc_url( $continue ) . '">' . $label . '</a></p>';
}
/**
* The chosen post-registration page's URL, or null when none is configured
* (or it has since been deleted). Unlike {@see loginUrl()} this has no
+50
View File
@@ -497,11 +497,61 @@ class RegistrationPageTest extends TestCase
Functions\when('is_user_logged_in')->justReturn(true);
Functions\when('sanitize_key')->alias(static fn ($v) => strtolower((string) $v));
Functions\expect('get_permalink')->once()->with(4)->andReturn('http://home.test/welcome/');
Functions\when('get_the_title')->justReturn('Book a Lesson');
$html = $this->ctx['page']->render([ 'loginPageId' => 4 ]);
self::assertStringContainsString('now logged in', $html);
self::assertStringContainsString('href="http://home.test/welcome/"', $html);
// The link names its destination rather than saying "your account".
self::assertStringContainsString('Continue to Book a Lesson', $html);
}
public function testContinueLinkFallsBackToGenericWordingForAnUntitledPage(): void
{
Functions\when('is_user_logged_in')->justReturn(true);
Functions\when('sanitize_key')->alias(static fn ($v) => strtolower((string) $v));
Functions\when('get_permalink')->justReturn('http://home.test/welcome/');
Functions\when('get_the_title')->justReturn(' ');
// An untitled page must not produce a link reading "Continue to ".
$html = $this->ctx['page']->render([ 'loginPageId' => 4 ]);
self::assertStringContainsString('Continue to your account', $html);
self::assertStringContainsString('href="http://home.test/welcome/"', $html);
}
public function testAlreadyLoggedInVisitorIsLinkedToTheChosenPage(): void
{
// No us_registered flag: someone who simply happens to be signed in and
// lands on the registration page. They still need a way onward.
Functions\when('is_user_logged_in')->justReturn(true);
Functions\when('sanitize_key')->alias(static fn ($v) => strtolower((string) $v));
Functions\expect('get_permalink')->once()->with(4)->andReturn('http://home.test/welcome/');
Functions\when('get_the_title')->justReturn('Book a Lesson');
$html = $this->ctx['page']->render([ 'loginPageId' => 4 ]);
self::assertStringContainsString('already have an account', $html);
self::assertStringContainsString('href="http://home.test/welcome/"', $html);
self::assertStringContainsString('Continue to Book a Lesson', $html);
// Not the just-registered message — that branch needs its own flag.
self::assertStringNotContainsString('us-success', $html);
}
public function testAlreadyLoggedInVisitorGetsNoLinkWithoutAChosenPage(): void
{
Functions\when('is_user_logged_in')->justReturn(true);
Functions\when('sanitize_key')->alias(static fn ($v) => strtolower((string) $v));
Functions\when('get_permalink')->justReturn(false);
// A deleted page resolves to false, which must not become a broken link.
$html = $this->ctx['page']->render([ 'loginPageId' => 4 ]);
self::assertStringContainsString('already have an account', $html);
self::assertStringNotContainsString('<a href', $html);
self::assertStringNotContainsString('<a href', $this->ctx['page']->render([]));
}
public function testContinueUrlIsNullWithoutAResolvablePage(): void