1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* This file is part of the TelegramBot package. |
4
|
|
|
* |
5
|
|
|
* (c) Avtandil Kikabidze aka LONGMAN <[email protected]> |
6
|
|
|
* |
7
|
|
|
* For the full copyright and license information, please view the LICENSE |
8
|
|
|
* file that was distributed with this source code. |
9
|
|
|
*/ |
10
|
|
|
|
11
|
|
|
namespace Longman\TelegramBot\Entities; |
12
|
|
|
|
13
|
|
|
use Exception; |
14
|
|
|
use Longman\TelegramBot\Entities\InlineQuery\InlineEntity; |
15
|
|
|
use ReflectionObject; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Class Entity |
19
|
|
|
* |
20
|
|
|
* This is the base class for all entities. |
21
|
|
|
*/ |
22
|
|
|
abstract class Entity |
23
|
|
|
{ |
24
|
|
|
/** |
25
|
|
|
* @var string |
26
|
|
|
*/ |
27
|
|
|
protected $bot_name; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* Get bot name |
31
|
|
|
* |
32
|
|
|
* @return string |
33
|
|
|
*/ |
34
|
|
|
public function getBotName() |
35
|
|
|
{ |
36
|
|
|
return $this->bot_name; |
37
|
|
|
} |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* Entity constructor. |
41
|
|
|
* |
42
|
|
|
* @todo Get rid of the $bot_name, it shouldn't be here! |
43
|
|
|
* |
44
|
|
|
* @param $data |
45
|
|
|
* @param string $bot_name |
46
|
|
|
* |
47
|
|
|
* @throws \Longman\TelegramBot\Exception\TelegramException |
48
|
|
|
*/ |
49
|
58 |
|
public function __construct($data, $bot_name = '') |
50
|
|
|
{ |
51
|
58 |
|
$this->assignMemberVariables($data); |
52
|
58 |
|
$this->validate(); |
53
|
49 |
|
$this->bot_name = $bot_name; |
54
|
49 |
|
} |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Perform to json |
58
|
|
|
* |
59
|
|
|
* @return string |
60
|
|
|
*/ |
61
|
1 |
|
public function toJson() |
62
|
|
|
{ |
63
|
1 |
|
return json_encode($this->reflect($this)); |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* Reflect |
68
|
|
|
* |
69
|
|
|
* @param null $object |
70
|
|
|
* |
71
|
|
|
* @return array |
72
|
|
|
*/ |
73
|
1 |
|
public function reflect($object = null) |
74
|
|
|
{ |
75
|
1 |
|
if ($object === null) { |
76
|
|
|
$object = $this; |
77
|
|
|
} |
78
|
|
|
|
79
|
1 |
|
$reflection = new ReflectionObject($object); |
80
|
1 |
|
$properties = $reflection->getProperties(); |
81
|
|
|
|
82
|
1 |
|
$fields = []; |
83
|
|
|
|
84
|
1 |
|
foreach ($properties as $property) { |
85
|
1 |
|
$name = $property->getName(); |
86
|
1 |
|
if ($name === 'bot_name') { |
87
|
1 |
|
continue; |
88
|
|
|
} |
89
|
|
|
|
90
|
1 |
|
if (!$property->isPrivate()) { |
91
|
1 |
|
$array_of_obj = false; |
92
|
1 |
|
$array_of_array_obj = false; |
93
|
1 |
|
if (is_array($object->$name)) { |
94
|
1 |
|
$array_of_obj = true; |
95
|
1 |
|
$array_of_array_obj = true; |
96
|
1 |
|
foreach ($object->$name as $elm) { |
97
|
1 |
|
if (!is_object($elm)) { |
98
|
|
|
//echo $name . " not array of object \n"; |
|
|
|
|
99
|
1 |
|
$array_of_obj = false; |
100
|
|
|
//break; |
101
|
|
|
} |
102
|
1 |
|
if (is_array($elm)) { |
103
|
1 |
|
foreach ($elm as $more_net) { |
104
|
1 |
|
if (!is_object($more_net)) { |
105
|
1 |
|
$array_of_array_obj = false; |
106
|
|
|
} |
107
|
|
|
} |
108
|
|
|
} |
109
|
|
|
} |
110
|
|
|
} |
111
|
|
|
|
112
|
1 |
|
if (is_object($object->$name)) { |
113
|
|
|
$fields[$name] = $this->reflect($object->$name); |
114
|
1 |
|
} elseif ($array_of_obj) { |
115
|
|
|
foreach ($object->$name as $elm) { |
116
|
|
|
$fields[$name][] = $this->reflect($elm); |
117
|
|
|
} |
118
|
1 |
|
} elseif ($array_of_array_obj) { |
119
|
|
|
foreach ($object->$name as $elm) { |
120
|
|
|
$temp = null; |
121
|
|
|
if (!is_array($elm) && !is_object($elm)) { |
122
|
|
|
continue; |
123
|
|
|
} |
124
|
|
|
foreach ($elm as $obj) { |
125
|
|
|
$temp[] = $this->reflect($obj); |
126
|
|
|
} |
127
|
|
|
$fields[$name][] = $temp; |
128
|
|
|
} |
129
|
|
|
} else { |
130
|
1 |
|
$property->setAccessible(true); |
131
|
1 |
|
$value = $property->getValue($object); |
132
|
1 |
|
if (null === $value) { |
133
|
|
|
continue; |
134
|
|
|
} |
135
|
1 |
|
$fields[$name] = $value; |
136
|
|
|
} |
137
|
|
|
} |
138
|
|
|
} |
139
|
|
|
|
140
|
1 |
|
return $fields; |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
/** |
144
|
|
|
* Perform to string |
145
|
|
|
* |
146
|
|
|
* @return string |
147
|
|
|
*/ |
148
|
|
|
public function __toString() |
149
|
|
|
{ |
150
|
|
|
return $this->toJson(); |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
/** |
154
|
|
|
* Helper to set member variables |
155
|
|
|
* |
156
|
|
|
* @param array $data |
157
|
|
|
*/ |
158
|
58 |
|
protected function assignMemberVariables(array $data) |
159
|
|
|
{ |
160
|
58 |
|
foreach ($data as $key => $value) { |
161
|
56 |
|
$this->$key = $value; |
162
|
|
|
} |
163
|
58 |
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* Get the list of the properties that are themselves Entities |
167
|
|
|
* |
168
|
|
|
* @return array |
169
|
|
|
*/ |
170
|
36 |
|
protected function subEntities() |
171
|
|
|
{ |
172
|
36 |
|
return []; |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
/** |
176
|
|
|
* Perform any special entity validation |
177
|
|
|
* |
178
|
|
|
* @throws \Longman\TelegramBot\Exception\TelegramException |
179
|
|
|
*/ |
180
|
31 |
|
protected function validate() |
181
|
|
|
{ |
182
|
31 |
|
} |
183
|
|
|
|
184
|
|
|
/** |
185
|
|
|
* Get a property from the current Entity |
186
|
|
|
* |
187
|
|
|
* @param mixed $property |
188
|
|
|
* @param mixed $default |
189
|
|
|
* |
190
|
|
|
* @return mixed |
191
|
|
|
*/ |
192
|
53 |
|
public function getProperty($property, $default = null) |
193
|
|
|
{ |
194
|
53 |
|
if (isset($this->$property)) { |
195
|
51 |
|
return $this->$property; |
196
|
|
|
} |
197
|
|
|
|
198
|
37 |
|
return $default; |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
/** |
202
|
|
|
* Return the variable for the called getter or magically set properties dynamically. |
203
|
|
|
* |
204
|
|
|
* @param $method |
205
|
|
|
* @param $args |
206
|
|
|
* |
207
|
|
|
* @return mixed|null |
208
|
|
|
*/ |
209
|
39 |
|
public function __call($method, $args) |
210
|
|
|
{ |
211
|
|
|
//Convert method to snake_case (which is the name of the property) |
212
|
39 |
|
$property_name = ltrim(strtolower(preg_replace('/[A-Z]/', '_$0', substr($method, 3))), '_'); |
213
|
|
|
|
214
|
39 |
|
$action = substr($method, 0, 3); |
215
|
39 |
|
if ($action === 'get') { |
216
|
39 |
|
$property = $this->getProperty($property_name); |
217
|
|
|
|
218
|
39 |
|
if ($property !== null) { |
219
|
|
|
//Get all sub-Entities of the current Entity |
220
|
39 |
|
$sub_entities = $this->subEntities(); |
221
|
|
|
|
222
|
39 |
|
if (isset($sub_entities[$property_name])) { |
223
|
15 |
|
return new $sub_entities[$property_name]($property); |
224
|
|
|
} |
225
|
|
|
|
226
|
38 |
|
return $property; |
227
|
|
|
} |
228
|
3 |
|
} elseif ($action === 'set') { |
229
|
|
|
// Limit setters to specific classes. |
230
|
3 |
|
if ($this instanceof InlineEntity || $this instanceof Keyboard || $this instanceof KeyboardButton) { |
231
|
3 |
|
$this->$property_name = $args[0]; |
232
|
|
|
|
233
|
3 |
|
return $this; |
234
|
|
|
} |
235
|
|
|
} |
236
|
|
|
|
237
|
23 |
|
return null; |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
/** |
241
|
|
|
* Return an array of nice objects from an array of object arrays |
242
|
|
|
* |
243
|
|
|
* This method is used to generate pretty object arrays |
244
|
|
|
* mainly for PhotoSize and Entities object arrays. |
245
|
|
|
* |
246
|
|
|
* @param string $class |
247
|
|
|
* @param string $property |
248
|
|
|
* |
249
|
|
|
* @return array |
250
|
|
|
*/ |
251
|
6 |
|
protected function makePrettyObjectArray($class, $property) |
252
|
|
|
{ |
253
|
6 |
|
$new_objects = []; |
254
|
|
|
|
255
|
|
|
try { |
256
|
6 |
|
if ($objects = $this->getProperty($property)) { |
257
|
|
|
foreach ($objects as $object) { |
258
|
|
|
if (!empty($object)) { |
259
|
6 |
|
$new_objects[] = new $class($object); |
260
|
|
|
} |
261
|
|
|
} |
262
|
|
|
} |
263
|
|
|
} catch (Exception $e) { |
264
|
|
|
$new_objects = []; |
265
|
|
|
} |
266
|
|
|
|
267
|
6 |
|
return $new_objects; |
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
/** |
271
|
|
|
* Escape markdown special characters |
272
|
|
|
* |
273
|
|
|
* @param string $string |
274
|
|
|
* |
275
|
|
|
* @return string |
276
|
|
|
*/ |
277
|
1 |
|
public function escapeMarkdown($string) |
278
|
|
|
{ |
279
|
1 |
|
return str_replace( |
280
|
1 |
|
['[', '`', '*', '_',], |
281
|
1 |
|
['\[', '\`', '\*', '\_',], |
282
|
|
|
$string |
283
|
|
|
); |
284
|
|
|
} |
285
|
|
|
|
286
|
|
|
/** |
287
|
|
|
* Try to mention the user |
288
|
|
|
* |
289
|
|
|
* Mention the user with the username otherwise print first and last name |
290
|
|
|
* if the $escape_markdown argument is true special characters are escaped from the output |
291
|
|
|
* |
292
|
|
|
* @param bool $escape_markdown |
293
|
|
|
* |
294
|
|
|
* @return string|null |
295
|
|
|
*/ |
296
|
3 |
|
public function tryMention($escape_markdown = false) |
297
|
|
|
{ |
298
|
|
|
//TryMention only makes sense for the User and Chat entity. |
299
|
3 |
|
if (!($this instanceof User || $this instanceof Chat)) { |
300
|
|
|
return null; |
301
|
|
|
} |
302
|
|
|
|
303
|
|
|
//Try with the username first... |
304
|
3 |
|
$username = $this->getProperty('username'); |
305
|
3 |
|
if ($username !== null) { |
306
|
3 |
|
if ($escape_markdown) { |
307
|
1 |
|
$username = $this->escapeMarkdown($username); |
308
|
|
|
} |
309
|
|
|
|
310
|
3 |
|
return '@' . $username; |
311
|
|
|
} |
312
|
|
|
|
313
|
|
|
//...otherwise try with the names |
314
|
3 |
|
$name = $this->getProperty('first_name'); |
315
|
3 |
|
$last_name = $this->getProperty('last_name'); |
316
|
3 |
|
if ($last_name !== null) { |
317
|
3 |
|
$name .= ' ' . $last_name; |
318
|
|
|
} |
319
|
|
|
|
320
|
3 |
|
if ($escape_markdown) { |
321
|
1 |
|
$name = $this->escapeMarkdown($name); |
322
|
|
|
} |
323
|
|
|
|
324
|
3 |
|
return $name; |
325
|
|
|
} |
326
|
|
|
} |
327
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.