Created
January 20, 2018 01:15
-
-
Save anonymous/13d3c6eecbfddc7715435d020d7e149a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Kirby\Registry { | |
use Kirby; | |
use Kirby\Registry; | |
class Rpc extends Entry { | |
public function set($name, $callback) { | |
$this->kirby->rpc->add($name, $callback); | |
} | |
} | |
} | |
namespace RpcPlugin { | |
class RpcDispatcher { | |
const JSON_RPC_VERSION = '2.0'; | |
const JSON_PARSE_ERROR = -32700; | |
const INVALID_REQUEST = -32600; | |
const METHOD_NOT_FOUND = -32601; | |
const INVALID_PARAMS = -32602; | |
const INTERNAL_ERROR = -32603; | |
private $methods = []; | |
public function __construct(\Kirby $kirby) { | |
$this->methods = []; | |
$kirby->set('route', [ | |
'pattern' => 'jsonrpc', | |
'method' => 'POST', | |
'action' => [$this, 'onMessage'] | |
]); | |
} | |
private static function error($code, $message) { | |
if (!is_int($code)) throw new \Exception('code must be int'); | |
$args = array_slice(func_get_args(), 1); | |
return new \Response([ | |
'error' => [ | |
'message' => call_user_func_array('sprintf', $args), | |
'code' => $code | |
] | |
], 'json', 504); | |
} | |
public function onMessage() { | |
$payloadRaw = file_get_contents('php://input'); | |
$payload = json_decode($payloadRaw, true); | |
if (is_null($payload)) { | |
return self::error(self::JSON_PARSE_ERROR, 'unable to parse json'); | |
} | |
if (!array_key_exists('id', $payload)) { | |
return self::error(0, 'missing id'); | |
} | |
$id = $payload['id']; | |
$version = $payload['jsonrpc']; | |
if ($version !== self::JSON_RPC_VERSION) { | |
return self::error(0, 'jsonrpc must be %s, was %s', self::JSON_RPC_VERSION, $version); | |
} | |
$method = $payload['method']; | |
if (!array_key_exists($method, $this->methods)) { | |
return self::error(self::METHOD_NOT_FOUND, 'method %s is missing', $method); | |
} | |
$cb = $this->methods[$method]; | |
$info = new \ReflectionFunction($cb); | |
$nargs = $info->getNumberOfRequiredParameters(); | |
if (!array_key_exists('params', $payload)) { | |
return self::error(0, 'missing params'); | |
} | |
$params = $payload['params']; | |
if (!is_array($params) || $nargs !== count($params)) { | |
return self::error(self::INVALID_PARAMS, 'Method expects %d params, but got %d', $nargs, count($params)); | |
} | |
try { | |
$r = call_user_func_array($cb, $params); | |
return new \Response([ | |
'result' => $r, | |
'jsonrpc' => self::JSON_RPC_VERSION, | |
'id' => $id | |
], 'json'); | |
} | |
catch (Exception $e) { | |
return self::error(self::INTERNAL_ERROR, 'error :('); | |
} | |
} | |
public function add($name, callable $callback) { | |
if (array_key_exists($name, $this->methods)) { | |
throw new \Exception("method name $name already taken"); | |
} | |
$this->methods[$name] = $callback; | |
} | |
} | |
$kirby->rpc = new RpcDispatcher(kirby()); | |
} | |
namespace MyPlugin { | |
kirby()->set('rpc', 'add', function ($a, $b) { | |
return $a + $b; | |
}); | |
kirby()->set('rpc', 'get_users', function () { | |
return kirby()->site()->users()->toArray(); | |
}); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment