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