1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
<?php
use MediaWiki\Context\DerivativeContext;
use MediaWiki\Context\RequestContext;
use MediaWiki\Language\Language;
use MediaWiki\Output\OutputPage;
use MediaWiki\Permissions\Authority;
use MediaWiki\Request\FauxRequest;
use MediaWiki\Request\FauxResponse;
use MediaWiki\Request\WebRequest;
use MediaWiki\SpecialPage\SpecialPage;
/**
* @author Addshore
*
* @since 1.27
*/
class SpecialPageExecutor {
/**
* @param SpecialPage $page The special page to execute
* @param string|null $subPage The subpage parameter to call the page with
* @param WebRequest|null $request Web request that may contain URL parameters, etc
* @param Language|string|null $language The language which should be used in the context;
* if not specified, the pseudo-code 'qqx' is used
* @param Authority|null $performer The user which should be used in the context of this special page
* @param bool $fullHtml if true, the entirety of the generated HTML will be returned, this
* includes the opening <!DOCTYPE> declaration and closing </html> tag. If false, only value
* of OutputPage::getHTML() will be returned except if the page is redirect or where OutputPage
* is completely disabled.
*
* @return array [ string, WebResponse ] A two-elements array containing the HTML output
* generated by the special page as well as the response object.
*/
public function executeSpecialPage(
SpecialPage $page,
$subPage = '',
?WebRequest $request = null,
$language = null,
?Authority $performer = null,
$fullHtml = false
) {
$context = $this->newContext( $request, $language, $performer );
$output = new OutputPage( $context );
$context->setOutput( $output );
$page->setContext( $context );
$output->setTitle( $page->getPageTitle() );
$html = $this->getHTMLFromSpecialPage( $page, $subPage, $fullHtml );
$response = $context->getRequest()->response();
if ( $response instanceof FauxResponse ) {
$code = $response->getStatusCode();
if ( $code > 0 ) {
$response->header( 'Status: ' . $code . ' ' . HttpStatus::getMessage( $code ) );
}
}
return [ $html, $response ];
}
/**
* @param WebRequest|null $request
* @param Language|string|null $language Defaults to 'qqx'
* @param Authority|null $performer
*
* @return DerivativeContext
*/
private function newContext(
?WebRequest $request = null,
$language = null,
?Authority $performer = null
) {
$context = new DerivativeContext( RequestContext::getMain() );
$context->setRequest( $request ?: new FauxRequest() );
$context->setLanguage( $language ?: 'qqx' );
if ( $performer !== null ) {
$context->setAuthority( $performer );
}
$this->setEditTokenFromUser( $context );
// Make sure the skin context is correctly set https://phabricator.wikimedia.org/T200771
$context->getSkin()->setContext( $context );
return $context;
}
/**
* If we are trying to edit and no token is set, supply one.
*
* @param DerivativeContext $context
*/
private function setEditTokenFromUser( DerivativeContext $context ) {
$request = $context->getRequest();
// Edits via GET are a security issue and should not succeed. On the other hand, not all
// POST requests are edits, but should ignore unused parameters.
if ( !$request->getCheck( 'wpEditToken' ) && $request->wasPosted() ) {
$request->setVal( 'wpEditToken', $context->getUser()->getEditToken() );
}
}
/**
* @param SpecialPage $page
* @param string|null $subPage
* @param bool $fullHtml
*
* @return string HTML
*/
private function getHTMLFromSpecialPage( SpecialPage $page, $subPage, $fullHtml ) {
ob_start();
try {
$page->execute( $subPage );
$output = $page->getOutput();
if ( $output->getRedirect() !== '' ) {
$output->output();
$html = ob_get_contents();
} elseif ( $output->isDisabled() ) {
$html = ob_get_contents();
} elseif ( $fullHtml ) {
$html = $output->output( true );
} else {
$html = $output->getHTML();
}
} finally {
ob_end_clean();
}
return $html;
}
}
|