Completed
Push — master ( ffef8a...ec94cb )
by Camilo
09:39 queued 05:35
created

TgLog::performApiRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1.0109

Importance

Changes 0
Metric Value
cc 1
eloc 10
nc 1
nop 1
dl 0
loc 13
ccs 7
cts 9
cp 0.7778
crap 1.0109
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace unreal4u\TelegramAPI;
6
7
use Psr\Log\LoggerInterface;
8
use React\Promise\PromiseInterface;
9
use unreal4u\Dummy\Logger;
10
use unreal4u\TelegramAPI\Abstracts\TelegramMethods;
11
use unreal4u\TelegramAPI\InternalFunctionality\PostOptionsConstructor;
12
use unreal4u\TelegramAPI\InternalFunctionality\TelegramDocument;
13
use unreal4u\TelegramAPI\InternalFunctionality\TelegramResponse;
14
use unreal4u\TelegramAPI\Telegram\Types\File;
15
16
/**
17
 * The main API which does it all
18
 */
19
class TgLog
20
{
21
    /**
22
     * @var RequestHandlerInterface
23
     */
24
    protected $requestHandler;
25
26
    /**
27
     * @var PostOptionsConstructor
28
     */
29
    protected $formConstructor;
30
31
    /**
32
     * Stores the token
33
     * @var string
34
     */
35
    private $botToken;
36
37
    /**
38
     * Contains an instance to a PSR-3 compatible logger
39
     * @var LoggerInterface
40
     */
41
    protected $logger;
42
43
    /**
44
     * Stores the API URL from Telegram
45
     * @var string
46
     */
47
    private $apiUrl;
48
49
    /**
50
     * @var string
51
     */
52
    protected $methodName = '';
53
54
    /**
55
     * TelegramLog constructor.
56
     *
57
     * @param string $botToken
58
     * @param RequestHandlerInterface $handler
59
     * @param LoggerInterface $logger
60
     */
61 41
    public function __construct(string $botToken, RequestHandlerInterface $handler, LoggerInterface $logger = null)
62
    {
63 41
        $this->botToken = $botToken;
64
65
        // Initialize new dummy logger (PSR-3 compatible) if not injected
66 41
        if ($logger === null) {
67 41
            $logger = new Logger();
68
        }
69 41
        $this->logger = $logger;
70
71 41
        $this->requestHandler = $handler;
72 41
        $this->formConstructor = new PostOptionsConstructor();
73 41
        $this->apiUrl = 'https://api.telegram.org/bot' . $this->botToken . '/';
74 41
    }
75
76
    /**
77
     * Performs the request to the Telegram servers
78
     *
79
     * @param TelegramMethods $method
80
     *
81
     * @return PromiseInterface
82
     * @throws \unreal4u\TelegramAPI\Exceptions\MissingMandatoryField
83
     */
84 32
    public function performApiRequest(TelegramMethods $method): PromiseInterface
85
    {
86 32
        $this->logger->debug('Request for async API call, resetting internal values', [\get_class($method)]);
87 32
        $this->resetObjectValues();
88 32
        $option = $this->formConstructor->constructOptions($method);
89 30
        return $this->sendRequestToTelegram($method, $option)
90
            ->then(function (TelegramResponse $response) use ($method) {
91 24
                return $method::bindToObject($response, $this->logger);
92
            }, function ($error) {
93
                $this->logger->error($error);
94
                throw $error;
95 24
            });
96
    }
97
98
    /**
99
     * @param File $file
100
     *
101
     * @return PromiseInterface
102
     */
103
    public function downloadFile(File $file): PromiseInterface
104
    {
105
        $url = 'https://api.telegram.org/file/bot' . $this->botToken . '/' . $file->file_path;
106
        $this->logger->debug('About to perform request to begin downloading file');
107
108
        return $this->requestHandler->get($url)->then(
109
            function (TelegramResponse $rawData) {
110
                return new TelegramDocument($rawData);
111
            }
112
        );
113
    }
114
115
    /**
116
     * This is the method that actually makes the call, which can be easily overwritten so that our unit tests can work
117
     *
118
     * @param TelegramMethods $method
119
     * @param array $formData
120
     *
121
     * @return PromiseInterface
122
     */
123
    protected function sendRequestToTelegram(TelegramMethods $method, array $formData): PromiseInterface
124
    {
125
        $this->logger->debug('About to perform async HTTP call to Telegram\'s API');
126
        return $this->requestHandler->post($this->composeApiMethodUrl($method), $formData);
127
    }
128
129
    /**
130
     * Resets everything to the default values
131
     *
132
     * @return TgLog
133
     */
134 32
    final protected function resetObjectValues(): TgLog
135
    {
136 32
        $this->formConstructor->formType = 'application/x-www-form-urlencoded';
137 32
        return $this;
138
    }
139
140
    /**
141
     * Builds up the URL with which we can work with
142
     *
143
     * All methods in the Bot API are case-insensitive.
144
     * All queries must be made using UTF-8.
145
     *
146
     * @see https://core.telegram.org/bots/api#making-requests
147
     *
148
     * @param TelegramMethods $call
149
     * @return string
150
     */
151 31
    protected function composeApiMethodUrl(TelegramMethods $call): string
152
    {
153 31
        $completeClassName = \get_class($call);
154 31
        $this->methodName = substr($completeClassName, strrpos($completeClassName, '\\') + 1);
155 31
        $this->logger->info('About to perform API request', ['method' => $this->methodName]);
156
157 31
        return $this->apiUrl . $this->methodName;
158
    }
159
}
160