diff --git a/src/aphront/httpparametertype/AphrontFileHTTPParameterType.php b/src/aphront/httpparametertype/AphrontFileHTTPParameterType.php --- a/src/aphront/httpparametertype/AphrontFileHTTPParameterType.php +++ b/src/aphront/httpparametertype/AphrontFileHTTPParameterType.php @@ -7,10 +7,17 @@ return $key.'_raw'; } + private function getDefaultKey($key) { + return $key.'_default'; + } + protected function getParameterExists(AphrontRequest $request, $key) { $file_key = $this->getFileKey($key); + $default_key = $this->getDefaultKey($key); + return $request->getExists($key) || - $request->getFileExists($file_key); + $request->getFileExists($file_key) || + $request->getExists($default_key); } protected function getParameterValue(AphrontRequest $request, $key) { @@ -27,8 +34,9 @@ // this code around as a fallback if the client-side JS goes awry. $file_key = $this->getFileKey($key); + $default_key = $this->getDefaultKey($key); if (!$request->getFileExists($file_key)) { - return null; + return $request->getStr($default_key); } $viewer = $this->getViewer(); diff --git a/src/view/form/control/PHUIFormFileControl.php b/src/view/form/control/PHUIFormFileControl.php --- a/src/view/form/control/PHUIFormFileControl.php +++ b/src/view/form/control/PHUIFormFileControl.php @@ -30,15 +30,47 @@ 'chunkThreshold' => PhabricatorFileStorageEngine::getChunkThreshold(), )); - return phutil_tag( - 'input', - array( - 'type' => 'file', - 'multiple' => $this->getAllowMultiple() ? 'multiple' : null, - 'name' => $this->getName().'.raw', - 'id' => $file_id, - 'disabled' => $this->getDisabled() ? 'disabled' : null, - )); + + // If the control has a value, add a hidden input which submits it as a + // default. This allows the file control to mean "don't change anything", + // instead of "remove the file", if the user submits the form without + // touching it. + + // This also allows the input to "hold" the value of an uploaded file if + // there is another error in the form: when you submit the form but are + // stopped because of an unrelated error, submitting it again will keep + // the value around (if you don't upload a new file) instead of requiring + // you to pick the file again. + + // TODO: This works alright, but is a bit of a hack, and the UI should + // provide the user better feedback about whether the state of the control + // is "keep the value the same" or "remove the value", and about whether + // or not the control is "holding" a value from a previous submission. + + $default_input = null; + $default_value = $this->getValue(); + if ($default_value !== null) { + $default_input = phutil_tag( + 'input', + array( + 'type' => 'hidden', + 'name' => $this->getName().'_default', + 'value' => $default_value, + )); + } + + return array( + phutil_tag( + 'input', + array( + 'type' => 'file', + 'multiple' => $this->getAllowMultiple() ? 'multiple' : null, + 'name' => $this->getName().'_raw', + 'id' => $file_id, + 'disabled' => $this->getDisabled() ? 'disabled' : null, + )), + $default_input, + ); } }