Passed
Push — master ( 78024d...fb0f34 )
by Armando
02:41
created

Entity::escapeMarkdownV2()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 1
dl 0
loc 6
ccs 4
cts 4
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 78
    public function __construct($data, $bot_username = '')
39
    {
40
        //Make sure we're not raw_data inception-ing
41 78
        if (array_key_exists('raw_data', $data)) {
42 11
            if ($data['raw_data'] === null) {
43 11
                unset($data['raw_data']);
44
            }
45
        } else {
46 72
            $data['raw_data'] = $data;
47
        }
48
49 78
        $data['bot_username'] = $bot_username;
50 78
        $this->assignMemberVariables($data);
51 78
        $this->validate();
52 69
    }
53
54
    /**
55
     * Perform to json
56
     *
57
     * @return string
58
     */
59 1
    public function toJson()
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 78
    protected function assignMemberVariables(array $data)
80
    {
81 78
        foreach ($data as $key => $value) {
82 78
            $this->$key = $value;
83
        }
84 78
    }
85
86
    /**
87
     * Get the list of the properties that are themselves Entities
88
     *
89
     * @return array
90
     */
91 48
    protected function subEntities()
92
    {
93 48
        return [];
94
    }
95
96
    /**
97
     * Perform any special entity validation
98
     */
99 55
    protected function validate()
100
    {
101 55
    }
102
103
    /**
104
     * Get a property from the current Entity
105
     *
106
     * @param mixed $property
107
     * @param mixed $default
108
     *
109
     * @return mixed
110
     */
111 72
    public function getProperty($property, $default = null)
112
    {
113 72
        if (isset($this->$property)) {
114 67
            return $this->$property;
115
        }
116
117 44
        return $default;
118
    }
119
120
    /**
121
     * Return the variable for the called getter or magically set properties dynamically.
122
     *
123
     * @param $method
124
     * @param $args
125
     *
126
     * @return mixed|null
127
     */
128 59
    public function __call($method, $args)
129
    {
130
        //Convert method to snake_case (which is the name of the property)
131 59
        $property_name = mb_strtolower(ltrim(preg_replace('/[A-Z]/', '_$0', substr($method, 3)), '_'));
132
133 59
        $action = substr($method, 0, 3);
134 59
        if ($action === 'get') {
135 59
            $property = $this->getProperty($property_name);
136
137 59
            if ($property !== null) {
138
                //Get all sub-Entities of the current Entity
139 56
                $sub_entities = $this->subEntities();
140
141 56
                if (isset($sub_entities[$property_name])) {
142 12
                    $class = $sub_entities[$property_name];
143
144 12
                    if (is_array($class)) {
145 1
                        return $this->makePrettyObjectArray(reset($class), $property_name);
146
                    }
147
148 11
                    return new $class($property, $this->getProperty('bot_username'));
149
                }
150
151 58
                return $property;
152
            }
153 3
        } elseif ($action === 'set') {
154
            // Limit setters to specific classes.
155 3
            if ($this instanceof InlineEntity || $this instanceof InputMedia || $this instanceof Keyboard || $this instanceof KeyboardButton) {
156 3
                $this->$property_name = $args[0];
157
158 3
                return $this;
159
            }
160
        }
161
162 30
        return null;
163
    }
164
165
    /**
166
     * Return an array of nice objects from an array of object arrays
167
     *
168
     * This method is used to generate pretty object arrays
169
     * mainly for PhotoSize and Entities object arrays.
170
     *
171
     * @param string $class
172
     * @param string $property
173
     *
174
     * @return array
175
     */
176 1
    protected function makePrettyObjectArray($class, $property)
177
    {
178 1
        $new_objects = [];
179
180
        try {
181 1
            if ($objects = $this->getProperty($property)) {
182 1
                foreach ($objects as $object) {
183 1
                    if (!empty($object)) {
184 1
                        $new_objects[] = new $class($object);
185
                    }
186
                }
187
            }
188
        } catch (Exception $e) {
189
            $new_objects = [];
190
        }
191
192 1
        return $new_objects;
193
    }
194
195
    /**
196
     * Escape markdown (v1) special characters
197
     *
198
     * @see https://core.telegram.org/bots/api#markdown-style
199
     *
200
     * @param string $string
201
     *
202
     * @return string
203
     */
204 2
    public static function escapeMarkdown($string)
205
    {
206 2
        return str_replace(
207 2
            ['[', '`', '*', '_',],
208 2
            ['\[', '\`', '\*', '\_',],
209
            $string
210
        );
211
    }
212
213
    /**
214
     * Escape markdown (v2) special characters
215
     *
216
     * @see https://core.telegram.org/bots/api#markdownv2-style
217
     *
218
     * @param string $string
219
     *
220
     * @return string
221
     */
222 1
    public static function escapeMarkdownV2($string)
223
    {
224 1
        return str_replace(
225 1
            ['_', '*', '[', ']', '(', ')', '~', '`', '>', '#', '+', '-', '=', '|', '{', '}', '.', '!'],
226 1
            ['\_', '\*', '\[', '\]', '\(', '\)', '\~', '\`', '\>', '\#', '\+', '\-', '\=', '\|', '\{', '\}', '\.', '\!'],
227
            $string
228
        );
229
    }
230
231
    /**
232
     * Try to mention the user
233
     *
234
     * Mention the user with the username otherwise print first and last name
235
     * if the $escape_markdown argument is true special characters are escaped from the output
236
     *
237
     * @todo What about MarkdownV2?
238
     *
239
     * @param bool $escape_markdown
240
     *
241
     * @return string|null
242
     */
243 3
    public function tryMention($escape_markdown = false)
244
    {
245
        //TryMention only makes sense for the User and Chat entity.
246 3
        if (!($this instanceof User || $this instanceof Chat)) {
247
            return null;
248
        }
249
250
        //Try with the username first...
251 3
        $name        = $this->getProperty('username');
252 3
        $is_username = $name !== null;
253
254 3
        if ($name === null) {
255
            //...otherwise try with the names.
256 3
            $name      = $this->getProperty('first_name');
257 3
            $last_name = $this->getProperty('last_name');
258 3
            if ($last_name !== null) {
259 3
                $name .= ' ' . $last_name;
260
            }
261
        }
262
263 3
        if ($escape_markdown) {
264 1
            $name = self::escapeMarkdown($name);
265
        }
266
267 3
        return ($is_username ? '@' : '') . $name;
268
    }
269
}
270