Completed
Push — master ( c9f97a...a10767 )
by Gusev
09:21 queued 05:37
created

Client   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 186
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 67.74%

Importance

Changes 11
Bugs 1 Features 5
Metric Value
wmc 24
c 11
b 1
f 5
lcom 1
cbo 5
dl 0
loc 186
ccs 42
cts 62
cp 0.6774
rs 10

12 Methods

Rating   Name   Duplication   Size   Complexity  
A run() 0 6 2
A __construct() 0 5 1
A command() 0 4 1
A inlineQuery() 0 4 1
A on() 0 6 1
A handle() 0 7 2
A getRawBody() 0 4 1
B getEvent() 0 27 5
A getInlineQueryEvent() 0 12 2
A getChecker() 0 13 4
A getInlineQueryChecker() 0 6 1
A __call() 0 9 3
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 = '/^\/([^\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 inlineQuery(Closure $action)
58
    {
59
        return $this->on(self::getInlineQueryEvent($action), self::getInlineQueryChecker());
60
    }
61
62
    /**
63
     * Use this method to add an event.
64
     * If second closure will return true (or if you are passed null instead of closure), first one will be executed.
65
     *
66
     * @param \Closure $event
67
     * @param \Closure|null $checker
68
     *
69
     * @return \TelegramBot\Api\Client
70
     */
71 1
    public function on(Closure $event, Closure $checker = null)
72
    {
73 1
        $this->events->add($event, $checker);
74
75 1
        return $this;
76
    }
77
78
    /**
79
     * Handle updates
80
     *
81
     * @param Update[] $updates
82
     */
83 4
    public function handle(array $updates)
84
    {
85 4
        foreach ($updates as $update) {
86
            /* @var \TelegramBot\Api\Types\Update $update */
87 4
            $this->events->handle($update);
88 4
        }
89 4
    }
90
91
    /**
92
     * Webhook handler
93
     *
94
     * @return array
95
     * @throws \TelegramBot\Api\InvalidJsonException
96
     */
97
    public function run()
98
    {
99
        if ($data = BotApi::jsonValidate($this->getRawBody(), true)) {
100
            $this->handle([Update::fromResponse($data)]);
101
        }
102
    }
103
104
    public function getRawBody()
105
    {
106
        return file_get_contents('php://input');
107
    }
108
109
    /**
110
     * Returns event function to handling the command.
111
     *
112
     * @param \Closure $action
113
     *
114
     * @return \Closure
115
     */
116 4
    protected static function getEvent(Closure $action)
117
    {
118
        return function (Update $update) use ($action) {
119 4
            $message = $update->getMessage();
120 4
            if (!$message) {
121 1
                return true;
122
            }
123
124 3
            preg_match(self::REGEXP, $message->getText(), $matches);
125
126 3
            if (isset($matches[3]) && !empty($matches[3])) {
127 1
                $parameters = str_getcsv($matches[3], chr(32));
128 1
            } else {
129 2
                $parameters = [];
130
            }
131
132 3
            array_unshift($parameters, $message);
133
134 3
            $action = new ReflectionFunction($action);
135
136 3
            if (count($parameters) >= $action->getNumberOfRequiredParameters()) {
137 3
                $action->invokeArgs($parameters);
138 3
            }
139
140 3
            return false;
141 4
        };
142
    }
143
144
    protected static function getInlineQueryEvent(Closure $action)
145
    {
146
        return function (Update $update) use ($action) {
147
            if (!$update->getInlineQuery()) {
148
                return true;
149
            }
150
151
            $reflectionAction = new ReflectionFunction($action);
152
            $reflectionAction->invokeArgs([$update->getInlineQuery()]);
153
            return false;
154
        };
155
    }
156
157
    /**
158
     * Returns check function to handling the command.
159
     *
160
     * @param string $name
161
     *
162
     * @return \Closure
163
     */
164 4
    protected static function getChecker($name)
165
    {
166
        return function (Update $update) use ($name) {
167 4
            $message = $update->getMessage();
168 4
            if (is_null($message) || !strlen($message->getText())) {
169 1
                return false;
170
            }
171
172 3
            preg_match(self::REGEXP, $message->getText(), $matches);
173
174 3
            return !empty($matches) && $matches[1] == $name;
175 4
        };
176
    }
177
178
    /**
179
     * Returns check function to handling the inline queries.
180
     *
181
     * @return Closure
182
     */
183
    protected static function getInlineQueryChecker()
184
    {
185 4
        return function (Update $update) {
186 4
            return !is_null($update->getInlineQuery());
187 4
        };
188
    }
189
190
191 1
    public function __call($name, array $arguments)
192
    {
193 1
        if (method_exists($this, $name)) {
194
            return call_user_func_array([$this, $name], $arguments);
195 1
        } elseif (method_exists($this->api, $name)) {
196
            return call_user_func_array([$this->api, $name], $arguments);
197
        }
198 1
        throw new BadMethodCallException("Method {$name} not exists");
199
    }
200
}
201