Commit 6d8b81f4 authored by Aaron Wells's avatar Aaron Wells Committed by Robert Lyon
Browse files

Bug 1620879: Improve formatting of WS function descriptions

behatnotneeded

Change-Id: Idea08ba7827d939af6f2fc8ec6be30774f2af5cb
parent 9efa71f6
......@@ -256,7 +256,7 @@ $string['context'] = 'Context';
$string['createtoken'] = 'Create token';
$string['createtokenforuser'] = 'Create a token for a user';
$string['createuser'] = 'Create a specific user';
$string['default'] = 'Default to "%s"';
$string['default'] = 'Default %s';
$string['deleteservice'] = 'Delete the service: {$a->name} (id: {$a->id})';
$string['doc'] = 'Documentation';
$string['documentation'] = 'web services documentation';
......@@ -292,6 +292,7 @@ $string['invalidtimedtoken'] = 'Invalid token: Token expired';
$string['invalidtoken'] = 'Invalid token: Token not found';
$string['invalidtokensession'] = 'Invalid session based token: Session not found or expired';
$string['iprestriction'] = 'IP restriction';
$string['list'] = 'list of';
$string['key'] = 'Key';
$string['missingpassword'] = 'Missing password';
$string['missingusername'] = 'Missing username';
......
......@@ -3,7 +3,7 @@
{/if}
<h2>{str tag="function" section="auth.webservice"}: {$function->name} </h2>
<table>
<table class="table table-striped">
<tr><td>{str tag="wsdocdescription" section="auth.webservice"}:</td><td>{$functiondescription}</td></tr>
<tr><td>{str tag="component" section="auth.webservice"}:</td><td>{$function->component}</td></tr>
<tr><td>{str tag="class" section="auth.webservice"}:</td><td>{$function->classname}</td></tr>
......@@ -13,20 +13,14 @@
<span class='arguments'>{str tag="arguments" section="auth.webservice"}</span>
<br/>
{foreach from=$fdesc->parameters_desc->keys item=paramdesc key=paramname}
<span style='font-size: 80%'>
<b>{$paramname}</b> ({if $paramdesc->required == 1 }{str tag="required" section="auth.webservice"}{else}{if $paramdesc->required == 2}{str tag="optional" section="auth.webservice"}{else}{if ($paramdesc->default === null)} null {else} {$paramdesc->default}{/if}{/if}{/if})
<br/>
{$paramdesc->desc}
<br/>
<div>
<div class="detaildescription">
<pre class='detaildescription'><b>{str tag="generalstructure" section="auth.webservice"}</b>
{wsdoc_detailed_description_html($paramdesc)}
<pre class='detaildescription'>
{foreach from=$fdesc->parameters_desc->keys item=paramdesc key=paramname}
<span class="wsname">{$paramname}:</span> {wsdoc_detailed_description_html($paramdesc, 1)}
{/foreach}
</pre>
</div>
</div>
{foreach from=$fdesc->parameters_desc->keys item=paramdesc key=paramname}
{if $xmlrpcactive == 1 }
<br/>
<div>
......@@ -48,7 +42,7 @@
</div>
{/if}
</span>
{/foreach}
{/foreach}
<br/>
<br/>
......
......@@ -257,3 +257,24 @@ label.lead {
.licenseicon {
padding: 0 10px 5px 0;
}
pre {
span.wsname {
font-weight: bold;
}
span.wsdescription {
color: #2A33A6;
padding-right: 10px;
.wsrequired {
font-weight: bold;
color: $brand-danger;
}
.wsoptional {
font-weight: bold;
}
.wsdescriptiontext {
font-style: italic;
}
}
}
\ No newline at end of file
......@@ -13,16 +13,37 @@ define('INTERNAL', 1);
define('MENUITEM', 'configextensions/pluginadminwebservices');
define('SECTION_PAGE', 'webservice');
require(dirname(dirname(__FILE__)) . '/init.php');
define('TITLE', get_string('pluginadmin', 'admin'));
require_once(get_config('docroot') . 'webservice/lib.php');
$function = param_integer('id', 0);
// The characters to use for indenting
define('WSDOC_INDENT_SPACE', '&nbsp;&nbsp;&nbsp;&nbsp;');
$functionname = param_alphanumext('functionname', '');
$functionid = param_integer('id', 0);
$dialog = param_integer('dialog', 0);
$dbfunction = get_record('external_functions', 'id', $function);
if ($functionid) {
// We've retained the id-based URL because it's used so many places. But it's
// a lot more readable (i.e. in URL completions) to use the name-based URL,
// so let's redirect to that.
$functionname = get_field('external_functions', 'name', 'id', $functionid);
if ($functionname) {
$redirect = '/webservice/wsdoc.php?functionname=' . $functionname;
if ($dialog) {
$redirect .= '&dialog=1';
}
redirect($redirect);
}
}
else if ($functionname) {
$dbfunction = get_record('external_functions', 'name', $functionname);
}
if (empty($dbfunction)) {
$SESSION->add_error_msg(get_string('invalidfunction', 'auth.webservice'));
redirect('/webservice/admin/index.php');
}
define('TITLE', get_string('function', 'auth.webservice') . ': ' . $dbfunction->name);
$fdesc = webservice_function_info($dbfunction->name);
$smarty = smarty(array(), array('<link rel="stylesheet" type="text/css" href="' . $THEME->get_url('style/webservice.css', false, 'auth/webservice') . '">',));
......@@ -34,93 +55,169 @@ $smarty->assign('fdesc', $fdesc);
$smarty->assign('xmlrpcactive', webservice_protocol_is_enabled('xmlrpc'));
$smarty->assign('restactive', webservice_protocol_is_enabled('rest'));
$smarty->assign('soapactive', webservice_protocol_is_enabled('soap'));
$heading = get_string('wsdoc', 'auth.webservice');
$smarty->assign('PAGEHEADING', $heading);
$smarty->assign('PAGEHEADING', get_string('wsdoc', 'auth.webservice'));
$smarty->assign('dialog', $dialog);
$smarty->display('auth:webservice:wsdoc.tpl');
die;
/**
* Return documentation for a ws description object
* ws description object can be 'external_multiple_structure', 'external_single_structure'
* or 'external_value'
* Example of documentation for moodle_group_create_groups function:
list of (
object {
courseid int //id of course
name string //multilang compatible name, course unique
description string //group description text
enrolmentkey string //group enrol secret phrase
}
)
* @param object $params a part of parameter/return description
* Recursively generates an HTML-formatted description of a webservice external_description
* object (i.e. webservice function parameters and return structures).
* The output includes some HTML tags for syntax highlighting, so it should
* not be htmlescaped.
*
* Example of documentation for module_mobileapi_get_notifications response structure
*
* object {
* synctime: int Current timestamp on server
* numnotifications: int Total number of unread notifications available
* notifications:
* list of (
* object {
* id: int notification record id
* subject: string Notification's subject line
* message: string Notification's body
* }
* )
* }
* @param object $params A part of parameter/return description
* @param integer $indentlevel The current level of indentation
* @return string the html to display
*/
function wsdoc_detailed_description_html($params) {
/// retrieve the description of the description object
$paramdesc = "";
if (!empty($params->desc)) {
$paramdesc .= '<span style="color:#2A33A6">';
if ($params->required == VALUE_REQUIRED) {
$required = '';
}
if ($params->required == VALUE_DEFAULT) {
if ($params->default === null) {
$params->default = "null";
}
$required = '<b>' .
get_string('default', 'auth.webservice', $params->default)
. '</b>';
}
if ($params->required == VALUE_OPTIONAL) {
$required = '<b>' .
get_string('optional', 'auth.webservice') . '</b>';
}
$paramdesc .= " " . $required . " ";
$paramdesc .= '<i>';
$paramdesc .= "//";
function wsdoc_detailed_description_html($params, $indentlevel = 0) {
$nlsame = '</br>' . str_repeat(WSDOC_INDENT_SPACE, $indentlevel);
$nlright = '</br>' . str_repeat(WSDOC_INDENT_SPACE, $indentlevel + 1);
$comment = '';
if (!empty($params->desc) || isset($params->required)) {
$comment .= '<span class="wsdescription">';
if (isset($params->required)) {
switch ($params->required) {
$paramdesc .= $params->desc;
case VALUE_DEFAULT:
if ($params->default === null) {
$params->default = "(null)";
}
else if (is_string($params->default)) {
$params->default = '"' . $params->default . '"';
}
else if (is_bool($params->default)) {
$params->default = $params->default ? "(true)" : "(false)";
}
else if (!is_scalar($params->default)) {
$params->default = '&lt;' . gettype($params->default) . '&gt;';
}
$required = '<span class="wsrequired">' . get_string('required', 'auth.webservice') . '</span> ' .
'<span class="wsoptional">' . get_string('default', 'auth.webservice', $params->default) . '</span> ';
break;
$paramdesc .= '</i>';
case VALUE_OPTIONAL:
$required = '<span class="wsoptional">' .
get_string('optional', 'auth.webservice')
. '</span> ';
break;
$paramdesc .= '</span>';
$paramdesc .= '<br/>';
// Don't need to print anything for a required param
case VALUE_REQUIRED:
default:
$required = '';
}
$comment .= $required;
}
// If we have a default and a desc, put a space between them
if (isset($params->required) && !empty($params->desc)) {
$comment .= ' ';
}
// Print the description for the param
if (!empty($params->desc)) {
$comment .= "<span class='wsdescriptiontext'>{$params->desc}</span>";
}
$comment .= '</span>';
}
/// description object is a list
if ($params instanceof external_multiple_structure) {
return $paramdesc . "list of ( " . '<br/>'
. ' ' . wsdoc_detailed_description_html($params->content) . ")";
return $comment
. $nlsame
// HACK: Normally a lang string like this should be parameterized
// "list of (%)". But in this case the stuff in the parens could be huge,
// and spaces are important for formatting. So just concatenating.
. get_string('list', 'auth.webservice') . ' ('
. ($params->content instanceof external_value ? $nlright : '')
. wsdoc_detailed_description_html($params->content, $indentlevel + 1)
. $nlsame
. ')';
}
/// description object is an object
else if ($params instanceof external_single_structure) {
/// description object is an object
$singlestructuredesc = $paramdesc . "object {" . '<br/>';
foreach ($params->keys as $attributname => $attribut) {
$singlestructuredesc .= '<b>';
$singlestructuredesc .= $attributname;
$singlestructuredesc .= '</b>';
$singlestructuredesc .= " " .
wsdoc_detailed_description_html($params->keys[$attributname]);
// Print comments (after attribute printed by parent)
// Then go down one line, indent, print "object {"
// Then down another line, indent again, and print each attribute one
// per line.
$returnstr =
$comment
. $nlsame
. 'object {';
if ($params->keys) {
foreach ($params->keys as $attributename => $attribute) {
$returnstr .=
$nlright
. "<span class='wsname'>$attributename:</span> ";
$i = $indentlevel + 1;
if (!$attribute instanceof external_value) {
$i++;
}
$returnstr .= wsdoc_detailed_description_html($attribute, $i);
}
$returnstr .= $nlsame;
}
$singlestructuredesc .= "} ";
$singlestructuredesc .= '<br/>';
return $singlestructuredesc;
$returnstr .= '}';
return $returnstr;
}
/// description object is a primary type (string, integer)
else {
/// description object is a primary type (string, integer)
switch ($params->type) {
case PARAM_BOOL:
$type = 'bool';
break;
case PARAM_INT:
case PARAM_INTEGER:
$type = 'int';
break;
case PARAM_FLOAT;
case PARAM_FLOAT:
case PARAM_NUMBER:
$type = 'double';
break;
default:
case PARAM_RAW:
case PARAM_RAW_TRIMMED:
case PARAM_TEXT:
$type = 'string';
break;
case PARAM_ALPHA:
case PARAM_ALPHAEXT:
case PARAM_ALPHANUM:
case PARAM_ALPHANUMEXT:
case PARAM_BASE64:
case PARAM_CLEANHTML:
case PARAM_CLEAN:
case PARAM_EMAIL:
case PARAM_FILE:
case PARAM_HOST:
case PARAM_LOCALURL:
case PARAM_NOTAGS:
case PARAM_PATH:
case PARAM_PEM:
case PARAM_RAW_TRIMMED:
case PARAM_SAFEDIR:
case PARAM_SAFEPATH:
case PARAM_SAFEPATH:
case PARAM_URL:
case PARAM_STRINGID:
default:
// String with additional filters/restrictions
$type = "string ({$params->type})";
}
return $type . " " . $paramdesc;
return $type . ($comment ? ' ' : '') . $comment;
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment