Problem/Motivation
file_save_upload() extracts uploaded files for a form field, loops over them, and returns a mix of a file entity, FALSE, an array, or NULL, depending on the $delta argument and number of files. This return shape forces callers to check multiple types and gives no structured way to read per-file errors.
It also calls \Drupal::messenger() directly for validation and operational failures, mixing upload logic with message display.
Steps to reproduce
Proposed resolution
Add a new service that extracts uploaded files with UploadedFilesExtractor, calls FileUploadHandler::handleFileUpload() for each one, and uses the memory cache service from a prior issue. It always returns an array of FileUploadResult objects, one per uploaded file. Each result carries its own violations and errors, from the getViolations()/getErrors() split in #3619417: Return FileExistsException and FileException as data on FileUploadResult, so the service has nothing left to report through Messenger. It returns data only; the caller decides whether and how to surface a message.
Deprecate file_save_upload() and reimplement it as a wrapper around the new service that reads each result's violations and errors and adds the same \Drupal::messenger() calls it adds today, so its external behavior stays the same until callers migrate.
Add Kernel tests for new proposed methods upload() and uploadMultiple(), following the pattern in FileUploadHandlerTest. Update SaveUploadTest's assertions to match file_save_upload()'s new BC-shim behavior. Investigate where we can use Kernel tests instead of functional tests.
Comments
Comment #2
kim.pepperUpdated IS
Comment #3
kim.pepperComment #4
kim.pepperComment #5
kim.pepperThis was fixed in #3375423: Deprecate file_managed_file_save_upload(), file_save_upload() and _file_save_upload_from_form() and replace with a service