Example #1
0
 /**
  * Get the IContextSource in use here
  * @return IContextSource
  */
 public final function getContext()
 {
     if ($this->context instanceof IContextSource) {
         return $this->context;
     }
     return $this->page->getContext();
 }
Example #2
0
	/**
	 * Get the IContextSource in use here
	 * @return IContextSource
	 */
	final public function getContext() {
		if ( $this->context instanceof IContextSource ) {
			return $this->context;
		} else if ( $this->page instanceof Article ) {
			// NOTE: $this->page can be a WikiPage, which does not have a context.
			wfDebug( __METHOD__ . ': no context known, falling back to Article\'s context.' );
			return $this->page->getContext();
		}

		wfWarn( __METHOD__ . ': no context known, falling back to RequestContext::getMain().' );
		return RequestContext::getMain();
	}
 /**
  * Display a message
  *
  * @param Article &$article
  * @param boolean $outputDone
  * @param boolean $useParserCache
  *
  * @return true
  */
 public static function onArticleViewHeader(Article &$article, &$outputDone, &$useParserCache)
 {
     global $wgOut;
     $title = $article->getTitle();
     if (!ApprovedRevs::isAssignedToProject($title)) {
         return true;
     }
     $user = $article->getContext()->getUser();
     $banner = self::showProjectBanner($title, $user);
     if (!is_null($banner)) {
         $wgOut->addModuleStyles('ext.wrApprovedRevs.main');
         $wgOut->addHTML($banner);
     }
     return true;
 }
 /**
  * Log stuff to EventLogging's Schema:Edit - see https://meta.wikimedia.org/wiki/Schema:Edit
  * If you don't have EventLogging installed, does nothing.
  *
  * @param string $action
  * @param Article $article Which article (with full context, page, title, etc.)
  * @param array $data Data to log for this action
  * @return bool Whether the event was logged or not.
  */
 public static function doEventLogging($action, $article, $data = array())
 {
     global $wgVersion;
     if (!class_exists('EventLogging')) {
         return false;
     }
     $user = $article->getContext()->getUser();
     $page = $article->getPage();
     $title = $article->getTitle();
     $data = array('action' => $action, 'version' => 1, 'editor' => 'wikitext', 'platform' => 'desktop', 'integration' => 'page', 'page.length' => -1, 'page.id' => $page->getId(), 'page.title' => $title->getPrefixedText(), 'page.ns' => $title->getNamespace(), 'page.revid' => $page->getRevision() ? $page->getRevision()->getId() : 0, 'user.id' => $user->getId(), 'user.editCount' => $user->getEditCount() ?: 0, 'mediawiki.version' => $wgVersion) + $data;
     if ($user->isAnon()) {
         $data['user.class'] = 'IP';
     }
     return EventLogging::logEvent('Edit', 11448630, $data);
 }
Example #5
0
 function __construct(Article $article)
 {
     // Set instance variables.
     $this->mArticle = $article;
     $this->mTitle = $article->getTitle();
     $this->mApplicableTypes = $this->mTitle->getRestrictionTypes();
     $this->mContext = $article->getContext();
     // Check if the form should be disabled.
     // If it is, the form will be available in read-only to show levels.
     $this->mPermErrors = $this->mTitle->getUserPermissionsErrors('protect', $this->mContext->getUser(), $this->mContext->getRequest()->wasPosted() ? 'secure' : 'full');
     if (wfReadOnly()) {
         $this->mPermErrors[] = ['readonlytext', wfReadOnlyReason()];
     }
     $this->disabled = $this->mPermErrors != [];
     $this->disabledAttrib = $this->disabled ? ['disabled' => 'disabled'] : [];
     $this->loadData();
 }
Example #6
0
 /**
  * @depends testAutoMerge
  */
 public function testCheckDirectEditingDisallowed_forNonTextContent()
 {
     $title = Title::newFromText('Dummy:NonTextPageForEditPage');
     $page = WikiPage::factory($title);
     $article = new Article($title);
     $article->getContext()->setTitle($title);
     $ep = new EditPage($article);
     $ep->setContextTitle($title);
     $user = $GLOBALS['wgUser'];
     $edit = ['wpTextbox1' => serialize('non-text content'), 'wpEditToken' => $user->getEditToken(), 'wpEdittime' => '', 'wpStarttime' => wfTimestampNow()];
     $req = new FauxRequest($edit, true);
     $ep->importFormData($req);
     $this->setExpectedException('MWException', 'This content model is not supported: testing');
     $ep->internalAttemptSave($result, false);
 }
Example #7
0
 /**
  * Show "your edit contains spam" page with your diff and text
  *
  * @param $match Text which triggered one or more filters
  */
 public function spamPageWithContent($match = false)
 {
     global $wgOut;
     $this->textbox2 = $this->textbox1;
     $wgOut->prepareErrorPage(wfMessage('spamprotectiontitle'));
     $wgOut->addHTML('<div id="spamprotected">');
     $wgOut->addWikiMsg('spamprotectiontext');
     if ($match) {
         $wgOut->addWikiMsg('spamprotectionmatch', wfEscapeWikiText($match));
     }
     $wgOut->addHTML('</div>');
     $wgOut->wrapWikiMsg('<h2>$1</h2>', "yourdiff");
     $de = new DifferenceEngine($this->mArticle->getContext());
     $de->setText($this->getCurrentText(), $this->textbox2);
     $de->showDiff(wfMsg("storedversion"), wfMsgExt('yourtext', 'parseinline'));
     $wgOut->wrapWikiMsg('<h2>$1</h2>', "yourtext");
     $this->showTextbox2();
     $wgOut->addReturnTo($this->getContextTitle(), array('action' => 'edit'));
 }
 /**
  * Performs an edit and checks the result.
  *
  * @param string|Title $title The title of the page to edit
  * @param string|null $baseText Some text to create the page with before attempting the edit.
  * @param User|string|null $user The user to perform the edit as.
  * @param array $edit An array of request parameters used to define the edit to perform.
  *              Some well known fields are:
  *              * wpTextbox1: the text to submit
  *              * wpSummary: the edit summary
  *              * wpEditToken: the edit token (will be inserted if not provided)
  *              * wpEdittime: timestamp of the edit's base revision (will be inserted
  *                if not provided)
  *              * wpStarttime: timestamp when the edit started (will be inserted if not provided)
  *              * wpSectionTitle: the section to edit
  *              * wpMinorEdit: mark as minor edit
  *              * wpWatchthis: whether to watch the page
  * @param int|null $expectedCode The expected result code (EditPage::AS_XXX constants).
  *                  Set to null to skip the check.
  * @param string|null $expectedText The text expected to be on the page after the edit.
  *                  Set to null to skip the check.
  * @param string|null $message An optional message to show along with any error message.
  *
  * @return WikiPage The page that was just edited, useful for getting the edit's rev_id, etc.
  */
 protected function assertEdit($title, $baseText, $user = null, array $edit, $expectedCode = null, $expectedText = null, $message = null)
 {
     if (is_string($title)) {
         $ns = $this->getDefaultWikitextNS();
         $title = Title::newFromText($title, $ns);
     }
     $this->assertNotNull($title);
     if (is_string($user)) {
         $user = User::newFromName($user);
         if ($user->getId() === 0) {
             $user->addToDatabase();
         }
     }
     $page = WikiPage::factory($title);
     if ($baseText !== null) {
         $content = ContentHandler::makeContent($baseText, $title);
         $page->doEditContent($content, "base text for test");
         $this->forceRevisionDate($page, '20120101000000');
         //sanity check
         $page->clear();
         $currentText = ContentHandler::getContentText($page->getContent());
         # EditPage rtrim() the user input, so we alter our expected text
         # to reflect that.
         $this->assertEditedTextEquals($baseText, $currentText);
     }
     if ($user == null) {
         $user = $GLOBALS['wgUser'];
     } else {
         $this->setMwGlobals('wgUser', $user);
     }
     if (!isset($edit['wpEditToken'])) {
         $edit['wpEditToken'] = $user->getEditToken();
     }
     if (!isset($edit['wpEdittime'])) {
         $edit['wpEdittime'] = $page->exists() ? $page->getTimestamp() : '';
     }
     if (!isset($edit['wpStarttime'])) {
         $edit['wpStarttime'] = wfTimestampNow();
     }
     $req = new FauxRequest($edit, true);
     // session ??
     $article = new Article($title);
     $article->getContext()->setTitle($title);
     $ep = new EditPage($article);
     $ep->setContextTitle($title);
     $ep->importFormData($req);
     $bot = isset($edit['bot']) ? (bool) $edit['bot'] : false;
     // this is where the edit happens!
     // Note: don't want to use EditPage::AttemptSave, because it messes with $wgOut
     // and throws exceptions like PermissionsError
     $status = $ep->internalAttemptSave($result, $bot);
     if ($expectedCode !== null) {
         // check edit code
         $this->assertEquals($expectedCode, $status->value, "Expected result code mismatch. {$message}");
     }
     $page = WikiPage::factory($title);
     if ($expectedText !== null) {
         // check resulting page text
         $content = $page->getContent();
         $text = ContentHandler::getContentText($content);
         # EditPage rtrim() the user input, so we alter our expected text
         # to reflect that.
         $this->assertEditedTextEquals($expectedText, $text, "Expected article text mismatch. {$message}");
     }
     return $page;
 }
Example #9
0
 /**
  * Get the rendered text for previewing.
  * @throws MWException
  * @return string
  */
 function getPreviewText()
 {
     global $wgOut, $wgUser, $wgRawHtml, $wgLang;
     global $wgAllowUserCss, $wgAllowUserJs;
     wfProfileIn(__METHOD__);
     if ($wgRawHtml && !$this->mTokenOk) {
         // Could be an offsite preview attempt. This is very unsafe if
         // HTML is enabled, as it could be an attack.
         $parsedNote = '';
         if ($this->textbox1 !== '') {
             // Do not put big scary notice, if previewing the empty
             // string, which happens when you initially edit
             // a category page, due to automatic preview-on-open.
             $parsedNote = $wgOut->parse("<div class='previewnote'>" . wfMessage('session_fail_preview_html')->text() . "</div>", true, true);
         }
         wfProfileOut(__METHOD__);
         return $parsedNote;
     }
     $note = '';
     try {
         $content = $this->toEditContent($this->textbox1);
         $previewHTML = '';
         if (!wfRunHooks('AlternateEditPreview', array($this, &$content, &$previewHTML, &$this->mParserOutput))) {
             wfProfileOut(__METHOD__);
             return $previewHTML;
         }
         # provide a anchor link to the editform
         $continueEditing = '<span class="mw-continue-editing">' . '[[#' . self::EDITFORM_ID . '|' . $wgLang->getArrow() . ' ' . wfMessage('continue-editing')->text() . ']]</span>';
         if ($this->mTriedSave && !$this->mTokenOk) {
             if ($this->mTokenOkExceptSuffix) {
                 $note = wfMessage('token_suffix_mismatch')->plain();
             } else {
                 $note = wfMessage('session_fail_preview')->plain();
             }
         } elseif ($this->incompleteForm) {
             $note = wfMessage('edit_form_incomplete')->plain();
         } else {
             $note = wfMessage('previewnote')->plain() . ' ' . $continueEditing;
         }
         $parserOptions = $this->mArticle->makeParserOptions($this->mArticle->getContext());
         $parserOptions->setEditSection(false);
         $parserOptions->setIsPreview(true);
         $parserOptions->setIsSectionPreview(!is_null($this->section) && $this->section !== '');
         # don't parse non-wikitext pages, show message about preview
         if ($this->mTitle->isCssJsSubpage() || $this->mTitle->isCssOrJsPage()) {
             if ($this->mTitle->isCssJsSubpage()) {
                 $level = 'user';
             } elseif ($this->mTitle->isCssOrJsPage()) {
                 $level = 'site';
             } else {
                 $level = false;
             }
             if ($content->getModel() == CONTENT_MODEL_CSS) {
                 $format = 'css';
                 if ($level === 'user' && !$wgAllowUserCss) {
                     $format = false;
                 }
             } elseif ($content->getModel() == CONTENT_MODEL_JAVASCRIPT) {
                 $format = 'js';
                 if ($level === 'user' && !$wgAllowUserJs) {
                     $format = false;
                 }
             } else {
                 $format = false;
             }
             # Used messages to make sure grep find them:
             # Messages: usercsspreview, userjspreview, sitecsspreview, sitejspreview
             if ($level && $format) {
                 $note = "<div id='mw-{$level}{$format}preview'>" . wfMessage("{$level}{$format}preview")->text() . ' ' . $continueEditing . "</div>";
             }
         }
         # If we're adding a comment, we need to show the
         # summary as the headline
         if ($this->section === "new" && $this->summary !== "") {
             $content = $content->addSectionHeader($this->summary);
         }
         $hook_args = array($this, &$content);
         ContentHandler::runLegacyHooks('EditPageGetPreviewText', $hook_args);
         wfRunHooks('EditPageGetPreviewContent', $hook_args);
         $parserOptions->enableLimitReport();
         # For CSS/JS pages, we should have called the ShowRawCssJs hook here.
         # But it's now deprecated, so never mind
         $content = $content->preSaveTransform($this->mTitle, $wgUser, $parserOptions);
         $parserOutput = $content->getParserOutput($this->getArticle()->getTitle(), null, $parserOptions);
         $previewHTML = $parserOutput->getText();
         $this->mParserOutput = $parserOutput;
         $wgOut->addParserOutputMetadata($parserOutput);
         if (count($parserOutput->getWarnings())) {
             $note .= "\n\n" . implode("\n\n", $parserOutput->getWarnings());
         }
     } catch (MWContentSerializationException $ex) {
         $m = wfMessage('content-failed-to-parse', $this->contentModel, $this->contentFormat, $ex->getMessage());
         $note .= "\n\n" . $m->parse();
         $previewHTML = '';
     }
     if ($this->isConflict) {
         $conflict = '<h2 id="mw-previewconflict">' . wfMessage('previewconflict')->escaped() . "</h2>\n";
     } else {
         $conflict = '<hr />';
     }
     $previewhead = "<div class='previewnote'>\n" . '<h2 id="mw-previewheader">' . wfMessage('preview')->escaped() . "</h2>" . $wgOut->parse($note, true, true) . $conflict . "</div>\n";
     $pageViewLang = $this->mTitle->getPageViewLanguage();
     $attribs = array('lang' => $pageViewLang->getHtmlCode(), 'dir' => $pageViewLang->getDir(), 'class' => 'mw-content-' . $pageViewLang->getDir());
     $previewHTML = Html::rawElement('div', $attribs, $previewHTML);
     wfProfileOut(__METHOD__);
     return $previewhead . $previewHTML . $this->previewTextAfterContent;
 }
 /**
  * Hook used to determine if current user should be given the edit interface
  * for a page.
  *
  * @todo Not clear if this is the best hook to use. onBeforePageDisplay
  *  doesn't have easy access to oldid
  *
  * @param $output OutputPage
  */
 public static function onArticleViewHeader(Article $article)
 {
     $title = $article->getTitle();
     $context = $article->getContext();
     $user = $context->getUser();
     $output = $context->getOutput();
     $action = $context->getRequest()->getVal('action', 'view');
     // @todo Does not trigger on perma-link to current revision
     //  not sure if that's a desired behaviour or not.
     if ($title->getContentModel() === __CLASS__ && $action === 'view' && $title->getArticleId() !== 0 && $article->getOldID() === 0 && $title->userCan('edit', $user, 'quick')) {
         $output->addJsConfigVars('wgEnableCollaborationKitListEdit', true);
         /*
         Disabling until JavaScript module is updated.
         $output->addModules( 'ext.CollaborationKit.list.edit' );
         */
         $output->preventClickjacking();
     }
 }
Example #11
0
 /**
  * Returns an array of html code of the following buttons:
  * save, diff, preview and live
  *
  * @param int $tabindex Current tabindex
  *
  * @return array
  */
 public function getEditButtons(&$tabindex)
 {
     $buttons = [];
     $labelAsPublish = $this->mArticle->getContext()->getConfig()->get('EditSubmitButtonLabelPublish');
     // Can't use $this->isNew as that's also true if we're adding a new section to an extant page
     if ($labelAsPublish) {
         $buttonLabelKey = !$this->mTitle->exists() ? 'publishpage' : 'publishchanges';
     } else {
         $buttonLabelKey = !$this->mTitle->exists() ? 'savearticle' : 'savechanges';
     }
     $buttonLabel = $this->context->msg($buttonLabelKey)->text();
     $attribs = ['id' => 'wpSave', 'name' => 'wpSave', 'tabindex' => ++$tabindex] + Linker::tooltipAndAccesskeyAttribs('save');
     $buttons['save'] = Html::submitButton($buttonLabel, $attribs, ['mw-ui-progressive']);
     ++$tabindex;
     // use the same for preview and live preview
     $attribs = ['id' => 'wpPreview', 'name' => 'wpPreview', 'tabindex' => $tabindex] + Linker::tooltipAndAccesskeyAttribs('preview');
     $buttons['preview'] = Html::submitButton($this->context->msg('showpreview')->text(), $attribs);
     $buttons['live'] = '';
     $attribs = ['id' => 'wpDiff', 'name' => 'wpDiff', 'tabindex' => ++$tabindex] + Linker::tooltipAndAccesskeyAttribs('diff');
     $buttons['diff'] = Html::submitButton($this->context->msg('showdiff')->text(), $attribs);
     Hooks::run('EditPageBeforeEditButtons', [&$this, &$buttons, &$tabindex]);
     return $buttons;
 }
 public static function onShowMissingArticle(Article $article)
 {
     if ($article->getPage()->getContentModel() !== CONTENT_MODEL_FLOW_BOARD) {
         return true;
     }
     if ($article->getTitle()->getNamespace() === NS_TOPIC) {
         // @todo pretty message about invalid workflow
         throw new FlowException('Non-existent topic');
     }
     $emptyContent = ContentHandler::getForModelID(CONTENT_MODEL_FLOW_BOARD)->makeEmptyContent();
     $parserOutput = $emptyContent->getParserOutput($article->getTitle());
     $article->getContext()->getOutput()->addParserOutput($parserOutput);
     return false;
 }
Example #13
0
 /**
  * The ArticleViewHeader hook, used to alter the headers before the rest
  * of the data is loaded.
  *
  * Note: this is not called when the Edit, Diff or History pages are loaded.
  *
  * @param Article $article pointer to the Article Object from the hook
  * @param boolean $outputDone pointer to variable that indicates that
  *                         the output should be terminated
  * @param boolean $pcache pointer to variable that indicates whether the parser
  * 			cache should try retrieving the cached results
  *
  * @return boolean indicating success to the caller
  */
 public function onArticleViewHeader(&$article, &$outputDone, &$pcache)
 {
     // avoid processing Mementos for nonexistent pages
     // if we're an article, do memento processing, otherwise don't worry
     // if we're a diff page, Memento doesn't make sense
     if ($article->getTitle()->isKnown()) {
         $this->oldIDSet = $article->getOldID() != 0;
         $revision = $article->getRevisionFetched();
         // avoid processing Mementos for bad revisions,
         // let MediaWiki handle that case instead
         if (is_object($revision)) {
             $this->articleDatetime = $revision->getTimestamp();
             $db = wfGetDB(DB_SLAVE);
             $oldID = $article->getOldID();
             $request = $article->getContext()->getRequest();
             $this->mementoResource = MementoResource::mementoPageResourceFactory($db, $article, $oldID);
             $this->mementoResource->alterHeaders();
         }
     }
     return true;
 }
Example #14
0
 /**
  * Get the rendered text for previewing.
  * @return string
  */
 function getPreviewText()
 {
     global $wgOut, $wgUser, $wgParser, $wgRawHtml, $wgLang;
     wfProfileIn(__METHOD__);
     if ($wgRawHtml && !$this->mTokenOk) {
         // Could be an offsite preview attempt. This is very unsafe if
         // HTML is enabled, as it could be an attack.
         $parsedNote = '';
         if ($this->textbox1 !== '') {
             // Do not put big scary notice, if previewing the empty
             // string, which happens when you initially edit
             // a category page, due to automatic preview-on-open.
             $parsedNote = $wgOut->parse("<div class='previewnote'>" . wfMessage('session_fail_preview_html')->text() . "</div>", true, true);
         }
         wfProfileOut(__METHOD__);
         return $parsedNote;
     }
     if ($this->mTriedSave && !$this->mTokenOk) {
         if ($this->mTokenOkExceptSuffix) {
             $note = wfMessage('token_suffix_mismatch')->plain();
         } else {
             $note = wfMessage('session_fail_preview')->plain();
         }
     } elseif ($this->incompleteForm) {
         $note = wfMessage('edit_form_incomplete')->plain();
     } else {
         $note = wfMessage('previewnote')->plain() . ' [[#' . self::EDITFORM_ID . '|' . $wgLang->getArrow() . ' ' . wfMessage('continue-editing')->text() . ']]';
     }
     $parserOptions = $this->mArticle->makeParserOptions($this->mArticle->getContext());
     $parserOptions->setEditSection(false);
     $parserOptions->setIsPreview(true);
     $parserOptions->setIsSectionPreview(!is_null($this->section) && $this->section !== '');
     # don't parse non-wikitext pages, show message about preview
     if ($this->mTitle->isCssJsSubpage() || !$this->mTitle->isWikitextPage()) {
         if ($this->mTitle->isCssJsSubpage()) {
             $level = 'user';
         } elseif ($this->mTitle->isCssOrJsPage()) {
             $level = 'site';
         } else {
             $level = false;
         }
         # Used messages to make sure grep find them:
         # Messages: usercsspreview, userjspreview, sitecsspreview, sitejspreview
         $class = 'mw-code';
         if ($level) {
             if (preg_match("/\\.css\$/", $this->mTitle->getText())) {
                 $previewtext = "<div id='mw-{$level}csspreview'>\n" . wfMessage("{$level}csspreview")->text() . "\n</div>";
                 $class .= " mw-css";
             } elseif (preg_match("/\\.js\$/", $this->mTitle->getText())) {
                 $previewtext = "<div id='mw-{$level}jspreview'>\n" . wfMessage("{$level}jspreview")->text() . "\n</div>";
                 $class .= " mw-js";
             } else {
                 throw new MWException('A CSS/JS (sub)page but which is not css nor js!');
             }
             $parserOutput = $wgParser->parse($previewtext, $this->mTitle, $parserOptions);
             $previewHTML = $parserOutput->getText();
         } else {
             $previewHTML = '';
         }
         $previewHTML .= "<pre class=\"{$class}\" dir=\"ltr\">\n" . htmlspecialchars($this->textbox1) . "\n</pre>\n";
     } else {
         $toparse = $this->textbox1;
         # If we're adding a comment, we need to show the
         # summary as the headline
         if ($this->section == "new" && $this->summary != "") {
             $toparse = wfMessage('newsectionheaderdefaultlevel', $this->summary)->inContentLanguage()->text() . "\n\n" . $toparse;
         }
         wfRunHooks('EditPageGetPreviewText', array($this, &$toparse));
         $toparse = $wgParser->preSaveTransform($toparse, $this->mTitle, $wgUser, $parserOptions);
         $parserOutput = $wgParser->parse($toparse, $this->mTitle, $parserOptions);
         $rt = Title::newFromRedirectArray($this->textbox1);
         if ($rt) {
             $previewHTML = $this->mArticle->viewRedirect($rt, false);
         } else {
             $previewHTML = $parserOutput->getText();
         }
         $this->mParserOutput = $parserOutput;
         $wgOut->addParserOutputNoText($parserOutput);
         if (count($parserOutput->getWarnings())) {
             $note .= "\n\n" . implode("\n\n", $parserOutput->getWarnings());
         }
     }
     if ($this->isConflict) {
         $conflict = '<h2 id="mw-previewconflict">' . wfMessage('previewconflict')->escaped() . "</h2>\n";
     } else {
         $conflict = '<hr />';
     }
     $previewhead = "<div class='previewnote'>\n" . '<h2 id="mw-previewheader">' . wfMessage('preview')->escaped() . "</h2>" . $wgOut->parse($note, true, true) . $conflict . "</div>\n";
     $pageLang = $this->mTitle->getPageLanguage();
     $attribs = array('lang' => $pageLang->getCode(), 'dir' => $pageLang->getDir(), 'class' => 'mw-content-' . $pageLang->getDir());
     $previewHTML = Html::rawElement('div', $attribs, $previewHTML);
     wfProfileOut(__METHOD__);
     return $previewhead . $previewHTML . $this->previewTextAfterContent;
 }