Civi::pipe - Rename maxLines to bufferSize
[civicrm-core.git] / Civi / Pipe / LineSessionTrait.php
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
12 namespace Civi\Pipe;
13
14 /**
15 * Synchronous line-oriented communication session.
16 *
17 * @code
18 * $session = new class {
19 * use LineSessionTrait;
20 * protected function onRequest(string $requestLine): ?string {
21 * return "Thanks";
22 * }
23 * protected function onException(string $requestLine, \Throwable $t): ?string {
24 * return "Oops";
25 * }
26 * }
27 * $session->setIO(STDIN, STDOUT)->run();
28 * @endCode
29 */
30 trait LineSessionTrait {
31
32 /**
33 * The onConnect() method is called when a new session is opened.
34 *
35 * @return string|null
36 * Header/welcome line, or NULL if none.
37 */
38 protected function onConnect(): ?string {
39 return NULL;
40 }
41
42 /**
43 * The onRequest() method is called after receiving one line of text.
44 *
45 * @param string $requestLine
46 * The received line of text.
47 * @return string|null
48 * The line to send back, or NULL if none.
49 */
50 abstract protected function onRequest(string $requestLine): ?string;
51
52 /**
53 * The onRequest() method is called after receiving one line of text.
54 *
55 * @param string $requestLine
56 * The received line of text - which led to the unhandled exception.
57 * @param \Throwable $t
58 * The unhandled exception.
59 * @return string|null
60 * The line to send back, or NULL if none.
61 */
62 abstract protected function onException(string $requestLine, \Throwable $t): ?string;
63
64 /**
65 * @var resource
66 * Ex: STDIN
67 */
68 protected $input;
69
70 /**
71 * @var resource
72 * Ex: STDOUT
73 */
74 protected $output;
75
76 /**
77 * Line-delimiter.
78 *
79 * @var string
80 */
81 protected $delimiter = "\n";
82
83 /**
84 * Maximum size of the buffer for reading lines.
85 *
86 * Clients may need to set this if they submit large requests.
87 *
88 * @var int
89 */
90 protected $bufferSize = 524288;
91
92 /**
93 * A value to display immediately before the response lines.
94 *
95 * Clients may set this is if they want to detect and skip buggy noise.
96 *
97 * @var string|null
98 * Ex: chr(1).chr(1)
99 */
100 protected $responsePrefix = NULL;
101
102 /**
103 * @param resource|null $input
104 * @param resource|null $output
105 */
106 public function __construct($input = NULL, $output = NULL) {
107 $this->input = $input;
108 $this->output = $output;
109 }
110
111 /**
112 * Run the main loop. Poll for commands on $input and write responses to $output.
113 */
114 public function run() {
115 $this->write($this->onConnect());
116
117 while (FALSE !== ($line = stream_get_line($this->input, $this->bufferSize, $this->delimiter))) {
118 $line = rtrim($line, $this->delimiter);
119 if (empty($line)) {
120 continue;
121 }
122
123 try {
124 $response = $this->onRequest($line);
125 }
126 catch (\Throwable $t) {
127 $response = $this->onException($line, $t);
128 }
129 $this->write($response);
130 }
131 }
132
133 /**
134 * @return int
135 */
136 public function getBufferSize(): int {
137 return $this->bufferSize;
138 }
139
140 /**
141 * @param int $bufferSize
142 * @return $this
143 */
144 public function setBufferSize(int $bufferSize) {
145 $this->bufferSize = $bufferSize;
146 return $this;
147 }
148
149 /**
150 * @return string|null
151 */
152 public function getResponsePrefix(): ?string {
153 return $this->responsePrefix;
154 }
155
156 /**
157 * @param string|null $responsePrefix
158 * @return $this
159 */
160 public function setResponsePrefix(?string $responsePrefix) {
161 $this->responsePrefix = $responsePrefix;
162 return $this;
163 }
164
165 /**
166 * @param resource $input
167 * @param resource $output
168 * @return $this
169 */
170 public function setIO($input, $output) {
171 $this->input = $input;
172 $this->output = $output;
173 return $this;
174 }
175
176 protected function write(?string $response): void {
177 if ($response === NULL) {
178 return;
179 }
180 if ($this->responsePrefix !== NULL) {
181 fwrite($this->output, $this->responsePrefix);
182 }
183 fwrite($this->output, $response);
184 fwrite($this->output, $this->delimiter);
185 }
186
187 }