Issues (2)

src/TdClient.php (2 issues)

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
$response is always a sub-type of PHPTdGram\Schema\UpdateOption.
Loading history...
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 ignore-call  annotation

58
        $clientVersion = $response->getValue()->/** @scrutinizer ignore-call */ getValue();
Loading history...
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