Passed
Push — master ( 7ecda6...2093cf )
by Armando
04:22 queued 02:31
created

Entity::makePrettyObjectArray()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 5.2742

Importance

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