Test Failed
Push — master ( cc6cb5...f69508 )
by Shahrad
10:37
created

UpdateHandler::loadFileOfEnv()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
dl 0
loc 3
c 1
b 0
f 0
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
namespace TelegramBot;
4
5
use TelegramBot\Entities\Update;
6
use TelegramBot\Exception\InvalidBotTokenException;
7
use TelegramBot\Util\DotEnv;
8
9
/**
10
 * UpdateHandler class
11
 *
12
 * @link    https://github.com/telegram-bot-php/core
13
 * @author  Shahrad Elahi (https://github.com/shahradelahi)
14
 * @license https://github.com/telegram-bot-php/core/blob/master/LICENSE (MIT License)
15
 */
16
abstract class UpdateHandler extends Telegram
17
{
18
19
    /**
20
     * @var ?Update
21
     */
22
    protected ?Update $update;
23
24
    /**
25
     * @var array<Plugin>
26
     */
27
    private array $plugins = [];
28
29
    /**
30
     * @var bool
31
     */
32
    private bool $isActive = false;
33
34
    /**
35
     * The default configuration of the webhook.
36
     *
37
     * @var array
38
     */
39
    private array $config = [
40
        'autoload_env_file' => false,
41
        'env_file_path' => null,
42
    ];
43
44
    /**
45
     * Webhook constructor.
46
     *
47
     * @param string $api_key The API key of the bot. Leave it blank for autoload from .env file.
48
     */
49
    public function __construct(string $api_key = '')
50
    {
51
        parent::__construct($api_key);
52
53
        if (!Telegram::validateToken(self::getApiKey())) {
54
            throw new InvalidBotTokenException();
55
        }
56
    }
57
58
    /**
59
     * Initialize the receiver.
60
     *
61
     * @return void
62
     */
63
    public function init(): void
64
    {
65
        $this->config['env_file_path'] = $_SERVER['DOCUMENT_ROOT'] . '/.env';
66
    }
67
68
    /**
69
     * Add a plugin to the receiver
70
     *
71
     * @param array<Plugin> $plugins
72
     */
73
    public function addPlugin(array $plugins): void
74
    {
75
        foreach ($plugins as $plugin) {
76
            if (!is_subclass_of($plugin, Plugin::class)) {
77
                throw new \RuntimeException(
78
                    sprintf('The plugin %s must be an instance of %s', get_class($plugin), Plugin::class)
79
                );
80
            }
81
            $this->plugins[] = $plugin;
82
        }
83
    }
84
85
    /**
86
     * Match the message to the plugins
87
     *
88
     * @param ?Update $update The update to match
89
     * @return void
90
     */
91
    public function loadPlugins(Update $update = null): void
92
    {
93
        $update = $update ?? ($this->update ?? Telegram::getUpdate());
94
        $this->loadPluginsWith($this->plugins, $update);
0 ignored issues
show
Bug introduced by
It seems like $update can also be of type false; however, parameter $update of TelegramBot\UpdateHandler::loadPluginsWith() does only seem to accept TelegramBot\Entities\Update|null, 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

94
        $this->loadPluginsWith($this->plugins, /** @scrutinizer ignore-type */ $update);
Loading history...
95
    }
96
97
    /**
98
     * Match the update with the given plugins
99
     *
100
     * @param array<Plugin> $plugins
101
     * @param ?Update $update The update to match
102
     * @return void
103
     */
104
    public function loadPluginsWith(array $plugins, Update $update = null): void
105
    {
106
        $update = $update ?? ($this->update ?? Telegram::getUpdate());
107
108
        foreach ($plugins as $plugin) {
109
            if (!is_subclass_of($plugin, Plugin::class)) {
110
                throw new \InvalidArgumentException(
111
                    sprintf('The plugin %s must be an instance of %s', get_class($plugin), Plugin::class)
112
                );
113
            }
114
        }
115
116
        if (!$update instanceof Update) {
117
            throw new \InvalidArgumentException(sprintf(
118
                'The update must be an instance of %s',
119
                Update::class
120
            ));
121
        }
122
123
        $this->spreadUpdateWith($update, $plugins);
124
    }
125
126
    /**
127
     * This function will get update and spread it to the plugins
128
     *
129
     * @param Update $update
130
     * @param array<Plugin> $plugins
131
     * @return void
132
     */
133
    private function spreadUpdateWith(Update $update, array $plugins): void
134
    {
135
        $this->isActive = true;
136
137
        foreach ($plugins as $plugin) {
138
            /** @var Plugin $plugin */
139
            (new $plugin())->__execute($this, $update);
140
            if ($this->isActive === false) break;
141
        }
142
143
        $this->isActive = false;
144
    }
145
146
    /**
147
     * Load the environment's
148
     *
149
     * @param string $path
150
     * @retrun void
151
     */
152
    public function loadFileOfEnv(string $path): void
153
    {
154
        DotEnv::load($path);
155
    }
156
157
    /**
158
     * Resolve the request.
159
     *
160
     * @param ?Update $update The custom to work with
161
     * @param array $config The configuration of the receiver
162
     *
163
     * @retrun void
164
     */
165
    public function resolve(Update $update = null, array $config = []): void
166
    {
167
        if (!method_exists($this, '__process')) {
168
            throw new \RuntimeException('The method __process does not exist');
169
        }
170
171
        if (is_array($config)) $this->updateConfiguration($config);
0 ignored issues
show
introduced by
The condition is_array($config) is always true.
Loading history...
172
173
        if (!empty($update)) $this->update = $update;
174
        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...
175
176
        if (empty($this->update)) {
177
            TelegramLog::error(
178
                'The update is empty, the request is not processed'
179
            );
180
            return;
181
        }
182
183
        putenv('TG_CURRENT_UPDATE=' . $this->update->getRawData(false));
184
185
        $this->__process($this->update);
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
     * Use this method on the webhook class to get the updates
201
     *
202
     * @param Update $update
203
     * @return void
204
     */
205
    abstract public function __process(Update $update): void;
206
207
    /**
208
     * Stop the speeding process
209
     *
210
     * @return void
211
     */
212
    public function stop(): void
213
    {
214
        $this->isActive = false;
215
    }
216
217
}