Test Failed
Push — master ( 67c9bb...4758b5 )
by
unknown
02:50 queued 38s
created

Client::inlineQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 0
cts 0
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
crap 2
1
<?php
2
3
namespace TelegramBot\Api;
4
5
use Closure;
6
use ReflectionFunction;
7
use TelegramBot\Api\Events\EventCollection;
8
use TelegramBot\Api\Types\Update;
9
10
/**
11
 * Class Client
12
 *
13
 * @package TelegramBot\Api
14
 */
15
class Client
16
{
17
    /**
18
     * RegExp for bot commands
19
     */
20
    const REGEXP = '/^(?:@\w+\s)?\/([^\s@]+)(@\S+)?\s?(.*)$/';
21
22
    /**
23
     * @var \TelegramBot\Api\BotApi
24
     */
25
    protected $api;
26
27
    /**
28
     * @var \TelegramBot\Api\Events\EventCollection
29
     */
30
    protected $events;
31
32
    /**
33
     * Client constructor
34
     *
35
     * @param string $token Telegram Bot API token
36
     * @param string|null $trackerToken Yandex AppMetrica application api_key
37
     */
38 7
    public function __construct($token, $trackerToken = null)
39
    {
40 7
        $this->api = new BotApi($token);
41 7
        $this->events = new EventCollection($trackerToken);
42 7
    }
43
44
    /**
45
     * Use this method to add command. Parameters will be automatically parsed and passed to closure.
46
     *
47
     * @param string $name
48
     * @param \Closure $action
49
     *
50
     * @return \TelegramBot\Api\Client
51
     */
52
    public function command($name, Closure $action)
53
    {
54
        return $this->on(self::getEvent($action), self::getChecker($name));
55
    }
56
57
    public function editedMessage(Closure $action)
58
    {
59
        $method = 'getEditedMessage';
60
        return $this->on(self::getCustomEvent($action, $method), self::getCustomEventChecker($method));
61
    }
62
63
    public function channelPost(Closure $action)
64
    {
65
        $method = 'getChannelPost';
66
        return $this->on(self::getCustomEvent($action, $method), self::getCustomEventChecker($method));
67
    }
68
69
    public function editedChannelPost(Closure $action)
70
    {
71
        $method = 'getEditedChannelPost';
72
        return $this->on(self::getCustomEvent($action, $method), self::getCustomEventChecker($method));
73
    }
74
75
    public function inlineQuery(Closure $action)
76
    {
77
        $method = 'getInlineQuery';
78
        return $this->on(self::getCustomEvent($action, $method), self::getCustomEventChecker($method));
79
    }
80
81 1
    public function chosenInlineResult(Closure $action)
82
    {
83 1
        $method = 'getChosenInlineResult';
84
        return $this->on(self::getCustomEvent($action, $method), self::getCustomEventChecker($method));
85 1
    }
86
87
    public function shippingQuery(Closure $action)
88
    {
89
        $method = 'getShippingQuery';
90
        return $this->on(self::getCustomEvent($action, $method), self::getCustomEventChecker($method));
91
    }
92
93 4
    public function preCheckoutQuery(Closure $action)
94
    {
95 4
        $method = 'getPreCheckoutQuery';
96
        return $this->on(self::getCustomEvent($action, $method), self::getCustomEventChecker($method));
97 4
    }
98 4
99 4
    /**
100
     * Use this method to add an event.
101
     * If second closure will return true (or if you are passed null instead of closure), first one will be executed.
102
     *
103
     * @param \Closure $event
104
     * @param \Closure|null $checker
105
     *
106
     * @return \TelegramBot\Api\Client
107
     */
108
    public function on(Closure $event, Closure $checker = null)
109
    {
110
        $this->events->add($event, $checker);
111
112
        return $this;
113
    }
114
115
    /**
116
     * Handle updates
117
     *
118
     * @param Update[] $updates
119
     */
120
    public function handle(array $updates)
121
    {
122
        foreach ($updates as $update) {
123
            /* @var \TelegramBot\Api\Types\Update $update */
124
            $this->events->handle($update);
125
        }
126 4
    }
127
128
    /**
129 4
     * Webhook handler
130 4
     *
131 1
     * @return array
132
     * @throws \TelegramBot\Api\InvalidJsonException
133
     */
134 3
    public function run()
135
    {
136 3
        if ($data = BotApi::jsonValidate($this->getRawBody(), true)) {
137 1
            $this->handle([Update::fromResponse($data)]);
138 1
        }
139 2
    }
140
141
    public function getRawBody()
142 3
    {
143
        return file_get_contents('php://input');
144 3
    }
145
146 3
    /**
147 3
     * Returns event function to handling the command.
148 3
     *
149
     * @param \Closure $action
150 3
     *
151 4
     * @return \Closure
152
     */
153
    protected static function getEvent(Closure $action)
154 4
    {
155
        return function (Update $update) use ($action) {
156
            $message = $update->getMessage();
157 4
            if (!$message) {
158 3
                return true;
159
            }
160
161 1
            preg_match(self::REGEXP, $message->getText(), $matches);
162 1
163 1
            if (isset($matches[3]) && !empty($matches[3])) {
164 4
                $parameters = str_getcsv($matches[3], chr(32));
165
            } else {
166
                $parameters = [];
167
            }
168
169
            array_unshift($parameters, $message);
170
171
            $action = new ReflectionFunction($action);
172
173
            if (count($parameters) >= $action->getNumberOfRequiredParameters()) {
174
                $action->invokeArgs($parameters);
175
            }
176
177
            return false;
178
        };
179
    }
180
181
    protected static function getCustomEvent(Closure $action, $method)
182
    {
183
        return function (Update $update) use ($action, $method) {
184
            if (!$update->$method()) {
185
                return true;
186
            }
187
188
            $reflectionAction = new ReflectionFunction($action);
189
            $reflectionAction->invokeArgs([$update->$method()]);
190
            return false;
191
        };
192
    }
193
194
    /**
195
     * Returns check function to handling the command.
196
     *
197
     * @param string $name
198
     *
199
     * @return \Closure
200 4
     */
201
    protected static function getChecker($name)
202
    {
203 4
        return function (Update $update) use ($name) {
204 4
            $message = $update->getMessage();
205 1
            if (is_null($message) || !strlen($message->getText())) {
206
                return false;
207
            }
208 3
209
            preg_match(self::REGEXP, $message->getText(), $matches);
210 3
211 4
            return !empty($matches) && $matches[1] == $name;
212
        };
213
    }
214
215
216
    /**
217
     * Returns check function to handling the custom event
218
     * @link https://core.telegram.org/bots/api#update
219 4
     *
220
     * @param string $method Update method name
221
     *
222 4
     * @return Closure
223 4
     */
224
    protected static function getCustomEventChecker($method)
225
    {
226
        return function (Update $update) use ($method) {
227
            return !is_null($update->$method());
228
        };
229
    }
230
231
    public function __call($name, array $arguments)
232
    {
233
        if (method_exists($this, $name)) {
234
            return call_user_func_array([$this, $name], $arguments);
235
        } elseif (method_exists($this->api, $name)) {
236
            return call_user_func_array([$this->api, $name], $arguments);
237
        }
238
        throw new BadMethodCallException("Method {$name} not exists");
239
    }
240
}
241