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