Skip to content

fix: normalize values in unique field validation and wire ignoreEntityId#90

Merged
ManukMinasyan merged 7 commits into3.xfrom
fix/unique-field-value-normalization
Feb 24, 2026
Merged

fix: normalize values in unique field validation and wire ignoreEntityId#90
ManukMinasyan merged 7 commits into3.xfrom
fix/unique-field-value-normalization

Conversation

@ManukMinasyan
Copy link
Collaborator

Summary

  • Protocol normalization bug: Entering https://example.com bypassed uniqueness check against stored example.com because dehydrateStateUsing stripped the protocol after validation ran. The UniqueCustomFieldValue rule now normalizes values via BaseFieldType::setValue() before comparing.
  • Edit ignoreEntityId bug: AbstractFormComponent never passed the current record's ID to the uniqueness rule, causing records to reject their own unchanged unique values during edit. Now passes $record->getKey() via a closure in ->rules().

Changes

  • Add setValue()/getValue() to BaseFieldType (identity by default)
  • Override setValue() in LinkFieldType to strip http:///https:// and trim
  • UniqueCustomFieldValue normalizes via field type before DB comparison
  • AbstractFormComponent resolves record ID at validation time via closure
  • LinkComponent uses fieldType->setValue() instead of inline regex
  • 17 new Livewire integration tests covering both bugs

Test plan

  • All 358 existing tests pass
  • 17 new tests cover: create with unique/duplicate domains, edit own record, edit conflict with another record, protocol variants (http/https/HTTPS), multi-value arrays, text field uniqueness, blank value handling

…yId during edit

Two bugs fixed:

1. UniqueCustomFieldValue compared raw input against stored (normalized)
   values. For link fields, entering "https://example.com" bypassed the
   uniqueness check against a stored "example.com" because the protocol
   was stripped by dehydrateStateUsing after validation ran.

2. AbstractFormComponent never passed the current record's ID to the
   uniqueness rule during edit, causing records to detect themselves as
   duplicates when saving unchanged unique values.

Changes:
- Add setValue()/getValue() to BaseFieldType for value normalization
- Override setValue() in LinkFieldType to strip protocol and trim
- UniqueCustomFieldValue now normalizes via field type before comparing
- AbstractFormComponent passes record ID via closure to rules()
- LinkComponent uses field type setValue() instead of inline regex
- Add 17 Livewire integration tests for uniqueness validation
Copilot AI review requested due to automatic review settings February 24, 2026 00:25
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes two bugs in custom field uniqueness validation: protocol normalization and edit-mode entity exclusion.

Changes:

  • Added setValue()/getValue() methods to BaseFieldType for value normalization, with LinkFieldType overriding to strip protocols
  • Updated UniqueCustomFieldValue rule to normalize values via field type before database comparison
  • Wired ignoreEntityId parameter through AbstractFormComponent to exclude current record during edit validation

Reviewed changes

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

Show a summary per file
File Description
tests/Feature/Rules/UniqueCustomFieldValueTest.php Comprehensive integration tests covering both protocol normalization and edit-mode bugs
src/Rules/UniqueCustomFieldValue.php Refactored to normalize values via field type and extract query logic
src/Filament/Integration/Components/Forms/LinkComponent.php Updated to use field type's setValue() instead of inline regex
src/Filament/Integration/Base/AbstractFormComponent.php Changed rules() to closure to pass record ID at validation time
src/FieldTypeSystem/Definitions/LinkFieldType.php Implements protocol-stripping normalization in setValue()
src/FieldTypeSystem/BaseFieldType.php Added identity implementation of setValue()/getValue() methods

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

blank('0') returns false in Laravel, but the original code treated '0'
as an empty expression. Restore the explicit '0' check to avoid a
subtle behavior change in field visibility.
…closures

- Use getMorphClass() directly instead of two-step Relation::getMorphAlias()
  fallback, matching codebase convention
- Collapse nested closures in LinkComponent dehydrateStateUsing to arrow
  functions
- Restore '0' check in visibility guard (blank('0') is false in Laravel)
@relaticle relaticle deleted a comment from Copilot AI Feb 24, 2026
@relaticle relaticle deleted a comment from Copilot AI Feb 24, 2026
…ns and unique validation logic

- Add explicit return types to closures and methods for better type safety
- Normalize and improve consistency of `Closure` imports and doc annotations
- Simplify conditional logic in AbstractFormComponent and cleanup orphaned value checks
- Standardize string concatenation with `.` instead of interpolation for warnings/messages
- Relocate and restore LinkFieldType `setValue` method for better class organization
@ManukMinasyan ManukMinasyan merged commit a0a6a24 into 3.x Feb 24, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants