Example #1
0
 /**
  * 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;
 }
Example #2
0
 /**
  * @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));
 }
Example #3
0
 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;
 }
Example #5
0
 /**
  * @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;
 }
Example #9
0
 /**
  * @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;
 }
Example #12
0
 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;
 }
Example #14
0
 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;
 }
Example #15
0
 public function formatComment($comment, $title = null, $local = false, $wikiId = null)
 {
     return Linker::formatComment($comment, $title, $local, $wikiId);
 }
Example #16
0
 /**
  * @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);
 }
Example #17
0
 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;
 }
Example #21
0
 /**
  * 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;
 }
Example #24
0
 /** @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);
 }
Example #25
0
 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;
 }
Example #26
0
 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');
 }
Example #27
0
 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
     }
 }
Example #28
0
 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);
     }
 }
Example #30
0
	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 );
		}
	}