public function detailed_description_html($params) {
        // retrieve the description of the description object
        $paramdesc = "";
        if (!empty($params->desc)) {
            $paramdesc .= html_writer::start_tag('span', array('style' => "color:#2A33A6"));
            if ($params->required == VALUE_REQUIRED) {
                $required = '';
            }
            if ($params->required == VALUE_DEFAULT) {
                if ($params->default === null) {
                    $params->default = "null";
                }
                $required = html_writer::start_tag('b', array()) .
                        get_string('default', 'webservice', print_r($params->default, true))
                        . html_writer::end_tag('b');
            }
            if ($params->required == VALUE_OPTIONAL) {
                $required = html_writer::start_tag('b', array()) .
                        get_string('optional', 'webservice') . html_writer::end_tag('b');
            }
            $paramdesc .= " " . $required . " ";
            $paramdesc .= html_writer::start_tag('i', array());
            $paramdesc .= "//";

            $paramdesc .= s($params->desc);

            $paramdesc .= html_writer::end_tag('i');

            $paramdesc .= html_writer::end_tag('span');
            $paramdesc .= html_writer::empty_tag('br', array());
        }

        // description object is a list
        if ($params instanceof external_multiple_structure) {
            return $paramdesc . "list of ( " . html_writer::empty_tag('br', array())
            . $this->detailed_description_html($params->content) . ")";
        } else if ($params instanceof external_single_structure) {
            // description object is an object
            $singlestructuredesc = $paramdesc . "object {" . html_writer::empty_tag('br', array());
            foreach ($params->keys as $attributname => $attribut) {
                $singlestructuredesc .= html_writer::start_tag('b', array());
                $singlestructuredesc .= $attributname;
                $singlestructuredesc .= html_writer::end_tag('b');
                $singlestructuredesc .= " " .
                        $this->detailed_description_html($params->keys[$attributname]);
            }
            $singlestructuredesc .= "} ";
            $singlestructuredesc .= html_writer::empty_tag('br', array());
            return $singlestructuredesc;
        } else {
            // description object is a primary type (string, integer)
            switch ($params->type) {
                case PARAM_BOOL: // 0 or 1 only for now
                case PARAM_INT:
                    $type = 'int';
                    break;
                case PARAM_FLOAT;
                    $type = 'double';
                    break;
                default:
                    $type = 'string';
            }
            return $type . " " . $paramdesc;
        }
    }
public function detailed_description_html($params) {
        // retrieve the description of the description object
        $paramdesc = "";
        if (!empty($params->desc)) {
            $paramdesc .= html_writer::start_tag('span', array('style' => "color:#2A33A6"));
            if ($params->required == VALUE_REQUIRED) {
                $required = '';
            }
            if ($params->required == VALUE_DEFAULT) {
                if ($params->default === null) {
                    $params->default = "null";
                }
                $required = html_writer::start_tag('b', array()) .
                        get_string('default', 'webservice', print_r($params->default, true))
                        . html_writer::end_tag('b');
            }
            if ($params->required == VALUE_OPTIONAL) {
                $required = html_writer::start_tag('b', array()) .
                        get_string('optional', 'webservice') . html_writer::end_tag('b');
            }
            $paramdesc .= " " . $required . " ";
            $paramdesc .= html_writer::start_tag('i', array());
            $paramdesc .= "//";

            $paramdesc .= s($params->desc);

            $paramdesc .= html_writer::end_tag('i');

            $paramdesc .= html_writer::end_tag('span');
            $paramdesc .= html_writer::empty_tag('br', array());
        }

        // description object is a list
        if ($params instanceof external_multiple_structure) {
            return $paramdesc . "list of ( " . html_writer::empty_tag('br', array())
            . $this->detailed_description_html($params->content) . ")";
        } else if ($params instanceof external_single_structure) {
            // description object is an object
            $singlestructuredesc = $paramdesc . "object {" . html_writer::empty_tag('br', array());
            foreach ($params->keys as $attributname => $attribut) {
                $singlestructuredesc .= html_writer::start_tag('b', array());
                $singlestructuredesc .= $attributname;
                $singlestructuredesc .= html_writer::end_tag('b');
                $singlestructuredesc .= " " .
                        $this->detailed_description_html($params->keys[$attributname]);
            }
            $singlestructuredesc .= "} ";
            $singlestructuredesc .= html_writer::empty_tag('br', array());
            return $singlestructuredesc;
        } else {
            // description object is a primary type (string, integer)
            switch ($params->type) {
                case PARAM_BOOL: // 0 or 1 only for now
                case PARAM_INT:
                    $type = 'int';
                    break;
                case PARAM_FLOAT;
                    $type = 'double';
                    break;
                default:
                    $type = 'string';
            }
            return $type . " " . $paramdesc;
        }
    }
public function detailed_description_html ( $ params ) { // retrieve the description of the description object $ paramdesc = "" ; if ( ! empty ( $ params -> desc ) ) { $ paramdesc .= html_writer :: start_tag ( 'span' , array ( 'style' => "color:#2A33A6" ) ) ; if ( $ params -> required == VALUE_REQUIRED ) { $ required = '' ; } if ( $ params -> required == VALUE_DEFAULT ) { if ( $ params -> default === null ) { $ params -> default = "null" ; } $ required = html_writer :: start_tag ( 'b' , array ( ) ) . get_string ( 'default' , 'webservice' , print_r ( $ params -> default , true ) ) . html_writer :: end_tag ( 'b' ) ; } if ( $ params -> required == VALUE_OPTIONAL ) { $ required = html_writer :: start_tag ( 'b' , array ( ) ) . get_string ( 'optional' , 'webservice' ) . html_writer :: end_tag ( 'b' ) ; } $ paramdesc .= " " . $ required . " " ; $ paramdesc .= html_writer :: start_tag ( 'i' , array ( ) ) ; $ paramdesc .= "//" ; $ paramdesc .= s ( $ params -> desc ) ; $ paramdesc .= html_writer :: end_tag ( 'i' ) ; $ paramdesc .= html_writer :: end_tag ( 'span' ) ; $ paramdesc .= html_writer :: empty_tag ( 'br' , array ( ) ) ; } // description object is a list if ( $ params instanceof external_multiple_structure ) { return $ paramdesc . "list of ( " . html_writer :: empty_tag ( 'br' , array ( ) ) . $ this -> detailed_description_html ( $ params -> content ) . ")" ; } else if ( $ params instanceof external_single_structure ) { // description object is an object $ singlestructuredesc = $ paramdesc . "object {" . html_writer :: empty_tag ( 'br' , array ( ) ) ; foreach ( $ params -> keys as $ attributname => $ attribut ) { $ singlestructuredesc .= html_writer :: start_tag ( 'b' , array ( ) ) ; $ singlestructuredesc .= $ attributname ; $ singlestructuredesc .= html_writer :: end_tag ( 'b' ) ; $ singlestructuredesc .= " " . $ this -> detailed_description_html ( $ params -> keys [ $ attributname ] ) ; } $ singlestructuredesc .= "} " ; $ singlestructuredesc .= html_writer :: empty_tag ( 'br' , array ( ) ) ; return $ singlestructuredesc ; } else { // description object is a primary type (string, integer) switch ( $ params -> type ) { case PARAM_BOOL : // 0 or 1 only for now case PARAM_INT : $ type = 'int' ; break ; case PARAM_FLOAT ; $ type = 'double' ; break ; default : $ type = 'string' ; } return $ type . " " . $ paramdesc ; } }
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 core_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 stdClass $params a part of parameter/return description
@return string the html to display
Return documentation for a ws description object ws description object can be external_multiple_structure external_single_structure or external_value