/** * This method will be called before an article is displayed or previewed. * For display and preview we strip out the semantic properties and append them * at the end of the article. * * @param Parser $parser * @param string $text */ static public function onInternalParseBeforeLinks( &$parser, &$text ) { global $smwgStoreAnnotations, $smwgLinksInValues; SMWParseData::stripMagicWords( $text, $parser ); // Store the results if enabled (we have to parse them in any case, // in order to clean the wiki source for further processing). $smwgStoreAnnotations = smwfIsSemanticsProcessed( $parser->getTitle()->getNamespace() ); SMWParserExtensions::$mTempStoreAnnotations = true; // used for [[SMW::on]] and [[SMW:off]] // Process redirects, if any (it seems that there is indeed no more direct way of getting this info from MW) if ( $smwgStoreAnnotations ) { $rt = Title::newFromRedirect( $text ); if ( !is_null( $rt ) ) { $p = new SMWDIProperty( '_REDI' ); $di = SMWDIWikiPage::newFromTitle( $rt, '__red' ); SMWParseData::getSMWData( $parser )->addPropertyObjectValue( $p, $di ); } } // only used in subsequent callbacks, forgotten afterwards SMWParserExtensions::$mTempParser = $parser; // In the regexp matches below, leading ':' escapes the markup, as known for Categories. // Parse links to extract semantic properties. if ( $smwgLinksInValues ) { // More complex regexp -- lib PCRE may cause segfaults if text is long :-( $semanticLinkPattern = '/\[\[ # Beginning of the link (?:([^:][^]]*):[=:])+ # Property name (or a list of those) ( # After that: (?:[^|\[\]] # either normal text (without |, [ or ]) |\[\[[^]]*\]\] # or a [[link]] |\[[^]]*\] # or an [external link] )*) # all this zero or more times (?:\|([^]]*))? # Display text (like "text" in [[link|text]]), optional \]\] # End of link /xu'; $text = preg_replace_callback( $semanticLinkPattern, array( 'SMWParserExtensions', 'parsePropertiesCallback' ), $text ); } else { // Simpler regexps -- no segfaults found for those, but no links in values. $semanticLinkPattern = '/\[\[ # Beginning of the link (?:([^:][^]]*):[=:])+ # Property name (or a list of those) ([^\[\]]*) # content: anything but [, |, ] \]\] # End of link /xu'; $text = preg_replace_callback( $semanticLinkPattern, array( 'SMWParserExtensions', 'simpleParsePropertiesCallback' ), $text ); } // Add link to RDF to HTML header. // TODO: do escaping via Html or Xml class. SMWOutputs::requireHeadItem( 'smw_rdf', '<link rel="alternate" type="application/rdf+xml" title="' . htmlspecialchars( $parser->getTitle()->getPrefixedText() ) . '" href="' . htmlspecialchars( SpecialPage::getTitleFor( 'ExportRDF', $parser->getTitle()->getPrefixedText() )->getLocalUrl( 'xmlmime=rdf' ) ) . "\" />" ); SMWOutputs::commitToParser( $parser ); return true; // always return true, in order not to stop MW's hook processing! }
function redircite_render($input, $args, &$parser) { // Generate HTML code and add it to the $redirciteMarkerList array // Add "xx-redircite-marker-NUMBER-redircite-xx" to the output, // which will be translated to the HTML stored in $redirciteMarkerList by // redircite_afterTidy() global $redirciteMarkerList; # Verify that $input is a valid title $inputTitle = Title::newFromText($input); if(!$inputTitle) return $input; $link1 = $parser->recursiveTagParse("[[$input]]"); $title1 = Title::newFromText($input); if(!$title1->exists()) // Page doesn't exist // Just output a normal (red) link return $link1; $articleObj = new Article($title1); $title2 = Title::newFromRedirect($articleObj->fetchContent()); if(!$title2) // Page is not a redirect // Just output a normal link return $link1; $link2 = $parser->recursiveTagParse("[[{$title2->getPrefixedText()}|$input]]"); $marker = "xx-redircite-marker-" . count($redirciteMarkerList) . "-redircite-xx"; $onmouseout = 'this.firstChild.innerHTML = "'. Xml::escapeJsString($input) . '";'; $onmouseover = 'this.firstChild.innerHTML = "' . Xml::escapeJsString($title2->getPrefixedText()) . '";'; return Xml::tags('span', array( 'onmouseout' => $onmouseout, 'onmouseover' => $onmouseover), $link2); }
function getTopLevelCategories() { global $wgCategoriesArticle; wfLoadExtensionMessages('Sitemap'); $results = array(); $revision = Revision::newFromTitle(Title::newFromText(wfMsg('categories_article'))); if (!$revision) { return $results; } // INTL: If there is a redirect to a localized page name, follow it if (strpos($revision->getText(), "#REDIRECT") !== false) { $revision = Revision::newFromTitle(Title::newFromRedirect($revision->getText())); } $lines = split("\n", $revision->getText()); foreach ($lines as $line) { if (preg_match('/^\\*[^\\*]/', $line)) { $line = trim(substr($line, 1)); switch ($line) { case "Other": case "wikiHow": break; default: $results[] = $line; } } } return $results; }
function formatResult($skin, $result) { global $wgContLang; # Make a link to the redirect itself $rd_title = Title::makeTitle($result->namespace, $result->title); $arr = $wgContLang->getArrow() . $wgContLang->getDirMark(); $rd_link = $skin->makeKnownLinkObj($rd_title, '', 'redirect=no'); # Find out where the redirect leads $revision = Revision::newFromTitle($rd_title); if ($revision) { # Make a link to the destination page $target = Title::newFromRedirect($revision->getText()); if ($target) { $targetLink = $skin->makeLinkObj($target); } else { /** @todo Put in some decent error display here */ $targetLink = '*'; } } else { /** @todo Put in some decent error display here */ $targetLink = '*'; } # Format the whole thing and return it return "{$rd_link} {$arr} {$targetLink}"; }
function formatResult($skin, $result) { global $wgContLang; # Make a link to the redirect itself $rd_title = Title::makeTitle($result->namespace, $result->title); $rd_link = $skin->makeKnownLinkObj($rd_title, '', 'redirect=no'); # Find out where the redirect leads $revision = Revision::newFromTitle($rd_title); if ($revision) { # Make a link to the destination page $target = Title::newFromRedirect($revision->getText()); if ($target) { $targetLink = $skin->makeLinkObj($target); } else { /** @todo Put in some decent error display here */ $targetLink = '*'; } } else { /** @todo Put in some decent error display here */ $targetLink = '*'; } # Check the language; RTL wikis need a ← $arr = $wgContLang->isRTL() ? ' ← ' : ' → '; # Format the whole thing and return it return $rd_link . $arr . $targetLink; }
/** * @since 1.1 * * @param EditPage $editor * @param OutputPage &$out * * @return true */ public function onEditConflict(EditPage &$editor, OutputPage &$out) { $conctext = $editor->textbox1; $actualtext = $editor->textbox2; $initialtext = $editor->getBaseRevision()->mText; // TODO: WTF?! $editor->mArticle->doEdit($actualtext, $editor->summary, $editor->minoredit ? EDIT_MINOR : 0); $query = Title::newFromRedirect($actualtext) === null ? '' : 'redirect=no'; $out->redirect($editor->mTitle->getFullURL($query)); return true; }
public function addArticle($month, $day, $year, $page) { $lines = array(); $temp = ""; $head = array(); $article = new Article(Title::newFromText($page)); if (!$article->exists()) { return ""; } $redirectCount = 0; if ($article->isRedirect() && $this->setting('disableredirects')) { return ''; } while ($article->isRedirect() && $redirectCount < 10) { $redirectedArticleTitle = Title::newFromRedirect($article->getContent()); $article = new Article($redirectedArticleTitle); $redirectCount += 1; } $body = $article->fetchContent(0, false, false); if (strlen(trim($body)) == 0) { return ""; } $lines = split("\n", $body); $cntLines = count($lines); // dont use section events... only line 1 of the page if ($this->setting('disablesectionevents')) { $key = $lines[0]; //initalize the key $head[$key] = ""; $cntLines = 0; } for ($i = 0; $i < $cntLines; $i++) { $line = $lines[$i]; if (substr($line, 0, 2) == '==') { $arr = split("==", $line); $key = $arr[1]; $head[$key] = ""; $temp = ""; } else { if ($i == 0) { // $i=0 means this is a one event page no (==event==) data $key = $line; //initalize the key $head[$key] = ""; } else { $temp .= "{$line}\n"; $head[$key] = Common::cleanWiki($temp); } } } while (list($event, $body) = each($head)) { $this->buildEvent($month, $day, $year, trim($event), $page, $body); } }
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; }
function getRS() { global $wgMemc; $key_rs = wfMemcKey("risingstar-feed3:" . date('YmdG') . ":" . number_format(date('i') / 10, 0, '', '')); $rsOut = $wgMemc->get($key_rs); if (!empty($rsOut)) { return $rsOut; } $t = Title::newFromText('wikiHow:Rising-star-feed'); if ($t->getArticleId() > 0) { $r = Revision::newFromTitle($t); $text = $r->getText(); } else { return false; } //NOTE: temporary patch to handle archives. the authoritative source for RS needs to be moved to the DB versus the feed article. add archive to array. $archives = array('wikiHow:Rising-star-feed/archive1'); foreach ($archives as $archive) { $tarch = Title::newFromText($archive); if ($tarch->getArticleId() > 0) { $r = Revision::newFromTitle($tarch); $text = $r->getText() . "\n" . $text; } } $rsout = array(); $rs = $text; $rs = preg_replace("/==\n/", ',', $rs); $rs = preg_replace("/^==/", "", $rs); $lines = preg_split("/\r|\n/", $rs, null, PREG_SPLIT_NO_EMPTY); $count = 0; foreach ($lines as $line) { if (preg_match('/^==(.*?),(.*?)$/', $line, $matches)) { $dt = $matches[1]; $pattern = "/{$wgServer}/"; $title = preg_replace("/http:\\/\\/www\\.wikihow\\.com\\//", "", $matches[2]); $title = preg_replace("/http:\\/\\/.*?\\.com\\//", "", $matches[2]); $t = Title::newFromText($title); if (!isset($t)) { continue; } $a = new Article($t); if ($a->isRedirect()) { $t = Title::newFromRedirect($a->fetchContent()); $a = new Article($t); } $rsout[$t->getPartialURL()] = $dt; } } // sort by most recent first $rsout = array_reverse($rsout); $wgMemc->set($key_rs, $rsout); return $rsout; }
public function hUnknownAction($action, &$article) { // check if request 'action=formsubmit' if ($action != 'formsubmit') { return true; } // continue hook-chain. $article->loadContent(); // follow redirects if ($article->mIsRedirect == true) { $title = Title::newFromRedirect($article->getContent()); $article = new Article($title); $article->loadContent(); } // Extract the code // Use our runphpClass helper $runphp = new runphpClass(); $runphp->initFromContent($article->getContent()); // Execute Code $code = $runphp->getCode(true); if (!empty($code)) { $callback = eval($code); } // we might implement functionality around a callback method in the future // Was there an expected class defined? $name = $article->mTitle->getDBkey(); // the page name might actually be a sub-page; extract the basename without the full path. $pn = explode('/', $name); if (!empty($pn)) { $rn = array_reverse($pn); $name = $rn[0]; } $name .= 'Class'; if (class_exists($name)) { $class = new $name(); if (is_object($class)) { if (method_exists($class, 'submit')) { $class->submit(); } } } // ... then it was a page built from ground up; nothing more to do here. return false; }
public function execute() { $this->output("Fetching redirects...\n"); $dbr = wfGetDB(DB_SLAVE); $result = $dbr->select(array('page'), array('page_namespace', 'page_title', 'page_latest'), array('page_is_redirect' => 1)); $count = $result->numRows(); $this->output("Found {$count} total redirects.\n" . "Looking for bad redirects:\n\n"); foreach ($result as $row) { $title = Title::makeTitle($row->page_namespace, $row->page_title); $rev = Revision::newFromId($row->page_latest); if ($rev) { $target = Title::newFromRedirect($rev->getText()); if (!$target) { $this->output($title->getPrefixedText() . "\n"); } } } $this->output("\ndone.\n"); }
function formatResult($skin, $result) { global $wgContLang; # Make a link to the redirect itself $rd_title = Title::makeTitle($result->namespace, $result->title); $rd_link = $skin->makeLinkObj($rd_title, '', 'redirect=no'); # Find out where the redirect leads $revision = Revision::newFromTitle($rd_title); if ($revision) { # Make a link to the destination page $target = Title::newFromRedirect($revision->getText()); if ($target) { $arr = $wgContLang->getArrow() . $wgContLang->getDirMark(); $targetLink = $skin->makeLinkObj($target); return "{$rd_link} {$arr} {$targetLink}"; } else { return "<s>{$rd_link}</s>"; } } else { return "<s>{$rd_link}</s>"; } }
function redirectThread() { $rev = Revision::newFromId($this->root()->getLatest()); $rtitle = Title::newFromRedirect($rev->getRawText()); if (!$rtitle) { return null; } $this->dieIfHistorical(); $rthread = Threads::withRoot(new Article($rtitle)); return $rthread; }
/** * Static function to get a template * Can be overridden via ParserOptions::setTemplateCallback(). */ static function statelessFetchTemplate($title, $parser = false) { $text = $skip = false; $finalTitle = $title; $deps = array(); // Loop to fetch the article, with up to 1 redirect for ($i = 0; $i < 2 && is_object($title); $i++) { # Give extensions a chance to select the revision instead $id = false; // Assume current wfRunHooks('BeforeParserFetchTemplateAndtitle', array($parser, &$title, &$skip, &$id)); if ($skip) { $text = false; $deps[] = array('title' => $title, 'page_id' => $title->getArticleID(), 'rev_id' => null); break; } $rev = $id ? Revision::newFromId($id) : Revision::newFromTitle($title); $rev_id = $rev ? $rev->getId() : 0; // If there is no current revision, there is no page if ($id === false && !$rev) { $linkCache = LinkCache::singleton(); $linkCache->addBadLinkObj($title); } $deps[] = array('title' => $title, 'page_id' => $title->getArticleID(), 'rev_id' => $rev_id); if ($rev) { $text = $rev->getText(); } elseif ($title->getNamespace() == NS_MEDIAWIKI) { global $wgContLang; $message = $wgContLang->lcfirst($title->getText()); $text = wfMsgForContentNoTrans($message); if (wfEmptyMsg($message, $text)) { $text = false; break; } } else { break; } if ($text === false) { break; } // Redirect? $finalTitle = $title; $title = Title::newFromRedirect($text); } return array('text' => $text, 'finalTitle' => $finalTitle, 'deps' => $deps); }
/** * Static function to get a template * Can be overridden via ParserOptions::setTemplateCallback(). * * @param $title Title * @param $parser Parser * * @return array */ static function statelessFetchTemplate($title, $parser = false) { $text = $skip = false; $finalTitle = $title; $deps = array(); # Loop to fetch the article, with up to 1 redirect for ($i = 0; $i < 2 && is_object($title); $i++) { # Give extensions a chance to select the revision instead $id = false; # Assume current wfRunHooks('BeforeParserFetchTemplateAndtitle', array($parser, $title, &$skip, &$id)); if ($skip) { $text = false; $deps[] = array('title' => $title, 'page_id' => $title->getArticleID(), 'rev_id' => null); break; } # Get the revision $rev = $id ? Revision::newFromId($id) : Revision::newFromTitle($title, false, Revision::READ_NORMAL); $rev_id = $rev ? $rev->getId() : 0; # If there is no current revision, there is no page if ($id === false && !$rev) { $linkCache = LinkCache::singleton(); $linkCache->addBadLinkObj($title); } $deps[] = array('title' => $title, 'page_id' => $title->getArticleID(), 'rev_id' => $rev_id); if ($rev && !$title->equals($rev->getTitle())) { # We fetched a rev from a different title; register it too... $deps[] = array('title' => $rev->getTitle(), 'page_id' => $rev->getPage(), 'rev_id' => $rev_id); } if ($rev) { $text = $rev->getText(); } elseif ($title->getNamespace() == NS_MEDIAWIKI) { global $wgContLang; $message = wfMessage($wgContLang->lcfirst($title->getText()))->inContentLanguage(); if (!$message->exists()) { $text = false; break; } $text = $message->plain(); } else { break; } if ($text === false) { break; } # Redirect? $finalTitle = $title; $title = Title::newFromRedirect($text); } return array('text' => $text, 'finalTitle' => $finalTitle, 'deps' => $deps); }
/** * Return an applicable autosummary if one exists for the given edit. * @param $oldtext String: the previous text of the page. * @param $newtext String: The submitted text of the page. * @param $flags Bitmask: a bitmask of flags submitted for the edit. * @return string An appropriate autosummary, or an empty string. */ public static function getAutosummary($oldtext, $newtext, $flags) { global $wgContLang; # Decide what kind of autosummary is needed. # Redirect autosummaries $ot = Title::newFromRedirect($oldtext); $rt = Title::newFromRedirect($newtext); if (is_object($rt) && (!is_object($ot) || !$rt->equals($ot) || $ot->getFragment() != $rt->getFragment())) { return wfMsgForContent('autoredircomment', $rt->getFullText()); } # New page autosummaries if ($flags & EDIT_NEW && strlen($newtext)) { # If they're making a new article, give its text, truncated, in the summary. $truncatedtext = $wgContLang->truncate(str_replace("\n", ' ', $newtext), max(0, 200 - strlen(wfMsgForContent('autosumm-new')))); return wfMsgForContent('autosumm-new', $truncatedtext); } # Blanking autosummaries if ($oldtext != '' && $newtext == '') { return wfMsgForContent('autosumm-blank'); } elseif (strlen($oldtext) > 10 * strlen($newtext) && strlen($newtext) < 500) { # Removing more than 90% of the article $truncatedtext = $wgContLang->truncate($newtext, max(0, 200 - strlen(wfMsgForContent('autosumm-replace')))); return wfMsgForContent('autosumm-replace', $truncatedtext); } # If we reach this point, there's no applicable autosummary for our case, so our # autosummary is empty. return ''; }
<?php require "commandLine.inc"; echo "Fetching redirects...\n"; $dbr = wfGetDB(DB_SLAVE); $result = $dbr->select(array('page'), array('page_namespace', 'page_title', 'page_latest'), array('page_is_redirect' => 1)); $count = $result->numRows(); echo "Found {$count} total redirects.\n"; echo "Looking for bad redirects:\n"; echo "\n"; foreach ($result as $row) { $title = Title::makeTitle($row->page_namespace, $row->page_title); $rev = Revision::newFromId($row->page_latest); if ($rev) { $target = Title::newFromRedirect($rev->getText()); if (!$target) { echo $title->getPrefixedText(); echo "\n"; } } } echo "\n"; echo "done.\n";
/** * This is the default action of the script: just view the page of * the given title. */ function view() { global $wgUser, $wgOut, $wgRequest, $wgContLang; global $wgEnableParserCache, $wgStylePath, $wgUseRCPatrol, $wgParser; global $wgUseTrackbacks, $wgNamespaceRobotPolicies; $sk = $wgUser->getSkin(); wfProfileIn(__METHOD__); $parserCache =& ParserCache::singleton(); $ns = $this->mTitle->getNamespace(); # shortcut # Get variables from query string $oldid = $this->getOldID(); # getOldID may want us to redirect somewhere else if ($this->mRedirectUrl) { $wgOut->redirect($this->mRedirectUrl); wfProfileOut(__METHOD__); return; } $diff = $wgRequest->getVal('diff'); $rcid = $wgRequest->getVal('rcid'); $rdfrom = $wgRequest->getVal('rdfrom'); $wgOut->setArticleFlag(true); if (isset($wgNamespaceRobotPolicies[$ns])) { $policy = $wgNamespaceRobotPolicies[$ns]; } else { $policy = 'index,follow'; } $wgOut->setRobotpolicy($policy); # If we got diff and oldid in the query, we want to see a # diff page instead of the article. if (!is_null($diff)) { require_once 'DifferenceEngine.php'; $wgOut->setPageTitle($this->mTitle->getPrefixedText()); $de = new DifferenceEngine($this->mTitle, $oldid, $diff, $rcid); // DifferenceEngine directly fetched the revision: $this->mRevIdFetched = $de->mNewid; $de->showDiffPage(); if ($diff == 0) { # Run view updates for current revision only $this->viewUpdates(); } wfProfileOut(__METHOD__); return; } if (empty($oldid) && $this->checkTouched()) { $wgOut->setETag($parserCache->getETag($this, $wgUser)); if ($wgOut->checkLastModified($this->mTouched)) { // WERELATE: add viewUpdates call just in case $this->viewUpdates(); wfProfileOut(__METHOD__); return; } else { if ($this->tryFileCache()) { # tell wgOut that output is taken care of $wgOut->disable(); $this->viewUpdates(); wfProfileOut(__METHOD__); return; } } } # Should the parser cache be used? $pcache = $wgEnableParserCache && intval($wgUser->getOption('stubthreshold')) == 0 && $this->exists() && empty($oldid); wfDebug('Article::view using parser cache: ' . ($pcache ? 'yes' : 'no') . "\n"); if ($wgUser->getOption('stubthreshold')) { wfIncrStats('pcache_miss_stub'); } $wasRedirected = false; if (isset($this->mRedirectedFrom)) { // This is an internally redirected page view. // We'll need a backlink to the source page for navigation. if (wfRunHooks('ArticleViewRedirect', array(&$this))) { $sk = $wgUser->getSkin(); $redir = $sk->makeKnownLinkObj($this->mRedirectedFrom, '', 'redirect=no'); $s = wfMsg('redirectedfrom', $redir); $wgOut->setSubtitle($s); $wasRedirected = true; } } elseif (!empty($rdfrom)) { // This is an externally redirected view, from some other wiki. // If it was reported from a trusted site, supply a backlink. global $wgRedirectSources; if ($wgRedirectSources && preg_match($wgRedirectSources, $rdfrom)) { $sk = $wgUser->getSkin(); $redir = $sk->makeExternalLink($rdfrom, $rdfrom); $s = wfMsg('redirectedfrom', $redir); $wgOut->setSubtitle($s); $wasRedirected = true; } } $outputDone = false; if ($pcache) { if ($wgOut->tryParserCache($this, $wgUser)) { $outputDone = true; } } if (!$outputDone) { $text = $this->getContent(); if ($text === false) { # Failed to load, replace text with error message $t = $this->mTitle->getPrefixedText(); if ($oldid) { $t .= ',oldid=' . $oldid; $text = wfMsg('missingarticle', $t); } else { $text = wfMsg('noarticletext', $t); } } # Another whitelist check in case oldid is altering the title if (!$this->mTitle->userCanRead()) { $wgOut->loginToUse(); $wgOut->output(); exit; } # We're looking at an old revision if (!empty($oldid)) { $wgOut->setRobotpolicy('noindex,nofollow'); if (is_null($this->mRevision)) { // FIXME: This would be a nice place to load the 'no such page' text. } else { $this->setOldSubtitle(isset($this->mOldId) ? $this->mOldId : $oldid); if ($this->mRevision->isDeleted(Revision::DELETED_TEXT)) { if (!$this->mRevision->userCan(Revision::DELETED_TEXT)) { $wgOut->addWikiText(wfMsg('rev-deleted-text-permission')); $wgOut->setPageTitle($this->mTitle->getPrefixedText()); return; } else { $wgOut->addWikiText(wfMsg('rev-deleted-text-view')); // and we are allowed to see... } } } } } if (!$outputDone) { /** * @fixme: this hook doesn't work most of the time, as it doesn't * trigger when the parser cache is used. */ wfRunHooks('ArticleViewHeader', array(&$this)); $wgOut->setRevisionId($this->getRevIdFetched()); # wrap user css and user js in pre and don't parse # XXX: use $this->mTitle->usCssJsSubpage() when php is fixed/ a workaround is found if ($ns == NS_USER && preg_match('/\\/[\\w]+\\.(css|js)$/', $this->mTitle->getDBkey())) { $wgOut->addWikiText(wfMsg('clearyourcache')); $wgOut->addHTML('<pre>' . htmlspecialchars($this->mContent) . "\n</pre>"); } else { if ($rt = Title::newFromRedirect($text)) { # Display redirect $imageDir = $wgContLang->isRTL() ? 'rtl' : 'ltr'; $imageUrl = $wgStylePath . '/common/images/redirect' . $imageDir . '.png'; # Don't overwrite the subtitle if this was an old revision if (!$wasRedirected && $this->isCurrent()) { $wgOut->setSubtitle(wfMsgHtml('redirectpagesub')); } $targetUrl = $rt->escapeLocalURL(); # fixme unused $titleText : $titleText = htmlspecialchars($rt->getPrefixedText()); $link = $sk->makeLinkObj($rt); $wgOut->addHTML('<img src="' . $imageUrl . '" alt="#REDIRECT" />' . '<span class="redirectText">' . $link . '</span>'); $parseout = $wgParser->parse($text, $this->mTitle, ParserOptions::newFromUser($wgUser)); $wgOut->addParserOutputNoText($parseout); } else { if ($pcache) { # Display content and save to parser cache $wgOut->addPrimaryWikiText($text, $this); } else { # Display content, don't attempt to save to parser cache # Don't show section-edit links on old revisions... this way lies madness. if (!$this->isCurrent()) { $oldEditSectionSetting = $wgOut->mParserOptions->setEditSection(false); } # Display content and don't save to parser cache $wgOut->addPrimaryWikiText($text, $this, false); if (!$this->isCurrent()) { $wgOut->mParserOptions->setEditSection($oldEditSectionSetting); } } } } } /* title may have been set from the cache */ $t = $wgOut->getPageTitle(); if (empty($t)) { $wgOut->setPageTitle($this->mTitle->getPrefixedText()); } # check if we're displaying a [[User talk:x.x.x.x]] anonymous talk page if ($ns == NS_USER_TALK && User::isIP($this->mTitle->getText())) { $wgOut->addWikiText(wfMsg('anontalkpagetext')); } # If we have been passed an &rcid= parameter, we want to give the user a # chance to mark this new article as patrolled. if ($wgUseRCPatrol && !is_null($rcid) && $rcid != 0 && $wgUser->isAllowed('patrol')) { $wgOut->addHTML("<div class='patrollink'>" . wfMsg('markaspatrolledlink', $sk->makeKnownLinkObj($this->mTitle, wfMsg('markaspatrolledtext'), "action=markpatrolled&rcid={$rcid}")) . '</div>'); } # Trackbacks if ($wgUseTrackbacks) { $this->addTrackbacks(); } $this->viewUpdates(); wfProfileOut(__METHOD__); }
/** * Attempt submission (no UI) * * @param $result * @param $bot bool * * @return Status object, possibly with a message, but always with one of the AS_* constants in $status->value, * * FIXME: This interface is TERRIBLE, but hard to get rid of due to various error display idiosyncrasies. There are * also lots of cases where error metadata is set in the object and retrieved later instead of being returned, e.g. * AS_CONTENT_TOO_BIG and AS_BLOCKED_PAGE_FOR_USER. All that stuff needs to be cleaned up some time. */ function internalAttemptSave(&$result, $bot = false) { global $wgFilterCallback, $wgUser, $wgRequest, $wgParser; global $wgMaxArticleSize; $status = Status::newGood(); wfProfileIn(__METHOD__); wfProfileIn(__METHOD__ . '-checks'); if (!wfRunHooks('EditPage::attemptSave', array($this))) { wfDebug("Hook 'EditPage::attemptSave' aborted article saving\n"); $status->fatal('hookaborted'); $status->value = self::AS_HOOK_ERROR; wfProfileOut(__METHOD__ . '-checks'); wfProfileOut(__METHOD__); return $status; } # Check image redirect if ($this->mTitle->getNamespace() == NS_FILE && Title::newFromRedirect($this->textbox1) instanceof Title && !$wgUser->isAllowed('upload')) { $code = $wgUser->isAnon() ? self::AS_IMAGE_REDIRECT_ANON : self::AS_IMAGE_REDIRECT_LOGGED; $status->setResult(false, $code); wfProfileOut(__METHOD__ . '-checks'); wfProfileOut(__METHOD__); return $status; } # Check for spam $match = self::matchSummarySpamRegex($this->summary); if ($match === false) { $match = self::matchSpamRegex($this->textbox1); } if ($match !== false) { $result['spam'] = $match; $ip = $wgRequest->getIP(); $pdbk = $this->mTitle->getPrefixedDBkey(); $match = str_replace("\n", '', $match); wfDebugLog('SpamRegex', "{$ip} spam regex hit [[{$pdbk}]]: \"{$match}\""); $status->fatal('spamprotectionmatch', $match); $status->value = self::AS_SPAM_ERROR; wfProfileOut(__METHOD__ . '-checks'); wfProfileOut(__METHOD__); return $status; } if ($wgFilterCallback && is_callable($wgFilterCallback) && $wgFilterCallback($this->mTitle, $this->textbox1, $this->section, $this->hookError, $this->summary)) { # Error messages or other handling should be performed by the filter function $status->setResult(false, self::AS_FILTERING); wfProfileOut(__METHOD__ . '-checks'); wfProfileOut(__METHOD__); return $status; } if (!wfRunHooks('EditFilter', array($this, $this->textbox1, $this->section, &$this->hookError, $this->summary))) { # Error messages etc. could be handled within the hook... $status->fatal('hookaborted'); $status->value = self::AS_HOOK_ERROR; wfProfileOut(__METHOD__ . '-checks'); wfProfileOut(__METHOD__); return $status; } elseif ($this->hookError != '') { # ...or the hook could be expecting us to produce an error $status->fatal('hookaborted'); $status->value = self::AS_HOOK_ERROR_EXPECTED; wfProfileOut(__METHOD__ . '-checks'); wfProfileOut(__METHOD__); return $status; } if ($wgUser->isBlockedFrom($this->mTitle, false)) { // Auto-block user's IP if the account was "hard" blocked $wgUser->spreadAnyEditBlock(); # Check block state against master, thus 'false'. $status->setResult(false, self::AS_BLOCKED_PAGE_FOR_USER); wfProfileOut(__METHOD__ . '-checks'); wfProfileOut(__METHOD__); return $status; } $this->kblength = (int) (strlen($this->textbox1) / 1024); if ($this->kblength > $wgMaxArticleSize) { // Error will be displayed by showEditForm() $this->tooBig = true; $status->setResult(false, self::AS_CONTENT_TOO_BIG); wfProfileOut(__METHOD__ . '-checks'); wfProfileOut(__METHOD__); return $status; } if (!$wgUser->isAllowed('edit')) { if ($wgUser->isAnon()) { $status->setResult(false, self::AS_READ_ONLY_PAGE_ANON); wfProfileOut(__METHOD__ . '-checks'); wfProfileOut(__METHOD__); return $status; } else { $status->fatal('readonlytext'); $status->value = self::AS_READ_ONLY_PAGE_LOGGED; wfProfileOut(__METHOD__ . '-checks'); wfProfileOut(__METHOD__); return $status; } } if (wfReadOnly()) { $status->fatal('readonlytext'); $status->value = self::AS_READ_ONLY_PAGE; wfProfileOut(__METHOD__ . '-checks'); wfProfileOut(__METHOD__); return $status; } if ($wgUser->pingLimiter()) { $status->fatal('actionthrottledtext'); $status->value = self::AS_RATE_LIMITED; wfProfileOut(__METHOD__ . '-checks'); wfProfileOut(__METHOD__); return $status; } # If the article has been deleted while editing, don't save it without # confirmation if ($this->wasDeletedSinceLastEdit() && !$this->recreate) { $status->setResult(false, self::AS_ARTICLE_WAS_DELETED); wfProfileOut(__METHOD__ . '-checks'); wfProfileOut(__METHOD__); return $status; } wfProfileOut(__METHOD__ . '-checks'); # If article is new, insert it. $aid = $this->mTitle->getArticleID(Title::GAID_FOR_UPDATE); $new = $aid == 0; if ($new) { // Late check for create permission, just in case *PARANOIA* if (!$this->mTitle->userCan('create')) { $status->fatal('nocreatetext'); $status->value = self::AS_NO_CREATE_PERMISSION; wfDebug(__METHOD__ . ": no create permission\n"); wfProfileOut(__METHOD__); return $status; } # Don't save a new article if it's blank. if ($this->textbox1 == '') { $status->setResult(false, self::AS_BLANK_ARTICLE); wfProfileOut(__METHOD__); return $status; } // Run post-section-merge edit filter if (!wfRunHooks('EditFilterMerged', array($this, $this->textbox1, &$this->hookError, $this->summary))) { # Error messages etc. could be handled within the hook... $status->fatal('hookaborted'); $status->value = self::AS_HOOK_ERROR; wfProfileOut(__METHOD__); return $status; } elseif ($this->hookError != '') { # ...or the hook could be expecting us to produce an error $status->fatal('hookaborted'); $status->value = self::AS_HOOK_ERROR_EXPECTED; wfProfileOut(__METHOD__); return $status; } # Handle the user preference to force summaries here. Check if it's not a redirect. if (!$this->allowBlankSummary && !Title::newFromRedirect($this->textbox1)) { if (md5($this->summary) == $this->autoSumm) { $this->missingSummary = true; $status->fatal('missingsummary'); // or 'missingcommentheader' if $section == 'new'. Blegh $status->value = self::AS_SUMMARY_NEEDED; wfProfileOut(__METHOD__); return $status; } } $text = $this->textbox1; $result['sectionanchor'] = ''; if ($this->section == 'new') { if ($this->sectiontitle !== '') { // Insert the section title above the content. $text = wfMsgForContent('newsectionheaderdefaultlevel', $this->sectiontitle) . "\n\n" . $text; // Jump to the new section $result['sectionanchor'] = $wgParser->guessLegacySectionNameFromWikiText($this->sectiontitle); // If no edit summary was specified, create one automatically from the section // title and have it link to the new section. Otherwise, respect the summary as // passed. if ($this->summary === '') { $cleanSectionTitle = $wgParser->stripSectionName($this->sectiontitle); $this->summary = wfMsgForContent('newsectionsummary', $cleanSectionTitle); } } elseif ($this->summary !== '') { // Insert the section title above the content. $text = wfMsgForContent('newsectionheaderdefaultlevel', $this->summary) . "\n\n" . $text; // Jump to the new section $result['sectionanchor'] = $wgParser->guessLegacySectionNameFromWikiText($this->summary); // Create a link to the new section from the edit summary. $cleanSummary = $wgParser->stripSectionName($this->summary); $this->summary = wfMsgForContent('newsectionsummary', $cleanSummary); } } $status->value = self::AS_SUCCESS_NEW_ARTICLE; } else { # Article exists. Check for edit conflict. $this->mArticle->clear(); # Force reload of dates, etc. $timestamp = $this->mArticle->getTimestamp(); wfDebug("timestamp: {$timestamp}, edittime: {$this->edittime}\n"); if ($timestamp != $this->edittime) { $this->isConflict = true; if ($this->section == 'new') { if ($this->mArticle->getUserText() == $wgUser->getName() && $this->mArticle->getComment() == $this->summary) { // Probably a duplicate submission of a new comment. // This can happen when squid resends a request after // a timeout but the first one actually went through. wfDebug(__METHOD__ . ": duplicate new section submission; trigger edit conflict!\n"); } else { // New comment; suppress conflict. $this->isConflict = false; wfDebug(__METHOD__ . ": conflict suppressed; new section\n"); } } elseif ($this->section == '' && $this->userWasLastToEdit($wgUser->getId(), $this->edittime)) { # Suppress edit conflict with self, except for section edits where merging is required. wfDebug(__METHOD__ . ": Suppressing edit conflict, same user.\n"); $this->isConflict = false; } } // If sectiontitle is set, use it, otherwise use the summary as the section title (for // backwards compatibility with old forms/bots). if ($this->sectiontitle !== '') { $sectionTitle = $this->sectiontitle; } else { $sectionTitle = $this->summary; } if ($this->isConflict) { wfDebug(__METHOD__ . ": conflict! getting section '{$this->section}' for time '{$this->edittime}' (article time '{$timestamp}')\n"); $text = $this->mArticle->replaceSection($this->section, $this->textbox1, $sectionTitle, $this->edittime); } else { wfDebug(__METHOD__ . ": getting section '{$this->section}'\n"); $text = $this->mArticle->replaceSection($this->section, $this->textbox1, $sectionTitle); } if (is_null($text)) { wfDebug(__METHOD__ . ": activating conflict; section replace failed.\n"); $this->isConflict = true; $text = $this->textbox1; // do not try to merge here! } elseif ($this->isConflict) { # Attempt merge if ($this->mergeChangesInto($text)) { // Successful merge! Maybe we should tell the user the good news? $this->isConflict = false; wfDebug(__METHOD__ . ": Suppressing edit conflict, successful merge.\n"); } else { $this->section = ''; $this->textbox1 = $text; wfDebug(__METHOD__ . ": Keeping edit conflict, failed merge.\n"); } } if ($this->isConflict) { $status->setResult(false, self::AS_CONFLICT_DETECTED); wfProfileOut(__METHOD__); return $status; } // Run post-section-merge edit filter if (!wfRunHooks('EditFilterMerged', array($this, $text, &$this->hookError, $this->summary))) { # Error messages etc. could be handled within the hook... $status->fatal('hookaborted'); $status->value = self::AS_HOOK_ERROR; wfProfileOut(__METHOD__); return $status; } elseif ($this->hookError != '') { # ...or the hook could be expecting us to produce an error $status->fatal('hookaborted'); $status->value = self::AS_HOOK_ERROR_EXPECTED; wfProfileOut(__METHOD__); return $status; } # Handle the user preference to force summaries here, but not for null edits if ($this->section != 'new' && !$this->allowBlankSummary && $this->getOriginalContent() != $text && !Title::newFromRedirect($text)) { if (md5($this->summary) == $this->autoSumm) { $this->missingSummary = true; $status->fatal('missingsummary'); $status->value = self::AS_SUMMARY_NEEDED; wfProfileOut(__METHOD__); return $status; } } # And a similar thing for new sections if ($this->section == 'new' && !$this->allowBlankSummary) { if (trim($this->summary) == '') { $this->missingSummary = true; $status->fatal('missingsummary'); // or 'missingcommentheader' if $section == 'new'. Blegh $status->value = self::AS_SUMMARY_NEEDED; wfProfileOut(__METHOD__); return $status; } } # All's well wfProfileIn(__METHOD__ . '-sectionanchor'); $sectionanchor = ''; if ($this->section == 'new') { if ($this->textbox1 == '') { $this->missingComment = true; $status->fatal('missingcommenttext'); $status->value = self::AS_TEXTBOX_EMPTY; wfProfileOut(__METHOD__ . '-sectionanchor'); wfProfileOut(__METHOD__); return $status; } if ($this->sectiontitle !== '') { $sectionanchor = $wgParser->guessLegacySectionNameFromWikiText($this->sectiontitle); // If no edit summary was specified, create one automatically from the section // title and have it link to the new section. Otherwise, respect the summary as // passed. if ($this->summary === '') { $cleanSectionTitle = $wgParser->stripSectionName($this->sectiontitle); $this->summary = wfMsgForContent('newsectionsummary', $cleanSectionTitle); } } elseif ($this->summary !== '') { $sectionanchor = $wgParser->guessLegacySectionNameFromWikiText($this->summary); # This is a new section, so create a link to the new section # in the revision summary. $cleanSummary = $wgParser->stripSectionName($this->summary); $this->summary = wfMsgForContent('newsectionsummary', $cleanSummary); } } elseif ($this->section != '') { # Try to get a section anchor from the section source, redirect to edited section if header found # XXX: might be better to integrate this into Article::replaceSection # for duplicate heading checking and maybe parsing $hasmatch = preg_match("/^ *([=]{1,6})(.*?)(\\1) *\\n/i", $this->textbox1, $matches); # we can't deal with anchors, includes, html etc in the header for now, # headline would need to be parsed to improve this if ($hasmatch && strlen($matches[2]) > 0) { $sectionanchor = $wgParser->guessLegacySectionNameFromWikiText($matches[2]); } } $result['sectionanchor'] = $sectionanchor; wfProfileOut(__METHOD__ . '-sectionanchor'); // Save errors may fall down to the edit form, but we've now // merged the section into full text. Clear the section field // so that later submission of conflict forms won't try to // replace that into a duplicated mess. $this->textbox1 = $text; $this->section = ''; $status->value = self::AS_SUCCESS_UPDATE; } // Check for length errors again now that the section is merged in $this->kblength = (int) (strlen($text) / 1024); if ($this->kblength > $wgMaxArticleSize) { $this->tooBig = true; $status->setResult(false, self::AS_MAX_ARTICLE_SIZE_EXCEEDED); wfProfileOut(__METHOD__); return $status; } $flags = EDIT_DEFER_UPDATES | EDIT_AUTOSUMMARY | ($new ? EDIT_NEW : EDIT_UPDATE) | ($this->minoredit && !$this->isNew ? EDIT_MINOR : 0) | ($bot ? EDIT_FORCE_BOT : 0); $doEditStatus = $this->mArticle->doEdit($text, $this->summary, $flags); if ($doEditStatus->isOK()) { $result['redirect'] = Title::newFromRedirect($text) !== null; $this->commitWatch(); wfProfileOut(__METHOD__); return $status; } else { $this->isConflict = true; $doEditStatus->value = self::AS_END; // Destroys data doEdit() put in $status->value but who cares wfProfileOut(__METHOD__); return $doEditStatus; } }
/** * Attempt submission * @return bool false if output is done, true if the rest of the form should be displayed */ function attemptSave() { global $wgSpamRegex, $wgFilterCallback, $wgUser, $wgOut; global $wgMaxArticleSize; $fname = 'EditPage::attemptSave'; wfProfileIn($fname); wfProfileIn("{$fname}-checks"); # Reintegrate metadata if ($this->mMetaData != '') { $this->textbox1 .= "\n" . $this->mMetaData; } $this->mMetaData = ''; # Check for spam if ($wgSpamRegex && preg_match($wgSpamRegex, $this->textbox1, $matches)) { $this->spamPage($matches[0]); wfProfileOut("{$fname}-checks"); wfProfileOut($fname); return false; } if ($wgFilterCallback && $wgFilterCallback($this->mTitle, $this->textbox1, $this->section)) { # Error messages or other handling should be performed by the filter function wfProfileOut($fname); wfProfileOut("{$fname}-checks"); return false; } if (!wfRunHooks('EditFilter', array($this, $this->textbox1, $this->section, &$this->hookError))) { # Error messages etc. could be handled within the hook... wfProfileOut($fname); wfProfileOut("{$fname}-checks"); return false; } elseif ($this->hookError != '') { # ...or the hook could be expecting us to produce an error wfProfileOut("{$fname}-checks "); wfProfileOut($fname); return true; } if ($wgUser->isBlockedFrom($this->mTitle, false)) { # Check block state against master, thus 'false'. $this->blockedPage(); wfProfileOut("{$fname}-checks"); wfProfileOut($fname); return false; } $this->kblength = (int) (strlen($this->textbox1) / 1024); if ($this->kblength > $wgMaxArticleSize) { // Error will be displayed by showEditForm() $this->tooBig = true; wfProfileOut("{$fname}-checks"); wfProfileOut($fname); return true; } if (!$wgUser->isAllowed('edit')) { if ($wgUser->isAnon()) { $this->userNotLoggedInPage(); wfProfileOut("{$fname}-checks"); wfProfileOut($fname); return false; } else { $wgOut->readOnlyPage(); wfProfileOut("{$fname}-checks"); wfProfileOut($fname); return false; } } if (wfReadOnly()) { $wgOut->readOnlyPage(); wfProfileOut("{$fname}-checks"); wfProfileOut($fname); return false; } if ($wgUser->pingLimiter()) { $wgOut->rateLimited(); wfProfileOut("{$fname}-checks"); wfProfileOut($fname); return false; } # If the article has been deleted while editing, don't save it without # confirmation if ($this->deletedSinceEdit && !$this->recreate) { wfProfileOut("{$fname}-checks"); wfProfileOut($fname); return true; } wfProfileOut("{$fname}-checks"); # If article is new, insert it. $aid = $this->mTitle->getArticleID(GAID_FOR_UPDATE); if (0 == $aid) { // Late check for create permission, just in case *PARANOIA* if (!$this->mTitle->userCanCreate()) { wfDebug("{$fname}: no create permission\n"); $this->noCreatePermission(); wfProfileOut($fname); return; } # Don't save a new article if it's blank. if ('' == $this->textbox1) { $wgOut->redirect($this->mTitle->getFullURL()); wfProfileOut($fname); return false; } # If no edit comment was given when creating a new page, and what's being # created is a redirect, be smart and fill in a neat auto-comment if ($this->summary == '') { $rt = Title::newFromRedirect($this->textbox1); if (is_object($rt)) { $this->summary = wfMsgForContent('autoredircomment', $rt->getPrefixedText()); } } $isComment = $this->section == 'new'; $this->mArticle->insertNewArticle($this->textbox1, $this->summary, $this->minoredit, $this->watchthis, false, $isComment); wfProfileOut($fname); return false; } # Article exists. Check for edit conflict. $this->mArticle->clear(); # Force reload of dates, etc. $this->mArticle->forUpdate(true); # Lock the article if ($this->mArticle->getTimestamp() != $this->edittime) { $this->isConflict = true; if ($this->section == 'new') { if ($this->mArticle->getUserText() == $wgUser->getName() && $this->mArticle->getComment() == $this->summary) { // Probably a duplicate submission of a new comment. // This can happen when squid resends a request after // a timeout but the first one actually went through. wfDebug("EditPage::editForm duplicate new section submission; trigger edit conflict!\n"); } else { // New comment; suppress conflict. $this->isConflict = false; wfDebug("EditPage::editForm conflict suppressed; new section\n"); } } } $userid = $wgUser->getID(); if ($this->isConflict) { wfDebug("EditPage::editForm conflict! getting section '{$this->section}' for time '{$this->edittime}' (article time '" . $this->mArticle->getTimestamp() . "'\n"); $text = $this->mArticle->replaceSection($this->section, $this->textbox1, $this->summary, $this->edittime); } else { wfDebug("EditPage::editForm getting section '{$this->section}'\n"); $text = $this->mArticle->replaceSection($this->section, $this->textbox1, $this->summary); } if (is_null($text)) { wfDebug("EditPage::editForm activating conflict; section replace failed.\n"); $this->isConflict = true; $text = $this->textbox1; } # Suppress edit conflict with self, except for section edits where merging is required. if ($this->section == '' && 0 != $userid && $this->mArticle->getUser() == $userid) { wfDebug("Suppressing edit conflict, same user.\n"); $this->isConflict = false; } else { # switch from section editing to normal editing in edit conflict if ($this->isConflict) { # Attempt merge if ($this->mergeChangesInto($text)) { // Successful merge! Maybe we should tell the user the good news? $this->isConflict = false; wfDebug("Suppressing edit conflict, successful merge.\n"); } else { $this->section = ''; $this->textbox1 = $text; wfDebug("Keeping edit conflict, failed merge.\n"); } } } if ($this->isConflict) { wfProfileOut($fname); return true; } # If no edit comment was given when turning a page into a redirect, be smart # and fill in a neat auto-comment if ($this->summary == '') { $rt = Title::newFromRedirect($this->textbox1); if (is_object($rt)) { $this->summary = wfMsgForContent('autoredircomment', $rt->getPrefixedText()); } } # Handle the user preference to force summaries here if ($this->section != 'new' && !$this->allowBlankSummary && $wgUser->getOption('forceeditsummary')) { if (md5($this->summary) == $this->autoSumm) { $this->missingSummary = true; wfProfileOut($fname); return true; } } # All's well wfProfileIn("{$fname}-sectionanchor"); $sectionanchor = ''; if ($this->section == 'new') { if ($this->textbox1 == '') { $this->missingComment = true; return true; } if ($this->summary != '') { $sectionanchor = $this->sectionAnchor($this->summary); } } elseif ($this->section != '') { # Try to get a section anchor from the section source, redirect to edited section if header found # XXX: might be better to integrate this into Article::replaceSection # for duplicate heading checking and maybe parsing $hasmatch = preg_match("/^ *([=]{1,6})(.*?)(\\1) *\\n/i", $this->textbox1, $matches); # we can't deal with anchors, includes, html etc in the header for now, # headline would need to be parsed to improve this if ($hasmatch and strlen($matches[2]) > 0) { $sectionanchor = $this->sectionAnchor($matches[2]); } } wfProfileOut("{$fname}-sectionanchor"); // Save errors may fall down to the edit form, but we've now // merged the section into full text. Clear the section field // so that later submission of conflict forms won't try to // replace that into a duplicated mess. $this->textbox1 = $text; $this->section = ''; // Check for length errors again now that the section is merged in $this->kblength = (int) (strlen($text) / 1024); if ($this->kblength > $wgMaxArticleSize) { $this->tooBig = true; wfProfileOut($fname); return true; } # update the article here if ($this->mArticle->updateArticle($text, $this->summary, $this->minoredit, $this->watchthis, '', $sectionanchor)) { wfProfileOut($fname); return false; } else { $this->isConflict = true; } wfProfileOut($fname); return true; }
$unbrokenTitle = Title::makeTitleSafe( $brokenTitle->getNamespace(), preg_replace( '/^Broken\//', '', $brokenTitle->getDBkey() ) ); # Check that the broken title is a redirect $revision = Revision::newFromTitle( $brokenTitle ); if ( !$revision ) { echo "Does not exist: $line\n"; continue; } $text = $revision->getText(); if ( $text === false ) { echo "Cannot load text: $line\n"; continue; } $redir = Title::newFromRedirect( $text ); if ( !$redir ) { echo "Not a redirect: $line\n"; continue; } if ( $unbrokenTitle->exists() ) { # Exists already, just delete this redirect $article = new Article( $brokenTitle ); $success = $article->doDeleteArticle( 'Redundant redirect' ); if ( $success ) { echo "Deleted: $line\n"; } else { echo "Failed to delete: $line\n"; }
public function hArticleViewHeader(&$article) { // check if we are dealing with a redirect page. $this->found = Title::newFromRedirect($article->getContent()); return true; }
private function getAttrs($titleString, $ns) { $result = ''; $t = Title::newFromText($titleString, $ns); $revision = null; $nt = $t; while ($nt) { // follow redirects $t = $nt; $nt = null; $revision = Revision::newFromTitle($t); if ($revision) { $text =& $revision->getText(); $nt = Title::newFromRedirect($text); } } if ($t) { $result .= ' title="' . $this->escapeXml($t->getText()) . '"'; } if ($revision) { // get attributes from text if ($ns == NS_PERSON) { $xml = $this->getXml('person', $text); if (isset($xml)) { $name = $xml->name; if (isset($name)) { if ((string) $name['given']) { $result .= ' given="' . $this->escapeXml((string) $name['given']) . '"'; } if ((string) $name['surname']) { $result .= ' surname="' . $this->escapeXml((string) $name['surname']) . '"'; } if ((string) $name['title_prefix']) { $result .= ' title_prefix="' . $this->escapeXml((string) $name['title_prefix']) . '"'; } if ((string) $name['title_suffix']) { $result .= ' title_suffix="' . $this->escapeXml((string) $name['title_suffix']) . '"'; } } if (isset($xml->event_fact)) { foreach ($xml->event_fact as $ef) { if ($ef['type'] == 'Birth') { $result .= $this->getEventAttrs('birth', $ef); } else { if ($ef['type'] == 'Death') { $result .= $this->getEventAttrs('death', $ef); } else { if ($ef['type'] == 'Christening' || $ef['type'] == 'Baptism') { $result .= $this->getEventAttrs('chr', $ef); } else { if ($ef['type'] == 'Burial') { $result .= $this->getEventAttrs('burial', $ef); } } } } } } } } } return $result; }
/** * Propagate data in xml property to other articles if necessary * @param string $oldText contains text being replaced * @param String $text which we never touch when propagating places * @param bool $textChanged which we never touch when propagating places * @return bool true if propagation was successful */ protected function propagateEditData($oldText, &$text, &$textChanged) { global $wrIsGedcomUpload, $wgESINHandler; $result = true; // cache new xml - it's used right away to generate family badges on the related person pages, // if you don't cache it, the badges pick up the old html $this->cachePageXml(); // update people that link to this family, because the family-badge contents could have changed // TODO this could be made more efficient by only invalidating if names, birthdates, or deathdates have changed $u = new HTMLCacheUpdate($this->title, 'pagelinks'); $u->doUpdate(); // get current info $propagatedData = Family::getPropagatedData($this->xml); $redirTitle = Title::newFromRedirect($text); // get original info $origPropagatedData = Family::getPropagatedData(null); // don't bother construction page text from WLH in a gedcom upload because nothing will link to this new page if (!@$wrIsGedcomUpload && (!$oldText || mb_strpos($oldText, '<family>') === false)) { // oldText contains MediaWiki:noarticletext if the article is being created // construct <family> text from What Links Here $oldText = $this->getPageTextFromWLH(false); } $origXml = null; if ($oldText) { $origXml = StructuredData::getXml('family', $oldText); if (isset($origXml)) { $origPropagatedData = Family::getPropagatedData($origXml); } } // TODO!!! // Revert, Unmerge, and eventually Undo should be getting the current attrs for existing people from origPropagatedData // and getting the current attrs and redirect-titles for newly-added people from the Person pages when adding the family title to them // then unmerge wouldn't need to get them in unmerge, and revert wouldn't be broken, and undo won't break things. // This duplicates the functionality found in fromEditFields, but it allows us to update the pages without going through fromEditFields // and it doesn't require reading any pages that we weren't reading already. // Also, instead of isMerging, if this Family page is on the propagation manager blacklist, then you can't trust the prior version // and we should get the person attrs from the Person pages for _all_ family members. // Finally, make sure that after redirects we don't have 2 links to the same Person (and also two links to the same Family on Person pages). // ignore changes of the husband <-> wife role for the same person $temp = array_diff($propagatedData['husbands'], $origPropagatedData['wives']); $origPropagatedData['wives'] = array_diff($origPropagatedData['wives'], $propagatedData['husbands']); $propagatedData['husbands'] = $temp; $temp = array_diff($propagatedData['wives'], $origPropagatedData['husbands']); $origPropagatedData['husbands'] = array_diff($origPropagatedData['husbands'], $propagatedData['wives']); $propagatedData['wives'] = $temp; $result = $result && $this->propagateFamilyMemberEditData($propagatedData['husbands'], $origPropagatedData['husbands'], 'husband', 'spouse_of_family', $text, $textChanged); $result = $result && $this->propagateFamilyMemberEditData($propagatedData['wives'], $origPropagatedData['wives'], 'wife', 'spouse_of_family', $text, $textChanged); $result = $result && $this->propagateFamilyMemberEditData($propagatedData['children'], $origPropagatedData['children'], 'child', 'child_of_family', $text, $textChanged); if (StructuredData::removeDuplicateLinks('husband|wife|child', $text)) { $textChanged = true; } $result = $result && $wgESINHandler->propagateSINEdit($this->title, 'family', $this->titleString, $propagatedData, $origPropagatedData, $text, $textChanged); // ensure footer tag is still there (might have been removed by editing the last section) if ($redirTitle == null && strpos($text, ESINHandler::ESIN_FOOTER_TAG) === false) { if (strlen($text) > 0 && substr($text, strlen($text) - 1) != "\n") { $text .= "\n"; } $text .= ESINHandler::ESIN_FOOTER_TAG; $textChanged = true; } // update watchlist summary if changed $summary = Family::getSummary($this->xml, $this->title); $origSummary = Family::getSummary($origXml, $this->title); if ($summary != $origSummary) { StructuredData::updateWatchlistSummary($this->title, $summary); } // if it's a redirect, add the people, families, and images that were on this page to the redirect target // but don't bother updating the redir target during a merge if ($redirTitle != null && PropagationManager::isPropagatablePage($redirTitle)) { // get the text of the redir page $article = StructuredData::getArticle($redirTitle, true); if ($article) { $content =& $article->fetchContent(); $updated = false; // add husbands from this page to the redir page foreach ($origPropagatedData['husbands'] as $p) { // get propagated data for p $pd = Person::getPropagatedData(StructuredData::getXmlForTitle('person', Title::newFromText($p, NS_PERSON))); Family::updatePersonLink('husband', $p, $p, $pd, 'spouse_of_family', $content, $updated); } // add wives from this page to the redir page foreach ($origPropagatedData['wives'] as $p) { $pd = Person::getPropagatedData(StructuredData::getXmlForTitle('person', Title::newFromText($p, NS_PERSON))); Family::updatePersonLink('wife', $p, $p, $pd, 'spouse_of_family', $content, $updated); } // add children from this page to the redir page foreach ($origPropagatedData['children'] as $p) { $pd = Person::getPropagatedData(StructuredData::getXmlForTitle('person', Title::newFromText($p, NS_PERSON))); Family::updatePersonLink('child', $p, $p, $pd, 'child_of_family', $content, $updated); } // add images from this page to the redir page foreach ($origPropagatedData['images'] as $i) { ESINHandler::updateImageLink('family', $i['filename'], $i['filename'], $i['caption'], $content, $updated); } // update the redir page if necessary if ($updated) { $result = $result && $article->doEdit($content, 'Copy data from [[' . $this->title->getPrefixedText() . ']]', PROPAGATE_EDIT_FLAGS); } } } if (!$result) { error_log("ERROR! Family edit/rollback not propagated: {$this->titleString}\n"); } return $result; }
/** * Return an auto-generated summary if the text provided is a redirect. * * @param string $text The wikitext to check * @return string '' or an appropriate summary */ public static function getRedirectAutosummary($text) { $rt = Title::newFromRedirect($text); if (is_object($rt)) { return wfMsgForContent('autoredircomment', $rt->getFullText()); } else { return ''; } }
/** * Attempt submission (no UI) * @return one of the constants describing the result */ function internalAttemptSave(&$result, $bot = false) { global $wgFilterCallback, $wgUser, $wgOut, $wgParser; global $wgMaxArticleSize; $fname = 'EditPage::attemptSave'; wfProfileIn($fname); wfProfileIn("{$fname}-checks"); if (!wfRunHooks('EditPage::attemptSave', array(&$this))) { wfDebug("Hook 'EditPage::attemptSave' aborted article saving\n"); return self::AS_HOOK_ERROR; } # Check image redirect if ($this->mTitle->getNamespace() == NS_FILE && Title::newFromRedirect($this->textbox1) instanceof Title && !$wgUser->isAllowed('upload')) { if ($wgUser->isAnon()) { return self::AS_IMAGE_REDIRECT_ANON; } else { return self::AS_IMAGE_REDIRECT_LOGGED; } } # Reintegrate metadata if ($this->mMetaData != '') { $this->textbox1 .= "\n" . $this->mMetaData; } $this->mMetaData = ''; # Check for spam $match = self::matchSummarySpamRegex($this->summary); if ($match === false) { $match = self::matchSpamRegex($this->textbox1); } if ($match !== false) { $result['spam'] = $match; $ip = wfGetIP(); $pdbk = $this->mTitle->getPrefixedDBkey(); $match = str_replace("\n", '', $match); wfDebugLog('SpamRegex', "{$ip} spam regex hit [[{$pdbk}]]: \"{$match}\""); wfProfileOut("{$fname}-checks"); wfProfileOut($fname); return self::AS_SPAM_ERROR; } if ($wgFilterCallback && $wgFilterCallback($this->mTitle, $this->textbox1, $this->section, $this->hookError, $this->summary)) { # Error messages or other handling should be performed by the filter function wfProfileOut("{$fname}-checks"); wfProfileOut($fname); return self::AS_FILTERING; } if (!wfRunHooks('EditFilter', array($this, $this->textbox1, $this->section, &$this->hookError, $this->summary))) { # Error messages etc. could be handled within the hook... wfProfileOut("{$fname}-checks"); wfProfileOut($fname); return self::AS_HOOK_ERROR; } elseif ($this->hookError != '') { # ...or the hook could be expecting us to produce an error wfProfileOut("{$fname}-checks"); wfProfileOut($fname); return self::AS_HOOK_ERROR_EXPECTED; } if ($wgUser->isBlockedFrom($this->mTitle, false)) { # Check block state against master, thus 'false'. wfProfileOut("{$fname}-checks"); wfProfileOut($fname); return self::AS_BLOCKED_PAGE_FOR_USER; } $this->kblength = (int) (strlen($this->textbox1) / 1024); if ($this->kblength > $wgMaxArticleSize) { // Error will be displayed by showEditForm() $this->tooBig = true; wfProfileOut("{$fname}-checks"); wfProfileOut($fname); return self::AS_CONTENT_TOO_BIG; } if (!$wgUser->isAllowed('edit')) { if ($wgUser->isAnon()) { wfProfileOut("{$fname}-checks"); wfProfileOut($fname); return self::AS_READ_ONLY_PAGE_ANON; } else { wfProfileOut("{$fname}-checks"); wfProfileOut($fname); return self::AS_READ_ONLY_PAGE_LOGGED; } } if (wfReadOnly()) { wfProfileOut("{$fname}-checks"); wfProfileOut($fname); return self::AS_READ_ONLY_PAGE; } if ($wgUser->pingLimiter()) { wfProfileOut("{$fname}-checks"); wfProfileOut($fname); return self::AS_RATE_LIMITED; } # If the article has been deleted while editing, don't save it without # confirmation if ($this->wasDeletedSinceLastEdit() && !$this->recreate) { wfProfileOut("{$fname}-checks"); wfProfileOut($fname); return self::AS_ARTICLE_WAS_DELETED; } wfProfileOut("{$fname}-checks"); # If article is new, insert it. $aid = $this->mTitle->getArticleID(GAID_FOR_UPDATE); if (0 == $aid) { // Late check for create permission, just in case *PARANOIA* if (!$this->mTitle->userCan('create')) { wfDebug("{$fname}: no create permission\n"); wfProfileOut($fname); return self::AS_NO_CREATE_PERMISSION; } # Don't save a new article if it's blank. if ('' == $this->textbox1) { wfProfileOut($fname); return self::AS_BLANK_ARTICLE; } // Run post-section-merge edit filter if (!wfRunHooks('EditFilterMerged', array($this, $this->textbox1, &$this->hookError, $this->summary))) { # Error messages etc. could be handled within the hook... wfProfileOut($fname); return self::AS_HOOK_ERROR; } # Handle the user preference to force summaries here. Check if it's not a redirect. if (!$this->allowBlankSummary && !Title::newFromRedirect($this->textbox1)) { if (md5($this->summary) == $this->autoSumm) { $this->missingSummary = true; wfProfileOut($fname); return self::AS_SUMMARY_NEEDED; } } $isComment = $this->section == 'new'; $this->mArticle->insertNewArticle($this->textbox1, $this->summary, $this->minoredit, $this->watchthis, false, $isComment, $bot); wfProfileOut($fname); return self::AS_SUCCESS_NEW_ARTICLE; } # Article exists. Check for edit conflict. $this->mArticle->clear(); # Force reload of dates, etc. $this->mArticle->forUpdate(true); # Lock the article wfDebug("timestamp: {$this->mArticle->getTimestamp()}, edittime: {$this->edittime}\n"); if ($this->mArticle->getTimestamp() != $this->edittime) { $this->isConflict = true; if ($this->section == 'new') { if ($this->mArticle->getUserText() == $wgUser->getName() && $this->mArticle->getComment() == $this->summary) { // Probably a duplicate submission of a new comment. // This can happen when squid resends a request after // a timeout but the first one actually went through. wfDebug("EditPage::editForm duplicate new section submission; trigger edit conflict!\n"); } else { // New comment; suppress conflict. $this->isConflict = false; wfDebug("EditPage::editForm conflict suppressed; new section\n"); } } } $userid = $wgUser->getId(); # Suppress edit conflict with self, except for section edits where merging is required. if ($this->isConflict && $this->section == '' && $this->userWasLastToEdit($userid, $this->edittime)) { wfDebug("EditPage::editForm Suppressing edit conflict, same user.\n"); $this->isConflict = false; } if ($this->isConflict) { wfDebug("EditPage::editForm conflict! getting section '{$this->section}' for time '{$this->edittime}' (article time '" . $this->mArticle->getTimestamp() . "')\n"); $text = $this->mArticle->replaceSection($this->section, $this->textbox1, $this->summary, $this->edittime); } else { wfDebug("EditPage::editForm getting section '{$this->section}'\n"); $text = $this->mArticle->replaceSection($this->section, $this->textbox1, $this->summary); } if (is_null($text)) { wfDebug("EditPage::editForm activating conflict; section replace failed.\n"); $this->isConflict = true; $text = $this->textbox1; // do not try to merge here! } else { if ($this->isConflict) { # Attempt merge if ($this->mergeChangesInto($text)) { // Successful merge! Maybe we should tell the user the good news? $this->isConflict = false; wfDebug("EditPage::editForm Suppressing edit conflict, successful merge.\n"); } else { $this->section = ''; $this->textbox1 = $text; wfDebug("EditPage::editForm Keeping edit conflict, failed merge.\n"); } } } if ($this->isConflict) { wfProfileOut($fname); return self::AS_CONFLICT_DETECTED; } $oldtext = $this->mArticle->getContent(); // Run post-section-merge edit filter if (!wfRunHooks('EditFilterMerged', array($this, $text, &$this->hookError, $this->summary))) { # Error messages etc. could be handled within the hook... wfProfileOut($fname); return self::AS_HOOK_ERROR; } # Handle the user preference to force summaries here, but not for null edits if ($this->section != 'new' && !$this->allowBlankSummary && 0 != strcmp($oldtext, $text) && !Title::newFromRedirect($text)) { if (md5($this->summary) == $this->autoSumm) { $this->missingSummary = true; wfProfileOut($fname); return self::AS_SUMMARY_NEEDED; } } # And a similar thing for new sections if ($this->section == 'new' && !$this->allowBlankSummary) { if (trim($this->summary) == '') { $this->missingSummary = true; wfProfileOut($fname); return self::AS_SUMMARY_NEEDED; } } # All's well wfProfileIn("{$fname}-sectionanchor"); $sectionanchor = ''; if ($this->section == 'new') { if ($this->textbox1 == '') { $this->missingComment = true; return self::AS_TEXTBOX_EMPTY; } if ($this->summary != '') { $sectionanchor = $wgParser->guessSectionNameFromWikiText($this->summary); # This is a new section, so create a link to the new section # in the revision summary. $cleanSummary = $wgParser->stripSectionName($this->summary); $this->summary = wfMsgForContent('newsectionsummary', $cleanSummary); } } elseif ($this->section != '') { # Try to get a section anchor from the section source, redirect to edited section if header found # XXX: might be better to integrate this into Article::replaceSection # for duplicate heading checking and maybe parsing $hasmatch = preg_match("/^ *([=]{1,6})(.*?)(\\1) *\\n/i", $this->textbox1, $matches); # we can't deal with anchors, includes, html etc in the header for now, # headline would need to be parsed to improve this if ($hasmatch and strlen($matches[2]) > 0) { $sectionanchor = $wgParser->guessSectionNameFromWikiText($matches[2]); } } wfProfileOut("{$fname}-sectionanchor"); // Save errors may fall down to the edit form, but we've now // merged the section into full text. Clear the section field // so that later submission of conflict forms won't try to // replace that into a duplicated mess. $this->textbox1 = $text; $this->section = ''; // Check for length errors again now that the section is merged in $this->kblength = (int) (strlen($text) / 1024); if ($this->kblength > $wgMaxArticleSize) { $this->tooBig = true; wfProfileOut($fname); return self::AS_MAX_ARTICLE_SIZE_EXCEEDED; } # update the article here if ($this->mArticle->updateArticle($text, $this->summary, $this->minoredit, $this->watchthis, $bot, $sectionanchor)) { wfProfileOut($fname); return self::AS_SUCCESS_UPDATE; } else { $this->isConflict = true; } wfProfileOut($fname); return self::AS_END; }
function buildCurrentSlide($page, $notoc) { global $wgScript, $wgParser; if (trim($page) == "") { return ""; } $link = $wgScript . "?title={$page}"; $article = new Article(Title::newFromText($page)); while ($article->isRedirect()) { $redirectedArticleTitle = Title::newFromRedirect($article->getContent()); $article = new Article($redirectedArticleTitle); } if ($article->exists()) { $slideBody = $article->getContent() . $notoc . " __NOEDITSECTION__"; } else { $slideBody = "The [[{$page}]] slide does not exist. Did you want to <b>[[{$page} | create]]</b> it?"; } $this->currentPageLink = "<a href='{$link}'>{$page}</a>"; //html $this->slideBody = $wgParser->recursiveTagParse($slideBody); //wiki markup converted to html }
function ProcessContractorEditChanges($doit) { global $wgOut, $wgUser, $wgRequest; global $wgServer, $wgArticlePath; $debug = 1; $dbr = wfGetDB(DB_SLAVE); # first lets process the changes to the existing entries $contractorId = $wgRequest->getInt('contractor', 0); $modify_array = $wgRequest->getArray('cb_modify', array()); $NewExpiryDate = $wgRequest->getVal('NewExpiryDate', ''); $action = $wgRequest->getVal('action', ''); if (!$doit) { # create the form for submitting the same data after review $wgOut->addHTML("<form name='mainform' method='post'>"); $wgOut->addHTML("<input type='hidden' name='contractor' value='{$contractorId}'>"); foreach ($modify_array as $modify) { $wgOut->addHTML("<input type='hidden' name='cb_modify[]' value='{$modify}'>"); } $wgOut->addHTML("<input type='hidden' name='NewExpiryDate' value='{$NewExpiryDate}'>"); $wgOut->addHTML("<input type='hidden' name='action' value='{$action}'>"); $ContractorUser = WhiteListUserFromID($contractorId); $wgOut->addWikiText(wfMsg('whitelistoverview', $ContractorUser->getRealName())); } if ($action == 'ChangeDate') { $date = $NewExpiryDate == '' ? "" : date("Y-m-d H:i:s", strtotime($NewExpiryDate)); foreach ($modify_array as $entry => $rowid) { $dbr->begin(); if ($doit) { $dbr->update('whitelist', array('wl_expires_on' => $date, 'wl_updated_by_user_id' => $wgUser->getId()), array('wl_id' => $rowid), __METHOD__); } else { $pagename = $dbr->selectField('whitelist', 'wl_page_title', array('wl_id' => $rowid), __METHOD__); $wgOut->addWikiText(wfMsg('whitelistoverviewcd', $date, $pagename)); } $dbr->commit(); } } else { if ($action == 'SetEdit' || $action == 'SetView') { foreach ($modify_array as $entry => $rowid) { $dbr->begin(); if ($doit) { $dbr->update('whitelist', array('wl_allow_edit' => $action == 'SetEdit' ? 1 : 0, 'wl_updated_by_user_id' => $wgUser->getId()), array('wl_id' => $rowid), __METHOD__); } else { $pagename = $dbr->selectField('whitelist', 'wl_page_title', array('wl_id' => $rowid), __METHOD__); $wgOut->addWikiText(wfMsg('whitelistoverviewsa', $action == 'SetEdit' ? wfMsg('whitelisttablesetedit') : wfMsg('whitelisttablesetview'), $pagename)); } $dbr->commit(); } } else { if ($action == 'Remove') { foreach ($modify_array as $entry => $rowid) { $dbr->begin(); if ($doit) { $dbr->delete('whitelist', array('wl_id' => $rowid), __METHOD__); } else { $pagename = $dbr->selectField('whitelist', 'wl_page_title', array('wl_id' => $rowid), __METHOD__); self::DisplayWildCardMatches($pagename, wfMsg('whitelistoverviewrm', $pagename), -1); } $dbr->commit(); } } } } # now process the new additions, but make sure not to add duplicates $newPages = $wgRequest->getVal('newPages', ''); $expiryDate = $wgRequest->getVal('ExpiryDate', ''); $newAction = $wgRequest->getVal('newAction', ''); if (!$doit) { $wgOut->addHTML("<input type='hidden' name='newPages' value='{$newPages}'>"); $wgOut->addHTML("<input type='hidden' name='ExpiryDate' value='{$expiryDate}'>"); $wgOut->addHTML("<input type='hidden' name='newAction' value='{$newAction}'>"); } $pages = preg_split('/\\n/', $newPages, -1, PREG_SPLIT_NO_EMPTY); foreach ($pages as $entry => $pagename) { $pagename = trim($pagename); if ($pagename == '') { continue; } # If the input is a URL, then convert it back to a title $myArticlePath = str_replace("\$1", '', $wgArticlePath); $myArticlePath = str_replace("/", '\\/', $myArticlePath); $myServer = str_replace("/", '\\/', $wgServer); if (preg_match("/^{$myServer}{$myArticlePath}(.*)\$/", $pagename, $matches)) { $pagename = preg_replace('/_/', ' ', $matches[1]); } # ensure we have a wildcard of % $pagename = str_replace('*', '%', $pagename); if ($doit) { self::insertNewPage($dbr, $contractorId, $pagename, $newAction, $expiryDate); } else { self::DisplayWildCardMatches($pagename, wfMsg('whitelistoverviewna', $pagename, $newAction == 'SetEdit' ? wfMsg('whitelisttablesetedit') : wfMsg('whitelisttablesetview'), $expiryDate == '' ? wfMsg('whitelistnever') : $expiryDate), -1); } # check to see if the page is a redirect and if so, add the redirected-to page also $title = Title::newFromText($pagename); if ($title) { $article = new Article($title); $pagetext = $article->getContent(); $redirecttitle = Title::newFromRedirect($pagetext); if ($redirecttitle) { if ($doit) { self::insertNewPage($dbr, $contractorId, $redirecttitle->getPrefixedText(), $newAction, $expiryDate); } else { $wgOut->addWikiText(wfMsg('whitelistoverviewna', $redirecttitle->getPrefixedText(), $newAction == 'SetEdit' ? wfMsg('whitelisttablesetedit') : wfMsg('whitelisttablesetview'), $expiryDate)); } } } } if (!$doit) { $wgOut->addHTML("<p><input type='submit' value='" . wfMsg('whitelistnewtableprocess') . "' />"); $wgOut->addHTML("</form>"); } return; }
/** * Display a moved thread * * @param $thread Thread * @throws Exception */ function showMovedThread($thread) { global $wgLang; // Grab target thread if (!$thread->title()) { return; // Odd case: moved thread with no title? } $article = new Article($thread->title(), 0); $target = Title::newFromRedirect($article->getContent()); if (!$target) { throw new Exception("Thread " . $thread->id() . ' purports to be moved, ' . 'but no redirect found in text (' . $article->getContent() . ') of ' . $thread->root()->getTitle()->getPrefixedText() . '. Dying.'); } $t_thread = Threads::withRoot(new Article($target, 0)); // Grab data about the new post. $author = $thread->author(); $sig = Linker::userLink($author->getID(), $author->getName()) . Linker::userToolLinks($author->getID(), $author->getName()); $newTalkpage = is_object($t_thread) ? $t_thread->getTitle() : ''; $html = wfMessage('lqt_move_placeholder')->rawParams(Linker::link($target), $sig)->params($wgLang->date($thread->modified()), $wgLang->time($thread->modified()))->rawParams(Linker::link($newTalkpage))->parse(); $this->output->addHTML($html); }
private function getRedirectTargets() { $linkBatch = new LinkBatch(); $db = $this->getDB(); // find redirect targets for all redirect pages $this->profileDBIn(); $res = $db->select('pagelinks', array('pl_from', 'pl_namespace', 'pl_title'), array('pl_from' => array_keys($this->mPendingRedirectIDs)), __METHOD__); $this->profileDBOut(); while ($row = $db->fetchObject($res)) { $plfrom = intval($row->pl_from); // Bug 7304 workaround // ( http://bugzilla.wikipedia.org/show_bug.cgi?id=7304 ) // A redirect page may have more than one link. // This code will only use the first link returned. if (isset($this->mPendingRedirectIDs[$plfrom])) { // remove line when bug 7304 is fixed $titleStrFrom = $this->mPendingRedirectIDs[$plfrom]->getPrefixedText(); $titleStrTo = Title::makeTitle($row->pl_namespace, $row->pl_title)->getPrefixedText(); unset($this->mPendingRedirectIDs[$plfrom]); // remove line when bug 7304 is fixed // Avoid an infinite loop by checking if we have already processed this target if (!isset($this->mAllPages[$row->pl_namespace][$row->pl_title])) { $linkBatch->add($row->pl_namespace, $row->pl_title); } } else { // This redirect page has more than one link. // This is very slow, but safer until bug 7304 is resolved $title = Title::newFromID($plfrom); $titleStrFrom = $title->getPrefixedText(); $article = new Article($title); $text = $article->getContent(); $titleTo = Title::newFromRedirect($text); $titleStrTo = $titleTo->getPrefixedText(); if (is_null($titleStrTo)) { ApiBase::dieDebug(__METHOD__, 'Bug7304 workaround: redir target from {$title->getPrefixedText()} not found'); } // Avoid an infinite loop by checking if we have already processed this target if (!isset($this->mAllPages[$titleTo->getNamespace()][$titleTo->getDBkey()])) { $linkBatch->addObj($titleTo); } } $this->mRedirectTitles[$titleStrFrom] = $titleStrTo; } $db->freeResult($res); // All IDs must exist in the page table if (!empty($this->mPendingRedirectIDs[$plfrom])) { ApiBase::dieDebug(__METHOD__, 'Invalid redirect IDs were found'); } return $linkBatch; }