/** * Pre-save transform helper function * * @param $text string * @param $user User * * @return string */ private function pstPass2($text, $user) { global $wgContLang; # Note: This is the timestamp saved as hardcoded wikitext to # the database, we use $wgContLang here in order to give # everyone the same signature and use the default one rather # than the one selected in each user's preferences. # (see also bug 12815) $ts = $this->mOptions->getTimestamp(); $timestamp = MWTimestamp::getLocalInstance($ts); $ts = $timestamp->format('YmdHis'); $tzMsg = $timestamp->format('T'); # might vary on DST changeover! # Allow translation of timezones through wiki. format() can return # whatever crap the system uses, localised or not, so we cannot # ship premade translations. $key = 'timezone-' . strtolower(trim($tzMsg)); $msg = wfMessage($key)->inContentLanguage(); if ($msg->exists()) { $tzMsg = $msg->text(); } $d = $wgContLang->timeanddate($ts, false, false) . " ({$tzMsg})"; # Variable replacement # Because mOutputType is OT_WIKI, this will only process {{subst:xxx}} type tags $text = $this->replaceVariables($text); # This works almost by chance, as the replaceVariables are done before the getUserSig(), # which may corrupt this parser instance via its wfMessage()->text() call- # Signatures $sigText = $this->getUserSig($user); $text = strtr($text, array('~~~~~' => $d, '~~~~' => "{$sigText} {$d}", '~~~' => $sigText)); # Context links ("pipe tricks"): [[|name]] and [[name (context)|]] $tc = '[' . Title::legalChars() . ']'; $nc = '[ _0-9A-Za-z\\x80-\\xff-]'; # Namespaces can use non-ascii! $p1 = "/\\[\\[(:?{$nc}+:|:|)({$tc}+?)( ?\\({$tc}+\\))\\|]]/"; # [[ns:page (context)|]] $p4 = "/\\[\\[(:?{$nc}+:|:|)({$tc}+?)( ?({$tc}+))\\|]]/"; # [[ns:page(context)|]] (double-width brackets, added in r40257) $p3 = "/\\[\\[(:?{$nc}+:|:|)({$tc}+?)( ?\\({$tc}+\\)|)((?:, |,){$tc}+|)\\|]]/"; # [[ns:page (context), context|]] (using either single or double-width comma) $p2 = "/\\[\\[\\|({$tc}+)]]/"; # [[|page]] (reverse pipe trick: add context from page title) # try $p1 first, to turn "[[A, B (C)|]]" into "[[A, B (C)|A, B]]" $text = preg_replace($p1, '[[\\1\\2\\3|\\2]]', $text); $text = preg_replace($p4, '[[\\1\\2\\3|\\2]]', $text); $text = preg_replace($p3, '[[\\1\\2\\3\\4|\\2]]', $text); $t = $this->mTitle->getText(); $m = array(); if (preg_match("/^({$nc}+:|){$tc}+?( \\({$tc}+\\))\$/", $t, $m)) { $text = preg_replace($p2, "[[{$m['1']}\\1{$m['2']}|\\1]]", $text); } elseif (preg_match("/^({$nc}+:|){$tc}+?(, {$tc}+|)\$/", $t, $m) && "{$m['1']}{$m['2']}" != '') { $text = preg_replace($p2, "[[{$m['1']}\\1{$m['2']}|\\1]]", $text); } else { # if there's no context, don't bother duplicating the title $text = preg_replace($p2, '[[\\1]]', $text); } # Trim trailing whitespace $text = rtrim($text); return $text; }
/** * Attempt to cache PST content and corresponding parser output in passing * * This method can be called when the output was already generated for other * reasons. Parsing should not be done just to call this method, however. * $pstOpts must be that of the user doing the edit preview. If $pOpts does * not match the options of WikiPage::makeParserOptions( 'canonical' ), this * will do nothing. Provided the values are cacheable, they will be stored * in memcached so that final edit submission might make use of them. * * @param Article|WikiPage $page Page title * @param Content $content Proposed page content * @param Content $pstContent The result of preSaveTransform() on $content * @param ParserOutput $pOut The result of getParserOutput() on $pstContent * @param ParserOptions $pstOpts Options for $pstContent (MUST be for prospective author) * @param ParserOptions $pOpts Options for $pOut * @param string $timestamp TS_MW timestamp of parser output generation * @return bool Success */ public static function stashEditFromPreview(Page $page, Content $content, Content $pstContent, ParserOutput $pOut, ParserOptions $pstOpts, ParserOptions $pOpts, $timestamp) { global $wgMemc; // getIsPreview() controls parser function behavior that references things // like user/revision that don't exists yet. The user/text should already // be set correctly by callers, just double check the preview flag. if (!$pOpts->getIsPreview()) { return false; // sanity } elseif ($pOpts->getIsSectionPreview()) { return false; // short-circuit (need the full content) } // PST parser options are for the user (handles signatures, etc...) $user = $pstOpts->getUser(); // Get a key based on the source text, format, and user preferences $key = self::getStashKey($page->getTitle(), $content, $user); // Parser output options must match cannonical options. // Treat some options as matching that are different but don't matter. $canonicalPOpts = $page->makeParserOptions('canonical'); $canonicalPOpts->setIsPreview(true); // force match $canonicalPOpts->setTimestamp($pOpts->getTimestamp()); // force match if (!$pOpts->matches($canonicalPOpts)) { wfDebugLog('StashEdit', "Uncacheable preview output for key '{$key}' (options)."); return false; } // Build a value to cache with a proper TTL list($stashInfo, $ttl) = self::buildStashValue($pstContent, $pOut, $timestamp); if (!$stashInfo) { wfDebugLog('StashEdit', "Uncacheable parser output for key '{$key}' (rev/TTL)."); return false; } $ok = $wgMemc->set($key, $stashInfo, $ttl); if (!$ok) { wfDebugLog('StashEdit', "Failed to cache preview parser output for key '{$key}'."); } else { wfDebugLog('StashEdit', "Cached preview output for key '{$key}'."); } return $ok; }