function MagicNoNumberedHeadingsParserBeforeInternalParse($parser, $text, $stripState) { if (MagicWord::get('MAG_NONUMBEREDHEADINGS')->matchAndRemove($text)) { $parser->mOptions->mNumberHeadings = FALSE; } return true; }
/** * * Process the MagicWords * * @param Parser $parser * @param string $text * @param StripState $stripState * @return boolean */ function onParserBeforeInternalParse(&$parser, &$text, &$stripState) { $config = \PageAttachment\Configuration\StaticConfiguration::getInstance(); $pageAttachmentDefinedMagicWord = false; $allowAttachments = false; $magicWord1 = \MagicWord::get(self::MagicWord_NOATTACHMENTS); if ($magicWord1->matchAndRemove($text)) { $pageAttachmentDefinedMagicWord = true; $allowAttachments = false; } $magicWord2 = \MagicWord::get(self::MagicWord_ALLOWATTACHMENTS); if ($magicWord2->matchAndRemove($text)) { $pageAttachmentDefinedMagicWord = true; $allowAttachments = true; } if ($pageAttachmentDefinedMagicWord == true) { if ($allowAttachments == true) { if ($config->isAllowAttachmentsUsingMagicWord()) { $parser->mOutput->addHeadItem('<script> pageAttachment__ALLOW_ATTACHMENTS__ = true; </script>'); } } else { if ($config->isDisallowAttachmentsUsingMagicWord()) { $parser->mOutput->addHeadItem('<script> pageAttachment__ALLOW_ATTACHMENTS__ = false; </script>'); } } } return true; }
/** * Hook entry for removing the magic words from displayed text */ public static function onInternalParseBeforeLinks(&$parser, &$text, &$strip_state) { global $wgRTEParserEnabled; if (empty($wgRTEParserEnabled)) { MagicWord::get('CATEXHIBITION_DISABLED')->matchAndRemove($text); } return true; }
function PSINoTocNumParserBeforeInternalParse($parser, $text, $stripState) { if (MagicWord::get(MAG_NOTOCNUM)->matchAndRemove($text)) { global $wgOut; $wgOut->addScript(' <style type="text/css"><!-- .tocnumber {display:none;} --></style> '); } return true; }
/** * Entry for removing the magic words from displayed text */ public static function onInternalParseBeforeLinks(&$parser, &$text, &$strip_state) { wfProfileIn(__METHOD__); if (empty(F::app()->wg->RTEParserEnabled)) { $oMagicWord = MagicWord::get('RELATEDVIDEOS_POSITION'); $text = $oMagicWord->replace('<span data-placeholder="RelatedVideosModule"></span>', $text, 1); $text = $oMagicWord->replace('', $text); } wfProfileOut(__METHOD__); return true; }
function run() { if (!$this->redirTitle) { $this->setLastError('Invalid title'); return false; } $targetRev = Revision::newFromTitle($this->title); if (!$targetRev) { wfDebug(__METHOD__ . ": target redirect already deleted, ignoring\n"); return true; } $text = $targetRev->getText(); $currentDest = Title::newFromRedirect($text); if (!$currentDest || !$currentDest->equals($this->redirTitle)) { wfDebug(__METHOD__ . ": Redirect has changed since the job was queued\n"); return true; } # Check for a suppression tag (used e.g. in periodically archived discussions) $mw = MagicWord::get('staticredirect'); if ($mw->match($text)) { wfDebug(__METHOD__ . ": skipping: suppressed with __STATICREDIRECT__\n"); return true; } # Find the current final destination $newTitle = self::getFinalDestination($this->redirTitle); if (!$newTitle) { wfDebug(__METHOD__ . ": skipping: single redirect, circular redirect or invalid redirect destination\n"); return true; } if ($newTitle->equals($this->redirTitle)) { # The redirect is already right, no need to change it # This can happen if the page was moved back (say after vandalism) wfDebug(__METHOD__ . ": skipping, already good\n"); } # Preserve fragment (bug 14904) $newTitle = Title::makeTitle($newTitle->getNamespace(), $newTitle->getDBkey(), $currentDest->getFragment()); # Fix the text # Remember that redirect pages can have categories, templates, etc., # so the regex has to be fairly general $newText = preg_replace('/ \\[ \\[ [^\\]]* \\] \\] /x', '[[' . $newTitle->getFullText() . ']]', $text, 1); if ($newText === $text) { $this->setLastError('Text unchanged???'); return false; } # Save it global $wgUser; $oldUser = $wgUser; $wgUser = $this->getUser(); $article = new Article($this->title); $reason = wfMsgForContent('double-redirect-fixed-' . $this->reason, $this->redirTitle->getPrefixedText(), $newTitle->getPrefixedText()); $article->doEdit($newText, $reason, EDIT_UPDATE | EDIT_SUPPRESS_RC); $wgUser = $oldUser; return true; }
public function execute() { $this->batchsize = $this->getOption( 'batchsize', 50 ); $variableIDs = MagicWord::getVariableIDs(); foreach ( $variableIDs as $id ) { $magic = MagicWord::get( $id ); foreach ( $magic->getSynonyms() as $synonym ) { $this->processSynonym( $synonym ); } } $this->output( "All done\n" ); }
/** * Static initializer. */ public static function init() { $iExQuoteMW = MagicWord::get( 'wc_initial_exterior_quote' ); $fExQuoteMW = MagicWord::get( 'wc_final_exterior_quote' ); $iInQuoteMW = MagicWord::get( 'wc_initial_interior_quote' ); $fInQuoteMW = MagicWord::get( 'wc_final_interior_quote' ); $iExQuotes = implode( $iExQuoteMW->getSynonyms() ); $fExQuotes = implode( $fExQuoteMW->getSynonyms() ); $iInQuotes = implode( $iInQuoteMW->getSynonyms() ); $fInQuotes = implode( $fInQuoteMW->getSynonyms() ); self::$patternExternal = '/(^|[\p{Ps}\p{Zs}\p{Pd}\p{Pi}\'])[' . $iExQuotes . '](.*?)[' . $fExQuotes . ']($|[\p{Pe}\p{Zs}\.,;:?!\p{Pd}\p{Pf}\'])/usS'; self::$patternInternal = '/(^|[\p{Ps}\p{Zs}\p{Pd}\p{Pi}"])[' . $iInQuotes . '](.*?)[' . $fInQuotes . ']($|[\p{Pe}\p{Zs}\.,;:?!\p{Pd}\p{Pf}"])/usS'; }
/** * Remove relevant SMW magic words from the given text and return * an array of the names of all discovered magic words. Moreover, * store this array in the current parser output, using the variable * mSMWMagicWords. */ public static function stripMagicWords(&$text, Parser $parser) { $words = array(); $mw = MagicWord::get('SMW_NOFACTBOX'); if ($mw->matchAndRemove($text)) { $words[] = 'SMW_NOFACTBOX'; } $mw = MagicWord::get('SMW_SHOWFACTBOX'); if ($mw->matchAndRemove($text)) { $words[] = 'SMW_SHOWFACTBOX'; } $output = $parser->getOutput(); $output->mSMWMagicWords = $words; return $words; }
/** * @param Title $title * @param WikiPage $article * @return bool */ public function onArticleFromTitle(Title &$title, &$article) { if ($title->exists() && $title->getNamespace() != NS_FILE && $title->getNamespace() != NS_CATEGORY) { $key = $this->generateCacheKey($title->getArticleId()); $this->switches = $this->app->wg->memc->get($key); if (empty($this->switches)) { $article = F::build('Article', array($title)); $this->switches = array(); foreach ($this->magicWords as $wordID) { $magicWord = MagicWord::get($wordID); $this->switches[$wordID] = 0 < $magicWord->match($article->getRawText()); } $this->app->wg->memc->set($key, $this->switches, self::CACHE_DURATION); } $this->process(); } return true; }
/** * Returns a WikitextContent object representing a redirect to the given destination page. * * @param Title $destination The page to redirect to. * @param string $text Text to include in the redirect, if possible. * * @return Content * * @see ContentHandler::makeRedirectContent */ public function makeRedirectContent(Title $destination, $text = '') { $optionalColon = ''; if ($destination->getNamespace() == NS_CATEGORY) { $optionalColon = ':'; } else { $iw = $destination->getInterwiki(); if ($iw && Language::fetchLanguageName($iw, null, 'mw')) { $optionalColon = ':'; } } $mwRedir = MagicWord::get('redirect'); $redirectText = $mwRedir->getSynonym(0) . ' [[' . $optionalColon . $destination->getFullText() . ']]'; if ($text != '') { $redirectText .= "\n" . $text; } return new WikitextContent($redirectText); }
/** * @param Title $title * @param WikiPage $article * @return bool */ public static function onArticleFromTitle(Title &$title, &$article) { global $wgLandingPagesAsContentMagicWords; $app = F::app(); if ($title->exists() && $title->getNamespace() != NS_FILE && $title->getNamespace() != NS_CATEGORY) { $key = self::generateCacheKey($title->getArticleId()); self::$switches = $app->wg->memc->get($key); if (empty(self::$switches)) { $article = new Article($title); self::$switches = array(); $magicWords = array_keys($wgLandingPagesAsContentMagicWords); foreach ($magicWords as $wordID) { $magicWord = MagicWord::get($wordID); self::$switches[$wordID] = 0 < $magicWord->match($article->getRawText()); } $app->wg->memc->set($key, self::$switches, self::CACHE_DURATION); } self::process(); } return true; }
function switchHook(&$parser) { $args = func_get_args(); array_shift($args); $value = trim(array_shift($args)); $found = false; $parts = null; $default = null; foreach ($args as $arg) { $parts = array_map('trim', explode('=', $arg, 2)); if (count($parts) == 2) { if ($found || $parts[0] == $value) { return $parts[1]; } else { $mwDefault =& MagicWord::get('default'); if ($mwDefault->matchStartAndRemove($parts[0])) { $default = $parts[1]; } # else wrong case, continue } } elseif (count($parts) == 1) { # Multiple input, single output # If the value matches, set a flag and continue if ($parts[0] == $value) { $found = true; } } # else RAM corruption due to cosmic ray? } # Default case # Check if the last item had no = sign, thus specifying the default case if (count($parts) == 1) { return $parts[0]; } elseif (!is_null($default)) { return $default; } else { return ''; } }
static function getDoubleUnderscoreRegex() { if ( WOMMagicWordParser::$mwa === null ) { WOMMagicWordParser::$mwa = MagicWord::getDoubleUnderscoreArray(); foreach ( WOMMagicWordParser::$mwa->names as $name ) { $magic = MagicWord::get( $name ); $case = intval( $magic->isCaseSensitive() ); foreach ( $magic->getSynonyms() as $i => $syn ) { $group = '(' . preg_quote( $syn, '/' ) . ')'; if ( WOMMagicWordParser::$underscores[$case] === '' ) { WOMMagicWordParser::$underscores[$case] = $group; } else { WOMMagicWordParser::$underscores[$case] .= '|' . $group; } } } if ( WOMMagicWordParser::$underscores[0] !== '' ) { WOMMagicWordParser::$underscores[0] = "/^(" . WOMMagicWordParser::$underscores[0] . ")/i"; } if ( WOMMagicWordParser::$underscores[1] !== '' ) { WOMMagicWordParser::$underscores[1] = "/^(" . WOMMagicWordParser::$underscores[1] . ")/"; } } return WOMMagicWordParser::$underscores; }
function leaveTrace($reason, $oldTitle, $newTitle) { $this->dieIfHistorical(); // Create redirect text $mwRedir = MagicWord::get('redirect'); $redirectText = $mwRedir->getSynonym(0) . ' [[' . $this->title()->getPrefixedText() . "]]\n"; // Make the article edit. $traceTitle = Threads::newThreadTitle($this->subject(), new Article($oldTitle)); $redirectArticle = new Article($traceTitle); $redirectArticle->doEdit($redirectText, $reason, EDIT_NEW | EDIT_SUPPRESS_RC); // Add the trace thread to the tracking table. $thread = Thread::create($redirectArticle, new Article($oldTitle), null, Threads::TYPE_MOVED, $this->subject()); $thread->setSortkey($this->sortkey()); $thread->save(); }
/** * Move page to non-existing title. * @param Title &$nt the new Title */ private function moveToNewTitle(&$nt, $reason = '') { global $wgUseSquid; $fname = 'MovePageForm::moveToNewTitle'; $comment = wfMsgForContent('1movedto2', $this->getPrefixedText(), $nt->getPrefixedText()); if ($reason) { $comment .= ": {$reason}"; } $newid = $nt->getArticleID(); $oldid = $this->getArticleID(); $dbw = wfGetDB(DB_MASTER); $now = $dbw->timestamp(); $linkCache =& LinkCache::singleton(); # Save a null revision in the page's history notifying of the move $nullRevision = Revision::newNullRevision($dbw, $oldid, $comment, true); $nullRevId = $nullRevision->insertOn($dbw); # Rename cur entry $dbw->update('page', array('page_touched' => $now, 'page_namespace' => $nt->getNamespace(), 'page_title' => $nt->getDBkey(), 'page_latest' => $nullRevId), array('page_id' => $oldid), $fname); $linkCache->clearLink($nt->getPrefixedDBkey()); # Insert redirect $mwRedir = MagicWord::get('redirect'); $redirectText = $mwRedir->getSynonym(0) . ' [[' . $nt->getPrefixedText() . "]]\n"; $redirectArticle = new Article($this); $newid = $redirectArticle->insertOn($dbw); $redirectRevision = new Revision(array('page' => $newid, 'comment' => $comment, 'text' => $redirectText)); $redirectRevision->insertOn($dbw); $redirectArticle->updateRevisionOn($dbw, $redirectRevision, 0); $linkCache->clearLink($this->getPrefixedDBkey()); # Log the move $log = new LogPage('move'); $log->addEntry('move', $this, $reason, array(1 => $nt->getPrefixedText())); # Purge caches as per article creation Article::onArticleCreate($nt); # Record the just-created redirect's linking to the page $dbw->insert('pagelinks', array('pl_from' => $newid, 'pl_namespace' => $nt->getNamespace(), 'pl_title' => $nt->getDBkey()), $fname); # Purge old title from squid # The new title, and links to the new title, are purged in Article::onArticleCreate() $this->purgeSquid(); }
/** * Strips the magic words added by Live Translate from the page text. * * @since 0.6 * * @param Parser &$parser * @param string &$text * * @return true */ public static function stripMagicWords(Parser &$parser, &$text) { global $egLiveTranslateMagicWords; $mw = MagicWord::get('LT_NOTRANSLATIONCONTROL'); if ($mw->matchAndRemove($text)) { $egLiveTranslateMagicWords[] = 'LT_NOTRANSLATIONCONTROL'; } $mw = MagicWord::get('LT_SHOWTRANSLATIONCONTROL'); if ($mw->matchAndRemove($text)) { $egLiveTranslateMagicWords[] = 'LT_SHOWTRANSLATIONCONTROL'; } $po = $parser->getOutput(); $po->mLTMagicWords = $egLiveTranslateMagicWords; return true; }
function merge() { global $wgOut, $wgUser; # Get the titles directly from the IDs, in case the target page params # were spoofed. The queries are done based on the IDs, so it's best to # keep it consistent... $targetTitle = Title::newFromID($this->mTargetID); $destTitle = Title::newFromID($this->mDestID); if (is_null($targetTitle) || is_null($destTitle)) { return false; } // validate these if ($targetTitle->getArticleId() == $destTitle->getArticleId()) { return false; } # Verify that this timestamp is valid # Must be older than the destination page $dbw = wfGetDB(DB_MASTER); # Get timestamp into DB format $this->mTimestamp = $this->mTimestamp ? $dbw->timestamp($this->mTimestamp) : ''; # Max timestamp should be min of destination page $maxtimestamp = $dbw->selectField('revision', 'MIN(rev_timestamp)', array('rev_page' => $this->mDestID), __METHOD__); # Destination page must exist with revisions if (!$maxtimestamp) { $wgOut->addWikiMsg('mergehistory-fail'); return false; } # Get the latest timestamp of the source $lasttimestamp = $dbw->selectField(array('page', 'revision'), 'rev_timestamp', array('page_id' => $this->mTargetID, 'page_latest = rev_id'), __METHOD__); # $this->mTimestamp must be older than $maxtimestamp if ($this->mTimestamp >= $maxtimestamp) { $wgOut->addWikiMsg('mergehistory-fail'); return false; } # Update the revisions if ($this->mTimestamp) { $timewhere = "rev_timestamp <= {$this->mTimestamp}"; $TimestampLimit = wfTimestamp(TS_MW, $this->mTimestamp); } else { $timewhere = "rev_timestamp <= {$maxtimestamp}"; $TimestampLimit = wfTimestamp(TS_MW, $lasttimestamp); } # Do the moving... $dbw->update('revision', array('rev_page' => $this->mDestID), array('rev_page' => $this->mTargetID, $timewhere), __METHOD__); $count = $dbw->affectedRows(); # Make the source page a redirect if no revisions are left $haveRevisions = $dbw->selectField('revision', 'rev_timestamp', array('rev_page' => $this->mTargetID), __METHOD__, array('FOR UPDATE')); if (!$haveRevisions) { if ($this->mComment) { $comment = wfMsgForContent('mergehistory-comment', $targetTitle->getPrefixedText(), $destTitle->getPrefixedText(), $this->mComment); } else { $comment = wfMsgForContent('mergehistory-autocomment', $targetTitle->getPrefixedText(), $destTitle->getPrefixedText()); } $mwRedir = MagicWord::get('redirect'); $redirectText = $mwRedir->getSynonym(0) . ' [[' . $destTitle->getPrefixedText() . "]]\n"; $redirectArticle = new Article($targetTitle); $redirectRevision = new Revision(array('page' => $this->mTargetID, 'comment' => $comment, 'text' => $redirectText)); $redirectRevision->insertOn($dbw); $redirectArticle->updateRevisionOn($dbw, $redirectRevision); # Now, we record the link from the redirect to the new title. # It should have no other outgoing links... $dbw->delete('pagelinks', array('pl_from' => $this->mDestID), __METHOD__); $dbw->insert('pagelinks', array('pl_from' => $this->mDestID, 'pl_namespace' => $destTitle->getNamespace(), 'pl_title' => $destTitle->getDBkey()), __METHOD__); } else { $targetTitle->invalidateCache(); // update histories } $destTitle->invalidateCache(); // update histories # Check if this did anything if (!$count) { $wgOut->addWikiMsg('mergehistory-fail'); return false; } # Update our logs $log = new LogPage('merge'); $log->addEntry('merge', $targetTitle, $this->mComment, array($destTitle->getPrefixedText(), $TimestampLimit)); $wgOut->addHTML(wfMsgExt('mergehistory-success', array('parseinline'), $targetTitle->getPrefixedText(), $destTitle->getPrefixedText(), $count)); wfRunHooks('ArticleMergeComplete', array($targetTitle, $destTitle)); return true; }
function switchObj($parser, $frame, $args) { if (count($args) == 0) { return ''; } $primary = trim($frame->expand(array_shift($args))); $found = false; $default = null; $lastItemHadNoEquals = false; $mwDefault =& MagicWord::get('default'); foreach ($args as $arg) { $bits = $arg->splitArg(); $nameNode = $bits['name']; $index = $bits['index']; $valueNode = $bits['value']; if ($index === '') { # Found "=" $lastItemHadNoEquals = false; $test = trim($frame->expand($nameNode)); if ($found) { # Multiple input match return trim($frame->expand($valueNode)); } else { $test = trim($frame->expand($nameNode)); if ($test == $primary) { # Found a match, return now return trim($frame->expand($valueNode)); } else { if ($mwDefault->matchStartAndRemove($test)) { $default = $valueNode; } # else wrong case, continue } } } else { # Multiple input, single output # If the value matches, set a flag and continue $lastItemHadNoEquals = true; $test = trim($frame->expand($valueNode)); if ($test == $primary) { $found = true; } } } # Default case # Check if the last item had no = sign, thus specifying the default case if ($lastItemHadNoEquals) { return $test; } elseif (!is_null($default)) { return trim($frame->expand($default)); } else { return ''; } }
/** * Renders an image gallery from a text with one line per image. * text labels may be given by using |-style alternative text. E.g. * Image:one.jpg|The number "1" * Image:tree.jpg|A tree * given as text will return the HTML of a gallery with two images, * labeled 'The number "1"' and * 'A tree'. * * @param string $text * @param array $params * @return string HTML */ function renderImageGallery($text, $params) { $ig = new ImageGallery(); $ig->setContextTitle($this->mTitle); $ig->setShowBytes(false); $ig->setShowFilename(false); $ig->setParser($this); $ig->setHideBadImages(); $ig->setAttributes(Sanitizer::validateTagAttributes($params, 'table')); if (isset($params['showfilename'])) { $ig->setShowFilename(true); } else { $ig->setShowFilename(false); } if (isset($params['caption'])) { $caption = $params['caption']; $caption = htmlspecialchars($caption); $caption = $this->replaceInternalLinks($caption); $ig->setCaptionHtml($caption); } if (isset($params['perrow'])) { $ig->setPerRow($params['perrow']); } if (isset($params['widths'])) { $ig->setWidths($params['widths']); } if (isset($params['heights'])) { $ig->setHeights($params['heights']); } wfRunHooks('BeforeParserrenderImageGallery', array(&$this, &$ig)); $lines = StringUtils::explode("\n", $text); foreach ($lines as $line) { # match lines like these: # Image:someimage.jpg|This is some image $matches = array(); preg_match("/^([^|]+)(\\|(.*))?\$/", $line, $matches); # Skip empty lines if (count($matches) == 0) { continue; } if (strpos($matches[0], '%') !== false) { $matches[1] = rawurldecode($matches[1]); } $title = Title::newFromText($matches[1], NS_FILE); if (is_null($title)) { # Bogus title. Ignore these so we don't bomb out later. continue; } $label = ''; $alt = ''; $link = ''; if (isset($matches[3])) { // look for an |alt= definition while trying not to break existing // captions with multiple pipes (|) in it, until a more sensible grammar // is defined for images in galleries $matches[3] = $this->recursiveTagParse(trim($matches[3])); $parameterMatches = StringUtils::explode('|', $matches[3]); $magicWordAlt = MagicWord::get('img_alt'); $magicWordLink = MagicWord::get('img_link'); foreach ($parameterMatches as $parameterMatch) { if ($match = $magicWordAlt->matchVariableStartToEnd($parameterMatch)) { $alt = $this->stripAltText($match, false); } elseif ($match = $magicWordLink->matchVariableStartToEnd($parameterMatch)) { $link = strip_tags($this->replaceLinkHoldersText($match)); $chars = self::EXT_LINK_URL_CLASS; $prots = $this->mUrlProtocols; //check to see if link matches an absolute url, if not then it must be a wiki link. if (!preg_match("/^({$prots}){$chars}+\$/u", $link)) { $localLinkTitle = Title::newFromText($link); $link = $localLinkTitle->getLocalURL(); } } else { // concatenate all other pipes $label .= '|' . $parameterMatch; } } // remove the first pipe $label = substr($label, 1); } $ig->add($title, $label, $alt, $link); } return $ig->toHTML(); }
/** * Move page to a title which is either a redirect to the * source page or nonexistent * * @param $nt Title the page to move to, which should be a redirect or nonexistent * @param $reason String The reason for the move * @param $createRedirect Bool Whether to leave a redirect at the old title. Ignored * if the user doesn't have the suppressredirect right */ private function moveToInternal(&$nt, $reason = '', $createRedirect = true) { global $wgUser, $wgContLang; $moveOverRedirect = $nt->exists(); $commentMsg = $moveOverRedirect ? '1movedto2_redir' : '1movedto2'; $comment = wfMsgForContent($commentMsg, $this->getPrefixedText(), $nt->getPrefixedText()); if ($reason) { $comment .= wfMsgForContent('colon-separator') . $reason; } # Truncate for whole multibyte characters. $comment = $wgContLang->truncate($comment, 255); $oldid = $this->getArticleID(); $latest = $this->getLatestRevID(); $dbw = wfGetDB(DB_MASTER); if ($moveOverRedirect) { $rcts = $dbw->timestamp($nt->getEarliestRevTime()); $newid = $nt->getArticleID(); $newns = $nt->getNamespace(); $newdbk = $nt->getDBkey(); # Delete the old redirect. We don't save it to history since # by definition if we've got here it's rather uninteresting. # We have to remove it so that the next step doesn't trigger # a conflict on the unique namespace+title index... $dbw->delete('page', array('page_id' => $newid), __METHOD__); if (!$dbw->cascadingDeletes()) { $dbw->delete('revision', array('rev_page' => $newid), __METHOD__); global $wgUseTrackbacks; if ($wgUseTrackbacks) { $dbw->delete('trackbacks', array('tb_page' => $newid), __METHOD__); } $dbw->delete('pagelinks', array('pl_from' => $newid), __METHOD__); $dbw->delete('imagelinks', array('il_from' => $newid), __METHOD__); $dbw->delete('categorylinks', array('cl_from' => $newid), __METHOD__); $dbw->delete('templatelinks', array('tl_from' => $newid), __METHOD__); $dbw->delete('externallinks', array('el_from' => $newid), __METHOD__); $dbw->delete('langlinks', array('ll_from' => $newid), __METHOD__); $dbw->delete('iwlinks', array('iwl_from' => $newid), __METHOD__); $dbw->delete('redirect', array('rd_from' => $newid), __METHOD__); } // If the target page was recently created, it may have an entry in recentchanges still $dbw->delete('recentchanges', array('rc_timestamp' => $rcts, 'rc_namespace' => $newns, 'rc_title' => $newdbk, 'rc_new' => 1), __METHOD__); } # Save a null revision in the page's history notifying of the move $nullRevision = Revision::newNullRevision($dbw, $oldid, $comment, true); if (!is_object($nullRevision)) { throw new MWException('No valid null revision produced in ' . __METHOD__); } $nullRevId = $nullRevision->insertOn($dbw); $now = wfTimestampNow(); # Change the name of the target page: $dbw->update('page', array('page_touched' => $dbw->timestamp($now), 'page_namespace' => $nt->getNamespace(), 'page_title' => $nt->getDBkey(), 'page_latest' => $nullRevId), array('page_id' => $oldid), __METHOD__); $nt->resetArticleID($oldid); $article = new Article($nt); wfRunHooks('NewRevisionFromEditComplete', array($article, $nullRevision, $latest, $wgUser)); $article->setCachedLastEditTime($now); # Recreate the redirect, this time in the other direction. if ($createRedirect || !$wgUser->isAllowed('suppressredirect')) { $mwRedir = MagicWord::get('redirect'); $redirectText = $mwRedir->getSynonym(0) . ' [[' . $nt->getPrefixedText() . "]]\n"; $redirectArticle = new Article($this); $newid = $redirectArticle->insertOn($dbw); $redirectRevision = new Revision(array('page' => $newid, 'comment' => $comment, 'text' => $redirectText)); $redirectRevision->insertOn($dbw); $redirectArticle->updateRevisionOn($dbw, $redirectRevision, 0); wfRunHooks('NewRevisionFromEditComplete', array($redirectArticle, $redirectRevision, false, $wgUser)); # Now, we record the link from the redirect to the new title. # It should have no other outgoing links... $dbw->delete('pagelinks', array('pl_from' => $newid), __METHOD__); $dbw->insert('pagelinks', array('pl_from' => $newid, 'pl_namespace' => $nt->getNamespace(), 'pl_title' => $nt->getDBkey()), __METHOD__); $redirectSuppressed = false; } else { $this->resetArticleID(0); $redirectSuppressed = true; } # Log the move $log = new LogPage('move'); $logType = $moveOverRedirect ? 'move_redir' : 'move'; $log->addEntry($logType, $this, $reason, array(1 => $nt->getPrefixedText(), 2 => $redirectSuppressed)); # Purge caches for old and new titles if ($moveOverRedirect) { # A simple purge is enough when moving over a redirect $nt->purgeSquid(); } else { # Purge caches as per article creation, including any pages that link to this title Article::onArticleCreate($nt); } $this->purgeSquid(); }
/** * Get the base regex */ function getBaseRegex() { if (is_null($this->baseRegex)) { $this->baseRegex = array(0 => '', 1 => ''); foreach ($this->names as $name) { $magic = MagicWord::get($name); $case = intval($magic->isCaseSensitive()); foreach ($magic->getSynonyms() as $i => $syn) { $group = "(?P<{$i}_{$name}>" . preg_quote($syn, '/') . ')'; if ($this->baseRegex[$case] === '') { $this->baseRegex[$case] = $group; } else { $this->baseRegex[$case] .= '|' . $group; } } } } return $this->baseRegex; }
/** * $magicarr is an associative array of (magic word ID => replacement) * This method uses the php feature to do several replacements at the same time, * thereby gaining some efficiency. The result is placed in the out variable * $result. The return value is true if something was replaced. * @static **/ function replaceMultiple($magicarr, $subject, &$result) { $search = array(); $replace = array(); foreach ($magicarr as $id => $replacement) { $mw = MagicWord::get($id); $search[] = $mw->getRegex(); $replace[] = $replacement; } $result = preg_replace($search, $replace, $subject); return !($result === $subject); }
/** * Matches the given value against the value of given magic word * * @param string $magicword Magic word key * @param string $value Value to match * @return bool True on successful match */ private static function matchAgainstMagicword($magicword, $value) { $value = trim(strval($value)); if ($value === '') { return false; } $mwObject = MagicWord::get($magicword); return $mwObject->matchStartToEnd($value); }
/** * @return bool */ function run() { if (!$this->redirTitle) { $this->setLastError('Invalid title'); return false; } $targetRev = Revision::newFromTitle($this->title, false, Revision::READ_LATEST); if (!$targetRev) { wfDebug(__METHOD__ . ": target redirect already deleted, ignoring\n"); return true; } $content = $targetRev->getContent(); $currentDest = $content ? $content->getRedirectTarget() : null; if (!$currentDest || !$currentDest->equals($this->redirTitle)) { wfDebug(__METHOD__ . ": Redirect has changed since the job was queued\n"); return true; } // Check for a suppression tag (used e.g. in periodically archived discussions) $mw = MagicWord::get('staticredirect'); if ($content->matchMagicWord($mw)) { wfDebug(__METHOD__ . ": skipping: suppressed with __STATICREDIRECT__\n"); return true; } // Find the current final destination $newTitle = self::getFinalDestination($this->redirTitle); if (!$newTitle) { wfDebug(__METHOD__ . ": skipping: single redirect, circular redirect or invalid redirect destination\n"); return true; } if ($newTitle->equals($this->redirTitle)) { // The redirect is already right, no need to change it // This can happen if the page was moved back (say after vandalism) wfDebug(__METHOD__ . " : skipping, already good\n"); } // Preserve fragment (bug 14904) $newTitle = Title::makeTitle($newTitle->getNamespace(), $newTitle->getDBkey(), $currentDest->getFragment(), $newTitle->getInterwiki()); // Fix the text $newContent = $content->updateRedirect($newTitle); if ($newContent->equals($content)) { $this->setLastError('Content unchanged???'); return false; } $user = $this->getUser(); if (!$user) { $this->setLastError('Invalid user'); return false; } // Save it global $wgUser; $oldUser = $wgUser; $wgUser = $user; $article = WikiPage::factory($this->title); // Messages: double-redirect-fixed-move, double-redirect-fixed-maintenance $reason = wfMessage('double-redirect-fixed-' . $this->reason, $this->redirTitle->getPrefixedText(), $newTitle->getPrefixedText())->inContentLanguage()->text(); $article->doEditContent($newContent, $reason, EDIT_UPDATE | EDIT_SUPPRESS_RC, false, $user); $wgUser = $oldUser; return true; }
/** * Create a function, e.g. {{sum:1|2|3}} * The callback function should have the form: * function myParserFunction( &$parser, $arg1, $arg2, $arg3 ) { ... } * * Or with SFH_OBJECT_ARGS: * function myParserFunction( $parser, $frame, $args ) { ... } * * The callback may either return the text result of the function, or an array with the text * in element 0, and a number of flags in the other elements. The names of the flags are * specified in the keys. Valid flags are: * found The text returned is valid, stop processing the template. This * is on by default. * nowiki Wiki markup in the return value should be escaped * isHTML The returned text is HTML, armour it against wikitext transformation * * @param string $id The magic word ID * @param mixed $callback The callback function (and object) to use * @param int $flags A combination of the following flags: * SFH_NO_HASH No leading hash, i.e. {{plural:...}} instead of {{#if:...}} * * SFH_OBJECT_ARGS Pass the template arguments as PPNode objects instead of text. This * allows for conditional expansion of the parse tree, allowing you to eliminate dead * branches and thus speed up parsing. It is also possible to analyse the parse tree of * the arguments, and to control the way they are expanded. * * The $frame parameter is a PPFrame. This can be used to produce expanded text from the * arguments, for instance: * $text = isset( $args[0] ) ? $frame->expand( $args[0] ) : ''; * * For technical reasons, $args[0] is pre-expanded and will be a string. This may change in * future versions. Please call $frame->expand() on it anyway so that your code keeps * working if/when this is changed. * * If you want whitespace to be trimmed from $args, you need to do it yourself, post- * expansion. * * Please read the documentation in includes/parser/Preprocessor.php for more information * about the methods available in PPFrame and PPNode. * * @throws MWException * @return string|callback The old callback function for this name, if any */ public function setFunctionHook($id, $callback, $flags = 0) { global $wgContLang; $oldVal = isset($this->mFunctionHooks[$id]) ? $this->mFunctionHooks[$id][0] : null; $this->mFunctionHooks[$id] = array($callback, $flags); # Add to function cache $mw = MagicWord::get($id); if (!$mw) { throw new MWException(__METHOD__ . '() expecting a magic word identifier.'); } $synonyms = $mw->getSynonyms(); $sensitive = intval($mw->isCaseSensitive()); foreach ($synonyms as $syn) { # Case if (!$sensitive) { $syn = $wgContLang->lc($syn); } # Add leading hash if (!($flags & SFH_NO_HASH)) { $syn = '#' . $syn; } # Remove trailing colon if (substr($syn, -1, 1) === ':') { $syn = substr($syn, 0, -1); } $this->mFunctionSynonyms[$sensitive][$syn] = $id; } return $oldVal; }
function efSharedHelpRemoveMagicWord(&$parser, &$text, &$strip_state) { $found = MagicWord::get('MAG_NOSHAREDHELP')->matchAndRemove($text); if ($found) { $text .= NOSHAREDHELP_MARKER; } return true; }
/** * @covers JavaScriptContent::matchMagicWord */ public function testMatchMagicWord() { $mw = MagicWord::get("staticredirect"); $content = $this->newContent("#REDIRECT [[FOO]]\n__STATICREDIRECT__"); $this->assertFalse($content->matchMagicWord($mw), "should not have matched magic word, since it's not wikitext"); }
/** * Get the base regex * @return array */ function getBaseRegex() { if (is_null($this->baseRegex)) { $this->baseRegex = array(0 => '', 1 => ''); foreach ($this->names as $name) { $magic = MagicWord::get($name); $case = intval($magic->isCaseSensitive()); foreach ($magic->getSynonyms() as $i => $syn) { // Group name must start with a non-digit in PCRE 8.34+ $it = strtr($i, '0123456789', 'abcdefghij'); $group = "(?P<{$it}_{$name}>" . preg_quote($syn, '/') . ')'; if ($this->baseRegex[$case] === '') { $this->baseRegex[$case] = $group; } else { $this->baseRegex[$case] .= '|' . $group; } } } } return $this->baseRegex; }
/** * {{wl-settings:...}} parser function handler. */ public static function settings( &$parser /* ... */ ) { global $wgOut; self::checkNamespace( $parser ); $mwIcon =& MagicWord::get( 'wlk-icon' ); $mwLogo =& MagicWord::get( 'wlk-logo' ); $mwSubtitle =& MagicWord::get( 'wlk-subtitle' ); $args = array_slice( func_get_args(), 1 ); foreach ( $args as $arg ) { $parts = array_map( 'trim', explode( '=', $arg, 2 ) ); if ( empty( $parts[0] ) ) continue; if ( count( $parts ) < 2 ) $parts[1] = ''; list( $key, $value ) = $parts; if ( $mwIcon->matchStart( $key ) ) { if ( ( $icon = self::parseImageLink( $parser, $value ) ) ) { $parser->mExtWikilog->mIcon = $icon->getTitle(); } } elseif ( $mwLogo->matchStart( $key ) ) { if ( ( $logo = self::parseImageLink( $parser, $value ) ) ) { $parser->mExtWikilog->mLogo = $logo->getTitle(); } } elseif ( $mwSubtitle->matchStart( $key ) ) { $popt = $parser->getOptions(); $popt->enableLimitReport( false ); $output = $parser->parse( $value, $parser->getTitle(), $popt, true, false ); $parser->mExtWikilog->mSummary = $output->getText(); } else { $warning = wfMsg( 'wikilog-error-msg', wfMsg( 'wikilog-invalid-param', htmlspecialchars( $key ) ) ); $parser->mOutput->addWarning( $warning ); } } return '<!-- -->'; }