Ask the account holder the studio's questions when they are a student too
CI / Tests (PHP 8.2) (pull_request) Successful in 43s
CI / Tests (PHP 8.1) (pull_request) Successful in 52s
CI / No Debug Code (pull_request) Successful in 2s
CI / PHPStan (pull_request) Successful in 2m50s
CI / Coding Standards (pull_request) Successful in 3m19s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m47s
CI / Build Plugin Zip (pull_request) Skipped

Under "both" the questions were collected per student only, so someone
registering themselves alongside their children was never asked their own
instrument, level or anything else — despite being able to book lessons. The
account-scope questions describe a student, and under "both" the account
holder is one.

Their answers are recorded against their own user id, not shared with a
child's, and recorded after the children so a rollback that deletes the
account cannot leave answers pointing at a user that no longer exists. A
pure guardian is unchanged: they are not a student, so anything posted for
them is still ignored.

Validation became two passes rather than one so the message can say whose
answers are missing — with one pass, "both" had to blame "each student" for
the account holder's own blank field.

In the form, the two questions turn out to be independent: whether student
blocks are in play, and whether the account holder answers for themselves.
"Both" is the case that needs its own answer to each, so sync() now tracks
them separately, and step two comes back into play under "both".

Verified in a headless browser: 21 checks across all three choices, now
including that "both" enables the account holder's own question panel and
offers Next rather than the early submit.

Closes #146

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-07-29 23:15:47 -03:00
co-authored by Claude Opus 5
parent 4e5382e259
commit 69179b75c9
5 changed files with 168 additions and 33 deletions
+20 -14
View File
@@ -11,10 +11,10 @@
* validation.
* 2. **Who are you registering?** The student section is hidden until the
* choice is "on behalf of students" or "both", and "Add another student"
* clones the student block. Either of those choices also takes the account
* holder's *own* question panel out of play — the questions are then asked
* per student, so the server ignores those answers and the browser must not
* demand them.
* clones the student block. "On behalf of students" *alone* also takes the
* account holder's own question panel out of play — they are not a student
* in that case, so the server ignores those answers and the browser must not
* demand them. Under "both" they are a student and do answer them.
* 3. **Password strength.** The password is scored with zxcvbn (via WordPress's
* own `wp.passwordStrength`) and a weak one is refused. The server applies
* its own, coarser rule regardless — see `Auth\PasswordPolicy`.
@@ -220,15 +220,21 @@
/**
* Keep the form in step with the choice.
*
* Student blocks appear for "students" and "both". The account holder's
* own question panel is the mirror image: the studio's questions describe
* a student, so whenever students are being added they are asked per
* student instead, and the account holder's copy goes out of play.
* Disabling it rather than hiding it is what stops a `required` question
* the server will ignore from blocking submit.
* Two independent questions, which is why "both" needs its own answer to
* each:
*
* - Are student blocks in play? For "students" and "both".
* - Does the account holder answer the studio's questions themselves? For
* "self" and "both" — they are a student in those two, and the questions
* describe a student. A pure guardian answers them per student instead,
* so their own copy goes out of play; disabling it rather than hiding it
* is what stops a `required` question the server will ignore from
* blocking submit.
*/
function sync() {
var wantsStudents = mode() !== 'self';
var current = mode();
var wantsStudents = current !== 'self';
var asksSelf = current !== 'students';
children.hidden = !wantsStudents;
@@ -248,15 +254,15 @@
var fields = steps.step2.querySelectorAll('input, select, textarea');
for (var i = 0; i < fields.length; i++) {
fields[i].disabled = wantsStudents;
fields[i].disabled = !asksSelf;
}
// With the questions out of play there is no second step to advance to,
// so "Next" would be a dead end — swap it for the submit.
steps.next.hidden = wantsStudents;
steps.next.hidden = !asksSelf;
if (steps.earlySubmit) {
steps.earlySubmit.hidden = !wantsStudents;
steps.earlySubmit.hidden = asksSelf;
}
}