[2.x] fix(nicknames): cast min/max settings to int before passing to Schema\Str#4599
Merged
[2.x] fix(nicknames): cast min/max settings to int before passing to Schema\Str#4599
Conversation
…strings
UserResourceFields passes the raw settings value to Schema\Str::minLength(int)
and maxLength(int). Numeric strings ('3', '150') coerce silently under PHP's
default weak typing, but an empty string — the result of an admin clearing
the min or max field in the nicknames config and saving — triggers:
Str::maxLength(): Argument #1 ($length) must be of type int, string given
From then on every forum request 500s because UserResourceFields is
invoked during JSON:API resource resolution. Fresh installs are unaffected
because the Extend\Settings() int defaults bypass the DB path.
Test reproduces the exact production stack trace. Fix follows.
dbff6a0 to
42362b6
Compare
Cast the persisted setting to int before handing it to Schema\Str's minLength/maxLength, and only apply the constraint when the admin has configured a positive value. An empty field saved from the admin panel was otherwise stored as '' — triggering a TypeError in PHP's default weak coercion — and, after the naive cast, coerced to 0, which made maxLength(0) reject every nickname. Reveals a gap in Schema\Str: the int-only signature offers no way to "disable" a length constraint via the condition argument without a guard at the call site. Keeping the guard local for this RC fix.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the TypeError reported against 2.x nightly:
Root cause
UserResourceFieldspassed the raw result of$this->settings->get('flarum-nicknames.min' / '.max')toSchema\Str::minLength(int)/maxLength(int). Settings are always returned as strings fromDatabaseSettingsRepository::get().Two separate failure modes on top of that:
'3'→3), but an empty''triggers aTypeError. That's the production symptom — the admin cleared the min or max field and saved the nicknames config form.(int) ''is0, sominLength(0)/maxLength(0)are applied unconditionally.maxLength(0)rejects every nickname with"must not be greater than 0 characters". A cast alone is worse than the TypeError — it turns a hard error into a confusing validation failure.Fresh installs haven't been affected because the
Extend\Settings()->default('…', 1 | 150)defaults only kick in when the key isn't in the DB. As soon as an admin saves the nicknames config, values are persisted as strings and the code path breaks.Fix
Cast the settings to int and gate the constraint on a positive value:
An empty or zero setting now means "no length constraint" — which is the intuitive behaviour for a cleared admin field.
Verifying the repro
Local integration test
request_succeeds_when_min_or_max_setting_is_empty_string:''for both settings via$this->setting(...).PATCH /api/users/2with a valid nickname.Tangential observation (not fixed here)
Schema\Str::minLength(int $length)gives no clean way to express "no constraint" without a guard at the call site. That's a framework-level ergonomic gap — arguablyminLengthshould no-op when$length <= 0, or accept a nullable. Keeping the local guard for this RC; happy to open a follow-up if there's appetite.Necessity
Confirmed
Required changes