Skip to content

fix: length rules reject a valid length of 0 - #17

Open
shakurShirajul wants to merge 3 commits into
bit-apps-pro:mainfrom
shakurShirajul:fix/between-rule
Open

fix: length rules reject a valid length of 0#17
shakurShirajul wants to merge 3 commits into
bit-apps-pro:mainfrom
shakurShirajul:fix/between-rule

Conversation

@shakurShirajul

@shakurShirajul shakurShirajul commented Aug 6, 2026

Copy link
Copy Markdown

Summary

The min, max, and between rules rejected any value whose length is 0. An empty string, an empty array, and the numbers 0 / 0.0 all failed validation even when the configured bounds explicitly allowed a length of zero — min:0, max:5, and between:0,5 would each reject ''.

The cause is a truthiness check on a length value:

$length = $this->getValueLength($value);

if ($length) {          // 0 is falsy, so a valid length of 0 falls through
    return $length >= $min;
}

return false;           // ...and is reported as a failure

getValueLength() returns an integer length, or false when the value has no measurable length at all (bool, null, object). Because 0 and false are both falsy, the guard could not tell "this value is legitimately empty" from "this value cannot be measured", and collapsed both into a failure.

This PR distinguishes the two, and moves the distinction into the shared helper so it is made in exactly one place.

Behaviour change

Only values with a length of 0 are affected. Verified before/after:

Value min:0 max:5 between:0,5
'' falsetrue falsetrue falsetrue
[] falsetrue falsetrue falsetrue
0 falsetrue falsetrue falsetrue
0.0 falsetrue falsetrue falsetrue

Everything else is untouched. Non-zero bounds behave identically to before (min:3 still accepts 'abc' and rejects 'ab'), and values with no measurable length — true, null, new stdClass() — still fail, as they should.

Note this only changes whether an empty value passes a length rule. It does not make empty values pass validation overall: required is still the rule that rejects them, which is the correct separation of concerns. A field declared min:0 was always meant to accept an empty value.

Changes

Fix — added Helpers::lengthWithin() next to getValueLength() in the trait all three rules already use. It decodes the false sentinel once and applies the bounds, with null meaning "no bound on this side":

protected function lengthWithin($value, $min = null, $max = null): bool

MinRule, MaxRule, and BetweenRule now each delegate to it in a single line rather than repeating the same guard three times. The original fix applied the corrected check separately in all three classes; consolidating it means a future length-based rule cannot reintroduce the bug by writing if ($length) again, and there is one definition of what a measurable length is.

Tests — added coverage to MinTest, MaxTest, and BetweenTest for the three distinct cases the old code conflated:

  • normal boundary behaviour (lengths above/below/at the bound)
  • a length of 0 is accepted, for strings, arrays, and numbers
  • values with no measurable length (true, null, stdClass) are still rejected

The previously commented-out array assertion in MaxTest is now enabled.

Developer tooling — added composer test:watch (bin/test-watch), which re-runs the suite when a PHP file under src/ or tests/ changes. It delegates to the existing test:unit script so there is a single definition of the test command, and uses plain polling so it needs no extra dependencies. Added /bin export-ignore to .gitattributes so this dev-only script is not shipped in the distributed package, and documented the two commands briefly under Contributing.

Testing

composer test:unit36 tests, 123 assertions, all passing.

Before/after behaviour in the table above was verified by running both revisions of the rules directly against each value.

Compatibility

No API changes. lengthWithin() is a new protected trait method; getValueLength() keeps its existing signature and return contract, so any code extending Rule or using Helpers continues to work unchanged. PHP 7.2+ compatible, consistent with the package's existing constraint.

One caveat worth calling out for reviewers: if a project currently relies on min:0 or between:0,N to reject empty values, that behaviour was a bug and this PR ends it. Such a field should use required instead.

Copilot AI lite review requested due to automatic review settings August 6, 2026 06:28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes an edge case in WPValidator’s length-based rules where a valid computed length of 0 was treated as falsy and incorrectly rejected. The change ensures only “unmeasurable” values (where getValueLength() returns false) short-circuit validation, while a real length/value of 0 proceeds through comparisons.

Changes:

  • Update BetweenRule, MinRule, and MaxRule to guard on $length === false rather than truthiness.
  • Expand rule test coverage to include zero-length/value cases (0, 0.0, '', []) and explicitly unmeasurable cases (true, null, stdClass).
  • Add boundary-negative assertions in existing min/max/between tests to validate rejection beyond configured limits.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/Rules/MinRule.php Treat 0 as a valid measurable length/value; only false (unmeasurable) fails fast.
src/Rules/MaxRule.php Same fix as MinRule for max comparisons (accepts 0).
src/Rules/BetweenRule.php Same fix as Min/Max for range comparisons (accepts 0).
tests/Rules/MinTest.php Adds coverage for zero-length acceptance, unmeasurable rejection, and boundary negatives.
tests/Rules/MaxTest.php Adds coverage for zero-length acceptance, unmeasurable rejection, and boundary negatives.
tests/Rules/BetweenTest.php Adds coverage for zero-length acceptance, unmeasurable rejection, and boundary negatives.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…tor Between, Max, and Min rules to utilize new method; add test-watch script and update README
Copilot AI review requested due to automatic review settings August 6, 2026 10:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 11 changed files in this pull request and generated no new comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants