/** * Really format a diff for the newsfeed * * @param $title Title object * @param $oldid Integer: old revision's id * @param $newid Integer: new revision's id * @param $timestamp Integer: new revision's timestamp * @param $comment String: new revision's comment * @param $actiontext String: text of the action; in case of log event * @return String */ public static function formatDiffRow($title, $oldid, $newid, $timestamp, $comment, $actiontext = '') { global $wgFeedDiffCutoff, $wgLang; wfProfileIn(__METHOD__); # log enties $completeText = '<p>' . implode(' ', array_filter(array($actiontext, Linker::formatComment($comment)))) . "</p>\n"; // NOTE: Check permissions for anonymous users, not current user. // No "privileged" version should end up in the cache. // Most feed readers will not log in anway. $anon = new User(); $accErrors = $title->getUserPermissionsErrors('read', $anon, true); // Can't diff special pages, unreadable pages or pages with no new revision // to compare against: just return the text. if ($title->getNamespace() < 0 || $accErrors || !$newid) { wfProfileOut(__METHOD__); return $completeText; } if ($oldid) { wfProfileIn(__METHOD__ . "-dodiff"); #$diffText = $de->getDiff( wfMsg( 'revisionasof', # $wgLang->timeanddate( $timestamp ), # $wgLang->date( $timestamp ), # $wgLang->time( $timestamp ) ), # wfMsg( 'currentrev' ) ); // Don't bother generating the diff if we won't be able to show it if ($wgFeedDiffCutoff > 0) { $de = new DifferenceEngine($title, $oldid, $newid); $diffText = $de->getDiff(wfMsg('previousrevision'), wfMsg('revisionasof', $wgLang->timeanddate($timestamp), $wgLang->date($timestamp), $wgLang->time($timestamp))); } if ($wgFeedDiffCutoff <= 0 || strlen($diffText) > $wgFeedDiffCutoff) { // Omit large diffs $diffText = self::getDiffLink($title, $newid, $oldid); } elseif ($diffText === false) { // Error in diff engine, probably a missing revision $diffText = "<p>Can't load revision {$newid}</p>"; } else { // Diff output fine, clean up any illegal UTF-8 $diffText = UtfNormal::cleanUp($diffText); $diffText = self::applyDiffStyle($diffText); } wfProfileOut(__METHOD__ . "-dodiff"); } else { $rev = Revision::newFromId($newid); if ($wgFeedDiffCutoff <= 0 || is_null($rev)) { $newtext = ''; } else { $newtext = $rev->getText(); } if ($wgFeedDiffCutoff <= 0 || strlen($newtext) > $wgFeedDiffCutoff) { // Omit large new page diffs, bug 29110 $diffText = self::getDiffLink($title, $newid); } else { $diffText = '<p><b>' . wfMsg('newpage') . '</b></p>' . '<div>' . nl2br(htmlspecialchars($newtext)) . '</div>'; } } $completeText .= $diffText; wfProfileOut(__METHOD__); return $completeText; }
/** * @dataProvider provideCasesForFormatComment * @covers Linker::formatComment * @covers Linker::formatAutocomments * @covers Linker::formatLinksInComment */ public function testFormatComment($expected, $comment, $title = false, $local = false) { $this->setMwGlobals(array('wgScript' => '/wiki/index.php', 'wgArticlePath' => '/wiki/$1', 'wgWellFormedXml' => true, 'wgCapitalLinks' => true)); if ($title === false) { // We need a page title that exists $title = Title::newFromText('Special:BlankPage'); } $this->assertEquals($expected, Linker::formatComment($comment, $title, $local)); }
public function onView() { $details = null; $request = $this->getRequest(); $result = $this->page->doRollback($request->getVal('from'), $request->getText('summary'), $request->getVal('token'), $request->getBool('bot'), $details, $this->getUser()); if (in_array(array('actionthrottledtext'), $result)) { throw new ThrottledError(); } if (isset($result[0][0]) && ($result[0][0] == 'alreadyrolled' || $result[0][0] == 'cantrollback')) { $this->getOutput()->setPageTitle(wfMsg('rollbackfailed')); $errArray = $result[0]; $errMsg = array_shift($errArray); $this->getOutput()->addWikiMsgArray($errMsg, $errArray); if (isset($details['current'])) { $current = $details['current']; if ($current->getComment() != '') { $this->getOutput()->addHTML(wfMessage('editcomment')->rawParams(Linker::formatComment($current->getComment()))->parse()); } } return; } # Display permissions errors before read-only message -- there's no # point in misleading the user into thinking the inability to rollback # is only temporary. if (!empty($result) && $result !== array(array('readonlytext'))) { # array_diff is completely broken for arrays of arrays, sigh. # Remove any 'readonlytext' error manually. $out = array(); foreach ($result as $error) { if ($error != array('readonlytext')) { $out[] = $error; } } $this->getOutput()->showPermissionsErrorPage($out); return; } if ($result == array(array('readonlytext'))) { throw new ReadOnlyError(); } $current = $details['current']; $target = $details['target']; $newId = $details['newid']; $this->getOutput()->setPageTitle(wfMsg('actioncomplete')); $this->getOutput()->setRobotPolicy('noindex,nofollow'); if ($current->getUserText() === '') { $old = wfMsg('rev-deleted-user'); } else { $old = Linker::userLink($current->getUser(), $current->getUserText()) . Linker::userToolLinks($current->getUser(), $current->getUserText()); } $new = Linker::userLink($target->getUser(), $target->getUserText()) . Linker::userToolLinks($target->getUser(), $target->getUserText()); $this->getOutput()->addHTML(wfMsgExt('rollback-success', array('parse', 'replaceafter'), $old, $new)); $this->getOutput()->returnToMain(false, $this->getTitle()); if (!$request->getBool('hidediff', false) && !$this->getUser()->getBoolOption('norollbackdiff', false)) { $de = new DifferenceEngine($this->getTitle(), $current->getId(), $newId, false, true); $de->showDiff('', ''); } }
/** * Formats an edit comment * @param string $comment The raw comment text * @param Title $title The title of the page that was edited * @fixme: Duplication with SpecialMobileWatchlist * * @return string HTML code */ protected function formatComment($comment, $title) { if ($comment === '') { $comment = $this->msg('mobile-frontend-changeslist-nocomment')->plain(); } else { $comment = Linker::formatComment($comment, $title); // flatten back to text $comment = Sanitizer::stripAllTags($comment); } return $comment; }
/** * @dataProvider provideCasesForFormatComment * @covers Linker::formatComment * @covers Linker::formatAutocomments * @covers Linker::formatLinksInComment */ public function testFormatComment($expected, $comment, $title = false, $local = false, $wikiId = null) { $conf = new SiteConfiguration(); $conf->settings = array('wgServer' => array('enwiki' => '//en.example.org', 'dewiki' => '//de.example.org'), 'wgArticlePath' => array('enwiki' => '/w/$1', 'dewiki' => '/w/$1')); $conf->suffixes = array('wiki'); $this->setMwGlobals(array('wgScript' => '/wiki/index.php', 'wgArticlePath' => '/wiki/$1', 'wgWellFormedXml' => true, 'wgCapitalLinks' => true, 'wgConf' => $conf)); if ($title === false) { // We need a page title that exists $title = Title::newFromText('Special:BlankPage'); } $this->assertEquals($expected, Linker::formatComment($comment, $title, $local, $wikiId)); }
public function onView() { // TODO: use $this->useTransactionalTimeLimit(); when POST only wfTransactionalTimeLimit(); $details = null; $request = $this->getRequest(); $user = $this->getUser(); $result = $this->page->doRollback($request->getVal('from'), $request->getText('summary'), $request->getVal('token'), $request->getBool('bot'), $details, $this->getUser()); if (in_array(array('actionthrottledtext'), $result)) { throw new ThrottledError(); } if (isset($result[0][0]) && ($result[0][0] == 'alreadyrolled' || $result[0][0] == 'cantrollback')) { $this->getOutput()->setPageTitle($this->msg('rollbackfailed')); $errArray = $result[0]; $errMsg = array_shift($errArray); $this->getOutput()->addWikiMsgArray($errMsg, $errArray); if (isset($details['current'])) { /** @var Revision $current */ $current = $details['current']; if ($current->getComment() != '') { $this->getOutput()->addHTML($this->msg('editcomment')->rawParams(Linker::formatComment($current->getComment()))->parse()); } } return; } #NOTE: Permission errors already handled by Action::checkExecute. if ($result == array(array('readonlytext'))) { throw new ReadOnlyError(); } #XXX: Would be nice if ErrorPageError could take multiple errors, and/or a status object. # Right now, we only show the first error foreach ($result as $error) { throw new ErrorPageError('rollbackfailed', $error[0], array_slice($error, 1)); } /** @var Revision $current */ $current = $details['current']; $target = $details['target']; $newId = $details['newid']; $this->getOutput()->setPageTitle($this->msg('actioncomplete')); $this->getOutput()->setRobotPolicy('noindex,nofollow'); $old = Linker::revUserTools($current); $new = Linker::revUserTools($target); $this->getOutput()->addHTML($this->msg('rollback-success')->rawParams($old, $new)->parseAsBlock()); if ($user->getBoolOption('watchrollback')) { $user->addWatch($this->page->getTitle(), WatchedItem::IGNORE_USER_RIGHTS); } $this->getOutput()->returnToMain(false, $this->getTitle()); if (!$request->getBool('hidediff', false) && !$this->getUser()->getBoolOption('norollbackdiff', false)) { $contentHandler = $current->getContentHandler(); $de = $contentHandler->createDifferenceEngine($this->getContext(), $current->getId(), $newId, false, true); $de->showDiff('', ''); } }
/** * Extract information from the Revision * * @param Revision $revision * @param object $row Should have a field 'ts_tags' if $this->fld_tags is set * @return array */ protected function extractRevisionInfo(Revision $revision, $row) { $title = $revision->getTitle(); $user = $this->getUser(); $vals = array(); $anyHidden = false; if ($this->fld_ids) { $vals['revid'] = intval($revision->getId()); if (!is_null($revision->getParentId())) { $vals['parentid'] = intval($revision->getParentId()); } } if ($this->fld_flags) { $vals['minor'] = $revision->isMinor(); } if ($this->fld_user || $this->fld_userid) { if ($revision->isDeleted(Revision::DELETED_USER)) { $vals['userhidden'] = true; $anyHidden = true; } if ($revision->userCan(Revision::DELETED_USER, $user)) { if ($this->fld_user) { $vals['user'] = $revision->getUserText(Revision::RAW); } $userid = $revision->getUser(Revision::RAW); if (!$userid) { $vals['anon'] = true; } if ($this->fld_userid) { $vals['userid'] = $userid; } } } if ($this->fld_timestamp) { $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $revision->getTimestamp()); } if ($this->fld_size) { if (!is_null($revision->getSize())) { $vals['size'] = intval($revision->getSize()); } else { $vals['size'] = 0; } } if ($this->fld_sha1) { if ($revision->isDeleted(Revision::DELETED_TEXT)) { $vals['sha1hidden'] = true; $anyHidden = true; } if ($revision->userCan(Revision::DELETED_TEXT, $user)) { if ($revision->getSha1() != '') { $vals['sha1'] = wfBaseConvert($revision->getSha1(), 36, 16, 40); } else { $vals['sha1'] = ''; } } } if ($this->fld_contentmodel) { $vals['contentmodel'] = $revision->getContentModel(); } if ($this->fld_comment || $this->fld_parsedcomment) { if ($revision->isDeleted(Revision::DELETED_COMMENT)) { $vals['commenthidden'] = true; $anyHidden = true; } if ($revision->userCan(Revision::DELETED_COMMENT, $user)) { $comment = $revision->getComment(Revision::RAW); if ($this->fld_comment) { $vals['comment'] = $comment; } if ($this->fld_parsedcomment) { $vals['parsedcomment'] = Linker::formatComment($comment, $title); } } } if ($this->fld_tags) { if ($row->ts_tags) { $tags = explode(',', $row->ts_tags); ApiResult::setIndexedTagName($tags, 'tag'); $vals['tags'] = $tags; } else { $vals['tags'] = array(); } } $content = null; global $wgParser; if ($this->fetchContent) { $content = $revision->getContent(Revision::FOR_THIS_USER, $this->getUser()); // Expand templates after getting section content because // template-added sections don't count and Parser::preprocess() // will have less input if ($content && $this->section !== false) { $content = $content->getSection($this->section, false); if (!$content) { $this->dieUsage("There is no section {$this->section} in r" . $revision->getId(), 'nosuchsection'); } } if ($revision->isDeleted(Revision::DELETED_TEXT)) { $vals['texthidden'] = true; $anyHidden = true; } elseif (!$content) { $vals['textmissing'] = true; } } if ($this->fld_content && $content) { $text = null; if ($this->generateXML) { if ($content->getModel() === CONTENT_MODEL_WIKITEXT) { $t = $content->getNativeData(); # note: don't set $text $wgParser->startExternalParse($title, ParserOptions::newFromContext($this->getContext()), Parser::OT_PREPROCESS); $dom = $wgParser->preprocessToDom($t); if (is_callable(array($dom, 'saveXML'))) { $xml = $dom->saveXML(); } else { $xml = $dom->__toString(); } $vals['parsetree'] = $xml; } else { $vals['badcontentformatforparsetree'] = true; $this->setWarning("Conversion to XML is supported for wikitext only, " . $title->getPrefixedDBkey() . " uses content model " . $content->getModel()); } } if ($this->expandTemplates && !$this->parseContent) { #XXX: implement template expansion for all content types in ContentHandler? if ($content->getModel() === CONTENT_MODEL_WIKITEXT) { $text = $content->getNativeData(); $text = $wgParser->preprocess($text, $title, ParserOptions::newFromContext($this->getContext())); } else { $this->setWarning("Template expansion is supported for wikitext only, " . $title->getPrefixedDBkey() . " uses content model " . $content->getModel()); $vals['badcontentformat'] = true; $text = false; } } if ($this->parseContent) { $po = $content->getParserOutput($title, $revision->getId(), ParserOptions::newFromContext($this->getContext())); $text = $po->getText(); } if ($text === null) { $format = $this->contentFormat ? $this->contentFormat : $content->getDefaultFormat(); $model = $content->getModel(); if (!$content->isSupportedFormat($format)) { $name = $title->getPrefixedDBkey(); $this->setWarning("The requested format {$this->contentFormat} is not " . "supported for content model {$model} used by {$name}"); $vals['badcontentformat'] = true; $text = false; } else { $text = $content->serialize($format); // always include format and model. // Format is needed to deserialize, model is needed to interpret. $vals['contentformat'] = $format; $vals['contentmodel'] = $model; } } if ($text !== false) { ApiResult::setContentValue($vals, 'content', $text); } } if ($content && (!is_null($this->diffto) || !is_null($this->difftotext))) { static $n = 0; // Number of uncached diffs we've had if ($n < $this->getConfig()->get('APIMaxUncachedDiffs')) { $vals['diff'] = array(); $context = new DerivativeContext($this->getContext()); $context->setTitle($title); $handler = $revision->getContentHandler(); if (!is_null($this->difftotext)) { $model = $title->getContentModel(); if ($this->contentFormat && !ContentHandler::getForModelID($model)->isSupportedFormat($this->contentFormat)) { $name = $title->getPrefixedDBkey(); $this->setWarning("The requested format {$this->contentFormat} is not " . "supported for content model {$model} used by {$name}"); $vals['diff']['badcontentformat'] = true; $engine = null; } else { $difftocontent = ContentHandler::makeContent($this->difftotext, $title, $model, $this->contentFormat); $engine = $handler->createDifferenceEngine($context); $engine->setContent($content, $difftocontent); } } else { $engine = $handler->createDifferenceEngine($context, $revision->getID(), $this->diffto); $vals['diff']['from'] = $engine->getOldid(); $vals['diff']['to'] = $engine->getNewid(); } if ($engine) { $difftext = $engine->getDiffBody(); ApiResult::setContentValue($vals['diff'], 'body', $difftext); if (!$engine->wasCacheHit()) { $n++; } } } else { $vals['diff']['notcached'] = true; } } if ($anyHidden && $revision->isDeleted(Revision::DELETED_RESTRICTED)) { $vals['suppressed'] = true; } return $vals; }
/** * Formats a comment of revision via Linker:formatComment and Sanitizer::stripAllTags * @param string $comment the comment * @param string $title the title object of comments page * @return string formatted comment */ protected function formatComment($comment, $title) { if ($comment !== '') { $comment = Linker::formatComment($comment, $title); // flatten back to text $comment = Sanitizer::stripAllTags($comment); } return $comment; }
/** * @param $iscur * @param $file File * @return string */ public function imageHistoryLine($iscur, $file) { global $wgContLang; $user = $this->getUser(); $lang = $this->getLanguage(); $timestamp = wfTimestamp(TS_MW, $file->getTimestamp()); $img = $iscur ? $file->getName() : $file->getArchiveName(); $userId = $file->getUser('id'); $userText = $file->getUser('text'); $description = $file->getDescription(File::FOR_THIS_USER, $user); $local = $this->current->isLocal(); $row = $selected = ''; // Deletion link if ($local && $user->isAllowedAny('delete', 'deletedhistory')) { $row .= '<td>'; # Link to remove from history if ($user->isAllowed('delete')) { $q = array('action' => 'delete'); if (!$iscur) { $q['oldimage'] = $img; } $row .= Linker::linkKnown($this->title, $this->msg($iscur ? 'filehist-deleteall' : 'filehist-deleteone')->escaped(), array(), $q); } # Link to hide content. Don't show useless link to people who cannot hide revisions. $canHide = $user->isAllowed('deleterevision'); if ($canHide || $user->isAllowed('deletedhistory') && $file->getVisibility()) { if ($user->isAllowed('delete')) { $row .= '<br />'; } // If file is top revision or locked from this user, don't link if ($iscur || !$file->userCan(File::DELETED_RESTRICTED, $user)) { $del = Linker::revDeleteLinkDisabled($canHide); } else { list($ts, ) = explode('!', $img, 2); $query = array('type' => 'oldimage', 'target' => $this->title->getPrefixedText(), 'ids' => $ts); $del = Linker::revDeleteLink($query, $file->isDeleted(File::DELETED_RESTRICTED), $canHide); } $row .= $del; } $row .= '</td>'; } // Reversion link/current indicator $row .= '<td>'; if ($iscur) { $row .= $this->msg('filehist-current')->escaped(); } elseif ($local && $this->title->quickUserCan('edit', $user) && $this->title->quickUserCan('upload', $user)) { if ($file->isDeleted(File::DELETED_FILE)) { $row .= $this->msg('filehist-revert')->escaped(); } else { $row .= Linker::linkKnown($this->title, $this->msg('filehist-revert')->escaped(), array(), array('action' => 'revert', 'oldimage' => $img, 'wpEditToken' => $user->getEditToken($img))); } } $row .= '</td>'; // Date/time and image link if ($file->getTimestamp() === $this->img->getTimestamp()) { $selected = "class='filehistory-selected'"; } $row .= "<td {$selected} style='white-space: nowrap;'>"; if (!$file->userCan(File::DELETED_FILE, $user)) { # Don't link to unviewable files $row .= '<span class="history-deleted">' . $lang->userTimeAndDate($timestamp, $user) . '</span>'; } elseif ($file->isDeleted(File::DELETED_FILE)) { if ($local) { $this->preventClickjacking(); $revdel = SpecialPage::getTitleFor('Revisiondelete'); # Make a link to review the image $url = Linker::linkKnown($revdel, $lang->userTimeAndDate($timestamp, $user), array(), array('target' => $this->title->getPrefixedText(), 'file' => $img, 'token' => $user->getEditToken($img))); } else { $url = $lang->userTimeAndDate($timestamp, $user); } $row .= '<span class="history-deleted">' . $url . '</span>'; } else { $url = $iscur ? $this->current->getUrl() : $this->current->getArchiveUrl($img); $row .= Xml::element('a', array('href' => $url), $lang->userTimeAndDate($timestamp, $user)); } $row .= "</td>"; // Thumbnail if ($this->showThumb) { $row .= '<td>' . $this->getThumbForLine($file) . '</td>'; } // Image dimensions + size $row .= '<td>'; $row .= htmlspecialchars($file->getDimensionsString()); $row .= $this->msg('word-separator')->plain(); $row .= '<span style="white-space: nowrap;">'; $row .= $this->msg('parentheses')->rawParams(Linker::formatSize($file->getSize()))->plain(); $row .= '</span>'; $row .= '</td>'; // Uploading user $row .= '<td>'; // Hide deleted usernames if ($file->isDeleted(File::DELETED_USER)) { $row .= '<span class="history-deleted">' . $this->msg('rev-deleted-user')->escaped() . '</span>'; } else { if ($local) { $row .= Linker::userLink($userId, $userText); $row .= $this->msg('word-separator')->plain(); $row .= '<span style="white-space: nowrap;">'; $row .= Linker::userToolLinks($userId, $userText); $row .= '</span>'; } else { $row .= htmlspecialchars($userText); } } $row .= '</td>'; // Don't show deleted descriptions if ($file->isDeleted(File::DELETED_COMMENT)) { $row .= '<td><span class="history-deleted">' . $this->msg('rev-deleted-comment')->escaped() . '</span></td>'; } else { $row .= '<td dir="' . $wgContLang->getDir() . '">' . Linker::formatComment($description, $this->title) . '</td>'; } $rowClass = null; wfRunHooks('ImagePageFileHistoryLine', array($this, $file, &$row, &$rowClass)); $classAttr = $rowClass ? " class='{$rowClass}'" : ''; return "<tr{$classAttr}>{$row}</tr>\n"; }
private function extractRowInfo($row) { $logEntry = DatabaseLogEntry::newFromRow($row); $vals = array(); if ($this->fld_ids) { $vals['logid'] = intval($row->log_id); $vals['pageid'] = intval($row->page_id); } if ($this->fld_title || $this->fld_parsedcomment) { $title = Title::makeTitle($row->log_namespace, $row->log_title); } if ($this->fld_title) { if (LogEventsList::isDeleted($row, LogPage::DELETED_ACTION)) { $vals['actionhidden'] = ''; } else { ApiQueryBase::addTitleInfo($vals, $title); } } if ($this->fld_type || $this->fld_action) { $vals['type'] = $row->log_type; $vals['action'] = $row->log_action; } if ($this->fld_details && $row->log_params !== '') { if (LogEventsList::isDeleted($row, LogPage::DELETED_ACTION)) { $vals['actionhidden'] = ''; } else { self::addLogParams($this->getResult(), $vals, $logEntry->getParameters(), $logEntry->getType(), $logEntry->getSubtype(), $logEntry->getTimestamp(), $logEntry->isLegacy()); } } if ($this->fld_user || $this->fld_userid) { if (LogEventsList::isDeleted($row, LogPage::DELETED_USER)) { $vals['userhidden'] = ''; } else { if ($this->fld_user) { $vals['user'] = $row->user_name; } if ($this->fld_userid) { $vals['userid'] = $row->user_id; } if (!$row->log_user) { $vals['anon'] = ''; } } } if ($this->fld_timestamp) { $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->log_timestamp); } if (($this->fld_comment || $this->fld_parsedcomment) && isset($row->log_comment)) { if (LogEventsList::isDeleted($row, LogPage::DELETED_COMMENT)) { $vals['commenthidden'] = ''; } else { if ($this->fld_comment) { $vals['comment'] = $row->log_comment; } if ($this->fld_parsedcomment) { $vals['parsedcomment'] = Linker::formatComment($row->log_comment, $title); } } } if ($this->fld_tags) { if ($row->ts_tags) { $tags = explode(',', $row->ts_tags); $this->getResult()->setIndexedTagName($tags, 'tag'); $vals['tags'] = $tags; } else { $vals['tags'] = array(); } } return $vals; }
/** * @param string $field * @param string $value * @return string HTML * @throws MWException */ function formatValue($field, $value) { /** @var $row object */ $row = $this->mCurrentRow; $formatted = ''; switch ($field) { case 'log_timestamp': // when timestamp is null, this is a old protection row if ($value === null) { $formatted = Html::rawElement('span', array('class' => 'mw-protectedpages-unknown'), $this->msg('protectedpages-unknown-timestamp')->escaped()); } else { $formatted = htmlspecialchars($this->getLanguage()->userTimeAndDate($value, $this->getUser())); } break; case 'pr_page': $title = Title::makeTitleSafe($row->page_namespace, $row->page_title); if (!$title) { $formatted = Html::element('span', array('class' => 'mw-invalidtitle'), Linker::getInvalidTitleDescription($this->getContext(), $row->page_namespace, $row->page_title)); } else { $formatted = Linker::link($title); } if (!is_null($row->page_len)) { $formatted .= $this->getLanguage()->getDirMark() . ' ' . Html::rawElement('span', array('class' => 'mw-protectedpages-length'), Linker::formatRevisionSize($row->page_len)); } break; case 'pr_expiry': $formatted = htmlspecialchars($this->getLanguage()->formatExpiry($value, true)); $title = Title::makeTitleSafe($row->page_namespace, $row->page_title); if ($this->getUser()->isAllowed('protect') && $title) { $changeProtection = Linker::linkKnown($title, $this->msg('protect_change')->escaped(), array(), array('action' => 'unprotect')); $formatted .= ' ' . Html::rawElement('span', array('class' => 'mw-protectedpages-actions'), $this->msg('parentheses')->rawParams($changeProtection)->escaped()); } break; case 'log_user': // when timestamp is null, this is a old protection row if ($row->log_timestamp === null) { $formatted = Html::rawElement('span', array('class' => 'mw-protectedpages-unknown'), $this->msg('protectedpages-unknown-performer')->escaped()); } else { $username = UserCache::singleton()->getProp($value, 'name'); if (LogEventsList::userCanBitfield($row->log_deleted, LogPage::DELETED_USER, $this->getUser())) { if ($username === false) { $formatted = htmlspecialchars($value); } else { $formatted = Linker::userLink($value, $username) . Linker::userToolLinks($value, $username); } } else { $formatted = $this->msg('rev-deleted-user')->escaped(); } if (LogEventsList::isDeleted($row, LogPage::DELETED_USER)) { $formatted = '<span class="history-deleted">' . $formatted . '</span>'; } } break; case 'pr_params': $params = array(); // Messages: restriction-level-sysop, restriction-level-autoconfirmed $params[] = $this->msg('restriction-level-' . $row->pr_level)->escaped(); if ($row->pr_cascade) { $params[] = $this->msg('protect-summary-cascade')->escaped(); } $formatted = $this->getLanguage()->commaList($params); break; case 'log_comment': // when timestamp is null, this is an old protection row if ($row->log_timestamp === null) { $formatted = Html::rawElement('span', array('class' => 'mw-protectedpages-unknown'), $this->msg('protectedpages-unknown-reason')->escaped()); } else { if (LogEventsList::userCanBitfield($row->log_deleted, LogPage::DELETED_COMMENT, $this->getUser())) { $formatted = Linker::formatComment($value !== null ? $value : ''); } else { $formatted = $this->msg('rev-deleted-comment')->escaped(); } if (LogEventsList::isDeleted($row, LogPage::DELETED_COMMENT)) { $formatted = '<span class="history-deleted">' . $formatted . '</span>'; } } break; default: throw new MWException("Unknown field '{$field}'"); } return $formatted; }
public function execute() { $user = $this->getUser(); // Before doing anything at all, let's check permissions if (!$user->isAllowed('deletedhistory')) { $this->dieUsage('You don\'t have permission to view deleted file information', 'permissiondenied'); } $db = $this->getDB(); $params = $this->extractRequestParams(); $prop = array_flip($params['prop']); $fld_sha1 = isset($prop['sha1']); $fld_timestamp = isset($prop['timestamp']); $fld_user = isset($prop['user']); $fld_size = isset($prop['size']); $fld_dimensions = isset($prop['dimensions']); $fld_description = isset($prop['description']) || isset($prop['parseddescription']); $fld_mime = isset($prop['mime']); $fld_mediatype = isset($prop['mediatype']); $fld_metadata = isset($prop['metadata']); $fld_bitdepth = isset($prop['bitdepth']); $fld_archivename = isset($prop['archivename']); $this->addTables('filearchive'); $this->addFields(ArchivedFile::selectFields()); $this->addFields(array('fa_id', 'fa_name', 'fa_timestamp', 'fa_deleted')); $this->addFieldsIf('fa_sha1', $fld_sha1); $this->addFieldsIf(array('fa_user', 'fa_user_text'), $fld_user); $this->addFieldsIf(array('fa_height', 'fa_width', 'fa_size'), $fld_dimensions || $fld_size); $this->addFieldsIf('fa_description', $fld_description); $this->addFieldsIf(array('fa_major_mime', 'fa_minor_mime'), $fld_mime); $this->addFieldsIf('fa_media_type', $fld_mediatype); $this->addFieldsIf('fa_metadata', $fld_metadata); $this->addFieldsIf('fa_bits', $fld_bitdepth); $this->addFieldsIf('fa_archive_name', $fld_archivename); if (!is_null($params['continue'])) { $cont = explode('|', $params['continue']); $this->dieContinueUsageIf(count($cont) != 3); $op = $params['dir'] == 'descending' ? '<' : '>'; $cont_from = $db->addQuotes($cont[0]); $cont_timestamp = $db->addQuotes($db->timestamp($cont[1])); $cont_id = (int) $cont[2]; $this->dieContinueUsageIf($cont[2] !== (string) $cont_id); $this->addWhere("fa_name {$op} {$cont_from} OR " . "(fa_name = {$cont_from} AND " . "(fa_timestamp {$op} {$cont_timestamp} OR " . "(fa_timestamp = {$cont_timestamp} AND " . "fa_id {$op}= {$cont_id} )))"); } // Image filters $dir = $params['dir'] == 'descending' ? 'older' : 'newer'; $from = $params['from'] === null ? null : $this->titlePartToKey($params['from'], NS_FILE); $to = $params['to'] === null ? null : $this->titlePartToKey($params['to'], NS_FILE); $this->addWhereRange('fa_name', $dir, $from, $to); if (isset($params['prefix'])) { $this->addWhere('fa_name' . $db->buildLike($this->titlePartToKey($params['prefix'], NS_FILE), $db->anyString())); } $sha1Set = isset($params['sha1']); $sha1base36Set = isset($params['sha1base36']); if ($sha1Set || $sha1base36Set) { $sha1 = false; if ($sha1Set) { $sha1 = strtolower($params['sha1']); if (!$this->validateSha1Hash($sha1)) { $this->dieUsage('The SHA1 hash provided is not valid', 'invalidsha1hash'); } $sha1 = wfBaseConvert($sha1, 16, 36, 31); } elseif ($sha1base36Set) { $sha1 = strtolower($params['sha1base36']); if (!$this->validateSha1Base36Hash($sha1)) { $this->dieUsage('The SHA1Base36 hash provided is not valid', 'invalidsha1base36hash'); } } if ($sha1) { $this->addWhereFld('fa_sha1', $sha1); } } // Exclude files this user can't view. if (!$user->isAllowed('deletedtext')) { $bitmask = File::DELETED_FILE; } elseif (!$user->isAllowedAny('suppressrevision', 'viewsuppressed')) { $bitmask = File::DELETED_FILE | File::DELETED_RESTRICTED; } else { $bitmask = 0; } if ($bitmask) { $this->addWhere($this->getDB()->bitAnd('fa_deleted', $bitmask) . " != {$bitmask}"); } $limit = $params['limit']; $this->addOption('LIMIT', $limit + 1); $sort = $params['dir'] == 'descending' ? ' DESC' : ''; $this->addOption('ORDER BY', array('fa_name' . $sort, 'fa_timestamp' . $sort, 'fa_id' . $sort)); $res = $this->select(__METHOD__); $count = 0; $result = $this->getResult(); foreach ($res as $row) { if (++$count > $limit) { // We've reached the one extra which shows that there are // additional pages to be had. Stop here... $this->setContinueEnumParameter('continue', "{$row->fa_name}|{$row->fa_timestamp}|{$row->fa_id}"); break; } $file = array(); $file['id'] = (int) $row->fa_id; $file['name'] = $row->fa_name; $title = Title::makeTitle(NS_FILE, $row->fa_name); self::addTitleInfo($file, $title); if ($fld_description && Revision::userCanBitfield($row->fa_deleted, File::DELETED_COMMENT, $user)) { $file['description'] = $row->fa_description; if (isset($prop['parseddescription'])) { $file['parseddescription'] = Linker::formatComment($row->fa_description, $title); } } if ($fld_user && Revision::userCanBitfield($row->fa_deleted, File::DELETED_USER, $user)) { $file['userid'] = (int) $row->fa_user; $file['user'] = $row->fa_user_text; } if ($fld_sha1) { $file['sha1'] = wfBaseConvert($row->fa_sha1, 36, 16, 40); } if ($fld_timestamp) { $file['timestamp'] = wfTimestamp(TS_ISO_8601, $row->fa_timestamp); } if ($fld_size || $fld_dimensions) { $file['size'] = $row->fa_size; $pageCount = ArchivedFile::newFromRow($row)->pageCount(); if ($pageCount !== false) { $file['pagecount'] = $pageCount; } $file['height'] = $row->fa_height; $file['width'] = $row->fa_width; } if ($fld_mediatype) { $file['mediatype'] = $row->fa_media_type; } if ($fld_metadata) { $file['metadata'] = $row->fa_metadata ? ApiQueryImageInfo::processMetaData(unserialize($row->fa_metadata), $result) : null; } if ($fld_bitdepth) { $file['bitdepth'] = $row->fa_bits; } if ($fld_mime) { $file['mime'] = "{$row->fa_major_mime}/{$row->fa_minor_mime}"; } if ($fld_archivename && !is_null($row->fa_archive_name)) { $file['archivename'] = $row->fa_archive_name; } if ($row->fa_deleted & File::DELETED_FILE) { $file['filehidden'] = true; } if ($row->fa_deleted & File::DELETED_COMMENT) { $file['commenthidden'] = true; } if ($row->fa_deleted & File::DELETED_USER) { $file['userhidden'] = true; } if ($row->fa_deleted & File::DELETED_RESTRICTED) { // This file is deleted for normal admins $file['suppressed'] = true; } $fit = $result->addValue(array('query', $this->getModuleName()), null, $file); if (!$fit) { $this->setContinueEnumParameter('continue', "{$row->fa_name}|{$row->fa_timestamp}|{$row->fa_id}"); break; } } $result->addIndexedTagName(array('query', $this->getModuleName()), 'fa'); }
/** * Get result information for an image revision * * @param File $file * @param array $prop Array of properties to get (in the keys) * @param ApiResult $result * @param array $thumbParams Containing 'width' and 'height' items, or null * @param array|bool|string $opts Options for data fetching. * This is an array consisting of the keys: * 'version': The metadata version for the metadata option * 'language': The language for extmetadata property * 'multilang': Return all translations in extmetadata property * 'revdelUser': User to use when checking whether to show revision-deleted fields. * @return array Result array */ static function getInfo($file, $prop, $result, $thumbParams = null, $opts = false) { global $wgContLang; $anyHidden = false; if (!$opts || is_string($opts)) { $opts = array('version' => $opts ?: 'latest', 'language' => $wgContLang, 'multilang' => false, 'extmetadatafilter' => array(), 'revdelUser' => null); } $version = $opts['version']; $vals = array(ApiResult::META_TYPE => 'assoc'); // Timestamp is shown even if the file is revdelete'd in interface // so do same here. if (isset($prop['timestamp'])) { $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $file->getTimestamp()); } // Handle external callers who don't pass revdelUser if (isset($opts['revdelUser']) && $opts['revdelUser']) { $revdelUser = $opts['revdelUser']; $canShowField = function ($field) use($file, $revdelUser) { return $file->userCan($field, $revdelUser); }; } else { $canShowField = function ($field) use($file) { return !$file->isDeleted($field); }; } $user = isset($prop['user']); $userid = isset($prop['userid']); if ($user || $userid) { if ($file->isDeleted(File::DELETED_USER)) { $vals['userhidden'] = true; $anyHidden = true; } if ($canShowField(File::DELETED_USER)) { if ($user) { $vals['user'] = $file->getUser(); } if ($userid) { $vals['userid'] = $file->getUser('id'); } if (!$file->getUser('id')) { $vals['anon'] = true; } } } // This is shown even if the file is revdelete'd in interface // so do same here. if (isset($prop['size']) || isset($prop['dimensions'])) { $vals['size'] = intval($file->getSize()); $vals['width'] = intval($file->getWidth()); $vals['height'] = intval($file->getHeight()); $pageCount = $file->pageCount(); if ($pageCount !== false) { $vals['pagecount'] = $pageCount; } // length as in how many seconds long a video is. $length = $file->getLength(); if ($length) { // Call it duration, because "length" can be ambiguous. $vals['duration'] = (double) $length; } } $pcomment = isset($prop['parsedcomment']); $comment = isset($prop['comment']); if ($pcomment || $comment) { if ($file->isDeleted(File::DELETED_COMMENT)) { $vals['commenthidden'] = true; $anyHidden = true; } if ($canShowField(File::DELETED_COMMENT)) { if ($pcomment) { $vals['parsedcomment'] = Linker::formatComment($file->getDescription(File::RAW), $file->getTitle()); } if ($comment) { $vals['comment'] = $file->getDescription(File::RAW); } } } $canonicaltitle = isset($prop['canonicaltitle']); $url = isset($prop['url']); $sha1 = isset($prop['sha1']); $meta = isset($prop['metadata']); $extmetadata = isset($prop['extmetadata']); $commonmeta = isset($prop['commonmetadata']); $mime = isset($prop['mime']); $mediatype = isset($prop['mediatype']); $archive = isset($prop['archivename']); $bitdepth = isset($prop['bitdepth']); $uploadwarning = isset($prop['uploadwarning']); if ($uploadwarning) { $vals['html'] = SpecialUpload::getExistsWarning(UploadBase::getExistsWarning($file)); } if ($file->isDeleted(File::DELETED_FILE)) { $vals['filehidden'] = true; $anyHidden = true; } if ($anyHidden && $file->isDeleted(File::DELETED_RESTRICTED)) { $vals['suppressed'] = true; } if (!$canShowField(File::DELETED_FILE)) { //Early return, tidier than indenting all following things one level return $vals; } if ($canonicaltitle) { $vals['canonicaltitle'] = $file->getTitle()->getPrefixedText(); } if ($url) { if (!is_null($thumbParams)) { $mto = $file->transform($thumbParams); self::$transformCount++; if ($mto && !$mto->isError()) { $vals['thumburl'] = wfExpandUrl($mto->getUrl(), PROTO_CURRENT); // bug 23834 - If the URL's are the same, we haven't resized it, so shouldn't give the wanted // thumbnail sizes for the thumbnail actual size if ($mto->getUrl() !== $file->getUrl()) { $vals['thumbwidth'] = intval($mto->getWidth()); $vals['thumbheight'] = intval($mto->getHeight()); } else { $vals['thumbwidth'] = intval($file->getWidth()); $vals['thumbheight'] = intval($file->getHeight()); } if (isset($prop['thumbmime']) && $file->getHandler()) { list(, $mime) = $file->getHandler()->getThumbType($mto->getExtension(), $file->getMimeType(), $thumbParams); $vals['thumbmime'] = $mime; } } elseif ($mto && $mto->isError()) { $vals['thumberror'] = $mto->toText(); } } $vals['url'] = wfExpandUrl($file->getFullURL(), PROTO_CURRENT); $vals['descriptionurl'] = wfExpandUrl($file->getDescriptionUrl(), PROTO_CURRENT); } if ($sha1) { $vals['sha1'] = wfBaseConvert($file->getSha1(), 36, 16, 40); } if ($meta) { wfSuppressWarnings(); $metadata = unserialize($file->getMetadata()); wfRestoreWarnings(); if ($metadata && $version !== 'latest') { $metadata = $file->convertMetadataVersion($metadata, $version); } $vals['metadata'] = $metadata ? self::processMetaData($metadata, $result) : null; } if ($commonmeta) { $metaArray = $file->getCommonMetaArray(); $vals['commonmetadata'] = $metaArray ? self::processMetaData($metaArray, $result) : array(); } if ($extmetadata) { // Note, this should return an array where all the keys // start with a letter, and all the values are strings. // Thus there should be no issue with format=xml. $format = new FormatMetadata(); $format->setSingleLanguage(!$opts['multilang']); $format->getContext()->setLanguage($opts['language']); $extmetaArray = $format->fetchExtendedMetadata($file); if ($opts['extmetadatafilter']) { $extmetaArray = array_intersect_key($extmetaArray, array_flip($opts['extmetadatafilter'])); } $vals['extmetadata'] = $extmetaArray; } if ($mime) { $vals['mime'] = $file->getMimeType(); } if ($mediatype) { $vals['mediatype'] = $file->getMediaType(); } if ($archive && $file->isOld()) { $vals['archivename'] = $file->getArchiveName(); } if ($bitdepth) { $vals['bitdepth'] = $file->getBitDepth(); } return $vals; }
private function extractRowInfo($row) { $revision = new Revision($row); $title = $revision->getTitle(); $vals = array(); if ($this->fld_ids) { $vals['revid'] = intval($revision->getId()); // $vals['oldid'] = intval( $row->rev_text_id ); // todo: should this be exposed? if (!is_null($revision->getParentId())) { $vals['parentid'] = intval($revision->getParentId()); } } if ($this->fld_flags && $revision->isMinor()) { $vals['minor'] = ''; } if ($this->fld_user || $this->fld_userid) { if ($revision->isDeleted(Revision::DELETED_USER)) { $vals['userhidden'] = ''; } else { if ($this->fld_user) { $vals['user'] = $revision->getUserText(); } $userid = $revision->getUser(); if (!$userid) { $vals['anon'] = ''; } if ($this->fld_userid) { $vals['userid'] = $userid; } } } if ($this->fld_timestamp) { $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $revision->getTimestamp()); } if ($this->fld_size) { if (!is_null($revision->getSize())) { $vals['size'] = intval($revision->getSize()); } else { $vals['size'] = 0; } } if ($this->fld_sha1) { if ($revision->getSha1() != '') { $vals['sha1'] = wfBaseConvert($revision->getSha1(), 36, 16, 40); } else { $vals['sha1'] = ''; } } if ($this->fld_comment || $this->fld_parsedcomment) { if ($revision->isDeleted(Revision::DELETED_COMMENT)) { $vals['commenthidden'] = ''; } else { $comment = $revision->getComment(); if ($this->fld_comment) { $vals['comment'] = $comment; } if ($this->fld_parsedcomment) { $vals['parsedcomment'] = Linker::formatComment($comment, $title); } } } if ($this->fld_tags) { if ($row->ts_tags) { $tags = explode(',', $row->ts_tags); $this->getResult()->setIndexedTagName($tags, 'tag'); $vals['tags'] = $tags; } else { $vals['tags'] = array(); } } if (!is_null($this->token)) { $tokenFunctions = $this->getTokenFunctions(); foreach ($this->token as $t) { $val = call_user_func($tokenFunctions[$t], $title->getArticleID(), $title, $revision); if ($val === false) { $this->setWarning("Action '{$t}' is not allowed for the current user"); } else { $vals[$t . 'token'] = $val; } } } $text = null; global $wgParser; if ($this->fld_content || !is_null($this->difftotext)) { $text = $revision->getText(); // Expand templates after getting section content because // template-added sections don't count and Parser::preprocess() // will have less input if ($this->section !== false) { $text = $wgParser->getSection($text, $this->section, false); if ($text === false) { $this->dieUsage("There is no section {$this->section} in r" . $revision->getId(), 'nosuchsection'); } } } if ($this->fld_content && !$revision->isDeleted(Revision::DELETED_TEXT)) { if ($this->generateXML) { $wgParser->startExternalParse($title, ParserOptions::newFromContext($this->getContext()), OT_PREPROCESS); $dom = $wgParser->preprocessToDom($text); if (is_callable(array($dom, 'saveXML'))) { $xml = $dom->saveXML(); } else { $xml = $dom->__toString(); } $vals['parsetree'] = $xml; } if ($this->expandTemplates && !$this->parseContent) { $text = $wgParser->preprocess($text, $title, ParserOptions::newFromContext($this->getContext())); } if ($this->parseContent) { $text = $wgParser->parse($text, $title, ParserOptions::newFromContext($this->getContext()))->getText(); } ApiResult::setContent($vals, $text); } elseif ($this->fld_content) { $vals['texthidden'] = ''; } if (!is_null($this->diffto) || !is_null($this->difftotext)) { global $wgAPIMaxUncachedDiffs; static $n = 0; // Number of uncached diffs we've had if ($n < $wgAPIMaxUncachedDiffs) { $vals['diff'] = array(); $context = new DerivativeContext($this->getContext()); $context->setTitle($title); if (!is_null($this->difftotext)) { $engine = new DifferenceEngine($context); $engine->setText($text, $this->difftotext); } else { $engine = new DifferenceEngine($context, $revision->getID(), $this->diffto); $vals['diff']['from'] = $engine->getOldid(); $vals['diff']['to'] = $engine->getNewid(); } $difftext = $engine->getDiffBody(); ApiResult::setContent($vals['diff'], $difftext); if (!$engine->wasCacheHit()) { $n++; } } else { $vals['diff']['notcached'] = ''; } } return $vals; }
public function formatComment($comment, $title = null, $local = false, $wikiId = null) { return Linker::formatComment($comment, $title, $local, $wikiId); }
/** * @group medium * @dataProvider parserTestProvider * @param string $desc * @param string $input * @param string $result * @param array $opts * @param array $config */ public function testParserTest($desc, $input, $result, $opts, $config) { if ($this->regex != '' && !preg_match('/' . $this->regex . '/', $desc)) { $this->assertTrue(true); // XXX: don't flood output with "test made no assertions" // $this->markTestSkipped( 'Filtered out by the user' ); return; } if (!$this->isWikitextNS(NS_MAIN)) { // parser tests frequently assume that the main namespace contains wikitext. // @todo When setting up pages, force the content model. Only skip if // $wgtContentModelUseDB is false. $this->markTestSkipped("Main namespace does not support wikitext," . "skipping parser test: {$desc}"); } wfDebug("Running parser test: {$desc}\n"); $opts = $this->parseOptions($opts); $context = $this->setupGlobals($opts, $config); $user = $context->getUser(); $options = ParserOptions::newFromContext($context); if (isset($opts['title'])) { $titleText = $opts['title']; } else { $titleText = 'Parser test'; } $local = isset($opts['local']); $preprocessor = isset($opts['preprocessor']) ? $opts['preprocessor'] : null; $parser = $this->getParser($preprocessor); $title = Title::newFromText($titleText); # Parser test requiring math. Make sure texvc is executable # or just skip such tests. if (isset($opts['math']) || isset($opts['texvc'])) { global $wgTexvc; if (!isset($wgTexvc)) { $this->markTestSkipped("SKIPPED: \$wgTexvc is not set"); } elseif (!is_executable($wgTexvc)) { $this->markTestSkipped("SKIPPED: texvc binary does not exist" . " or is not executable.\n" . "Current configuration is:\n\$wgTexvc = '{$wgTexvc}'"); } } if (isset($opts['djvu'])) { if (!$this->djVuSupport->isEnabled()) { $this->markTestSkipped("SKIPPED: djvu binaries do not exist or are not executable.\n"); } } if (isset($opts['tidy'])) { if (!$this->tidySupport->isEnabled()) { $this->markTestSkipped("SKIPPED: tidy extension is not installed.\n"); } else { $options->setTidy(true); } } if (isset($opts['pst'])) { $out = $parser->preSaveTransform($input, $title, $user, $options); } elseif (isset($opts['msg'])) { $out = $parser->transformMsg($input, $options, $title); } elseif (isset($opts['section'])) { $section = $opts['section']; $out = $parser->getSection($input, $section); } elseif (isset($opts['replace'])) { $section = $opts['replace'][0]; $replace = $opts['replace'][1]; $out = $parser->replaceSection($input, $section, $replace); } elseif (isset($opts['comment'])) { $out = Linker::formatComment($input, $title, $local); } elseif (isset($opts['preload'])) { $out = $parser->getPreloadText($input, $title, $options); } else { $output = $parser->parse($input, $title, $options, true, true, 1337); $output->setTOCEnabled(!isset($opts['notoc'])); $out = $output->getText(); if (isset($opts['tidy'])) { $out = preg_replace('/\\s+$/', '', $out); } if (isset($opts['showtitle'])) { if ($output->getTitleText()) { $title = $output->getTitleText(); } $out = "{$title}\n{$out}"; } if (isset($opts['showindicators'])) { $indicators = ''; foreach ($output->getIndicators() as $id => $content) { $indicators .= "{$id}={$content}\n"; } $out = $indicators . $out; } if (isset($opts['ill'])) { $out = implode(' ', $output->getLanguageLinks()); } elseif (isset($opts['cat'])) { $outputPage = $context->getOutput(); $outputPage->addCategoryLinks($output->getCategories()); $cats = $outputPage->getCategoryLinks(); if (isset($cats['normal'])) { $out = implode(' ', $cats['normal']); } else { $out = ''; } } $parser->mPreprocessor = null; } $this->teardownGlobals(); $this->assertEquals($result, $out, $desc); }
function formatValue($name, $value) { static $msg = null; if ($msg === null) { $keys = ['anononlyblock', 'createaccountblock', 'noautoblockblock', 'emailblock', 'blocklist-nousertalk', 'unblocklink', 'change-blocklink']; foreach ($keys as $key) { $msg[$key] = $this->msg($key)->escaped(); } } /** @var $row object */ $row = $this->mCurrentRow; $language = $this->getLanguage(); $formatted = ''; switch ($name) { case 'ipb_timestamp': $formatted = htmlspecialchars($language->userTimeAndDate($value, $this->getUser())); break; case 'ipb_target': if ($row->ipb_auto) { $formatted = $this->msg('autoblockid', $row->ipb_id)->parse(); } else { list($target, $type) = Block::parseTarget($row->ipb_address); switch ($type) { case Block::TYPE_USER: case Block::TYPE_IP: $formatted = Linker::userLink($target->getId(), $target); $formatted .= Linker::userToolLinks($target->getId(), $target, false, Linker::TOOL_LINKS_NOBLOCK); break; case Block::TYPE_RANGE: $formatted = htmlspecialchars($target); } } break; case 'ipb_expiry': $formatted = htmlspecialchars($language->formatExpiry($value, true)); if ($this->getUser()->isAllowed('block')) { if ($row->ipb_auto) { $links[] = Linker::linkKnown(SpecialPage::getTitleFor('Unblock'), $msg['unblocklink'], [], ['wpTarget' => "#{$row->ipb_id}"]); } else { $links[] = Linker::linkKnown(SpecialPage::getTitleFor('Unblock', $row->ipb_address), $msg['unblocklink']); $links[] = Linker::linkKnown(SpecialPage::getTitleFor('Block', $row->ipb_address), $msg['change-blocklink']); } $formatted .= ' ' . Html::rawElement('span', ['class' => 'mw-blocklist-actions'], $this->msg('parentheses')->rawParams($language->pipeList($links))->escaped()); } if ($value !== 'infinity') { $timestamp = new MWTimestamp($value); $formatted .= '<br />' . $this->msg('ipb-blocklist-duration-left', $language->formatDuration($timestamp->getTimestamp() - time(), ['minutes', 'hours', 'days', 'years']))->escaped(); } break; case 'ipb_by': if (isset($row->by_user_name)) { $formatted = Linker::userLink($value, $row->by_user_name); $formatted .= Linker::userToolLinks($value, $row->by_user_name); } else { $formatted = htmlspecialchars($row->ipb_by_text); // foreign user? } break; case 'ipb_reason': $formatted = Linker::formatComment($value); break; case 'ipb_params': $properties = []; if ($row->ipb_anon_only) { $properties[] = $msg['anononlyblock']; } if ($row->ipb_create_account) { $properties[] = $msg['createaccountblock']; } if ($row->ipb_user && !$row->ipb_enable_autoblock) { $properties[] = $msg['noautoblockblock']; } if ($row->ipb_block_email) { $properties[] = $msg['emailblock']; } if (!$row->ipb_allow_usertalk) { $properties[] = $msg['blocklist-nousertalk']; } $formatted = $language->commaList($properties); break; default: $formatted = "Unable to format {$name}"; break; } return $formatted; }
/** * Extract fields from the database row and append them to a result array * * @param $row * @return array */ private function extractRowInfo($row) { $vals = array(); $vals['userid'] = $row->rev_user; $vals['user'] = $row->rev_user_text; if ($row->rev_deleted & Revision::DELETED_USER) { $vals['userhidden'] = ''; } if ($this->fld_ids) { $vals['pageid'] = intval($row->rev_page); $vals['revid'] = intval($row->rev_id); // $vals['textid'] = intval( $row->rev_text_id ); // todo: Should this field be exposed? } $title = Title::makeTitle($row->page_namespace, $row->page_title); if ($this->fld_title) { ApiQueryBase::addTitleInfo($vals, $title); } if ($this->fld_timestamp) { $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->rev_timestamp); } if ($this->fld_flags) { if ($row->rev_parent_id == 0 && !is_null($row->rev_parent_id)) { $vals['new'] = ''; } if ($row->rev_minor_edit) { $vals['minor'] = ''; } if ($row->page_latest == $row->rev_id) { $vals['top'] = ''; } } if (($this->fld_comment || $this->fld_parsedcomment) && isset($row->rev_comment)) { if ($row->rev_deleted & Revision::DELETED_COMMENT) { $vals['commenthidden'] = ''; } else { if ($this->fld_comment) { $vals['comment'] = $row->rev_comment; } if ($this->fld_parsedcomment) { $vals['parsedcomment'] = Linker::formatComment($row->rev_comment, $title); } } } if ($this->fld_patrolled && $row->rc_patrolled) { $vals['patrolled'] = ''; } if ($this->fld_size && !is_null($row->rev_len)) { $vals['size'] = intval($row->rev_len); } if ($this->fld_tags) { if ($row->ts_tags) { $tags = explode(',', $row->ts_tags); $this->getResult()->setIndexedTagName($tags, 'tag'); $vals['tags'] = $tags; } else { $vals['tags'] = array(); } } return $vals; }
/** * @param $resultPageSet ApiPageSet * @return void */ private function run($resultPageSet = null) { $params = $this->extractRequestParams(); $this->addTables('protected_titles'); $this->addFields(array('pt_namespace', 'pt_title', 'pt_timestamp')); $prop = array_flip($params['prop']); $this->addFieldsIf('pt_user', isset($prop['user']) || isset($prop['userid'])); $this->addFieldsIf('pt_reason', isset($prop['comment']) || isset($prop['parsedcomment'])); $this->addFieldsIf('pt_expiry', isset($prop['expiry'])); $this->addFieldsIf('pt_create_perm', isset($prop['level'])); $this->addTimestampWhereRange('pt_timestamp', $params['dir'], $params['start'], $params['end']); $this->addWhereFld('pt_namespace', $params['namespace']); $this->addWhereFld('pt_create_perm', $params['level']); if (isset($prop['user'])) { $this->addTables('user'); $this->addFields('user_name'); $this->addJoinConds(array('user' => array('LEFT JOIN', 'user_id=pt_user'))); } $this->addOption('LIMIT', $params['limit'] + 1); $res = $this->select(__METHOD__); $count = 0; $result = $this->getResult(); $titles = array(); foreach ($res as $row) { if (++$count > $params['limit']) { // We've reached the one extra which shows that there are // additional pages to be had. Stop here... $this->setContinueEnumParameter('start', wfTimestamp(TS_ISO_8601, $row->pt_timestamp)); break; } $title = Title::makeTitle($row->pt_namespace, $row->pt_title); if (is_null($resultPageSet)) { $vals = array(); ApiQueryBase::addTitleInfo($vals, $title); if (isset($prop['timestamp'])) { $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->pt_timestamp); } if (isset($prop['user']) && !is_null($row->user_name)) { $vals['user'] = $row->user_name; } if (isset($prop['userid']) || isset($prop['user'])) { $vals['userid'] = $row->pt_user; } if (isset($prop['comment'])) { $vals['comment'] = $row->pt_reason; } if (isset($prop['parsedcomment'])) { $vals['parsedcomment'] = Linker::formatComment($row->pt_reason, $title); } if (isset($prop['expiry'])) { global $wgContLang; $vals['expiry'] = $wgContLang->formatExpiry($row->pt_expiry, TS_ISO_8601); } if (isset($prop['level'])) { $vals['level'] = $row->pt_create_perm; } $fit = $result->addValue(array('query', $this->getModuleName()), null, $vals); if (!$fit) { $this->setContinueEnumParameter('start', wfTimestamp(TS_ISO_8601, $row->pt_timestamp)); break; } } else { $titles[] = $title; } } if (is_null($resultPageSet)) { $result->setIndexedTagName_internal(array('query', $this->getModuleName()), $this->getModulePrefix()); } else { $resultPageSet->populateFromTitles($titles); } }
private function extractRowInfo($row) { $logEntry = DatabaseLogEntry::newFromRow($row); $vals = array(ApiResult::META_TYPE => 'assoc'); $anyHidden = false; $user = $this->getUser(); if ($this->fld_ids) { $vals['logid'] = intval($row->log_id); } if ($this->fld_title || $this->fld_parsedcomment) { $title = Title::makeTitle($row->log_namespace, $row->log_title); } if ($this->fld_title || $this->fld_ids || $this->fld_details && $row->log_params !== '') { if (LogEventsList::isDeleted($row, LogPage::DELETED_ACTION)) { $vals['actionhidden'] = true; $anyHidden = true; } if (LogEventsList::userCan($row, LogPage::DELETED_ACTION, $user)) { if ($this->fld_title) { ApiQueryBase::addTitleInfo($vals, $title); } if ($this->fld_ids) { $vals['pageid'] = intval($row->page_id); $vals['logpage'] = intval($row->log_page); } if ($this->fld_details) { $vals['params'] = LogFormatter::newFromEntry($logEntry)->formatParametersForApi(); } } } if ($this->fld_type) { $vals['type'] = $row->log_type; $vals['action'] = $row->log_action; } if ($this->fld_user || $this->fld_userid) { if (LogEventsList::isDeleted($row, LogPage::DELETED_USER)) { $vals['userhidden'] = true; $anyHidden = true; } if (LogEventsList::userCan($row, LogPage::DELETED_USER, $user)) { if ($this->fld_user) { $vals['user'] = $row->user_name === null ? $row->log_user_text : $row->user_name; } if ($this->fld_userid) { $vals['userid'] = intval($row->log_user); } if (!$row->log_user) { $vals['anon'] = true; } } } if ($this->fld_timestamp) { $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->log_timestamp); } if (($this->fld_comment || $this->fld_parsedcomment) && isset($row->log_comment)) { if (LogEventsList::isDeleted($row, LogPage::DELETED_COMMENT)) { $vals['commenthidden'] = true; $anyHidden = true; } if (LogEventsList::userCan($row, LogPage::DELETED_COMMENT, $user)) { if ($this->fld_comment) { $vals['comment'] = $row->log_comment; } if ($this->fld_parsedcomment) { $vals['parsedcomment'] = Linker::formatComment($row->log_comment, $title); } } } if ($this->fld_tags) { if ($row->ts_tags) { $tags = explode(',', $row->ts_tags); ApiResult::setIndexedTagName($tags, 'tag'); $vals['tags'] = $tags; } else { $vals['tags'] = array(); } } if ($anyHidden && LogEventsList::isDeleted($row, LogPage::DELETED_RESTRICTED)) { $vals['suppressed'] = true; } return $vals; }
/** * This mimicks the behavior of EditPage in formatting a summary * * @param Title $title of the page being parsed * @param Array $params the API parameters of the request * @return Content|bool */ private function formatSummary($title, $params) { global $wgParser; $summary = !is_null($params['summary']) ? $params['summary'] : ''; $sectionTitle = !is_null($params['sectiontitle']) ? $params['sectiontitle'] : ''; if ($this->section === 'new' && ($sectionTitle === '' || $summary === '')) { if ($sectionTitle !== '') { $summary = $params['sectiontitle']; } if ($summary !== '') { $summary = wfMessage('newsectionsummary')->rawParams($wgParser->stripSectionName($summary))->inContentLanguage()->text(); } } return Linker::formatComment($summary, $title, $this->section === 'new'); }
/** * Extracts from a single sql row the data needed to describe one recent change. * * @param stdClass $row The row from which to extract the data. * @return array An array mapping strings (descriptors) to their respective string values. * @access public */ public function extractRowInfo($row) { /* Determine the title of the page that has been changed. */ $title = Title::makeTitle($row->rc_namespace, $row->rc_title); $user = $this->getUser(); /* Our output data. */ $vals = array(); $type = intval($row->rc_type); $vals['type'] = RecentChange::parseFromRCType($type); $anyHidden = false; /* Create a new entry in the result for the title. */ if ($this->fld_title || $this->fld_ids) { if ($type === RC_LOG && $row->rc_deleted & LogPage::DELETED_ACTION) { $vals['actionhidden'] = true; $anyHidden = true; } if ($type !== RC_LOG || LogEventsList::userCanBitfield($row->rc_deleted, LogPage::DELETED_ACTION, $user)) { if ($this->fld_title) { ApiQueryBase::addTitleInfo($vals, $title); } if ($this->fld_ids) { $vals['pageid'] = intval($row->rc_cur_id); $vals['revid'] = intval($row->rc_this_oldid); $vals['old_revid'] = intval($row->rc_last_oldid); } } } if ($this->fld_ids) { $vals['rcid'] = intval($row->rc_id); } /* Add user data and 'anon' flag, if user is anonymous. */ if ($this->fld_user || $this->fld_userid) { if ($row->rc_deleted & Revision::DELETED_USER) { $vals['userhidden'] = true; $anyHidden = true; } if (Revision::userCanBitfield($row->rc_deleted, Revision::DELETED_USER, $user)) { if ($this->fld_user) { $vals['user'] = $row->rc_user_text; } if ($this->fld_userid) { $vals['userid'] = $row->rc_user; } if (!$row->rc_user) { $vals['anon'] = true; } } } /* Add flags, such as new, minor, bot. */ if ($this->fld_flags) { $vals['bot'] = (bool) $row->rc_bot; $vals['new'] = $row->rc_type == RC_NEW; $vals['minor'] = (bool) $row->rc_minor; } /* Add sizes of each revision. (Only available on 1.10+) */ if ($this->fld_sizes) { $vals['oldlen'] = intval($row->rc_old_len); $vals['newlen'] = intval($row->rc_new_len); } /* Add the timestamp. */ if ($this->fld_timestamp) { $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->rc_timestamp); } /* Add edit summary / log summary. */ if ($this->fld_comment || $this->fld_parsedcomment) { if ($row->rc_deleted & Revision::DELETED_COMMENT) { $vals['commenthidden'] = true; $anyHidden = true; } if (Revision::userCanBitfield($row->rc_deleted, Revision::DELETED_COMMENT, $user)) { if ($this->fld_comment && isset($row->rc_comment)) { $vals['comment'] = $row->rc_comment; } if ($this->fld_parsedcomment && isset($row->rc_comment)) { $vals['parsedcomment'] = Linker::formatComment($row->rc_comment, $title); } } } if ($this->fld_redirect) { $vals['redirect'] = (bool) $row->page_is_redirect; } /* Add the patrolled flag */ if ($this->fld_patrolled) { $vals['patrolled'] = $row->rc_patrolled == 1; $vals['unpatrolled'] = ChangesList::isUnpatrolled($row, $user); } if ($this->fld_loginfo && $row->rc_type == RC_LOG) { if ($row->rc_deleted & LogPage::DELETED_ACTION) { $vals['actionhidden'] = true; $anyHidden = true; } if (LogEventsList::userCanBitfield($row->rc_deleted, LogPage::DELETED_ACTION, $user)) { $vals['logid'] = intval($row->rc_logid); $vals['logtype'] = $row->rc_log_type; $vals['logaction'] = $row->rc_log_action; $vals['logparams'] = LogFormatter::newFromRow($row)->formatParametersForApi(); } } if ($this->fld_tags) { if ($row->ts_tags) { $tags = explode(',', $row->ts_tags); ApiResult::setIndexedTagName($tags, 'tag'); $vals['tags'] = $tags; } else { $vals['tags'] = array(); } } if ($this->fld_sha1 && $row->rev_sha1 !== null) { if ($row->rev_deleted & Revision::DELETED_TEXT) { $vals['sha1hidden'] = true; $anyHidden = true; } if (Revision::userCanBitfield($row->rev_deleted, Revision::DELETED_TEXT, $user)) { if ($row->rev_sha1 !== '') { $vals['sha1'] = wfBaseConvert($row->rev_sha1, 36, 16, 40); } else { $vals['sha1'] = ''; } } } if (!is_null($this->token)) { $tokenFunctions = $this->getTokenFunctions(); foreach ($this->token as $t) { $val = call_user_func($tokenFunctions[$t], $row->rc_cur_id, $title, RecentChange::newFromRow($row)); if ($val === false) { $this->setWarning("Action '{$t}' is not allowed for the current user"); } else { $vals[$t . 'token'] = $val; } } } if ($anyHidden && $row->rc_deleted & Revision::DELETED_RESTRICTED) { $vals['suppressed'] = true; } return $vals; }
/** * Extracts from a single sql row the data needed to describe one recent change. * * @param $row The row from which to extract the data. * @return An array mapping strings (descriptors) to their respective string values. * @access public */ public function extractRowInfo($row) { /* If page was moved somewhere, get the title of the move target. */ $movedToTitle = false; if (isset($row->rc_moved_to_title) && $row->rc_moved_to_title !== '') { $movedToTitle = Title::makeTitle($row->rc_moved_to_ns, $row->rc_moved_to_title); } /* Determine the title of the page that has been changed. */ $title = Title::makeTitle($row->rc_namespace, $row->rc_title); /* Our output data. */ $vals = array(); $type = intval($row->rc_type); /* Determine what kind of change this was. */ switch ($type) { case RC_EDIT: $vals['type'] = 'edit'; break; case RC_NEW: $vals['type'] = 'new'; break; case RC_MOVE: $vals['type'] = 'move'; break; case RC_LOG: $vals['type'] = 'log'; break; case RC_MOVE_OVER_REDIRECT: $vals['type'] = 'move over redirect'; break; default: $vals['type'] = $type; } /* Create a new entry in the result for the title. */ if ($this->fld_title) { ApiQueryBase::addTitleInfo($vals, $title); if ($movedToTitle) { ApiQueryBase::addTitleInfo($vals, $movedToTitle, 'new_'); } } /* Add ids, such as rcid, pageid, revid, and oldid to the change's info. */ if ($this->fld_ids) { $vals['rcid'] = intval($row->rc_id); $vals['pageid'] = intval($row->rc_cur_id); $vals['revid'] = intval($row->rc_this_oldid); $vals['old_revid'] = intval($row->rc_last_oldid); } /* Add user data and 'anon' flag, if use is anonymous. */ if ($this->fld_user || $this->fld_userid) { if ($this->fld_user) { $vals['user'] = $row->rc_user_text; } if ($this->fld_userid) { $vals['userid'] = $row->rc_user; } if (!$row->rc_user) { $vals['anon'] = ''; } } /* Add flags, such as new, minor, bot. */ if ($this->fld_flags) { if ($row->rc_bot) { $vals['bot'] = ''; } if ($row->rc_new) { $vals['new'] = ''; } if ($row->rc_minor) { $vals['minor'] = ''; } } /* Add sizes of each revision. (Only available on 1.10+) */ if ($this->fld_sizes) { $vals['oldlen'] = intval($row->rc_old_len); $vals['newlen'] = intval($row->rc_new_len); } /* Add the timestamp. */ if ($this->fld_timestamp) { $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->rc_timestamp); } /* Add edit summary / log summary. */ if ($this->fld_comment && isset($row->rc_comment)) { $vals['comment'] = $row->rc_comment; } if ($this->fld_parsedcomment && isset($row->rc_comment)) { $vals['parsedcomment'] = Linker::formatComment($row->rc_comment, $title); } if ($this->fld_redirect) { if ($row->page_is_redirect) { $vals['redirect'] = ''; } } /* Add the patrolled flag */ if ($this->fld_patrolled && $row->rc_patrolled == 1) { $vals['patrolled'] = ''; } if ($this->fld_loginfo && $row->rc_type == RC_LOG) { $vals['logid'] = intval($row->rc_logid); $vals['logtype'] = $row->rc_log_type; $vals['logaction'] = $row->rc_log_action; ApiQueryLogEvents::addLogParams($this->getResult(), $vals, $row->rc_params, $row->rc_log_action, $row->rc_log_type, $row->rc_timestamp); } if ($this->fld_tags) { if ($row->ts_tags) { $tags = explode(',', $row->ts_tags); $this->getResult()->setIndexedTagName($tags, 'tag'); $vals['tags'] = $tags; } else { $vals['tags'] = array(); } } if (!is_null($this->token)) { $tokenFunctions = $this->getTokenFunctions(); foreach ($this->token as $t) { $val = call_user_func($tokenFunctions[$t], $row->rc_cur_id, $title, RecentChange::newFromRow($row)); if ($val === false) { $this->setWarning("Action '{$t}' is not allowed for the current user"); } else { $vals[$t . 'token'] = $val; } } } if ($this->fld_wikiamode) { $vals['rc_params'] = $row->rc_params; } return $vals; }
/** @dataProvider parserTestProvider */ public function testParserTest($desc, $input, $result, $opts, $config) { if ($this->regex != '' && !preg_match('/' . $this->regex . '/', $desc)) { $this->assertTrue(true); // XXX: don't flood output with "test made no assertions" //$this->markTestSkipped( 'Filtered out by the user' ); return; } wfDebug("Running parser test: {$desc}\n"); $opts = $this->parseOptions($opts); $context = $this->setupGlobals($opts, $config); $user = $context->getUser(); $options = ParserOptions::newFromContext($context); if (isset($opts['title'])) { $titleText = $opts['title']; } else { $titleText = 'Parser test'; } $local = isset($opts['local']); $preprocessor = isset($opts['preprocessor']) ? $opts['preprocessor'] : null; $parser = $this->getParser($preprocessor); $title = Title::newFromText($titleText); if (isset($opts['pst'])) { $out = $parser->preSaveTransform($input, $title, $user, $options); } elseif (isset($opts['msg'])) { $out = $parser->transformMsg($input, $options, $title); } elseif (isset($opts['section'])) { $section = $opts['section']; $out = $parser->getSection($input, $section); } elseif (isset($opts['replace'])) { $section = $opts['replace'][0]; $replace = $opts['replace'][1]; $out = $parser->replaceSection($input, $section, $replace); } elseif (isset($opts['comment'])) { $out = Linker::formatComment($input, $title, $local); } elseif (isset($opts['preload'])) { $out = $parser->getpreloadText($input, $title, $options); } else { $output = $parser->parse($input, $title, $options, true, true, 1337); $out = $output->getText(); if (isset($opts['showtitle'])) { if ($output->getTitleText()) { $title = $output->getTitleText(); } $out = "{$title}\n{$out}"; } if (isset($opts['ill'])) { $out = $this->tidy(implode(' ', $output->getLanguageLinks())); } elseif (isset($opts['cat'])) { $outputPage = $context->getOutput(); $outputPage->addCategoryLinks($output->getCategories()); $cats = $outputPage->getCategoryLinks(); if (isset($cats['normal'])) { $out = $this->tidy(implode(' ', $cats['normal'])); } else { $out = ''; } } $parser->mPreprocessor = null; $result = $this->tidy($result); } $this->teardownGlobals(); $this->assertEquals($result, $out, $desc); }
private function extractRowInfo($row) { $vals = array(); $type = intval($row->rc_type); /* Determine what kind of change this was. */ switch ($type) { case RC_EDIT: $vals['type'] = 'edit'; break; case RC_NEW: $vals['type'] = 'new'; break; case RC_MOVE: $vals['type'] = 'move'; break; case RC_LOG: $vals['type'] = 'log'; break; case RC_EXTERNAL: $vals['type'] = 'external'; break; case RC_MOVE_OVER_REDIRECT: $vals['type'] = 'move over redirect'; break; default: $vals['type'] = $type; } if ($this->fld_ids) { $vals['pageid'] = intval($row->rc_cur_id); $vals['revid'] = intval($row->rc_this_oldid); $vals['old_revid'] = intval($row->rc_last_oldid); } $title = Title::makeTitle($row->rc_namespace, $row->rc_title); if ($this->fld_title) { ApiQueryBase::addTitleInfo($vals, $title); } if ($this->fld_user || $this->fld_userid) { if ($this->fld_userid) { $vals['userid'] = $row->rc_user; // for backwards compatibility $vals['user'] = $row->rc_user; } if ($this->fld_user) { $vals['user'] = $row->rc_user_text; } if (!$row->rc_user) { $vals['anon'] = ''; } } if ($this->fld_flags) { if ($row->rc_type == RC_NEW) { $vals['new'] = ''; } if ($row->rc_minor) { $vals['minor'] = ''; } if ($row->rc_bot) { $vals['bot'] = ''; } } if ($this->fld_patrol && isset($row->rc_patrolled)) { $vals['patrolled'] = ''; } if ($this->fld_timestamp) { $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->rc_timestamp); } if ($this->fld_sizes) { $vals['oldlen'] = intval($row->rc_old_len); $vals['newlen'] = intval($row->rc_new_len); } if ($this->fld_notificationtimestamp) { $vals['notificationtimestamp'] = $row->wl_notificationtimestamp == null ? '' : wfTimestamp(TS_ISO_8601, $row->wl_notificationtimestamp); } if ($this->fld_comment && isset($row->rc_comment)) { $vals['comment'] = $row->rc_comment; } if ($this->fld_parsedcomment && isset($row->rc_comment)) { $vals['parsedcomment'] = Linker::formatComment($row->rc_comment, $title); } if ($this->fld_loginfo && $row->rc_type == RC_LOG) { $vals['logid'] = intval($row->rc_logid); $vals['logtype'] = $row->rc_log_type; $vals['logaction'] = $row->rc_log_action; $logEntry = DatabaseLogEntry::newFromRow((array) $row); ApiQueryLogEvents::addLogParams($this->getResult(), $vals, $logEntry->getParameters(), $logEntry->getType(), $logEntry->getSubtype(), $logEntry->getTimestamp()); } return $vals; }
public function execute() { $user = $this->getUser(); // Before doing anything at all, let's check permissions if (!$user->isAllowed('deletedhistory')) { $this->dieUsage('You don\'t have permission to view deleted file information', 'permissiondenied'); } $db = $this->getDB(); $params = $this->extractRequestParams(); $prop = array_flip($params['prop']); $fld_sha1 = isset($prop['sha1']); $fld_timestamp = isset($prop['timestamp']); $fld_user = isset($prop['user']); $fld_size = isset($prop['size']); $fld_dimensions = isset($prop['dimensions']); $fld_description = isset($prop['description']) || isset($prop['parseddescription']); $fld_mime = isset($prop['mime']); $fld_mediatype = isset($prop['mediatype']); $fld_metadata = isset($prop['metadata']); $fld_bitdepth = isset($prop['bitdepth']); $fld_archivename = isset($prop['archivename']); $this->addTables('filearchive'); $this->addFields(array('fa_name', 'fa_deleted')); $this->addFieldsIf('fa_storage_key', $fld_sha1); $this->addFieldsIf('fa_timestamp', $fld_timestamp); $this->addFieldsIf(array('fa_user', 'fa_user_text'), $fld_user); $this->addFieldsIf(array('fa_height', 'fa_width', 'fa_size'), $fld_dimensions || $fld_size); $this->addFieldsIf('fa_description', $fld_description); $this->addFieldsIf(array('fa_major_mime', 'fa_minor_mime'), $fld_mime); $this->addFieldsIf('fa_media_type', $fld_mediatype); $this->addFieldsIf('fa_metadata', $fld_metadata); $this->addFieldsIf('fa_bits', $fld_bitdepth); $this->addFieldsIf('fa_archive_name', $fld_archivename); if (!is_null($params['continue'])) { $cont = explode('|', $params['continue']); if (count($cont) != 1) { $this->dieUsage("Invalid continue param. You should pass the " . "original value returned by the previous query", "_badcontinue"); } $op = $params['dir'] == 'descending' ? '<' : '>'; $cont_from = $db->addQuotes($cont[0]); $this->addWhere("fa_name {$op}= {$cont_from}"); } // Image filters $dir = $params['dir'] == 'descending' ? 'older' : 'newer'; $from = is_null($params['from']) ? null : $this->titlePartToKey($params['from']); if (!is_null($params['continue'])) { $from = $params['continue']; } $to = is_null($params['to']) ? null : $this->titlePartToKey($params['to']); $this->addWhereRange('fa_name', $dir, $from, $to); if (isset($params['prefix'])) { $this->addWhere('fa_name' . $db->buildLike($this->titlePartToKey($params['prefix']), $db->anyString())); } $sha1Set = isset($params['sha1']); $sha1base36Set = isset($params['sha1base36']); if ($sha1Set || $sha1base36Set) { global $wgMiserMode; if ($wgMiserMode) { $this->dieUsage('Search by hash disabled in Miser Mode', 'hashsearchdisabled'); } $sha1 = false; if ($sha1Set) { if (!$this->validateSha1Hash($params['sha1'])) { $this->dieUsage('The SHA1 hash provided is not valid', 'invalidsha1hash'); } $sha1 = wfBaseConvert($params['sha1'], 16, 36, 31); } elseif ($sha1base36Set) { if (!$this->validateSha1Base36Hash($params['sha1base36'])) { $this->dieUsage('The SHA1Base36 hash provided is not valid', 'invalidsha1base36hash'); } $sha1 = $params['sha1base36']; } if ($sha1) { $this->addWhere('fa_storage_key ' . $db->buildLike("{$sha1}.", $db->anyString())); } } if (!$user->isAllowed('suppressrevision')) { // Filter out revisions that the user is not allowed to see. There // is no way to indicate that we have skipped stuff because the // continuation parameter is fa_name // Note that this field is unindexed. This should however not be // a big problem as files with fa_deleted are rare $this->addWhereFld('fa_deleted', 0); } $limit = $params['limit']; $this->addOption('LIMIT', $limit + 1); $sort = $params['dir'] == 'descending' ? ' DESC' : ''; $this->addOption('ORDER BY', 'fa_name' . $sort); $res = $this->select(__METHOD__); $count = 0; $result = $this->getResult(); foreach ($res as $row) { if (++$count > $limit) { // We've reached the one extra which shows that there are additional pages to be had. Stop here... $this->setContinueEnumParameter('continue', $row->fa_name); break; } $file = array(); $file['name'] = $row->fa_name; $title = Title::makeTitle(NS_FILE, $row->fa_name); self::addTitleInfo($file, $title); if ($fld_sha1) { $file['sha1'] = wfBaseConvert(LocalRepo::getHashFromKey($row->fa_storage_key), 36, 16, 40); } if ($fld_timestamp) { $file['timestamp'] = wfTimestamp(TS_ISO_8601, $row->fa_timestamp); } if ($fld_user) { $file['userid'] = $row->fa_user; $file['user'] = $row->fa_user_text; } if ($fld_size || $fld_dimensions) { $file['size'] = $row->fa_size; $pageCount = ArchivedFile::newFromRow($row)->pageCount(); if ($pageCount !== false) { $vals['pagecount'] = $pageCount; } $file['height'] = $row->fa_height; $file['width'] = $row->fa_width; } if ($fld_description) { $file['description'] = $row->fa_description; if (isset($prop['parseddescription'])) { $file['parseddescription'] = Linker::formatComment($row->fa_description, $title); } } if ($fld_mediatype) { $file['mediatype'] = $row->fa_media_type; } if ($fld_metadata) { $file['metadata'] = $row->fa_metadata ? ApiQueryImageInfo::processMetaData(unserialize($row->fa_metadata), $result) : null; } if ($fld_bitdepth) { $file['bitdepth'] = $row->fa_bits; } if ($fld_mime) { $file['mime'] = "{$row->fa_major_mime}/{$row->fa_minor_mime}"; } if ($fld_archivename && !is_null($row->fa_archive_name)) { $file['archivename'] = $row->fa_archive_name; } if ($row->fa_deleted & File::DELETED_FILE) { $file['filehidden'] = ''; } if ($row->fa_deleted & File::DELETED_COMMENT) { $file['commenthidden'] = ''; } if ($row->fa_deleted & File::DELETED_USER) { $file['userhidden'] = ''; } if ($row->fa_deleted & File::DELETED_RESTRICTED) { // This file is deleted for normal admins $file['suppressed'] = ''; } $fit = $result->addValue(array('query', $this->getModuleName()), null, $file); if (!$fit) { $this->setContinueEnumParameter('continue', $row->fa_name); break; } } $result->setIndexedTagName_internal(array('query', $this->getModuleName()), 'fa'); }
public function execute() { // The data is hot but user-dependent, like page views, so we set vary cookies $this->getMain()->setCacheMode('anon-public-user-private'); // Get parameters $params = $this->extractRequestParams(); $text = $params['text']; $title = $params['title']; $page = $params['page']; $pageid = $params['pageid']; $oldid = $params['oldid']; $model = $params['contentmodel']; $format = $params['contentformat']; if (!is_null($page) && (!is_null($text) || $title != 'API')) { $this->dieUsage('The page parameter cannot be used together with the text and title parameters', 'params'); } $prop = array_flip($params['prop']); if (isset($params['section'])) { $this->section = $params['section']; } else { $this->section = false; } // The parser needs $wgTitle to be set, apparently the // $title parameter in Parser::parse isn't enough *sigh* // TODO: Does this still need $wgTitle? global $wgParser, $wgTitle; // Currently unnecessary, code to act as a safeguard against any change in current behaviour of uselang breaks $oldLang = null; if (isset($params['uselang']) && $params['uselang'] != $this->getContext()->getLanguage()->getCode()) { $oldLang = $this->getContext()->getLanguage(); // Backup language $this->getContext()->setLanguage(Language::factory($params['uselang'])); } $redirValues = null; // Return result $result = $this->getResult(); if (!is_null($oldid) || !is_null($pageid) || !is_null($page)) { if (!is_null($oldid)) { // Don't use the parser cache $rev = Revision::newFromID($oldid); if (!$rev) { $this->dieUsage("There is no revision ID {$oldid}", 'missingrev'); } if (!$rev->userCan(Revision::DELETED_TEXT, $this->getUser())) { $this->dieUsage("You don't have permission to view deleted revisions", 'permissiondenied'); } $titleObj = $rev->getTitle(); $wgTitle = $titleObj; $pageObj = WikiPage::factory($titleObj); $popts = $pageObj->makeParserOptions($this->getContext()); $popts->enableLimitReport(!$params['disablepp']); // If for some reason the "oldid" is actually the current revision, it may be cached if ($rev->isCurrent()) { // May get from/save to parser cache $p_result = $this->getParsedContent($pageObj, $popts, $pageid, isset($prop['wikitext'])); } else { // This is an old revision, so get the text differently $this->content = $rev->getContent(Revision::FOR_THIS_USER, $this->getUser()); if ($this->section !== false) { $this->content = $this->getSectionContent($this->content, 'r' . $rev->getId()); } // Should we save old revision parses to the parser cache? $p_result = $this->content->getParserOutput($titleObj, $rev->getId(), $popts); } } else { // Not $oldid, but $pageid or $page if ($params['redirects']) { $reqParams = array('action' => 'query', 'redirects' => ''); if (!is_null($pageid)) { $reqParams['pageids'] = $pageid; } else { // $page $reqParams['titles'] = $page; } $req = new FauxRequest($reqParams); $main = new ApiMain($req); $main->execute(); $data = $main->getResultData(); $redirValues = isset($data['query']['redirects']) ? $data['query']['redirects'] : array(); $to = $page; foreach ((array) $redirValues as $r) { $to = $r['to']; } $pageParams = array('title' => $to); } elseif (!is_null($pageid)) { $pageParams = array('pageid' => $pageid); } else { // $page $pageParams = array('title' => $page); } $pageObj = $this->getTitleOrPageId($pageParams, 'fromdb'); $titleObj = $pageObj->getTitle(); if (!$titleObj || !$titleObj->exists()) { $this->dieUsage("The page you specified doesn't exist", 'missingtitle'); } $wgTitle = $titleObj; if (isset($prop['revid'])) { $oldid = $pageObj->getLatest(); } $popts = $pageObj->makeParserOptions($this->getContext()); $popts->enableLimitReport(!$params['disablepp']); // Potentially cached $p_result = $this->getParsedContent($pageObj, $popts, $pageid, isset($prop['wikitext'])); } } else { // Not $oldid, $pageid, $page. Hence based on $text $titleObj = Title::newFromText($title); if (!$titleObj) { $this->dieUsageMsg(array('invalidtitle', $title)); } if (!$titleObj->canExist()) { $this->dieUsage("Namespace doesn't allow actual pages", 'pagecannotexist'); } $wgTitle = $titleObj; $pageObj = WikiPage::factory($titleObj); $popts = $pageObj->makeParserOptions($this->getContext()); $popts->enableLimitReport(!$params['disablepp']); if (is_null($text)) { $this->dieUsage('The text parameter should be passed with the title parameter. Should you be using the "page" parameter instead?', 'params'); } try { $this->content = ContentHandler::makeContent($text, $titleObj, $model, $format); } catch (MWContentSerializationException $ex) { $this->dieUsage($ex->getMessage(), 'parseerror'); } if ($this->section !== false) { $this->content = $this->getSectionContent($this->content, $titleObj->getText()); } if ($params['pst'] || $params['onlypst']) { $this->pstContent = $this->content->preSaveTransform($titleObj, $this->getUser(), $popts); } if ($params['onlypst']) { // Build a result and bail out $result_array = array(); $result_array['text'] = array(); $result->setContent($result_array['text'], $this->pstContent->serialize($format)); if (isset($prop['wikitext'])) { $result_array['wikitext'] = array(); $result->setContent($result_array['wikitext'], $this->content->serialize($format)); } $result->addValue(null, $this->getModuleName(), $result_array); return; } // Not cached (save or load) if ($params['pst']) { $p_result = $this->pstContent->getParserOutput($titleObj, null, $popts); } else { $p_result = $this->content->getParserOutput($titleObj, null, $popts); } } $result_array = array(); $result_array['title'] = $titleObj->getPrefixedText(); if (!is_null($oldid)) { $result_array['revid'] = intval($oldid); } if ($params['redirects'] && !is_null($redirValues)) { $result_array['redirects'] = $redirValues; } if (isset($prop['text'])) { $result_array['text'] = array(); $result->setContent($result_array['text'], $p_result->getText()); } if (!is_null($params['summary'])) { $result_array['parsedsummary'] = array(); $result->setContent($result_array['parsedsummary'], Linker::formatComment($params['summary'], $titleObj)); } if (isset($prop['langlinks'])) { $result_array['langlinks'] = $this->formatLangLinks($p_result->getLanguageLinks()); } if (isset($prop['languageshtml'])) { $languagesHtml = $this->languagesHtml($p_result->getLanguageLinks()); $result_array['languageshtml'] = array(); $result->setContent($result_array['languageshtml'], $languagesHtml); } if (isset($prop['categories'])) { $result_array['categories'] = $this->formatCategoryLinks($p_result->getCategories()); } if (isset($prop['categorieshtml'])) { $categoriesHtml = $this->categoriesHtml($p_result->getCategories()); $result_array['categorieshtml'] = array(); $result->setContent($result_array['categorieshtml'], $categoriesHtml); } if (isset($prop['links'])) { $result_array['links'] = $this->formatLinks($p_result->getLinks()); } if (isset($prop['templates'])) { $result_array['templates'] = $this->formatLinks($p_result->getTemplates()); } if (isset($prop['images'])) { $result_array['images'] = array_keys($p_result->getImages()); } if (isset($prop['externallinks'])) { $result_array['externallinks'] = array_keys($p_result->getExternalLinks()); } if (isset($prop['sections'])) { $result_array['sections'] = $p_result->getSections(); } if (isset($prop['displaytitle'])) { $result_array['displaytitle'] = $p_result->getDisplayTitle() ? $p_result->getDisplayTitle() : $titleObj->getPrefixedText(); } if (isset($prop['headitems']) || isset($prop['headhtml'])) { $context = $this->getContext(); $context->setTitle($titleObj); $context->getOutput()->addParserOutputNoText($p_result); if (isset($prop['headitems'])) { $headItems = $this->formatHeadItems($p_result->getHeadItems()); $css = $this->formatCss($context->getOutput()->buildCssLinksArray()); $scripts = array($context->getOutput()->getHeadScripts()); $result_array['headitems'] = array_merge($headItems, $css, $scripts); } if (isset($prop['headhtml'])) { $result_array['headhtml'] = array(); $result->setContent($result_array['headhtml'], $context->getOutput()->headElement($context->getSkin())); } } if (isset($prop['iwlinks'])) { $result_array['iwlinks'] = $this->formatIWLinks($p_result->getInterwikiLinks()); } if (isset($prop['wikitext'])) { $result_array['wikitext'] = array(); $result->setContent($result_array['wikitext'], $this->content->serialize($format)); if (!is_null($this->pstContent)) { $result_array['psttext'] = array(); $result->setContent($result_array['psttext'], $this->pstContent->serialize($format)); } } if (isset($prop['properties'])) { $result_array['properties'] = $this->formatProperties($p_result->getProperties()); } if ($params['generatexml']) { if ($this->content->getModel() != CONTENT_MODEL_WIKITEXT) { $this->dieUsage("generatexml is only supported for wikitext content", "notwikitext"); } $wgParser->startExternalParse($titleObj, $popts, OT_PREPROCESS); $dom = $wgParser->preprocessToDom($this->content->getNativeData()); if (is_callable(array($dom, 'saveXML'))) { $xml = $dom->saveXML(); } else { $xml = $dom->__toString(); } $result_array['parsetree'] = array(); $result->setContent($result_array['parsetree'], $xml); } $result_mapping = array('redirects' => 'r', 'langlinks' => 'll', 'categories' => 'cl', 'links' => 'pl', 'templates' => 'tl', 'images' => 'img', 'externallinks' => 'el', 'iwlinks' => 'iw', 'sections' => 's', 'headitems' => 'hi', 'properties' => 'pp'); $this->setIndexedTagNames($result_array, $result_mapping); $result->addValue(null, $this->getModuleName(), $result_array); if (!is_null($oldLang)) { $this->getContext()->setLanguage($oldLang); // Reset language to $oldLang } }
public function execute() { // The data is hot but user-dependent, like page views, so we set vary cookies $this->getMain()->setCacheMode('anon-public-user-private'); // Get parameters $params = $this->extractRequestParams(); $text = $params['text']; $title = $params['title']; $page = $params['page']; $pageid = $params['pageid']; $oldid = $params['oldid']; if (!is_null($page) && (!is_null($text) || $title != 'API')) { $this->dieUsage('The page parameter cannot be used together with the text and title parameters', 'params'); } $prop = array_flip($params['prop']); if (isset($params['section'])) { $this->section = $params['section']; } else { $this->section = false; } // The parser needs $wgTitle to be set, apparently the // $title parameter in Parser::parse isn't enough *sigh* // TODO: Does this still need $wgTitle? global $wgParser, $wgTitle, $wgLang; // Currently unnecessary, code to act as a safeguard against any change in current behaviour of uselang breaks $oldLang = null; if (isset($params['uselang']) && $params['uselang'] != $wgLang->getCode()) { $oldLang = $wgLang; // Backup wgLang $wgLang = Language::factory($params['uselang']); } $popts = ParserOptions::newFromContext($this->getContext()); $popts->setTidy(true); $popts->enableLimitReport(!$params['disablepp']); $redirValues = null; // Return result $result = $this->getResult(); if (!is_null($oldid) || !is_null($pageid) || !is_null($page)) { if (!is_null($oldid)) { // Don't use the parser cache $rev = Revision::newFromID($oldid); if (!$rev) { $this->dieUsage("There is no revision ID {$oldid}", 'missingrev'); } if (!$rev->userCan(Revision::DELETED_TEXT, $this->getUser())) { $this->dieUsage("You don't have permission to view deleted revisions", 'permissiondenied'); } $titleObj = $rev->getTitle(); $wgTitle = $titleObj; // If for some reason the "oldid" is actually the current revision, it may be cached if ($titleObj->getLatestRevID() === intval($oldid)) { // May get from/save to parser cache $p_result = $this->getParsedSectionOrText($titleObj, $popts, $pageid, isset($prop['wikitext'])); } else { // This is an old revision, so get the text differently $this->text = $rev->getText(Revision::FOR_THIS_USER, $this->getUser()); if ($this->section !== false) { $this->text = $this->getSectionText($this->text, 'r' . $rev->getId()); } // Should we save old revision parses to the parser cache? $p_result = $wgParser->parse($this->text, $titleObj, $popts); } } else { // Not $oldid, but $pageid or $page if ($params['redirects']) { $reqParams = array('action' => 'query', 'redirects' => ''); if (!is_null($pageid)) { $reqParams['pageids'] = $pageid; } else { // $page $reqParams['titles'] = $page; } $req = new FauxRequest($reqParams); $main = new ApiMain($req); $main->execute(); $data = $main->getResultData(); $redirValues = isset($data['query']['redirects']) ? $data['query']['redirects'] : array(); $to = $page; foreach ((array) $redirValues as $r) { $to = $r['to']; } $titleObj = Title::newFromText($to); } else { if (!is_null($pageid)) { $reqParams['pageids'] = $pageid; $titleObj = Title::newFromID($pageid); } else { // $page $to = $page; $titleObj = Title::newFromText($to); } } if (!is_null($pageid)) { if (!$titleObj) { // Still throw nosuchpageid error if pageid was provided $this->dieUsageMsg(array('nosuchpageid', $pageid)); } } elseif (!$titleObj || !$titleObj->exists()) { $this->dieUsage("The page you specified doesn't exist", 'missingtitle'); } $wgTitle = $titleObj; if (isset($prop['revid'])) { $oldid = $titleObj->getLatestRevID(); } // Potentially cached $p_result = $this->getParsedSectionOrText($titleObj, $popts, $pageid, isset($prop['wikitext'])); } } else { // Not $oldid, $pageid, $page. Hence based on $text if (is_null($text)) { $this->dieUsage('The text parameter should be passed with the title parameter. Should you be using the "page" parameter instead?', 'params'); } $this->text = $text; $titleObj = Title::newFromText($title); if (!$titleObj) { $this->dieUsageMsg(array('invalidtitle', $title)); } $wgTitle = $titleObj; if ($this->section !== false) { $this->text = $this->getSectionText($this->text, $titleObj->getText()); } if ($params['pst'] || $params['onlypst']) { $this->pstText = $wgParser->preSaveTransform($this->text, $titleObj, $this->getUser(), $popts); } if ($params['onlypst']) { // Build a result and bail out $result_array = array(); $result_array['text'] = array(); $result->setContent($result_array['text'], $this->pstText); if (isset($prop['wikitext'])) { $result_array['wikitext'] = array(); $result->setContent($result_array['wikitext'], $this->text); } $result->addValue(null, $this->getModuleName(), $result_array); return; } // Not cached (save or load) $p_result = $wgParser->parse($params['pst'] ? $this->pstText : $this->text, $titleObj, $popts); } $result_array = array(); $result_array['title'] = $titleObj->getPrefixedText(); if (!is_null($oldid)) { $result_array['revid'] = intval($oldid); } if ($params['redirects'] && !is_null($redirValues)) { $result_array['redirects'] = $redirValues; } if (isset($prop['text'])) { $result_array['text'] = array(); $result->setContent($result_array['text'], $p_result->getText()); } if (!is_null($params['summary'])) { $result_array['parsedsummary'] = array(); $result->setContent($result_array['parsedsummary'], Linker::formatComment($params['summary'], $titleObj)); } if (isset($prop['langlinks'])) { $result_array['langlinks'] = $this->formatLangLinks($p_result->getLanguageLinks()); } if (isset($prop['languageshtml'])) { $languagesHtml = $this->languagesHtml($p_result->getLanguageLinks()); $result_array['languageshtml'] = array(); $result->setContent($result_array['languageshtml'], $languagesHtml); } if (isset($prop['categories'])) { $result_array['categories'] = $this->formatCategoryLinks($p_result->getCategories()); } if (isset($prop['categorieshtml'])) { $categoriesHtml = $this->categoriesHtml($p_result->getCategories()); $result_array['categorieshtml'] = array(); $result->setContent($result_array['categorieshtml'], $categoriesHtml); } if (isset($prop['links'])) { $result_array['links'] = $this->formatLinks($p_result->getLinks()); } if (isset($prop['templates'])) { $result_array['templates'] = $this->formatLinks($p_result->getTemplates()); } if (isset($prop['images'])) { $result_array['images'] = array_keys($p_result->getImages()); } if (isset($prop['externallinks'])) { $result_array['externallinks'] = array_keys($p_result->getExternalLinks()); } if (isset($prop['sections'])) { $result_array['sections'] = $p_result->getSections(); } if (isset($prop['displaytitle'])) { $result_array['displaytitle'] = $p_result->getDisplayTitle() ? $p_result->getDisplayTitle() : $titleObj->getPrefixedText(); } if (isset($prop['headitems']) || isset($prop['headhtml'])) { $context = $this->getContext(); $context->setTitle($titleObj); $context->getOutput()->addParserOutputNoText($p_result); if (isset($prop['headitems'])) { $headItems = $this->formatHeadItems($p_result->getHeadItems()); $css = $this->formatCss($context->getOutput()->buildCssLinksArray()); $scripts = array($context->getOutput()->getHeadScripts()); $result_array['headitems'] = array_merge($headItems, $css, $scripts); } if (isset($prop['headhtml'])) { $result_array['headhtml'] = array(); $result->setContent($result_array['headhtml'], $context->getOutput()->headElement($context->getSkin())); } } if (isset($prop['iwlinks'])) { $result_array['iwlinks'] = $this->formatIWLinks($p_result->getInterwikiLinks()); } if (isset($prop['wikitext'])) { $result_array['wikitext'] = array(); $result->setContent($result_array['wikitext'], $this->text); if (!is_null($this->pstText)) { $result_array['psttext'] = array(); $result->setContent($result_array['psttext'], $this->pstText); } } $result_mapping = array('redirects' => 'r', 'langlinks' => 'll', 'categories' => 'cl', 'links' => 'pl', 'templates' => 'tl', 'images' => 'img', 'externallinks' => 'el', 'iwlinks' => 'iw', 'sections' => 's', 'headitems' => 'hi'); $this->setIndexedTagNames($result_array, $result_mapping); $result->addValue(null, $this->getModuleName(), $result_array); if (!is_null($oldLang)) { $wgLang = $oldLang; // Reset $wgLang to $oldLang } }
/** * @param ApiPageSet $resultPageSet * @return void */ private function run($resultPageSet = null) { $params = $this->extractRequestParams(); $this->addTables('protected_titles'); $this->addFields(array('pt_namespace', 'pt_title', 'pt_timestamp')); $prop = array_flip($params['prop']); $this->addFieldsIf('pt_user', isset($prop['user']) || isset($prop['userid'])); $this->addFieldsIf('pt_reason', isset($prop['comment']) || isset($prop['parsedcomment'])); $this->addFieldsIf('pt_expiry', isset($prop['expiry'])); $this->addFieldsIf('pt_create_perm', isset($prop['level'])); $this->addTimestampWhereRange('pt_timestamp', $params['dir'], $params['start'], $params['end']); $this->addWhereFld('pt_namespace', $params['namespace']); $this->addWhereFld('pt_create_perm', $params['level']); // Include in ORDER BY for uniqueness $this->addWhereRange('pt_namespace', $params['dir'], null, null); $this->addWhereRange('pt_title', $params['dir'], null, null); if (!is_null($params['continue'])) { $cont = explode('|', $params['continue']); $this->dieContinueUsageIf(count($cont) != 3); $op = $params['dir'] === 'newer' ? '>' : '<'; $db = $this->getDB(); $continueTimestamp = $db->addQuotes($db->timestamp($cont[0])); $continueNs = (int) $cont[1]; $this->dieContinueUsageIf($continueNs != $cont[1]); $continueTitle = $db->addQuotes($cont[2]); $this->addWhere("pt_timestamp {$op} {$continueTimestamp} OR " . "(pt_timestamp = {$continueTimestamp} AND " . "(pt_namespace {$op} {$continueNs} OR " . "(pt_namespace = {$continueNs} AND " . "pt_title {$op}= {$continueTitle})))"); } if (isset($prop['user'])) { $this->addTables('user'); $this->addFields('user_name'); $this->addJoinConds(array('user' => array('LEFT JOIN', 'user_id=pt_user'))); } $this->addOption('LIMIT', $params['limit'] + 1); $res = $this->select(__METHOD__); $count = 0; $result = $this->getResult(); $titles = array(); foreach ($res as $row) { if (++$count > $params['limit']) { // We've reached the one extra which shows that there are // additional pages to be had. Stop here... $this->setContinueEnumParameter('continue', "{$row->pt_timestamp}|{$row->pt_namespace}|{$row->pt_title}"); break; } $title = Title::makeTitle($row->pt_namespace, $row->pt_title); if (is_null($resultPageSet)) { $vals = array(); ApiQueryBase::addTitleInfo($vals, $title); if (isset($prop['timestamp'])) { $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $row->pt_timestamp); } if (isset($prop['user']) && !is_null($row->user_name)) { $vals['user'] = $row->user_name; } if (isset($prop['userid']) || isset($prop['user'])) { $vals['userid'] = (int) $row->pt_user; } if (isset($prop['comment'])) { $vals['comment'] = $row->pt_reason; } if (isset($prop['parsedcomment'])) { $vals['parsedcomment'] = Linker::formatComment($row->pt_reason, $title); } if (isset($prop['expiry'])) { global $wgContLang; $vals['expiry'] = $wgContLang->formatExpiry($row->pt_expiry, TS_ISO_8601); } if (isset($prop['level'])) { $vals['level'] = $row->pt_create_perm; } $fit = $result->addValue(array('query', $this->getModuleName()), null, $vals); if (!$fit) { $this->setContinueEnumParameter('continue', "{$row->pt_timestamp}|{$row->pt_namespace}|{$row->pt_title}"); break; } } else { $titles[] = $title; } } if (is_null($resultPageSet)) { $result->addIndexedTagName(array('query', $this->getModuleName()), $this->getModulePrefix()); } else { $resultPageSet->populateFromTitles($titles); } }
function formatValue( $field, $value ) { switch ( $field ) { case 'thumb': $opt = array( 'time' => $this->mCurrentRow->img_timestamp ); $file = RepoGroup::singleton()->getLocalRepo()->findFile( $value, $opt ); // If statement for paranoia if ( $file ) { $thumb = $file->transform( array( 'width' => 180, 'height' => 360 ) ); return $thumb->toHtml( array( 'desc-link' => true ) ); } else { return htmlspecialchars( $value ); } case 'img_timestamp': // We may want to make this a link to the "old" version when displaying old files return htmlspecialchars( $this->getLanguage()->userTimeAndDate( $value, $this->getUser() ) ); case 'img_name': static $imgfile = null; if ( $imgfile === null ) { $imgfile = $this->msg( 'imgfile' )->text(); } // Weird files can maybe exist? Bug 22227 $filePage = Title::makeTitleSafe( NS_FILE, $value ); if ( $filePage ) { $link = Linker::linkKnown( $filePage, htmlspecialchars( $filePage->getText() ) ); $download = Xml::element( 'a', array( 'href' => wfLocalFile( $filePage )->getURL() ), $imgfile ); $download = $this->msg( 'parentheses' )->rawParams( $download )->escaped(); return "$link $download"; } else { return htmlspecialchars( $value ); } case 'img_user_text': if ( $this->mCurrentRow->img_user ) { $name = User::whoIs( $this->mCurrentRow->img_user ); $link = Linker::link( Title::makeTitle( NS_USER, $name ), htmlspecialchars( $name ) ); } else { $link = htmlspecialchars( $value ); } return $link; case 'img_size': return htmlspecialchars( $this->getLanguage()->formatSize( $value ) ); case 'img_description': return Linker::formatComment( $value ); case 'count': return intval( $value ) + 1; case 'top': // Messages: listfiles-latestversion-yes, listfiles-latestversion-no return $this->msg( 'listfiles-latestversion-' . $value ); } }