1
|
|
|
<?php
|
2
|
|
|
if (! function_exists('mb_lcfirst') && extension_loaded('mbstring')) {
|
3
|
|
|
/**
|
4
|
|
|
* Преобразует первый символ в нижний регистр
|
5
|
|
|
*
|
6
|
|
|
* @param string|array $data строка или массив
|
7
|
|
|
* @param string $charset кодировка, по-умолчанию UTF-8
|
8
|
|
|
* @return mixed
|
9
|
|
|
*/
|
10
|
|
|
function mb_lcfirst($data, $charset = 'UTF-8')
|
11
|
|
|
{
|
12
|
|
|
return for_all($data, function ($el) use ($charset) {
|
13
|
4 |
|
$str = one_space($el);
|
14
|
|
|
|
15
|
4 |
|
return mb_strtolower(mb_substr($str, 0, 1, $charset), $charset) .
|
16
|
4 |
|
mb_substr($str, 1, mb_strlen($str), $charset);
|
17
|
4 |
|
});
|
18
|
|
|
}
|
19
|
|
|
}
|
20
|
|
|
|
21
|
|
|
if (! function_exists('mb_ucfirst') && extension_loaded('mbstring')) {
|
22
|
|
|
/**
|
23
|
|
|
* Преобразует первый символ в верхний регистр
|
24
|
|
|
*
|
25
|
|
|
* @param mixed $data строка или массив
|
26
|
|
|
* @param string $charset кодировка, по-умолчанию UTF-8
|
27
|
|
|
* @return mixed
|
28
|
|
|
*/
|
29
|
|
|
function mb_ucfirst($data, $charset = 'UTF-8')
|
30
|
|
|
{
|
31
|
|
|
return for_all($data, function ($el) use ($charset) {
|
32
|
4 |
|
$str = one_space($el);
|
33
|
|
|
|
34
|
4 |
|
return mb_strtoupper(mb_substr($str, 0, 1, $charset), $charset) .
|
35
|
4 |
|
mb_substr($str, 1, mb_strlen($str), $charset);
|
36
|
4 |
|
});
|
37
|
|
|
}
|
38
|
|
|
}
|
39
|
|
|
|
40
|
|
|
if (! function_exists('one_space')) {
|
41
|
|
|
/**
|
42
|
|
|
* Заменить множественную последовательность пробелов и табуляций на 1 пробел
|
43
|
|
|
*
|
44
|
|
|
* @param mixed $data строка или массив
|
45
|
|
|
* @return mixed
|
46
|
|
|
*/
|
47
|
|
|
function one_space($data)
|
48
|
|
|
{
|
49
|
|
|
return for_all($data, function ($el) {
|
50
|
12 |
|
return preg_replace('/[ \t]+/', ' ', $el);
|
51
|
12 |
|
});
|
52
|
|
|
}
|
53
|
|
|
}
|
54
|
|
|
|
55
|
|
|
if (! function_exists('one_new_line')) {
|
56
|
|
|
/**
|
57
|
|
|
* Заменить множественную последовательность перевода строки на 1 перевод
|
58
|
|
|
*
|
59
|
|
|
* @param mixed $data строка или массив
|
60
|
|
|
* @return mixed
|
61
|
|
|
*/
|
62
|
|
|
function one_new_line($data)
|
63
|
|
|
{
|
64
|
|
|
return for_all($data, function ($el) {
|
65
|
3 |
|
return preg_replace('/(\R)+/', '$1', $el);
|
66
|
3 |
|
});
|
67
|
|
|
}
|
68
|
|
|
}
|
69
|
|
|
|
70
|
|
|
if (! function_exists('full_one_space')) {
|
71
|
|
|
/**
|
72
|
|
|
* Заменить множественную последовательность пробелов, табуляций и переводов строк на 1 пробел
|
73
|
|
|
*
|
74
|
|
|
* @param mixed $data строка или массив
|
75
|
|
|
* @return mixed
|
76
|
|
|
*/
|
77
|
|
|
function full_one_space($data)
|
78
|
|
|
{
|
79
|
|
|
return for_all($data, function ($el) {
|
80
|
3 |
|
return preg_replace('/\s+/', ' ', $el);
|
81
|
3 |
|
});
|
82
|
|
|
}
|
83
|
|
|
}
|
84
|
|
|
|
85
|
|
|
if (! function_exists('e_decode')) {
|
86
|
|
|
/**
|
87
|
|
|
* Декодирование HTML сущностей в строке
|
88
|
|
|
*
|
89
|
|
|
* @param mixed $data строка или массив
|
90
|
|
|
* @param string $charset кодировка
|
91
|
|
|
* @return mixed
|
92
|
|
|
*/
|
93
|
|
|
function e_decode($data, $charset = 'UTF-8')
|
94
|
|
|
{
|
95
|
|
|
return for_all($data, function ($el) use ($charset) {
|
96
|
|
|
return one_space(str_replace("\xC2\xA0", ' ', html_entity_decode($el, ENT_COMPAT, $charset)));
|
97
|
|
|
});
|
98
|
|
|
}
|
99
|
|
|
}
|
100
|
|
|
|
101
|
|
|
if (! function_exists('e')) {
|
102
|
|
|
/**
|
103
|
|
|
* Преобразование всех символов строки в HTML сущности
|
104
|
|
|
*
|
105
|
|
|
* @param mixed $data
|
106
|
|
|
* @param string $charset кодировка
|
107
|
|
|
* @return mixed
|
108
|
|
|
*/
|
109
|
|
|
function e($data, $charset = 'UTF-8')
|
110
|
|
|
{
|
111
|
|
|
return for_all($data, function ($el) use ($charset) {
|
112
|
|
|
return one_space(htmlentities($el, ENT_COMPAT | ENT_SUBSTITUTE, $charset, false));
|
113
|
|
|
});
|
114
|
|
|
}
|
115
|
|
|
}
|
116
|
|
|
|
117
|
|
|
if (! function_exists('camel_case')) {
|
118
|
|
|
/**
|
119
|
|
|
* Преобразовывание строки в CamelCase формат
|
120
|
|
|
*
|
121
|
|
|
* @param string $str обрабатываемая строка
|
122
|
|
|
* @param bool $first Необходимо ли первый символ перевести в верхний регистр
|
123
|
|
|
* @return string
|
124
|
|
|
*/
|
125
|
|
|
function camel_case($str, $first = false)
|
126
|
|
|
{
|
127
|
|
|
return for_all($str, function ($str) use ($first) {
|
128
|
|
|
$str = preg_replace('/[^-_\w\s]/', '', $str);
|
129
|
|
|
$parts = preg_split('/[-_\s]/', $str);
|
130
|
|
|
$out = strtolower(array_shift($parts));
|
|
|
|
|
131
|
|
|
if ($first) {
|
132
|
|
|
$out = ucfirst($out);
|
133
|
|
|
}
|
134
|
|
|
foreach ($parts as $word) {
|
135
|
|
|
$out .= ucfirst(strtolower($word));
|
136
|
|
|
}
|
137
|
|
|
|
138
|
|
|
return $out;
|
139
|
|
|
});
|
140
|
|
|
}
|
141
|
|
|
}
|
142
|
|
|
|
143
|
|
|
if (! function_exists('underscore')) {
|
144
|
|
|
/**
|
145
|
|
|
* Преобразовывание строки в underscore формат
|
146
|
|
|
*
|
147
|
|
|
* @param string $str обрабатываемая строка
|
148
|
|
|
* @return string
|
149
|
|
|
*/
|
150
|
|
|
function underscore($str)
|
151
|
|
|
{
|
152
|
|
|
return for_all($str, function ($str) {
|
153
|
|
|
$str = preg_replace('/[^-_\w\s]/', '', $str);
|
154
|
|
|
$str = preg_replace('/([a-z])([A-Z])/', '$1 $2', $str);
|
155
|
|
|
$str = preg_replace('/[-\s]/', '_', $str);
|
156
|
|
|
|
157
|
|
|
return strtolower($str);
|
158
|
|
|
});
|
159
|
|
|
}
|
160
|
|
|
}
|
161
|
|
|
|
162
|
|
|
if (! function_exists('normalize_name')) {
|
163
|
|
|
/**
|
164
|
|
|
* Нормализация имен
|
165
|
|
|
* Иванов-петров => Иванов-Петров
|
166
|
|
|
*
|
167
|
|
|
* @param string $name обрабатываемая строка
|
168
|
|
|
* @return string
|
169
|
|
|
*/
|
170
|
|
|
function normalize_name($name)
|
171
|
|
|
{
|
172
|
|
|
return for_all($name, function ($name) {
|
173
|
|
|
$name = ucwords(strtolower($name));
|
174
|
|
|
foreach (['-', "'"] as $delimiter) {
|
175
|
|
|
if (strpos($name, $delimiter) !== false) {
|
176
|
|
|
$name = implode($delimiter, array_map('ucfirst', explode($delimiter, $name)));
|
177
|
|
|
}
|
178
|
|
|
}
|
179
|
|
|
|
180
|
|
|
return $name;
|
181
|
|
|
});
|
182
|
|
|
}
|
183
|
|
|
}
|
184
|
|
|
|
185
|
|
|
if (! function_exists('mb_str_replace')) {
|
186
|
|
|
/**
|
187
|
|
|
* Replace all occurrences of the search string with the replacement string.
|
188
|
|
|
*
|
189
|
|
|
* @author Sean Murphy <[email protected]>
|
190
|
|
|
* @copyright Copyright 2012 Sean Murphy. All rights reserved.
|
191
|
|
|
* @license http://creativecommons.org/publicdomain/zero/1.0/
|
192
|
|
|
* @see https://gist.github.com/sgmurphy/3098836
|
193
|
|
|
* @link http://php.net/manual/function.str-replace.php
|
194
|
|
|
*
|
195
|
|
|
* @param mixed $search искомая строка
|
196
|
|
|
* @param mixed $replace строка на которую необходимо заменить искомое
|
197
|
|
|
* @param mixed $subject строка в которой производится замена
|
198
|
|
|
* @param int $count число произведенных замен в строке
|
199
|
|
|
* @return string
|
200
|
|
|
*/
|
201
|
|
|
function mb_str_replace($search, $replace, $subject, &$count = 0)
|
202
|
|
|
{
|
203
|
|
|
mb_regex_encoding('utf-8');
|
204
|
|
|
if (! is_array($subject)) {
|
205
|
|
|
// Normalize $search and $replace so they are both arrays of the same length
|
206
|
|
|
$searches = is_array($search) ? array_values($search) : [$search];
|
207
|
|
|
$replacements = is_array($replace) ? array_values($replace) : [$replace];
|
208
|
|
|
$replacements = array_pad($replacements, count($searches), '');
|
209
|
|
|
|
210
|
|
|
foreach ($searches as $key => $search) {
|
|
|
|
|
211
|
|
|
$parts = mb_split(preg_quote($search), $subject);
|
212
|
|
|
$count += count($parts) - 1;
|
213
|
|
|
$subject = implode($replacements[$key], $parts);
|
214
|
|
|
}
|
215
|
|
|
} else {
|
216
|
|
|
// Call mb_str_replace for each subject in array, recursively
|
217
|
|
|
foreach ($subject as $key => $value) {
|
218
|
|
|
$subject[$key] = mb_str_replace($search, $replace, $value, $count);
|
219
|
|
|
}
|
220
|
|
|
}
|
221
|
|
|
|
222
|
|
|
return $subject;
|
|
|
|
|
223
|
|
|
}
|
224
|
|
|
}
|
225
|
|
|
|
226
|
|
|
if (! function_exists('mb_trim_word')) {
|
227
|
|
|
/**
|
228
|
|
|
* Обрезание текста по длине с поиском последнего полностью вмещающегося слова и удалением лишних крайних знаков пунктуации.
|
229
|
|
|
*
|
230
|
|
|
* @param string $html HTML текст
|
231
|
|
|
* @param integer $len максимальная длина строки
|
232
|
|
|
* @param string $encoding кодировка
|
233
|
|
|
* @return string
|
234
|
|
|
*/
|
235
|
|
|
function mb_trim_word($html, $len, $encoding = 'UTF-8')
|
236
|
|
|
{
|
237
|
|
|
$text = trim(preg_replace('|\s+|', ' ', strip_tags($html)));
|
238
|
|
|
$text = mb_substr($text, 0, $len + 1, $encoding);
|
239
|
|
|
if (mb_substr($text, -1, null, $encoding) == ' ') {
|
240
|
|
|
$out = trim($text);
|
241
|
|
|
} else {
|
242
|
|
|
$out = mb_substr($text, 0, mb_strripos($text, ' ', null, $encoding), $encoding);
|
243
|
|
|
}
|
244
|
|
|
|
245
|
|
|
return preg_replace("/(([\.,\-:!?;\s])|(&\w+;))+$/ui", "", $out);
|
246
|
|
|
}
|
247
|
|
|
}
|
248
|
|
|
|
249
|
|
|
if (! function_exists('strip_tags_smart')) {
|
250
|
|
|
/**
|
251
|
|
|
* Более продвинутый аналог strip_tags() для корректного вырезания тагов из html кода.
|
252
|
|
|
* Функция strip_tags(), в зависимости от контекста, может работать не корректно.
|
253
|
|
|
* Возможности:
|
254
|
|
|
* - корректно обрабатываются вхождения типа "a < b > c"
|
255
|
|
|
* - корректно обрабатывается "грязный" html, когда в значениях атрибутов тагов могут встречаться символы < >
|
256
|
|
|
* - корректно обрабатывается разбитый html
|
257
|
|
|
* - вырезаются комментарии, скрипты, стили, PHP, Perl, ASP код, MS Word таги, CDATA
|
258
|
|
|
* - автоматически форматируется текст, если он содержит html код
|
259
|
|
|
* - защита от подделок типа: "<<fake>script>alert('hi')</</fake>script>"
|
260
|
|
|
*
|
261
|
|
|
* @param array|string $s
|
262
|
|
|
* @param array $allowable_tags Массив тагов, которые не будут вырезаны
|
263
|
|
|
* Пример: 'b' -- таг останется с атрибутами, '<b>' -- таг останется без атрибутов
|
264
|
|
|
* @param bool $is_format_spaces Форматировать пробелы и переносы строк?
|
265
|
|
|
* Вид текста на выходе (plain) максимально приближеется виду текста в браузере на входе.
|
266
|
|
|
* Другими словами, грамотно преобразует text/html в text/plain.
|
267
|
|
|
* Текст форматируется только в том случае, если были вырезаны какие-либо таги.
|
268
|
|
|
* @param array $pair_tags массив имён парных тагов, которые будут удалены вместе с содержимым
|
269
|
|
|
* см. значения по умолчанию
|
270
|
|
|
* @param array $para_tags массив имён парных тагов, которые будут восприниматься как параграфы (если $is_format_spaces = true)
|
271
|
|
|
* см. значения по умолчанию
|
272
|
|
|
* @return string
|
273
|
|
|
*
|
274
|
|
|
* @license http://creativecommons.org/licenses/by-sa/3.0/
|
275
|
|
|
* @author Nasibullin Rinat, http://orangetie.ru/
|
276
|
|
|
* @charset ANSI
|
277
|
|
|
* @version 4.0.14
|
278
|
|
|
*/
|
279
|
|
|
function strip_tags_smart(
|
280
|
|
|
$s,
|
281
|
|
|
array $allowable_tags = null,
|
282
|
|
|
/*boolean*/
|
283
|
|
|
$is_format_spaces = true,
|
284
|
|
|
array $pair_tags = [
|
285
|
|
|
'script',
|
286
|
|
|
'style',
|
287
|
|
|
'map',
|
288
|
|
|
'iframe',
|
289
|
|
|
'frameset',
|
290
|
|
|
'object',
|
291
|
|
|
'applet',
|
292
|
|
|
'comment',
|
293
|
|
|
'button',
|
294
|
|
|
'textarea',
|
295
|
|
|
'select'
|
296
|
|
|
],
|
297
|
|
|
array $para_tags = ['p', 'td', 'th', 'li', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'form', 'title', 'pre']
|
298
|
|
|
) {
|
299
|
|
|
//return strip_tags($s);
|
300
|
|
|
static $_callback_type = false;
|
301
|
|
|
static $_allowable_tags = [];
|
302
|
|
|
static $_para_tags = [];
|
303
|
|
|
#regular expression for tag attributes
|
304
|
|
|
#correct processes dirty and broken HTML in a singlebyte or multibyte UTF-8 charset!
|
305
|
|
|
static $re_attrs_fast_safe = '(?![a-zA-Z\d]) #statement, which follows after a tag
|
306
|
|
|
#correct attributes
|
307
|
|
|
(?>
|
308
|
|
|
[^>"\']+
|
309
|
|
|
| (?<=[\=\x20\r\n\t]|\xc2\xa0) "[^"]*"
|
310
|
|
|
| (?<=[\=\x20\r\n\t]|\xc2\xa0) \'[^\']*\'
|
311
|
|
|
)*
|
312
|
|
|
#incorrect attributes
|
313
|
|
|
[^>]*+';
|
314
|
|
|
|
315
|
|
|
if (is_array($s)) {
|
316
|
|
|
if ($_callback_type === 'strip_tags') {
|
317
|
|
|
$tag = strtolower($s[1]);
|
318
|
|
|
if (! empty($_allowable_tags)) {
|
319
|
|
|
#tag with attributes
|
320
|
|
|
if (array_key_exists($tag, $_allowable_tags)) {
|
321
|
|
|
return $s[0];
|
322
|
|
|
}
|
323
|
|
|
|
324
|
|
|
#tag without attributes
|
325
|
|
|
if (array_key_exists('<' . $tag . '>', $_allowable_tags)) {
|
326
|
|
|
if (substr($s[0], 0, 2) === '</') {
|
327
|
|
|
return '</' . $tag . '>';
|
328
|
|
|
}
|
329
|
|
|
if (substr($s[0], -2) === '/>') {
|
330
|
|
|
return '<' . $tag . ' />';
|
331
|
|
|
}
|
332
|
|
|
|
333
|
|
|
return '<' . $tag . '>';
|
334
|
|
|
}
|
335
|
|
|
}
|
336
|
|
|
if ($tag === 'br') {
|
337
|
|
|
return "\r\n";
|
338
|
|
|
}
|
339
|
|
|
if (! empty($_para_tags) && array_key_exists($tag, $_para_tags)) {
|
340
|
|
|
return "\r\n\r\n";
|
341
|
|
|
}
|
342
|
|
|
|
343
|
|
|
return '';
|
344
|
|
|
}
|
345
|
|
|
trigger_error('Unknown callback type "' . $_callback_type . '"!', E_USER_ERROR);
|
346
|
|
|
}
|
347
|
|
|
|
348
|
|
|
if (($pos = strpos($s, '<')) === false || strpos($s, '>', $pos) === false) {
|
|
|
|
|
349
|
|
|
#speed improve
|
350
|
|
|
{
|
351
|
|
|
#tags are not found
|
352
|
|
|
return $s;
|
|
|
|
|
353
|
|
|
}
|
354
|
|
|
}
|
355
|
|
|
|
356
|
|
|
$length = strlen($s);
|
|
|
|
|
357
|
|
|
|
358
|
|
|
#unpaired tags (opening, closing, !DOCTYPE, MS Word namespace)
|
359
|
|
|
$re_tags = '~ <[/!]?+
|
360
|
|
|
(
|
361
|
|
|
[a-zA-Z][a-zA-Z\d]*+
|
362
|
|
|
(?>:[a-zA-Z][a-zA-Z\d]*+)?
|
363
|
|
|
) #1
|
364
|
|
|
' . $re_attrs_fast_safe . '
|
365
|
|
|
>
|
366
|
|
|
~sxSX';
|
367
|
|
|
|
368
|
|
|
$patterns = [
|
369
|
|
|
'/<([\?\%]) .*? \\1>/sxSX', #встроенный PHP, Perl, ASP код
|
370
|
|
|
'/<\!\[CDATA\[ .*? \]\]>/sxSX', #блоки CDATA
|
371
|
|
|
#'/<\!\[ [\x20\r\n\t]* [a-zA-Z] .*? \]>/sxSX', #:DEPRECATED: MS Word таги типа <![if! vml]>...<![endif]>
|
372
|
|
|
|
373
|
|
|
'/<\!--.*?-->/sSX', #комментарии
|
374
|
|
|
|
375
|
|
|
#MS Word таги типа "<![if! vml]>...<![endif]>",
|
376
|
|
|
#условное выполнение кода для IE типа "<!--[if expression]> HTML <![endif]-->"
|
377
|
|
|
#условное выполнение кода для IE типа "<![if expression]> HTML <![endif]>"
|
378
|
|
|
#см. http://www.tigir.com/comments.htm
|
379
|
|
|
'/ <\! (?:--)?+
|
380
|
|
|
\[
|
381
|
|
|
(?> [^\]"\']+ | "[^"]*" | \'[^\']*\' )*
|
382
|
|
|
\]
|
383
|
|
|
(?:--)?+
|
384
|
|
|
>
|
385
|
|
|
/sxSX',
|
386
|
|
|
];
|
387
|
|
|
if (! empty($pair_tags)) {
|
388
|
|
|
#парные таги вместе с содержимым:
|
389
|
|
|
foreach ($pair_tags as $k => $v) {
|
390
|
|
|
$pair_tags[$k] = preg_quote($v, '/');
|
391
|
|
|
}
|
392
|
|
|
$patterns[] = '/ <((?i:' . implode('|', $pair_tags) . '))' . $re_attrs_fast_safe . '(?<!\/)>
|
393
|
|
|
.*?
|
394
|
|
|
<\/(?i:\\1)' . $re_attrs_fast_safe . '>
|
395
|
|
|
/sxSX';
|
396
|
|
|
}
|
397
|
|
|
#d($patterns);
|
398
|
|
|
|
399
|
|
|
$i = 0; #защита от зацикливания
|
400
|
|
|
$max = 99;
|
401
|
|
|
while ($i < $max) {
|
402
|
|
|
$s2 = preg_replace($patterns, '', $s);
|
403
|
|
|
if (preg_last_error() !== PREG_NO_ERROR) {
|
404
|
|
|
$i = 999;
|
405
|
|
|
break;
|
406
|
|
|
}
|
407
|
|
|
$is_html = false;
|
408
|
|
|
|
409
|
|
|
if ($i == 0) {
|
410
|
|
|
$is_html = ($s2 != $s || preg_match($re_tags, $s2));
|
411
|
|
|
if (preg_last_error() !== PREG_NO_ERROR) {
|
412
|
|
|
$i = 999;
|
413
|
|
|
break;
|
414
|
|
|
}
|
415
|
|
|
if ($is_html) {
|
416
|
|
|
if ($is_format_spaces) {
|
417
|
|
|
/*
|
418
|
|
|
В библиотеке PCRE для PHP \s - это любой пробельный символ, а именно класс символов [\x09\x0a\x0c\x0d\x20\xa0] или, по другому, [\t\n\f\r \xa0]
|
419
|
|
|
Если \s используется с модификатором /u, то \s трактуется как [\x09\x0a\x0c\x0d\x20]
|
420
|
|
|
Браузер не делает различия между пробельными символами, друг за другом подряд идущие символы воспринимаются как один
|
421
|
|
|
$s2 = str_replace(array("\r", "\n", "\t"), ' ', $s2);
|
422
|
|
|
$s2 = strtr($s2, "\x09\x0a\x0c\x0d", ' ');
|
423
|
|
|
*/
|
424
|
|
|
$s2 = preg_replace('/ [\x09\x0a\x0c\x0d]++
|
425
|
|
|
| <((?i:pre|textarea))' . $re_attrs_fast_safe . '(?<!\/)>
|
426
|
|
|
.+?
|
427
|
|
|
<\/(?i:\\1)' . $re_attrs_fast_safe . '>
|
428
|
|
|
\K
|
429
|
|
|
/sxSX', ' ', $s2);
|
430
|
|
|
if (preg_last_error() !== PREG_NO_ERROR) {
|
431
|
|
|
$i = 999;
|
432
|
|
|
break;
|
433
|
|
|
}
|
434
|
|
|
}
|
435
|
|
|
|
436
|
|
|
#массив тагов, которые не будут вырезаны
|
437
|
|
|
if (! empty($allowable_tags)) {
|
438
|
|
|
$_allowable_tags = array_flip($allowable_tags);
|
439
|
|
|
}
|
440
|
|
|
|
441
|
|
|
#парные таги, которые будут восприниматься как параграфы
|
442
|
|
|
if (! empty($para_tags)) {
|
443
|
|
|
$_para_tags = array_flip($para_tags);
|
444
|
|
|
}
|
445
|
|
|
}
|
446
|
|
|
}#if
|
447
|
|
|
|
448
|
|
|
#tags processing
|
449
|
|
|
if ($is_html) {
|
450
|
|
|
$_callback_type = 'strip_tags';
|
451
|
|
|
$s2 = preg_replace_callback($re_tags, __FUNCTION__, $s2);
|
452
|
|
|
$_callback_type = false;
|
|
|
|
|
453
|
|
|
if (preg_last_error() !== PREG_NO_ERROR) {
|
454
|
|
|
$i = 999;
|
455
|
|
|
break;
|
456
|
|
|
}
|
457
|
|
|
}
|
458
|
|
|
|
459
|
|
|
if ($s === $s2) {
|
460
|
|
|
break;
|
461
|
|
|
}
|
462
|
|
|
$s = $s2;
|
463
|
|
|
$i++;
|
464
|
|
|
}#while
|
465
|
|
|
if ($i >= $max) {
|
466
|
|
|
$s = strip_tags($s);
|
|
|
|
|
467
|
|
|
}
|
468
|
|
|
#too many cycles for replace...
|
469
|
|
|
|
470
|
|
|
if ($is_format_spaces && strlen($s) !== $length) {
|
471
|
|
|
#remove a duplicate spaces
|
472
|
|
|
$s = preg_replace('/\x20\x20++/sSX', ' ', trim($s));
|
|
|
|
|
473
|
|
|
#remove a spaces before and after new lines
|
474
|
|
|
$s = str_replace(["\r\n\x20", "\x20\r\n"], "\r\n", $s);
|
475
|
|
|
#replace 3 and more new lines to 2 new lines
|
476
|
|
|
$s = preg_replace('/[\r\n]{3,}+/sSX', "\r\n\r\n", $s);
|
477
|
|
|
}
|
478
|
|
|
|
479
|
|
|
return $s;
|
|
|
|
|
480
|
|
|
}
|
481
|
|
|
}
|
482
|
|
|
|
483
|
|
|
if (! function_exists('last_implode')) {
|
484
|
|
|
/**
|
485
|
|
|
* Склеивание всех элементов массива по разделителю. Для последнего элемента используется специфичный разделитель
|
486
|
|
|
*
|
487
|
|
|
* @param string $sep разделитель элементов массива
|
488
|
|
|
* @param array $data массив
|
489
|
|
|
* @param string $last разделитель для последнего элемента массива
|
490
|
|
|
* @return mixed|string
|
491
|
|
|
*/
|
492
|
|
|
function last_implode($sep, $data, $last = null)
|
493
|
|
|
{
|
494
|
|
|
$end = array_pop($data);
|
495
|
|
|
$out = implode($sep, $data);
|
496
|
|
|
if (is_nop($last)) {
|
497
|
|
|
$last = $sep;
|
498
|
|
|
}
|
499
|
|
|
|
500
|
|
|
return empty($out) ? $end : $out . $last . $end;
|
501
|
|
|
}
|
502
|
|
|
}
|
503
|
|
|
|
504
|
|
|
if (! function_exists('is_nop')) {
|
505
|
|
|
/**
|
506
|
|
|
* Является ли строка пустой
|
507
|
|
|
*
|
508
|
|
|
* @param string $val проверяемая строка
|
509
|
|
|
* @return bool
|
510
|
|
|
*/
|
511
|
|
|
function is_nop($val)
|
512
|
|
|
{
|
513
|
|
|
return (is_scalar($val) && empty($val) && $val != '0');
|
514
|
|
|
}
|
515
|
|
|
}
|
516
|
|
|
|
517
|
|
|
if (! function_exists('first_word')) {
|
518
|
|
|
/**
|
519
|
|
|
* Получение первого слова из строки
|
520
|
|
|
*
|
521
|
|
|
* @param string $string
|
522
|
|
|
* @return string
|
523
|
|
|
*/
|
524
|
|
|
function first_word($string)
|
525
|
|
|
{
|
526
|
|
|
return is_scalar($string) ? current(explode(" ", $string)) : '';
|
|
|
|
|
527
|
|
|
}
|
528
|
|
|
}
|
529
|
|
|
|
530
|
|
|
if (! function_exists('is_real_int')) {
|
531
|
|
|
/**
|
532
|
|
|
* Проверяет содержит ли переменная тип integer.
|
533
|
|
|
* Функция успешно определяет целые числа даже если они хранятся в переменной с типом string
|
534
|
|
|
*
|
535
|
|
|
* @param $value
|
536
|
|
|
* @return bool
|
537
|
|
|
*/
|
538
|
|
|
function is_real_int($value)
|
539
|
|
|
{
|
540
|
|
|
return is_numeric($value) && ! is_float(1 * $value);
|
541
|
|
|
}
|
542
|
|
|
}
|
543
|
|
|
|
544
|
|
|
if (! function_exists('is_real_float')) {
|
545
|
|
|
/**
|
546
|
|
|
* Проверяет содержит ли переменная тип float.
|
547
|
|
|
* Функция успешно определяет числа с плавающей точкой даже если они хранятся в переменной с типом string
|
548
|
|
|
*
|
549
|
|
|
* @param $value
|
550
|
|
|
* @return bool
|
551
|
|
|
*/
|
552
|
|
|
function is_real_float($value)
|
553
|
|
|
{
|
554
|
|
|
return is_numeric($value) && is_float(1*$value);
|
555
|
|
|
}
|
556
|
|
|
}
|
557
|
|
|
|