public function execute() { $params = $this->extractRequestParams(); $modules = array(); foreach ($params['modules'] as $path) { $modules[] = $this->getModuleFromPath($path); } // Get the help $context = new DerivativeContext($this->getMain()->getContext()); $context->setSkin(SkinFactory::getDefaultInstance()->makeSkin('apioutput')); $context->setLanguage($this->getMain()->getLanguage()); $context->setTitle(SpecialPage::getTitleFor('ApiHelp')); $out = new OutputPage($context); $out->setCopyrightUrl('https://www.mediawiki.org/wiki/Special:MyLanguage/Copyright'); $context->setOutput($out); self::getHelp($context, $modules, $params); // Grab the output from the skin ob_start(); $context->getOutput()->output(); $html = ob_get_clean(); $result = $this->getResult(); if ($params['wrap']) { $data = array('mime' => 'text/html', 'help' => $html); ApiResult::setSubelementsList($data, 'help'); $result->addValue(null, $this->getModuleName(), $data); } else { $result->reset(); $result->addValue(null, 'text', $html, ApiResult::NO_SIZE_CHECK); $result->addValue(null, 'mime', 'text/html', ApiResult::NO_SIZE_CHECK); } }
/** * Formats the internal list of exposed APIs into an array suitable * to pass to the API's XML formatter. * * @return array */ protected function formatRsdApiList() { $apis = $this->getRsdApiList(); $outputData = array(); foreach ($apis as $name => $info) { $data = array('name' => $name, 'preferred' => wfBoolToStr($name == 'MediaWiki'), 'apiLink' => $info['apiLink'], 'blogID' => isset($info['blogID']) ? $info['blogID'] : ''); $settings = array(); if (isset($info['docs'])) { $settings['docs'] = $info['docs']; ApiResult::setSubelementsList($settings, 'docs'); } if (isset($info['settings'])) { foreach ($info['settings'] as $setting => $val) { if (is_bool($val)) { $xmlVal = wfBoolToStr($val); } else { $xmlVal = $val; } $setting = array('name' => $setting); ApiResult::setContentValue($setting, 'value', $xmlVal); $settings[] = $setting; } } if (count($settings)) { ApiResult::setIndexedTagName($settings, 'setting'); $data['settings'] = $settings; } $outputData[] = $data; } return $outputData; }
public function execute() { // Cache may vary on $wgUser because ParserOptions gets data from it $this->getMain()->setCacheMode('anon-public-user-private'); // Get parameters $params = $this->extractRequestParams(); $this->requireMaxOneParameter($params, 'prop', 'generatexml'); if ($params['prop'] === null) { $this->logFeatureUsage('action=expandtemplates&!prop'); $this->setWarning('Because no values have been specified for the prop parameter, a ' . 'legacy format has been used for the output. This format is deprecated, and in ' . 'the future, a default value will be set for the prop parameter, causing the new' . 'format to always be used.'); $prop = array(); } else { $prop = array_flip($params['prop']); } // Get title and revision ID for parser $revid = $params['revid']; if ($revid !== null) { $rev = Revision::newFromId($revid); if (!$rev) { $this->dieUsage("There is no revision ID {$revid}", 'missingrev'); } $title_obj = $rev->getTitle(); } else { $title_obj = Title::newFromText($params['title']); if (!$title_obj || $title_obj->isExternal()) { $this->dieUsageMsg(array('invalidtitle', $params['title'])); } } $result = $this->getResult(); // Parse text global $wgParser; $options = ParserOptions::newFromContext($this->getContext()); if ($params['includecomments']) { $options->setRemoveComments(false); } $retval = array(); if (isset($prop['parsetree']) || $params['generatexml']) { if (!isset($prop['parsetree'])) { $this->logFeatureUsage('action=expandtemplates&generatexml'); } $wgParser->startExternalParse($title_obj, $options, Parser::OT_PREPROCESS); $dom = $wgParser->preprocessToDom($params['text']); if (is_callable(array($dom, 'saveXML'))) { $xml = $dom->saveXML(); } else { $xml = $dom->__toString(); } if (isset($prop['parsetree'])) { unset($prop['parsetree']); $retval['parsetree'] = $xml; } else { // the old way $result->addValue(null, 'parsetree', $xml); $result->addValue(null, ApiResult::META_BC_SUBELEMENTS, array('parsetree')); } } // if they didn't want any output except (probably) the parse tree, // then don't bother actually fully expanding it if ($prop || $params['prop'] === null) { $wgParser->startExternalParse($title_obj, $options, Parser::OT_PREPROCESS); $frame = $wgParser->getPreprocessor()->newFrame(); $wikitext = $wgParser->preprocess($params['text'], $title_obj, $options, $revid, $frame); if ($params['prop'] === null) { // the old way ApiResult::setContentValue($retval, 'wikitext', $wikitext); } else { if (isset($prop['categories'])) { $categories = $wgParser->getOutput()->getCategories(); if ($categories) { $categories_result = array(); foreach ($categories as $category => $sortkey) { $entry = array(); $entry['sortkey'] = $sortkey; ApiResult::setContentValue($entry, 'category', $category); $categories_result[] = $entry; } ApiResult::setIndexedTagName($categories_result, 'category'); $retval['categories'] = $categories_result; } } if (isset($prop['properties'])) { $properties = $wgParser->getOutput()->getProperties(); if ($properties) { ApiResult::setArrayType($properties, 'BCkvp', 'name'); ApiResult::setIndexedTagName($properties, 'property'); $retval['properties'] = $properties; } } if (isset($prop['volatile'])) { $retval['volatile'] = $frame->isVolatile(); } if (isset($prop['ttl']) && $frame->getTTL() !== null) { $retval['ttl'] = $frame->getTTL(); } if (isset($prop['wikitext'])) { $retval['wikitext'] = $wikitext; } } } ApiResult::setSubelementsList($retval, array('wikitext', 'parsetree')); $result->addValue(null, $this->getModuleName(), $retval); }
/** * @covers ApiResult */ public function testMetadata() { $arr = array('foo' => array('bar' => array())); $result = new ApiResult(8388608); $result->addValue(null, 'foo', array('bar' => array())); $expect = array('foo' => array('bar' => array(ApiResult::META_INDEXED_TAG_NAME => 'ritn', ApiResult::META_TYPE => 'default'), ApiResult::META_INDEXED_TAG_NAME => 'ritn', ApiResult::META_TYPE => 'default'), ApiResult::META_SUBELEMENTS => array('foo', 'bar'), ApiResult::META_INDEXED_TAG_NAME => 'itn', ApiResult::META_PRESERVE_KEYS => array('foo', 'bar'), ApiResult::META_TYPE => 'array'); ApiResult::setSubelementsList($arr, 'foo'); ApiResult::setSubelementsList($arr, array('bar', 'baz')); ApiResult::unsetSubelementsList($arr, 'baz'); ApiResult::setIndexedTagNameRecursive($arr, 'ritn'); ApiResult::setIndexedTagName($arr, 'itn'); ApiResult::setPreserveKeysList($arr, 'foo'); ApiResult::setPreserveKeysList($arr, array('bar', 'baz')); ApiResult::unsetPreserveKeysList($arr, 'baz'); ApiResult::setArrayTypeRecursive($arr, 'default'); ApiResult::setArrayType($arr, 'array'); $this->assertSame($expect, $arr); $result->addSubelementsList(null, 'foo'); $result->addSubelementsList(null, array('bar', 'baz')); $result->removeSubelementsList(null, 'baz'); $result->addIndexedTagNameRecursive(null, 'ritn'); $result->addIndexedTagName(null, 'itn'); $result->addPreserveKeysList(null, 'foo'); $result->addPreserveKeysList(null, array('bar', 'baz')); $result->removePreserveKeysList(null, 'baz'); $result->addArrayTypeRecursive(null, 'default'); $result->addArrayType(null, 'array'); $this->assertEquals($expect, $result->getResultData()); $arr = array('foo' => array('bar' => array())); $expect = array('foo' => array('bar' => array(ApiResult::META_TYPE => 'kvp', ApiResult::META_KVP_KEY_NAME => 'key'), ApiResult::META_TYPE => 'kvp', ApiResult::META_KVP_KEY_NAME => 'key'), ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'bc'); ApiResult::setArrayTypeRecursive($arr, 'kvp', 'key'); ApiResult::setArrayType($arr, 'BCkvp', 'bc'); $this->assertSame($expect, $arr); }
/** * @param ApiBase $module * @return ApiResult */ private function getModuleInfo($module) { $ret = []; $path = $module->getModulePath(); $ret['name'] = $module->getModuleName(); $ret['classname'] = get_class($module); $ret['path'] = $path; if (!$module->isMain()) { $ret['group'] = $module->getParent()->getModuleManager()->getModuleGroup($module->getModuleName()); } $ret['prefix'] = $module->getModulePrefix(); $sourceInfo = $module->getModuleSourceInfo(); if ($sourceInfo) { $ret['source'] = $sourceInfo['name']; if (isset($sourceInfo['namemsg'])) { $ret['sourcename'] = $this->context->msg($sourceInfo['namemsg'])->text(); } else { $ret['sourcename'] = $ret['source']; } $link = SpecialPage::getTitleFor('Version', 'License/' . $sourceInfo['name'])->getFullURL(); if (isset($sourceInfo['license-name'])) { $ret['licensetag'] = $sourceInfo['license-name']; $ret['licenselink'] = (string) $link; } elseif (SpecialVersion::getExtLicenseFileName(dirname($sourceInfo['path']))) { $ret['licenselink'] = (string) $link; } } $this->formatHelpMessages($ret, 'description', $module->getFinalDescription()); foreach ($module->getHelpFlags() as $flag) { $ret[$flag] = true; } $ret['helpurls'] = (array) $module->getHelpUrls(); if (isset($ret['helpurls'][0]) && $ret['helpurls'][0] === false) { $ret['helpurls'] = []; } ApiResult::setIndexedTagName($ret['helpurls'], 'helpurl'); if ($this->helpFormat !== 'none') { $ret['examples'] = []; $examples = $module->getExamplesMessages(); foreach ($examples as $qs => $msg) { $item = ['query' => $qs]; $msg = ApiBase::makeMessage($msg, $this->context, [$module->getModulePrefix(), $module->getModuleName(), $module->getModulePath()]); $this->formatHelpMessages($item, 'description', [$msg]); if (isset($item['description'])) { if (is_array($item['description'])) { $item['description'] = $item['description'][0]; } else { ApiResult::setSubelementsList($item, 'description'); } } $ret['examples'][] = $item; } ApiResult::setIndexedTagName($ret['examples'], 'example'); } $ret['parameters'] = []; $params = $module->getFinalParams(ApiBase::GET_VALUES_FOR_HELP); $paramDesc = $module->getFinalParamDescription(); foreach ($params as $name => $settings) { if (!is_array($settings)) { $settings = [ApiBase::PARAM_DFLT => $settings]; } $item = ['name' => $name]; if (isset($paramDesc[$name])) { $this->formatHelpMessages($item, 'description', $paramDesc[$name], true); } $item['required'] = !empty($settings[ApiBase::PARAM_REQUIRED]); if (!empty($settings[ApiBase::PARAM_DEPRECATED])) { $item['deprecated'] = true; } if ($name === 'token' && $module->needsToken()) { $item['tokentype'] = $module->needsToken(); } if (!isset($settings[ApiBase::PARAM_TYPE])) { $dflt = isset($settings[ApiBase::PARAM_DFLT]) ? $settings[ApiBase::PARAM_DFLT] : null; if (is_bool($dflt)) { $settings[ApiBase::PARAM_TYPE] = 'boolean'; } elseif (is_string($dflt) || is_null($dflt)) { $settings[ApiBase::PARAM_TYPE] = 'string'; } elseif (is_int($dflt)) { $settings[ApiBase::PARAM_TYPE] = 'integer'; } } if (isset($settings[ApiBase::PARAM_DFLT])) { switch ($settings[ApiBase::PARAM_TYPE]) { case 'boolean': $item['default'] = (bool) $settings[ApiBase::PARAM_DFLT]; break; case 'string': case 'text': case 'password': $item['default'] = strval($settings[ApiBase::PARAM_DFLT]); break; case 'integer': case 'limit': $item['default'] = intval($settings[ApiBase::PARAM_DFLT]); break; case 'timestamp': $item['default'] = wfTimestamp(TS_ISO_8601, $settings[ApiBase::PARAM_DFLT]); break; default: $item['default'] = $settings[ApiBase::PARAM_DFLT]; break; } } $item['multi'] = !empty($settings[ApiBase::PARAM_ISMULTI]); if ($item['multi']) { $item['limit'] = $this->getMain()->canApiHighLimits() ? ApiBase::LIMIT_SML2 : ApiBase::LIMIT_SML1; $item['lowlimit'] = ApiBase::LIMIT_SML1; $item['highlimit'] = ApiBase::LIMIT_SML2; } if (!empty($settings[ApiBase::PARAM_ALLOW_DUPLICATES])) { $item['allowsduplicates'] = true; } if (isset($settings[ApiBase::PARAM_TYPE])) { if ($settings[ApiBase::PARAM_TYPE] === 'submodule') { if (isset($settings[ApiBase::PARAM_SUBMODULE_MAP])) { ksort($settings[ApiBase::PARAM_SUBMODULE_MAP]); $item['type'] = array_keys($settings[ApiBase::PARAM_SUBMODULE_MAP]); $item['submodules'] = $settings[ApiBase::PARAM_SUBMODULE_MAP]; } else { $item['type'] = $module->getModuleManager()->getNames($name); sort($item['type']); $prefix = $module->isMain() ? '' : $module->getModulePath() . '+'; $item['submodules'] = []; foreach ($item['type'] as $v) { $item['submodules'][$v] = $prefix . $v; } } if (isset($settings[ApiBase::PARAM_SUBMODULE_PARAM_PREFIX])) { $item['submoduleparamprefix'] = $settings[ApiBase::PARAM_SUBMODULE_PARAM_PREFIX]; } } elseif ($settings[ApiBase::PARAM_TYPE] === 'tags') { $item['type'] = ChangeTags::listExplicitlyDefinedTags(); } else { $item['type'] = $settings[ApiBase::PARAM_TYPE]; } if (is_array($item['type'])) { // To prevent sparse arrays from being serialized to JSON as objects $item['type'] = array_values($item['type']); ApiResult::setIndexedTagName($item['type'], 't'); } } if (isset($settings[ApiBase::PARAM_MAX])) { $item['max'] = $settings[ApiBase::PARAM_MAX]; } if (isset($settings[ApiBase::PARAM_MAX2])) { $item['highmax'] = $settings[ApiBase::PARAM_MAX2]; } if (isset($settings[ApiBase::PARAM_MIN])) { $item['min'] = $settings[ApiBase::PARAM_MIN]; } if (!empty($settings[ApiBase::PARAM_RANGE_ENFORCE])) { $item['enforcerange'] = true; } if (!empty($settings[ApiBase::PARAM_HELP_MSG_INFO])) { $item['info'] = []; foreach ($settings[ApiBase::PARAM_HELP_MSG_INFO] as $i) { $tag = array_shift($i); $info = ['name' => $tag]; if (count($i)) { $info['values'] = $i; ApiResult::setIndexedTagName($info['values'], 'v'); } $this->formatHelpMessages($info, 'text', [$this->context->msg("apihelp-{$path}-paraminfo-{$tag}")->numParams(count($i))->params($this->context->getLanguage()->commaList($i))->params($module->getModulePrefix())]); ApiResult::setSubelementsList($info, 'text'); $item['info'][] = $info; } ApiResult::setIndexedTagName($item['info'], 'i'); } $ret['parameters'][] = $item; } ApiResult::setIndexedTagName($ret['parameters'], 'param'); $dynamicParams = $module->dynamicParameterDocumentation(); if ($dynamicParams !== null) { if ($this->helpFormat === 'none') { $ret['dynamicparameters'] = true; } else { $dynamicParams = ApiBase::makeMessage($dynamicParams, $this->context, [$module->getModulePrefix(), $module->getModuleName(), $module->getModulePath()]); $this->formatHelpMessages($ret, 'dynamicparameters', [$dynamicParams]); } } return $ret; }
/** * @param string $search * @param array &$results */ protected function populateResult($search, &$results) { $result = $this->getResult(); switch ($this->getFormat()) { case 'json': // http://www.opensearch.org/Specifications/OpenSearch/Extensions/Suggestions/1.1 $result->addArrayType(null, 'array'); $result->addValue(null, 0, strval($search)); $terms = []; $descriptions = []; $urls = []; foreach ($results as $r) { $terms[] = $r['title']->getPrefixedText(); $descriptions[] = strval($r['extract']); $urls[] = $r['url']; } $result->addValue(null, 1, $terms); $result->addValue(null, 2, $descriptions); $result->addValue(null, 3, $urls); break; case 'xml': // http://msdn.microsoft.com/en-us/library/cc891508%28v=vs.85%29.aspx $imageKeys = ['source' => true, 'alt' => true, 'width' => true, 'height' => true, 'align' => true]; $items = []; foreach ($results as $r) { $item = ['Text' => $r['title']->getPrefixedText(), 'Url' => $r['url']]; if (is_string($r['extract']) && $r['extract'] !== '') { $item['Description'] = $r['extract']; } if (is_array($r['image']) && isset($r['image']['source'])) { $item['Image'] = array_intersect_key($r['image'], $imageKeys); } ApiResult::setSubelementsList($item, array_keys($item)); $items[] = $item; } ApiResult::setIndexedTagName($items, 'Item'); $result->addValue(null, 'version', '2.0'); $result->addValue(null, 'xmlns', 'http://opensearch.org/searchsuggest2'); $result->addValue(null, 'Query', strval($search)); $result->addSubelementsList(null, 'Query'); $result->addValue(null, 'Section', $items); break; default: ApiBase::dieDebug(__METHOD__, "Unsupported format '{$this->getFormat()}'"); } }
/** * @param ApiBase $module * @return ApiResult */ private function getModuleInfo($module) { $result = $this->getResult(); $ret = array(); $path = $module->getModulePath(); $ret['name'] = $module->getModuleName(); $ret['classname'] = get_class($module); $ret['path'] = $path; if (!$module->isMain()) { $ret['group'] = $module->getParent()->getModuleManager()->getModuleGroup($module->getModuleName()); } $ret['prefix'] = $module->getModulePrefix(); $this->formatHelpMessages($ret, 'description', $module->getFinalDescription()); foreach ($module->getHelpFlags() as $flag) { $ret[$flag] = true; } $ret['helpurls'] = (array) $module->getHelpUrls(); if (isset($ret['helpurls'][0]) && $ret['helpurls'][0] === false) { $ret['helpurls'] = array(); } ApiResult::setIndexedTagName($ret['helpurls'], 'helpurl'); if ($this->helpFormat !== 'none') { $ret['examples'] = array(); $examples = $module->getExamplesMessages(); foreach ($examples as $qs => $msg) { $item = array('query' => $qs); $msg = ApiBase::makeMessage($msg, $this->context, array($module->getModulePrefix(), $module->getModuleName(), $module->getModulePath())); $this->formatHelpMessages($item, 'description', array($msg)); if (isset($item['description'])) { if (is_array($item['description'])) { $item['description'] = $item['description'][0]; } else { ApiResult::setSubelementsList($item, 'description'); } } $ret['examples'][] = $item; } ApiResult::setIndexedTagName($ret['examples'], 'example'); } $ret['parameters'] = array(); $params = $module->getFinalParams(ApiBase::GET_VALUES_FOR_HELP); $paramDesc = $module->getFinalParamDescription(); foreach ($params as $name => $settings) { if (!is_array($settings)) { $settings = array(ApiBase::PARAM_DFLT => $settings); } $item = array('name' => $name); if (isset($paramDesc[$name])) { $this->formatHelpMessages($item, 'description', $paramDesc[$name], true); } $item['required'] = !empty($settings[ApiBase::PARAM_REQUIRED]); if (!empty($settings[ApiBase::PARAM_DEPRECATED])) { $item['deprecated'] = true; } if ($name === 'token' && $module->needsToken()) { $item['tokentype'] = $module->needsToken(); } if (!isset($settings[ApiBase::PARAM_TYPE])) { $dflt = isset($settings[ApiBase::PARAM_DFLT]) ? $settings[ApiBase::PARAM_DFLT] : null; if (is_bool($dflt)) { $settings[ApiBase::PARAM_TYPE] = 'boolean'; } elseif (is_string($dflt) || is_null($dflt)) { $settings[ApiBase::PARAM_TYPE] = 'string'; } elseif (is_int($dflt)) { $settings[ApiBase::PARAM_TYPE] = 'integer'; } } if (isset($settings[ApiBase::PARAM_DFLT])) { switch ($settings[ApiBase::PARAM_TYPE]) { case 'boolean': $item['default'] = $settings[ApiBase::PARAM_DFLT] ? 'true' : 'false'; break; case 'string': $item['default'] = strval($settings[ApiBase::PARAM_DFLT]); break; case 'integer': $item['default'] = intval($settings[ApiBase::PARAM_DFLT]); break; default: $item['default'] = $settings[ApiBase::PARAM_DFLT]; break; } } $item['multi'] = !empty($settings[ApiBase::PARAM_ISMULTI]); if ($item['multi']) { $item['limit'] = $this->getMain()->canApiHighLimits() ? ApiBase::LIMIT_SML2 : ApiBase::LIMIT_SML1; $item['lowlimit'] = ApiBase::LIMIT_SML1; $item['highlimit'] = ApiBase::LIMIT_SML2; } if (!empty($settings[ApiBase::PARAM_ALLOW_DUPLICATES])) { $item['allowsduplicates'] = true; } if (isset($settings[ApiBase::PARAM_TYPE])) { if ($settings[ApiBase::PARAM_TYPE] === 'submodule') { $item['type'] = $module->getModuleManager()->getNames($name); sort($item['type']); $item['submodules'] = true; } else { $item['type'] = $settings[ApiBase::PARAM_TYPE]; } if (is_array($item['type'])) { // To prevent sparse arrays from being serialized to JSON as objects $item['type'] = array_values($item['type']); ApiResult::setIndexedTagName($item['type'], 't'); } } if (isset($settings[ApiBase::PARAM_MAX])) { $item['max'] = $settings[ApiBase::PARAM_MAX]; } if (isset($settings[ApiBase::PARAM_MAX2])) { $item['highmax'] = $settings[ApiBase::PARAM_MAX2]; } if (isset($settings[ApiBase::PARAM_MIN])) { $item['min'] = $settings[ApiBase::PARAM_MIN]; } if (!empty($settings[ApiBase::PARAM_HELP_MSG_INFO])) { $item['info'] = array(); foreach ($settings[ApiBase::PARAM_HELP_MSG_INFO] as $i) { $tag = array_shift($i); $info = array('name' => $tag); if (count($i)) { $info['values'] = $i; ApiResult::setIndexedTagName($info['values'], 'v'); } $this->formatHelpMessages($info, 'text', array($this->context->msg("apihelp-{$path}-paraminfo-{$tag}")->numParams(count($i))->params($this->context->getLanguage()->commaList($i))->params($module->getModulePrefix()))); ApiResult::setSubelementsList($info, 'text'); $item['info'][] = $info; } ApiResult::setIndexedTagName($item['info'], 'i'); } $ret['parameters'][] = $item; } ApiResult::setIndexedTagName($ret['parameters'], 'param'); return $ret; }