Skip to content

#636 TFileValidator, TImageValidator, TFileUpload and TActiveFileUpload tweaks - #1246

Merged
ctrlaltca merged 2 commits into
pradosoft:masterfrom
belisoful:636-file-validation
Aug 27, 2026
Merged

#636 TFileValidator, TImageValidator, TFileUpload and TActiveFileUpload tweaks#1246
ctrlaltca merged 2 commits into
pradosoft:masterfrom
belisoful:636-file-validation

Conversation

@belisoful

Copy link
Copy Markdown
Member

TFileValidator, TImageValidator, and file upload validation (closes #636)

Implements the client- and server-side file upload validation requested in #636, built on the Prado validator architecture. No new dependencies: server-side image checks use core getimagesize(), MIME sniffing uses the bundled fileinfo extension with graceful degradation.

New components

  • TFileValidator — validates the files of a TFileUpload: per-file MaxFileSize/MinFileSize, combined TotalMaxFileSize, MinFileCount/MaxFileCount, AllowedFileExtensions, AllowedFileTypes (image/* wildcards), and server-only CheckExtensionMimeType (sniffed content must correspond to the file name extension; map extendable via static::$extensionMimeTypes). Client side mirrors every check through the HTML5 File API before transfer.
  • TImageValidator — extends TFileValidator with Min/MaxImageWidth, Min/MaxImageHeight, and a readable-image check.
  • TFileUpload — new Accept and Capture properties rendering the HTML5 accept/capture attributes (advisory; inherited by TActiveFileUpload).
  • TActiveFileUpload — new CausesValidation (default true) and ValidationGroup; attached validators now gate the auto-upload client side and the page validates during the upload callback.

Nuances

  • Empty selection is valid — pair with TRequiredFieldValidator to require a file. Files with PHP upload error codes fail validation.
  • Type matching semantics: explicit AllowedFileExtensions/AllowedFileTypes are AND checks; when both are empty the restrictions derive from the target's Accept value with match-any-token (OR) semantics, mirroring the browser file picker.
  • MaxFileSize=0 (default) falls back to the target's TFileUpload::MaxFileSize (1 MB default), so a size limit is always enforced — consistent with PHP's own MAX_FILE_SIZE handling.
  • Unverifiable server checks pass, except images: missing fileinfo, unknown extensions, or no local file pass CheckExtensionMimeType; TImageValidator instead fails closed on any file getimagesize() cannot read.
  • Image validation is header-level by design (no GD): a valid-header/garbage-body file passes server side; the browser's full decode catches it client side.
  • Client image dimensions decode asynchronously (Prado client validation is synchronous): dimensions cache on change, undecoded files pass, the validator re-validates when decoding completes. A submit that outruns the decode posts back and the authoritative server check catches it.
  • No changes to TBaseValidator::$_clientClass or the getRawValidationValue() switches — the JS validators read control.files directly, so TRequiredFieldValidator behavior on file inputs is unchanged.
  • {files} ErrorMessage token is replaced with the invalid file names (HTML-encoded server side, textContent client side); client options keep the raw token for client-side substitution.

⚠️ BC break: TActiveFileUpload

CausesValidation defaults to true, so uploads now validate. Previously, validators attached to a TActiveFileUpload were effectively inert (the auto-upload bypassed client validation and OnFileUpload was raised without page validation). Now: the client gate skips the iframe upload while the selection is invalid, and $page->validate(ValidationGroup) runs in raiseCallbackEvent() before OnFileUpload — so TPage::getIsValid() can be false in existing handlers, and with the default empty ValidationGroup all default-group validators of the page validate during the upload callback. Set CausesValidation=false to restore the old behavior, or assign a dedicated ValidationGroup to scope it. Related timing note: validation must happen during the upload callback — the selection never persists to a later postback (successful uploads clear the input and temp files are removed at callback end), and the status icons reflect transfer status only; validation feedback belongs to the OnFileUpload handler.

Tests & docs

70 PHPUnit tests, 40 vitest tests, and 11 Playwright tests (green on Chromium, Firefox, and WebKit; real PNG fixtures generated by tests/playwright/validators/png.js). New error code filevalidator_fileupload_required; classes.php updated; agents/ knowledge files added/updated for all touched classes.

…t and capture, TActiveFileUpload causes validation, and has validation group. unit and functional tests
@belisoful
belisoful marked this pull request as ready for review August 26, 2026 22:18
@belisoful
belisoful marked this pull request as draft August 26, 2026 22:18
@belisoful
belisoful marked this pull request as ready for review August 26, 2026 22:24
@ctrlaltca
ctrlaltca merged commit 79d679a into pradosoft:master Aug 27, 2026
17 checks passed
@belisoful
belisoful deleted the 636-file-validation branch August 27, 2026 06:53
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.

Feature request: File validator

2 participants