Introduce UploadStashFile hook, improve API handling of stash errors
UploadBase:
* Introduce a new method, tryStashFile(), as a replacement for the
now-soft-deprecated stashFile(). The method runs the new hook and
returns a Status object, with an error (if the hook returned an
error) or a value (if it didn't).
* Introduce a new hook, UploadStashFile, allowing extensions to
prevent a file from being stashed. Note that code in extensions
which has not been updated for MediaWiki 1.28 may still call
stashFile() directly, and therefore not call this hook. For
important checks (not just for UI), extension authors should use
UploadVerifyFile or UploadVerifyUpload hooks.
* Extract common code of tryStashFile() and stashFile() to
a new protected method doStashFile().
SpecialUpload:
* Use tryStashFile() when stashing a file after a warning or
"recoverable error" was encountered.
ApiUpload:
* Refactor stashing code so that error handling only happens in one
place, not four different ones. Use Status objects rather than
exception throwing/catching for control flow.
* Simplify the error messages slightly (error codes are unchanged).
Produce better ones by always using handleStashException().
'stashfailed' is now always at root (not nested inside 'warnings'),
behaving the same as 'filekey' does on success.
* Use tryStashFile() when stashing. Handle errors so as to allow
custom API results passed via ApiMessage to be preserved.
Some API result changes for different requests are shown below.
api.php?action=upload&format=json&filename=good.png&file=...&stash=1
Before:
{
"error": {
"code": "stashfilestorage",
"info": "Could not store upload in the stash: Stashing temporary file failed: UploadStashFileException Error storing file in '/tmp/phpB32SRT': Could not create directory \"mwstore://local-backend/local-temp/3/3a\".",
"*": "See http://localhost:3080/w/api.php for API usage"
}
}
After:
{
"error": {
"code": "stashfilestorage",
"info": "Could not store upload in the stash: Error storing file in '/tmp/phpB32SRT': Could not create directory \"mwstore://local-backend/local-temp/3/3a\".",
"*": "See http://localhost:3080/w/api.php for API usage"
}
}
api.php?action=upload&format=json&filename=[bad].png&file=...
Before:
{
"upload": {
"result": "Warning",
"warnings": {
"badfilename": "-bad-.png",
"stashfailed": "Stashing temporary file failed: UploadStashFileException Error storing file in '/tmp/phpB32SRT': Could not create directory \"mwstore://local-backend/local-temp/3/3a\"."
}
}
}
After:
{
"upload": {
"result": "Warning",
"stashfailed": "Could not store upload in the stash: Error storing file in '/tmp/phpB32SRT': Could not create directory \"mwstore://local-backend/local-temp/3/3a\"."
"warnings": {
"badfilename": "-bad-.png",
}
}
}
Bug: T140521
Change-Id: I2f574b355cd33b2e9fa7ff8e1793503b257cce65