/** * Stash the file and add the file key, or error information if it fails, to the data. * * @param string $failureMode What to do on failure to stash: * - When 'critical', use dieStatus() to produce an error response and throw an exception. * Use this when stashing the file was the primary purpose of the API request. * - When 'optional', only add a 'stashfailed' key to the data and return null. * Use this when some error happened for a non-stash upload and we're stashing the file * only to save the client the trouble of re-uploading it. * @param array &$data API result to which to add the information * @return string|null File key */ private function performStash($failureMode, &$data = null) { $isPartial = (bool) $this->mParams['chunk']; try { $status = $this->mUpload->tryStashFile($this->getUser(), $isPartial); if ($status->isGood() && !$status->getValue()) { // Not actually a 'good' status... $status->fatal(new ApiRawMessage('Invalid stashed file', 'stashfailed')); } } catch (Exception $e) { $debugMessage = 'Stashing temporary file failed: ' . get_class($e) . ' ' . $e->getMessage(); wfDebug(__METHOD__ . ' ' . $debugMessage . "\n"); $status = Status::newFatal(new ApiRawMessage($e->getMessage(), 'stashfailed')); } if ($status->isGood()) { $stashFile = $status->getValue(); $data['filekey'] = $stashFile->getFileKey(); // Backwards compatibility $data['sessionkey'] = $data['filekey']; return $data['filekey']; } if ($status->getMessage()->getKey() === 'uploadstash-exception') { // The exceptions thrown by upload stash code and pretty silly and UploadBase returns poor // Statuses for it. Just extract the exception details and parse them ourselves. list($exceptionType, $message) = $status->getMessage()->getParams(); $debugMessage = 'Stashing temporary file failed: ' . $exceptionType . ' ' . $message; wfDebug(__METHOD__ . ' ' . $debugMessage . "\n"); list($msg, $code) = $this->handleStashException($exceptionType, $message); $status = Status::newFatal(new ApiRawMessage($msg, $code)); } // Bad status if ($failureMode !== 'optional') { $this->dieStatus($status); } else { list($code, $msg) = $this->getErrorFromStatus($status); $data['stashfailed'] = $msg; return null; } }
/** * Stashes the upload, shows the main form, but adds a "continue anyway button". * Also checks whether there are actually warnings to display. * * @param array $warnings * @return bool True if warnings were displayed, false if there are no * warnings and it should continue processing */ protected function showUploadWarning($warnings) { # If there are no warnings, or warnings we can ignore, return early. # mDestWarningAck is set when some javascript has shown the warning # to the user. mForReUpload is set when the user clicks the "upload a # new version" link. if (!$warnings || count($warnings) == 1 && isset($warnings['exists']) && ($this->mDestWarningAck || $this->mForReUpload)) { return false; } $stashStatus = $this->mUpload->tryStashFile($this->getUser()); if ($stashStatus->isGood()) { $sessionKey = $stashStatus->getValue()->getFileKey(); } else { $sessionKey = null; // TODO Add a warning message about the failure to stash here? } // Add styles for the warning, reused from the live preview $this->getOutput()->addModuleStyles('mediawiki.special.upload.styles'); $linkRenderer = $this->getLinkRenderer(); $warningHtml = '<h2>' . $this->msg('uploadwarning')->escaped() . "</h2>\n" . '<div class="mw-destfile-warning"><ul>'; foreach ($warnings as $warning => $args) { if ($warning == 'badfilename') { $this->mDesiredDestName = Title::makeTitle(NS_FILE, $args)->getText(); } if ($warning == 'exists') { $msg = "\t<li>" . self::getExistsWarning($args) . "</li>\n"; } elseif ($warning == 'no-change') { $file = $args; $filename = $file->getTitle()->getPrefixedText(); $msg = "\t<li>" . wfMessage('fileexists-no-change', $filename)->parse() . "</li>\n"; } elseif ($warning == 'duplicate-version') { $file = $args[0]; $count = count($args); $filename = $file->getTitle()->getPrefixedText(); $message = wfMessage('fileexists-duplicate-version')->params($filename)->numParams($count); $msg = "\t<li>" . $message->parse() . "</li>\n"; } elseif ($warning == 'was-deleted') { # If the file existed before and was deleted, warn the user of this $ltitle = SpecialPage::getTitleFor('Log'); $llink = $linkRenderer->makeKnownLink($ltitle, wfMessage('deletionlog')->text(), [], ['type' => 'delete', 'page' => Title::makeTitle(NS_FILE, $args)->getPrefixedText()]); $msg = "\t<li>" . wfMessage('filewasdeleted')->rawParams($llink)->parse() . "</li>\n"; } elseif ($warning == 'duplicate') { $msg = $this->getDupeWarning($args); } elseif ($warning == 'duplicate-archive') { if ($args === '') { $msg = "\t<li>" . $this->msg('file-deleted-duplicate-notitle')->parse() . "</li>\n"; } else { $msg = "\t<li>" . $this->msg('file-deleted-duplicate', Title::makeTitle(NS_FILE, $args)->getPrefixedText())->parse() . "</li>\n"; } } else { if ($args === true) { $args = []; } elseif (!is_array($args)) { $args = [$args]; } $msg = "\t<li>" . $this->msg($warning, $args)->parse() . "</li>\n"; } $warningHtml .= $msg; } $warningHtml .= "</ul></div>\n"; $warningHtml .= $this->msg('uploadwarning-text')->parseAsBlock(); $form = $this->getUploadForm($warningHtml, $sessionKey, true); $form->setSubmitText($this->msg('upload-tryagain')->text()); $form->addButton(['name' => 'wpUploadIgnoreWarning', 'value' => $this->msg('ignorewarning')->text()]); $form->addButton(['name' => 'wpCancelUpload', 'value' => $this->msg('reuploaddesc')->text()]); $this->showUploadForm($form); # Indicate that we showed a form return true; }