Skip to content

feat(attribute): Add InputCheckbox class for HTML <input type="checkbox"> element with attributes and rendering capabilities.#31

Merged
terabytesoftw merged 23 commits intomainfrom
feature_12
Feb 9, 2026
Merged

feat(attribute): Add InputCheckbox class for HTML <input type="checkbox"> element with attributes and rendering capabilities.#31
terabytesoftw merged 23 commits intomainfrom
feature_12

Conversation

@terabytesoftw
Copy link
Contributor

Pull Request

Q A
Is bugfix?
New feature? ✔️
Breaks BC?

terabytesoftw and others added 2 commits February 7, 2026 15:41
@coderabbitai
Copy link

coderabbitai bot commented Feb 7, 2026

Important

Review skipped

This PR was authored by the user configured for CodeRabbit reviews. By default, CodeRabbit skips reviewing PRs authored by this user. It's recommended to use a dedicated user account to post CodeRabbit review feedback.

To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)
📝 Walkthrough

Walkthrough

Adds a new InputCheckbox component with label-enclosure support, two label-related traits, extensive unit tests and a test data provider, and updates CHANGELOG entries for 0.4.0.

Changes

Cohort / File(s) Summary
InputCheckbox Core Component
src/Form/InputCheckbox.php
New final InputCheckbox class: checkbox rendering, immutable setters (checked, uncheckedValue), boolean/value normalization, conditional hidden input emission when uncheckedValue is set, label wiring/envelope handling, getAttributes, loadDefault, and run implementations.
Label Management Traits
src/Form/Mixin/CanBeEnclosedByLabel.php, src/Form/Mixin/HasLabel.php
Two new traits: CanBeEnclosedByLabel (adds enclosedByLabel flag + immutable mutator) and HasLabel (label content, attributes, class management, labelFor, notLabel, immutable-style setters).
Tests & Test Provider
tests/Form/InputCheckboxTest.php, tests/Provider/Form/CheckedProvider.php
Adds comprehensive InputCheckbox test suite exercising rendering, attributes, ARIA/data/global attributes, label/enclosure modes, immutability, theme/provider interactions, ID/translation cases; adds CheckedProvider supplying many checked-state scenarios.
Changelog
CHANGELOG.md
Updates 0.4.0 "Under development" section: removes previous Enh #16 and adds enhancement entries #17#34.

Sequence Diagram

sequenceDiagram
    participant Client
    participant InputCheckbox
    participant BaseInput
    participant InputHidden
    participant Label
    participant HtmlRenderer

    Client->>InputCheckbox: instantiate & configure (checked, uncheckedValue, label, enclosedByLabel, ...)
    InputCheckbox->>BaseInput: load defaults / inherit behavior
    Client->>InputCheckbox: render() / run()
    InputCheckbox->>HtmlRenderer: build main <input type="checkbox"> (getAttributes)
    HtmlRenderer-->>InputCheckbox: checkbox HTML
    alt uncheckedValue is set
        InputCheckbox->>InputHidden: create hidden input with same name & uncheckedValue
        InputHidden->>HtmlRenderer: render hidden input
        HtmlRenderer-->>InputCheckbox: hidden input HTML
    end
    alt label rendering enabled
        InputCheckbox->>Label: build label (envelope or separate, set for/id)
        Label->>HtmlRenderer: render label HTML
        HtmlRenderer-->>InputCheckbox: label HTML
    end
    InputCheckbox-->>Client: return composed HTML (label + checkbox + hidden as applicable)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I nibble code and hop with glee,
A checkbox popped, snug as can be,
A hidden friend beneath the name,
Labels curl and link the same,
Hooray — this rabbit ships with glee. 🐰

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.52% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main addition: a new InputCheckbox class for HTML checkbox input elements with attributes and rendering capabilities.
Description check ✅ Passed The description is related to the changeset, indicating this is a new feature that adds the InputCheckbox class without breaking backward compatibility.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Feb 7, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (d587d38) to head (e421dd8).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@             Coverage Diff              @@
##                main       #31    +/-   ##
============================================
  Coverage     100.00%   100.00%            
- Complexity       104       135    +31     
============================================
  Files             67        70     +3     
  Lines            215       315   +100     
============================================
+ Hits             215       315   +100     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@coderabbitai coderabbitai bot added the enhancement New feature or request label Feb 7, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Fix all issues with AI agents
In `@src/Form/InputCheckbox.php`:
- Around line 19-20: The PHPDoc for InputCheckbox.php incorrectly describes
checkbox behavior as "mutually exclusive" (which is for radio buttons); update
the docblock for the InputCheckbox class (or the file-level doc) to state that
checkboxes allow independent selection of one or more options from a set
(non‑exclusive), and adjust the descriptive sentence to mention
independent/optional selection rather than mutual exclusivity so the PHPDoc for
InputCheckbox accurately reflects checkbox semantics.
- Line 96: Update the PHPDoc to say checkboxes allow independent multiple
selections (not "mutually exclusive" which applies to radio buttons) in class
InputCheckbox, and stop mutating the instance property $template inside run();
instead create a local $template variable (or copy $this->template to a local
variable), modify that local value and pass it into buildElement()/render logic,
or restore $this->template immediately after buildElement() returns so repeated
renders don't persist the change; reference InputCheckbox::run(),
InputCheckbox::buildElement(), and the $template property when making this
change.

In `@src/Form/Mixin/HasLabel.php`:
- Line 111: The default parameter behavior of
HasLabel::labelClass(string|Stringable|UnitEnum|null $value, bool $override =
false) isn't covered: add a unit test that calls labelClass() twice on the same
instance without passing $override (relying on the default false) and assert
that the resulting class string contains/merges both values rather than the
second replacing the first; use the HasLabel trait (or the concrete class that
uses it) and verify the internal classes/state or the output from the method
that renders label classes to ensure they are combined when $override is
omitted.
- Line 195: The conditional in HasLabel.php uses the verbose negation
"isset($attributes['for']) === false"; change it to the consistent and concise
form "!isset($attributes['for'])" to match the style used in InputCheckbox.php
(see the similar check against $labelAttributes in that class) so the if
statement reads the same negation style across the codebase.

In `@tests/Form/InputCheckboxTest.php`:
- Around line 345-360: Add a test that covers the enclosedByLabel path when no
id is provided so the label's for attribute is omitted: create a new test method
(e.g., testRenderWithEnclosedByLabelWithoutId) that calls
InputCheckbox::tag()->enclosedByLabel(true)->label('Label')->render() (do not
call ->id()), and assert the rendered HTML contains a <label> without a for="…"
attribute and an <input> without an id; this exercises the run() logic that only
sets label for when $this->attributes['id'] exists.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4af7f9d and aba0f06.

📒 Files selected for processing (5)
  • CHANGELOG.md
  • src/Form/InputCheckbox.php
  • src/Form/Mixin/CanBeEnclosedByLabel.php
  • src/Form/Mixin/HasLabel.php
  • tests/Form/InputCheckboxTest.php
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2026-02-06T21:37:44.509Z
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 24
File: tests/Form/InputTextTest.php:33-620
Timestamp: 2026-02-06T21:37:44.509Z
Learning: In the ui-awesome/html repository, prefer individual test methods over PHPUnit data providers in test classes. This helps maintainers see exactly how each test behaves without cross-referencing data providers. Apply to all PHP test files under tests. Use separate, descriptively named test methods to cover different inputs/edge cases; retain data providers only if they clearly improve readability or reduce duplication.

Applied to files:

  • tests/Form/InputCheckboxTest.php
🧬 Code graph analysis (3)
tests/Form/InputCheckboxTest.php (6)
src/Root/Html.php (1)
  • Html (27-40)
src/Form/InputCheckbox.php (1)
  • InputCheckbox (36-103)
tests/Support/Stub/DefaultProvider.php (1)
  • DefaultProvider (17-34)
tests/Support/Stub/DefaultThemeProvider.php (1)
  • DefaultThemeProvider (17-39)
src/Form/Mixin/HasLabel.php (6)
  • label (57-63)
  • labelClass (111-122)
  • labelFor (136-142)
  • labelAttributes (79-85)
  • notLabel (174-180)
  • labelTag (156-162)
src/Form/Mixin/CanBeEnclosedByLabel.php (1)
  • enclosedByLabel (32-38)
src/Form/InputCheckbox.php (2)
src/Form/Mixin/CanBeEnclosedByLabel.php (1)
  • enclosedByLabel (32-38)
src/Form/Mixin/HasLabel.php (4)
  • label (57-63)
  • labelAttributes (79-85)
  • labelTag (156-162)
  • renderLabelTag (187-200)
src/Form/Mixin/HasLabel.php (1)
src/Root/Html.php (1)
  • Html (27-40)
🪛 GitHub Check: mutation / PHP 8.5-ubuntu-latest
src/Form/Mixin/HasLabel.php

[warning] 187-187:
Escaped Mutant for Mutator "ProtectedVisibility":

@@ @@
*
* @return string The rendered label tag.
*/

  • protected function renderLabelTag(): string
  • private function renderLabelTag(): string
    {
    if ($this->notLabel || $this->label === '') {
    return '';

[warning] 111-111:
Escaped Mutant for Mutator "FalseValue":

@@ @@
*
* @return static New instance with the updated labelAttributes['class'] value.
*/

  • public function labelClass(string|Stringable|UnitEnum|null $value, bool $override = false): static
  • public function labelClass(string|Stringable|UnitEnum|null $value, bool $override = true): static
    {
    $new = clone $this;
🪛 PHPMD (2.15.0)
tests/Form/InputCheckboxTest.php

[warning] 35-808: The class InputCheckboxTest has 53 public methods and attributes. Consider reducing the number of public items to less than 45. (undefined)

(ExcessivePublicCount)


[warning] 35-808: The class InputCheckboxTest has 53 non-getter- and setter-methods. Consider refactoring InputCheckboxTest to keep number of methods under 25. (undefined)

(TooManyMethods)


[warning] 35-808: The class InputCheckboxTest has 53 public methods. Consider refactoring InputCheckboxTest to keep number of public methods under 10. (undefined)

(TooManyPublicMethods)


[warning] 35-808: The class InputCheckboxTest has an overall complexity of 53 which is very high. The configured complexity threshold is 50. (undefined)

(ExcessiveClassComplexity)


[error] 35-808: The class InputCheckboxTest has a coupling between objects value of 13. Consider to reduce the number of dependencies under 13. (undefined)

(CouplingBetweenObjects)


[error] 409-409: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithGlobalDefaultsAreApplied'. (undefined)

(StaticAccess)


[error] 417-417: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithGlobalDefaultsAreApplied'. (undefined)

(StaticAccess)


[error] 709-709: Avoid using static access to class '\UIAwesome\Html\Form\InputCheckbox' in method 'testRenderWithToString'. (undefined)

(StaticAccess)


[error] 744-744: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithUserOverridesGlobalDefaults'. (undefined)

(StaticAccess)


[error] 751-751: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithUserOverridesGlobalDefaults'. (undefined)

(StaticAccess)


[error] 770-770: Avoid using static access to class '\UIAwesome\Html\Form\InputCheckbox' in method 'testReturnNewInstanceWhenSettingAttribute'. (undefined)

(StaticAccess)

src/Form/InputCheckbox.php

[error] 84-84: Avoid using static access to class '\UIAwesome\Html\Core\Html' in method 'run'. (undefined)

(StaticAccess)


[error] 94-94: Avoid using static access to class '\UIAwesome\Html\Core\Html' in method 'run'. (undefined)

(StaticAccess)

src/Form/Mixin/HasLabel.php

[error] 111-111: The method labelClass has a boolean flag argument $override, which is a certain sign of a Single Responsibility Principle violation. (undefined)

(BooleanArgumentFlag)


[error] 117-119: The method labelClass uses an else expression. Else clauses are basically not necessary and you can simplify the code by not using them. (undefined)

(ElseExpression)


[error] 118-118: Avoid using static access to class '\UIAwesome\Html\Helper\CSSClass' in method 'labelClass'. (undefined)

(StaticAccess)


[error] 199-199: Avoid using static access to class '\UIAwesome\Html\Core\Html' in method 'renderLabelTag'. (undefined)

(StaticAccess)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: phpunit / PHP 8.2-windows-2022
  • GitHub Check: phpunit / PHP 8.3-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.2-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.1-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.4-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.5-ubuntu-latest
  • GitHub Check: linter / Super Linter
  • GitHub Check: linter / Super Linter
🔇 Additional comments (6)
CHANGELOG.md (1)

19-19: LGTM!

The changelog entry follows the established pattern and correctly references the enhancement issue.

src/Form/Mixin/CanBeEnclosedByLabel.php (1)

13-38: LGTM!

Clean immutable trait following the established clone-and-return pattern used throughout the codebase.

src/Form/InputCheckbox.php (1)

64-70: LGTM!

The loadDefault() method cleanly merges checkbox-specific defaults with the parent configuration using the + operator, which correctly gives precedence to the child's values.

src/Form/Mixin/HasLabel.php (1)

21-43: LGTM!

The trait properties and their defaults are well-defined. Using Inline::LABEL as the default for $labelTag is a sensible choice.

tests/Form/InputCheckboxTest.php (2)

407-418: Good: global defaults are properly cleaned up after each test.

The SimpleFactory::setDefaults(..., []) teardown prevents state leakage between tests. Consider using setUp/tearDown or @after hooks if more tests need this pattern in the future, but for now this is fine.

Also applies to: 742-752


768-807: LGTM!

Thorough immutability checks covering all new trait methods. This aligns well with the clone-based immutable pattern used throughout the codebase.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/Form/InputCheckbox.php`:
- Around line 98-102: The clone operation in the enclosedByLabel flow isn't
protected by tests (mutation removing "clone" goes undetected) so add a unit
test that builds an InputCheckbox via
InputCheckbox::tag()->enclosedByLabel(true)->id('inputcheckbox-')->label('Label'),
calls render() twice on the same instance, and asserts the two outputs are
identical (assertSame) to ensure the method keeps immutability and that $new =
clone $this remains effective in the code path that modifies $new->template and
returns $new->buildElement.

In `@tests/Form/InputCheckboxTest.php`:
- Around line 350-368: The multi-line assertion in
testRenderWithEnclosedByLabelAndCustomTemplate is missing line-ending
normalization and should wrap the InputCheckbox::tag()->...->render() call with
LineEndingNormalizer::normalize(...); update the assertion to call
LineEndingNormalizer::normalize(InputCheckbox::tag()->enclosedByLabel(true)->id('inputcheckbox-')->label('Red')->template('<div
class="wrapper">'.PHP_EOL.'{tag}'.PHP_EOL.'</div>')->render()) so it matches the
sibling tests that use LineEndingNormalizer::normalize() and avoids
platform-specific newline failures.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 765e540 and 9482e79.

📒 Files selected for processing (3)
  • src/Form/InputCheckbox.php
  • src/Form/Mixin/HasLabel.php
  • tests/Form/InputCheckboxTest.php
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2026-02-07T18:51:37.079Z
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 31
File: src/Form/Mixin/HasLabel.php:195-195
Timestamp: 2026-02-07T18:51:37.079Z
Learning: In the ui-awesome/html repository, explicit boolean comparisons (e.g., `isset($var) === false`) are required instead of negation operators (e.g., `!isset($var)`) due to PHPStan strict rules configuration at the highest level.

Applied to files:

  • src/Form/Mixin/HasLabel.php
📚 Learning: 2026-02-06T21:37:44.509Z
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 24
File: tests/Form/InputTextTest.php:33-620
Timestamp: 2026-02-06T21:37:44.509Z
Learning: In the ui-awesome/html repository, prefer individual test methods over PHPUnit data providers in test classes. This helps maintainers see exactly how each test behaves without cross-referencing data providers. Apply to all PHP test files under tests. Use separate, descriptively named test methods to cover different inputs/edge cases; retain data providers only if they clearly improve readability or reduce duplication.

Applied to files:

  • tests/Form/InputCheckboxTest.php
🧬 Code graph analysis (1)
tests/Form/InputCheckboxTest.php (6)
src/Root/Html.php (1)
  • Html (27-40)
src/Form/InputCheckbox.php (1)
  • InputCheckbox (38-107)
tests/Support/Stub/DefaultProvider.php (1)
  • DefaultProvider (17-34)
tests/Support/Stub/DefaultThemeProvider.php (1)
  • DefaultThemeProvider (17-39)
src/Form/Mixin/CanBeEnclosedByLabel.php (1)
  • enclosedByLabel (32-38)
src/Form/Mixin/HasLabel.php (6)
  • label (57-63)
  • labelFor (136-142)
  • labelAttributes (79-85)
  • labelClass (111-122)
  • notLabel (174-180)
  • labelTag (156-162)
🪛 GitHub Check: mutation / PHP 8.5-ubuntu-latest
src/Form/InputCheckbox.php

[warning] 98-98:
Escaped Mutant for Mutator "CloneRemoval":

@@ @@

         $label = Html::element($this->labelTag, $labelContent, $labelAttributes);
  •        $new = clone $this;
    
  •        $new = $this;
    
           $new->template = str_replace('{tag}', '{label_enclosed}', $this->template);
    
🪛 PHPMD (2.15.0)
src/Form/InputCheckbox.php

[error] 86-86: Avoid using static access to class '\UIAwesome\Html\Core\Html' in method 'run'. (undefined)

(StaticAccess)


[error] 96-96: Avoid using static access to class '\UIAwesome\Html\Core\Html' in method 'run'. (undefined)

(StaticAccess)

src/Form/Mixin/HasLabel.php

[error] 111-111: The method labelClass has a boolean flag argument $override, which is a certain sign of a Single Responsibility Principle violation. (undefined)

(BooleanArgumentFlag)


[error] 117-119: The method labelClass uses an else expression. Else clauses are basically not necessary and you can simplify the code by not using them. (undefined)

(ElseExpression)


[error] 118-118: Avoid using static access to class '\UIAwesome\Html\Helper\CSSClass' in method 'labelClass'. (undefined)

(StaticAccess)


[error] 199-199: Avoid using static access to class '\UIAwesome\Html\Core\Html' in method 'renderLabelTag'. (undefined)

(StaticAccess)

tests/Form/InputCheckboxTest.php

[warning] 36-881: The class InputCheckboxTest has 57 public methods and attributes. Consider reducing the number of public items to less than 45. (undefined)

(ExcessivePublicCount)


[warning] 36-881: The class InputCheckboxTest has 57 non-getter- and setter-methods. Consider refactoring InputCheckboxTest to keep number of methods under 25. (undefined)

(TooManyMethods)


[warning] 36-881: The class InputCheckboxTest has 57 public methods. Consider refactoring InputCheckboxTest to keep number of public methods under 10. (undefined)

(TooManyPublicMethods)


[warning] 36-881: The class InputCheckboxTest has an overall complexity of 57 which is very high. The configured complexity threshold is 50. (undefined)

(ExcessiveClassComplexity)


[error] 36-881: The class InputCheckboxTest has a coupling between objects value of 14. Consider to reduce the number of dependencies under 13. (undefined)

(CouplingBetweenObjects)


[error] 340-346: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabel'. (undefined)

(StaticAccess)


[error] 392-399: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabelAndLabelFor'. (undefined)

(StaticAccess)


[error] 419-419: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithGlobalDefaultsAreApplied'. (undefined)

(StaticAccess)


[error] 427-427: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithGlobalDefaultsAreApplied'. (undefined)

(StaticAccess)


[error] 782-782: Avoid using static access to class '\UIAwesome\Html\Form\InputCheckbox' in method 'testRenderWithToString'. (undefined)

(StaticAccess)


[error] 817-817: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithUserOverridesGlobalDefaults'. (undefined)

(StaticAccess)


[error] 824-824: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithUserOverridesGlobalDefaults'. (undefined)

(StaticAccess)


[error] 843-843: Avoid using static access to class '\UIAwesome\Html\Form\InputCheckbox' in method 'testReturnNewInstanceWhenSettingAttribute'. (undefined)

(StaticAccess)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: composer-require-checker / PHP 8.5-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.4-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.4-windows-2022
  • GitHub Check: phpunit / PHP 8.5-windows-2022
  • GitHub Check: phpunit / PHP 8.2-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.1-windows-2022
  • GitHub Check: phpunit / PHP 8.5-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.1-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.2-windows-2022
  • GitHub Check: linter / Super Linter
  • GitHub Check: linter / Super Linter
🔇 Additional comments (4)
src/Form/Mixin/HasLabel.php (1)

1-201: Well-structured trait with clean immutable API.

The fluent, clone-based immutable pattern is consistently applied across all public methods. The renderLabelTag() method correctly auto-wires the for attribute from the element's id. No issues found.

src/Form/InputCheckbox.php (1)

38-107: Clean implementation addressing prior review feedback.

The PHPDoc now correctly describes checkbox semantics (independent selection, not mutually exclusive), and the template mutation uses clone to preserve immutability. The three rendering branches (enclosedByLabel with empty label, enclosedByLabel with content, and standard label) are well-structured.

tests/Form/InputCheckboxTest.php (2)

417-428: Good: global defaults are properly cleaned up after each test.

Both testRenderWithGlobalDefaultsAreApplied and testRenderWithUserOverridesGlobalDefaults correctly reset SimpleFactory::setDefaults to empty after assertions, preventing test pollution.

Also applies to: 815-825


841-880: Thorough immutability checks.

All new public methods from HasLabel and CanBeEnclosedByLabel are covered for assertNotSame, confirming the clone-based immutable pattern.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/Form/Base/BaseInputChoice.php`:
- Around line 161-177: The buildElement method silently treats a boolean true
for the aria-describedby attribute as a sentinel to auto-generate an "{id}-help"
value; add a brief docblock note to explain this behavior so maintainers know
true triggers auto-generation while a string is used verbatim—update the PHPDoc
for buildElement (or the HasAria trait) to mention the boolean-sentinel
convention for aria-describedby, referencing the
getAttribute('aria-describedby') check and the "{$id}-help" generation logic so
readers can locate the behavior quickly.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9482e79 and b324d7e.

📒 Files selected for processing (5)
  • CHANGELOG.md
  • src/Form/Base/BaseInputChoice.php
  • src/Form/InputCheckbox.php
  • src/Form/Mixin/HasLabel.php
  • tests/Form/InputCheckboxTest.php
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2026-02-07T18:51:37.079Z
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 31
File: src/Form/Mixin/HasLabel.php:195-195
Timestamp: 2026-02-07T18:51:37.079Z
Learning: In the ui-awesome/html repository, explicit boolean comparisons (e.g., `isset($var) === false`) are required instead of negation operators (e.g., `!isset($var)`) due to PHPStan strict rules configuration at the highest level.

Applied to files:

  • src/Form/Mixin/HasLabel.php
📚 Learning: 2026-02-06T21:37:44.509Z
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 24
File: tests/Form/InputTextTest.php:33-620
Timestamp: 2026-02-06T21:37:44.509Z
Learning: In the ui-awesome/html repository, prefer individual test methods over PHPUnit data providers in test classes. This helps maintainers see exactly how each test behaves without cross-referencing data providers. Apply to all PHP test files under tests. Use separate, descriptively named test methods to cover different inputs/edge cases; retain data providers only if they clearly improve readability or reduce duplication.

Applied to files:

  • tests/Form/InputCheckboxTest.php
🧬 Code graph analysis (1)
src/Form/InputCheckbox.php (1)
src/Form/Base/BaseInputChoice.php (3)
  • BaseInputChoice (35-199)
  • getTag (81-81)
  • loadDefault (92-100)
🪛 PHPMD (2.15.0)
src/Form/Mixin/HasLabel.php

[error] 104-104: The method labelClass has a boolean flag argument $override, which is a certain sign of a Single Responsibility Principle violation. (undefined)

(BooleanArgumentFlag)


[error] 110-112: The method labelClass uses an else expression. Else clauses are basically not necessary and you can simplify the code by not using them. (undefined)

(ElseExpression)


[error] 111-111: Avoid using static access to class '\UIAwesome\Html\Helper\CSSClass' in method 'labelClass'. (undefined)

(StaticAccess)

tests/Form/InputCheckboxTest.php

[warning] 35-940: The class InputCheckboxTest has 61 public methods and attributes. Consider reducing the number of public items to less than 45. (undefined)

(ExcessivePublicCount)


[warning] 35-940: The class InputCheckboxTest has 61 non-getter- and setter-methods. Consider refactoring InputCheckboxTest to keep number of methods under 25. (undefined)

(TooManyMethods)


[warning] 35-940: The class InputCheckboxTest has 61 public methods. Consider refactoring InputCheckboxTest to keep number of public methods under 10. (undefined)

(TooManyPublicMethods)


[warning] 35-940: The class InputCheckboxTest has an overall complexity of 61 which is very high. The configured complexity threshold is 50. (undefined)

(ExcessiveClassComplexity)


[error] 35-940: The class InputCheckboxTest has a coupling between objects value of 13. Consider to reduce the number of dependencies under 13. (undefined)

(CouplingBetweenObjects)


[error] 339-345: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabel'. (undefined)

(StaticAccess)


[error] 360-367: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabelAndCustomTemplate'. (undefined)

(StaticAccess)


[error] 393-400: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabelAndLabelFor'. (undefined)

(StaticAccess)


[error] 430-436: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabelWithoutId'. (undefined)

(StaticAccess)


[warning] 457-457: Avoid variables with short names like $id. Configured minimum length is 3. (undefined)

(ShortVariable)


[error] 468-468: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithGlobalDefaultsAreApplied'. (undefined)

(StaticAccess)


[error] 476-476: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithGlobalDefaultsAreApplied'. (undefined)

(StaticAccess)


[error] 846-846: Avoid using static access to class '\UIAwesome\Html\Form\InputCheckbox' in method 'testRenderWithToString'. (undefined)

(StaticAccess)


[error] 881-881: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithUserOverridesGlobalDefaults'. (undefined)

(StaticAccess)


[error] 888-888: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithUserOverridesGlobalDefaults'. (undefined)

(StaticAccess)


[error] 907-907: Avoid using static access to class '\UIAwesome\Html\Form\InputCheckbox' in method 'testReturnNewInstanceWhenSettingAttribute'. (undefined)

(StaticAccess)

src/Form/Base/BaseInputChoice.php

[error] 94-94: Avoid using static access to class '\UIAwesome\Html\Helper\Naming' in method 'loadDefault'. (undefined)

(StaticAccess)


[error] 97-97: Avoid using static access to class '\UIAwesome\Html\Helper\Naming' in method 'loadDefault'. (undefined)

(StaticAccess)


[warning] 110-110: Avoid variables with short names like $id. Configured minimum length is 3. (undefined)

(ShortVariable)


[error] 116-116: Avoid using static access to class '\UIAwesome\Html\Phrasing\Label' in method 'run'. (undefined)

(StaticAccess)


[error] 134-134: Avoid using static access to class '\UIAwesome\Html\Core\Html' in method 'run'. (undefined)

(StaticAccess)


[warning] 161-161: Avoid variables with short names like $id. Configured minimum length is 3. (undefined)

(ShortVariable)


[error] 176-176: Avoid using static access to class '\UIAwesome\Html\Helper\Template' in method 'buildElement'. (undefined)

(StaticAccess)


[error] 197-197: Avoid using static access to class '\UIAwesome\Html\Core\Html' in method 'renderTag'. (undefined)

(StaticAccess)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (15)
  • GitHub Check: easy-coding-standard / PHP 8.5-ubuntu-latest
  • GitHub Check: composer-require-checker / PHP 8.5-ubuntu-latest
  • GitHub Check: phpstan / PHP 8.5-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.4-windows-2022
  • GitHub Check: phpunit / PHP 8.5-windows-2022
  • GitHub Check: phpunit / PHP 8.1-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.3-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.2-windows-2022
  • GitHub Check: phpunit / PHP 8.3-windows-2022
  • GitHub Check: phpunit / PHP 8.1-windows-2022
  • GitHub Check: phpunit / PHP 8.5-ubuntu-latest
  • GitHub Check: linter / Super Linter
  • GitHub Check: phpunit / PHP 8.1-ubuntu-latest
  • GitHub Check: linter / Super Linter
  • GitHub Check: mutation / PHP 8.5-ubuntu-latest
🔇 Additional comments (7)
CHANGELOG.md (1)

5-22: LGTM!

Changelog entries are well-structured, consistently formatted, and cover the new features and fixes introduced in this release cycle.

src/Form/InputCheckbox.php (1)

31-54: Clean, minimal subclass — LGTM!

The class correctly delegates rendering to BaseInputChoice, overrides only what's necessary (getTag() and loadDefault()), and the use of the + array union operator ensures type => checkbox takes precedence over parent defaults. The final modifier is appropriate here.

tests/Form/InputCheckboxTest.php (2)

37-939: Thorough test coverage — LGTM!

The test suite comprehensively covers attribute rendering, ARIA/data attributes, label handling (including enclosed-by-label scenarios with and without id), immutability checks, idempotent rendering, theme/default providers, and global defaults. The individual-test-method approach aligns with the project's preference. The PHPMD warnings about excessive method count are expected and acceptable here. Based on learnings, this project prefers individual test methods over data providers.


466-477: 🧹 Nitpick | 🔵 Trivial

Global state cleanup is not exception-safe.

If the assertion on Line 470 fails (or any other exception occurs before Line 476), SimpleFactory::setDefaults(InputCheckbox::class, []) is never called, potentially polluting subsequent tests. The same applies to testRenderWithUserOverridesGlobalDefaults (Lines 879–889).

Consider using try/finally or PHPUnit's tearDown() to guarantee cleanup.

🛡️ Proposed fix
     public function testRenderWithGlobalDefaultsAreApplied(): void
     {
         SimpleFactory::setDefaults(InputCheckbox::class, ['class' => 'default-class']);
 
-        self::assertStringContainsString(
-            'class="default-class"',
-            InputCheckbox::tag()->render(),
-            'Failed asserting that global defaults are applied correctly.',
-        );
-
-        SimpleFactory::setDefaults(InputCheckbox::class, []);
+        try {
+            self::assertStringContainsString(
+                'class="default-class"',
+                InputCheckbox::tag()->render(),
+                'Failed asserting that global defaults are applied correctly.',
+            );
+        } finally {
+            SimpleFactory::setDefaults(InputCheckbox::class, []);
+        }
     }

Apply the same pattern to testRenderWithUserOverridesGlobalDefaults.

⛔ Skipped due to learnings
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 24
File: tests/Form/InputTextTest.php:33-620
Timestamp: 2026-02-06T21:37:44.509Z
Learning: In the ui-awesome/html repository, prefer individual test methods over PHPUnit data providers in test classes. The maintainer values the ability to see exactly how each test works without needing to cross-reference data providers, even if it results in more methods.
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 24
File: tests/Form/InputTextTest.php:289-300
Timestamp: 2026-02-06T21:37:17.409Z
Learning: In the ui-awesome/html repository, the maintainer prefers not to use defensive cleanup patterns (like try/finally) for global state in tests. Their philosophy is that if one test fails, they all fail anyway, so defensive cleanup is not necessary.
src/Form/Mixin/HasLabel.php (1)

19-155: Well-structured immutable trait — LGTM!

All mutator methods correctly clone $this before modification, maintaining immutability. The labelClass method properly handles null (removal), enum-backed values, and merge vs. override semantics. PHPDoc is thorough and consistent.

src/Form/Base/BaseInputChoice.php (2)

107-141: Well-structured rendering with clear branching — LGTM!

The three rendering paths (no label, external label, enclosed-by-label) are cleanly separated. The template token override mechanism ($tokenValues spreading after $tokenTemplateValues in buildElement) correctly allows run() to replace {tag} in the enclosed-by-label path. The immutability concern from the prior review (template mutation) has been resolved by this refactored design.


35-65: No method-name collisions detected.

The 22 traits are successfully composed without PHP fatal errors. The codebase is actively tested with PHPUnit, PHPStan static analysis, and mutation testing (as shown in the CI/CD badges in README), which would immediately catch any method-name collisions. The two local traits in this repository (CanBeEnclosedByLabel and HasLabel) have no overlapping method names, and the remaining 26 traits from external dependencies (ui-awesome/html-attribute package) are maintained as part of the published library ecosystem.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@terabytesoftw
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 8, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

…ox` for handling unchecked state rendering.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/Form/InputCheckbox.php`:
- Around line 96-156: The run() method relies on attributes() merging to
preserve a previously set for() value; change the call order so
attributes($this->labelAttributes) is applied first and then call for($id) (i.e.
ensure explicit setters run after attributes()) in both the non-enclosed branch
where you currently do $labelTag = $labelTag->for($id); ...
->attributes($this->labelAttributes)->content(...) and in the enclosedByLabel
branch where you build $labelTag =
$labelTag->attributes($this->labelAttributes)->html(...); make attributes()
happen first and then call for($id) after to guarantee the explicit for() always
wins regardless of attributes() merge behavior.

In `@tests/Form/InputCheckboxTest.php`:
- Around line 33-35: Add PHPMD suppression annotations to the test class to
silence expected class-size warnings: update the docblock for the
InputCheckboxTest class (final class InputCheckboxTest extends TestCase) to
include `@SuppressWarnings` entries for PHPMD.TooManyMethods,
PHPMD.ExcessivePublicCount, and PHPMD.ExcessiveClassComplexity so CI ignores
these test-suite-specific warnings.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b324d7e and 7b923a6.

📒 Files selected for processing (2)
  • src/Form/InputCheckbox.php
  • tests/Form/InputCheckboxTest.php
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2026-02-06T21:37:44.509Z
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 24
File: tests/Form/InputTextTest.php:33-620
Timestamp: 2026-02-06T21:37:44.509Z
Learning: In the ui-awesome/html repository, prefer individual test methods over PHPUnit data providers in test classes. This helps maintainers see exactly how each test behaves without cross-referencing data providers. Apply to all PHP test files under tests. Use separate, descriptively named test methods to cover different inputs/edge cases; retain data providers only if they clearly improve readability or reduce duplication.

Applied to files:

  • tests/Form/InputCheckboxTest.php
🧬 Code graph analysis (2)
tests/Form/InputCheckboxTest.php (6)
src/Root/Html.php (1)
  • Html (27-40)
src/Form/InputCheckbox.php (2)
  • InputCheckbox (39-157)
  • uncheckedValue (58-64)
tests/Support/Stub/DefaultProvider.php (1)
  • DefaultProvider (17-34)
tests/Support/Stub/DefaultThemeProvider.php (1)
  • DefaultThemeProvider (17-39)
src/Form/Mixin/CanBeEnclosedByLabel.php (1)
  • enclosedByLabel (32-38)
src/Form/Mixin/HasLabel.php (5)
  • label (50-56)
  • labelFor (130-136)
  • labelAttributes (72-78)
  • labelClass (104-115)
  • notLabel (148-154)
src/Form/InputCheckbox.php (4)
src/Phrasing/Label.php (2)
  • Label (27-68)
  • for (42-45)
src/Form/InputHidden.php (1)
  • InputHidden (31-68)
src/Form/Mixin/HasLabel.php (3)
  • notLabel (148-154)
  • label (50-56)
  • labelAttributes (72-78)
src/Form/Mixin/CanBeEnclosedByLabel.php (1)
  • enclosedByLabel (32-38)
🪛 PHPMD (2.15.0)
tests/Form/InputCheckboxTest.php

[warning] 35-985: The class InputCheckboxTest has 63 public methods and attributes. Consider reducing the number of public items to less than 45. (undefined)

(ExcessivePublicCount)


[warning] 35-985: The class InputCheckboxTest has 63 non-getter- and setter-methods. Consider refactoring InputCheckboxTest to keep number of methods under 25. (undefined)

(TooManyMethods)


[warning] 35-985: The class InputCheckboxTest has 63 public methods. Consider refactoring InputCheckboxTest to keep number of public methods under 10. (undefined)

(TooManyPublicMethods)


[warning] 35-985: The class InputCheckboxTest has an overall complexity of 63 which is very high. The configured complexity threshold is 50. (undefined)

(ExcessiveClassComplexity)


[error] 35-985: The class InputCheckboxTest has a coupling between objects value of 13. Consider to reduce the number of dependencies under 13. (undefined)

(CouplingBetweenObjects)


[error] 339-345: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabel'. (undefined)

(StaticAccess)


[error] 360-367: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabelAndCustomTemplate'. (undefined)

(StaticAccess)


[error] 393-400: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabelAndLabelFor'. (undefined)

(StaticAccess)


[error] 430-436: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabelWithoutId'. (undefined)

(StaticAccess)


[warning] 457-457: Avoid variables with short names like $id. Configured minimum length is 3. (undefined)

(ShortVariable)


[error] 468-468: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithGlobalDefaultsAreApplied'. (undefined)

(StaticAccess)


[error] 476-476: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithGlobalDefaultsAreApplied'. (undefined)

(StaticAccess)


[error] 846-846: Avoid using static access to class '\UIAwesome\Html\Form\InputCheckbox' in method 'testRenderWithToString'. (undefined)

(StaticAccess)


[error] 906-915: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithUncheckedValueAndEnclosedByLabel'. (undefined)

(StaticAccess)


[error] 921-921: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithUserOverridesGlobalDefaults'. (undefined)

(StaticAccess)


[error] 928-928: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithUserOverridesGlobalDefaults'. (undefined)

(StaticAccess)


[error] 947-947: Avoid using static access to class '\UIAwesome\Html\Form\InputCheckbox' in method 'testReturnNewInstanceWhenSettingAttribute'. (undefined)

(StaticAccess)

src/Form/InputCheckbox.php

[warning] 99-99: Avoid variables with short names like $id. Configured minimum length is 3. (undefined)

(ShortVariable)


[error] 118-118: Avoid using static access to class '\UIAwesome\Html\Phrasing\Label' in method 'run'. (undefined)

(StaticAccess)


[error] 142-142: Avoid using static access to class '\UIAwesome\Html\Core\Html' in method 'run'. (undefined)

(StaticAccess)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
  • GitHub Check: phpstan / PHP 8.5-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.5-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.5-windows-2022
  • GitHub Check: phpunit / PHP 8.3-windows-2022
  • GitHub Check: phpunit / PHP 8.2-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.4-windows-2022
  • GitHub Check: phpunit / PHP 8.1-windows-2022
  • GitHub Check: phpunit / PHP 8.4-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.2-windows-2022
  • GitHub Check: phpunit / PHP 8.1-ubuntu-latest
  • GitHub Check: linter / Super Linter
  • GitHub Check: linter / Super Linter
  • GitHub Check: phpunit / PHP 8.5-ubuntu-latest
🔇 Additional comments (7)
src/Form/InputCheckbox.php (2)

1-47: LGTM!

Class declaration, imports, PHPDoc, and trait composition look correct. The PHPDoc accurately describes checkbox behavior (non-exclusive selection), addressing the earlier review feedback.


49-64: LGTM!

Immutable setter for uncheckedValue follows the established clone pattern. Since InputCheckbox is final, the self return type on line 58 is equivalent to static and is fine.

tests/Form/InputCheckboxTest.php (5)

404-419: Good addition of idempotency test.

This directly addresses the earlier clone-removal mutation escape, ensuring render() produces consistent output across multiple calls on the same instance.


421-438: Good coverage of the for-attribute branch without an id.

Verifies that when no id is provided, the <label> omits the for attribute entirely, as expected.


879-917: Good uncheckedValue coverage.

Both standalone and enclosed-by-label paths for the hidden input are tested, confirming the name propagation and value rendering work correctly.


945-984: LGTM — immutability assertions are thorough.

All public fluent setters (including the new uncheckedValue) are verified to return new instances.


466-477: ⚠️ Potential issue | 🟡 Minor

Global state cleanup is not exception-safe.

If the assertion fails (throws), SimpleFactory::setDefaults(InputCheckbox::class, []) on lines 476 and 928 never executes, leaking global state into subsequent tests. Wrap in try/finally or use tearDown():

🛠️ Proposed fix (example for one test)
 public function testRenderWithGlobalDefaultsAreApplied(): void
 {
     SimpleFactory::setDefaults(InputCheckbox::class, ['class' => 'default-class']);
 
-    self::assertStringContainsString(
-        'class="default-class"',
-        InputCheckbox::tag()->render(),
-        'Failed asserting that global defaults are applied correctly.',
-    );
-
-    SimpleFactory::setDefaults(InputCheckbox::class, []);
+    try {
+        self::assertStringContainsString(
+            'class="default-class"',
+            InputCheckbox::tag()->render(),
+            'Failed asserting that global defaults are applied correctly.',
+        );
+    } finally {
+        SimpleFactory::setDefaults(InputCheckbox::class, []);
+    }
 }

Apply the same pattern to testRenderWithUserOverridesGlobalDefaults.

Also applies to: 919-929

⛔ Skipped due to learnings
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 24
File: tests/Form/InputTextTest.php:33-620
Timestamp: 2026-02-06T21:37:44.509Z
Learning: In the ui-awesome/html repository, prefer individual test methods over PHPUnit data providers in test classes. The maintainer values the ability to see exactly how each test works without needing to cross-reference data providers, even if it results in more methods.
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 24
File: tests/Form/InputTextTest.php:289-300
Timestamp: 2026-02-06T21:37:17.409Z
Learning: In the ui-awesome/html repository, the maintainer prefers not to use defensive cleanup patterns (like try/finally) for global state in tests. Their philosophy is that if one test fails, they all fail anyway, so defensive cleanup is not necessary.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/Form/InputCheckbox.php`:
- Around line 118-122: The label's explicit for attribute is added
unconditionally via Label::tag()->attributes($this->labelAttributes) and
$labelTag->for($id) even when enclosedByLabel is true and the input is wrapped
by the label; skip adding the for attribute in that case to avoid redundant
output. Update the logic around $labelTag->for($id) to check
$this->enclosedByLabel (or the same condition used when rendering the wrapped
label block) and only call ->for($id) when enclosedByLabel is false, preserving
any existing $this->labelAttributes['for'] override.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7b923a6 and ea5c5ff.

📒 Files selected for processing (1)
  • src/Form/InputCheckbox.php
🧰 Additional context used
🧬 Code graph analysis (1)
src/Form/InputCheckbox.php (4)
src/Phrasing/Label.php (2)
  • Label (27-68)
  • for (42-45)
src/Form/InputHidden.php (1)
  • InputHidden (31-68)
src/Form/Mixin/HasLabel.php (3)
  • notLabel (148-154)
  • label (50-56)
  • labelAttributes (72-78)
src/Form/Mixin/CanBeEnclosedByLabel.php (1)
  • enclosedByLabel (32-38)
🪛 PHPMD (2.15.0)
src/Form/InputCheckbox.php

[warning] 99-99: Avoid variables with short names like $id. Configured minimum length is 3. (undefined)

(ShortVariable)


[error] 139-139: Avoid using static access to class '\UIAwesome\Html\Core\Html' in method 'run'. (undefined)

(StaticAccess)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: linter / Super Linter
  • GitHub Check: phpunit / PHP 8.5-windows-2022
  • GitHub Check: phpunit / PHP 8.2-windows-2022
  • GitHub Check: composer-require-checker / PHP 8.5-ubuntu-latest
  • GitHub Check: easy-coding-standard / PHP 8.5-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.2-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.1-windows-2022
  • GitHub Check: phpunit / PHP 8.4-windows-2022
  • GitHub Check: phpunit / PHP 8.3-windows-2022
  • GitHub Check: mutation / PHP 8.5-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.4-ubuntu-latest
  • GitHub Check: linter / Super Linter
🔇 Additional comments (1)
src/Form/InputCheckbox.php (1)

1-153: Clean implementation — past review concerns addressed.

The PHPDoc is corrected, template mutation is eliminated (replacements are now passed to buildElement instead of mutating $this->template), and the label attribute ordering is handled properly with an explicit array_key_exists guard on line 120. The immutable clone pattern is consistently applied across uncheckedValue() and the composed traits.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/Form/InputCheckbox.php`:
- Around line 100-119: getAttributes() currently only compares booleans and
scalars so Stringable and UnitEnum values passed via checked() are ignored;
update the comparison to first normalize non-scalar checked/value by converting
Stringable or UnitEnum objects to strings before comparing. Specifically, in
getAttributes() check if $this->checked or $value are objects and either
implement Stringable or are instances of UnitEnum, cast them to string (e.g.
$checkedStr = (string)$this->checked or use $this->checked->name for enums if
needed) and then perform the "{$value}" === "{$checked}" comparison, preserving
the existing boolean-true branch for $this->checked === true and keeping
attributes['value'] handling.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ea5c5ff and befd389.

📒 Files selected for processing (3)
  • src/Form/InputCheckbox.php
  • tests/Form/InputCheckboxTest.php
  • tests/Provider/Form/CheckedProvider.php
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2026-02-06T21:37:44.509Z
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 24
File: tests/Form/InputTextTest.php:33-620
Timestamp: 2026-02-06T21:37:44.509Z
Learning: In the ui-awesome/html repository, prefer individual test methods over PHPUnit data providers in test classes. This helps maintainers see exactly how each test behaves without cross-referencing data providers. Apply to all PHP test files under tests. Use separate, descriptively named test methods to cover different inputs/edge cases; retain data providers only if they clearly improve readability or reduce duplication.

Applied to files:

  • tests/Provider/Form/CheckedProvider.php
  • tests/Form/InputCheckboxTest.php
📚 Learning: 2026-02-06T21:37:17.409Z
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 24
File: tests/Form/InputTextTest.php:289-300
Timestamp: 2026-02-06T21:37:17.409Z
Learning: In the ui-awesome/html repository, the maintainer prefers not to use defensive cleanup patterns (like try/finally) for global state in tests. Their philosophy is that if one test fails, they all fail anyway, so defensive cleanup is not necessary.

Applied to files:

  • tests/Form/InputCheckboxTest.php
🧬 Code graph analysis (2)
tests/Provider/Form/CheckedProvider.php (1)
src/Form/InputCheckbox.php (1)
  • checked (85-91)
tests/Form/InputCheckboxTest.php (6)
src/Form/InputCheckbox.php (3)
  • InputCheckbox (42-224)
  • checked (85-91)
  • uncheckedValue (128-134)
tests/Provider/Form/CheckedProvider.php (2)
  • CheckedProvider (15-165)
  • checked (20-164)
tests/Support/Stub/DefaultProvider.php (1)
  • DefaultProvider (17-34)
tests/Support/Stub/DefaultThemeProvider.php (1)
  • DefaultThemeProvider (17-39)
src/Form/Mixin/CanBeEnclosedByLabel.php (1)
  • enclosedByLabel (32-38)
src/Form/Mixin/HasLabel.php (5)
  • label (50-56)
  • labelFor (130-136)
  • labelAttributes (72-78)
  • labelClass (104-115)
  • notLabel (148-154)
🪛 PHPMD (2.15.0)
tests/Provider/Form/CheckedProvider.php

[warning] 20-164: The method checked() has 145 lines of code. Current threshold is set to 100. Avoid really long methods. (undefined)

(ExcessiveMethodLength)

tests/Form/InputCheckboxTest.php

[warning] 38-1010: The class InputCheckboxTest has 64 public methods and attributes. Consider reducing the number of public items to less than 45. (undefined)

(ExcessivePublicCount)


[warning] 38-1010: The class InputCheckboxTest has 64 non-getter- and setter-methods. Consider refactoring InputCheckboxTest to keep number of methods under 25. (undefined)

(TooManyMethods)


[warning] 38-1010: The class InputCheckboxTest has 64 public methods. Consider refactoring InputCheckboxTest to keep number of public methods under 10. (undefined)

(TooManyPublicMethods)


[warning] 38-1010: The class InputCheckboxTest has an overall complexity of 64 which is very high. The configured complexity threshold is 50. (undefined)

(ExcessiveClassComplexity)


[error] 38-1010: The class InputCheckboxTest has a coupling between objects value of 15. Consider to reduce the number of dependencies under 13. (undefined)

(CouplingBetweenObjects)


[error] 359-365: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabel'. (undefined)

(StaticAccess)


[error] 380-387: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabelAndCustomTemplate'. (undefined)

(StaticAccess)


[error] 413-420: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabelAndLabelFor'. (undefined)

(StaticAccess)


[error] 450-456: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabelWithoutId'. (undefined)

(StaticAccess)


[warning] 477-477: Avoid variables with short names like $id. Configured minimum length is 3. (undefined)

(ShortVariable)


[error] 488-488: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithGlobalDefaultsAreApplied'. (undefined)

(StaticAccess)


[error] 496-496: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithGlobalDefaultsAreApplied'. (undefined)

(StaticAccess)


[error] 866-866: Avoid using static access to class '\UIAwesome\Html\Form\InputCheckbox' in method 'testRenderWithToString'. (undefined)

(StaticAccess)


[error] 926-935: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithUncheckedValueAndEnclosedByLabel'. (undefined)

(StaticAccess)


[error] 941-941: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithUserOverridesGlobalDefaults'. (undefined)

(StaticAccess)


[error] 948-948: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithUserOverridesGlobalDefaults'. (undefined)

(StaticAccess)


[error] 967-967: Avoid using static access to class '\UIAwesome\Html\Form\InputCheckbox' in method 'testReturnNewInstanceWhenSettingAttribute'. (undefined)

(StaticAccess)

src/Form/InputCheckbox.php

[warning] 169-169: Avoid variables with short names like $id. Configured minimum length is 3. (undefined)

(ShortVariable)


[error] 209-209: Avoid using static access to class '\UIAwesome\Html\Core\Html' in method 'run'. (undefined)

(StaticAccess)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
  • GitHub Check: phpunit / PHP 8.4-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.2-windows-2022
  • GitHub Check: phpunit / PHP 8.1-windows-2022
  • GitHub Check: phpunit / PHP 8.1-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.3-windows-2022
  • GitHub Check: phpunit / PHP 8.5-windows-2022
  • GitHub Check: phpunit / PHP 8.5-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.2-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.4-windows-2022
  • GitHub Check: phpunit / PHP 8.3-ubuntu-latest
  • GitHub Check: linter / Super Linter
  • GitHub Check: phpunit / PHP 8.1-ubuntu-latest
  • GitHub Check: linter / Super Linter
🔇 Additional comments (10)
src/Form/InputCheckbox.php (5)

1-49: LGTM — class structure, PHPDoc, and trait composition are well-organized.

The PHPDoc correctly describes checkbox semantics (independent selection), the immutable clone pattern is consistently applied across setters, and the trait composition cleanly separates concerns.


85-91: LGTM — immutable setter pattern.


128-134: LGTM — uncheckedValue() follows the same immutable pattern.


153-159: LGTM — default configuration cleanly composes with parent defaults.


166-223: LGTM — rendering logic is clean after prior review fixes.

The for attribute is correctly scoped to the non-enclosed path, the enclosed-by-label branch properly delegates template replacement to buildElement() without mutating instance state, and the hidden input for uncheckedValue is correctly wired.

tests/Provider/Form/CheckedProvider.php (1)

15-164: Data provider is well-structured and appropriate here.

The 18 test cases systematically cover boolean, null, scalar matching/mismatching, and type juggling scenarios — this is a case where a data provider clearly reduces duplication vs. 18 individual methods with identical logic. The PHPMD method-length warning is expected.

Note: the provider doesn't cover Stringable or UnitEnum checked values, which aligns with the gap flagged in getAttributes() — consider adding coverage once that's addressed.

tests/Form/InputCheckboxTest.php (4)

36-38: Comprehensive test suite with thorough coverage.

The test class covers attributes, ARIA/data attributes, label configurations (enclosed, non-enclosed, with/without id, custom templates), immutability, idempotent rendering, global defaults, theme providers, and unchecked value handling. The PHPMD class-size warnings are expected given the individual-test-method preference in this repository. Based on learnings: "prefer individual test methods over PHPUnit data providers in test classes."


209-224: Good use of DataProviderExternal for the checked-value matrix.

This is an appropriate exception to the individual-test-method preference — 18 cases with identical assertion logic would be pure duplication without the provider. Based on learnings: "retain data providers only if they clearly improve readability or reduce duplication."


424-439: Idempotent render test effectively catches clone-removal mutations.

This directly addresses the previously identified escaped mutant.


486-497: Global state cleanup follows repository conventions.

Both testRenderWithGlobalDefaultsAreApplied and testRenderWithUserOverridesGlobalDefaults reset SimpleFactory defaults at the end of each test without try/finally, consistent with the maintainer's preference. Based on learnings: "the maintainer prefers not to use defensive cleanup patterns (like try/finally) for global state in tests."

Also applies to: 939-949

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/Form/InputCheckbox.php`:
- Around line 113-119: The bug is that casting false to string ("") makes the
scalar comparison with an empty-string value return true and incorrectly set
$attributes['checked']; to fix, explicitly short-circuit when $normalizedChecked
=== false (based on $this->checked) and ensure $attributes['checked'] is not set
(or is false) in that branch before falling back to the scalar comparison;
update the logic around $normalizedChecked, $this->checked and
$attributes['checked'] in the InputCheckbox rendering code so the sequence is:
if ($normalizedChecked === true) set checked; elseif ($normalizedChecked ===
false) ensure checked is unset/false; elseif (is_scalar($normalizedChecked) &&
is_scalar($value)) do the string-equality check.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between befd389 and 0f6f0a5.

📒 Files selected for processing (2)
  • src/Form/InputCheckbox.php
  • tests/Provider/Form/CheckedProvider.php
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2026-02-06T21:37:44.509Z
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 24
File: tests/Form/InputTextTest.php:33-620
Timestamp: 2026-02-06T21:37:44.509Z
Learning: In the ui-awesome/html repository, prefer individual test methods over PHPUnit data providers in test classes. This helps maintainers see exactly how each test behaves without cross-referencing data providers. Apply to all PHP test files under tests. Use separate, descriptively named test methods to cover different inputs/edge cases; retain data providers only if they clearly improve readability or reduce duplication.

Applied to files:

  • tests/Provider/Form/CheckedProvider.php
📚 Learning: 2026-02-06T21:37:44.509Z
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 24
File: tests/Form/InputTextTest.php:33-620
Timestamp: 2026-02-06T21:37:44.509Z
Learning: In the ui-awesome/html repository, prefer individual test methods over PHPUnit data providers in test classes. The maintainer values the ability to see exactly how each test works without needing to cross-reference data providers, even if it results in more methods.

Applied to files:

  • src/Form/InputCheckbox.php
📚 Learning: 2026-02-07T18:51:37.079Z
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 31
File: src/Form/Mixin/HasLabel.php:195-195
Timestamp: 2026-02-07T18:51:37.079Z
Learning: In the ui-awesome/html repository, explicit boolean comparisons (e.g., `isset($var) === false`) are required instead of negation operators (e.g., `!isset($var)`) due to PHPStan strict rules configuration at the highest level.

Applied to files:

  • src/Form/InputCheckbox.php
🧬 Code graph analysis (1)
tests/Provider/Form/CheckedProvider.php (2)
src/Root/Html.php (1)
  • Html (27-40)
src/Form/InputCheckbox.php (1)
  • checked (86-92)
🪛 PHPMD (2.15.0)
tests/Provider/Form/CheckedProvider.php

[warning] 28-260: The method checked() has 233 lines of code. Current threshold is set to 100. Avoid really long methods. (undefined)

(ExcessiveMethodLength)

src/Form/InputCheckbox.php

[error] 113-113: Avoid using static access to class '\UIAwesome\Html\Helper\Enum' in method 'getAttributes'. (undefined)

(StaticAccess)


[warning] 172-172: Avoid variables with short names like $id. Configured minimum length is 3. (undefined)

(ShortVariable)


[error] 212-212: Avoid using static access to class '\UIAwesome\Html\Core\Html' in method 'run'. (undefined)

(StaticAccess)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: phpstan / PHP 8.5-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.3-windows-2022
  • GitHub Check: phpunit / PHP 8.5-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.3-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.1-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.4-ubuntu-latest
  • GitHub Check: linter / Super Linter
  • GitHub Check: easy-coding-standard / PHP 8.5-ubuntu-latest
  • GitHub Check: composer-require-checker / PHP 8.5-ubuntu-latest
  • GitHub Check: mutation / PHP 8.5-ubuntu-latest
  • GitHub Check: linter / Super Linter
🔇 Additional comments (6)
tests/Provider/Form/CheckedProvider.php (1)

28-260: Well-structured provider with comprehensive type coverage.

The test cases cover a good matrix of types and match/mismatch scenarios. The descriptive array keys make debugging failures straightforward.

Note: PHPMD flags ExcessiveMethodLength (233 lines vs 100 threshold), but this is expected and acceptable for a data provider method — splitting it would reduce cohesion without improving readability.

src/Form/InputCheckbox.php (5)

43-64: Clean class structure with well-documented properties.

The immutable design, union types, and clear PHPDoc for $uncheckedValue explaining the hidden input mechanism are all solid.


86-92: LGTM — standard immutable setter.


131-137: LGTM — standard immutable setter.


144-162: LGTM — tag and default configuration.


169-226: Rendering logic is well-structured with clear separation of label modes.

The two label paths (explicit vs. enclosed) are clean, the hidden input for uncheckedValue is correctly placed before the checkbox, and the template placeholder replacements in buildElement avoid the prior template-mutation issue.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/Form/InputCheckbox.php`:
- Around line 229-266: Refactor buildAttributes to reduce cyclomatic/NPath
complexity by extracting the array-matching logic into a small helper (e.g.,
isValueInNormalizedChecked(array|string|null $normalizedChecked, mixed $value):
bool) and by using early returns: call Enum::normalizeArray/Enum::normalizeValue
as now, if normalizedChecked is false|null return early, then determine
$valueStr once, and delegate multi-item checks to the helper instead of nested
foreach/else so buildAttributes only sets $attributes['checked'] based on
helper/boolean comparisons; reference buildAttributes, Enum::normalizeArray,
Enum::normalizeValue when locating and updating the code.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0f6f0a5 and 9c95cb8.

📒 Files selected for processing (3)
  • src/Form/InputCheckbox.php
  • tests/Form/InputCheckboxTest.php
  • tests/Provider/Form/CheckedProvider.php
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2026-02-06T21:37:44.509Z
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 24
File: tests/Form/InputTextTest.php:33-620
Timestamp: 2026-02-06T21:37:44.509Z
Learning: In the ui-awesome/html repository, prefer individual test methods over PHPUnit data providers in test classes. This helps maintainers see exactly how each test behaves without cross-referencing data providers. Apply to all PHP test files under tests. Use separate, descriptively named test methods to cover different inputs/edge cases; retain data providers only if they clearly improve readability or reduce duplication.

Applied to files:

  • tests/Provider/Form/CheckedProvider.php
  • tests/Form/InputCheckboxTest.php
📚 Learning: 2026-02-06T21:37:17.409Z
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 24
File: tests/Form/InputTextTest.php:289-300
Timestamp: 2026-02-06T21:37:17.409Z
Learning: In the ui-awesome/html repository, the maintainer prefers not to use defensive cleanup patterns (like try/finally) for global state in tests. Their philosophy is that if one test fails, they all fail anyway, so defensive cleanup is not necessary.

Applied to files:

  • tests/Form/InputCheckboxTest.php
📚 Learning: 2026-02-06T21:37:44.509Z
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 24
File: tests/Form/InputTextTest.php:33-620
Timestamp: 2026-02-06T21:37:44.509Z
Learning: In the ui-awesome/html repository, prefer individual test methods over PHPUnit data providers in test classes. The maintainer values the ability to see exactly how each test works without needing to cross-reference data providers, even if it results in more methods.

Applied to files:

  • src/Form/InputCheckbox.php
📚 Learning: 2026-02-07T18:51:37.079Z
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 31
File: src/Form/Mixin/HasLabel.php:195-195
Timestamp: 2026-02-07T18:51:37.079Z
Learning: In the ui-awesome/html repository, explicit boolean comparisons (e.g., `isset($var) === false`) are required instead of negation operators (e.g., `!isset($var)`) due to PHPStan strict rules configuration at the highest level.

Applied to files:

  • src/Form/InputCheckbox.php
🧬 Code graph analysis (3)
tests/Provider/Form/CheckedProvider.php (2)
src/Root/Html.php (1)
  • Html (27-40)
src/Form/InputCheckbox.php (1)
  • checked (92-98)
tests/Form/InputCheckboxTest.php (4)
src/Root/Html.php (1)
  • Html (27-40)
src/Form/InputCheckbox.php (3)
  • InputCheckbox (44-267)
  • checked (92-98)
  • uncheckedValue (119-125)
src/Form/Mixin/CanBeEnclosedByLabel.php (1)
  • enclosedByLabel (32-38)
src/Form/Mixin/HasLabel.php (4)
  • label (50-56)
  • labelAttributes (72-78)
  • labelClass (104-115)
  • notLabel (148-154)
src/Form/InputCheckbox.php (3)
src/Phrasing/Label.php (2)
  • Label (27-68)
  • for (42-45)
src/Form/Mixin/HasLabel.php (3)
  • notLabel (148-154)
  • label (50-56)
  • labelAttributes (72-78)
src/Form/Mixin/CanBeEnclosedByLabel.php (1)
  • enclosedByLabel (32-38)
🪛 PHPMD (2.15.0)
tests/Provider/Form/CheckedProvider.php

[warning] 31-301: The method checked() has 271 lines of code. Current threshold is set to 100. Avoid really long methods. (undefined)

(ExcessiveMethodLength)

tests/Form/InputCheckboxTest.php

[warning] 38-1013: The class InputCheckboxTest has 64 public methods and attributes. Consider reducing the number of public items to less than 45. (undefined)

(ExcessivePublicCount)


[warning] 38-1013: The class InputCheckboxTest has 64 non-getter- and setter-methods. Consider refactoring InputCheckboxTest to keep number of methods under 25. (undefined)

(TooManyMethods)


[warning] 38-1013: The class InputCheckboxTest has 64 public methods. Consider refactoring InputCheckboxTest to keep number of public methods under 10. (undefined)

(TooManyPublicMethods)


[warning] 38-1013: The class InputCheckboxTest has an overall complexity of 64 which is very high. The configured complexity threshold is 50. (undefined)

(ExcessiveClassComplexity)


[error] 38-1013: The class InputCheckboxTest has a coupling between objects value of 15. Consider to reduce the number of dependencies under 13. (undefined)

(CouplingBetweenObjects)


[error] 362-368: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabel'. (undefined)

(StaticAccess)


[error] 383-390: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabelAndCustomTemplate'. (undefined)

(StaticAccess)


[error] 416-423: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabelAndLabelFor'. (undefined)

(StaticAccess)


[error] 453-459: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabelWithoutId'. (undefined)

(StaticAccess)


[warning] 480-480: Avoid variables with short names like $id. Configured minimum length is 3. (undefined)

(ShortVariable)


[error] 491-491: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithGlobalDefaultsAreApplied'. (undefined)

(StaticAccess)


[error] 499-499: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithGlobalDefaultsAreApplied'. (undefined)

(StaticAccess)


[error] 869-869: Avoid using static access to class '\UIAwesome\Html\Form\InputCheckbox' in method 'testRenderWithToString'. (undefined)

(StaticAccess)


[error] 929-938: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithUncheckedValueAndEnclosedByLabel'. (undefined)

(StaticAccess)


[error] 944-944: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithUserOverridesGlobalDefaults'. (undefined)

(StaticAccess)


[error] 951-951: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithUserOverridesGlobalDefaults'. (undefined)

(StaticAccess)


[error] 970-970: Avoid using static access to class '\UIAwesome\Html\Form\InputCheckbox' in method 'testReturnNewInstanceWhenSettingAttribute'. (undefined)

(StaticAccess)

src/Form/InputCheckbox.php

[warning] 160-160: Avoid variables with short names like $id. Configured minimum length is 3. (undefined)

(ShortVariable)


[error] 200-200: Avoid using static access to class '\UIAwesome\Html\Core\Html' in method 'run'. (undefined)

(StaticAccess)


[warning] 229-266: The method buildAttributes() has a Cyclomatic Complexity of 13. The configured cyclomatic complexity threshold is 10. (undefined)

(CyclomaticComplexity)


[warning] 229-266: The method buildAttributes() has an NPath complexity of 264. The configured NPath complexity threshold is 200. (undefined)

(NPathComplexity)


[error] 238-238: Avoid using static access to class '\UIAwesome\Html\Helper\Enum' in method 'buildAttributes'. (undefined)

(StaticAccess)


[error] 239-239: Avoid using static access to class '\UIAwesome\Html\Helper\Enum' in method 'buildAttributes'. (undefined)

(StaticAccess)


[error] 249-263: The method buildAttributes uses an else expression. Else clauses are basically not necessary and you can simplify the code by not using them. (undefined)

(ElseExpression)


[error] 260-262: The method buildAttributes uses an else expression. Else clauses are basically not necessary and you can simplify the code by not using them. (undefined)

(ElseExpression)

🔇 Additional comments (13)
src/Form/InputCheckbox.php (5)

44-52: LGTM!

The class declaration, trait composition, and imports are well-organized. The combination of traits provides a clean separation of concerns for the various checkbox capabilities.


53-98: LGTM!

The $checked property and checked() method correctly implement the immutable pattern using clone $this. The type signature is comprehensive, supporting arrays, booleans, scalars, Stringable, and UnitEnum types. The docblock is well-documented with usage examples.


100-125: LGTM!

The getAttributes() method properly delegates to buildAttributes(), and uncheckedValue() correctly implements immutability. The docblocks are clear and accurate.


127-150: LGTM!

The getTag() and loadDefault() methods are correctly implemented. The default template with {unchecked} placeholder properly supports the hidden input feature.


157-214: LGTM!

The run() method handles all rendering paths correctly:

  • Hidden input emission when uncheckedValue is set
  • Label suppression via notLabel or empty label
  • Separate label with for attribute wiring
  • Enclosed label wrapping the input

The explicit boolean comparison $this->enclosedByLabel === false and array_key_exists('for', $this->labelAttributes) === false comply with the repository's PHPStan strict rules. Based on learnings: "explicit boolean comparisons are required instead of negation operators due to PHPStan strict rules."

tests/Form/InputCheckboxTest.php (7)

36-38: PHPMD class-size warnings are expected for comprehensive test suites.

The TooManyMethods, ExcessivePublicCount, and ExcessiveClassComplexity warnings are inherent to test classes with individual test methods (which is the preferred pattern per repository learnings). These warnings can be safely ignored or suppressed with @SuppressWarnings annotations if desired.

Based on learnings: "prefer individual test methods over PHPUnit data providers in test classes" — the high method count is a direct consequence of following this guideline.


40-48: LGTM!

Good test for the default value behavior of getAttribute().


209-227: LGTM!

The data-provider-driven test efficiently covers the 34 checked/value combinations defined in CheckedProvider. This is a reasonable use of a data provider given the volume of edge cases.


353-461: LGTM!

Excellent coverage of the enclosedByLabel functionality:

  • Basic enclosed label rendering
  • Custom template with enclosed label
  • Empty label content behavior
  • Label for attribute with enclosed mode
  • Idempotency test (addresses the past mutation concern)
  • Enclosed label without ID

The LineEndingNormalizer::normalize() is correctly applied to all multi-line assertions.


489-500: LGTM!

The global defaults test correctly sets up and tears down the SimpleFactory state. The cleanup at line 499 follows the pattern used elsewhere in the codebase.


902-940: LGTM!

Good coverage of uncheckedValue feature:

  • Standalone hidden input rendering
  • Combined with enclosedByLabel mode

Both tests verify the hidden input appears before the checkbox with the correct name and value attributes.


968-1012: LGTM!

Comprehensive immutability tests covering all setter methods:

  • checked()
  • enclosedByLabel()
  • label()
  • labelAttributes()
  • labelClass()
  • labelFor()
  • notLabel()
  • uncheckedValue()

Each assertion confirms the fluent methods return new instances, preserving immutability guarantees.

tests/Provider/Form/CheckedProvider.php (1)

20-301: 🧹 Nitpick | 🔵 Trivial

Data provider conflicts with repository preference for individual test methods.

Based on learnings: "In the ui-awesome/html repository, prefer individual test methods over PHPUnit data providers in test classes. This helps maintainers see exactly how each test behaves without cross-referencing data providers."

However, for the 34 test cases covering type juggling, enums, booleans, and edge cases, a data provider is a pragmatic choice that significantly reduces code duplication. The provider is well-documented with clear section comments. If you prefer to keep the provider (which is reasonable here), consider adding a brief note in the class docblock explaining why a provider is used for this specific case.

⛔ Skipped due to learnings
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 24
File: tests/Form/InputTextTest.php:33-620
Timestamp: 2026-02-06T21:37:44.509Z
Learning: In the ui-awesome/html repository, prefer individual test methods over PHPUnit data providers in test classes. The maintainer values the ability to see exactly how each test works without needing to cross-reference data providers, even if it results in more methods.
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 24
File: tests/Form/InputTextTest.php:289-300
Timestamp: 2026-02-06T21:37:17.409Z
Learning: In the ui-awesome/html repository, the maintainer prefers not to use defensive cleanup patterns (like try/finally) for global state in tests. Their philosophy is that if one test fails, they all fail anyway, so defensive cleanup is not necessary.
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 31
File: src/Form/Mixin/HasLabel.php:195-195
Timestamp: 2026-02-07T18:51:37.079Z
Learning: In the ui-awesome/html repository, explicit boolean comparisons (e.g., `isset($var) === false`) are required instead of negation operators (e.g., `!isset($var)`) due to PHPStan strict rules configuration at the highest level.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/Form/InputCheckbox.php`:
- Around line 229-270: In buildAttributes, when iterating the normalizedChecked
array inside the foreach loop (variable $normalizedChecked) you should stop
iterating once a match is found: set $attributes['checked'] = true and
immediately break out of the foreach to avoid redundant comparisons for large
arrays; update the loop in buildAttributes so that after detecting
is_scalar($item) && "{$item}" === $valueStr you both set checked and break.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0f6f0a5 and e421dd8.

📒 Files selected for processing (3)
  • src/Form/InputCheckbox.php
  • tests/Form/InputCheckboxTest.php
  • tests/Provider/Form/CheckedProvider.php
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2026-02-06T21:37:44.509Z
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 24
File: tests/Form/InputTextTest.php:33-620
Timestamp: 2026-02-06T21:37:44.509Z
Learning: In the ui-awesome/html repository, prefer individual test methods over PHPUnit data providers in test classes. This helps maintainers see exactly how each test behaves without cross-referencing data providers. Apply to all PHP test files under tests. Use separate, descriptively named test methods to cover different inputs/edge cases; retain data providers only if they clearly improve readability or reduce duplication.

Applied to files:

  • tests/Provider/Form/CheckedProvider.php
  • tests/Form/InputCheckboxTest.php
📚 Learning: 2026-02-06T21:37:44.509Z
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 24
File: tests/Form/InputTextTest.php:33-620
Timestamp: 2026-02-06T21:37:44.509Z
Learning: In the ui-awesome/html repository, prefer individual test methods over PHPUnit data providers in test classes. The maintainer values the ability to see exactly how each test works without needing to cross-reference data providers, even if it results in more methods.

Applied to files:

  • src/Form/InputCheckbox.php
📚 Learning: 2026-02-07T18:51:37.079Z
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 31
File: src/Form/Mixin/HasLabel.php:195-195
Timestamp: 2026-02-07T18:51:37.079Z
Learning: In the ui-awesome/html repository, explicit boolean comparisons (e.g., `isset($var) === false`) are required instead of negation operators (e.g., `!isset($var)`) due to PHPStan strict rules configuration at the highest level.

Applied to files:

  • src/Form/InputCheckbox.php
📚 Learning: 2026-02-06T21:37:17.409Z
Learnt from: terabytesoftw
Repo: ui-awesome/html PR: 24
File: tests/Form/InputTextTest.php:289-300
Timestamp: 2026-02-06T21:37:17.409Z
Learning: In the ui-awesome/html repository, the maintainer prefers not to use defensive cleanup patterns (like try/finally) for global state in tests. Their philosophy is that if one test fails, they all fail anyway, so defensive cleanup is not necessary.

Applied to files:

  • tests/Form/InputCheckboxTest.php
🧬 Code graph analysis (3)
tests/Provider/Form/CheckedProvider.php (1)
src/Form/InputCheckbox.php (1)
  • checked (92-98)
src/Form/InputCheckbox.php (4)
src/Phrasing/Label.php (2)
  • Label (27-68)
  • for (42-45)
src/Form/InputHidden.php (1)
  • InputHidden (31-68)
src/Form/Mixin/HasLabel.php (3)
  • notLabel (148-154)
  • label (50-56)
  • labelAttributes (72-78)
src/Form/Mixin/CanBeEnclosedByLabel.php (1)
  • enclosedByLabel (32-38)
tests/Form/InputCheckboxTest.php (7)
src/Root/Html.php (1)
  • Html (27-40)
src/Form/InputCheckbox.php (3)
  • InputCheckbox (44-271)
  • checked (92-98)
  • uncheckedValue (119-125)
tests/Provider/Form/CheckedProvider.php (2)
  • CheckedProvider (20-302)
  • checked (31-301)
tests/Support/Stub/DefaultProvider.php (1)
  • DefaultProvider (17-34)
tests/Support/Stub/DefaultThemeProvider.php (1)
  • DefaultThemeProvider (17-39)
src/Form/Mixin/CanBeEnclosedByLabel.php (1)
  • enclosedByLabel (32-38)
src/Form/Mixin/HasLabel.php (5)
  • label (50-56)
  • labelFor (130-136)
  • labelAttributes (72-78)
  • labelClass (104-115)
  • notLabel (148-154)
🪛 PHPMD (2.15.0)
tests/Provider/Form/CheckedProvider.php

[warning] 31-301: The method checked() has 271 lines of code. Current threshold is set to 100. Avoid really long methods. (undefined)

(ExcessiveMethodLength)

src/Form/InputCheckbox.php

[warning] 160-160: Avoid variables with short names like $id. Configured minimum length is 3. (undefined)

(ShortVariable)


[error] 200-200: Avoid using static access to class '\UIAwesome\Html\Core\Html' in method 'run'. (undefined)

(StaticAccess)


[warning] 229-270: The method buildAttributes() has a Cyclomatic Complexity of 13. The configured cyclomatic complexity threshold is 10. (undefined)

(CyclomaticComplexity)


[warning] 229-270: The method buildAttributes() has an NPath complexity of 768. The configured NPath complexity threshold is 200. (undefined)

(NPathComplexity)


[error] 238-238: Avoid using static access to class '\UIAwesome\Html\Helper\Enum' in method 'buildAttributes'. (undefined)

(StaticAccess)


[error] 239-239: Avoid using static access to class '\UIAwesome\Html\Helper\Enum' in method 'buildAttributes'. (undefined)

(StaticAccess)

tests/Form/InputCheckboxTest.php

[warning] 38-1013: The class InputCheckboxTest has 64 public methods and attributes. Consider reducing the number of public items to less than 45. (undefined)

(ExcessivePublicCount)


[warning] 38-1013: The class InputCheckboxTest has 64 non-getter- and setter-methods. Consider refactoring InputCheckboxTest to keep number of methods under 25. (undefined)

(TooManyMethods)


[warning] 38-1013: The class InputCheckboxTest has 64 public methods. Consider refactoring InputCheckboxTest to keep number of public methods under 10. (undefined)

(TooManyPublicMethods)


[warning] 38-1013: The class InputCheckboxTest has an overall complexity of 64 which is very high. The configured complexity threshold is 50. (undefined)

(ExcessiveClassComplexity)


[error] 38-1013: The class InputCheckboxTest has a coupling between objects value of 15. Consider to reduce the number of dependencies under 13. (undefined)

(CouplingBetweenObjects)


[error] 362-368: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabel'. (undefined)

(StaticAccess)


[error] 383-390: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabelAndCustomTemplate'. (undefined)

(StaticAccess)


[error] 416-423: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabelAndLabelFor'. (undefined)

(StaticAccess)


[error] 453-459: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithEnclosedByLabelWithoutId'. (undefined)

(StaticAccess)


[warning] 480-480: Avoid variables with short names like $id. Configured minimum length is 3. (undefined)

(ShortVariable)


[error] 491-491: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithGlobalDefaultsAreApplied'. (undefined)

(StaticAccess)


[error] 499-499: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithGlobalDefaultsAreApplied'. (undefined)

(StaticAccess)


[error] 869-869: Avoid using static access to class '\UIAwesome\Html\Form\InputCheckbox' in method 'testRenderWithToString'. (undefined)

(StaticAccess)


[error] 929-938: Avoid using static access to class '\PHPForge\Support\LineEndingNormalizer' in method 'testRenderWithUncheckedValueAndEnclosedByLabel'. (undefined)

(StaticAccess)


[error] 944-944: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithUserOverridesGlobalDefaults'. (undefined)

(StaticAccess)


[error] 951-951: Avoid using static access to class '\UIAwesome\Html\Core\Factory\SimpleFactory' in method 'testRenderWithUserOverridesGlobalDefaults'. (undefined)

(StaticAccess)


[error] 970-970: Avoid using static access to class '\UIAwesome\Html\Form\InputCheckbox' in method 'testReturnNewInstanceWhenSettingAttribute'. (undefined)

(StaticAccess)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: composer-require-checker / PHP 8.5-ubuntu-latest
  • GitHub Check: mutation / PHP 8.5-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.3-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.1-windows-2022
  • GitHub Check: phpunit / PHP 8.5-windows-2022
  • GitHub Check: phpstan / PHP 8.5-ubuntu-latest
  • GitHub Check: phpunit / PHP 8.3-windows-2022
  • GitHub Check: phpunit / PHP 8.2-windows-2022
  • GitHub Check: phpunit / PHP 8.4-windows-2022
  • GitHub Check: easy-coding-standard / PHP 8.5-ubuntu-latest
  • GitHub Check: linter / Super Linter
  • GitHub Check: linter / Super Linter
🔇 Additional comments (7)
tests/Provider/Form/CheckedProvider.php (1)

31-301: Well-structured data provider with comprehensive edge-case coverage.

The test cases thoroughly cover array matching, type juggling, backed/unit enums, Stringable, booleans, floats, and null — all with clear descriptive keys. Retaining a data provider here is justified since it clearly reduces duplication across 30+ structurally identical assertions. The PHPMD ExcessiveMethodLength warning is expected and acceptable for this pattern.

Based on learnings: "retain data providers only if they clearly improve readability or reduce duplication."

src/Form/InputCheckbox.php (2)

1-51: Clean class structure with well-chosen traits and clear PHPDoc.

The docblock correctly describes checkbox semantics (independent, non-exclusive selection), the usage example is helpful, and the trait composition is clean.


157-214: run() logic is well-structured after prior review fixes.

The label-enclosure paths, for-attribute handling, and unchecked hidden input rendering all look correct. The template replacement strategy for enclosedByLabel properly substitutes {tag} with the wrapping label to avoid double-rendering the input.

tests/Form/InputCheckboxTest.php (4)

36-38: Comprehensive test suite with thorough coverage.

The test class covers attributes, rendering, label configurations, immutability, global defaults, theme providers, idempotency, and data-driven checked/value combinations. The PHPMD class-size warnings are inherent to the preferred individual-test-method pattern.


209-227: Data provider usage for checked/value combinator is appropriate here.

The #[DataProviderExternal] attribute with CheckedProvider::checked efficiently covers 30+ type-juggling and edge-case scenarios that would otherwise require 30+ nearly identical test methods. This is a clear case where the provider improves readability and reduces duplication.

Based on learnings: "retain data providers only if they clearly improve readability or reduce duplication."


427-442: Good idempotency test — catches clone-removal mutations.

This test ensures rendering the same enclosedByLabel instance twice produces identical output, directly guarding against the escaped mutant identified in the prior review.


968-1012: Thorough immutability assertions.

All public fluent methods (checked, enclosedByLabel, label, labelAttributes, labelClass, labelFor, notLabel, uncheckedValue) are verified to return new instances.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@terabytesoftw terabytesoftw merged commit 20600de into main Feb 9, 2026
49 checks passed
@terabytesoftw terabytesoftw deleted the feature_12 branch February 9, 2026 10:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant