Civi::pipe - Remove BasicJsonSession
[civicrm-core.git] / Civi / Pipe / JsonRpcSession.php
CommitLineData
54675f57
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11
12namespace Civi\Pipe;
13
14class JsonRpcSession {
15
16 use LineSessionTrait;
17
18 protected const METHOD_REGEX = ';^[a-z][a-zA-Z0-9_]*$;';
19
20 /**
21 * Open-ended object. Any public method will be available during this session.
22 *
23 * @var object
24 */
25 protected $methods;
26
27 /**
28 * @inheritDoc
29 */
30 protected function onConnect(): ?string {
31 \CRM_Core_Session::useFakeSession();
32 $this->methods = new PublicMethods();
33 return json_encode(["Civi::pipe" => ['jsonrpc20']]);
34 }
35
36 /**
37 * @inheritDoc
38 */
39 protected function onRequest(string $requestLine): ?string {
40 $request = \json_decode($requestLine, TRUE);
41
42 if ($request === NULL) {
43 throw new \InvalidArgumentException('Parse error', -32700);
44 }
45
46 if (!is_array($request)) {
47 throw new \InvalidArgumentException('Invalid Request', -32600);
48 }
49
50 if (isset($request[0])) {
51 $response = array_map([$this, 'handleRequest'], $request);
52 }
53 else {
54 $response = $this->handleRequest($request);
55 }
56
57 return \json_encode($response);
58 }
59
60 protected function handleRequest($request): array {
61 try {
62 if ($request === NULL) {
63 throw new \InvalidArgumentException('Parse error', -32700);
64 }
65 if (($request['jsonrpc'] ?? '') !== '2.0') {
66 throw new \InvalidArgumentException('Invalid Request', -32600);
67 }
68
69 $method = str_replace('.', '_', mb_strtolower($request['method']));
70 if (!is_string($method) || !preg_match(self::METHOD_REGEX, $method)) {
71 throw new \InvalidArgumentException('Invalid Request', -32600);
72 }
73
74 if (!is_callable([$this->methods, $method])) {
75 throw new \InvalidArgumentException('Method not found', -32601);
76 }
77
78 $result = call_user_func([$this->methods, $method], $this, $request['params'] ?? []);
79 $id = array_key_exists('id', $request) ? ['id' => $request['id']] : [];
80 return [
81 'jsonrpc' => '2.0',
82 'result' => $result,
83 ] + $id;
84 }
85 catch (\Throwable $t) {
86 return $this->createJsonError($request, $t);
87 }
88 }
89
90 /**
91 * @inheritDoc
92 */
93 protected function onException(string $requestLine, \Throwable $t): ?string {
94 return \json_encode($this->createJsonError(['jsonrpc' => '2.0'], $t));
95 }
96
97 protected function createJsonError(array $request, \Throwable $t): array {
98 $isJsonErrorCode = $t->getCode() >= -32999 && $t->getCode() <= -32000;
99 $errorData = \CRM_Core_Config::singleton()->debug
100 ? ['class' => get_class($t), 'trace' => $t->getTraceAsString()]
101 : NULL;
102 return \CRM_Utils_Array::subset($request, ['jsonrpc', 'id']) + [
103 'error' => [
104 'code' => $isJsonErrorCode ? $t->getCode() : -32099,
105 'message' => $t->getMessage(),
106 'data' => $errorData,
107 ],
108 ];
109 }
110
111}