Skip to content

feat: add FieldDataType::FILE to fix file upload validation#100

Merged
ManukMinasyan merged 1 commit into3.xfrom
fix/file-upload-validation-3x
Mar 6, 2026
Merged

feat: add FieldDataType::FILE to fix file upload validation#100
ManukMinasyan merged 1 commit into3.xfrom
fix/file-upload-validation-3x

Conversation

@ManukMinasyan
Copy link
Collaborator

Summary

  • Adds FieldDataType::FILE enum case with FieldSchema::file() factory method
  • FILE maps to string_value for storage but skips database column constraints in validation
  • Fixes file upload fields rejecting files >255 KB due to string_value column's max:255 being interpreted as kilobytes when combined with the file validation rule

Problem

File upload custom fields use FieldSchema::string() which stores file paths in string_value (VARCHAR 255). DatabaseFieldConstraints adds string + max:255 rules for that column. When combined with the file default validation rule, Laravel interprets max:255 as 255 KB file size limit instead of 255 characters — causing valid file uploads (e.g., a 608 KB PDF) to fail validation.

Solution

Introduces FieldDataType::FILE as a first-class data type that:

  • Maps to string_value for storage (file paths fit in VARCHAR 255)
  • Returns empty database validation rules (the column constraints are irrelevant — validation runs against the uploaded file, not the stored path)
  • Provides FieldSchema::file() factory for semantic clarity
  • Updates FileUploadFieldType to use FieldSchema::file() instead of FieldSchema::string()

Files changed

File Change
FieldDataType Add FILE = 'file' case with visibility operators
FieldSchema Add file() factory method
FileUploadFieldType Use FieldSchema::file()
CustomFieldValue Map FILE to string_value
ValidationService Skip DB constraints for FILE data type
MakeFieldTypeCommand Handle FILE in scaffolding

Test plan

  • New FileUploadValidationTest with 5 tests covering:
    • FILE resolves to string_value column
    • No string or max:255 rules applied to file uploads
    • Capability-based max_size_kb works correctly
    • getDatabaseValidationRules returns empty for file types
    • FieldDataType::FILE enum behavior
  • Full test suite passes (396 tests, 2103 assertions)

File upload fields stored paths in string_value, causing
DatabaseFieldConstraints to add max:255 (characters) which Laravel
interpreted as 255 KB when combined with the 'file' rule.

Adds FieldDataType::FILE with FieldSchema::file() factory method.
FILE maps to string_value for storage but skips database column
constraints, since validation runs against the uploaded file,
not the stored path.
Copilot AI review requested due to automatic review settings March 6, 2026 18:04
@ManukMinasyan ManukMinasyan merged commit dd42685 into 3.x Mar 6, 2026
5 checks passed
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

Adds a first-class FieldDataType::FILE to ensure file upload custom fields validate the uploaded file correctly without inheriting string_value (VARCHAR 255) column constraints that conflict with Laravel’s file rule semantics.

Changes:

  • Introduces FieldDataType::FILE plus FieldSchema::file() and updates FileUploadFieldType to use it.
  • Maps FILE to string_value storage while updating validation logic to skip DB column constraints for file data types.
  • Adds integration tests covering column resolution and validation rule composition for file uploads.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/Feature/Integration/FileUploadValidationTest.php New tests asserting FILE storage mapping and that DB constraints are skipped for file uploads.
src/Services/ValidationService.php Skips DB constraint merging for FieldDataType::FILE to avoid max:255 being treated as KB.
src/Models/CustomFieldValue.php Maps FieldDataType::FILE to string_value.
src/FieldTypeSystem/FieldSchema.php Adds FieldSchema::file() factory.
src/FieldTypeSystem/Definitions/FileUploadFieldType.php Uses FieldSchema::file() for the file upload field type.
src/Enums/FieldDataType.php Adds FILE enum case and compatible visibility operators.
src/Console/Commands/MakeFieldTypeCommand.php Adds scaffolding support for FILE (configurator + Filament FileUpload component generation).
Comments suppressed due to low confidence (1)

src/Services/ValidationService.php:120

  • getDatabaseValidationRules() calls CustomFieldsType::getFieldType() to detect FieldDataType::FILE, and then (for non-FILE types) calls CustomFieldValue::getValueColumn($fieldType), which internally calls CustomFieldsType::getFieldType() again. Because FieldManager::getFieldType() rebuilds the field type collection (instantiating all field type definitions) on each call, this introduces redundant work on a hot path. Consider retrieving the FieldTypeData once and deriving the value column from its dataType, or adding an overload/helper that accepts FieldTypeData/FieldDataType to avoid repeated lookups.
        // File types validate the uploaded file, not the stored path
        $fieldTypeData = CustomFieldsType::getFieldType($fieldType);

        if ($fieldTypeData?->dataType === FieldDataType::FILE) {
            return [];
        }

        // Determine the database column for this field type
        $columnName = CustomFieldValue::getValueColumn($fieldType);

        // Get base database rules for this column
        $dbRules = DatabaseFieldConstraints::getValidationRulesForColumn($columnName, $isEncrypted);

Comment on lines +247 to +252
// File types validate the uploaded file, not the stored path — skip DB constraints
$fieldTypeData = CustomFieldsType::getFieldType($fieldType);

if ($fieldTypeData?->dataType === FieldDataType::FILE) {
return $mergedRules;
}
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

mergeAllValidationRules() performs another CustomFieldsType::getFieldType($fieldType) lookup to decide whether to skip DB constraints for files. This duplicates the lookup already done earlier in getDatabaseValidationRules() and can be avoided by passing the resolved FieldDataType (or a skipDbConstraints boolean) into this method, reducing repeated field-type resolution work.

Copilot uses AI. Check for mistakes.
Comment on lines 168 to 181
protected function getConfiguratorForDataType(FieldDataType $dataType): string
{
return match ($dataType) {
FieldDataType::STRING => 'text()',
FieldDataType::TEXT => 'text()',
FieldDataType::NUMERIC => 'numeric()',
FieldDataType::FLOAT => 'float()',
FieldDataType::DATE => 'date()',
FieldDataType::DATE_TIME => 'dateTime()',
FieldDataType::BOOLEAN => 'boolean()',
FieldDataType::SINGLE_CHOICE => 'singleChoice()',
FieldDataType::MULTI_CHOICE => 'multiChoice()',
FieldDataType::FILE => 'file()',
};
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

getConfiguratorForDataType() (and related methods) now support FieldDataType::FILE, but getDataType()'s interactive $options list doesn’t include a file entry. This makes the new data type unreachable when running the command without --type=file. Add a file option to the prompt/choice list so the scaffolder can generate FILE field types via the interactive flow as well.

Copilot uses AI. Check for mistakes.
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