aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/inc/Extension/RemotePlugin.php
blob: fd67110443e97f3fcf64ecafeb9a573948157c0b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<?php

namespace dokuwiki\Extension;

use dokuwiki\Remote\Api;
use ReflectionException;
use ReflectionMethod;

/**
 * Remote Plugin prototype
 *
 * Add functionality to the remote API in a plugin
 */
abstract class RemotePlugin extends Plugin
{

    private Api $api;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->api = new Api();
    }

    /**
     * Get all available methods with remote access.
     *
     * By default it exports all public methods of a remote plugin. Methods beginning
     * with an underscore are skipped.
     *
     * @return array Information about all provided methods. {@see dokuwiki\Remote\RemoteAPI}.
     * @throws ReflectionException
     */
    public function _getMethods()
    {
        $result = [];

        $reflection = new \ReflectionClass($this);
        foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
            // skip parent methods, only methods further down are exported
            $declaredin = $method->getDeclaringClass()->name;
            if ($declaredin === 'dokuwiki\Extension\Plugin' || $declaredin === 'dokuwiki\Extension\RemotePlugin') {
                continue;
            }
            $method_name = $method->name;
            if (strpos($method_name, '_') === 0) {
                continue;
            }

            // strip asterisks
            $doc = $method->getDocComment();
            $doc = preg_replace(
                ['/^[ \t]*\/\*+[ \t]*/m', '/[ \t]*\*+[ \t]*/m', '/\*+\/\s*$/m', '/\s*\/\s*$/m'],
                ['', '', '', ''],
                $doc
            );

            // prepare data
            $data = [];
            $data['name'] = $method_name;
            $data['public'] = 0;
            $data['doc'] = $doc;
            $data['args'] = [];

            // get parameter type from doc block type hint
            foreach ($method->getParameters() as $parameter) {
                $name = $parameter->name;
                $type = 'string'; // we default to string
                if (preg_match('/^@param[ \t]+([\w|\[\]]+)[ \t]\$' . $name . '/m', $doc, $m)) {
                    $type = $this->cleanTypeHint($m[1]);
                }
                $data['args'][] = $type;
            }

            // get return type from doc block type hint
            if (preg_match('/^@return[ \t]+([\w|\[\]]+)/m', $doc, $m)) {
                $data['return'] = $this->cleanTypeHint($m[1]);
            } else {
                $data['return'] = 'string';
            }

            // add to result
            $result[$method_name] = $data;
        }

        return $result;
    }

    /**
     * Matches the given type hint against the valid options for the remote API
     *
     * @param string $hint
     * @return string
     */
    protected function cleanTypeHint($hint)
    {
        $types = explode('|', $hint);
        foreach ($types as $t) {
            if (substr($t, -2) === '[]') {
                return 'array';
            }
            if ($t === 'boolean') {
                return 'bool';
            }
            if (in_array($t, ['array', 'string', 'int', 'double', 'bool', 'null', 'date', 'file'])) {
                return $t;
            }
        }
        return 'string';
    }

    /**
     * @return Api
     */
    protected function getApi()
    {
        return $this->api;
    }

}