method = $method; $this->category = $category; } /** * Call the method * * Important: access/authentication checks need to be done before calling this! * * @param array $args * @return mixed */ public function __invoke($args) { if (!array_is_list($args)) { $args = $this->namedArgsToPositional($args); } return call_user_func_array($this->method, $args); } /** * Access the method documentation * * This lazy loads the docs only when needed * * @return DocBlockMethod */ public function getDocs() { if ($this->docs === null) { try { if (is_array($this->method)) { $reflect = new ReflectionMethod($this->method[0], $this->method[1]); } else { $reflect = new ReflectionFunction($this->method); } $this->docs = new DocBlockMethod($reflect); } catch (ReflectionException $e) { throw new RuntimeException('Failed to parse API method documentation', 0, $e); } } return $this->docs; } /** * Is this a public method? * * Public methods can be called without authentication * * @return bool */ public function isPublic() { return $this->isPublic; } /** * Set the public flag * * @param bool $isPublic * @return $this */ public function setPublic(bool $isPublic = true) { $this->isPublic = $isPublic; return $this; } /** * Get information about the argument of this call * * @return array */ public function getArgs() { return $this->getDocs()->getParameters(); } /** * Get information about the return value of this call * * @return array */ public function getReturn() { return $this->getDocs()->getReturn(); } /** * Get the summary of this call * * @return string */ public function getSummary() { return $this->getDocs()->getSummary(); } /** * Get the description of this call * * @return string */ public function getDescription() { return $this->getDocs()->getDescription(); } /** * Get the category of this call * * @return string */ public function getCategory() { return $this->category; } /** * Converts named arguments to positional arguments * * @fixme with PHP 8 we can use named arguments directly using the spread operator * @param array $params * @return array */ protected function namedArgsToPositional($params) { $args = []; foreach ($this->getDocs()->getParameters() as $arg => $arginfo) { if (isset($params[$arg])) { $args[] = $params[$arg]; } elseif ($arginfo['optional'] && array_key_exists('default', $arginfo)) { $args[] = $arginfo['default']; } else { throw new InvalidArgumentException("Missing argument $arg"); } } return $args; } }