MediaWiki 1.41.2
ApiExpandTemplates.php
Go to the documentation of this file.
1<?php
26
35 private RevisionStore $revisionStore;
36 private ParserFactory $parserFactory;
37
44 public function __construct(
45 ApiMain $main,
46 $action,
47 RevisionStore $revisionStore,
48 ParserFactory $parserFactory
49 ) {
50 parent::__construct( $main, $action );
51 $this->revisionStore = $revisionStore;
52 $this->parserFactory = $parserFactory;
53 }
54
55 public function execute() {
56 // Cache may vary on the user because ParserOptions gets data from it
57 $this->getMain()->setCacheMode( 'anon-public-user-private' );
58
59 // Get parameters
60 $params = $this->extractRequestParams();
61 $this->requireMaxOneParameter( $params, 'prop', 'generatexml' );
62
63 $title = $params['title'];
64 if ( $title === null ) {
65 $titleProvided = false;
66 // A title is needed for parsing, so arbitrarily choose one
67 $title = 'API';
68 } else {
69 $titleProvided = true;
70 }
71
72 if ( $params['prop'] === null ) {
73 $this->addDeprecation(
74 [ 'apiwarn-deprecation-missingparam', 'prop' ], 'action=expandtemplates&!prop'
75 );
76 $prop = [];
77 } else {
78 $prop = array_fill_keys( $params['prop'], true );
79 }
80
81 $titleObj = Title::newFromText( $title );
82 if ( !$titleObj || $titleObj->isExternal() ) {
83 $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['title'] ) ] );
84 }
85
86 // Get title and revision ID for parser
87 $revid = $params['revid'];
88 if ( $revid !== null ) {
89 $rev = $this->revisionStore->getRevisionById( $revid );
90 if ( !$rev ) {
91 $this->dieWithError( [ 'apierror-nosuchrevid', $revid ] );
92 }
93 $pTitleObj = $titleObj;
94 $titleObj = Title::newFromLinkTarget( $rev->getPageAsLinkTarget() );
95 if ( $titleProvided && !$titleObj->equals( $pTitleObj ) ) {
96 $this->addWarning( [ 'apierror-revwrongpage', $rev->getId(),
97 wfEscapeWikiText( $pTitleObj->getPrefixedText() ) ] );
98 }
99 }
100
101 $result = $this->getResult();
102
103 // Parse text
104 $options = ParserOptions::newFromContext( $this->getContext() );
105
106 if ( $params['includecomments'] ) {
107 $options->setRemoveComments( false );
108 }
109
110 $reset = null;
111 $suppressCache = false;
112 $this->getHookRunner()->onApiMakeParserOptions(
113 $options, $titleObj, $params, $this, $reset, $suppressCache );
114
115 $retval = [];
116
117 if ( isset( $prop['parsetree'] ) || $params['generatexml'] ) {
118 $parser = $this->parserFactory->getInstance();
119 $parser->startExternalParse( $titleObj, $options, Parser::OT_PREPROCESS );
120 $dom = $parser->preprocessToDom( $params['text'] );
121 // @phan-suppress-next-line PhanUndeclaredMethodInCallable
122 if ( is_callable( [ $dom, 'saveXML' ] ) ) {
123 // @phan-suppress-next-line PhanUndeclaredMethod
124 $xml = $dom->saveXML();
125 } else {
126 // @phan-suppress-next-line PhanUndeclaredMethod
127 $xml = $dom->__toString();
128 }
129 if ( isset( $prop['parsetree'] ) ) {
130 unset( $prop['parsetree'] );
131 $retval['parsetree'] = $xml;
132 } else {
133 // the old way
134 $result->addValue( null, 'parsetree', $xml );
135 $result->addValue( null, ApiResult::META_BC_SUBELEMENTS, [ 'parsetree' ] );
136 }
137 }
138
139 // if they didn't want any output except (probably) the parse tree,
140 // then don't bother actually fully expanding it
141 if ( $prop || $params['prop'] === null ) {
142 $parser = $this->parserFactory->getInstance();
143 $parser->startExternalParse( $titleObj, $options, Parser::OT_PREPROCESS );
144 $frame = $parser->getPreprocessor()->newFrame();
145 $wikitext = $parser->preprocess( $params['text'], $titleObj, $options, $revid, $frame );
146 if ( $params['prop'] === null ) {
147 // the old way
148 ApiResult::setContentValue( $retval, 'wikitext', $wikitext );
149 } else {
150 $p_output = $parser->getOutput();
151 if ( isset( $prop['categories'] ) ) {
152 $categories = $p_output->getCategoryNames();
153 if ( $categories ) {
154 $categories_result = [];
155 foreach ( $categories as $category ) {
156 $entry = [
157 'sortkey' => $p_output->getCategorySortKey( $category ),
158 ];
159 ApiResult::setContentValue( $entry, 'category', $category );
160 $categories_result[] = $entry;
161 }
162 ApiResult::setIndexedTagName( $categories_result, 'category' );
163 $retval['categories'] = $categories_result;
164 }
165 }
166 if ( isset( $prop['properties'] ) ) {
167 $properties = $p_output->getPageProperties();
168 if ( $properties ) {
169 ApiResult::setArrayType( $properties, 'BCkvp', 'name' );
170 ApiResult::setIndexedTagName( $properties, 'property' );
171 $retval['properties'] = $properties;
172 }
173 }
174 if ( isset( $prop['volatile'] ) ) {
175 $retval['volatile'] = $frame->isVolatile();
176 }
177 if ( isset( $prop['ttl'] ) && $frame->getTTL() !== null ) {
178 $retval['ttl'] = $frame->getTTL();
179 }
180 if ( isset( $prop['wikitext'] ) ) {
181 $retval['wikitext'] = $wikitext;
182 }
183 if ( isset( $prop['modules'] ) ) {
184 $retval['modules'] = array_values( array_unique( $p_output->getModules() ) );
185 // Deprecated since 1.32 (T188689)
186 $retval['modulescripts'] = [];
187 $retval['modulestyles'] = array_values( array_unique( $p_output->getModuleStyles() ) );
188 }
189 if ( isset( $prop['jsconfigvars'] ) ) {
190 $showStrategyKeys = (bool)( $params['showstrategykeys'] );
191 $retval['jsconfigvars'] =
192 ApiResult::addMetadataToResultVars( $p_output->getJsConfigVars( $showStrategyKeys ) );
193 }
194 if ( isset( $prop['encodedjsconfigvars'] ) ) {
195 $retval['encodedjsconfigvars'] = FormatJson::encode(
196 $p_output->getJsConfigVars(), false, FormatJson::ALL_OK
197 );
198 $retval[ApiResult::META_SUBELEMENTS][] = 'encodedjsconfigvars';
199 }
200 if ( isset( $prop['modules'] ) &&
201 !isset( $prop['jsconfigvars'] ) && !isset( $prop['encodedjsconfigvars'] ) ) {
202 $this->addWarning( 'apiwarn-moduleswithoutvars' );
203 }
204 }
205 }
206 ApiResult::setSubelementsList( $retval, [ 'wikitext', 'parsetree' ] );
207 $result->addValue( null, $this->getModuleName(), $retval );
208 }
209
210 public function getAllowedParams() {
211 return [
212 'title' => null,
213 'text' => [
214 ParamValidator::PARAM_TYPE => 'text',
215 ParamValidator::PARAM_REQUIRED => true,
216 ],
217 'revid' => [
218 ParamValidator::PARAM_TYPE => 'integer',
219 ],
220 'prop' => [
221 ParamValidator::PARAM_TYPE => [
222 'wikitext',
223 'categories',
224 'properties',
225 'volatile',
226 'ttl',
227 'modules',
228 'jsconfigvars',
229 'encodedjsconfigvars',
230 'parsetree',
231 ],
232 ParamValidator::PARAM_ISMULTI => true,
234 ],
235 'includecomments' => false,
236 'showstrategykeys' => false,
237 'generatexml' => [
238 ParamValidator::PARAM_TYPE => 'boolean',
239 ParamValidator::PARAM_DEPRECATED => true,
240 ],
241 ];
242 }
243
244 protected function getExamplesMessages() {
245 return [
246 'action=expandtemplates&text={{Project:Sandbox}}'
247 => 'apihelp-expandtemplates-example-simple',
248 ];
249 }
250
251 public function getHelpUrls() {
252 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Expandtemplates';
253 }
254}
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
This abstract class implements many basic API functions, and is the base of all API classes.
Definition ApiBase.php:62
dieWithError( $msg, $code=null, $data=null, $httpCode=0)
Abort execution with an error.
Definition ApiBase.php:1515
getMain()
Get the main module.
Definition ApiBase.php:546
const PARAM_HELP_MSG_PER_VALUE
((string|array|Message)[]) When PARAM_TYPE is an array, or 'string' with PARAM_ISMULTI,...
Definition ApiBase.php:209
addDeprecation( $msg, $feature, $data=[])
Add a deprecation warning for this module.
Definition ApiBase.php:1447
requireMaxOneParameter( $params,... $required)
Dies if more than one parameter from a certain set of parameters are set and not false.
Definition ApiBase.php:981
getResult()
Get the result object.
Definition ApiBase.php:667
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition ApiBase.php:807
addWarning( $msg, $code=null, $data=null)
Add a warning for this module.
Definition ApiBase.php:1433
getModuleName()
Get the name of the module being executed by this instance.
Definition ApiBase.php:528
getHookRunner()
Get an ApiHookRunner for running core API hooks.
Definition ApiBase.php:752
API module that functions as a shortcut to the wikitext preprocessor.
getExamplesMessages()
Returns usage examples for this module.
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
__construct(ApiMain $main, $action, RevisionStore $revisionStore, ParserFactory $parserFactory)
getHelpUrls()
Return links to more detailed help pages about the module.
This is the main API class, used for both external and internal processing.
Definition ApiMain.php:64
getContext()
Get the base IContextSource object.
Service for looking up page revisions.
Represents a title within MediaWiki.
Definition Title.php:76
const OT_PREPROCESS
Output type: like Parser::preprocess()
Definition Parser.php:156
Service for formatting and validating API parameters.