moved OpenAPI generator to correct namespace
[dokuwiki.git] / inc / Remote / Api.php
blobd258d59b48d9d71cc81196be0a7079e8a04ec900
1 <?php
3 namespace dokuwiki\Remote;
5 use dokuwiki\Extension\RemotePlugin;
6 use dokuwiki\Logger;
8 /**
9 * This class provides information about remote access to the wiki.
11 * == Types of methods ==
12 * There are two types of remote methods. The first is the core methods.
13 * These are always available and provided by dokuwiki.
14 * The other is plugin methods. These are provided by remote plugins.
16 * == Information structure ==
17 * The information about methods will be given in an array with the following structure:
18 * array(
19 * 'method.remoteName' => array(
20 * 'args' => array(
21 * 'type eg. string|int|...|date|file',
22 * )
23 * 'name' => 'method name in class',
24 * 'return' => 'type',
25 * 'public' => 1/0 - method bypass default group check (used by login)
26 * ['doc' = 'method documentation'],
27 * )
28 * )
30 * plugin names are formed the following:
31 * core methods begin by a 'dokuwiki' or 'wiki' followed by a . and the method name itself.
32 * i.e.: dokuwiki.version or wiki.getPage
34 * plugin methods are formed like 'plugin.<plugin name>.<method name>'.
35 * i.e.: plugin.clock.getTime or plugin.clock_gmt.getTime
37 class Api
39 /** @var ApiCall[] core methods provided by dokuwiki */
40 protected $coreMethods;
42 /** @var ApiCall[] remote methods provided by dokuwiki plugins */
43 protected $pluginMethods;
45 private $dateTransformation;
46 private $fileTransformation;
48 /**
49 * constructor
51 public function __construct()
53 $this->dateTransformation = [$this, 'dummyTransformation'];
54 $this->fileTransformation = [$this, 'dummyTransformation'];
57 /**
58 * Get all available methods with remote access.
60 * @return ApiCall[] with information to all available methods
62 public function getMethods()
64 return array_merge($this->getCoreMethods(), $this->getPluginMethods());
67 /**
68 * Collects all the core methods
70 * @param ApiCore|\RemoteAPICoreTest $apiCore this parameter is used for testing.
71 * Here you can pass a non-default RemoteAPICore instance. (for mocking)
72 * @return ApiCall[] all core methods.
74 public function getCoreMethods($apiCore = null)
76 if (!$this->coreMethods) {
77 if ($apiCore === null) {
78 $this->coreMethods = (new ApiCore())->getMethods();
79 } else {
80 $this->coreMethods = $apiCore->getMethods();
83 return $this->coreMethods;
86 /**
87 * Collects all the methods of the enabled Remote Plugins
89 * @return ApiCall[] all plugin methods.
91 public function getPluginMethods()
93 if ($this->pluginMethods) return $this->pluginMethods;
95 $plugins = plugin_list('remote');
96 foreach ($plugins as $pluginName) {
97 /** @var RemotePlugin $plugin */
98 $plugin = plugin_load('remote', $pluginName);
99 if (!is_subclass_of($plugin, RemotePlugin::class)) {
100 Logger::error("Remote Plugin $pluginName does not implement dokuwiki\Extension\RemotePlugin");
101 continue;
104 try {
105 $methods = $plugin->getMethods();
106 } catch (\ReflectionException $e) {
107 Logger::error(
108 "Remote Plugin $pluginName failed to return methods",
109 $e->getMessage(),
110 $e->getFile(),
111 $e->getLine()
113 continue;
116 foreach ($methods as $method => $call) {
117 $this->pluginMethods["plugin.$pluginName.$method"] = $call;
121 return $this->pluginMethods;
125 * Call a method via remote api.
127 * @param string $method name of the method to call.
128 * @param array $args arguments to pass to the given method
129 * @return mixed result of method call, must be a primitive type.
130 * @throws RemoteException
132 public function call($method, $args = [])
134 if ($args === null) {
135 $args = [];
138 // pre-flight checks
139 $this->ensureApiIsEnabled();
140 $methods = $this->getMethods();
141 if (!isset($methods[$method])) {
142 throw new RemoteException('Method does not exist', -32603);
144 $this->ensureAccessIsAllowed($methods[$method]);
146 // invoke the ApiCall
147 try {
148 return $methods[$method]($args);
149 } catch (\ArgumentCountError $th) {
150 throw new RemoteException('Method does not exist - wrong parameter count.', -32603);
155 * Check that the API is generally enabled
157 * @return void
158 * @throws RemoteException thrown when the API is disabled
160 public function ensureApiIsEnabled()
162 global $conf;
163 if (!$conf['remote'] || trim($conf['remoteuser']) == '!!not set!!') {
164 throw new AccessDeniedException('Server Error. API is not enabled in config.', -32604);
169 * Check if the current user is allowed to call the given method
171 * @param ApiCall $method
172 * @return void
173 * @throws AccessDeniedException Thrown when the user is not allowed to call the method
175 public function ensureAccessIsAllowed(ApiCall $method)
177 global $conf;
178 global $INPUT;
179 global $USERINFO;
181 if ($method->isPublic()) return; // public methods are always allowed
182 if (!$conf['useacl']) return; // ACL is not enabled, so we can't check users
183 if (trim($conf['remoteuser']) === '') return; // all users are allowed
184 if (auth_isMember($conf['remoteuser'], $INPUT->server->str('REMOTE_USER'), (array)($USERINFO['grps'] ?? []))) {
185 return; // user is allowed
188 // still here? no can do
189 throw new AccessDeniedException('server error. not authorized to call method', -32604);
193 * Transform file to xml
195 * @param mixed $data
196 * @return mixed
198 public function toFile($data)
200 return call_user_func($this->fileTransformation, $data);
204 * Transform date to xml
206 * @param mixed $data
207 * @return mixed
209 public function toDate($data)
211 return call_user_func($this->dateTransformation, $data);
215 * A simple transformation
217 * @param mixed $data
218 * @return mixed
220 public function dummyTransformation($data)
222 return $data;
226 * Set the transformer function
228 * @param callback $dateTransformation
230 public function setDateTransformation($dateTransformation)
232 $this->dateTransformation = $dateTransformation;
236 * Set the transformer function
238 * @param callback $fileTransformation
240 public function setFileTransformation($fileTransformation)
242 $this->fileTransformation = $fileTransformation;