32 private $mRootElemName =
'api';
33 public static $namespace =
'http://www.mediawiki.org/xml/api/';
34 private $mIncludeNamespace =
false;
35 private $mXslt =
null;
42 $this->mRootElemName = $rootElemName;
47 $this->mIncludeNamespace = $params[
'includexmlnamespace'];
48 $this->mXslt = $params[
'xslt'];
50 $this->
printText(
'<?xml version="1.0"?>' );
51 if ( $this->mXslt !==
null ) {
56 if ( $this->mIncludeNamespace && $result->getResultData(
'xmlns' ) ===
null ) {
63 $data = $result->getResultData(
null, [
64 'Custom' =>
static function ( &$data, &$metadata ) {
74 'BC' => [
'nobool',
'no*',
'nosub' ],
75 'Types' => [
'ArmorKVP' =>
'_name' ],
79 static::recXmlPrint( $this->mRootElemName,
95 public static function recXmlPrint( $name, $value, $indent, $attributes = [] ) {
97 if ( $indent !==
null ) {
98 if ( $name !==
null ) {
101 $indstr =
"\n" . str_repeat(
' ', $indent );
106 if ( is_object( $value ) ) {
107 $value = (array)$value;
109 if ( is_array( $value ) ) {
113 $subelementKeys = array_merge(
127 $indexedSubelements = [];
128 foreach ( $value as $k => $v ) {
134 if ( is_bool( $v ) && !in_array( $k, $bcBools,
true ) ) {
135 $v = $v ?
'true' :
'false';
138 if ( $name !==
null && $k === $contentKey ) {
140 } elseif ( is_int( $k ) ) {
141 $indexedSubelements[$k] = $v;
142 } elseif ( is_array( $v ) || is_object( $v ) ) {
143 $subelements[self::mangleName( $k, $preserveKeys )] = $v;
144 } elseif ( in_array( $k, $subelementKeys,
true ) || $name ===
null ) {
145 $subelements[self::mangleName( $k, $preserveKeys )] = [
150 } elseif ( is_bool( $oldv ) ) {
152 $attributes[self::mangleName( $k, $preserveKeys )] =
'';
154 } elseif ( $v !==
null ) {
155 $attributes[self::mangleName( $k, $preserveKeys )] = $v;
160 if ( $subelements || $indexedSubelements ) {
161 $subelements[self::mangleName( $contentKey, $preserveKeys )] = [
167 } elseif ( is_scalar(
$content ) ) {
170 $attributes += [
'xml:space' =>
'preserve' ];
179 if ( $name !==
null ) {
180 $retval .= $indstr .
Xml::element( $name, $attributes,
null );
182 $retval .= static::recXmlPrint(
null,
$content, $indent );
183 if ( $name !==
null ) {
187 } elseif ( !$indexedSubelements && !$subelements ) {
188 if ( $name !==
null ) {
189 $retval .= $indstr .
Xml::element( $name, $attributes );
192 if ( $name !==
null ) {
193 $retval .= $indstr .
Xml::element( $name, $attributes,
null );
195 foreach ( $subelements as $k => $v ) {
196 $retval .= static::recXmlPrint( $k, $v, $indent );
198 foreach ( $indexedSubelements as $k => $v ) {
199 $retval .= static::recXmlPrint( $indexedTagName, $v, $indent,
200 $indexSubelements ? [
'_idx' => $k ] : []
203 if ( $name !==
null ) {
210 if ( $value ===
null ) {
212 $retval .= $indstr .
Xml::element( $name, $attributes );
215 $retval .= $indstr .
Xml::element( $name, $attributes, $value );
228 private static function mangleName( $name, $preserveKeys = [] ) {
229 static $nsc =
null, $nc =
null;
231 if ( in_array( $name, $preserveKeys,
true ) ) {
235 if ( $name ===
'' ) {
239 if ( $nsc ===
null ) {
243 $nsc =
'A-Za-z\x{C0}-\x{D6}\x{D8}-\x{F6}\x{F8}-\x{2FF}\x{370}-\x{37D}\x{37F}-\x{1FFF}' .
244 '\x{200C}-\x{200D}\x{2070}-\x{218F}\x{2C00}-\x{2FEF}\x{3001}-\x{D7FF}' .
245 '\x{F900}-\x{FDCF}\x{FDF0}-\x{FFFD}\x{10000}-\x{EFFFF}';
246 $nc = $nsc .
'_\-.0-9\x{B7}\x{300}-\x{36F}\x{203F}-\x{2040}';
249 if ( preg_match(
"/^[$nsc][$nc]*$/uS", $name ) ) {
253 return '_' . preg_replace_callback(
255 static function ( $m ) {
256 return sprintf(
'.%X.', UtfNormal\Utils::utf8ToCodepoint( $m[0] ) );
258 str_replace(
'.',
'.2E.', $name )
263 $nt = Title::newFromText( $this->mXslt );
264 if ( $nt ===
null || !$nt->exists() ) {
265 $this->
addWarning(
'apiwarn-invalidxmlstylesheet' );
270 $this->
addWarning(
'apiwarn-invalidxmlstylesheetns' );
274 if ( !str_ends_with( $nt->getText(),
'.xsl' ) ) {
275 $this->
addWarning(
'apiwarn-invalidxmlstylesheetext' );
279 $this->
printText(
'<?xml-stylesheet href="' .
280 htmlspecialchars( $nt->getLocalURL(
'action=raw' ) ) .
'" type="text/xsl" ?>' );
284 return parent::getAllowedParams() + [
288 'includexmlnamespace' => [
289 ParamValidator::PARAM_DEFAULT =>
false,
getResult()
Get the result object.
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
const PARAM_HELP_MSG
(string|array|Message) Specify an alternative i18n documentation message for this parameter.
addWarning( $msg, $code=null, $data=null)
Add a warning for this module.
const META_TYPE
Key for the 'type' metadata item.
const META_SUBELEMENTS
Key for the 'subelements' metadata item.
const META_BC_BOOLS
Key for the 'BC bools' metadata item.
const META_PRESERVE_KEYS
Key for the 'preserve keys' metadata item.
const NO_SIZE_CHECK
For addValue() and similar functions, do not check size while adding a value Don't use this unless yo...
const META_CONTENT
Key for the 'content' metadata item.
const META_BC_SUBELEMENTS
Key for the 'BC subelements' metadata item.
const META_INDEXED_TAG_NAME
Key for the 'indexed tag name' metadata item.
static isMetadataKey( $key)
Test whether a key should be considered metadata.
static closeElement( $element)
Shortcut to close an XML element.
static element( $element, $attribs=null, $contents='', $allowShortTag=true)
Format an XML element with given attributes and, optionally, text content.