Esempio n. 1
0
 public function execute()
 {
     $this->output("Looking for pages with page_latest set to 0...\n");
     $dbw = wfGetDB(DB_MASTER);
     $result = $dbw->select('page', array('page_id', 'page_namespace', 'page_title'), array('page_latest' => 0), __METHOD__);
     $n = 0;
     foreach ($result as $row) {
         $pageId = intval($row->page_id);
         $title = Title::makeTitle($row->page_namespace, $row->page_title);
         $name = $title->getPrefixedText();
         $latestTime = $dbw->selectField('revision', 'MAX(rev_timestamp)', array('rev_page' => $pageId), __METHOD__);
         if (!$latestTime) {
             $this->output(wfWikiID() . " {$pageId} [[{$name}]] can't find latest rev time?!\n");
             continue;
         }
         $revision = Revision::loadFromTimestamp($dbw, $title, $latestTime);
         if (is_null($revision)) {
             $this->output(wfWikiID() . " {$pageId} [[{$name}]] latest time {$latestTime}, can't find revision id\n");
             continue;
         }
         $id = $revision->getId();
         $this->output(wfWikiID() . " {$pageId} [[{$name}]] latest time {$latestTime}, rev id {$id}\n");
         if ($this->hasOption('fix')) {
             $article = new Article($title);
             $article->updateRevisionOn($dbw, $revision);
         }
         $n++;
     }
     $dbw->freeResult($result);
     $this->output("Done! Processed {$n} pages.\n");
     if (!$this->hasOption('fix')) {
         $this->output("This was a dry run; rerun with --fix to update page_latest.\n");
     }
 }
Esempio n. 2
0
 /**
  * @param $section empty/null/false or a section number (0, 1, 2, T1, T2...)
  * @param $text String: new text of the section
  * @param $summary String: new section's subject, only if $section is 'new'
  * @param $edittime String: revision timestamp or null to use the current revision
  * @return string Complete article text, or null if error
  */
 public function replaceSection($section, $text, $summary = '', $edittime = null)
 {
     wfProfileIn(__METHOD__);
     if (strval($section) == '') {
         // Whole-page edit; let the whole text through
     } else {
         if (is_null($edittime)) {
             $rev = Revision::newFromTitle($this->mTitle);
         } else {
             $dbw = wfGetDB(DB_MASTER);
             $rev = Revision::loadFromTimestamp($dbw, $this->mTitle, $edittime);
         }
         if (!$rev) {
             wfDebug("Article::replaceSection asked for bogus section (page: " . $this->getId() . "; section: {$section}; edittime: {$edittime})\n");
             wfProfileOut(__METHOD__);
             return null;
         }
         $oldtext = $rev->getText();
         if ($section == 'new') {
             # Inserting a new section
             $subject = $summary ? wfMsgForContent('newsectionheaderdefaultlevel', $summary) . "\n\n" : '';
             $text = strlen(trim($oldtext)) > 0 ? "{$oldtext}\n\n{$subject}{$text}" : "{$subject}{$text}";
         } else {
             # Replacing an existing section; roll out the big guns
             global $wgParser;
             $text = $wgParser->replaceSection($oldtext, $section, $text);
         }
     }
     wfProfileOut(__METHOD__);
     return $text;
 }
 /**
  * @param $vars AbuseFilterVariableHolder
  * @return AFPData|array|int|mixed|null|string
  * @throws MWException
  * @throws AFPException
  */
 function compute($vars)
 {
     $parameters = $this->mParameters;
     $result = null;
     if (!wfRunHooks('AbuseFilter-interceptVariable', array($this->mMethod, $vars, $parameters, &$result))) {
         return $result instanceof AFPData ? $result : AFPData::newFromPHPVar($result);
     }
     switch ($this->mMethod) {
         case 'diff':
             $text1Var = $parameters['oldtext-var'];
             $text2Var = $parameters['newtext-var'];
             $text1 = $vars->getVar($text1Var)->toString() . "\n";
             $text2 = $vars->getVar($text2Var)->toString() . "\n";
             $result = wfDiff($text1, $text2);
             break;
         case 'diff-split':
             $diff = $vars->getVar($parameters['diff-var'])->toString();
             $line_prefix = $parameters['line-prefix'];
             $diff_lines = explode("\n", $diff);
             $interest_lines = array();
             foreach ($diff_lines as $line) {
                 if (substr($line, 0, 1) === $line_prefix) {
                     $interest_lines[] = substr($line, strlen($line_prefix));
                 }
             }
             $result = $interest_lines;
             break;
         case 'links-from-wikitext':
             // This should ONLY be used when sharing a parse operation with the edit.
             /* @var WikiPage $article */
             $article = $parameters['article'];
             if ($article !== null && (!defined('MW_SUPPORTS_CONTENTHANDLER') || $article->getContentModel() === CONTENT_MODEL_WIKITEXT)) {
                 $textVar = $parameters['text-var'];
                 // XXX: Use prepareContentForEdit. But we need a Content object for that.
                 $new_text = $vars->getVar($textVar)->toString();
                 $content = ContentHandler::makeContent($new_text, $article->getTitle());
                 $editInfo = $article->prepareContentForEdit($content);
                 $links = array_keys($editInfo->output->getExternalLinks());
                 $result = $links;
                 break;
             }
             // Otherwise fall back to database
         // Otherwise fall back to database
         case 'links-from-wikitext-nonedit':
         case 'links-from-wikitext-or-database':
             // TODO: use Content object instead, if available! In any case, use WikiPage, not Article.
             $article = self::articleFromTitle($parameters['namespace'], $parameters['title']);
             if ($vars->getVar('context')->toString() == 'filter') {
                 $links = $this->getLinksFromDB($article);
                 wfDebug("AbuseFilter: loading old links from DB\n");
             } elseif (!defined('MW_SUPPORTS_CONTENTHANDLER') || $article->getContentModel() === CONTENT_MODEL_WIKITEXT) {
                 wfDebug("AbuseFilter: loading old links from Parser\n");
                 $textVar = $parameters['text-var'];
                 $wikitext = $vars->getVar($textVar)->toString();
                 $editInfo = $this->parseNonEditWikitext($wikitext, $article);
                 $links = array_keys($editInfo->output->getExternalLinks());
             } else {
                 // TODO: Get links from Content object. But we don't have the content object.
                 //      And for non-text content, $wikitext is usually not going to be a valid
                 //      serialization, but rather some dummy text for filtering.
                 $links = array();
             }
             $result = $links;
             break;
         case 'link-diff-added':
         case 'link-diff-removed':
             $oldLinkVar = $parameters['oldlink-var'];
             $newLinkVar = $parameters['newlink-var'];
             $oldLinks = $vars->getVar($oldLinkVar)->toString();
             $newLinks = $vars->getVar($newLinkVar)->toString();
             $oldLinks = explode("\n", $oldLinks);
             $newLinks = explode("\n", $newLinks);
             if ($this->mMethod == 'link-diff-added') {
                 $result = array_diff($newLinks, $oldLinks);
             }
             if ($this->mMethod == 'link-diff-removed') {
                 $result = array_diff($oldLinks, $newLinks);
             }
             break;
         case 'parse-wikitext':
             // Should ONLY be used when sharing a parse operation with the edit.
             $article = $parameters['article'];
             if ($article !== null && (!defined('MW_SUPPORTS_CONTENTHANDLER') || $article->getContentModel() === CONTENT_MODEL_WIKITEXT)) {
                 $textVar = $parameters['wikitext-var'];
                 // XXX: Use prepareContentForEdit. But we need a Content object for that.
                 $new_text = $vars->getVar($textVar)->toString();
                 $editInfo = $article->prepareTextForEdit($new_text);
                 if (isset($parameters['pst']) && $parameters['pst']) {
                     $result = $editInfo->pstContent->serialize($editInfo->format);
                 } else {
                     $newHTML = $editInfo->output->getText();
                     // Kill the PP limit comments. Ideally we'd just remove these by not setting the
                     // parser option, but then we can't share a parse operation with the edit, which is bad.
                     $result = preg_replace('/<!--\\s*NewPP limit report[^>]*-->\\s*$/si', '', $newHTML);
                 }
                 break;
             }
             // Otherwise fall back to database
         // Otherwise fall back to database
         case 'parse-wikitext-nonedit':
             // TODO: use Content object instead, if available! In any case, use WikiPage, not Article.
             $article = self::articleFromTitle($parameters['namespace'], $parameters['title']);
             $textVar = $parameters['wikitext-var'];
             if (!defined('MW_SUPPORTS_CONTENTHANDLER') || $article->getContentModel() === CONTENT_MODEL_WIKITEXT) {
                 if (isset($parameters['pst']) && $parameters['pst']) {
                     // $textVar is already PSTed when it's not loaded from an ongoing edit.
                     $result = $vars->getVar($textVar)->toString();
                 } else {
                     $text = $vars->getVar($textVar)->toString();
                     $editInfo = $this->parseNonEditWikitext($text, $article);
                     $result = $editInfo->output->getText();
                 }
             } else {
                 // TODO: Parser Output from Content object. But we don't have the content object.
                 //      And for non-text content, $wikitext is usually not going to be a valid
                 //      serialization, but rather some dummy text for filtering.
                 $result = '';
             }
             break;
         case 'strip-html':
             $htmlVar = $parameters['html-var'];
             $html = $vars->getVar($htmlVar)->toString();
             $result = StringUtils::delimiterReplace('<', '>', '', $html);
             break;
         case 'load-recent-authors':
             $cutOff = $parameters['cutoff'];
             $title = Title::makeTitle($parameters['namespace'], $parameters['title']);
             if (!$title->exists()) {
                 $result = '';
                 break;
             }
             $dbr = wfGetDB(DB_SLAVE);
             $res = $dbr->select('revision', 'DISTINCT rev_user_text', array('rev_page' => $title->getArticleID(), 'rev_timestamp<' . $dbr->addQuotes($dbr->timestamp($cutOff))), __METHOD__, array('ORDER BY' => 'rev_timestamp DESC', 'LIMIT' => 10));
             $users = array();
             foreach ($res as $row) {
                 $users[] = $row->rev_user_text;
             }
             $result = $users;
             break;
         case 'get-page-restrictions':
             $action = $parameters['action'];
             $title = Title::makeTitle($parameters['namespace'], $parameters['title']);
             $rights = $title->getRestrictions($action);
             $rights = count($rights) ? $rights : array();
             $result = $rights;
             break;
         case 'simple-user-accessor':
             $user = $parameters['user'];
             $method = $parameters['method'];
             if (!$user) {
                 throw new MWException('No user parameter given.');
             }
             $obj = self::getUserObject($user);
             if (!$obj) {
                 throw new MWException("Invalid username {$user}");
             }
             $result = call_user_func(array($obj, $method));
             break;
         case 'user-age':
             $user = $parameters['user'];
             $asOf = $parameters['asof'];
             $obj = self::getUserObject($user);
             if ($obj->getId() == 0) {
                 $result = 0;
                 break;
             }
             $registration = $obj->getRegistration();
             $result = wfTimestamp(TS_UNIX, $asOf) - wfTimestampOrNull(TS_UNIX, $registration);
             break;
         case 'user-groups':
             // Deprecated but needed by old log entries
             $user = $parameters['user'];
             $obj = self::getUserObject($user);
             $result = $obj->getEffectiveGroups();
             break;
         case 'length':
             $s = $vars->getVar($parameters['length-var'])->toString();
             $result = strlen($s);
             break;
         case 'subtract':
             $v1 = $vars->getVar($parameters['val1-var'])->toFloat();
             $v2 = $vars->getVar($parameters['val2-var'])->toFloat();
             $result = $v1 - $v2;
             break;
         case 'revision-text-by-id':
             $rev = Revision::newFromId($parameters['revid']);
             $result = AbuseFilter::revisionToString($rev);
             break;
         case 'revision-text-by-timestamp':
             $timestamp = $parameters['timestamp'];
             $title = Title::makeTitle($parameters['namespace'], $parameters['title']);
             $dbr = wfGetDB(DB_SLAVE);
             $rev = Revision::loadFromTimestamp($dbr, $title, $timestamp);
             $result = AbuseFilter::revisionToString($rev);
             break;
         default:
             if (wfRunHooks('AbuseFilter-computeVariable', array($this->mMethod, $vars, $parameters, &$result))) {
                 throw new AFPException('Unknown variable compute type ' . $this->mMethod);
             }
     }
     return $result instanceof AFPData ? $result : AFPData::newFromPHPVar($result);
 }
Esempio n. 4
0
 /**
  * @return Revision
  */
 function getBaseRevision()
 {
     if (!$this->mBaseRevision) {
         $db = wfGetDB(DB_MASTER);
         $baseRevision = Revision::loadFromTimestamp($db, $this->mTitle, $this->edittime);
         return $this->mBaseRevision = $baseRevision;
     } else {
         return $this->mBaseRevision;
     }
 }
 function importOldRevision()
 {
     $dbw = wfGetDB(DB_MASTER);
     # Sneak a single revision into place
     $user = User::newFromName($this->getUser());
     if ($user) {
         $userId = intval($user->getId());
         $userText = $user->getName();
     } else {
         $userId = 0;
         $userText = $this->getUser();
     }
     // avoid memory leak...?
     $linkCache =& LinkCache::singleton();
     $linkCache->clear();
     $article = new Article($this->title);
     $pageId = $article->getId();
     if ($pageId == 0) {
         # must create the page...
         $pageId = $article->insertOn($dbw);
         $created = true;
     } else {
         $created = false;
         $prior = Revision::loadFromTimestamp($dbw, $this->title, $this->timestamp);
         if (!is_null($prior)) {
             // FIXME: this could fail slightly for multiple matches :P
             wfDebug(__METHOD__ . ": skipping existing revision for [[" . $this->title->getPrefixedText() . "]], timestamp " . $this->timestamp . "\n");
             return false;
         }
     }
     # FIXME: Use original rev_id optionally
     # FIXME: blah blah blah
     #if( $numrows > 0 ) {
     #	return wfMsg( "importhistoryconflict" );
     #}
     # Insert the row
     $revision = new Revision(array('page' => $pageId, 'text' => $this->getText(), 'comment' => $this->getComment(), 'user' => $userId, 'user_text' => $userText, 'timestamp' => $this->timestamp, 'minor_edit' => $this->minor));
     $revId = $revision->insertOn($dbw);
     $changed = $article->updateIfNewerOn($dbw, $revision);
     if ($created) {
         wfDebug(__METHOD__ . ": running onArticleCreate\n");
         Article::onArticleCreate($this->title);
         wfDebug(__METHOD__ . ": running create updates\n");
         $article->createUpdates($revision);
     } elseif ($changed) {
         wfDebug(__METHOD__ . ": running onArticleEdit\n");
         Article::onArticleEdit($this->title);
         wfDebug(__METHOD__ . ": running edit updates\n");
         $article->editUpdates($this->getText(), $this->getComment(), $this->minor, $this->timestamp, $revId);
     }
     return true;
 }
Esempio n. 6
0
 /**
  * @return string Complete article text, or null if error
  */
 function replaceSection($section, $text, $summary = '', $edittime = NULL)
 {
     wfProfileIn(__METHOD__);
     if ($section == '') {
         // Whole-page edit; let the text through unmolested.
     } else {
         if (is_null($edittime)) {
             $rev = Revision::newFromTitle($this->mTitle);
         } else {
             $dbw =& wfGetDB(DB_MASTER);
             $rev = Revision::loadFromTimestamp($dbw, $this->mTitle, $edittime);
         }
         if (is_null($rev)) {
             wfDebug("Article::replaceSection asked for bogus section (page: " . $this->getId() . "; section: {$section}; edittime: {$edittime})\n");
             return null;
         }
         $oldtext = $rev->getText();
         if ($section == 'new') {
             if ($summary) {
                 $subject = "== {$summary} ==\n\n";
             }
             $text = $oldtext . "\n\n" . $subject . $text;
         } else {
             global $wgParser;
             $text = $wgParser->replaceSection($oldtext, $section, $text);
         }
     }
     wfProfileOut(__METHOD__);
     return $text;
 }
Esempio n. 7
0
 /**
  * @param string|number|null|bool $sectionId Section identifier as a number or string
  * (e.g. 0, 1 or 'T-1'), null/false or an empty string for the whole page
  * or 'new' for a new section.
  * @param Content $sectionContent New content of the section.
  * @param string $sectionTitle New section's subject, only if $section is "new".
  * @param string $edittime Revision timestamp or null to use the current revision.
  *
  * @throws MWException
  * @return Content New complete article content, or null if error.
  *
  * @since 1.21
  * @deprecated since 1.24, use replaceSectionAtRev instead
  */
 public function replaceSectionContent($sectionId, Content $sectionContent, $sectionTitle = '', $edittime = null)
 {
     wfProfileIn(__METHOD__);
     $baseRevId = null;
     if ($edittime && $sectionId !== 'new') {
         $dbw = wfGetDB(DB_MASTER);
         $rev = Revision::loadFromTimestamp($dbw, $this->mTitle, $edittime);
         if ($rev) {
             $baseRevId = $rev->getId();
         }
     }
     wfProfileOut(__METHOD__);
     return $this->replaceSectionAtRev($sectionId, $sectionContent, $sectionTitle, $baseRevId);
 }
Esempio n. 8
0
 /**
  * @access private
  * @todo document
  */
 function mergeChangesInto(&$editText)
 {
     $fname = 'EditPage::mergeChangesInto';
     wfProfileIn($fname);
     $db =& wfGetDB(DB_MASTER);
     // This is the revision the editor started from
     $baseRevision = Revision::loadFromTimestamp($db, $this->mArticle->mTitle, $this->edittime);
     if (is_null($baseRevision)) {
         wfProfileOut($fname);
         return false;
     }
     $baseText = $baseRevision->getText();
     // The current state, we want to merge updates into it
     $currentRevision = Revision::loadFromTitle($db, $this->mArticle->mTitle);
     if (is_null($currentRevision)) {
         wfProfileOut($fname);
         return false;
     }
     $currentText = $currentRevision->getText();
     if (wfMerge($baseText, $editText, $currentText, $result)) {
         $editText = $result;
         wfProfileOut($fname);
         return true;
     } else {
         wfProfileOut($fname);
         return false;
     }
 }
Esempio n. 9
0
$fixit = isset($options['fix']);
$fname = 'attachLatest';
echo "Looking for pages with page_latest set to 0...\n";
$dbw =& wfGetDB(DB_MASTER);
$result = $dbw->select('page', array('page_id', 'page_namespace', 'page_title'), array('page_latest' => 0), $fname);
$n = 0;
while ($row = $dbw->fetchObject($result)) {
    $pageId = intval($row->page_id);
    $title = Title::makeTitle($row->page_namespace, $row->page_title);
    $name = $title->getPrefixedText();
    $latestTime = $dbw->selectField('revision', 'MAX(rev_timestamp)', array('rev_page' => $pageId), $fname);
    if (!$latestTime) {
        echo "{$wgDBname} {$pageId} [[{$name}]] can't find latest rev time?!\n";
        continue;
    }
    $revision = Revision::loadFromTimestamp($dbw, $title, $latestTime);
    if (is_null($revision)) {
        echo "{$wgDBname} {$pageId} [[{$name}]] latest time {$latestTime}, can't find revision id\n";
        continue;
    }
    $id = $revision->getId();
    echo "{$wgDBname} {$pageId} [[{$name}]] latest time {$latestTime}, rev id {$id}\n";
    if ($fixit) {
        $article = new Article($title);
        $article->updateRevisionOn($dbw, $revision);
    }
    $n++;
}
$dbw->freeResult($result);
echo "Done! Processed {$n} pages.\n";
if (!$fixit) {
Esempio n. 10
0
 function getTextOfLastEditWithSectionReplacedOrAdded($section, $text, $summary = '', $edittime = NULL)
 {
     $fname = 'Article::getTextOfLastEditWithSectionReplacedOrAdded';
     if ($section != '') {
         if (is_null($edittime)) {
             $rev = Revision::newFromTitle($this->mTitle);
         } else {
             $dbw =& wfGetDB(DB_MASTER);
             $rev = Revision::loadFromTimestamp($dbw, $this->mTitle, $edittime);
         }
         $oldtext = $rev->getText();
         if ($section == 'new') {
             if ($summary) {
                 $subject = "== {$summary} ==\n\n";
             }
             $text = $oldtext . "\n\n" . $subject . $text;
         } else {
             # strip NOWIKI etc. to avoid confusion (true-parameter causes HTML
             # comments to be stripped as well)
             $striparray = array();
             $parser = new Parser();
             $parser->mOutputType = OT_WIKI;
             $parser->mOptions = new ParserOptions();
             $oldtext = $parser->strip($oldtext, $striparray, true);
             # now that we can be sure that no pseudo-sections are in the source,
             # split it up
             # Unfortunately we can't simply do a preg_replace because that might
             # replace the wrong section, so we have to use the section counter instead
             $secs = preg_split('/(^=+.+?=+|^<h[1-6].*?' . '>.*?<\\/h[1-6].*?' . '>)(?!\\S)/mi', $oldtext, -1, PREG_SPLIT_DELIM_CAPTURE);
             $secs[$section * 2] = $text . "\n\n";
             // replace with edited
             # section 0 is top (intro) section
             if ($section != 0) {
                 # headline of old section - we need to go through this section
                 # to determine if there are any subsections that now need to
                 # be erased, as the mother section has been replaced with
                 # the text of all subsections.
                 $headline = $secs[$section * 2 - 1];
                 preg_match('/^(=+).+?=+|^<h([1-6]).*?' . '>.*?<\\/h[1-6].*?' . '>(?!\\S)/mi', $headline, $matches);
                 $hlevel = $matches[1];
                 # determine headline level for wikimarkup headings
                 if (strpos($hlevel, '=') !== false) {
                     $hlevel = strlen($hlevel);
                 }
                 $secs[$section * 2 - 1] = '';
                 // erase old headline
                 $count = $section + 1;
                 $break = false;
                 while (!empty($secs[$count * 2 - 1]) && !$break) {
                     $subheadline = $secs[$count * 2 - 1];
                     preg_match('/^(=+).+?=+|^<h([1-6]).*?' . '>.*?<\\/h[1-6].*?' . '>(?!\\S)/mi', $subheadline, $matches);
                     $subhlevel = $matches[1];
                     if (strpos($subhlevel, '=') !== false) {
                         $subhlevel = strlen($subhlevel);
                     }
                     if ($subhlevel > $hlevel) {
                         // erase old subsections
                         $secs[$count * 2 - 1] = '';
                         $secs[$count * 2] = '';
                     }
                     if ($subhlevel <= $hlevel) {
                         $break = true;
                     }
                     $count++;
                 }
             }
             $text = join('', $secs);
             # reinsert the stuff that we stripped out earlier
             $text = $parser->unstrip($text, $striparray);
             $text = $parser->unstripNoWiki($text, $striparray);
         }
     }
     return $text;
 }
Esempio n. 11
0
 /**
  * @desc Saving CSS content
  * If there is more recent edit it will try to merge text and save.
  * Returns false when conflict is found and cannot be resolved
  *
  * @param string $content
  * @param string $summary
  * @param bool $isMinor
  * @param int $editTime timestamp
  * @param User $user
  * @return Status|bool
  */
 public function saveCssFileContent($content, $summary, $isMinor, $editTime, $user)
 {
     $cssTitle = $this->getCssFileTitle();
     $flags = 0;
     if ($cssTitle instanceof Title) {
         $aid = $cssTitle->getArticleID(Title::GAID_FOR_UPDATE);
         $flags |= $aid == 0 ? EDIT_NEW : EDIT_UPDATE;
         if ($isMinor) {
             $flags |= EDIT_MINOR;
         }
         $db = wfGetDB(DB_MASTER);
         $currentRevision = Revision::loadFromTitle($db, $cssTitle);
         // we handle both - edit and creation conflicts below
         if (!empty($currentRevision) && $editTime != $currentRevision->getTimestamp()) {
             $result = '';
             $currentText = $currentRevision->getText();
             if (!$editTime) {
                 // the css did not exist when the editor was started, so the base revision for
                 // parallel edits is an empty file
                 $baseText = '';
             } else {
                 $baseText = Revision::loadFromTimestamp($db, $this->getCssFileTitle(), $editTime)->getText();
             }
             // remove windows endlines from input before merging texts
             $content = str_replace("\r", "", $content);
             if (wfMerge($baseText, $content, $currentText, $result)) {
                 // This conflict can be resolved
                 $content = $result;
             } else {
                 // We have real conflict here
                 return false;
             }
         }
         $page = new WikiPage($cssTitle);
         $status = $page->doEdit($content, $summary, $flags, false, $user);
         return $status;
     }
     return Status::newFatal('special-css-saving-internal-error');
 }
 function compute($vars)
 {
     $parameters = $this->mParameters;
     $result = null;
     switch ($this->mMethod) {
         case 'diff':
             $text1Var = $parameters['oldtext-var'];
             $text2Var = $parameters['newtext-var'];
             $text1 = $vars->getVar($text1Var)->toString();
             $text2 = $vars->getVar($text2Var)->toString();
             $result = wfDiff($text1, $text2);
             $result = trim(preg_replace("/^\\\\ No newline at end of file\n/m", '', $result));
             break;
         case 'diff-split':
             $diff = $vars->getVar($parameters['diff-var'])->toString();
             $line_prefix = $parameters['line-prefix'];
             $diff_lines = explode("\n", $diff);
             $interest_lines = array();
             foreach ($diff_lines as $line) {
                 if (substr($line, 0, 1) === $line_prefix) {
                     $interest_lines[] = substr($line, strlen($line_prefix));
                 }
             }
             $result = $interest_lines;
             break;
         case 'links-from-wikitext':
             // This should ONLY be used when sharing a parse operation with the edit.
             $article = $parameters['article'];
             if ($article) {
                 $textVar = $parameters['text-var'];
                 $new_text = $vars->getVar($textVar)->toString();
                 $editInfo = $article->prepareTextForEdit($new_text);
                 $links = array_keys($editInfo->output->getExternalLinks());
                 $result = $links;
                 break;
             }
             // Otherwise fall back to database
         // Otherwise fall back to database
         case 'links-from-wikitext-nonedit':
         case 'links-from-wikitext-or-database':
             $article = self::articleFromTitle($parameters['namespace'], $parameters['title']);
             if ($vars->getVar('context')->toString() == 'filter') {
                 $links = $this->getLinksFromDB($article);
                 wfDebug("AbuseFilter: loading old links from DB\n");
             } else {
                 wfDebug("AbuseFilter: loading old links from Parser\n");
                 $textVar = $parameters['text-var'];
                 $wikitext = $vars->getVar($textVar)->toString();
                 $editInfo = $this->parseNonEditWikitext($wikitext, $article);
                 $links = array_keys($editInfo->output->getExternalLinks());
             }
             $result = $links;
             break;
         case 'link-diff-added':
         case 'link-diff-removed':
             $oldLinkVar = $parameters['oldlink-var'];
             $newLinkVar = $parameters['newlink-var'];
             $oldLinks = $vars->getVar($oldLinkVar)->toString();
             $newLinks = $vars->getVar($newLinkVar)->toString();
             $oldLinks = explode("\n", $oldLinks);
             $newLinks = explode("\n", $newLinks);
             if ($this->mMethod == 'link-diff-added') {
                 $result = array_diff($newLinks, $oldLinks);
             }
             if ($this->mMethod == 'link-diff-removed') {
                 $result = array_diff($oldLinks, $newLinks);
             }
             break;
         case 'parse-wikitext':
             // Should ONLY be used when sharing a parse operation with the edit.
             $article = $parameters['article'];
             if ($article) {
                 $textVar = $parameters['wikitext-var'];
                 $new_text = $vars->getVar($textVar)->toString();
                 $editInfo = $article->prepareTextForEdit($new_text);
                 $newHTML = $editInfo->output->getText();
                 // Kill the PP limit comments. Ideally we'd just remove these by not setting the
                 // parser option, but then we can't share a parse operation with the edit, which is bad.
                 $result = preg_replace('/<!--\\s*NewPP limit report[^>]*-->\\s*$/si', '', $newHTML);
                 break;
             }
             // Otherwise fall back to database
         // Otherwise fall back to database
         case 'parse-wikitext-nonedit':
             $article = self::articleFromTitle($parameters['namespace'], $parameters['title']);
             $textVar = $parameters['wikitext-var'];
             $text = $vars->getVar($textVar)->toString();
             $editInfo = $this->parseNonEditWikitext($text, $article);
             $result = $editInfo->output->getText();
             break;
         case 'strip-html':
             $htmlVar = $parameters['html-var'];
             $html = $vars->getVar($htmlVar)->toString();
             $result = StringUtils::delimiterReplace('<', '>', '', $html);
             break;
         case 'load-recent-authors':
             $cutOff = $parameters['cutoff'];
             $title = Title::makeTitle($parameters['namespace'], $parameters['title']);
             if (!$title->exists()) {
                 $result = '';
                 break;
             }
             $dbr = wfGetDB(DB_SLAVE);
             $res = $dbr->select('revision', 'DISTINCT rev_user_text', array('rev_page' => $title->getArticleId(), 'rev_timestamp<' . $dbr->addQuotes($dbr->timestamp($cutOff))), __METHOD__, array('ORDER BY' => 'rev_timestamp DESC', 'LIMIT' => 10));
             $users = array();
             foreach ($res as $row) {
                 $users[] = $row->rev_user_text;
             }
             $result = $users;
             break;
         case 'get-page-restrictions':
             $action = $parameters['action'];
             $title = Title::makeTitle($parameters['namespace'], $parameters['title']);
             $rights = $title->getRestrictions($action);
             $rights = count($rights) ? $rights : array();
             $result = $rights;
             break;
         case 'simple-user-accessor':
             $user = $parameters['user'];
             $method = $parameters['method'];
             if (!$user) {
                 throw new MWException('No user parameter given.');
             }
             $obj = self::userObjectFromName($user);
             if (!$obj) {
                 throw new MWException("Invalid username {$user}");
             }
             $result = call_user_func(array($obj, $method));
             break;
         case 'user-age':
             $user = $parameters['user'];
             $asOf = $parameters['asof'];
             $obj = self::userObjectFromName($user);
             if ($obj->getId() == 0) {
                 $result = 0;
                 break;
             }
             $registration = $obj->getRegistration();
             $result = wfTimestamp(TS_UNIX, $asOf) - wfTimestampOrNull(TS_UNIX, $registration);
             break;
         case 'user-groups':
             $user = $parameters['user'];
             $obj = self::userObjectFromName($user);
             $result = $obj->getEffectiveGroups();
             break;
         case 'length':
             $s = $vars->getVar($parameters['length-var'])->toString();
             $result = strlen($s);
             break;
         case 'subtract':
             $v1 = $vars->getVar($parameters['val1-var'])->toFloat();
             $v2 = $vars->getVar($parameters['val2-var'])->toFloat();
             $result = $v1 - $v2;
             break;
         case 'revision-text-by-id':
             $rev = Revision::newFromId($parameters['revid']);
             $result = $rev->getText();
             break;
         case 'revision-text-by-timestamp':
             $timestamp = $parameters['timestamp'];
             $title = Title::makeTitle($parameters['namespace'], $parameters['title']);
             $dbr = wfGetDB(DB_SLAVE);
             $rev = Revision::loadFromTimestamp($dbr, $title, $timestamp);
             if ($rev) {
                 $result = $rev->getText();
             } else {
                 $result = '';
             }
             break;
         default:
             if (wfRunHooks('AbuseFilter-computeVariable', array($this->mMethod, $vars))) {
                 throw new AFPException('Unknown variable compute type ' . $this->mMethod);
             }
     }
     return $result instanceof AFPData ? $result : AFPData::newFromPHPVar($result);
 }
 /**
  * When an user makes a null-edit we sometimes want to review it...
  * (a) Null undo or rollback
  * (b) Null edit with review box checked
  * Note: called after edit ops are finished
  */
 public static function maybeNullEditReview(Page $article, $user, $text, $s, $m, $a, $b, $flags, $rev, &$status, $baseId)
 {
     global $wgRequest;
     # Revision must *be* null (null edit). We also need the user who made the edit.
     if (!$user || $rev !== null) {
         return true;
     }
     # Rollback/undo or box checked
     $reviewEdit = $wgRequest->getCheck('wpReviewEdit');
     if (!$baseId && !$reviewEdit) {
         return true;
         // short-circuit
     }
     $fa = FlaggableWikiPage::getTitleInstance($article->getTitle());
     $fa->loadPageData('fromdbmaster');
     if (!$fa->isReviewable()) {
         return true;
         // page is not reviewable
     }
     $title = $article->getTitle();
     // convenience
     # Get the current revision ID
     $rev = Revision::newFromTitle($title, false, Revision::READ_LATEST);
     if (!$rev) {
         return true;
         // wtf?
     }
     $flags = null;
     # Is this a rollback/undo that didn't change anything?
     if ($baseId > 0) {
         $frev = FlaggedRevision::newFromTitle($title, $baseId);
         // base rev of null edit
         $pRev = Revision::newFromId($rev->getParentId());
         // current rev parent
         $revIsNull = $pRev && $pRev->getTextId() == $rev->getTextId();
         # Was the edit that we tried to revert to reviewed?
         # We avoid auto-reviewing null edits to avoid confusion (bug 28476).
         if ($frev && !$revIsNull) {
             # Review this revision of the page...
             $ok = FlaggedRevs::autoReviewEdit($article, $user, $rev, $flags);
             if ($ok) {
                 FlaggedRevs::markRevisionPatrolled($rev);
                 // reviewed -> patrolled
                 FlaggedRevs::extraHTMLCacheUpdate($title);
                 return true;
             }
         }
     }
     # Get edit timestamp, it must exist.
     $editTimestamp = $wgRequest->getVal('wpEdittime');
     # Is the page checked off to be reviewed?
     if ($editTimestamp && $reviewEdit && $title->userCan('review')) {
         # Check wpEdittime against current revision's time.
         # If an edit was auto-merged in between, review only up to what
         # was the current rev when this user started editing the page.
         if ($rev->getTimestamp() != $editTimestamp) {
             $dbw = wfGetDB(DB_MASTER);
             $rev = Revision::loadFromTimestamp($dbw, $title, $editTimestamp);
             if (!$rev) {
                 return true;
                 // deleted?
             }
         }
         # Review this revision of the page...
         $ok = FlaggedRevs::autoReviewEdit($article, $user, $rev, $flags, false);
         if ($ok) {
             FlaggedRevs::markRevisionPatrolled($rev);
             // reviewed -> patrolled
             FlaggedRevs::extraHTMLCacheUpdate($title);
         }
     }
     return true;
 }
Esempio n. 14
0
 /**
  * Return the data needed to construct links for new talk page message
  * alerts. If there are new messages, this will return an associative array
  * with the following data:
  *     wiki: The database name of the wiki
  *     link: Root-relative link to the user's talk page
  *     rev: The last talk page revision that the user has seen or null. This
  *         is useful for building diff links.
  * If there are no new messages, it returns an empty array.
  * @note This function was designed to accomodate multiple talk pages, but
  * currently only returns a single link and revision.
  * @return array
  */
 public function getNewMessageLinks()
 {
     $talks = array();
     if (!Hooks::run('UserRetrieveNewTalks', array(&$this, &$talks))) {
         return $talks;
     } elseif (!$this->getNewtalk()) {
         return array();
     }
     $utp = $this->getTalkPage();
     $dbr = wfGetDB(DB_SLAVE);
     // Get the "last viewed rev" timestamp from the oldest message notification
     $timestamp = $dbr->selectField('user_newtalk', 'MIN(user_last_timestamp)', $this->isAnon() ? array('user_ip' => $this->getName()) : array('user_id' => $this->getID()), __METHOD__);
     $rev = $timestamp ? Revision::loadFromTimestamp($dbr, $utp, $timestamp) : null;
     return array(array('wiki' => wfWikiID(), 'link' => $utp->getLocalURL(), 'rev' => $rev));
 }
Esempio n. 15
0
 /**
  * @note: this method is very poorly named. If the user opened the form with ?oldid=X,
  *        one might think of X as the "base revision", which is NOT what this returns.
  * @return Revision Current version when the edit was started
  */
 function getBaseRevision()
 {
     if (!$this->mBaseRevision) {
         $db = wfGetDB(DB_MASTER);
         $this->mBaseRevision = $this->editRevId ? Revision::newFromId($this->editRevId, Revision::READ_LATEST) : Revision::loadFromTimestamp($db, $this->mTitle, $this->edittime);
     }
     return $this->mBaseRevision;
 }
Esempio n. 16
0
 /**
  * @param string|number|null|bool $sectionId Section identifier as a number or string
  * (e.g. 0, 1 or 'T-1'), null/false or an empty string for the whole page
  * or 'new' for a new section.
  * @param Content $sectionContent New content of the section.
  * @param string $sectionTitle New section's subject, only if $section is "new".
  * @param string $edittime Revision timestamp or null to use the current revision.
  *
  * @throws MWException
  * @return Content|null New complete article content, or null if error.
  *
  * @since 1.21
  * @deprecated since 1.24, use replaceSectionAtRev instead
  */
 public function replaceSectionContent($sectionId, Content $sectionContent, $sectionTitle = '', $edittime = null)
 {
     $baseRevId = null;
     if ($edittime && $sectionId !== 'new') {
         $dbr = wfGetDB(DB_REPLICA);
         $rev = Revision::loadFromTimestamp($dbr, $this->mTitle, $edittime);
         // Try the master if this thread may have just added it.
         // This could be abstracted into a Revision method, but we don't want
         // to encourage loading of revisions by timestamp.
         if (!$rev && wfGetLB()->getServerCount() > 1 && wfGetLB()->hasOrMadeRecentMasterChanges()) {
             $dbw = wfGetDB(DB_MASTER);
             $rev = Revision::loadFromTimestamp($dbw, $this->mTitle, $edittime);
         }
         if ($rev) {
             $baseRevId = $rev->getId();
         }
     }
     return $this->replaceSectionAtRev($sectionId, $sectionContent, $sectionTitle, $baseRevId);
 }
Esempio n. 17
0
 /**
  * @since 1.1
  *
  * @param EditPage $editpage
  *
  * @return true
  */
 public function onAttemptSave(EditPage $editpage)
 {
     global $wgServerName, $wgScriptPath;
     $urlServer = 'http://' . $wgServerName . $wgScriptPath;
     $ns = $editpage->mTitle->getNamespace();
     if ($ns == PATCH || $ns == PUSHFEED || $ns == PULLFEED || $ns == CHANGESET) {
         return true;
     }
     $actualtext = $editpage->textbox1;
     // V2
     $dbr = wfGetDB(DB_SLAVE);
     $lastRevision = Revision::loadFromTitle($dbr, $editpage->mTitle);
     if (is_null($lastRevision)) {
         $conctext = "";
         $rev_id = 0;
     } elseif (($ns == NS_FILE || $ns == NS_IMAGE || $ns == NS_MEDIA) && $lastRevision->getRawText() == "") {
         $rev_id = 0;
         $conctext = $lastRevision->getText();
     } else {
         $conctext = $lastRevision->getText();
         // V1 conc
         $rev_id = $lastRevision->getId();
     }
     // if there is no modification on the text
     if ($actualtext == $conctext) {
         return true;
     }
     $model = DSMWRevisionManager::loadModel($rev_id);
     $logoot = new logootEngine($model);
     // get the revision with the edittime==>V0
     $rev = Revision::loadFromTimestamp($dbr, $editpage->mTitle, $editpage->edittime);
     if (is_null($rev)) {
         $text = "";
         $rev_id1 = 0;
     } else {
         $text = $rev->getText();
         // VO
         $rev_id1 = $rev->getId();
     }
     if ($conctext != $text) {
         // if last revision is not V0, there is editing conflict
         $model1 = DSMWRevisionManager::loadModel($rev_id1);
         $logoot1 = new logootEngine($model1);
         $listOp1 = $logoot1->generate($text, $actualtext);
         // creation Patch P2
         $tmp = serialize($listOp1);
         $patch = new DSMWPatch(false, false, $listOp1, $urlServer, $rev_id1);
         if ($editpage->mTitle->getNamespace() == 0) {
             $title = $editpage->mTitle->getText();
         } else {
             $title = $editpage->mTitle->getNsText() . ':' . $editpage->mTitle->getText();
         }
         // integration: diffs between VO and V2 into V1
         $modelAfterIntegrate = $logoot->integrate($listOp1);
     } else {
         // no edition conflict
         $listOp = $logoot->generate($conctext, $actualtext);
         $modelAfterIntegrate = $logoot->getModel();
         $tmp = serialize($listOp);
         $patch = new DSMWPatch(false, false, $listOp, $urlServer, $rev_id1);
         if ($editpage->mTitle->getNamespace() == 0) {
             $title = $editpage->mTitle->getText();
         } else {
             $title = $editpage->mTitle->getNsText() . ':' . $editpage->mTitle->getText();
         }
     }
     $revId = utils::getNewArticleRevId();
     wfDebugLog('p2p', ' -> store model rev : ' . $revId . ' session ' . session_id() . ' model ' . $modelAfterIntegrate->getText());
     DSMWRevisionManager::storeModel($revId + 1, $sessionId = session_id(), $modelAfterIntegrate, $blobCB = 0);
     $patch->storePage($title, $revId + 1);
     // stores the patch in a wikipage
     $editpage->textbox1 = $modelAfterIntegrate->getText();
     return true;
 }
Esempio n. 18
0
	/**
	 * @param $section null|bool|int or a section number (0, 1, 2, T1, T2...)
	 * @param $sectionContent Content: new content of the section
	 * @param string $sectionTitle new section's subject, only if $section is 'new'
	 * @param string $edittime revision timestamp or null to use the current revision
	 *
	 * @throws MWException
	 * @return Content new complete article content, or null if error
	 *
	 * @since 1.21
	 */
	public function replaceSectionContent( $section, Content $sectionContent, $sectionTitle = '', $edittime = null ) {
		wfProfileIn( __METHOD__ );

		if ( strval( $section ) == '' ) {
			// Whole-page edit; let the whole text through
			$newContent = $sectionContent;
		} else {
			if ( !$this->supportsSections() ) {
				wfProfileOut( __METHOD__ );
				throw new MWException( "sections not supported for content model " . $this->getContentHandler()->getModelID() );
			}

			// Bug 30711: always use current version when adding a new section
			if ( is_null( $edittime ) || $section == 'new' ) {
				$oldContent = $this->getContent();
			} else {
				$dbw = wfGetDB( DB_MASTER );
				$rev = Revision::loadFromTimestamp( $dbw, $this->mTitle, $edittime );

				if ( !$rev ) {
					wfDebug( "WikiPage::replaceSection asked for bogus section (page: " .
						$this->getId() . "; section: $section; edittime: $edittime)\n" );
					wfProfileOut( __METHOD__ );
					return null;
				}

				$oldContent = $rev->getContent();
			}

			if ( ! $oldContent ) {
				wfDebug( __METHOD__ . ": no page text\n" );
				wfProfileOut( __METHOD__ );
				return null;
			}

			// FIXME: $oldContent might be null?
			$newContent = $oldContent->replaceSection( $section, $sectionContent, $sectionTitle );
		}

		wfProfileOut( __METHOD__ );
		return $newContent;
	}
Esempio n. 19
0
 /**
  * @param $section null|bool|int or a section number (0, 1, 2, T1, T2...)
  * @param $text String: new text of the section
  * @param $sectionTitle String: new section's subject, only if $section is 'new'
  * @param $edittime String: revision timestamp or null to use the current revision
  * @return string Complete article text, or null if error
  */
 public function replaceSection($section, $text, $sectionTitle = '', $edittime = null)
 {
     wfProfileIn(__METHOD__);
     if (strval($section) == '') {
         // Whole-page edit; let the whole text through
     } else {
         // Bug 30711: always use current version when adding a new section
         if (is_null($edittime) || $section == 'new') {
             $oldtext = $this->getRawText();
             if ($oldtext === false) {
                 wfDebug(__METHOD__ . ": no page text\n");
                 wfProfileOut(__METHOD__);
                 return null;
             }
         } else {
             $dbw = wfGetDB(DB_MASTER);
             $rev = Revision::loadFromTimestamp($dbw, $this->mTitle, $edittime);
             if (!$rev) {
                 wfDebug("WikiPage::replaceSection asked for bogus section (page: " . $this->getId() . "; section: {$section}; edittime: {$edittime})\n");
                 wfProfileOut(__METHOD__);
                 return null;
             }
             $oldtext = $rev->getText();
         }
         if ($section == 'new') {
             # Inserting a new section
             $subject = $sectionTitle ? wfMessage('newsectionheaderdefaultlevel')->rawParams($sectionTitle)->inContentLanguage()->text() . "\n\n" : '';
             if (wfRunHooks('PlaceNewSection', array($this, $oldtext, $subject, &$text))) {
                 $text = strlen(trim($oldtext)) > 0 ? "{$oldtext}\n\n{$subject}{$text}" : "{$subject}{$text}";
             }
         } else {
             # Replacing an existing section; roll out the big guns
             global $wgParser;
             $text = $wgParser->replaceSection($oldtext, $section, $text);
         }
     }
     wfProfileOut(__METHOD__);
     return $text;
 }