Passed
Push — master ( 163ca3...6d62ea )
by Armando
01:57
created

Entity::makePrettyObjectArray()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

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

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

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