1. Accepting an invite now keeps the student signed in
The registration form was processed inside render() (during the_content), so wp_set_auth_cookie() ran after headers were sent — the cookie never persisted and the new student was bounced back to the logged-out registration page. Submissions are now handled on template_redirect, before any output, via post/redirect/get (?us_registered=…), so the cookie sticks and the student lands logged in. Only invite signups can auto-login at submit time; group-link and self-approval signups still confirm their email first (the login gate blocks them until then), so those are unchanged.
2. Customizable "registration is by invitation only" message
New Invitation-only notice panel on the Student Registration block (attribute inviteOnlyMessage; shortcode invite_only_message). Blank keeps the default wording.
3. Account-registration questions save again
dbDelta does not reliably relax a column from NOT NULL to NULL, so sites created before account-scope questions kept us_questions.offering_id NOT NULL and rejected account inserts with "Column 'offering_id' cannot be null". A one-time, self-healing migration (QuestionRepository::ensureOfferingNullable()) re-applies the nullable definition. It is guarded by its own us_questions_offering_nullable option rather than the version gate, so it heals sites already on the current version, and only marks itself done once the ALTER succeeds.
Tests
composer test — 602 tests, 1742 assertions, all pass (added 6)
Three registration fixes reported from live use.
### 1. Accepting an invite now keeps the student signed in
The registration form was processed inside `render()` (during `the_content`), so `wp_set_auth_cookie()` ran **after** headers were sent — the cookie never persisted and the new student was bounced back to the logged-out registration page. Submissions are now handled on `template_redirect`, before any output, via post/redirect/get (`?us_registered=…`), so the cookie sticks and the student lands logged in. Only invite signups can auto-login at submit time; group-link and self-approval signups still confirm their email first (the login gate blocks them until then), so those are unchanged.
### 2. Customizable "registration is by invitation only" message
New **Invitation-only notice** panel on the Student Registration block (attribute `inviteOnlyMessage`; shortcode `invite_only_message`). Blank keeps the default wording.
### 3. Account-registration questions save again
`dbDelta` does not reliably relax a column from `NOT NULL` to `NULL`, so sites created before account-scope questions kept `us_questions.offering_id NOT NULL` and rejected account inserts with *"Column 'offering_id' cannot be null"*. A one-time, self-healing migration (`QuestionRepository::ensureOfferingNullable()`) re-applies the nullable definition. It is guarded by its own `us_questions_offering_nullable` option rather than the version gate, so it heals sites already on the current version, and only marks itself done once the `ALTER` succeeds.
### Tests
- `composer test` — 602 tests, 1742 assertions, all pass (added 6)
- `composer lint` (PHPStan level 10) — clean
- `composer cs` (PHPCS) — clean
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Three registration fixes reported from live use:
- Accepting an invite now keeps the student signed in. The form was
processed inside render() during the_content, so wp_set_auth_cookie()
ran after headers were sent and the cookie never persisted — the new
student was bounced back to the logged-out registration page. The
submission is now handled on template_redirect (before output) with a
post/redirect/get, so the cookie sticks and the student lands logged in.
- The "registration is by invitation only" message is now customisable via
a new block attribute (inviteOnlyMessage / shortcode invite_only_message),
falling back to the default wording when blank.
- Account-registration questions save again. dbDelta does not reliably
relax a column from NOT NULL to NULL, so sites created before account-
scope questions kept us_questions.offering_id NOT NULL and rejected
account inserts ("Column 'offering_id' cannot be null"). A one-time,
self-healing migration (guarded by its own option, not the version gate)
re-applies the nullable definition on next load.
composer test, composer lint, composer cs all pass.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Three registration fixes reported from live use.
1. Accepting an invite now keeps the student signed in
The registration form was processed inside
render()(duringthe_content), sowp_set_auth_cookie()ran after headers were sent — the cookie never persisted and the new student was bounced back to the logged-out registration page. Submissions are now handled ontemplate_redirect, before any output, via post/redirect/get (?us_registered=…), so the cookie sticks and the student lands logged in. Only invite signups can auto-login at submit time; group-link and self-approval signups still confirm their email first (the login gate blocks them until then), so those are unchanged.2. Customizable "registration is by invitation only" message
New Invitation-only notice panel on the Student Registration block (attribute
inviteOnlyMessage; shortcodeinvite_only_message). Blank keeps the default wording.3. Account-registration questions save again
dbDeltadoes not reliably relax a column fromNOT NULLtoNULL, so sites created before account-scope questions keptus_questions.offering_id NOT NULLand rejected account inserts with "Column 'offering_id' cannot be null". A one-time, self-healing migration (QuestionRepository::ensureOfferingNullable()) re-applies the nullable definition. It is guarded by its ownus_questions_offering_nullableoption rather than the version gate, so it heals sites already on the current version, and only marks itself done once theALTERsucceeds.Tests
composer test— 602 tests, 1742 assertions, all pass (added 6)composer lint(PHPStan level 10) — cleancomposer cs(PHPCS) — clean🤖 Generated with Claude Code
Three registration fixes reported from live use: - Accepting an invite now keeps the student signed in. The form was processed inside render() during the_content, so wp_set_auth_cookie() ran after headers were sent and the cookie never persisted — the new student was bounced back to the logged-out registration page. The submission is now handled on template_redirect (before output) with a post/redirect/get, so the cookie sticks and the student lands logged in. - The "registration is by invitation only" message is now customisable via a new block attribute (inviteOnlyMessage / shortcode invite_only_message), falling back to the default wording when blank. - Account-registration questions save again. dbDelta does not reliably relax a column from NOT NULL to NULL, so sites created before account- scope questions kept us_questions.offering_id NOT NULL and rejected account inserts ("Column 'offering_id' cannot be null"). A one-time, self-healing migration (guarded by its own option, not the version gate) re-applies the nullable definition on next load. composer test, composer lint, composer cs all pass. Co-Authored-By: Claude Opus 4.8 <[email protected]>