1 | <?php |
||||
2 | |||||
3 | declare(strict_types=1); |
||||
4 | |||||
5 | namespace PHPTdGram\TdClient; |
||||
6 | |||||
7 | use PHPTdGram\Adapter\AdapterInterface; |
||||
8 | use PHPTdGram\Adapter\Exception\AdapterException; |
||||
9 | use PHPTdGram\Adapter\Exception\JsonException; |
||||
10 | use PHPTdGram\Schema\Error; |
||||
11 | use PHPTdGram\Schema\LogStreamDefault; |
||||
12 | use PHPTdGram\Schema\LogStreamEmpty; |
||||
13 | use PHPTdGram\Schema\LogStreamFile; |
||||
14 | use PHPTdGram\Schema\SetLogStream; |
||||
15 | use PHPTdGram\Schema\SetLogVerbosityLevel; |
||||
16 | use PHPTdGram\Schema\TdFunction; |
||||
17 | use PHPTdGram\Schema\TdObject; |
||||
18 | use PHPTdGram\Schema\TdSchemaRegistry; |
||||
19 | use PHPTdGram\Schema\UpdateOption; |
||||
20 | use PHPTdGram\TdClient\Exception\ErrorReceivedException; |
||||
21 | use PHPTdGram\TdClient\Exception\QueryTimeoutException; |
||||
22 | use PHPTdGram\TdClient\Exception\TdClientException; |
||||
23 | use Psr\Log\LoggerInterface; |
||||
24 | use Psr\Log\NullLogger; |
||||
25 | |||||
26 | /** |
||||
27 | * @author Aurimas Niekis <[email protected]> |
||||
28 | */ |
||||
29 | class TdClient |
||||
30 | { |
||||
31 | private AdapterInterface $adapter; |
||||
32 | private LoggerInterface $logger; |
||||
33 | |||||
34 | /** @var TdObject[] */ |
||||
35 | private array $packetBacklog; |
||||
36 | |||||
37 | 9 | public function __construct(AdapterInterface $adapter, LoggerInterface $logger = null) |
|||
38 | { |
||||
39 | 9 | $this->adapter = $adapter; |
|||
40 | 9 | $this->logger = $logger ?? new NullLogger(); |
|||
41 | 9 | $this->packetBacklog = []; |
|||
42 | 9 | } |
|||
43 | |||||
44 | /** |
||||
45 | * @throws AdapterException |
||||
46 | * @throws JsonException |
||||
47 | * @throws TdClientException |
||||
48 | */ |
||||
49 | 3 | public function verifyVersion(): void |
|||
50 | { |
||||
51 | /** @var UpdateOption $response */ |
||||
52 | 3 | $response = $this->receive(10); |
|||
53 | |||||
54 | 3 | if (!($response instanceof UpdateOption)) { |
|||
0 ignored issues
–
show
introduced
by
![]() |
|||||
55 | 1 | throw new TdClientException(sprintf('First packet supposed to be "UpdateOption" received "%s"', $response->getTdTypeName())); |
|||
56 | } |
||||
57 | |||||
58 | 2 | $clientVersion = $response->getValue()->getValue(); |
|||
0 ignored issues
–
show
The method
getValue() does not exist on PHPTdGram\Schema\OptionValue . It seems like you code against a sub-type of said class. However, the method does not exist in PHPTdGram\Schema\OptionValueEmpty . Are you sure you never get one of those?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
59 | 2 | $schemaVersion = TdSchemaRegistry::VERSION; |
|||
60 | |||||
61 | 2 | if ($schemaVersion !== $clientVersion) { |
|||
62 | 1 | throw new TdClientException(sprintf('Client TdLib version "%s" doesnt match Schema version "%s"', $clientVersion, $schemaVersion)); |
|||
63 | } |
||||
64 | 1 | } |
|||
65 | |||||
66 | /** |
||||
67 | * @param float $timeout the maximum number of seconds allowed for this function to wait for new data |
||||
68 | * @param bool $processBacklog should process backlog packets |
||||
69 | * |
||||
70 | * @throws AdapterException |
||||
71 | * @throws ErrorReceivedException |
||||
72 | * @throws JsonException |
||||
73 | */ |
||||
74 | 7 | public function receive(float $timeout, bool $processBacklog = true): ?TdObject |
|||
75 | { |
||||
76 | 7 | if (count($this->packetBacklog) > 0 && $processBacklog) { |
|||
77 | 1 | return array_shift($this->packetBacklog); |
|||
78 | } |
||||
79 | |||||
80 | 7 | $response = $this->adapter->receive($timeout); |
|||
81 | |||||
82 | 7 | if (null === $response) { |
|||
83 | 3 | return null; |
|||
84 | } |
||||
85 | |||||
86 | 6 | $object = TdSchemaRegistry::fromArray($response); |
|||
87 | |||||
88 | 6 | $this->logger->debug( |
|||
89 | 6 | sprintf('Received packet "%s" from TdLib', $object->getTdTypeName()), |
|||
90 | 6 | ['packet' => $object] |
|||
91 | ); |
||||
92 | |||||
93 | 6 | if ($object instanceof Error) { |
|||
94 | 1 | throw new ErrorReceivedException($object); |
|||
95 | } |
||||
96 | |||||
97 | 6 | return $object; |
|||
98 | } |
||||
99 | |||||
100 | /** |
||||
101 | * @param int $level New value of the verbosity level for logging. Value 0 corresponds to fatal errors, value 1 |
||||
102 | * corresponds to errors, value 2 corresponds to warnings and debug warnings, value 3 corresponds |
||||
103 | * to informational, value 4 corresponds to debug, value 5 corresponds to verbose debug, value |
||||
104 | * greater than 5 and up to 1023 can be used to enable even more logging. |
||||
105 | * |
||||
106 | * @return $this |
||||
107 | * |
||||
108 | * @throws AdapterException |
||||
109 | * @throws JsonException |
||||
110 | */ |
||||
111 | 1 | public function setLogVerbosityLevel(int $level): self |
|||
112 | { |
||||
113 | 1 | $this->adapter->execute( |
|||
114 | 1 | new SetLogVerbosityLevel($level) |
|||
115 | ); |
||||
116 | |||||
117 | 1 | return $this; |
|||
118 | } |
||||
119 | |||||
120 | /** |
||||
121 | * @param string $file path to the file to where the internal TDLib log will be written |
||||
122 | * @param int $maxLogFileSize the maximum size of the file to where the internal TDLib log is written before the |
||||
123 | * file will be auto-rotated |
||||
124 | * |
||||
125 | * @return $this |
||||
126 | * |
||||
127 | * @throws AdapterException |
||||
128 | * @throws JsonException |
||||
129 | */ |
||||
130 | 1 | public function setLogToFile(string $file, int $maxLogFileSize = PHP_INT_MAX): self |
|||
131 | { |
||||
132 | 1 | $this->adapter->execute( |
|||
133 | 1 | new SetLogStream( |
|||
134 | 1 | new LogStreamFile($file, $maxLogFileSize) |
|||
135 | ) |
||||
136 | ); |
||||
137 | |||||
138 | 1 | return $this; |
|||
139 | } |
||||
140 | |||||
141 | /** |
||||
142 | * @return $this |
||||
143 | * |
||||
144 | * @throws AdapterException |
||||
145 | * @throws JsonException |
||||
146 | */ |
||||
147 | 1 | public function setLogToStderr(): self |
|||
148 | { |
||||
149 | 1 | $this->adapter->execute( |
|||
150 | 1 | new SetLogStream( |
|||
151 | 1 | new LogStreamDefault() |
|||
152 | ) |
||||
153 | ); |
||||
154 | |||||
155 | 1 | return $this; |
|||
156 | } |
||||
157 | |||||
158 | /** |
||||
159 | * @return $this |
||||
160 | * |
||||
161 | * @throws AdapterException |
||||
162 | * @throws JsonException |
||||
163 | */ |
||||
164 | 1 | public function setLogToNone(): self |
|||
165 | { |
||||
166 | 1 | $this->adapter->execute( |
|||
167 | 1 | new SetLogStream( |
|||
168 | 1 | new LogStreamEmpty() |
|||
169 | ) |
||||
170 | ); |
||||
171 | |||||
172 | 1 | return $this; |
|||
173 | } |
||||
174 | |||||
175 | /** |
||||
176 | * Sends packet to TdLib marked with extra identifier and loops till received marked response back or timeout |
||||
177 | * occurs. Stores all in between packets in backlog. |
||||
178 | * |
||||
179 | * @param TdFunction $packet request packet to send to TdLib |
||||
180 | * @param int $timeout the maximum number of seconds allowed for this function to wait for a response |
||||
181 | * packet |
||||
182 | * @param float $receiveTimeout the maximum number of seconds allowed for this function to wait for new data |
||||
183 | * |
||||
184 | * @throws AdapterException |
||||
185 | * @throws ErrorReceivedException |
||||
186 | * @throws JsonException |
||||
187 | * @throws QueryTimeoutException |
||||
188 | */ |
||||
189 | 3 | public function query(TdFunction $packet, int $timeout = 10, float $receiveTimeout = 0.1): TdObject |
|||
190 | { |
||||
191 | 3 | if (null === $packet->getTdExtra()) { |
|||
192 | 3 | $packet->setTdExtra(spl_object_hash($packet)); |
|||
193 | } |
||||
194 | |||||
195 | 3 | $extra = $packet->getTdExtra(); |
|||
196 | 3 | $this->send($packet); |
|||
197 | |||||
198 | 3 | $startTime = time(); |
|||
199 | 3 | $obj = null; |
|||
200 | 3 | while (true) { |
|||
201 | 3 | $obj = $this->receive($receiveTimeout, false); |
|||
202 | |||||
203 | 3 | if (null === $obj) { |
|||
204 | 2 | if ((time() - $startTime) > $timeout) { |
|||
205 | 1 | throw new QueryTimeoutException($packet); |
|||
206 | } |
||||
207 | |||||
208 | 2 | continue; |
|||
209 | } |
||||
210 | |||||
211 | 2 | if ($extra === $obj->getTdExtra()) { |
|||
212 | 1 | break; |
|||
213 | } else { |
||||
214 | 2 | $this->packetBacklog[] = $obj; |
|||
215 | } |
||||
216 | |||||
217 | 2 | if ((time() - $startTime) > $timeout) { |
|||
218 | 1 | throw new QueryTimeoutException($packet); |
|||
219 | } |
||||
220 | } |
||||
221 | |||||
222 | 1 | return $obj; |
|||
223 | } |
||||
224 | |||||
225 | /** |
||||
226 | * Sends packet to TdLib. |
||||
227 | * |
||||
228 | * @param TdFunction $packet request packet to send to TdLib |
||||
229 | * |
||||
230 | * @throws AdapterException |
||||
231 | * @throws JsonException |
||||
232 | */ |
||||
233 | 4 | public function send(TdFunction $packet): void |
|||
234 | { |
||||
235 | 4 | $this->logger->debug( |
|||
236 | 4 | sprintf('Sending packet "%s" to TdLib', $packet->getTdTypeName()), |
|||
237 | 4 | ['packet' => $packet] |
|||
238 | ); |
||||
239 | |||||
240 | 4 | $this->adapter->send($packet); |
|||
241 | 4 | } |
|||
242 | } |
||||
243 |