Studio admins can define account-registration questions that every new student answers as a required second step during signup (after name/password), and each student's answers appear under a new Registration Information section in the admin.
Approach
Extends the existing Registration domain rather than building a parallel system — the answer side was already polymorphic and account-aware.
Schema (Schema.php): us_questions.offering_id is now nullable and a new scope column (offering | account) distinguishes the two. Account answers reuse us_question_answers with the new Answer::REG_ACCOUNT type (registration_id = user ID). Plugin version bumped 1.0.0 → 1.1.0 so dbDelta runs the migration.
Authoring: reuses Offerings → Questions with an "Account signup (all registrations)" scope, visible to studio admins only.
Signup step 2: RegistrationPage + register-page.php + new assets/js/register.js split the form into two panels behind a "Next" button (progressive enhancement — works without JS). Required answers are validated before the user is created; applies to all paths (invite, group link, self-approval).
Admin review: StudentHistory::registrationInfo() lists each account question with the student's answer ("—" when unanswered); account answers are excluded from the existing "Intake answers" table to avoid duplication.
REST stays offering-scope only (account questions are managed through the server-rendered admin page).
Notes
Field types reuse the existing set (text / paragraph / dropdown / checkbox) with a per-question required toggle.
A question added after a student registered shows "—" for that student (they are not re-prompted).
Tests
composer test — 421 tests, 1246 assertions, all passing
composer lint — PHPStan level 10, no errors
composer cs — PHPCS clean
no-debug check — clean
Closes #90
## What this does
Studio admins can define **account-registration questions** that every new student answers as a required **second step** during signup (after name/password), and each student's answers appear under a new **Registration Information** section in the admin.
## Approach
Extends the existing `Registration` domain rather than building a parallel system — the answer side was already polymorphic and `account`-aware.
- **Schema** (`Schema.php`): `us_questions.offering_id` is now nullable and a new `scope` column (`offering` | `account`) distinguishes the two. Account answers reuse `us_question_answers` with the new `Answer::REG_ACCOUNT` type (`registration_id` = user ID). **Plugin version bumped 1.0.0 → 1.1.0** so `dbDelta` runs the migration.
- **Authoring**: reuses **Offerings → Questions** with an "Account signup (all registrations)" scope, visible to studio admins only.
- **Signup step 2**: `RegistrationPage` + `register-page.php` + new `assets/js/register.js` split the form into two panels behind a "Next" button (progressive enhancement — works without JS). Required answers are validated **before** the user is created; applies to all paths (invite, group link, self-approval).
- **Admin review**: `StudentHistory::registrationInfo()` lists each account question with the student's answer ("—" when unanswered); account answers are excluded from the existing "Intake answers" table to avoid duplication.
- REST stays offering-scope only (account questions are managed through the server-rendered admin page).
## Notes
- Field types reuse the existing set (text / paragraph / dropdown / checkbox) with a per-question required toggle.
- A question added after a student registered shows "—" for that student (they are not re-prompted).
## Tests
- `composer test` — 421 tests, 1246 assertions, all passing
- `composer lint` — PHPStan level 10, no errors
- `composer cs` — PHPCS clean
- no-debug check — clean
Studio admins can now define registration questions that every new student
answers as a required second step during signup, with each student's answers
shown under a "Registration Information" section in the admin.
Extends the existing Registration domain: us_questions gains a scope column
(offering | account) and a nullable offering_id, and account answers reuse
us_question_answers with registration_type = 'account'. Authoring reuses the
Offerings -> Questions page via an "Account signup" scope (studio-admin only).
The registration form becomes two steps (progressive enhancement via
assets/js/register.js; works without JS); required answers are validated before
the account is created and apply to all signup paths (invite, group link,
self-approval). StudentHistory::registrationInfo() powers the admin section.
Bumps the plugin version to 1.1.0 so dbDelta runs the schema migration.
Closes#90
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.
Closes #90
What this does
Studio admins can define account-registration questions that every new student answers as a required second step during signup (after name/password), and each student's answers appear under a new Registration Information section in the admin.
Approach
Extends the existing
Registrationdomain rather than building a parallel system — the answer side was already polymorphic andaccount-aware.Schema.php):us_questions.offering_idis now nullable and a newscopecolumn (offering|account) distinguishes the two. Account answers reuseus_question_answerswith the newAnswer::REG_ACCOUNTtype (registration_id= user ID). Plugin version bumped 1.0.0 → 1.1.0 sodbDeltaruns the migration.RegistrationPage+register-page.php+ newassets/js/register.jssplit the form into two panels behind a "Next" button (progressive enhancement — works without JS). Required answers are validated before the user is created; applies to all paths (invite, group link, self-approval).StudentHistory::registrationInfo()lists each account question with the student's answer ("—" when unanswered); account answers are excluded from the existing "Intake answers" table to avoid duplication.Notes
Tests
composer test— 421 tests, 1246 assertions, all passingcomposer lint— PHPStan level 10, no errorscomposer cs— PHPCS clean