public function provideTestToString() { $mockToStringObj = $this->getMock('stdClass', ['__toString']); $mockToStringObj->expects($this->any())->method('__toString')->will($this->returnValue('{STRING_OBJ_VAL}')); $requestId = 'requestId=' . WebRequest::getRequestId(); return [[$this->getMockJob(false), 'someCommand ' . $requestId], [$this->getMockJob(['key' => 'val']), 'someCommand key=val ' . $requestId], [$this->getMockJob(['key' => ['inkey' => 'inval']]), 'someCommand key={"inkey":"inval"} ' . $requestId], [$this->getMockJob(['val1']), 'someCommand 0=val1 ' . $requestId], [$this->getMockJob(['val1', 'val2']), 'someCommand 0=val1 1=val2 ' . $requestId], [$this->getMockJob([new stdClass()]), 'someCommand 0=object(stdClass) ' . $requestId], [$this->getMockJob([$mockToStringObj]), 'someCommand 0={STRING_OBJ_VAL} ' . $requestId], [$this->getMockJob(["pages" => ["932737" => [0, "Robert_James_Waller"]], "rootJobSignature" => "45868e99bba89064e4483743ebb9b682ef95c1a7", "rootJobTimestamp" => "20160309110158", "masterPos" => ["file" => "db1023-bin.001288", "pos" => "308257743", "asOfTime" => 1457521464.3814], "triggeredRecursive" => true]), 'someCommand pages={"932737":[0,"Robert_James_Waller"]} ' . 'rootJobSignature=45868e99bba89064e4483743ebb9b682ef95c1a7 ' . 'rootJobTimestamp=20160309110158 masterPos=' . '{"file":"db1023-bin.001288","pos":"308257743","asOfTime":1457521464.3814} ' . 'triggeredRecursive=1 ' . $requestId]]; }
/** * @param string $command * @param Title $title * @param array|bool $params Can not be === true */ public function __construct($command, $title, $params = false) { $this->command = $command; $this->title = $title; $this->params = is_array($params) ? $params : []; // sanity // expensive jobs may set this to true $this->removeDuplicates = false; if (!isset($this->params['requestId'])) { $this->params['requestId'] = WebRequest::getRequestId(); } }
/** * Get a structured representation of an Exception. * * Returns an array of structured data (class, message, code, file, * backtrace) derived from the given exception. The backtrace information * will be redacted as per getRedactedTraceAsArray(). * * @param Exception|Throwable $e * @return array * @since 1.26 */ public static function getStructuredExceptionData($e) { global $wgLogExceptionBacktrace; $data = ['id' => WebRequest::getRequestId(), 'type' => get_class($e), 'file' => $e->getFile(), 'line' => $e->getLine(), 'message' => $e->getMessage(), 'code' => $e->getCode(), 'url' => self::getURL() ?: null]; if ($e instanceof ErrorException && (error_reporting() & $e->getSeverity()) === 0) { // Flag surpressed errors $data['suppressed'] = true; } if ($wgLogExceptionBacktrace) { $data['backtrace'] = self::getRedactedTrace($e); } $previous = $e->getPrevious(); if ($previous !== null) { $data['previous'] = self::getStructuredExceptionData($previous); } return $data; }
/** * Create an error message for the given exception. * * If the exception is a UsageException then * UsageException::getMessageArray() will be called to create the message. * * @param Exception $e * @return array ['code' => 'some string', 'info' => 'some other string'] * @since 1.27 */ protected function errorMessageFromException($e) { if ($e instanceof UsageException) { // User entered incorrect parameters - generate error response $errMessage = $e->getMessageArray(); } else { $config = $this->getConfig(); // Something is seriously wrong if ($e instanceof DBQueryError && !$config->get('ShowSQLErrors')) { $info = 'Database query error'; } else { $info = "Exception Caught: {$e->getMessage()}"; } $errMessage = ['code' => 'internal_api_error_' . get_class($e), 'info' => '[' . WebRequest::getRequestId() . '] ' . $info]; } return $errMessage; }
/** * Get an array containing the variables to be set in mw.config in JavaScript. * * Do not add things here which can be evaluated in ResourceLoaderStartUpModule * - in other words, page-independent/site-wide variables (without state). * You will only be adding bloat to the html page and causing page caches to * have to be purged on configuration changes. * @return array */ public function getJSVars() { global $wgContLang; $curRevisionId = 0; $articleId = 0; $canonicalSpecialPageName = false; # bug 21115 $title = $this->getTitle(); $ns = $title->getNamespace(); $canonicalNamespace = MWNamespace::exists($ns) ? MWNamespace::getCanonicalName($ns) : $title->getNsText(); $sk = $this->getSkin(); // Get the relevant title so that AJAX features can use the correct page name // when making API requests from certain special pages (bug 34972). $relevantTitle = $sk->getRelevantTitle(); $relevantUser = $sk->getRelevantUser(); if ($ns == NS_SPECIAL) { list($canonicalSpecialPageName, ) = SpecialPageFactory::resolveAlias($title->getDBkey()); } elseif ($this->canUseWikiPage()) { $wikiPage = $this->getWikiPage(); $curRevisionId = $wikiPage->getLatest(); $articleId = $wikiPage->getId(); } $lang = $title->getPageViewLanguage(); // Pre-process information $separatorTransTable = $lang->separatorTransformTable(); $separatorTransTable = $separatorTransTable ? $separatorTransTable : []; $compactSeparatorTransTable = [implode("\t", array_keys($separatorTransTable)), implode("\t", $separatorTransTable)]; $digitTransTable = $lang->digitTransformTable(); $digitTransTable = $digitTransTable ? $digitTransTable : []; $compactDigitTransTable = [implode("\t", array_keys($digitTransTable)), implode("\t", $digitTransTable)]; $user = $this->getUser(); $vars = ['wgCanonicalNamespace' => $canonicalNamespace, 'wgCanonicalSpecialPageName' => $canonicalSpecialPageName, 'wgNamespaceNumber' => $title->getNamespace(), 'wgPageName' => $title->getPrefixedDBkey(), 'wgTitle' => $title->getText(), 'wgCurRevisionId' => $curRevisionId, 'wgRevisionId' => (int) $this->getRevisionId(), 'wgArticleId' => $articleId, 'wgIsArticle' => $this->isArticle(), 'wgIsRedirect' => $title->isRedirect(), 'wgAction' => Action::getActionName($this->getContext()), 'wgUserName' => $user->isAnon() ? null : $user->getName(), 'wgUserGroups' => $user->getEffectiveGroups(), 'wgCategories' => $this->getCategories(), 'wgBreakFrames' => $this->getFrameOptions() == 'DENY', 'wgPageContentLanguage' => $lang->getCode(), 'wgPageContentModel' => $title->getContentModel(), 'wgSeparatorTransformTable' => $compactSeparatorTransTable, 'wgDigitTransformTable' => $compactDigitTransTable, 'wgDefaultDateFormat' => $lang->getDefaultDateFormat(), 'wgMonthNames' => $lang->getMonthNamesArray(), 'wgMonthNamesShort' => $lang->getMonthAbbreviationsArray(), 'wgRelevantPageName' => $relevantTitle->getPrefixedDBkey(), 'wgRelevantArticleId' => $relevantTitle->getArticleID(), 'wgRequestId' => WebRequest::getRequestId()]; if ($user->isLoggedIn()) { $vars['wgUserId'] = $user->getId(); $vars['wgUserEditCount'] = $user->getEditCount(); $userReg = $user->getRegistration(); $vars['wgUserRegistration'] = $userReg ? wfTimestamp(TS_UNIX, $userReg) * 1000 : null; // Get the revision ID of the oldest new message on the user's talk // page. This can be used for constructing new message alerts on // the client side. $vars['wgUserNewMsgRevisionId'] = $user->getNewMessageRevisionId(); } if ($wgContLang->hasVariants()) { $vars['wgUserVariant'] = $wgContLang->getPreferredVariant(); } // Same test as SkinTemplate $vars['wgIsProbablyEditable'] = $title->quickUserCan('edit', $user) && ($title->exists() || $title->quickUserCan('create', $user)); foreach ($title->getRestrictionTypes() as $type) { $vars['wgRestriction' . ucfirst($type)] = $title->getRestrictions($type); } if ($title->isMainPage()) { $vars['wgIsMainPage'] = true; } if ($this->mRedirectedFrom) { $vars['wgRedirectedFrom'] = $this->mRedirectedFrom->getPrefixedDBkey(); } if ($relevantUser) { $vars['wgRelevantUserName'] = $relevantUser->getName(); } // Allow extensions to add their custom variables to the mw.config map. // Use the 'ResourceLoaderGetConfigVars' hook if the variable is not // page-dependant but site-wide (without state). // Alternatively, you may want to use OutputPage->addJsConfigVars() instead. Hooks::run('MakeGlobalVariablesScript', [&$vars, $this]); // Merge in variables from addJsConfigVars last return array_merge($vars, $this->getJsConfigVars()); }
/** * If $wgShowExceptionDetails is true, return a HTML message with a * backtrace to the error, otherwise show a message to ask to set it to true * to show that information. * * @return string Html to output */ public function getHTML() { global $wgShowExceptionDetails; if ($wgShowExceptionDetails) { return '<p>' . nl2br(htmlspecialchars(MWExceptionHandler::getLogMessage($this))) . '</p><p>Backtrace:</p><p>' . nl2br(htmlspecialchars(MWExceptionHandler::getRedactedTraceAsString($this))) . "</p>\n"; } else { $logId = WebRequest::getRequestId(); $type = get_class($this); return "<div class=\"errorbox\">" . '[' . $logId . '] ' . gmdate('Y-m-d H:i:s') . ": " . $this->msg("internalerror-fatal-exception", "Fatal exception of type \$1", $type, $logId, MWExceptionHandler::getURL($this)) . "</div>\n" . "<!-- Set \$wgShowExceptionDetails = true; " . "at the bottom of LocalSettings.php to show detailed " . "debugging information. -->"; } }
/** * @param array $record * @return array */ public function __invoke(array $record) { global $wgVersion; $record['extra'] = array_merge($record['extra'], ['host' => wfHostname(), 'wiki' => wfWikiID(), 'mwversion' => $wgVersion, 'reqId' => \WebRequest::getRequestId()]); return $record; }
/** * If $wgShowExceptionDetails is true, return a HTML message with a * backtrace to the error, otherwise show a message to ask to set it to true * to show that information. * * @param Exception|Throwable $e * @return string Html to output */ public static function getHTML($e) { if (self::showBackTrace($e)) { $html = "<div class=\"errorbox\"><p>" . nl2br(htmlspecialchars(MWExceptionHandler::getLogMessage($e))) . '</p><p>Backtrace:</p><p>' . nl2br(htmlspecialchars(MWExceptionHandler::getRedactedTraceAsString($e))) . "</p></div>\n"; } else { $logId = WebRequest::getRequestId(); $html = "<div class=\"errorbox\">" . '[' . $logId . '] ' . gmdate('Y-m-d H:i:s') . ": " . self::msg("internalerror-fatal-exception", "Fatal exception of type \$1", get_class($e), $logId, MWExceptionHandler::getURL()) . "</div>\n" . "<!-- Set \$wgShowExceptionDetails = true; " . "at the bottom of LocalSettings.php to show detailed " . "debugging information. -->"; } return $html; }