ApiExpandTemplates::execute()   F
last analyzed

Complexity

Conditions 29
Paths > 20000

Size

Total Lines 137
Code Lines 95

Duplication

Lines 22
Ratio 16.06 %

Importance

Changes 0
Metric Value
cc 29
eloc 95
nc 92320
nop 0
dl 22
loc 137
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 *
4
 *
5
 * Created on Oct 05, 2007
6
 *
7
 * Copyright © 2007 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 2 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License along
20
 * with this program; if not, write to the Free Software Foundation, Inc.,
21
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22
 * http://www.gnu.org/copyleft/gpl.html
23
 *
24
 * @file
25
 */
26
27
/**
28
 * API module that functions as a shortcut to the wikitext preprocessor. Expands
29
 * any templates in a provided string, and returns the result of this expansion
30
 * to the caller.
31
 *
32
 * @ingroup API
33
 */
34
class ApiExpandTemplates extends ApiBase {
35
36
	public function execute() {
37
		// Cache may vary on the user because ParserOptions gets data from it
38
		$this->getMain()->setCacheMode( 'anon-public-user-private' );
39
40
		// Get parameters
41
		$params = $this->extractRequestParams();
42
		$this->requireMaxOneParameter( $params, 'prop', 'generatexml' );
43
44
		if ( $params['prop'] === null ) {
45
			$this->logFeatureUsage( 'action=expandtemplates&!prop' );
46
			$this->setWarning( 'Because no values have been specified for the prop parameter, a ' .
47
				'legacy format has been used for the output. This format is deprecated, and in ' .
48
				'the future, a default value will be set for the prop parameter, causing the new' .
49
				'format to always be used.' );
50
			$prop = [];
51
		} else {
52
			$prop = array_flip( $params['prop'] );
53
		}
54
55
		// Get title and revision ID for parser
56
		$revid = $params['revid'];
57
		if ( $revid !== null ) {
58
			$rev = Revision::newFromId( $revid );
59
			if ( !$rev ) {
60
				$this->dieUsage( "There is no revision ID $revid", 'missingrev' );
61
			}
62
			$title_obj = $rev->getTitle();
63
		} else {
64
			$title_obj = Title::newFromText( $params['title'] );
65
			if ( !$title_obj || $title_obj->isExternal() ) {
66
				$this->dieUsageMsg( [ 'invalidtitle', $params['title'] ] );
67
			}
68
		}
69
70
		$result = $this->getResult();
71
72
		// Parse text
73
		global $wgParser;
74
		$options = ParserOptions::newFromContext( $this->getContext() );
75
76
		if ( $params['includecomments'] ) {
77
			$options->setRemoveComments( false );
78
		}
79
80
		$reset = null;
81
		$suppressCache = false;
82
		Hooks::run( 'ApiMakeParserOptions',
83
			[ $options, $title_obj, $params, $this, &$reset, &$suppressCache ] );
84
85
		$retval = [];
86
87
		if ( isset( $prop['parsetree'] ) || $params['generatexml'] ) {
88
			$wgParser->startExternalParse( $title_obj, $options, Parser::OT_PREPROCESS );
89
			$dom = $wgParser->preprocessToDom( $params['text'] );
90 View Code Duplication
			if ( is_callable( [ $dom, 'saveXML' ] ) ) {
91
				$xml = $dom->saveXML();
92
			} else {
93
				$xml = $dom->__toString();
94
			}
95
			if ( isset( $prop['parsetree'] ) ) {
96
				unset( $prop['parsetree'] );
97
				$retval['parsetree'] = $xml;
98
			} else {
99
				// the old way
100
				$result->addValue( null, 'parsetree', $xml );
101
				$result->addValue( null, ApiResult::META_BC_SUBELEMENTS, [ 'parsetree' ] );
102
			}
103
		}
104
105
		// if they didn't want any output except (probably) the parse tree,
106
		// then don't bother actually fully expanding it
107
		if ( $prop || $params['prop'] === null ) {
108
			$wgParser->startExternalParse( $title_obj, $options, Parser::OT_PREPROCESS );
109
			$frame = $wgParser->getPreprocessor()->newFrame();
110
			$wikitext = $wgParser->preprocess( $params['text'], $title_obj, $options, $revid, $frame );
111
			if ( $params['prop'] === null ) {
112
				// the old way
113
				ApiResult::setContentValue( $retval, 'wikitext', $wikitext );
114
			} else {
115
				$p_output = $wgParser->getOutput();
116
				if ( isset( $prop['categories'] ) ) {
117
					$categories = $p_output->getCategories();
118
					if ( $categories ) {
119
						$categories_result = [];
120
						foreach ( $categories as $category => $sortkey ) {
121
							$entry = [];
122
							$entry['sortkey'] = $sortkey;
123
							ApiResult::setContentValue( $entry, 'category', (string)$category );
124
							$categories_result[] = $entry;
125
						}
126
						ApiResult::setIndexedTagName( $categories_result, 'category' );
127
						$retval['categories'] = $categories_result;
128
					}
129
				}
130
				if ( isset( $prop['properties'] ) ) {
131
					$properties = $p_output->getProperties();
132
					if ( $properties ) {
133
						ApiResult::setArrayType( $properties, 'BCkvp', 'name' );
134
						ApiResult::setIndexedTagName( $properties, 'property' );
135
						$retval['properties'] = $properties;
136
					}
137
				}
138
				if ( isset( $prop['volatile'] ) ) {
139
					$retval['volatile'] = $frame->isVolatile();
140
				}
141
				if ( isset( $prop['ttl'] ) && $frame->getTTL() !== null ) {
142
					$retval['ttl'] = $frame->getTTL();
143
				}
144
				if ( isset( $prop['wikitext'] ) ) {
145
					$retval['wikitext'] = $wikitext;
146
				}
147 View Code Duplication
				if ( isset( $prop['modules'] ) ) {
148
					$retval['modules'] = array_values( array_unique( $p_output->getModules() ) );
149
					$retval['modulescripts'] = array_values( array_unique( $p_output->getModuleScripts() ) );
150
					$retval['modulestyles'] = array_values( array_unique( $p_output->getModuleStyles() ) );
151
				}
152
				if ( isset( $prop['jsconfigvars'] ) ) {
153
					$retval['jsconfigvars'] =
154
						ApiResult::addMetadataToResultVars( $p_output->getJsConfigVars() );
155
				}
156 View Code Duplication
				if ( isset( $prop['encodedjsconfigvars'] ) ) {
157
					$retval['encodedjsconfigvars'] = FormatJson::encode(
158
						$p_output->getJsConfigVars(), false, FormatJson::ALL_OK
159
					);
160
					$retval[ApiResult::META_SUBELEMENTS][] = 'encodedjsconfigvars';
161
				}
162 View Code Duplication
				if ( isset( $prop['modules'] ) &&
163
					!isset( $prop['jsconfigvars'] ) && !isset( $prop['encodedjsconfigvars'] ) ) {
164
					$this->setWarning( "Property 'modules' was set but not 'jsconfigvars' " .
165
						"or 'encodedjsconfigvars'. Configuration variables are necessary " .
166
						'for proper module usage.' );
167
				}
168
			}
169
		}
170
		ApiResult::setSubelementsList( $retval, [ 'wikitext', 'parsetree' ] );
171
		$result->addValue( null, $this->getModuleName(), $retval );
172
	}
173
174
	public function getAllowedParams() {
175
		return [
176
			'title' => [
177
				ApiBase::PARAM_DFLT => 'API',
178
			],
179
			'text' => [
180
				ApiBase::PARAM_TYPE => 'text',
181
				ApiBase::PARAM_REQUIRED => true,
182
			],
183
			'revid' => [
184
				ApiBase::PARAM_TYPE => 'integer',
185
			],
186
			'prop' => [
187
				ApiBase::PARAM_TYPE => [
188
					'wikitext',
189
					'categories',
190
					'properties',
191
					'volatile',
192
					'ttl',
193
					'modules',
194
					'jsconfigvars',
195
					'encodedjsconfigvars',
196
					'parsetree',
197
				],
198
				ApiBase::PARAM_ISMULTI => true,
199
				ApiBase::PARAM_HELP_MSG_PER_VALUE => [],
200
			],
201
			'includecomments' => false,
202
			'generatexml' => [
203
				ApiBase::PARAM_TYPE => 'boolean',
204
				ApiBase::PARAM_DEPRECATED => true,
205
			],
206
		];
207
	}
208
209
	protected function getExamplesMessages() {
210
		return [
211
			'action=expandtemplates&text={{Project:Sandbox}}'
212
				=> 'apihelp-expandtemplates-example-simple',
213
		];
214
	}
215
216
	public function getHelpUrls() {
217
		return 'https://www.mediawiki.org/wiki/API:Parsing_wikitext#expandtemplates';
218
	}
219
}
220