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