xref: /dokuwiki/inc/Extension/RemotePlugin.php (revision 8cbc5ee84fe788597ede5266255a74af6da47555)
1<?php
2
3namespace dokuwiki\Extension;
4
5use dokuwiki\Remote\Api;
6use ReflectionException;
7use ReflectionMethod;
8
9/**
10 * Remote Plugin prototype
11 *
12 * Add functionality to the remote API in a plugin
13 */
14abstract class RemotePlugin extends Plugin
15{
16
17    private $api;
18
19    /**
20     * Constructor
21     */
22    public function __construct()
23    {
24        $this->api = new Api();
25    }
26
27    /**
28     * Get all available methods with remote access.
29     *
30     * By default it exports all public methods of a remote plugin. Methods beginning
31     * with an underscore are skipped.
32     *
33     * @return array Information about all provided methods. {@see dokuwiki\Remote\RemoteAPI}.
34     * @throws ReflectionException
35     */
36    public function _getMethods()
37    {
38        $result = array();
39
40        $reflection = new \ReflectionClass($this);
41        foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
42            // skip parent methods, only methods further down are exported
43            $declaredin = $method->getDeclaringClass()->name;
44            if ($declaredin == 'dokuwiki\Extension\Plugin' || $declaredin == 'dokuwiki\Extension\RemotePlugin') continue;
45            $method_name = $method->name;
46            if (substr($method_name, 0, 1) == '_') continue;
47
48            // strip asterisks
49            $doc = $method->getDocComment();
50            $doc = preg_replace(
51                array('/^[ \t]*\/\*+[ \t]*/m', '/[ \t]*\*+[ \t]*/m', '/\*+\/\s*$/m', '/\s*\/\s*$/m'),
52                array('', '', '', ''),
53                $doc
54            );
55
56            // prepare data
57            $data = array();
58            $data['name'] = $method_name;
59            $data['public'] = 0;
60            $data['doc'] = $doc;
61            $data['args'] = array();
62
63            // get parameter type from doc block type hint
64            foreach ($method->getParameters() as $parameter) {
65                $name = $parameter->name;
66                $type = 'string'; // we default to string
67                if (preg_match('/^@param[ \t]+([\w|\[\]]+)[ \t]\$' . $name . '/m', $doc, $m)) {
68                    $type = $this->cleanTypeHint($m[1]);
69                }
70                $data['args'][] = $type;
71            }
72
73            // get return type from doc block type hint
74            if (preg_match('/^@return[ \t]+([\w|\[\]]+)/m', $doc, $m)) {
75                $data['return'] = $this->cleanTypeHint($m[1]);
76            } else {
77                $data['return'] = 'string';
78            }
79
80            // add to result
81            $result[$method_name] = $data;
82        }
83
84        return $result;
85    }
86
87    /**
88     * Matches the given type hint against the valid options for the remote API
89     *
90     * @param string $hint
91     * @return string
92     */
93    protected function cleanTypeHint($hint)
94    {
95        $types = explode('|', $hint);
96        foreach ($types as $t) {
97            if (substr($t, -2) == '[]') {
98                return 'array';
99            }
100            if ($t == 'boolean') {
101                return 'bool';
102            }
103            if (in_array($t, array('array', 'string', 'int', 'double', 'bool', 'null', 'date', 'file'))) {
104                return $t;
105            }
106        }
107        return 'string';
108    }
109
110    /**
111     * @return Api
112     */
113    protected function getApi()
114    {
115        return $this->api;
116    }
117
118}
119