From 03a84977e96ed9635d448555478d20fa77fb1b0d Mon Sep 17 00:00:00 2001 From: Ad Schellevis Date: Tue, 7 Apr 2020 20:44:03 +0200 Subject: [PATCH] collect_api_endpoints.py: extend script with support for abstract classes, add used model when using standard templates. needed to better explain documentation for https://github.com/opnsense/plugins/issues/1749 --- collect_api_endpoints.in | 9 ++++++-- collect_api_endpoints.py | 44 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/collect_api_endpoints.in b/collect_api_endpoints.in index f60d3f26..fc13bd55 100644 --- a/collect_api_endpoints.in +++ b/collect_api_endpoints.in @@ -4,7 +4,12 @@ .. csv-table:: {{controller.type}} ({{controller.filename}}) :header: "Method", "Module", "Controller", "Command", "Parameters" :widths: 4, 15, 15, 30, 40 -{% for endpoint in controller.endpoints %} +{% for endpoint in controller.endpoints %} "``{{endpoint.method}}``","{{endpoint.module}}","{{endpoint.controller}}","{{endpoint.command}}","{{endpoint.parameters}}" -{%- endfor %} +{%- endfor %} +{%- if controller.uses %} +{% for use in controller.uses %} + "``<>``", "", "", "", "*{{use.type}}* `{{use.name}} <{{use.link}}>`__" +{%- endfor %} +{%- endif %} {% endfor %} diff --git a/collect_api_endpoints.py b/collect_api_endpoints.py index a8435c36..edc3ceef 100755 --- a/collect_api_endpoints.py +++ b/collect_api_endpoints.py @@ -38,6 +38,21 @@ def parse_api_php(src_filename): module_name = src_filename.replace('\\', '/').split('/')[-3].lower() data = open(src_filename).read() + m = re.findall(r"\n([\w]*).*class.*Controller.*extends\s([\w|\\]*)", data) + base_class = m[0][1].split('\\')[-1] if len(m) > 0 else None + is_abstract = len(m) > 0 and m[0][0] == 'abstract' + + m = re.findall(r"\sprotected\sstatic\s\$internalModelClass\s=\s['|\"]([\w|\\]*)['|\"];", data) + if len(m) == 0: + m = re.findall(r"\sprotected\sstatic\s\$internalServiceClass\s=\s['|\"]([\w|\\]*)['|\"];", data) + + model_filename = None + if len(m) > 0: + app_location = "/".join(src_filename.split('/')[:-5]) + model_xml = "%s/models/%s.xml" % (app_location, m[0].replace("\\", "/")) + if os.path.isfile(model_xml): + model_filename = model_xml.replace('//', '/') + function_callouts = re.findall(r"(\n\s+(private|public|protected)\s+function\s+(\w+)\((.*)\))", data) result = list() for idx, function in enumerate(function_callouts): @@ -52,11 +67,19 @@ def parse_api_php(src_filename): 'method': 'GET', 'module': module_name, 'controller': controller, + 'is_abstract': is_abstract, + 'base_class': base_class, 'command': function[2][:-6], 'parameters': function[3].replace(' ', ''), - 'type': 'Service' if controller.find('service') > -1 else 'Resources', - 'filename': base_filename + 'filename': base_filename, + 'model_filename': model_filename } + if is_abstract: + record['type'] = 'Abstract [non-callable]' + elif controller.find('service') > -1: + record['type'] = 'Service' + else: + record['type'] = 'Resources' # find most likely method (default => GET) if code_block.find('request->isPost(') > -1: record['method'] = 'POST' @@ -74,6 +97,12 @@ def parse_api_php(src_filename): return sorted(result, key=lambda i: i['command']) +def source_url(repo, src_filename): + parts = src_filename.split('/') + if repo == 'plugins': + return "https://github.com/opnsense/plugins/blob/master/%s" % "/".join(parts[parts.index('src') - 2:]) + else: + return "https://github.com/opnsense/core/blob/master/%s" % "/".join(parts[parts.index('src') - 2:]) if __name__ == '__main__': parser = argparse.ArgumentParser() @@ -114,10 +143,19 @@ if __name__ == '__main__': payload = { 'type': controller[0]['type'], 'filename': controller[0]['filename'], - 'endpoints': [] + 'is_abstract': controller[0]['is_abstract'], + 'base_class': controller[0]['base_class'], + 'endpoints': [], + 'uses': [] } for endpoint in controller: payload['endpoints'].append(endpoint) + if controller[0]['model_filename']: + payload['uses'].append({ + 'type': 'model', + 'link': source_url(cmd_args.repo, controller[0]['model_filename']), + 'name': os.path.basename(controller[0]['model_filename']) + }) template_data['controllers'].append(payload) with open(target_filename, 'w') as f_out: