Passed
Pull Request — develop (#1229)
by
unknown
02:50
created

Entity::toJson()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * This file is part of the TelegramBot package.
5
 *
6
 * (c) Avtandil Kikabidze aka LONGMAN <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Longman\TelegramBot\Entities;
13
14
use Exception;
15
use Longman\TelegramBot\Entities\InlineQuery\InlineEntity;
16
use Longman\TelegramBot\Entities\InputMedia\InputMedia;
17
18
/**
19
 * Class Entity
20
 *
21
 * This is the base class for all entities.
22
 *
23
 * @link https://core.telegram.org/bots/api#available-types
24
 *
25
 * @method array  getRawData()     Get the raw data passed to this entity
26
 * @method string getBotUsername() Return the bot name passed to this entity
27
 */
28
abstract class Entity
29
{
30
    /**
31
     * Entity constructor.
32
     *
33
     * @todo Get rid of the $bot_username, it shouldn't be here!
34
     *
35
     * @param array  $data
36
     * @param string $bot_username
37
     */
38 79
    public function __construct(array $data, string $bot_username = '')
39
    {
40
        //Make sure we're not raw_data inception-ing
41 79
        if (array_key_exists('raw_data', $data)) {
42 11
            if ($data['raw_data'] === null) {
43 11
                unset($data['raw_data']);
44
            }
45
        } else {
46 73
            $data['raw_data'] = $data;
47
        }
48
49 79
        $data['bot_username'] = $bot_username;
50 79
        $this->assignMemberVariables($data);
51 79
        $this->validate();
52 71
    }
53
54
    /**
55
     * Perform to json
56
     *
57
     * @return string
58
     */
59 1
    public function toJson(): string
60
    {
61 1
        return json_encode($this->getRawData());
62
    }
63
64
    /**
65
     * Perform to string
66
     *
67
     * @return string
68
     */
69
    public function __toString()
70
    {
71
        return $this->toJson();
72
    }
73
74
    /**
75
     * Helper to set member variables
76
     *
77
     * @param array $data
78
     */
79 79
    protected function assignMemberVariables(array $data): void
80
    {
81 79
        foreach ($data as $key => $value) {
82 79
            $this->$key = $value;
83
        }
84 79
    }
85
86
    /**
87
     * Get the list of the properties that are themselves Entities
88
     *
89
     * @return array
90
     */
91 49
    protected function subEntities(): array
92
    {
93 49
        return [];
94
    }
95
96
    /**
97
     * Perform any special entity validation
98
     */
99 57
    protected function validate(): void
100
    {
101 57
    }
102
103
    /**
104
     * Get a property from the current Entity
105
     *
106
     * @param string $property
107
     * @param mixed  $default
108
     *
109
     * @return mixed
110
     */
111 73
    public function getProperty(string $property, $default = null)
112
    {
113 73
        return $this->$property ?? $default;
114
    }
115
116
    /**
117
     * Return the variable for the called getter or magically set properties dynamically.
118
     *
119
     * @param $method
120
     * @param $args
121
     *
122
     * @return mixed|null
123
     */
124 60
    public function __call($method, $args)
125
    {
126
        //Convert method to snake_case (which is the name of the property)
127 60
        $property_name = mb_strtolower(ltrim(preg_replace('/[A-Z]/', '_$0', substr($method, 3)), '_'));
128
129 60
        $action = substr($method, 0, 3);
130 60
        if ($action === 'get') {
131 60
            $property = $this->getProperty($property_name);
132
133 60
            if ($property !== null) {
134
                //Get all sub-Entities of the current Entity
135 57
                $sub_entities = $this->subEntities();
136
137 57
                if (isset($sub_entities[$property_name])) {
138 12
                    $class = $sub_entities[$property_name];
139
140 12
                    if (is_array($class)) {
141 1
                        return $this->makePrettyObjectArray(reset($class), $property_name);
142
                    }
143
144 11
                    return Factory::resolveEntityClass($class, $property, $this->getProperty('bot_username'));
0 ignored issues
show
Bug introduced by
It seems like $this->getProperty('bot_username') can also be of type null; however, parameter $bot_username of Longman\TelegramBot\Enti...y::resolveEntityClass() 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

144
                    return Factory::resolveEntityClass($class, $property, /** @scrutinizer ignore-type */ $this->getProperty('bot_username'));
Loading history...
145
                }
146
147 59
                return $property;
148
            }
149 3
        } elseif ($action === 'set') {
150
            // Limit setters to specific classes.
151 3
            if ($this instanceof InlineEntity || $this instanceof InputMedia || $this instanceof Keyboard || $this instanceof KeyboardButton) {
152 3
                $this->$property_name = $args[0];
153
154 3
                return $this;
155
            }
156
        }
157
158 30
        return null;
159
    }
160
161
    /**
162
     * Return an array of nice objects from an array of object arrays
163
     *
164
     * This method is used to generate pretty object arrays
165
     * mainly for PhotoSize and Entities object arrays.
166
     *
167
     * @param string $class
168
     * @param string $property
169
     *
170
     * @return array
171
     */
172 1
    protected function makePrettyObjectArray(string $class, string $property): array
173
    {
174 1
        $new_objects = [];
175
176 1
        $bot_username = $this->getProperty('bot_username');
177
        try {
178 1
            if ($objects = $this->getProperty($property)) {
179 1
                foreach ($objects as $object) {
180 1
                    if (!empty($object)) {
181 1
                        $new_objects[] = Factory::resolveEntityClass($class, $object, $bot_username);
0 ignored issues
show
Bug introduced by
It seems like $bot_username can also be of type null; however, parameter $bot_username of Longman\TelegramBot\Enti...y::resolveEntityClass() 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

181
                        $new_objects[] = Factory::resolveEntityClass($class, $object, /** @scrutinizer ignore-type */ $bot_username);
Loading history...
182
                    }
183
                }
184
            }
185
        } catch (Exception $e) {
186
            $new_objects = [];
187
        }
188
189 1
        return $new_objects;
190
    }
191
192
    /**
193
     * Escape markdown (v1) special characters
194
     *
195
     * @see https://core.telegram.org/bots/api#markdown-style
196
     *
197
     * @param string $string
198
     *
199
     * @return string
200
     */
201 2
    public static function escapeMarkdown(string $string): string
202
    {
203 2
        return str_replace(
204 2
            ['[', '`', '*', '_',],
205 2
            ['\[', '\`', '\*', '\_',],
206
            $string
207
        );
208
    }
209
210
    /**
211
     * Escape markdown (v2) special characters
212
     *
213
     * @see https://core.telegram.org/bots/api#markdownv2-style
214
     *
215
     * @param string $string
216
     *
217
     * @return string
218
     */
219 1
    public static function escapeMarkdownV2(string $string): string
220
    {
221 1
        return str_replace(
222 1
            ['_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!'],
223 1
            ['\_', '\*', '\[', '\]', '\(', '\)', '\~', '\`', '\>', '\#', '\+', '\-', '\=', '\|', '\{', '\}', '\.', '\!'],
224
            $string
225
        );
226
    }
227
228
    /**
229
     * Try to mention the user
230
     *
231
     * Mention the user with the username otherwise print first and last name
232
     * if the $escape_markdown argument is true special characters are escaped from the output
233
     *
234
     * @todo What about MarkdownV2?
235
     *
236
     * @param bool $escape_markdown
237
     *
238
     * @return string
239
     */
240 3
    public function tryMention($escape_markdown = false): string
241
    {
242
        // TryMention only makes sense for the User and Chat entity.
243 3
        if (!($this instanceof User || $this instanceof Chat)) {
244
            return '';
245
        }
246
247
        //Try with the username first...
248 3
        $name        = $this->getProperty('username');
249 3
        $is_username = $name !== null;
250
251 3
        if ($name === null) {
252
            //...otherwise try with the names.
253 3
            $name      = $this->getProperty('first_name');
254 3
            $last_name = $this->getProperty('last_name');
255 3
            if ($last_name !== null) {
256 3
                $name .= ' ' . $last_name;
257
            }
258
        }
259
260 3
        if ($escape_markdown) {
261 1
            $name = self::escapeMarkdown($name);
262
        }
263
264 3
        return ($is_username ? '@' : '') . $name;
265
    }
266
}
267