Passed
Push — master ( 4c2b59...061776 )
by Shahrad
02:09
created

UpdateHandler::resolve()   A

Complexity

Conditions 6
Paths 13

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 12
c 1
b 0
f 0
dl 0
loc 22
rs 9.2222
cc 6
nc 13
nop 2
1
<?php
2
3
namespace TelegramBot;
4
5
use TelegramBot\Entities\Update;
6
use TelegramBot\Exception\InvalidBotTokenException;
7
use TelegramBot\Interfaces\HandlerInterface;
8
use TelegramBot\Traits\HandlerTrait;
9
use TelegramBot\Util\Toolkit;
10
11
/**
12
 * UpdateHandler class
13
 *
14
 * @link    https://github.com/telegram-bot-php/core
15
 * @author  Shahrad Elahi (https://github.com/shahradelahi)
16
 * @license https://github.com/telegram-bot-php/core/blob/master/LICENSE (MIT License)
17
 */
18
class UpdateHandler extends Telegram implements HandlerInterface
19
{
20
21
    use HandlerTrait;
22
23
    /**
24
     * @var ?Update
25
     */
26
    protected ?Update $update;
27
28
    /**
29
     * @var Plugin[]
30
     */
31
    private array $plugins = [];
32
33
    /**
34
     * @var bool
35
     */
36
    private bool $active_spreader = false;
37
38
    /**
39
     * The default configuration of the webhook.
40
     *
41
     * @var array
42
     */
43
    private array $config = [
44
        'autoload_env_file' => false,
45
        'env_file_path' => null,
46
    ];
47
48
    /**
49
     * Webhook constructor.
50
     *
51
     * @param string $api_token The API key of the bot. Leave it blank for autoload from .env file.
52
     */
53
    public function __construct(string $api_token = '')
54
    {
55
        parent::__construct($api_token);
56
57
        if (!Telegram::validateToken(self::getApiToken())) {
0 ignored issues
show
Bug introduced by
It seems like self::getApiToken() can also be of type false; however, parameter $token of TelegramBot\Telegram::validateToken() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

57
        if (!Telegram::validateToken(/** @scrutinizer ignore-type */ self::getApiToken())) {
Loading history...
58
            throw new InvalidBotTokenException();
59
        }
60
    }
61
62
    /**
63
     * Add plugins to the receiver
64
     *
65
     * @param Plugin[]|array $plugins
66
     * @retrun void
67
     */
68
    public function addPlugins(Plugin|array $plugins): UpdateHandler
69
    {
70
        if (is_object($plugins)) {
0 ignored issues
show
introduced by
The condition is_object($plugins) is always false.
Loading history...
71
            $plugins = [$plugins];
72
        }
73
74
        foreach ($plugins as $plugin) {
75
            if (!is_subclass_of($plugin, Plugin::class)) {
76
                throw new \RuntimeException(
77
                    sprintf('The plugin %s must be an instance of %s', get_class($plugin), Plugin::class)
78
                );
79
            }
80
81
            $reflection = Toolkit::reflectionClass($plugin);
0 ignored issues
show
Unused Code introduced by
The assignment to $reflection is dead and can be removed.
Loading history...
82
            $this->plugins[] = [
83
                'class' => $plugin,
84
                'initialized' => is_object($plugin),
85
            ];
86
        }
87
88
        return $this;
89
    }
90
91
    /**
92
     * Match the update with the given plugins
93
     *
94
     * @param Plugin[]|array $plugins
95
     * @return void
96
     */
97
    private function loadPlugins(array $plugins): void
98
    {
99
        $update = $update ?? ($this->update ?? Telegram::getUpdate());
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $update seems to never exist and therefore isset should always be false.
Loading history...
100
101
        foreach ($plugins as $plugin) {
102
            if (!is_subclass_of($plugin['class'], Plugin::class)) {
103
                throw new \InvalidArgumentException(sprintf(
104
                    'The plugin %s must be an instance of %s',
105
                    get_class($plugin['class']), Plugin::class
106
                ));
107
            }
108
        }
109
110
        if (!$update instanceof Update) {
111
            throw new \InvalidArgumentException(sprintf(
112
                'The update must be an instance of %s. %s given',
113
                Update::class, gettype($update)
114
            ));
115
        }
116
117
        $this->spreadUpdateWith($update, $plugins);
118
    }
119
120
    /**
121
     * This function will get update and spread it to the plugins
122
     *
123
     * @param Update $update
124
     * @param array<Plugin> $plugins
125
     * @return void
126
     */
127
    private function spreadUpdateWith(Update $update, array $plugins): void
128
    {
129
        $this->active_spreader = true;
130
131
        foreach ($plugins as $plugin) {
132
            if ($plugin['initialized'] === false) {
133
                $plugin['class'] = new $plugin['class']();
134
            }
135
136
            $plugin['class']->__execute($this, $update);
137
            if ($this->active_spreader === false) break;
138
        }
139
140
        $this->active_spreader = false;
141
    }
142
143
    /**
144
     * Resolve the request.
145
     *
146
     * @param ?Update $update The custom to work with
147
     * @param array $config The configuration of the receiver
148
     *
149
     * @retrun void
150
     */
151
    public function resolve(Update $update = null, array $config = []): void
152
    {
153
        if (!method_exists($this, '__process')) {
154
            throw new \RuntimeException('The method __process does not exist');
155
        }
156
157
        if (is_array($config)) $this->updateConfiguration($config);
0 ignored issues
show
introduced by
The condition is_array($config) is always true.
Loading history...
158
159
        if (!empty($update)) $this->update = $update;
160
        else $this->update = Telegram::getUpdate() !== false ? Telegram::getUpdate() : null;
0 ignored issues
show
Documentation Bug introduced by
It seems like TelegramBot\Telegram::ge...ram::getUpdate() : null can also be of type false. However, the property $update is declared as type TelegramBot\Entities\Update|null. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
161
162
        if (empty($this->update)) {
163
            TelegramLog::error(
164
                'The update is empty, the request is not processed'
165
            );
166
            return;
167
        }
168
169
        putenv('TG_CURRENT_UPDATE=' . $this->update->getRawData(false));
170
171
        $this->__process($this->update);
172
        $this->loadPlugins($this->plugins);
173
    }
174
175
    /**
176
     * Resolve the request on single plugin.
177
     *
178
     * @param Plugin $plugin The plugin to work with
179
     * @param ?Update $update The custom to work with
180
     * @param array $config The configuration of the receiver
181
     * @return void
182
     */
183
    public static function resolveOn(Plugin $plugin, Update $update = null, array $config = []): void
0 ignored issues
show
Unused Code introduced by
The parameter $update is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

183
    public static function resolveOn(Plugin $plugin, /** @scrutinizer ignore-unused */ Update $update = null, array $config = []): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $plugin is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

183
    public static function resolveOn(/** @scrutinizer ignore-unused */ Plugin $plugin, Update $update = null, array $config = []): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $config is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

183
    public static function resolveOn(Plugin $plugin, Update $update = null, /** @scrutinizer ignore-unused */ array $config = []): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
184
    {
185
        // TODO: Implement resolveOn() method.
186
    }
187
188
    /**
189
     * Update the configuration
190
     *
191
     * @param array $configuration
192
     * @return void
193
     */
194
    public function updateConfiguration(array $configuration): void
195
    {
196
        $this->config = array_merge($this->config, $configuration);
197
    }
198
199
    /**
200
     * Stop the spreader process
201
     *
202
     * @return void
203
     */
204
    public function stop(): void
205
    {
206
        $this->active_spreader = false;
207
    }
208
209
}