Collect a birth year instead of a full date of birth #153

Merged
thatguygriff merged 1 commits from feature/147-birth-year into main 2026-07-29 23:53:38 +00:00
Owner

Closes #147.

Signup and the profile page now ask for a birth year instead of a full date of birth: a four-digit year between 1900 and the current year, as a type="number" input capped at today. Anything else — a short year, a full date pasted in, a year in the future — is discarded rather than stored, so a typo cannot leave a nonsense age on the record.

Storage, and the two open questions from the issue

New meta key, not a reused one. The year lives in us_birth_year. Reusing us_date_of_birth would have left one key holding two formats with no way to tell them apart.

No bulk migration. GuardianService handles the old key in two halves instead:

  • birthYear() falls back to the year of the old date when us_birth_year is absent, so a student added before this change still shows a birth year with no migration step.
  • setBirthYear() deletes us_date_of_birth on every save.

That deletion is load-bearing, not housekeeping. Without it, clearing the birth year on a student who predates the change would leave the old date behind for the fallback to read straight back — the year could never be cleared. There's a test pinning exactly that (testSavingAChildClearsTheLegacyDateOfBirth).

The consequence worth your explicit sign-off: this means a student's stored full date of birth is deleted the first time their record is saved. That's the intended direction — the studio stops holding data it no longer asks for — but it is data going away, so I'd rather flag it than have you find it. Nothing runs in bulk: dates for students nobody edits stay until someone does. If you want them all gone now, that's a one-line meta delete and I can add it to the installer's migration step; say the word.

Also renamed, since the meaning changed

child_dobchild_birth_year, children[<n>][dob]children[<n>][birth_year], and the matching element ids and the us-family-child-dob CSS class. These are our own form fields posted by our own templates — not a saved contract like a block name — and leaving them called "dob" while they carry a year is the kind of thing that misleads someone six months from now. register.js's clone logic is index-generic and needed no change.

Verification

composer test (770 tests, up from 762), composer lint, composer cs all pass. New coverage: a data provider over six rejected inputs (not-a-year, 2015-04-02, 15, 20155, 1899, and a future year), the legacy-date read fallback, and the clear-on-save behaviour above.

No Schema.php change — this is user meta — so no USC_VERSION bump, per the rule in CLAUDE.md.

Closes #147. Signup and the profile page now ask for a **birth year** instead of a full date of birth: a four-digit year between 1900 and the current year, as a `type="number"` input capped at today. Anything else — a short year, a full date pasted in, a year in the future — is discarded rather than stored, so a typo cannot leave a nonsense age on the record. ## Storage, and the two open questions from the issue **New meta key, not a reused one.** The year lives in `us_birth_year`. Reusing `us_date_of_birth` would have left one key holding two formats with no way to tell them apart. **No bulk migration.** `GuardianService` handles the old key in two halves instead: - `birthYear()` falls back to the *year of* the old date when `us_birth_year` is absent, so a student added before this change still shows a birth year with no migration step. - `setBirthYear()` deletes `us_date_of_birth` on every save. That deletion is load-bearing, not housekeeping. Without it, clearing the birth year on a student who predates the change would leave the old date behind for the fallback to read straight back — the year could never be cleared. There's a test pinning exactly that (`testSavingAChildClearsTheLegacyDateOfBirth`). **The consequence worth your explicit sign-off:** this means a student's stored full date of birth is deleted the first time their record is saved. That's the intended direction — the studio stops holding data it no longer asks for — but it is data going away, so I'd rather flag it than have you find it. Nothing runs in bulk: dates for students nobody edits stay until someone does. If you want them all gone now, that's a one-line meta delete and I can add it to the installer's migration step; say the word. ## Also renamed, since the meaning changed `child_dob` → `child_birth_year`, `children[<n>][dob]` → `children[<n>][birth_year]`, and the matching element ids and the `us-family-child-dob` CSS class. These are our own form fields posted by our own templates — not a saved contract like a block name — and leaving them called "dob" while they carry a year is the kind of thing that misleads someone six months from now. `register.js`'s clone logic is index-generic and needed no change. ## Verification `composer test` (770 tests, up from 762), `composer lint`, `composer cs` all pass. New coverage: a data provider over six rejected inputs (`not-a-year`, `2015-04-02`, `15`, `20155`, `1899`, and a future year), the legacy-date read fallback, and the clear-on-save behaviour above. No `Schema.php` change — this is user meta — so no `USC_VERSION` bump, per the rule in CLAUDE.md.
thatguygriff added 1 commit 2026-07-29 23:49:02 +00:00
Collect a birth year instead of a full date of birth
CI / Tests (PHP 8.1) (pull_request) Successful in 43s
CI / No Debug Code (pull_request) Successful in 2s
CI / Tests (PHP 8.2) (pull_request) Successful in 50s
CI / PHPStan (pull_request) Successful in 2m55s
CI / Coding Standards (pull_request) Successful in 3m0s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m40s
CI / Build Plugin Zip (pull_request) Skipped
7e2bba79fe
Signup and the profile page now ask for a four-digit year between 1900 and
the current year. Anything else — a short year, a full date, a year in the
future — is discarded rather than stored, so a typo cannot leave a nonsense
age on the record.

The year lives in a new us_birth_year user meta rather than reusing
us_date_of_birth, which would have left one key holding two formats. The old
key is not migrated in bulk. Instead GuardianService handles it in two
halves: birthYear() falls back to the year of the old date when the new key
is absent, so a student added before this change still shows one, and
setBirthYear() deletes the old date on every save.

That deletion is what makes the fallback safe rather than merely tidy.
Without it, clearing the birth year on a student who predates the change
would leave the old date behind for the fallback to read straight back, and
the year could never be cleared at all.

Stored in user meta, so no Schema.php change and no USC_VERSION bump.

Closes #147

Co-Authored-By: Claude Opus 5 <[email protected]>
thatguygriff merged commit 2878beb221 into main 2026-07-29 23:53:38 +00:00
thatguygriff deleted branch feature/147-birth-year 2026-07-29 23:53:38 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Unsupervised/unsupervised-scheduler#153